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
fix: Do not activate app when calling focus on inactive panel window #40307
Conversation
c78d89f
to
8256ae3
Compare
a3a8536
to
4eb3123
Compare
No windows files changed, failed Windows build is a flake! |
@felixrieseberg would you mind rebasing this? |
4eb3123
to
a61887f
Compare
@codebytere Rebased! |
@tzahola Thank you, that's really helpful! You're right, maybe we just use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-approving with latest change
Release Notes Persisted
|
I have automatically backported this PR to "26-x-y", please check out #40463 |
I have automatically backported this PR to "27-x-y", please check out #40464 |
I have automatically backported this PR to "28-x-y", please check out #40465 |
So I've experimented a bit with app activation on macOS Sonoma, to see how this new "cooperative" app activation API works. Contrary what the header docs and the WWDC23 video suggests, the new According to the docs, when using the new API to activate an app, it is merely a suggestion to the system, and it is ultimately up to the OS to decide whether the currently active app will be replaced with the requested one or not:
In addition to Now, how the target app would know that some other app wants to activate it, is unclear, as there's no API that would notify it that someone wants it to become active... Are you supposed to communicate this via some side channel, or what? I could only see that working between two apps from the same developer though. And then Apple goes on to show a code snippet that makes even less sense:
So this is how you're supposed to pass control to another app with the new API. What's the point of calling two methods in sequence, that are semantically the same? First we're announcing that we're yielding activation to Anyway, this is only half of the story. You hardly ever care about activating other apps. How do you activate your own app when it's needed with the new API? Apple says:
and Apple also says that:
They don't elaborate how the system decides whether to honor our request and activate our app when it wants to come to the foreground, but they assure us that they're going to consider "the user’s intent and larger system context". (Again, there's no API which would let us negotiate with the currently active app about taking over the active status. Only the active app can influence the system's decision by yielding, but why would any random app - that happens to be active - even know about our app in the first place???) So I've made a few experiments in a bare Cocoa app to see when the system honors the activation request from an inactive/backgrounded app. These are my findings as of macOS Sonoma 14.1:
In conclusion: the new API seems to only activate our app, if there was some user interaction beforehand, like clicking a dock menu, a system menubar menu, or hitting a global hotkey. Activating the app if it was put in the background when starting some long-running process, or activating it in response to an incoming network message does not work with the new API. Based on this, I'd recommend reverting to What does everyone else think? |
Thanks, @tzahola for all this research. In my sense, What should be the behavior is that on What I understand from you commentIf I understand well (there is a lot of information to process) the actual PR will not fix the behavior. Because when you do a globalShortcut that calls |
What I'm saying basically, is that replacing the "deprecated" This is independent of the original issue that this PR fixes, that is, the undesirable app activation when opening nonactivating Long story short: so your original issue with the Spotlight-like panel window is fixed by this PR, but a different, more subtle issue was introduced by switching to the new app activation API. This can be fixed by returning to the original version of @felixrieseberg which used the old API (which was replaced with the new API only because @codebytere noticed that the old one got marked as deprecated), but checked the window type to not activate the app inadvertently for |
@felixrieseberg what are your thoughts? |
@tzahola Thank you for all this research and the very elaborate write-up. I appreciate it quite a bit. @codebytere I think what we should do is to fix-forward to an earlier version of this PR - we'll use the new API for |
Follow-up PR: #40570 |
…lectron#40307) * fix: Do not activate app when calling focus on inactive panel window * Use activate * Use "activate" for all windows
is this fixed? I am still encountering this issue... |
@felixrieseberg hey Felix, does this commit fix the activation problem? |
Description of Change
This PR fixes #39914. On macOS Sonoma, a BrowserWindow of the
panel
type could no longer be focused without also making the app the foregrounded app.This was likely caused by us incorrectly calling
[[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
in those scenarios. However, having done some sleuthing, we've tried to not call that method in recent years and saw different focus bugs. With that in mind, this PR does two things:activateIgnoringOtherApps
for panel windows on macOS 14.0 or newer.We've also verified this approach internally at Notion. Anyone needing a fix for this urgently can use this native module.
Checklist
npm test
passesRelease Notes
Notes: Fixed app incorrectly activating panel windows on macOS Sonoma