Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On macOS, pass key event to menu on key press #760

Merged
merged 1 commit into from Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/key-eq.md
@@ -0,0 +1,6 @@
---
"wry": patch
---

On macOS, pass key event to menu if we have one on key press.

22 changes: 22 additions & 0 deletions src/webview/wkwebview/mod.rs
Expand Up @@ -276,6 +276,14 @@ impl InnerWebView {
sel!(acceptsFirstMouse:),
accept_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(doCommandBySelector:),
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
);
decl.add_method(
sel!(keyDown:),
key_down as extern "C" fn(&mut Object, Sel, id),
);

extern "C" fn accept_first_mouse(this: &Object, _sel: Sel, _event: id) -> BOOL {
unsafe {
Expand All @@ -287,6 +295,20 @@ impl InnerWebView {
}
}
}

// Key event chain is consumed by window and cannot pass to menu.
// So we pass the event to menu if we have one
extern "C" fn key_down(_: &mut Object, _: Sel, event: id) {
unsafe {
let app = cocoa::appkit::NSApp();
let menu: id = msg_send![app, mainMenu];
if !menu.is_null() {
let () = msg_send![menu, performKeyEquivalent: event];
}
}
}
// We need to declare this method to get Command+ key equivalent.
extern "C" fn do_command_by_selector(_: &Object, _: Sel, _: Sel) {}
Comment on lines +298 to +311
Copy link
Member

Choose a reason for hiding this comment

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

can this fix be upstream to winit? seems like a valid use-case for any winit app.

Copy link
Member Author

@wusyong wusyong Nov 19, 2022

Choose a reason for hiding this comment

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

winit can call performKeyEquivalent in WinitWindow's sendEvent but I'm not sure if winit team willing to take this workaround. Key event chain in macOS is a mess tbh.

As for workaround for users of winit, I think we can add a NSView as subview and add similar code like above. Or just replace winitWindow with default NSView if they don't care any window events sent from winit like we did before (we can't do this in wry anymore since event like resize has moved to winitView).

Copy link
Member

Choose a reason for hiding this comment

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

winit ships with a default menu so this workaround is valid for their use-case too but we won't know for sure until we open a PR.

}
decl.register()
}
Expand Down