Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 23 additions & 1 deletion shell/browser/native_window_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ bool IsFramelessWindow(NSView* view) {
return window && !window->has_frame();
}

bool IsPanel(NSWindow* window) {
return [window level] == NSFloatingWindowLevel;
codebytere marked this conversation as resolved.
Show resolved Hide resolved
}

IMP original_set_frame_size = nullptr;
IMP original_view_did_move_to_superview = nullptr;

Expand Down Expand Up @@ -469,7 +473,25 @@ void ReorderChildWindowAbove(NSWindow* child_window, NSWindow* other_window) {
return;

if (focus) {
[[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
// If we're a panel window, we do not want to activate the app,
// which enables Electron-apps to build Spotlight-like experiences.
//
// 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, *)) {
if (!IsPanel(window_)) {
codebytere marked this conversation as resolved.
Show resolved Hide resolved
[[NSApplication sharedApplication] activate];
}
} else {
[[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
}

[window_ makeKeyAndOrderFront:nil];
} else {
[window_ orderOut:nil];
Expand Down
34 changes: 34 additions & 0 deletions spec/api-browser-window-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down