Skip to content

Commit

Permalink
fix: navigator.keyboard.lock() fullscreen exit handling
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Oct 30, 2023
1 parent dd68581 commit ceae6fd
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 16 deletions.
6 changes: 0 additions & 6 deletions shell/browser/api/electron_api_web_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1334,12 +1334,6 @@ bool WebContents::HandleKeyboardEvent(
bool WebContents::PlatformHandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}

// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences && web_preferences->ShouldIgnoreMenuShortcuts())
Expand Down
6 changes: 0 additions & 6 deletions shell/browser/api/electron_api_web_contents_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ - (void)redispatchKeyEvent:(NSEvent*)event;
event.GetType() == content::NativeWebKeyboardEvent::Type::kChar)
return false;

// Escape exits tabbed fullscreen mode.
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen()) {
ExitFullscreenModeForTab(source);
return true;
}

// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences && web_preferences->ShouldIgnoreMenuShortcuts())
Expand Down
57 changes: 57 additions & 0 deletions spec/chromium-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,63 @@ describe('chromium features', () => {
});
});

describe('navigator.keyboard', () => {
afterEach(closeAllWindows);

it('getLayoutMap() should return a KeyboardLayoutMap object', async () => {
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(fixturesPath, 'pages', 'blank.html'));
const size = await w.webContents.executeJavaScript(`
navigator.keyboard.getLayoutMap().then(map => map.size)
`);

expect(size).to.be.a('number');
});

it('should lock the keyboard', async () => {
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(fixturesPath, 'pages', 'modal.html'));

// Test that without lock, with ESC:
// - the window leaves fullscreen
// - the dialog is not closed
const enterFS1 = once(w, 'enter-full-screen');
await w.webContents.executeJavaScript('document.body.requestFullscreen()', true);
await enterFS1;

await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').showModal()', true);
const open1 = await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').open');
expect(open1).to.be.true();

w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
await setTimeout(1000);
const openAfter1 = await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').open');
expect(openAfter1).to.be.true();
expect(w.isFullScreen()).to.be.false();

// Test that with lock, with ESC:
// - the window does not leave fullscreen
// - the dialog is closed
const enterFS2 = once(w, 'enter-full-screen');
await w.webContents.executeJavaScript(`
navigator.keyboard.lock(['Escape']);
document.body.requestFullscreen();
`, true);

await enterFS2;

await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').showModal()', true);
const open2 = await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').open');
expect(open2).to.be.true();

w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
await setTimeout(1000);
const openAfter2 = await w.webContents.executeJavaScript('document.getElementById(\'favDialog\').open');
expect(openAfter2).to.be.false();
expect(w.isFullScreen()).to.be.true();
});
});

describe('navigator.languages', () => {
it('should return the system locale only', async () => {
const appLocale = app.getLocale();
Expand Down
26 changes: 26 additions & 0 deletions spec/fixtures/pages/modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">

<body>
<dialog id="favDialog">
<form>
<p>
<label>
Favorite animal:
<select>
<option value="default">Choose…</option>
<option>Brine shrimp</option>
<option>Red panda</option>
<option>Spider monkey</option>
</select>
</label>
</p>
<div>
<button value="cancel" formmethod="dialog">Cancel</button>
<button id="confirmBtn" value="default">Confirm</button>
</div>
</form>
</dialog>
</body>

</html>
7 changes: 3 additions & 4 deletions spec/webview-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,17 +547,16 @@ describe('<webview> tag', function () {
await close;
});

// Sending ESC via sendInputEvent only works on Windows.
ifit(process.platform === 'win32')('pressing ESC should unfullscreen window', async () => {
it('pressing ESC should unfullscreen window', async () => {
const [w, webview] = await loadWebViewWindow();
const enterFullScreen = once(w, 'enter-full-screen');
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
await enterFullScreen;

const leaveFullScreen = once(w, 'leave-full-screen');
w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
webview.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
await leaveFullScreen;
await setTimeout();
await setTimeout(1000);
expect(w.isFullScreen()).to.be.false();

const close = once(w, 'closed');
Expand Down

0 comments on commit ceae6fd

Please sign in to comment.