host(macos): install default Edit menu so Cmd+C/V work in WKWebView - #5
Open
dominicletz wants to merge 2 commits into
Open
host(macos): install default Edit menu so Cmd+C/V work in WKWebView#5dominicletz wants to merge 2 commits into
dominicletz wants to merge 2 commits into
Conversation
The macOS host never installed an Edit submenu on the AppKit main menu, so NSApp.performKeyEquivalent could not route Cmd+C/V/X/A into the responder chain. WKWebView implements copy:/cut:/paste:/selectAll:, but AppKit only reaches those selectors through a registered Edit menu item. Install a default Edit menu (Undo, Redo, Cut, Copy, Paste, Delete, Select All) in start() and rebuild it on every window.set_menubar so user menubars do not displace it. Targets are nil so the responder chain selects the first responder; no notifications or RPC are emitted. Add test.menu.list (gated by --edw-test-rpc) so the E2E suite can assert the Edit menu exists with the expected accelerators and actions. The new E2E test in test/e2e/e2e_test.exs covers the four reported regressions (Cut, Copy, Paste, Select All) and runs against the universal binary. Update docs/protocol.md, docs/status/macos.md, and docs/porting.md to document the new test method, the default Edit menu, and the requirement for other platform hosts to install an equivalent. Builds with Apple Swift 6.3 against origin/master; full E2E suite (8 tests) and unit suite (17 tests) pass.
The Edit menu RPC and assertion are macOS-only: the GTK-based Linux host does not implement test.menu.list and returns -32601, so the new E2E test failed on the Linux CI run. Branch the assertion on the platform the setup block already exposes: on macOS, run the same checks as before; on any other platform, assert the documented contract (the RPC returns -32601 "Unknown test method"). The Linux host's Edit menu itself is still required by docs/porting.md and will be added by a follow-up port. Also clarify in docs/protocol.md that test.menu.list is macOS-only until other hosts implement the equivalent.
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
The macOS host never installed an Edit submenu on the AppKit main menu, so
NSApp.performKeyEquivalentcould not routeCmd+C/V/X/Ainto the responder chain.WKWebViewimplementscopy:/cut:/paste:/selectAll:for the focused text-input view, but AppKit only reaches those selectors when an Edit menu item is registered with a matchingkeyEquivalentandkeyEquivalentModifierMask.Reported on
diode-drive-wt-native(Diode Collab): the restore-code and invite-code text fields do not respond toCmd+C/Cmd+V. The keyboard event is dropped because the AppKit responder chain has no Edit menu to handle the equivalent.This change:
buildEditMenu()helper inHostController.swiftthat returns anNSMenuItemtitledEditwithUndo,Redo,Cut,Copy,Paste,Delete, andSelect All. Targets arenilso AppKit dispatches via the responder chain; the WKWebView's internal text-input views implement the actions.start()viainstallMainMenuPreservingApple(extraItems:), so it is present before the firstmenu.createRPC and survives the firstmenu.set_apple.window.set_menubarso the Edit menu is also present next to user-supplied menubars (Apple → Edit → user menus). Whenmenu_idis omitted,set_menubaris a no-op as before.test.menu.listRPC (gated by--edw-test-rpc) that snapshots the host's main menu and returns{title, items:[{label, key, modifiers, action}]}for each top-level menu. The macOS host implements it; other hosts return-32601until they do.test/e2e/e2e_test.exsthat branches on theplatformfield the setup block already exposes. On macOS it asserts that the Edit menu exists and that the four reported regressions (Cut, Copy, Paste, Select All) carry the expected key equivalent andcut:/copy:/paste:/selectAll:actions. On any other platform it asserts the documented contract:test.menu.listreturns-32601 "Unknown test method".docs/protocol.mdto document the newtest.menu.listmethod (and to mark it macOS-only),docs/status/macos.mdto mark the featuredone(E2E-covered), anddocs/porting.mdto require an Edit menu on Linux/Windows.No Elixir-side change. No protocol-version bump (additive only, gated by the existing
--edw-test-rpcflag).Why this is the right fix
AppKit walks the main menu on every key event to find a matching
keyEquivalent. Without a registered Edit menu,Cmd+C/Cmd+Vsimply have nothing to match. The webview's text-input view already implements the standard responder actions, so installing the menu is the missing piece. This is the same approach Electron and WKWebView Hosted Apps take; it is not aWKWebViewlimitation.Test plan
./scripts/build_macos.shsucceeds (universal arm64 + x86_64 binary built)mix test test/e2e/e2e_test.exs --only e2e --no-start→ 8 tests, 0 failures on macOS (includes the new Edit menu test, macOS branch)mix test --exclude e2e --no-start→ 17 unit tests, 0 failuresmix format --check-formattedcleanmacos-e2ejob greenlinux-e2ejob green (the new test runs the non-macOS branch and asserts the documented-32601contract; the Linux Edit menu itself is a follow-up port required bydocs/porting.md)<input>, type Cmd+C / Cmd+V — clipboard operations succeedNotes
nil. This routes actions through the responder chain. The first responder — typically the WKWebView's text-input view — implementscut(_:),copy(_:),paste(_:),selectAll(_:), anddelete(_:)via the standard Cocoa text responder behaviour.undo:andredo:go throughUndoManageron the first responder. WKWebView's editable views carry anUndoManager, so Undo/Redo work inside text fields. They will be a no-op elsewhere, matching every other macOS app.Deletekey equivalent isNSBackspaceCharacter(0x08) and has no modifier mask — matches Finder, TextEdit, and the system Edit menu.test.menu.listis intentionally minimal: it serialises only what the E2E suite needs to assert (label, key equivalent, modifier bitmask, action selector) and nothing more.docs/porting.mdand will be added by a follow-up port; until thentest.menu.listreturns-32601on Linux and the new E2E test asserts exactly that.