forked from gnachman/iTerm2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ThreeFingerTapGestureRecognizer.m
127 lines (112 loc) · 3.42 KB
/
ThreeFingerTapGestureRecognizer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//
// ThreeFingerTapGestureRecognizer.m
// iTerm
//
// Created by George Nachman on 1/9/13.
//
//
#import "ThreeFingerTapGestureRecognizer.h"
#import "FutureMethods.h"
#import "iTermApplicationDelegate.h"
static const NSTimeInterval kDelay = 0.35; // Just a bit longer than the system's default delay for detecting a two-finger tap.
@implementation ThreeFingerTapGestureRecognizer
- (id)initWithTarget:(NSView *)target selector:(SEL)selector {
self = [super init];
if (self) {
target_ = target;
selector_ = selector;
}
return self;
}
- (void)cancel {
firstTouchTime_ = 0;
}
- (void)touchesBeganWithEvent:(NSEvent *)ev
{
fired_ = NO;
DLog(@"fired->NO");
int touches = [[ev futureTouchesMatchingPhase:1 | (1 << 2)/*NSTouchPhasesBegan | NSTouchPhasesStationary*/
inView:target_] count];
if (numTouches_ == 0 && touches > 0) {
DLog(@"Set first touch time");
firstTouchTime_ = [NSDate timeIntervalSinceReferenceDate];
}
if (numTouches_ < 3 && touches == 3) {
DLog(@"Set three touch time");
threeTouchTime_ = [NSDate timeIntervalSinceReferenceDate];
}
if (numTouches_ > 3) {
DLog(@"Too many touches!");
// Not possible to be a three finger tap if more than three fingers were down at any point.
[self cancel];
}
if (firstTouchTime_ && threeTouchTime_ && touches < 3) {
DLog(@"Touch count not concave");
// Number of touches went down and then up: can't be a three finger tap.
[self cancel];
}
numTouches_ = touches;
}
- (void)touchesEndedWithEvent:(NSEvent *)ev
{
numTouches_ = [[ev futureTouchesMatchingPhase:(1 << 2)/*NSTouchPhasesStationary*/
inView:target_] count];
const NSTimeInterval maxTimeForSimulatedThreeFingerTap = 1;
if (numTouches_ == 0 &&
firstTouchTime_ &&
threeTouchTime_ &&
[NSDate timeIntervalSinceReferenceDate] - firstTouchTime_ < maxTimeForSimulatedThreeFingerTap) {
DLog(@"Fake a three finger click");
[target_ performSelector:selector_ withObject:ev];
DLog(@"fired->YES");
fired_ = YES;
}
if (numTouches_ == 0) {
DLog(@"Reset first/three times");
firstTouchTime_ = 0;
threeTouchTime_ = 0;
}
DLog(@"%@ End touch. numTouches_ -> %d (first=%d, three=%d, dt=%d)", self, numTouches_, (int)firstTouchTime_, (int)threeTouchTime_, (int)([NSDate timeIntervalSinceReferenceDate] - firstTouchTime_));
}
- (void)touchesCancelledWithEvent:(NSEvent *)event {
DLog(@"%@ canceled", self);
numTouches_ = 0;
firstTouchTime_ = 0;
threeTouchTime_ = 0;
}
- (BOOL)getAndResetFired {
// This is called for [right]mouseUp events. It returns and resets the value of fired_ so it doesn't get stuck.
BOOL value = fired_;
DLog(@"get and reset fired. fired->NO");
fired_ = NO;
return value;
}
- (BOOL)rightMouseDown:(NSEvent*)event
{
DLog(@"Right mouse down");
[self cancel];
return fired_;
}
- (BOOL)rightMouseUp:(NSEvent*)event
{
DLog(@"right mouse up");
[self cancel];
return [self getAndResetFired];
}
- (BOOL)mouseDown:(NSEvent*)event
{
DLog(@"mouse down");
[self cancel];
return fired_;
}
- (BOOL)mouseUp:(NSEvent*)event
{
DLog(@"mouse up");
[self cancel];
return [self getAndResetFired];
}
- (void)disconnectTarget
{
target_ = nil;
}
@end