diff --git a/shell/renderer/electron_render_frame_observer.cc b/shell/renderer/electron_render_frame_observer.cc index 5423b18018e5..b3cded053a2a 100644 --- a/shell/renderer/electron_render_frame_observer.cc +++ b/shell/renderer/electron_render_frame_observer.cc @@ -66,10 +66,10 @@ ElectronRenderFrameObserver::ElectronRenderFrameObserver( // Initialise resource for directory listing. net::NetModule::SetResourceProvider(NetResourceProvider); - // App regions are only supported in the main frame. - auto* main_frame = frame->GetMainRenderFrame(); - if (main_frame && main_frame == frame) - render_frame_->GetWebView()->SetSupportsAppRegion(true); + // In Chrome, app regions are only supported in the main frame. + // However, we need to support draggable regions on other + // local frames/windows, so extend support beyond the main frame. + render_frame_->GetWebView()->SetSupportsAppRegion(true); } void ElectronRenderFrameObserver::DidClearWindowObject() { diff --git a/spec/api-browser-window-spec.ts b/spec/api-browser-window-spec.ts index a8a1fc93808a..0b4b24126693 100644 --- a/spec/api-browser-window-spec.ts +++ b/spec/api-browser-window-spec.ts @@ -6646,5 +6646,70 @@ describe('BrowserWindow module', () => { expect(startPos).to.not.deep.equal(endPos); }); + + ifit(hasCapturableScreen())('should allow the window to be dragged when no WCO and --webkit-app-region: drag enabled', async () => { + // @ts-ignore: nut-js is an optional dependency so it may not be installed + const { mouse, straightTo, centerOf, Region, Button } = require('@nut-tree/nut-js') as typeof import('@nut-tree/nut-js'); + + const display = screen.getPrimaryDisplay(); + const w = new BrowserWindow({ + x: 0, + y: 0, + width: display.bounds.width / 2, + height: display.bounds.height / 2, + frame: false + }); + + const basePageHTML = path.join(__dirname, 'fixtures', 'pages', 'base-page.html'); + w.loadFile(basePageHTML); + await once(w, 'ready-to-show'); + + await w.webContents.executeJavaScript(` + const style = document.createElement('style'); + style.innerHTML = \` + #titlebar { + + background-color: red; + height: 30px; + width: 100%; + -webkit-user-select: none; + -webkit-app-region: drag; + position: fixed; + top: 0; + left: 0; + z-index: 1000000000000; + } + \`; + + const titleBar = document.createElement('title-bar'); + titleBar.id = 'titlebar'; + titleBar.textContent = 'test-titlebar'; + + document.body.append(style); + document.body.append(titleBar); + `); + // allow time for titlebar to finish loading + await setTimeout(2000); + + const winBounds = w.getBounds(); + const titleBarHeight = 30; + const titleBarRegion = new Region(winBounds.x, winBounds.y, winBounds.width, titleBarHeight); + const screenRegion = new Region(display.bounds.x, display.bounds.y, display.bounds.width, display.bounds.height); + + const startPos = w.getPosition(); + await mouse.setPosition(await centerOf(titleBarRegion)); + await mouse.pressButton(Button.LEFT); + await mouse.drag(straightTo(centerOf(screenRegion))); + + // Wait for move to complete + await Promise.race([ + once(w, 'move'), + setTimeout(1000) // fallback for possible race condition + ]); + + const endPos = w.getPosition(); + + expect(startPos).to.not.deep.equal(endPos); + }); }); });