Browse Source

fix: Do not activate app when calling focus on inactive panel window (#40465)

* fix: Do not activate app when calling focus on inactive panel window

Co-authored-by: Felix Rieseberg <[email protected]>

* Use activate

Co-authored-by: Felix Rieseberg <[email protected]>

* Use "activate" for all windows

Co-authored-by: Felix Rieseberg <[email protected]>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Felix Rieseberg <[email protected]>
trop[bot] 1 year ago
parent
commit
b92b4c8fcf
2 changed files with 48 additions and 1 deletions
  1. 14 1
      shell/browser/native_window_mac.mm
  2. 34 0
      spec/api-browser-window-spec.ts

+ 14 - 1
shell/browser/native_window_mac.mm

@@ -469,7 +469,20 @@ void NativeWindowMac::Focus(bool focus) {
     return;
 
   if (focus) {
-    [[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
+    // On macOS < Sonoma, "activateIgnoringOtherApps:NO" would not
+    // activate apps if focusing a window that is inActive. That
+    // changed with macOS Sonoma.
+    //
+    // There's a slim chance we should have never called
+    // activateIgnoringOtherApps, but we tried that many years ago
+    // and saw weird focus bugs on other macOS versions. So, to make
+    // this safe, we're gating by versions.
+    if (@available(macOS 14.0, *)) {
+      [[NSApplication sharedApplication] activate];
+    } else {
+      [[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
+    }
+
     [window_ makeKeyAndOrderFront:nil];
   } else {
     [window_ orderOut:nil];

+ 34 - 0
spec/api-browser-window-spec.ts

@@ -1196,6 +1196,40 @@ describe('BrowserWindow module', () => {
           await isClosed3;
         }
       });
+
+      ifit(process.platform === 'darwin')('it does not activate the app if focusing an inactive panel', async () => {
+        // Show to focus app, then remove existing window
+        w.show();
+        w.destroy();
+
+        // We first need to resign app focus for this test to work
+        const isInactive = once(app, 'did-resign-active');
+        childProcess.execSync('osascript -e \'tell application "Finder" to activate\'');
+        await isInactive;
+
+        // Create new window
+        w = new BrowserWindow({
+          type: 'panel',
+          height: 200,
+          width: 200,
+          center: true,
+          show: false
+        });
+
+        const isShow = once(w, 'show');
+        const isFocus = once(w, 'focus');
+
+        w.showInactive();
+        w.focus();
+
+        await isShow;
+        await isFocus;
+
+        const getActiveAppOsa = 'tell application "System Events" to get the name of the first process whose frontmost is true';
+        const activeApp = childProcess.execSync(`osascript -e '${getActiveAppOsa}'`).toString().trim();
+
+        expect(activeApp).to.equal('Finder');
+      });
     });
 
     // TODO(RaisinTen): Make this work on Windows too.