From d3a80e67019bebe82638951577134efc9f4f52d5 Mon Sep 17 00:00:00 2001 From: samuelmaddock Date: Sat, 10 Oct 2020 04:24:12 -0400 Subject: [PATCH] feat: add focus and blur events for WebContents test: add focus and blur WebContents event tests test: confirm that webcontents focus event is fired on browserwindow focus fix: mac focus event test timeout --- docs/api/web-contents.md | 8 +++ .../browser/api/electron_api_web_contents.cc | 10 ++++ shell/browser/api/electron_api_web_contents.h | 4 ++ spec-main/api-web-contents-spec.ts | 56 ++++++++++++++++++- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index df97b90e7e7aa..8bf9d9a8b8062 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -508,6 +508,14 @@ Returns: Emitted when the user is requesting to change the zoom level using the mouse wheel. +#### Event: 'blur' + +Emitted when the `WebContents` loses focus. + +#### Event: 'focus' + +Emitted when the `WebContents` gains focus. + #### Event: 'devtools-opened' Emitted when DevTools is opened. diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 69dd0b925390a..dd53ce0dba80e 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1629,6 +1629,16 @@ void WebContents::DidAcquireFullscreen(content::RenderFrameHost* rfh) { set_fullscreen_frame(rfh); } +void WebContents::OnWebContentsFocused( + content::RenderWidgetHost* render_widget_host) { + Emit("focus"); +} + +void WebContents::OnWebContentsLostFocus( + content::RenderWidgetHost* render_widget_host) { + Emit("blur"); +} + void WebContents::DOMContentLoaded( content::RenderFrameHost* render_frame_host) { auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host); diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index 984e3c1c26747..48cb59a2867d2 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -621,6 +621,10 @@ class WebContents : public ExclusiveAccessContext, void DidChangeThemeColor() override; void OnCursorChanged(const content::WebCursor& cursor) override; void DidAcquireFullscreen(content::RenderFrameHost* rfh) override; + void OnWebContentsFocused( + content::RenderWidgetHost* render_widget_host) override; + void OnWebContentsLostFocus( + content::RenderWidgetHost* render_widget_host) override; // InspectableWebContentsDelegate: void DevToolsReloadPage() override; diff --git a/spec-main/api-web-contents-spec.ts b/spec-main/api-web-contents-spec.ts index c4aa16b67729b..38bcbe4d01980 100644 --- a/spec-main/api-web-contents-spec.ts +++ b/spec-main/api-web-contents-spec.ts @@ -807,10 +807,10 @@ describe('webContents module', () => { }); }); - describe('focus()', () => { - describe('when the web contents is hidden', () => { + describe('focus APIs', () => { + describe('focus()', () => { afterEach(closeAllWindows); - it('does not blur the focused window', async () => { + it('does not blur the focused window when the web contents is hidden', async () => { const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } }); w.show(); await w.loadURL('about:blank'); @@ -825,6 +825,56 @@ describe('webContents module', () => { expect(childFocused).to.be.false(); }); }); + + describe('focus event', () => { + afterEach(closeAllWindows); + it('is triggered when web contents is focused', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadURL('about:blank'); + const devToolsOpened = emittedOnce(w.webContents, 'devtools-opened'); + w.webContents.openDevTools(); + await devToolsOpened; + w.webContents.devToolsWebContents!.focus(); + const focusPromise = emittedOnce(w.webContents, 'focus'); + w.webContents.focus(); + await expect(focusPromise).to.eventually.be.fulfilled(); + }); + + it('is triggered when BrowserWindow is focused', async () => { + const window1 = new BrowserWindow({ show: false }); + const window2 = new BrowserWindow({ show: false }); + + await Promise.all([ + window1.loadURL('about:blank'), + window2.loadURL('about:blank') + ]); + + window1.showInactive(); + window2.showInactive(); + + let focusPromise = emittedOnce(window1.webContents, 'focus'); + window1.focus(); + await expect(focusPromise).to.eventually.be.fulfilled(); + + focusPromise = emittedOnce(window2.webContents, 'focus'); + window2.focus(); + await expect(focusPromise).to.eventually.be.fulfilled(); + }); + }); + + describe('blur event', () => { + afterEach(closeAllWindows); + it('is triggered when web contents is blurred', async () => { + const w = new BrowserWindow({ show: true }); + await w.loadURL('about:blank'); + const blurPromise = emittedOnce(w.webContents, 'blur'); + const devToolsOpened = emittedOnce(w.webContents, 'devtools-opened'); + w.webContents.openDevTools({ mode: 'detach' }); + await devToolsOpened; + w.webContents.devToolsWebContents!.focus(); + await expect(blurPromise).to.eventually.be.fulfilled(); + }); + }); }); describe('getOSProcessId()', () => {