-
-
Notifications
You must be signed in to change notification settings - Fork 327
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 high CPU usage #1481 #1484
fix high CPU usage #1481 #1484
Changes from 9 commits
d058db6
5d33d3a
c68b298
53b3fe3
43d44d2
4093f57
8e6a973
c6f656f
0595767
1bed0b3
50eaed6
41a3883
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,11 +14,30 @@ class WorkspaceEvents { | |
let diff = Array(workspaceApps.symmetricDifference(previousValueOfRunningApps)) | ||
if change.kind == .insertion { | ||
debugPrint("OS event", "apps launched", diff.map { ($0.processIdentifier, $0.bundleIdentifier) }) | ||
Applications.addRunningApplications(diff) | ||
} else if change.kind == .removal { | ||
debugPrint("OS event", "apps quit", diff.map { ($0.processIdentifier, $0.bundleIdentifier) }) | ||
Applications.removeRunningApplications(diff) | ||
previousValueOfRunningApps = workspaceApps | ||
} | ||
} | ||
|
||
static func registerFrontAppChangeNote() { | ||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(receiveFrontAppChangeNote(_:)), name: NSWorkspace.didActivateApplicationNotification, object: nil) | ||
} | ||
|
||
// We add apps when we receive a didActivateApplicationNotification notification, not when we receive an apps launched, because any app will have an apps launched notification. | ||
// But we are only interested in apps that have windows. We think that since an app can be activated, it must have a window, and subscribing to its window event makes sense and is likely to work, even if it requires multiple retries to subscribe. | ||
// I'm not very sure if there is an edge case, but so far testing down the line has not revealed it. | ||
// When we receive the didActivateApplicationNotification notification, NSRunningApplication.isActive=true, even if the app is not the frontmost window anymore. | ||
// If we go to add the application when we receive the message of apps launched, at this time NSRunningApplication.isActive may be false, and try axUiElement.windows() may also throw an exception. | ||
// For those background applications, we don't receive notifications of didActivateApplicationNotification until they have their own window. For example, those menu bar applications. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is true, then your approach here to listen to Also, if I summarize this change, it seems you found an API that gives us properly filtered apps (only apps with windows), but that's only for apps launched after AltTab is started. For apps launched before AltTab is started, we still have to filter out processes with And then you mention the edge-case of an app launching at the same time as AltTab, which would be annoying. This is actually a very important edge-case, unfortunately. That's what happens when you log into macOS. All the startup apps launch at once, concurrently. This means AltTab is launched, and all sorts of app at the very same time. I guess for that scenario, Am I understanding correctly the whole approach? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
At first I was thinking that when we open an application, as long as they show a window, then a change in window switching is bound to happen, and if we can find a way to observe this change, we will be able to tell that the program is equipped with a window. Then I used some window management software, such as automatic window layout APP, like AppGrid, Rectangle, and found that they can observe this change very well, so I went to study their code, and then found in Rectangle's code that it subscribes to
That's my concern, and I still need to do some testing on this situation.
This edge case only happens when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For that edge-case, we probably don't need to restart the applications that are missing windows, we can do a check when we get the |
||
@objc static func receiveFrontAppChangeNote(_ notification: Notification) { | ||
if let application = notification.userInfo?["NSWorkspaceApplicationKey"] as? NSRunningApplication { | ||
debugPrint("OS event", "didActivateApplicationNotification", application.bundleIdentifier) | ||
let workspaceApps = Set(NSWorkspace.shared.runningApplications) | ||
let diff = Array(workspaceApps.symmetricDifference(previousValueOfRunningApps)) | ||
Applications.addRunningApplications(diff) | ||
previousValueOfRunningApps = workspaceApps | ||
} | ||
previousValueOfRunningApps = workspaceApps | ||
} | ||
} |
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.
If your comment below is correct (that apps that trigger a
didActivateApplicationNotification
event must have windows), then all these checks are no longer useful for these apps, no?I imagine that they would only be useful for the
wasLaunchedBeforeAltTab == true
apps. So maybe we should add that boolean check first (left-side), to avoid the more expansive checks in the case where it'swasLaunchedBeforeAltTab == false
, no?