Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,17 @@ jobs:
- name: Validate Swift warning budget
run: python3 scripts/swift_warning_budget.py --log /tmp/cmux-build-output.txt

- name: Create virtual display
run: |
set -euo pipefail
clang -framework Foundation -framework CoreGraphics \
-o /tmp/create-virtual-display scripts/create-virtual-display.m
/tmp/create-virtual-display &
VDISPLAY_PID=$!
echo "VDISPLAY_PID=$VDISPLAY_PID" >> "$GITHUB_ENV"
sleep 3
kill -0 "$VDISPLAY_PID"
Comment on lines +634 to +643

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Virtual display readiness check is fragile; consider using helper's signal files.

The sleep 3 + kill -0 pattern only confirms the helper process is running, not that the virtual display was successfully created. The helper supports --ready-path and --display-id-path flags (see scripts/create-virtual-display.m) which signal when the display is actually ready. The same workflow in test-e2e.yml uses these for robust polling.

Since this step was moved earlier, both the CoreAnimation regression and workspace churn typing-lag regression now depend on it. If display creation takes longer than 3 seconds on a loaded runner, downstream steps could fail intermittently.

🛡️ Suggested improvement using readiness files
       - name: Create virtual display
         run: |
           set -euo pipefail
           clang -framework Foundation -framework CoreGraphics \
             -o /tmp/create-virtual-display scripts/create-virtual-display.m
-          /tmp/create-virtual-display &
+          VDISPLAY_READY="$RUNNER_TEMP/cmux-virtual-display.ready"
+          VDISPLAY_ID_PATH="$RUNNER_TEMP/cmux-virtual-display.id"
+          rm -f "$VDISPLAY_READY" "$VDISPLAY_ID_PATH"
+          /tmp/create-virtual-display \
+            --ready-path "$VDISPLAY_READY" \
+            --display-id-path "$VDISPLAY_ID_PATH" &
           VDISPLAY_PID=$!
           echo "VDISPLAY_PID=$VDISPLAY_PID" >> "$GITHUB_ENV"
-          sleep 3
-          kill -0 "$VDISPLAY_PID"
+          for _ in $(seq 1 60); do
+            if [ -s "$VDISPLAY_READY" ]; then break; fi
+            if ! kill -0 "$VDISPLAY_PID" 2>/dev/null; then
+              echo "Virtual display helper exited before ready" >&2
+              exit 1
+            fi
+            sleep 0.5
+          done
+          if [ ! -s "$VDISPLAY_READY" ]; then
+            echo "Timed out waiting for virtual display" >&2
+            exit 1
+          fi
+          echo "Virtual display ready"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Create virtual display
run: |
set -euo pipefail
clang -framework Foundation -framework CoreGraphics \
-o /tmp/create-virtual-display scripts/create-virtual-display.m
/tmp/create-virtual-display &
VDISPLAY_PID=$!
echo "VDISPLAY_PID=$VDISPLAY_PID" >> "$GITHUB_ENV"
sleep 3
kill -0 "$VDISPLAY_PID"
- name: Create virtual display
run: |
set -euo pipefail
clang -framework Foundation -framework CoreGraphics \
-o /tmp/create-virtual-display scripts/create-virtual-display.m
VDISPLAY_READY="$RUNNER_TEMP/cmux-virtual-display.ready"
VDISPLAY_ID_PATH="$RUNNER_TEMP/cmux-virtual-display.id"
rm -f "$VDISPLAY_READY" "$VDISPLAY_ID_PATH"
/tmp/create-virtual-display \
--ready-path "$VDISPLAY_READY" \
--display-id-path "$VDISPLAY_ID_PATH" &
VDISPLAY_PID=$!
echo "VDISPLAY_PID=$VDISPLAY_PID" >> "$GITHUB_ENV"
for _ in $(seq 1 60); do
if [ -s "$VDISPLAY_READY" ]; then break; fi
if ! kill -0 "$VDISPLAY_PID" 2>/dev/null; then
echo "Virtual display helper exited before ready" >&2
exit 1
fi
sleep 0.5
done
if [ ! -s "$VDISPLAY_READY" ]; then
echo "Timed out waiting for virtual display" >&2
exit 1
fi
echo "Virtual display ready"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 634 - 643, Replace the fragile "sleep
3" + "kill -0" readiness check by invoking the helper with its --ready-path and
--display-id-path flags (from scripts/create-virtual-display.m), write the
helper's PID to VDISPLAY_PID as before, then poll for the ready file (with a
timeout) and read the display id from the display-id file into the environment
(echo "VDISPLAY_ID=..." >> "$GITHUB_ENV"); if the ready file isn't created in
time, kill the helper and fail. Ensure you still export VDISPLAY_PID to
GITHUB_ENV and keep robust cleanup on timeout.


- name: Run CoreAnimation main-thread startup regression
run: |
set -euo pipefail
Expand All @@ -650,17 +661,6 @@ jobs:
CMUX_TAG="ci-ca-main-thread" \
./scripts/verify-main-thread-ca-transactions.sh "$APP"

- name: Create virtual display
run: |
set -euo pipefail
clang -framework Foundation -framework CoreGraphics \
-o /tmp/create-virtual-display scripts/create-virtual-display.m
/tmp/create-virtual-display &
VDISPLAY_PID=$!
echo "VDISPLAY_PID=$VDISPLAY_PID" >> "$GITHUB_ENV"
sleep 3
kill -0 "$VDISPLAY_PID"

- name: Run workspace churn typing-lag regression
run: |
set -euo pipefail
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extension ShortcutAction {
case .attachTextBoxFile: return ShortcutStroke(key: "a", command: true, shift: true, option: true)
case .sendCtrlFToTerminal: return nil
case .toggleRightSidebar: return ShortcutStroke(key: "b", command: true, option: true)
case .openFileExplorerSelection: return ShortcutStroke(key: "↓", command: true)
case .openDiffViewer: return ShortcutStroke(key: "d", command: true, shift: true, control: true)
case .saveFilePreview: return ShortcutStroke(key: "s", command: true)
case .openBrowser: return ShortcutStroke(key: "l", command: true, shift: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public enum ShortcutAction: String, CaseIterable, Sendable, Hashable, SettingCod
case splitBrowserRight
case splitBrowserDown
case toggleRightSidebar = "toggleFileExplorer"
case openFileExplorerSelection

// MARK: Browser & Find
case openDiffViewer
Expand Down Expand Up @@ -163,7 +164,7 @@ extension ShortcutAction {
return .navigation
case .focusLeft, .focusRight, .focusUp, .focusDown, .splitRight, .splitDown,
.toggleSplitZoom, .equalizeSplits, .splitBrowserRight, .splitBrowserDown,
.toggleRightSidebar:
.toggleRightSidebar, .openFileExplorerSelection:
return .panes
case .openDiffViewer, .saveFilePreview, .openBrowser, .focusBrowserAddressBar, .browserBack,
.browserForward, .browserReload, .browserZoomIn, .browserZoomOut,
Expand Down Expand Up @@ -227,6 +228,8 @@ extension ShortcutAction {
case .switchRightSidebarToFiles, .switchRightSidebarToFind,
.switchRightSidebarToSessions, .switchRightSidebarToFeed, .switchRightSidebarToDock:
return .atom(.sidebarFocus)
case .openFileExplorerSelection:
return .atom(.sidebarFocus)
case .renameTab, .renameWorkspace:
return .and(.not(.atom(.browserFocus)), .not(.atom(.sidebarFocus)))
case .sendCtrlFToTerminal:
Expand Down Expand Up @@ -334,6 +337,8 @@ extension ShortcutAction {
case .splitBrowserRight: return "Split Browser Right"
case .splitBrowserDown: return "Split Browser Down"
case .toggleRightSidebar: return "Toggle Right Sidebar"
case .openFileExplorerSelection:
return String(localized: "shortcut.openFileExplorerSelection.label", defaultValue: "File Explorer: Open Selection")
case .openDiffViewer: return "Open Diff Viewer"
case .saveFilePreview: return "Save File Preview"
case .openBrowser: return "Open Browser"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,15 @@ public struct KeyboardShortcutsSection: View {

/// Mirrors legacy `KeyboardShortcutSettings.settingsVisibleActions`:
/// filters out `.showHideAllWindows` (owned by Global Hotkey section)
/// then re-orders so `focusRightSidebar`, `toggleRightSidebar`, and
/// `findInDirectory` sit immediately after `markOldestUnreadAndJumpNext`
/// then re-orders the right-sidebar/find actions after `markOldestUnreadAndJumpNext`
/// or `jumpToUnread` (the unread navigation cluster), so colocated
/// sidebar/find shortcuts appear together in the settings UI.
private static var settingsVisibleActions: [ShortcutAction] {
let base = ShortcutAction.allCases.filter { $0 != .showHideAllWindows }
let colocated: [ShortcutAction] = [
.focusRightSidebar,
.toggleRightSidebar,
.openFileExplorerSelection,
.findInDirectory,
].filter(base.contains)
let colocatedSet = Set(colocated)
Expand Down
125 changes: 125 additions & 0 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,131 @@
}
}
},
"shortcut.openFileExplorerSelection.label": {
"extractionState": "manual",
"localizations": {
"ar": {
"stringUnit": {
"state": "translated",
"value": "مستكشف الملفات: فتح التحديد"
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Istraživač datoteka: otvori odabrano"
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Filoversigt: Åbn markering"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Dateiexplorer: Auswahl öffnen"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "File Explorer: Open Selection"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Explorador de archivos: abrir selección"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Explorateur de fichiers : ouvrir la sélection"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Esplora file: apri selezione"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ファイルエクスプローラ: 選択項目を開く"
}
},
"km": {
"stringUnit": {
"state": "translated",
"value": "កម្មវិធីរុករកឯកសារ៖ បើកជម្រើស"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "파일 탐색기: 선택 항목 열기"
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Filutforsker: Åpne markering"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Eksplorator plików: otwórz zaznaczenie"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Explorador de arquivos: abrir seleção"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Проводник файлов: открыть выбранное"
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "ตัวสำรวจไฟล์: เปิดรายการที่เลือก"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Dosya Gezgini: Seçimi Aç"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "Провідник файлів: відкрити вибране"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "文件浏览器:打开所选项"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "檔案瀏覽器:開啟所選項"
}
}
}
},
"command.markdownZoomIn.title": {
"extractionState": "manual",
"localizations": {
Expand Down
Loading
Loading