| | |
| | | } |
| | | } |
| | | |
| | | private func foregroundWindowForActivationPolicyRestore() -> NSWindow? { |
| | | if let settingsWindow, settingsWindow.isVisible { |
| | | return settingsWindow |
| | | } |
| | | if let overlayWindow, overlayWindow.isVisible { |
| | | return overlayWindow |
| | | } |
| | | return NSApp.keyWindow |
| | | } |
| | | |
| | | private func setLauncherActivationPolicy(_ desiredPolicy: NSApplication.ActivationPolicy) { |
| | | guard NSApp.activationPolicy() != desiredPolicy else { return } |
| | | |
| | | let restoreWindow = desiredPolicy == .accessory && NSApp.isActive |
| | | ? foregroundWindowForActivationPolicyRestore() |
| | | : nil |
| | | |
| | | // Deactivate before switching regular -> accessory; otherwise Dock can |
| | | // keep a stale running tile until Dock itself restarts. |
| | | if desiredPolicy == .accessory && NSApp.isActive { |
| | | NSApp.deactivate() |
| | | } |
| | | |
| | | NSApp.setActivationPolicy(desiredPolicy) |
| | | |
| | | guard desiredPolicy == .accessory, |
| | | let restoreWindow, |
| | | restoreWindow.isVisible |
| | | else { return } |
| | | |
| | | DispatchQueue.main.async { [weak self, weak restoreWindow] in |
| | | guard let self, |
| | | let restoreWindow, |
| | | restoreWindow.isVisible, |
| | | self.requiresForegroundOwnership |
| | | else { return } |
| | | NSApp.activate(ignoringOtherApps: true) |
| | | restoreWindow.makeKeyAndOrderFront(nil) |
| | | restoreWindow.orderFrontRegardless() |
| | | } |
| | | } |
| | | |
| | | private func beginLauncherForegroundOwnership(activate: Bool = true, keyWindow: NSWindow? = nil) { |
| | | let showDock = UserDefaults.standard.bool(forKey: Self.showDockIconKey) |
| | | let desiredPolicy: NSApplication.ActivationPolicy = showDock ? .regular : .accessory |
| | | if NSApp.activationPolicy() != desiredPolicy { |
| | | NSApp.setActivationPolicy(desiredPolicy) |
| | | setLauncherActivationPolicy(desiredPolicy) |
| | | } |
| | | if activate, showDock { |
| | | claimLauncherForeground(keyWindow: keyWindow) |
| | |
| | | overlayGeneration expectedOverlayGeneration: Int? = nil |
| | | ) { |
| | | if NSApp.activationPolicy() != .regular { |
| | | NSApp.setActivationPolicy(.regular) |
| | | setLauncherActivationPolicy(.regular) |
| | | } |
| | | |
| | | if isOverlayVisible && !NSApp.presentationOptions.contains(.hideDock) { |
| | |
| | | ? .regular |
| | | : (showDock ? .regular : .accessory)))) |
| | | if NSApp.activationPolicy() != desiredPolicy { |
| | | NSApp.setActivationPolicy(desiredPolicy) |
| | | setLauncherActivationPolicy(desiredPolicy) |
| | | } |
| | | |
| | | let desiredPresentation: NSApplication.PresentationOptions = isOverlayVisible ? [.hideDock] : [] |
| | |
| | | super.mouseDown(with: event) |
| | | return |
| | | } |
| | | if routeUsageTipsMouseDownIfNeeded(event) { |
| | | return |
| | | } |
| | | if hit == self { |
| | | if shouldSwallowUsageTipsBackdropClick(at: location) { |
| | | return |
| | | } |
| | | if quickSearchSuppressesBackdropDismiss { |
| | | NotificationCenter.default.post( |
| | | name: .tagLauncherQuickSearchDismissRequested, |
| | |
| | | super.mouseDown(with: event) |
| | | } |
| | | |
| | | private func routeUsageTipsMouseDownIfNeeded(_ event: NSEvent) -> Bool { |
| | | guard let appGridHost = findAppGridCollectionHost(in: self) else { return false } |
| | | return appGridHost.handleUsageTipsMouseDown(event) |
| | | } |
| | | |
| | | private func findAppGridCollectionHost(in view: NSView) -> AppGridCollectionHostView? { |
| | | if let host = view as? AppGridCollectionHostView { |
| | | return host |
| | | } |
| | | for subview in view.subviews { |
| | | if let host = findAppGridCollectionHost(in: subview) { |
| | | return host |
| | | } |
| | | } |
| | | return nil |
| | | } |
| | | |
| | | private func shouldSwallowUsageTipsBackdropClick(at location: NSPoint) -> Bool { |
| | | guard !UserDefaults.standard.bool(forKey: "hideUsageTips") else { return false } |
| | | let height = min(bounds.height, AppGridUsageTipsMetrics.reservedHeight) |
| | | guard height > 0 else { return false } |
| | | let y = isFlipped ? max(0, bounds.height - height) : 0 |
| | | let region = NSRect(x: 0, y: y, width: bounds.width, height: height) |
| | | return region.contains(location) |
| | | } |
| | | |
| | | private func observeBackdropDismissSuppressionChanges() { |
| | | modalInteractionObserver = NotificationCenter.default.addObserver( |
| | | forName: .tagLauncherModalInteractionChanged, |