Skip to content

Commit

Permalink
fix: show finder file copy windows (closes #1466)
Browse files Browse the repository at this point in the history
also improve dealing with steam windows
  • Loading branch information
lwouis committed Jun 27, 2022
1 parent 0af9e0f commit c78481b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 36 deletions.
31 changes: 22 additions & 9 deletions src/api-wrappers/AXUIElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ extension AXUIElement {
// Minimized windows or windows of a hidden app have subrole "AXDialog"
// Activity Monitor main window subrole is "AXDialog" for a brief moment at launch; it then becomes "AXStandardWindow"

// debugPrint(runningApp.bundleIdentifier, title, level, CGWindow.normalLevel, subrole, role, size)

// Some non-windows have cgWindowId == 0 (e.g. windows of apps starting at login with the checkbox "Hidden" checked)
return wid != 0 &&
size != nil && size!.width > 100 && size!.height > 100 &&
return wid != 0 && size != nil &&
(books(runningApp) || keynote(runningApp) || iina(runningApp) || (
// CGWindowLevel == .normalWindow helps filter out iStats Pro and other top-level pop-overs, and floating windows
level == CGWindow.normalLevel &&
jetbrainApp(runningApp, title, subrole) &&
([kAXStandardWindowSubrole, kAXDialogSubrole].contains(subrole) ||
openBoard(runningApp) ||
adobeAudition(runningApp, subrole) ||
Expand All @@ -95,17 +95,24 @@ extension AXUIElement {
battleNetBootstrapper(runningApp, role) ||
firefoxFullscreenVideo(runningApp, role) ||
vlcFullscreenVideo(runningApp, role) ||
androidEmulator(runningApp, title) ||
sanGuoShaAirWD(runningApp) ||
dvdFab(runningApp) ||
drBetotte(runningApp))))
drBetotte(runningApp) ||
androidEmulator(runningApp, title)
) &&
mustHaveIfJetbrainApp(runningApp, title, subrole, size!) &&
mustHaveIfSteam(runningApp, title, role)
))
}

private static func jetbrainApp(_ runningApp: NSRunningApplication, _ title: String?, _ subrole: String?) -> Bool {
private static func mustHaveIfJetbrainApp(_ runningApp: NSRunningApplication, _ title: String?, _ subrole: String?, _ size: NSSize) -> Bool {
// jetbrain apps sometimes generate non-windows that pass all checks in isActualWindow
// they have no title, so we can filter them out based on that
return runningApp.bundleIdentifier?.range(of: "^com\\.(jetbrains\\.|google\\.android\\.studio).*?$", options: .regularExpression) == nil ||
(subrole == kAXStandardWindowSubrole || title != nil && title != "")
// we also hide windows too small
return runningApp.bundleIdentifier?.range(of: "^com\\.(jetbrains\\.|google\\.android\\.studio).*?$", options: .regularExpression) == nil || (
(subrole == kAXStandardWindowSubrole || (title != nil && title != "")) &&
size.width > 100 && size.height > 100
)
}

private static func iina(_ runningApp: NSRunningApplication) -> Bool {
Expand Down Expand Up @@ -158,7 +165,13 @@ extension AXUIElement {
private static func steam(_ runningApp: NSRunningApplication, _ title: String?, _ role: String?) -> Bool {
// All Steam windows have subrole == AXUnknown
// some dropdown menus are not desirable; they have title == "", or sometimes role == nil when switching between menus quickly
return runningApp.bundleIdentifier == "com.valvesoftware.steam" && title != "" && role != nil
return runningApp.bundleIdentifier == "com.valvesoftware.steam" && (title != nil && title != "" && role != nil)
}

private static func mustHaveIfSteam(_ runningApp: NSRunningApplication, _ title: String?, _ role: String?) -> Bool {
// All Steam windows have subrole == AXUnknown
// some dropdown menus are not desirable; they have title == "", or sometimes role == nil when switching between menus quickly
return runningApp.bundleIdentifier != "com.valvesoftware.steam" || (title != nil && title != "" && role != nil)
}

private static func firefoxFullscreenVideo(_ runningApp: NSRunningApplication, _ role: String?) -> Bool {
Expand Down
52 changes: 25 additions & 27 deletions src/logic/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,27 @@ class Application: NSObject {
guard let self = self else { return }
if let axWindows_ = try self.axUiElement!.windows(), axWindows_.count > 0 {
// bug in macOS: sometimes the OS returns multiple duplicate windows (e.g. Mail.app starting at login)
let axWindows = try Array(Set(axWindows_)).compactMap {
if let wid = try $0.cgWindowId() {
let title = try $0.title()
let subrole = try $0.subrole()
let role = try $0.role()
let size = try $0.size()
try Array(Set(axWindows_)).forEach { axWindow in
if let wid = try axWindow.cgWindowId() {
let title = try axWindow.title()
let subrole = try axWindow.subrole()
let role = try axWindow.role()
let size = try axWindow.size()
let level = try wid.level()
if AXUIElement.isActualWindow(self.runningApplication, wid, level, title, subrole, role, size) {
return ($0, wid, title, try $0.isFullscreen(), try $0.isMinimized(), try $0.position(), size)
let isFullscreen = try axWindow.isFullscreen()
let isMinimized = try axWindow.isMinimized()
let position = try axWindow.position()
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
if let window = self.addWindow(axWindow, wid, title, isFullscreen, isMinimized, position, size) {
App.app.refreshOpenUi([window])
} else if let window = self.addWindowslessAppsIfNeeded() {
App.app.refreshOpenUi(window)
}
}
}
}
return nil
} as [(AXUIElement, CGWindowID, String?, Bool, Bool, CGPoint?, CGSize?)]
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
var windows = self.addWindows(axWindows)
if let window = self.addWindowslessAppsIfNeeded() {
windows.append(contentsOf: window)
}
App.app.refreshOpenUi(windows)
}
} else {
DispatchQueue.main.async { [weak self] in
Expand Down Expand Up @@ -135,19 +136,16 @@ class Application: NSObject {
}
}

private func addWindows(_ axWindows: [(AXUIElement, CGWindowID, String?, Bool, Bool, CGPoint?, CGSize?)]) -> [Window] {
let windows: [Window] = axWindows.compactMap { (axUiElement, wid, axTitle, isFullscreen, isMinimized, position, size) in
if (Windows.list.firstIndex { $0.isEqualRobust(axUiElement, wid) }) == nil {
let window = Window(axUiElement, self, wid, axTitle, isFullscreen, isMinimized, position, size)
Windows.appendAndUpdateFocus(window)
return window
private func addWindow(_ axUiElement: AXUIElement, _ wid: CGWindowID, _ axTitle: String?, _ isFullscreen: Bool, _ isMinimized: Bool, _ position: CGPoint?, _ size: CGSize?) -> Window? {
if (Windows.list.firstIndex { $0.isEqualRobust(axUiElement, wid) }) == nil {
let window = Window(axUiElement, self, wid, axTitle, isFullscreen, isMinimized, position, size)
Windows.appendAndUpdateFocus(window)
if App.app.appIsBeingUsed {
Windows.cycleFocusedWindowIndex(1)
}
return nil
}
if App.app.appIsBeingUsed {
Windows.cycleFocusedWindowIndex(windows.count)
return window
}
return windows
return nil
}

private func observeEvents() {
Expand Down

0 comments on commit c78481b

Please sign in to comment.