fix: better handle context menu in search bar
This commit is contained in:
1 parent
106f7c90f9
commit
9aea8f62c9
8 files changed
+59
-8
No files matched your search
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 : ""
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in new issue
Block a user