Repository: electron/electron (language: cpp)

Issue:
[Bug]: `-webkit-app-region: drag` still doesn't works after #41030
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

29.0.0-beta.4

### What operating system are you using?

Windows

### Operating System Version

Windows 11 23H2 (22631)

### What arch are you using?

x64

### Last Known Working Electron version

29.0.0-alpha.7

### Expected Behavior

If `-webkit-app-region: drag` was used, it should be possible to click on the region and drag the `Window`. 

### Actual Behavior

It will behave as if the property is not applied.

### Testcase Gist URL

https://gist.github.com/JellyBrick/ec1ef4b79d55bc8a46fcdcd289259996

### Additional Information

In this case (gist), `YouTube` internally overrides the browser's events (like `MouseEvent`, `Event`, etc), which seems to cause `-webkit-app-region: drag` to be ignored. (Until `29.0.0-alpha.7`, `-webkit-app-region: drag` was not ignored and worked fine)

- Related to #40985


Discussion / hints:
cc @deepak1556
https://github.com/electron/electron/issues/40985#issuecomment-1918768529
Bisected this down to http://crrev.com/c/4814003 - this is a side effect from Chrome only collecting app regions for apps using the Window Controls Overlay or borderless apps

Fix patch:
diff --git a/shell/renderer/electron_render_frame_observer.cc b/shell/renderer/electron_render_frame_observer.cc
index 0f321f9adf7aa..346858c23cca1 100644
--- a/shell/renderer/electron_render_frame_observer.cc
+++ b/shell/renderer/electron_render_frame_observer.cc
@@ -58,10 +58,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 a8a1fc93808a3..0b4b241266936 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);
+    });
   });
 });


Test patch: