Repository navigation
feat(desktop): run the workbench on NSH's AppKit backend behind MAKA_APPKIT - #6509
Merged
Merged
Conversation
The macOS backend did not compile against the shared hover signature and could only run bundles it loaded itself, so a host could not hand it an EngineConfig. Maka's composer also needs what only the GPUI and terminal backends implemented. Add load_with_config, run_app_with_config and with_running_view, with asset:/ images read through the config's reader. Support `within` and `fallback` key bindings; a text view's key bindings report an unused key as noop:, which is where fallback runs. Implement Input.replaceRange. Add accessibilityPerformPress. Automation clicks without it sent AppKit an activation click outside the window's corner, which it read as a double click on the corner and resized the window to the screen edges. Keep a saved frame when the hidden title bar applies: AppKit keeps the content size there, and the window lost the title bar's height on every launch. Generated-by: Claude Code
Comparing the backends needs the real workbench on AppKit without changing what anyone runs today. A non-empty MAKA_APPKIT opens the same admitted Connection in an AppKit window; GPUI stays the default, and Windows and Linux do not build this path. The path carries out the workbench's quit, folder and text size requests and reports the window's key state as Foreground. It has one Host and refuses a UI reload rather than pausing input it cannot pause. Detaching moves to host.rs so both windows share it. Adding the path dependency made Cargo re-resolve some multi-version ranges in Cargo.lock: windows-sys 0.59 to 0.61 and windows-core 0.61 to 0.62 for existing crates, on Windows only. Generated-by: Claude Code
Generated-by: OpenAI Codex
The native test host starter already rejects Tui before host_target is called. Make that existing boundary explicit so nsh-cli compiles after the NSH synchronization. Refresh the source fingerprint; no dependency or notice text changes. Generated-by: OpenAI Codex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Runs the real workbench on NSH's AppKit backend behind a non-empty
MAKA_APPKIT, so the two backends can be compared on the same Host and TSX. GPUI stays the default on macOS, and Windows and Linux do not build this path. Host and shared TSX are unchanged.The direction and the order of this work were agreed in #6502. The multi-session benchmark and the look into why streaming runs at about 120 fps come after this PR.
What the AppKit backend gains:
EngineConfig, withasset:/images read through that config's reader, the same way the GPUI backend does it.withinandfallbackkey bindings, so Ctrl+C clears a draft. A text view's key bindings report an unused key asnoop:, and fallback runs there.Input.replaceRange, which composer completion and clearing a draft depend on.accessibilityPerformPress, for VoiceOver and automation.products/maka/desktop-shell/src/appkit.rscarries out the workbench's quit, folder and text size requests, and reports the window's key state as Foreground.Root cause: the window growing on rapid sidebar clicks
This was not a Maka bug. It reproduced from 1280×820 at (116,90) to 1396×877 at (0,33), with the bottom right corner fixed and the top left corner at the screen edge.
Background automation clicks send an activation click at a far-off point before the real click, and AppKit clamps it to just outside the window's top left corner. Rapid clicks make two of those a double click on the corner, and AppKit's corner gesture (
_attemptToSnapWindowSizeFromPoint:, seen in lldb) resizes the window. On GPUI the same tool uses AXPress, so it sends no raw click. AppKit views had no AXPress until this PR, and with it rapid sidebar presses keep the window at 1280×820.Rapid clicks with a physical mouse were not tested.
Gaps in this first version
Each of these keeps GPUI behavior out of scope for now:
followandDetachtouches the GPUI path. Before adding this,Image.getSizereplies need to stay with the engine that asked:Surface::eventposts to the current engine and request ids restart at 1, so a late reply can answer a second load's request.AppView::loadalready has this problem, and the path here loads once.pause_input, so a plugin change that needs a reload is refused with an error rather than left hanging.NSUserDefaultsper Root, notclients/desktop-window.json, and the full-screen state is not restored.Inputtokens. Not implemented on AppKit, so skill tokens in the composer are plain text.Verification
Checks run on this branch, rebased on
rust-preview:cargo fmt --all -- --check, andcargo clippy -p maka-desktop-shell --no-deps -- -D warnings.cargo nextest run -p maka-desktop-shell: 8 passed.cargo clippy -p nsh-platform-macos -p nsh-macos-host -p nsh-macos-app --all-targets --features nsh-platform-macos/dev: no new warnings (3 existing ones innavigation.rs).cargo test -p nsh-platform-macos --features dev --lib: 59 passed.nsh test crates/nsh-platform-macos/tests/keymap/phases.test.tsx --target macos: 4 passed in a real window. It coverswithin,fallbackin plain and masked fields, and areplaceRangeclipped tomaxLength. Headless apps refuse these bindings, so CI does not run it.examples/gallery/tests/shortcuts.test.tsxandpress.test.tsxpass with--target macos. Inform.test.tsx, "a controlled input shows what the app makes of each key" fails with or without this change.nsh-clidoes not compile onrust-previewsince #6507 (run::Target::Tuiis not covered intest_host.rs). I ran these with a one-line local patch that is not in this PR.Real window, Maka release build on a long test Root, before the rebase onto #6507 (screenshots and AX):
asset:/logo renders./completion moves, accepts and clears the/.Real window on the final code:
asset:/logo renders in the sidebar and on the welcome screen, on the loader chore(nsh): sync upstream main and migrate Maka consumers #6507 rewrote (screenshot below).chrome.rsit lost the title bar's height on every launch. Three restarts in a row kept the frame; those ran just before the rebase, on the samechrome.rscode.Focus message composer, which isfocusable={false}.An adversarial review by GPT 6.1 Sol High found no P0 or P1. Of its four P2s, three are fixed here (AXPress and
focusable={false}, the masked field, the clippedreplaceRangecaret), and theImage.getSizeone is listed above. It reviewed the commit before those fixes.Not verified:
binding selects a disabled provider), sobeginUiReloadwas never reached.Review focus
Cargo.lock: adding the path dependency made Cargo re-resolve some multi-version ranges, moving existing crates fromwindows-sys0.59 to 0.61 andwindows-core0.61 to 0.62. This only affects Windows. Restoring the old entries by hand was not accepted by--locked, so this is Cargo's own result. Please check Windows CI with that in mind.Public API
All in
nsh-platform-macos:AppView::load_with_config(&self, config: EngineConfig): runs an engine the host configured, replacing what ran.AppView::choose_directory(&self, done: impl FnOnce(Option<PathBuf>) + 'static): asks for one folder in a sheet of the view's window.run_app_with_config(config: EngineConfig, options: AppOptions, on_active: impl Fn(bool) + 'static) -> ExitCode:run_appfor such an engine;on_activehears whether the window has the keyboard.with_running_view(f: impl FnOnce(&AppView) + Send + 'static): runsfwith the standalone view on the main thread, from any thread.AppOptions::min_size: Option<(i32, i32)>: the content's minimum size.AppOptions::frame_autosave_name: Option<String>: saves and restores the window's frame under this name.AI use
Select exactly one:
Tool(s) and scope: Claude Code wrote the code, tests and docs, and ran the verification. GPT 6.1 Sol High (Codex) reviewed the branch before this PR opened.
Checklist
replaceRangetest runs in a window by hand, not in CI. The embedding entries, window frame and AXPress were checked in the real window, with no automated test.Does this PR entail a change in behavior?
MAKA_APPKITset; the default path is unchanged.