Skip to content

Commit b6e7ec5

Browse files
committed
🐞 Fix multitouch gesture targeting and magnify gate
1 parent f56c1de commit b6e7ec5

3 files changed

Lines changed: 26 additions & 4 deletions

File tree

Loop/Core/Multitouch/MultitouchRecognizerRegistry.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ final class MultitouchRecognizerRegistry {
109109
) {
110110
let recognizer = SubsurfaceGestureRecognizer(
111111
fingerCount: fingerCount,
112+
recognizedGestureTypes: [.swipe, .magnify],
112113
requiresExactFingerCountToContinue: true
113114
)
114115

Loop/Core/Multitouch/MultitouchTargetResolver.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ final class MultitouchTargetResolver {
1515
/// Window most recently targeted by a repeatable gesture.
1616
/// Lets shrinking/growing continue after the cursor falls off the resized frame.
1717
private var lastRepeatableWindow: Window?
18+
private var gestureWindowLookups: [GestureBinding.ActivationZone: WindowLookup] = [:]
1819

1920
func reset() {
2021
lastRepeatableWindow = nil
22+
resetGestureState()
23+
}
24+
25+
func resetGestureState() {
26+
gestureWindowLookups.removeAll()
2127
}
2228

2329
func targetWindow(for gesture: GestureBinding, allowsRapidRepeat: Bool) -> Window? {
@@ -35,13 +41,19 @@ final class MultitouchTargetResolver {
3541

3642
private func findTargetWindow(for gesture: GestureBinding) -> Window? {
3743
let cursorPosition = NSEvent.mouseLocation.flipY(screen: NSScreen.screens[0])
44+
let activationZone: GestureBinding.ActivationZone = gesture.fingerCount <= 2 ? .titlebar : gesture.activationZone
45+
46+
if let windowLookup = gestureWindowLookups[activationZone] {
47+
return windowLookup.window
48+
}
3849

3950
guard let window = WindowUtility.windowAtPosition(cursorPosition) else {
51+
gestureWindowLookups[activationZone] = WindowLookup(window: nil)
4052
return nil
4153
}
4254

4355
// 2-finger gestures are always titlebar-only to avoid system gesture conflicts.
44-
switch gesture.fingerCount <= 2 ? .titlebar : gesture.activationZone {
56+
switch activationZone {
4557
case .titlebar:
4658
let minimumTitlebarHeight = Defaults[.gestureTitlebarHeight]
4759
let titlebarHeight: CGFloat = if #available(macOS 26, *) {
@@ -60,10 +72,17 @@ final class MultitouchTargetResolver {
6072
let titlebarMinY = window.frame.minY
6173
let titlebarMaxY = window.frame.minY + titlebarHeight
6274
let isInTitlebar = cursorPosition.y >= titlebarMinY && cursorPosition.y <= titlebarMaxY
63-
return isInTitlebar ? window : nil
75+
let targetWindow = isInTitlebar ? window : nil
76+
gestureWindowLookups[activationZone] = WindowLookup(window: targetWindow)
77+
return targetWindow
6478

6579
case .anywhere:
80+
gestureWindowLookups[activationZone] = WindowLookup(window: window)
6681
return window
6782
}
6883
}
6984
}
85+
86+
private struct WindowLookup {
87+
let window: Window?
88+
}

Loop/Core/Multitouch/MultitouchTrigger.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ final class MultitouchTrigger {
3636
private var isStarted = false
3737

3838
let swipeCycleStepSize: CGFloat = 0.15
39-
let magnifyStepSize: CGFloat = 0.3
39+
let magnifyStepSize: CGFloat = 0.2
4040
let cardinalBiasedRadialMenuActionCount = 8
4141

4242
var radialMenuActions = RadialMenuAction.userConfiguredActions
@@ -208,13 +208,14 @@ final class MultitouchTrigger {
208208
magnifyDisplacement: CGFloat? = nil
209209
) async -> Bool {
210210
guard let session = recognizerRegistry.session(for: fingerCount), !session.isGestureRejected else { return false }
211-
if session.hasActivated { return true }
212211

213212
if let magnifyDisplacement,
214213
abs(magnifyDisplacement) < magnifyStepSize {
215214
return false
216215
}
217216

217+
if session.hasActivated { return true }
218+
218219
var openedLoop = false
219220
if let window = session.pendingTargetWindow {
220221
do {
@@ -241,6 +242,7 @@ final class MultitouchTrigger {
241242

242243
gestureBlocker.stop()
243244
recognizerRegistry.session(for: fingerCount)?.reset()
245+
targetResolver.resetGestureState()
244246
}
245247
}
246248

0 commit comments

Comments
 (0)