diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 78190dbacbea..710179015d0b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -581,10 +581,11 @@ bool WebContents::PreHandleKeyboardEvent( const content::NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { if (event.type() == blink::WebInputEvent::Type::RawKeyDown || - event.type() == blink::WebInputEvent::Type::KeyUp) + event.type() == blink::WebInputEvent::Type::KeyUp) { return Emit("before-input-event", event); - else + } else { return false; + } } void WebContents::EnterFullscreenModeForTab(content::WebContents* source, @@ -1240,6 +1241,10 @@ void WebContents::UnregisterServiceWorker( callback); } +void WebContents::SetIgnoreMenuShortcuts(bool ignore) { + set_ignore_menu_shortcuts(ignore); +} + void WebContents::SetAudioMuted(bool muted) { web_contents()->SetAudioMuted(muted); } @@ -1763,12 +1768,12 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("closeDevTools", &WebContents::CloseDevTools) .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) .SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused) - .SetMethod("enableDeviceEmulation", - &WebContents::EnableDeviceEmulation) - .SetMethod("disableDeviceEmulation", - &WebContents::DisableDeviceEmulation) + .SetMethod("enableDeviceEmulation", &WebContents::EnableDeviceEmulation) + .SetMethod("disableDeviceEmulation", &WebContents::DisableDeviceEmulation) .SetMethod("toggleDevTools", &WebContents::ToggleDevTools) .SetMethod("inspectElement", &WebContents::InspectElement) + .SetMethod("setIgnoreMenuShortcuts", + &WebContents::SetIgnoreMenuShortcuts) .SetMethod("setAudioMuted", &WebContents::SetAudioMuted) .SetMethod("isAudioMuted", &WebContents::IsAudioMuted) .SetMethod("undo", &WebContents::Undo) @@ -1789,8 +1794,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("tabTraverse", &WebContents::TabTraverse) .SetMethod("_send", &WebContents::SendIPCMessage) .SetMethod("sendInputEvent", &WebContents::SendInputEvent) - .SetMethod("beginFrameSubscription", - &WebContents::BeginFrameSubscription) + .SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription) .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) .SetMethod("startDrag", &WebContents::StartDrag) .SetMethod("setSize", &WebContents::SetSize) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index a65ff5148eb9..1270a0ce2c79 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -117,6 +117,7 @@ class WebContents : public mate::TrackableObject, void InspectServiceWorker(); void HasServiceWorker(const base::Callback&); void UnregisterServiceWorker(const base::Callback&); + void SetIgnoreMenuShortcuts(bool ignore); void SetAudioMuted(bool muted); bool IsAudioMuted(); void Print(mate::Arguments* args); diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index b0430dafeb82..f36272052f4f 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -149,7 +149,8 @@ bool IsDevToolsFileSystemAdded( } // namespace CommonWebContentsDelegate::CommonWebContentsDelegate() - : html_fullscreen_(false), + : ignore_menu_shortcuts_(false), + html_fullscreen_(false), native_fullscreen_(false), devtools_file_system_indexer_(new DevToolsFileSystemIndexer) { } diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index fd468afd563d..a7a29db33cc3 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -53,6 +53,10 @@ class CommonWebContentsDelegate NativeWindow* owner_window() const { return owner_window_.get(); } + void set_ignore_menu_shortcuts(bool ignore) { + ignore_menu_shortcuts_ = ignore; + } + bool is_html_fullscreen() const { return html_fullscreen_; } protected: @@ -137,6 +141,8 @@ class CommonWebContentsDelegate // The window that this WebContents belongs to. base::WeakPtr owner_window_; + bool ignore_menu_shortcuts_; + // Whether window is fullscreened by HTML5 api. bool html_fullscreen_; diff --git a/atom/browser/common_web_contents_delegate_mac.mm b/atom/browser/common_web_contents_delegate_mac.mm index 079d17624c95..eac3d8769247 100644 --- a/atom/browser/common_web_contents_delegate_mac.mm +++ b/atom/browser/common_web_contents_delegate_mac.mm @@ -27,14 +27,16 @@ void CommonWebContentsDelegate::HandleKeyboardEvent( if (event.windowsKeyCode == ui::VKEY_ESCAPE && is_html_fullscreen()) ExitFullscreenModeForTab(source); - // Send the event to the menu before sending it to the window - if (event.os_event.type == NSKeyDown && - [[NSApp mainMenu] performKeyEquivalent:event.os_event]) - return; + if (!ignore_menu_shortcuts_) { + // Send the event to the menu before sending it to the window + if (event.os_event.type == NSKeyDown && + [[NSApp mainMenu] performKeyEquivalent:event.os_event]) + return; - if (event.os_event.window && - [event.os_event.window isKindOfClass:[EventDispatchingWindow class]]) - [event.os_event.window redispatchKeyEvent:event.os_event]; + if (event.os_event.window && + [event.os_event.window isKindOfClass:[EventDispatchingWindow class]]) + [event.os_event.window redispatchKeyEvent:event.os_event]; + } } } // namespace atom diff --git a/atom/browser/common_web_contents_delegate_views.cc b/atom/browser/common_web_contents_delegate_views.cc index d70884c45c2a..efea8829424a 100644 --- a/atom/browser/common_web_contents_delegate_views.cc +++ b/atom/browser/common_web_contents_delegate_views.cc @@ -23,7 +23,7 @@ void CommonWebContentsDelegate::HandleKeyboardEvent( ExitFullscreenModeForTab(source); // Let the NativeWindow handle other parts. - if (owner_window()) + if (!ignore_menu_shortcuts_ && owner_window()) owner_window()->HandleKeyboardEvent(source, event); } diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 6f662b469b3d..3c85a693306b 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -288,7 +288,22 @@ Returns: Emitted before dispatching the `keydown` and `keyup` events in the page. Calling `event.preventDefault` will prevent the page `keydown`/`keyup` events -from being dispatched. +and the menu shortcuts. + +To only prevent the menu shortcuts, use +[`setIgnoreMenuShortcuts`](#contentssetignoremenushortcuts): + +```javascript +const {BrowserWindow} = require('electron') + +let win = new BrowserWindow({width: 800, height: 600}) + +win.webContents.on('before-input-event', (event, input) => { + // For example, only enable application menu keyboard shortcuts when + // Ctrl/Cmd are down. + win.webContents.setIgnoreMenuShortcuts(!input.control && !input.meta) +}) +``` #### Event: 'devtools-opened' @@ -730,6 +745,12 @@ contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1" }) ``` +#### `contents.setIgnoreMenuShortcuts(ignore)` _Experimental_ + +* `ignore` Boolean + +Ignore application menu shortcuts while this web contents is focused. + #### `contents.setAudioMuted(muted)` * `muted` Boolean diff --git a/spec/api-web-contents-spec.js b/spec/api-web-contents-spec.js index 9bbeefc4d7a8..ca35a231f4b9 100644 --- a/spec/api-web-contents-spec.js +++ b/spec/api-web-contents-spec.js @@ -582,6 +582,13 @@ describe('webContents module', function () { }) }) + describe('setIgnoreMenuShortcuts(ignore)', function () { + it('does not throw', function () { + assert.equal(w.webContents.setIgnoreMenuShortcuts(true), undefined) + assert.equal(w.webContents.setIgnoreMenuShortcuts(false), undefined) + }) + }) + describe('destroy()', () => { let server