From 4a8bdebacc2693f8e5aed13d5136c3ebbc11e025 Mon Sep 17 00:00:00 2001 From: "louis.pontoise" Date: Tue, 14 Jan 2020 10:38:18 +0900 Subject: [PATCH] fix: better focus/order for preferences (closes #80) --- alt-tab-macos.xcodeproj/project.pbxproj | 8 ++-- alt-tab-macos/logic/Screen.swift | 12 ++---- alt-tab-macos/ui/App.swift | 10 ++--- ...cesPanel.swift => PreferencesWindow.swift} | 37 +++++++++++-------- alt-tab-macos/ui/ThumbnailsPanel.swift | 4 ++ 5 files changed, 38 insertions(+), 33 deletions(-) rename alt-tab-macos/ui/{PreferencesPanel.swift => PreferencesWindow.swift} (91%) diff --git a/alt-tab-macos.xcodeproj/project.pbxproj b/alt-tab-macos.xcodeproj/project.pbxproj index d1ef77b6..f09efe9a 100644 --- a/alt-tab-macos.xcodeproj/project.pbxproj +++ b/alt-tab-macos.xcodeproj/project.pbxproj @@ -20,7 +20,7 @@ D04BA4D356055A39B97712DE /* PrivateApis.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAF0DFC1F44322973CE1E /* PrivateApis.swift */; }; D04BA57A871B7269BEBAFF84 /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA35456DA0DDA74F9687E /* Keyboard.swift */; }; D04BA57FB9EF1373D59A1AA7 /* CGWindowID.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAEA3EDC4F80FA23DBEC4 /* CGWindowID.swift */; }; - D04BA6368E681BE3A408AC99 /* PreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA02F476DE30C4647886C /* PreferencesPanel.swift */; }; + D04BA6368E681BE3A408AC99 /* PreferencesWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA02F476DE30C4647886C /* PreferencesWindow.swift */; }; D04BA6B6B703DCEFE892D5A4 /* Spaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA5EB5ED248C8C22CC672 /* Spaces.swift */; }; D04BA70FF7262BF5F9E6E13B /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BADCB1C0F50340A6CAFC2 /* Preferences.swift */; }; D04BA8373D4DE452C0C081ED /* SF-Pro-Text-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = D04BABC654F40BE74DA25BC7 /* SF-Pro-Text-Regular.otf */; }; @@ -39,7 +39,7 @@ /* Begin PBXFileReference section */ 4807A6C523A9CD190052A53E /* SkyLight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SkyLight.framework; path = ../../../../System/Library/PrivateFrameworks/SkyLight.framework; sourceTree = ""; }; - D04BA02F476DE30C4647886C /* PreferencesPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesPanel.swift; sourceTree = ""; }; + D04BA02F476DE30C4647886C /* PreferencesWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesWindow.swift; sourceTree = ""; }; D04BA0AF7C5DCF367FBB663C /* StatusItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusItem.swift; sourceTree = ""; }; D04BA0CE87BE264C52987ED1 /* 7 windows - 2 lines - wide window.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "7 windows - 2 lines - wide window.jpg"; sourceTree = ""; }; D04BA0E1C5DBC07108AC2F54 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; @@ -244,7 +244,7 @@ D04BA3202A2C22C347E849B3 /* CollectionViewCenterFlowLayout.swift */, D04BA56355579F78776E6D51 /* Cell.swift */, D04BA90C6C36DB1D65BC2B66 /* App.swift */, - D04BA02F476DE30C4647886C /* PreferencesPanel.swift */, + D04BA02F476DE30C4647886C /* PreferencesWindow.swift */, D04BAE5BBE182DD5DDFE2E3E /* ThumbnailsPanel.swift */, D04BA0AF7C5DCF367FBB663C /* StatusItem.swift */, D04BAD32E130E4A061DC8332 /* Labels.swift */, @@ -363,7 +363,7 @@ D04BA278D9EFA568C8D18A4C /* Windows.swift in Sources */, D04BA3261C7DA5F48310E654 /* App.swift in Sources */, D04BA70FF7262BF5F9E6E13B /* Preferences.swift in Sources */, - D04BA6368E681BE3A408AC99 /* PreferencesPanel.swift in Sources */, + D04BA6368E681BE3A408AC99 /* PreferencesWindow.swift in Sources */, D04BA9119E2329DB5A35B3C7 /* ThumbnailsPanel.swift in Sources */, D04BA8EBC0365A019A27C7EA /* Screen.swift in Sources */, D04BA9CCE02D30C8164A552A /* SystemPermissions.swift in Sources */, diff --git a/alt-tab-macos/logic/Screen.swift b/alt-tab-macos/logic/Screen.swift index 3a7504ff..37d44a3c 100644 --- a/alt-tab-macos/logic/Screen.swift +++ b/alt-tab-macos/logic/Screen.swift @@ -25,18 +25,12 @@ class Screen { return NSSize(width: frame.width * Preferences.maxScreenUsage!, height: frame.height * Preferences.maxScreenUsage!) } - static func repositionPanel(_ panel: NSPanel, _ screen: NSScreen, _ alignment: VerticalAlignment) { + static func repositionPanel(_ window: NSWindow, _ screen: NSScreen, _ alignment: VerticalAlignment) { let screenFrame = screen.visibleFrame - let panelFrame = panel.frame + let panelFrame = window.frame let x = screenFrame.minX + max(screenFrame.width - panelFrame.width, 0) * 0.5 let y = screenFrame.minY + max(screenFrame.height - panelFrame.height, 0) * alignment.rawValue - panel.setFrameOrigin(NSPoint(x: x, y: y)) - } - - static func showPanel(_ panel: NSPanel) { - let panelFrame = panel.frame - panel.makeKeyAndOrderFront(nil) - App.shared.arrangeInFront(nil) + window.setFrameOrigin(NSPoint(x: x, y: y)) } static func mainUuid() -> CFString { diff --git a/alt-tab-macos/ui/App.swift b/alt-tab-macos/ui/App.swift index 112cf7de..4f13c776 100644 --- a/alt-tab-macos/ui/App.swift +++ b/alt-tab-macos/ui/App.swift @@ -7,7 +7,7 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate { static let name = "AltTab" var statusItem: NSStatusItem? var thumbnailsPanel: ThumbnailsPanel? - var preferencesPanel: PreferencesPanel? + var preferencesPanel: PreferencesWindow? var uiWorkShouldBeDone = true var isFirstSummon = true var appIsBeingUsed = false @@ -59,10 +59,10 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate { @objc func showPreferencesPanel() { if preferencesPanel == nil { - preferencesPanel = PreferencesPanel() + preferencesPanel = PreferencesWindow() } Screen.repositionPanel(preferencesPanel!, Screen.preferred(), .appleCentered) - Screen.showPanel(preferencesPanel!) + preferencesPanel?.show() } @objc @@ -96,7 +96,7 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate { Windows.focusedWindowIndex = 0 Windows.cycleFocusedWindowIndex(step) refreshOpenUi() - Screen.showPanel(thumbnailsPanel!) + thumbnailsPanel?.show() } else { debugPrint("showUiOrCycleSelection: !isFirstSummon") cycleSelection(step) @@ -108,7 +108,7 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate { let currentScreen = Screen.preferred() // fix screen between steps since it could change (e.g. mouse moved to another screen) if uiWorkShouldBeDone { thumbnailsPanel!.refreshCollectionView(currentScreen); debugPrint("refreshCollectionView") } if uiWorkShouldBeDone { thumbnailsPanel!.highlightCell(); debugPrint("highlightCellAt") } - if uiWorkShouldBeDone { Screen.repositionPanel(thumbnailsPanel!, currentScreen, .appleCentered); debugPrint("showPanel") } + if uiWorkShouldBeDone { Screen.repositionPanel(thumbnailsPanel!, currentScreen, .appleCentered); debugPrint("repositionPanel") } } func focusSelectedWindow(_ window: Window?) { diff --git a/alt-tab-macos/ui/PreferencesPanel.swift b/alt-tab-macos/ui/PreferencesWindow.swift similarity index 91% rename from alt-tab-macos/ui/PreferencesPanel.swift rename to alt-tab-macos/ui/PreferencesWindow.swift index d65c9c35..261290b0 100644 --- a/alt-tab-macos/ui/PreferencesPanel.swift +++ b/alt-tab-macos/ui/PreferencesWindow.swift @@ -1,23 +1,30 @@ import Cocoa import Foundation -class PreferencesPanel: NSPanel, NSWindowDelegate { - let panelWidth = CGFloat(496) - let panelHeight = CGFloat(256) // auto expands to content height (but does not auto shrink) - let panelPadding = CGFloat(40) +class PreferencesWindow: NSWindow, NSWindowDelegate { + let width = CGFloat(496) + let height = CGFloat(256) // auto expands to content height (but does not auto shrink) + let padding = CGFloat(40) var labelWidth: CGFloat { - return (panelWidth - panelPadding) * CGFloat(0.45) + return (width - padding) * CGFloat(0.45) } var windowCloseRequested = false override init(contentRect: NSRect, styleMask style: StyleMask, backing backingStoreType: BackingStoreType, defer flag: Bool) { - let initialRect = NSRect(x: 0, y: 0, width: panelWidth, height: panelHeight) + let initialRect = NSRect(x: 0, y: 0, width: width, height: height) super.init(contentRect: initialRect, styleMask: style, backing: backingStoreType, defer: flag) title = App.name + " Preferences" hidesOnDeactivate = false + isReleasedWhenClosed = false + styleMask.insert([.miniaturizable, .closable]) contentView = makeContentView() } + func show() { + App.shared.activate(ignoringOtherApps: true) + makeKeyAndOrderFront(nil) + } + public func windowShouldClose(_ sender: NSWindow) -> Bool { windowCloseRequested = true challengeNextInvalidEditableTextField() @@ -46,11 +53,11 @@ class PreferencesPanel: NSPanel, NSWindowDelegate { // visual setup wrappingView.orientation = .vertical wrappingView.alignment = .left - wrappingView.spacing = panelPadding * 0.3 - wrappingView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: panelPadding * 0.5).isActive = true - wrappingView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: panelPadding * -0.5).isActive = true - wrappingView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: panelPadding * 0.5).isActive = true - wrappingView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: panelPadding * -0.5).isActive = true + wrappingView.spacing = padding * 0.3 + wrappingView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: padding * 0.5).isActive = true + wrappingView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: padding * -0.5).isActive = true + wrappingView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: padding * 0.5).isActive = true + wrappingView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: padding * -0.5).isActive = true return contentView } @@ -204,7 +211,7 @@ class PreferencesPanel: NSPanel, NSWindowDelegate { (NSApp as! App).initPreferencesDependentComponents() try Preferences.saveRawToDisk() } catch let error { - debugPrint("PreferencesPanel: save: error", key, newValue, error) + debugPrint("PreferencesWindow: save: error", key, newValue, error) showSaveErrorSheetModal(error as NSError, senderControl, key, previousValue) // allows recursive call by user choice } } @@ -219,11 +226,11 @@ class PreferencesPanel: NSPanel, NSWindowDelegate { alert.beginSheetModal(for: self, completionHandler: { (modalResponse: NSApplication.ModalResponse) -> Void in if modalResponse == NSApplication.ModalResponse.alertFirstButtonReturn { - debugPrint("PreferencesPanel: save: error: user choice: edit") + debugPrint("PreferencesWindow: save: error: user choice: edit") self.windowCloseRequested = false } if modalResponse == NSApplication.ModalResponse.alertSecondButtonReturn { - debugPrint("PreferencesPanel: save: error: user choice: cancel -> revert value and eventually close window") + debugPrint("PreferencesWindow: save: error: user choice: cancel -> revert value and eventually close window") try! Preferences.updateAndValidateFromString(key, previousValue) self.setControlValue(control, previousValue) self.updateControlExtras(control, previousValue) @@ -232,7 +239,7 @@ class PreferencesPanel: NSPanel, NSWindowDelegate { } } if modalResponse == NSApplication.ModalResponse.alertThirdButtonReturn { - debugPrint("PreferencesPanel: save: error: user choice: check again") + debugPrint("PreferencesWindow: save: error: user choice: check again") self.controlWasChanged(senderControl: control) } }) diff --git a/alt-tab-macos/ui/ThumbnailsPanel.swift b/alt-tab-macos/ui/ThumbnailsPanel.swift index 8c2094d1..c39677e8 100644 --- a/alt-tab-macos/ui/ThumbnailsPanel.swift +++ b/alt-tab-macos/ui/ThumbnailsPanel.swift @@ -30,6 +30,10 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele setAccessibilitySubrole(.unknown) } + func show() { + makeKeyAndOrderFront(nil) + } + private func makeBackgroundView() -> NSVisualEffectView { let backgroundView = NSVisualEffectView() backgroundView.translatesAutoresizingMaskIntoConstraints = false