-
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add universal back and forward support (#14)
- Loading branch information
Showing
22 changed files
with
1,186 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// ScrollWheelEventTap.swift | ||
// LinearMouse | ||
// | ||
// Created by lujjjh on 2021/6/11. | ||
// | ||
|
||
import Foundation | ||
|
||
class EventTap { | ||
var eventTap: CFMachPort? | ||
var runLoopSource: CFRunLoopSource? | ||
|
||
let eventTapCallback: CGEventTapCallBack = { (proxy, type, event, refcon) in | ||
if let transformed: CGEvent = { | ||
switch type { | ||
case .scrollWheel: | ||
return MouseWheelEvent(event).transformed | ||
case .otherMouseUp: | ||
return fixSideButtonsEvent(event) | ||
default: | ||
return event | ||
} | ||
}() { | ||
return Unmanaged.passUnretained(transformed) | ||
} | ||
return nil | ||
} | ||
|
||
init() { | ||
let eventsOfInterest: CGEventMask = | ||
1 << CGEventType.scrollWheel.rawValue | ||
| 1 << CGEventType.otherMouseUp.rawValue | ||
eventTap = CGEvent.tapCreate( | ||
tap: .cghidEventTap, | ||
place: .tailAppendEventTap, | ||
options: .defaultTap, | ||
eventsOfInterest: eventsOfInterest, | ||
callback: eventTapCallback, | ||
userInfo: nil | ||
) | ||
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) | ||
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, CFRunLoopMode.commonModes) | ||
CFRunLoopRun() | ||
} | ||
|
||
func enable() { | ||
if let eventTap = eventTap { | ||
CGEvent.tapEnable(tap: eventTap, enable: true) | ||
} | ||
} | ||
|
||
func disable() { | ||
if let eventTap = eventTap { | ||
CGEvent.tapEnable(tap: eventTap, enable: false) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// | ||
// Touch-Bridging-Header.h | ||
// LinearMouse | ||
// | ||
// Created by lujjjh on 2021/8/5. | ||
// | ||
|
||
#include "../Touch/TouchSimulate.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// | ||
// MouseWheelEvent.swift | ||
// LinearMouse | ||
// | ||
// Created by lujjjh on 2021/8/1. | ||
// | ||
|
||
import Foundation | ||
|
||
class MouseWheelEvent { | ||
let event: CGEvent | ||
|
||
let defaults = AppDefaults.shared | ||
|
||
var continuous: Bool { | ||
get { event.getIntegerValueField(.scrollWheelEventIsContinuous) != 0 } | ||
set { event.setIntegerValueField(.scrollWheelEventIsContinuous, value: newValue ? 1 : 0) } | ||
} | ||
|
||
var deltaX: Int64 { | ||
get { event.getIntegerValueField(.scrollWheelEventDeltaAxis2) } | ||
set { event.setIntegerValueField(.scrollWheelEventDeltaAxis2, value: newValue) } | ||
} | ||
|
||
var deltaY: Int64 { | ||
get { event.getIntegerValueField(.scrollWheelEventDeltaAxis1) } | ||
set { event.setIntegerValueField(.scrollWheelEventDeltaAxis1, value: newValue) } | ||
} | ||
|
||
init(_ event: CGEvent) { | ||
self.event = event | ||
} | ||
|
||
lazy var transformed: CGEvent = { | ||
guard !continuous else { | ||
return event | ||
} | ||
|
||
if defaults.reverseScrollingOn { | ||
negateDelta() | ||
} | ||
|
||
if defaults.linearScrollingOn { | ||
let scrollLines = Int64(defaults.scrollLines) | ||
deltaX = deltaX.signum() * scrollLines | ||
deltaY = deltaY.signum() * scrollLines | ||
} | ||
|
||
modifierActions() | ||
|
||
return event | ||
}() | ||
|
||
func negateDelta() { | ||
deltaX = -deltaX | ||
deltaY = -deltaY | ||
} | ||
|
||
func modifierActions() { | ||
let actions: [(CGEventFlags.Element, ModifierKeyAction)] = [ | ||
(.maskCommand, defaults.modifiersCommandAction), | ||
(.maskShift, defaults.modifiersShiftAction), | ||
(.maskAlternate, defaults.modifiersAlternateAction), | ||
(.maskControl, defaults.modifiersControlAction), | ||
] | ||
for case (let flag, let action) in actions { | ||
if event.flags.contains(flag) { | ||
if handleModifierKeyAction(for: event, action: action) { | ||
event.flags.remove(flag) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func handleModifierKeyAction(for event: CGEvent, action: ModifierKeyAction) -> Bool { | ||
guard action.type != .noAction else { | ||
return false | ||
} | ||
|
||
// fix orientation on Catalina | ||
// TODO: is there a better way? | ||
if deltaY == 0 { | ||
(deltaX, deltaY) = (deltaY, deltaX) | ||
} | ||
|
||
switch action.type { | ||
case .noAction: // make the compiler happy | ||
break | ||
case .alterOrientation: | ||
(deltaX, deltaY) = (deltaY, deltaX) | ||
case .changeSpeed: | ||
let factor = action.speedFactor | ||
let scale = { (delta: Int64, factor: Double) in Int64((Double(delta) * factor).rounded()) } | ||
deltaX = deltaX.signum() * max(1, abs(scale(deltaX, factor))) | ||
deltaY = deltaY.signum() * max(1, abs(scale(deltaY, factor))) | ||
} | ||
|
||
return true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.