fix: better handle context menu in search bar

This commit is contained in:
lwouis committed 2026-03-10 21:33:00 +01:00
1 parent 106f7c90f9
commit 9aea8f62c9
8 files changed
+59 -8

No files matched your search

+4
View File
@@ -210,6 +210,7 @@
BF0C8F303887F8454452F85C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C843F6EF209A70B06FE19 /* Localizable.strings */; };
BF0C8F3526BC393290D5BE59 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C81EC1C5F3052A75C7D7B /* InfoPlist.strings */; };
BF0C8F40C2D0FF7601D926D3 /* LightweightTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8363D45FECB8D6F8DCD5 /* LightweightTimer.swift */; };
BF0C8F8F1B7A3C4D5E6F7082 /* ContextMenuEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8F8E1B7A3C4D5E6F7081 /* ContextMenuEvents.swift */; };
BF0C8F9B8014AD21E68B1349 /* HelperExtensionsTestable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C810FA0F6BC70E5886E11 /* HelperExtensionsTestable.swift */; };
BF0C8FF2A4B00D409494EA80 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C88D79FA0C773D94F351A /* InfoPlist.strings */; };
BF0CAAAA0000000000001001 /* SearchAcronymTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0CAAAA0000000000000001 /* SearchAcronymTests.swift */; };
@@ -581,6 +582,7 @@
BF0C8EE00994AC6C8323EE12 /* table-of-contents.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "table-of-contents.js"; sourceTree = "<group>"; };
BF0C8EE17F3ABD7A6D44BFFE /* pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pl; path = Localizable.strings; sourceTree = "<group>"; };
BF0C8F58B38F29B2662E6C2D /* PreferencesMigrations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesMigrations.swift; sourceTree = "<group>"; };
BF0C8F8E1B7A3C4D5E6F7081 /* ContextMenuEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuEvents.swift; sourceTree = "<group>"; };
BF0C8FAF34022E23582797F3 /* ScrollwheelEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollwheelEvents.swift; sourceTree = "<group>"; };
BF0C8FB9777EE9BE74EF542B /* zh-hk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = "zh-hk"; path = Localizable.strings; sourceTree = "<group>"; };
BF0C8FC083A2443F3EAF5DB7 /* preferences-blacklist.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "preferences-blacklist.jpg"; sourceTree = "<group>"; };
@@ -2033,6 +2035,7 @@
BF0C8C69316EAAF6DC9AE391 /* CliEvents.swift */,
BF0C8FAF34022E23582797F3 /* ScrollwheelEvents.swift */,
BF0C81DD40D5AAD9B7C09028 /* CursorEvents.swift */,
BF0C8F8E1B7A3C4D5E6F7081 /* ContextMenuEvents.swift */,
);
path = events;
sourceTree = "<group>";
@@ -2643,6 +2646,7 @@
BF0C8AD478399D2E97AE3FB4 /* CustomRecorderControlTestable.swift in Sources */,
BF0C8A5FA46C5E74A071FF4C /* ScrollwheelEvents.swift in Sources */,
BF0C82E9AB495AAAA182764A /* CursorEvents.swift in Sources */,
BF0C8F8F1B7A3C4D5E6F7082 /* ContextMenuEvents.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+44
View File
@@ -0,0 +1,44 @@
import Cocoa
class ContextMenuEvents {
private static var isEnabled = false
private static var beginObserver: NSObjectProtocol?
private static var endObserver: NSObjectProtocol?
private static var openMenuCount = 0
static var isMenuOpen: Bool { openMenuCount > 0 }
static func toggle(_ enabled: Bool) {
guard enabled != isEnabled else { return }
isEnabled = enabled
if enabled {
startObserving()
} else {
stopObserving()
}
}
private static func startObserving() {
guard beginObserver == nil, endObserver == nil else { return }
let center = NotificationCenter.default
beginObserver = center.addObserver(forName: NSMenu.didBeginTrackingNotification, object: nil, queue: .main) { _ in
openMenuCount += 1
}
endObserver = center.addObserver(forName: NSMenu.didEndTrackingNotification, object: nil, queue: .main) { _ in
openMenuCount = max(0, openMenuCount - 1)
}
}
private static func stopObserving() {
openMenuCount = 0
let center = NotificationCenter.default
if let beginObserver {
center.removeObserver(beginObserver)
self.beginObserver = nil
}
if let endObserver {
center.removeObserver(endObserver)
self.endObserver = nil
}
}
}
+3 -2
View File
@@ -58,7 +58,7 @@ class CursorEvents {
}
private static func handleLeftMouseDown(_ cgEvent: CGEvent) -> Unmanaged<CGEvent>? {
if TilesView.hasMarkedText() { return Unmanaged.passUnretained(cgEvent) }
if TilesView.hasMarkedText() || ContextMenuEvents.isMenuOpen { return Unmanaged.passUnretained(cgEvent) }
if isPointerInsideSearchField() {
mouseDownInsideSearchField = true
return Unmanaged.passUnretained(cgEvent)
@@ -70,7 +70,7 @@ class CursorEvents {
}
private static func handleLeftMouseUp(_ cgEvent: CGEvent) -> Unmanaged<CGEvent>? {
if TilesView.hasMarkedText() { return Unmanaged.passUnretained(cgEvent) }
if TilesView.hasMarkedText() || ContextMenuEvents.isMenuOpen { return Unmanaged.passUnretained(cgEvent) }
if mouseDownInsideSearchField || isPointerInsideSearchField() {
mouseDownInsideSearchField = false
return Unmanaged.passUnretained(cgEvent)
@@ -94,6 +94,7 @@ class CursorEvents {
}
private static func handleOtherMouseUp(_ cgEvent: CGEvent) -> Unmanaged<CGEvent>? {
if ContextMenuEvents.isMenuOpen { return Unmanaged.passUnretained(cgEvent) }
guard isPointerInsideUi(),
cgEvent.getIntegerValueField(.mouseEventButtonNumber) == 2,
let target = findTileViewUnderPointer(),
+2 -1
View File
@@ -59,6 +59,7 @@ class App: AppCenterApplication {
isFirstSummon = true
forceDoNothingOnRelease = false
TilesView.endSearchSession()
ContextMenuEvents.toggle(false)
CursorEvents.toggle(false)
TrackpadEvents.reset()
hideTilesPanelWithoutChangingKeyWindow()
@@ -66,7 +67,7 @@ class App: AppCenterApplication {
PreviewPanel.shared.orderOut(nil)
}
hideAllTooltips()
MainMenu.toggle(enabled: true)
MainMenu.toggle(true)
}
/// some tooltips may not be hidden when the main window is hidden; we force it through a private API
+1 -1
View File
@@ -12,7 +12,7 @@ class MainMenu {
rememberMenuItemsWithShortcut()
}
static func toggle(enabled: Bool) {
static func toggle(_ enabled: Bool) {
for (item, keyEquivalent) in menuItemsWithShortcut {
item.keyEquivalent = enabled ? keyEquivalent : ""
}
+1 -1
View File
@@ -36,7 +36,7 @@ class TileOverView: FlippedView {
// MARK: - Mouse hover management
func updateHover() {
guard let scrollView, !scrollView.isCurrentlyScrolling, !TilesView.hasMarkedText() else { return }
guard let scrollView, !scrollView.isCurrentlyScrolling, !TilesView.hasMarkedText(), !ContextMenuEvents.isMenuOpen else { return }
let location = convert(TilesPanel.shared.mouseLocationOutsideOfEventStream, from: nil)
updateButtonHover(location)
let newTarget = findTarget(location)
+3 -2
View File
@@ -64,6 +64,7 @@ class TilesPanel: NSPanel {
updateAppearance()
alphaValue = 1
makeKeyAndOrderFront(nil)
ContextMenuEvents.toggle(true)
CursorEvents.toggle(true)
DispatchQueue.main.async { TilesView.scrollView.flashScrollers() }
}
@@ -118,7 +119,7 @@ extension TilesPanel: NSWindowDelegate {
if App.appIsBeingUsed {
TilesPanel.shared.makeKeyAndOrderFront(nil)
}
MainMenu.toggle(enabled: true)
MainMenu.toggle(true)
}
}
@@ -126,7 +127,7 @@ extension TilesPanel: NSWindowDelegate {
// we toggle the mainMenu off when showing the main window
// this avoids command+q from quitting AltTab itself, or command+p from printing
DispatchQueue.main.async {
MainMenu.toggle(enabled: false)
MainMenu.toggle(false)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
Applications.manuallyRefreshAllWindows()
+1 -1
View File
@@ -107,7 +107,7 @@ class TilesView {
}
static func handleSearchEditingKeyDown(_ event: NSEvent) -> SearchKeyResult {
if hasMarkedText() { return .passToField }
if hasMarkedText() || ContextMenuEvents.isMenuOpen { return .passToField }
let keyCode = event.keyCode
if keyCode == UInt16(kVK_LeftArrow) { App.cycleSelection(.left); return .handled }
if keyCode == UInt16(kVK_RightArrow) { App.cycleSelection(.right); return .handled }