| | |
| | | Settings { |
| | | PreferencesView() |
| | | } |
| | | .defaultSize(width: 1000, height: 480) |
| | | .defaultSize(width: 1000, height: 640) |
| | | .commands { |
| | | CommandGroup(replacing: .systemServices) { } |
| | | CommandGroup(replacing: .appVisibility) { } |
| | |
| | | private static let launcherOverlayLevel = NSWindow.Level(rawValue: NSWindow.Level.mainMenu.rawValue - 1) |
| | | private static let overlayDefaultLevel = launcherOverlayLevel |
| | | private static let overlayTextInputLevel = launcherOverlayLevel |
| | | private static let settingsContentSize = NSSize(width: 1000, height: 640) |
| | | |
| | | private var statusItem: NSStatusItem? |
| | | private var overlayKeyMonitor: Any? |
| | |
| | | .combinedSessionState, |
| | | eventType: .leftMouseUp |
| | | ) |
| | | let recentMouseClick = min(lastMouseDown, lastMouseUp) < 1.2 |
| | | let recentMouseClick = min(lastMouseDown, lastMouseUp) < 0.9 |
| | | return recentMouseClick && isPointerNearDockArea() |
| | | } |
| | | |
| | | private func isPointerNearDockArea() -> Bool { |
| | | let mouse = NSEvent.mouseLocation |
| | | let dockOrientation = UserDefaults(suiteName: "com.apple.dock")? |
| | | .string(forKey: "orientation") ?? "bottom" |
| | | let hiddenDockEdgeTolerance: CGFloat = 96 |
| | | return NSScreen.screens.contains { screen in |
| | | let frame = screen.frame |
| | | let visible = screen.visibleFrame |
| | |
| | | let rightDock = visible.maxX < frame.maxX |
| | | && mouse.x <= frame.maxX |
| | | && mouse.x >= visible.maxX - 24 |
| | | return bottomDock || leftDock || rightDock |
| | | let hiddenDockFallback: Bool |
| | | switch dockOrientation { |
| | | case "left": |
| | | hiddenDockFallback = mouse.x <= frame.minX + hiddenDockEdgeTolerance |
| | | case "right": |
| | | hiddenDockFallback = mouse.x >= frame.maxX - hiddenDockEdgeTolerance |
| | | default: |
| | | hiddenDockFallback = mouse.y <= frame.minY + hiddenDockEdgeTolerance |
| | | } |
| | | return bottomDock || leftDock || rightDock || hiddenDockFallback |
| | | } |
| | | } |
| | | |
| | |
| | | /// Settings must always appear centered over the current overlay view and float above it. |
| | | private func prepareSettingsWindow(_ window: NSWindow) { |
| | | dismissQuickSearchIfNeeded() |
| | | let settingsSize = NSSize(width: 1000, height: 480) |
| | | let settingsSize = Self.settingsContentSize |
| | | let settingsFrameSize = window.frameRect( |
| | | forContentRect: NSRect(origin: .zero, size: settingsSize) |
| | | ).size |
| | | window.identifier = NSUserInterfaceItemIdentifier("TagLauncherPreferencesWindow") |
| | | window.minSize = settingsSize |
| | | window.maxSize = settingsSize |
| | | if abs(window.frame.width - settingsSize.width) > 0.5 || abs(window.frame.height - settingsSize.height) > 0.5 { |
| | | window.setFrame( |
| | | NSRect(origin: window.frame.origin, size: settingsSize), |
| | | display: false |
| | | ) |
| | | window.contentMinSize = settingsSize |
| | | window.contentMaxSize = settingsSize |
| | | window.minSize = settingsFrameSize |
| | | window.maxSize = settingsFrameSize |
| | | let currentContentSize = window.contentView?.bounds.size ?? window.contentLayoutRect.size |
| | | if abs(currentContentSize.width - settingsSize.width) > 0.5 |
| | | || abs(currentContentSize.height - settingsSize.height) > 0.5 { |
| | | window.setContentSize(settingsSize) |
| | | } |
| | | |
| | | if let overlayWindow, overlayWindow.isVisible { |
| | |
| | | return |
| | | } |
| | | |
| | | let settingsSize = NSSize(width: 1000, height: 480) |
| | | let window = NSWindow( |
| | | contentRect: NSRect(origin: .zero, size: settingsSize), |
| | | contentRect: NSRect(origin: .zero, size: Self.settingsContentSize), |
| | | styleMask: [.titled, .closable], |
| | | backing: .buffered, |
| | | defer: false |