fix: apps could steal key focus from alt-tab main window (#719 #916)

(closes #719, closes #916)
This commit is contained in:
Louis Pontoise
2021-04-17 20:07:30 +09:00
committed by lwouis
parent 682cd1ea8b
commit 6be72f36d7
7 changed files with 45 additions and 41 deletions
+1 -1
View File
@@ -93,7 +93,7 @@ class SystemPermissions {
startupBlock()
} else {
permissionsWindow = PermissionsWindow()
permissionsWindow.show()
App.app.showSecondaryWindow(permissionsWindow)
observePermissionsPreStartup(startupBlock)
}
}
+7
View File
@@ -216,5 +216,12 @@ class Window {
isOnAllSpaces = true
}
}
func isOnScreen(_ screen: NSScreen) -> Bool {
if let screenUuid = screen.uuid(), let screenSpaces = Spaces.screenSpacesMap[screenUuid] {
return screenSpaces.contains { $0 == spaceId }
}
return true
}
}
+1 -22
View File
@@ -181,30 +181,9 @@ class Windows {
!(!(Preferences.showMinimizedWindows[App.app.shortcutIndex] != .hide) && window.isMinimized) &&
!(Preferences.spacesToShow[App.app.shortcutIndex] == .active && window.spaceId != Spaces.currentSpaceId) &&
!(Preferences.spacesToShow[App.app.shortcutIndex] == .visible && !Spaces.visibleSpaces.contains(window.spaceId)) &&
!(Preferences.screensToShow[App.app.shortcutIndex] == .showingAltTab && !isOnScreen(window, screen)) &&
!(Preferences.screensToShow[App.app.shortcutIndex] == .showingAltTab && !window.isOnScreen(screen)) &&
(Preferences.showTabsAsWindows || !window.isTabbed))
}
static func isOnScreen(_ window: Window, _ screen: NSScreen) -> Bool {
if let screenUuid = screen.uuid(), let screenSpaces = Spaces.screenSpacesMap[screenUuid] {
return screenSpaces.contains { $0 == window.spaceId }
}
return true
}
static func checkIfShortcutsShouldBeDisabled(_ activeWindow: Window) {
let shortcutsShouldBeDisabled = (!Preferences.disableShortcutsBlacklistOnlyFullscreen || activeWindow.isFullscreen) &&
(Preferences.disableShortcutsBlacklist.first { blacklistedId in
if let id = activeWindow.application.runningApplication.bundleIdentifier {
return id.hasPrefix(blacklistedId)
}
return false
} != nil)
KeyboardEvents.toggleGlobalShortcuts(shortcutsShouldBeDisabled)
if shortcutsShouldBeDisabled && App.app.appIsBeingUsed {
App.app.hideUi()
}
}
}
func sortByBooleanAttribute(_ b1: Bool, _ b2: Bool) -> Bool? {
+9 -11
View File
@@ -36,18 +36,16 @@ fileprivate func focusedUiElementChanged(_ pid: pid_t) throws {
}
fileprivate func applicationActivated(_ element: AXUIElement, _ pid: pid_t) throws {
if let appFocusedWindow = try element.focusedWindow(),
let wid = try appFocusedWindow.cgWindowId() {
DispatchQueue.main.async {
if let app = (Applications.list.first { $0.pid == pid }), !app.hasBeenActiveOnce {
let appFocusedWindow = try element.focusedWindow()
let wid = try appFocusedWindow?.cgWindowId()
DispatchQueue.main.async {
if let app = (Applications.list.first { $0.pid == pid }) {
if !app.hasBeenActiveOnce {
app.hasBeenActiveOnce = true
}
// ensure alt-tab window remains key, so local shortcuts work
if App.app.appIsBeingUsed { App.app.thumbnailsPanel.makeKeyAndOrderFront(nil) }
if let window = Windows.updateLastFocus(appFocusedWindow, wid) {
Windows.checkIfShortcutsShouldBeDisabled(window.first!)
App.app.refreshOpenUi(window)
}
let window = (appFocusedWindow != nil && wid != nil) ? Windows.updateLastFocus(appFocusedWindow!, wid!)?.first : nil
App.app.checkIfShortcutsShouldBeDisabled(window, app.runningApplication)
App.app.refreshOpenUi(window != nil ? [window!] : nil)
}
}
}
@@ -187,7 +185,7 @@ fileprivate func windowResized(_ element: AXUIElement) throws {
if let window = (Windows.list.first { $0.isEqualRobust(element, wid) }) {
if window.isFullscreen != isFullscreen {
window.isFullscreen = isFullscreen
Windows.checkIfShortcutsShouldBeDisabled(window)
App.app.checkIfShortcutsShouldBeDisabled(window, nil)
}
App.app.refreshOpenUi([window])
}
+15
View File
@@ -282,4 +282,19 @@ class App: AppCenterApplication, NSApplicationDelegate {
Applications.refreshBadges()
KeyRepeatTimer.toggleRepeatingKeyNextWindow()
}
func checkIfShortcutsShouldBeDisabled(_ activeWindow: Window?, _ activeApp: NSRunningApplication?) {
let app = activeWindow?.application.runningApplication ?? activeApp
let shortcutsShouldBeDisabled = (!Preferences.disableShortcutsBlacklistOnlyFullscreen || (activeWindow?.isFullscreen ?? false)) &&
(Preferences.disableShortcutsBlacklist.first { blacklistedId in
if let id = app?.bundleIdentifier {
return id.hasPrefix(blacklistedId)
}
return false
} != nil)
KeyboardEvents.toggleGlobalShortcuts(shortcutsShouldBeDisabled)
if shortcutsShouldBeDisabled && App.app.appIsBeingUsed {
App.app.hideUi()
}
}
}
+12 -1
View File
@@ -1,11 +1,12 @@
import Cocoa
class ThumbnailsPanel: NSPanel {
class ThumbnailsPanel: NSPanel, NSWindowDelegate {
var thumbnailsView = ThumbnailsView()
override var canBecomeKey: Bool { true }
convenience init() {
self.init(contentRect: .zero, styleMask: .nonactivatingPanel, backing: .buffered, defer: false)
delegate = self
isFloatingPanel = true
updateFadeOutAnimation()
hidesOnDeactivate = false
@@ -24,6 +25,16 @@ class ThumbnailsPanel: NSPanel {
setAccessibilitySubrole(.unknown)
}
func windowDidResignKey(_ notification: Notification) {
// other windows can steal key focus from alt-tab; we make sure that if it's active, if keeps key focus
// dispatching to the main queue is necessary to introduce a delay in scheduling the makeKey; otherwise it is ignored
DispatchQueue.main.async {
if App.app.appIsBeingUsed {
App.app.thumbnailsPanel.makeKeyAndOrderFront(nil)
}
}
}
func updateFadeOutAnimation() {
animationBehavior = Preferences.fadeOutAnimation ? .utilityWindow : .none
}
@@ -11,12 +11,6 @@ class PermissionsWindow: NSWindow, NSWindowDelegate {
setupView()
}
func show() {
center()
App.shared.activate(ignoringOtherApps: true)
makeKeyAndOrderFront(nil)
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
debugPrint("Before using this app, you need to give permission in System Preferences > Security & Privacy > Privacy > Accessibility.",
"Please authorize and re-launch.",