Skip to content

Commit 92cd898

Browse files
committed
♻️ Migrate MultitouchTrigger to SubsurfaceGestureRecognizer
1 parent b17c6cd commit 92cd898

3 files changed

Lines changed: 143 additions & 294 deletions

File tree

Loop/Core/LoopManager.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ final class LoopManager {
7575
await self?.closeLoop(forceClose: forceClose)
7676
}
7777
},
78-
changeAction: { [weak self] action in
78+
changeAction: { [weak self] action, reverse in
7979
Task {
80-
await self?.changeAction(action)
80+
await self?.changeAction(action, reverse: reverse)
8181
}
8282
},
8383
checkIfLoopOpen: { [weak self] in
@@ -257,7 +257,8 @@ extension LoopManager {
257257
_ newAction: WindowAction,
258258
triggeredFromScreenChange: Bool = false,
259259
disableHapticFeedback: Bool = false,
260-
canAdvanceCycle: Bool = true
260+
canAdvanceCycle: Bool = true,
261+
reverse: Bool = false
261262
) async {
262263
guard
263264
isLoopActive,
@@ -286,7 +287,7 @@ extension LoopManager {
286287
// The ability to advance a cycle is only available when the action is triggered via a keybind or a left click on the mouse.
287288
// This should be set to false when the mouse is moved to prevent rapid cycling.
288289
if canAdvanceCycle {
289-
newAction = await getNextCycleAction(newAction)
290+
newAction = await getNextCycleAction(newAction, reverse: reverse)
290291
} else {
291292
if let cycle = newAction.cycle, !cycle.contains(resizeContext.action) {
292293
newAction = cycle.first ?? .init(.noAction)
@@ -444,7 +445,7 @@ extension LoopManager {
444445
}
445446
}
446447

447-
private func getNextCycleAction(_ action: WindowAction) async -> WindowAction {
448+
private func getNextCycleAction(_ action: WindowAction, reverse: Bool) async -> WindowAction {
448449
guard let currentCycle = action.cycle else {
449450
return action
450451
}
@@ -457,7 +458,7 @@ extension LoopManager {
457458
&& Defaults[.triggerKey].contains(.kVK_Shift) == false
458459
&& Defaults[.cycleBackwardsOnShiftPressed]
459460

460-
let shouldCycleBackwards = allowReverseCycle && keybindTrigger.effectiveEventFlags.contains(.maskShift)
461+
let shouldCycleBackwards = reverse || (allowReverseCycle && keybindTrigger.effectiveEventFlags.contains(.maskShift))
461462
var currentIndex: Int? = nil
462463

463464
if Defaults[.cycleModeRestartEnabled],
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// MultitouchGestureBlocker.swift
3+
// Loop
4+
//
5+
// Created by Kai Azim on 2026-04-05.
6+
//
7+
8+
import AppKit
9+
import Scribe
10+
11+
@Loggable
12+
final class MultitouchGestureBlocker {
13+
private var monitor: ActiveEventMonitor?
14+
15+
func start() {
16+
log.info("Starting gesture blocker")
17+
18+
let eventTypes: [CGEventType] = [
19+
.scrollWheel,
20+
CGEventType(rawValue: UInt32(NSEvent.EventType.gesture.rawValue)),
21+
CGEventType(rawValue: UInt32(NSEvent.EventType.magnify.rawValue)),
22+
CGEventType(rawValue: UInt32(NSEvent.EventType.rotate.rawValue)),
23+
CGEventType(rawValue: UInt32(NSEvent.EventType.smartMagnify.rawValue))
24+
].compactMap(\.self)
25+
26+
monitor = ActiveEventMonitor("gesture_blocker", events: eventTypes) { _ in .ignore }
27+
monitor?.start()
28+
}
29+
30+
func stop() {
31+
monitor?.stop()
32+
monitor = nil
33+
34+
log.info("Stopped gesture blocker")
35+
}
36+
}

0 commit comments

Comments
 (0)