fix: focusing alt-tab own windows with alt-tab had jank (closes #501)

This commit is contained in:
Louis Pontoise authored and lwouis committed 2020-08-31 14:41:16 +09:00
1 parent 30625662a2
commit c927920070
5 files changed
+40 -25

No files matched your search

+16 -12
View File
@@ -136,18 +136,22 @@ class Window {
}
func focus() {
// macOS bug: when switching to a System Preferences window in another space, it switches to that space,
// but quickly switches back to another window in that space
// You can reproduce this buggy behaviour by clicking on the dock icon, proving it's an OS bug
BackgroundWork.accessibilityCommandsQueue.asyncWithCap { [weak self] in
guard let self = self else { return }
var elementConnection = UInt32(0)
CGSGetWindowOwner(cgsMainConnectionId, self.cgWindowId, &elementConnection)
var psn = ProcessSerialNumber()
CGSGetConnectionPSN(elementConnection, &psn)
_SLPSSetFrontProcessWithOptions(&psn, self.cgWindowId, .userGenerated)
self.makeKeyWindow(psn)
self.axUiElement.focusWindow()
if application.runningApplication.processIdentifier == ProcessInfo.processInfo.processIdentifier {
App.app.showSecondaryWindow(App.app.window(withWindowNumber: Int(cgWindowId)))
} else {
// macOS bug: when switching to a System Preferences window in another space, it switches to that space,
// but quickly switches back to another window in that space
// You can reproduce this buggy behaviour by clicking on the dock icon, proving it's an OS bug
BackgroundWork.accessibilityCommandsQueue.asyncWithCap { [weak self] in
guard let self = self else { return }
var elementConnection = UInt32(0)
CGSGetWindowOwner(cgsMainConnectionId, self.cgWindowId, &elementConnection)
var psn = ProcessSerialNumber()
CGSGetConnectionPSN(elementConnection, &psn)
_SLPSSetFrontProcessWithOptions(&psn, self.cgWindowId, .userGenerated)
self.makeKeyWindow(psn)
self.axUiElement.focusWindow()
}
}
}
+1 -3
View File
@@ -123,9 +123,7 @@ private func windowCreated(_ element: AXUIElement, _ pid: pid_t) throws {
}
private func focusedWindowChanged(_ element: AXUIElement, _ pid: pid_t) throws {
if let wid = try element.cgWindowId(),
pid != ProcessInfo.processInfo.processIdentifier ||
(App.app.preferencesWindow.isKeyWindow || App.app.feedbackWindow?.isKeyWindow ?? false) {
if let wid = try element.cgWindowId() {
let axTitle = try element.title()
let subrole = try element.subrole()
let role = try element.role()
+19 -10
View File
@@ -14,7 +14,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
static var app: App!
var thumbnailsPanel: ThumbnailsPanel!
var preferencesWindow: PreferencesWindow!
var feedbackWindow: FeedbackWindow?
var feedbackWindow: FeedbackWindow!
var isFirstSummon = true
var appIsBeingUsed = false
var shortcutsShouldBeDisabled = false
@@ -51,6 +51,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
Spaces.initialDiscovery()
Applications.initialDiscovery()
self.preferencesWindow = PreferencesWindow()
self.feedbackWindow = FeedbackWindow()
KeyboardEvents.observe()
MouseEvents.observe()
// TODO: undeterministic; events in the queue may still be processing; good enough for now
@@ -107,7 +108,16 @@ class App: AppCenterApplication, NSApplicationDelegate {
appIsBeingUsed = false
isFirstSummon = true
MouseEvents.toggle(false)
hideThumbnailPanelWithoutChangingKeyWindow()
}
// we don't want another window to become key when the thumbnailPanel is hidden
func hideThumbnailPanelWithoutChangingKeyWindow() {
preferencesWindow.canBecomeKey_ = false
feedbackWindow.canBecomeKey_ = false
thumbnailsPanel.orderOut(nil)
preferencesWindow.canBecomeKey_ = true
feedbackWindow.canBecomeKey_ = true
}
func closeSelectedWindow() {
@@ -136,19 +146,18 @@ class App: AppCenterApplication, NSApplicationDelegate {
}
@objc func showFeedbackPanel() {
if feedbackWindow == nil {
feedbackWindow = FeedbackWindow()
}
Screen.repositionPanel(feedbackWindow!, Screen.preferred(), .appleCentered)
App.shared.activate(ignoringOtherApps: true)
feedbackWindow!.makeKeyAndOrderFront(nil)
showSecondaryWindow(feedbackWindow)
}
@objc func showPreferencesWindow() {
if let preferencesWindow = preferencesWindow {
Screen.repositionPanel(preferencesWindow, Screen.preferred(), .appleCentered)
showSecondaryWindow(preferencesWindow)
}
func showSecondaryWindow(_ window: NSWindow?) {
if let window = window {
Screen.repositionPanel(window, Screen.preferred(), .appleCentered)
App.shared.activate(ignoringOtherApps: true)
preferencesWindow.makeKeyAndOrderFront(nil)
window.makeKeyAndOrderFront(nil)
}
}
+2
View File
@@ -6,6 +6,8 @@ class FeedbackWindow: NSWindow {
var email: TextArea!
var sendButton: NSButton!
var debugProfile: NSButton!
var canBecomeKey_ = true
override var canBecomeKey: Bool { canBecomeKey_ }
override init(contentRect: NSRect, styleMask style: StyleMask, backing backingStoreType: BackingStoreType, defer flag: Bool) {
super.init(contentRect: .zero, styleMask: style, backing: backingStoreType, defer: flag)
@@ -2,6 +2,8 @@ import Cocoa
class PreferencesWindow: NSWindow, NSToolbarDelegate {
var toolbarItems = [NSToolbarItem.Identifier: (Int, NSToolbarItem, NSView)]()
var canBecomeKey_ = true
override var canBecomeKey: Bool { canBecomeKey_ }
override init(contentRect: NSRect, styleMask style: StyleMask, backing backingStoreType: BackingStoreType, defer flag: Bool) {
super.init(contentRect: .zero, styleMask: style, backing: backingStoreType, defer: flag)