1 /*
2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
25
26 #import "common.h"
27 #import "com_sun_glass_events_TouchEvent.h"
28
29 #import "GlassMacros.h"
30 #import "GlassTouches.h"
31 #import "GlassKey.h"
32 #import "GlassHelper.h"
33 #import "GlassStatics.h"
34
35
36 //#define VERBOSE
37 #ifndef VERBOSE
38 #define LOG(MSG, ...)
39 #else
40 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
41 #endif
42
43
44 static GlassTouches* glassTouches = nil;
45
46
47 @interface GlassTouches (hidden)
48
49 - (void)releaseTouches;
50
51 - (void)terminateImpl;
52
53 - (void)enableTouchInputEventTap;
54
55 - (void)sendJavaTouchEvent:(NSEvent *)theEvent;
56 - (void)notifyTouch:(JNIEnv*)env identity:(const id)identity
57 phase:(NSUInteger)phase
58 pos:(const NSPoint*)pos;
59 @end
60
61
62 static jint getTouchStateFromPhase(NSUInteger phase)
63 {
64 switch (phase)
159 if (!glassTouches || glassTouches->curConsumer != delegate)
160 {
161 return;
162 }
163
164 // Keep updating java touch point counter, just have no view to notify.
165 glassTouches->curConsumer = nil;
166
167 LOG("TOUCHES: stopTracking: delegate=%p\n", glassTouches->curConsumer);
168 }
169
170 + (void)terminate
171 {
172 // Should be called right after Application's run loop terminate
173 [glassTouches terminateImpl];
174 glassTouches = nil;
175 }
176
177 - (id)init
178 {
179 self = [super init];
180 if (self != nil)
181 {
182 self->curConsumer = nil;
183 self->eventTap = nil;
184 self->runLoopSource = nil;
185 self->touches = nil;
186 self->lastTouchId = 0;
187
188 //
189 // Notes after fixing RT-23199:
190 //
191 // Don't use NSMachPort and NSRunLoop to integrate CFMachPortRef
192 // instance into run loop.
193 //
194 // Ignoring the above "don't"s results into performance degradation
195 // referenced in the bug.
196 //
197
198 self->eventTap = CGEventTapCreate(kCGHIDEventTap,
199 kCGHeadInsertEventTap,
200 kCGEventTapOptionListenOnly,
201 CGEventMaskBit(NSEventTypeGesture),
202 listenTouchEvents, nil);
203
204 LOG("TOUCHES: eventTap=%p\n", self->eventTap);
205
206 if (self->eventTap)
207 { // Create a run loop source.
208 self->runLoopSource = CFMachPortCreateRunLoopSource(
209 kCFAllocatorDefault,
210 self->eventTap, 0);
211
212 LOG("TOUCHES: runLoopSource=%p\n", self->runLoopSource);
213
214 // Add to the current run loop.
215 CFRunLoopAddSource(CFRunLoopGetCurrent(), self->runLoopSource,
216 kCFRunLoopCommonModes);
217 }
218 }
219 return self;
220 }
221
222 @end
223
224
225 @implementation GlassTouches (hidden)
226 - (void)terminateImpl
227 {
228 LOG("TOUCHES: terminateImpl eventTap=%p runLoopSource=%p\n", self->eventTap,
229 self->runLoopSource);
230
231 if (self->runLoopSource)
232 {
233 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), self->runLoopSource,
234 kCFRunLoopCommonModes);
235 CFRelease(self->runLoopSource);
236 self->runLoopSource = nil;
237 }
238
239 if (self->eventTap)
240 {
241 CFRelease(self->eventTap);
242 self->eventTap = nil;
243 }
244
245 [self releaseTouches];
246 }
247
248 - (void)enableTouchInputEventTap
249 {
250 CGEventTapEnable(self->eventTap, true);
251 }
252
253 - (void)sendJavaTouchEvent:(NSEvent *)theEvent
254 {
255 jint modifiers = GetJavaModifiers(theEvent);
256
257 const NSSet* touchPoints =
258 [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
259
260 //
261 // Known issues with OSX touch input:
262 // - multiple 'NSTouchPhaseBegan' for the same touch point;
263 // - missing 'NSTouchPhaseEnded' for released touch points
264 // (RT-20139, RT-20375);
265 //
266
267 //
268 // Find just released touch points that are not in the cache already.
269 // Don't send TouchEvent#TOUCH_RELEASED for these touch points.
270 //
|
1 /*
2 * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
25
26 #import "common.h"
27 #import "com_sun_glass_events_TouchEvent.h"
28
29 #import "GlassMacros.h"
30 #import "GlassTouches.h"
31 #import "GlassKey.h"
32 #import "GlassHelper.h"
33 #import "GlassStatics.h"
34
35
36 //#define VERBOSE
37 #ifndef VERBOSE
38 #define LOG(MSG, ...)
39 #else
40 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
41 #endif
42
43
44 static GlassTouches* glassTouches = nil;
45 static BOOL useEventTap = NO;
46
47
48 @interface GlassTouches (hidden)
49
50 - (void)releaseTouches;
51
52 - (void)terminateImpl;
53
54 - (void)enableTouchInputEventTap;
55
56 - (void)sendJavaTouchEvent:(NSEvent *)theEvent;
57 - (void)notifyTouch:(JNIEnv*)env identity:(const id)identity
58 phase:(NSUInteger)phase
59 pos:(const NSPoint*)pos;
60 @end
61
62
63 static jint getTouchStateFromPhase(NSUInteger phase)
64 {
65 switch (phase)
160 if (!glassTouches || glassTouches->curConsumer != delegate)
161 {
162 return;
163 }
164
165 // Keep updating java touch point counter, just have no view to notify.
166 glassTouches->curConsumer = nil;
167
168 LOG("TOUCHES: stopTracking: delegate=%p\n", glassTouches->curConsumer);
169 }
170
171 + (void)terminate
172 {
173 // Should be called right after Application's run loop terminate
174 [glassTouches terminateImpl];
175 glassTouches = nil;
176 }
177
178 - (id)init
179 {
180 useEventTap = YES;
181 if (@available(macOS 10.15, *)) {
182 useEventTap = NO;
183 }
184
185 self = [super init];
186 if (self != nil)
187 {
188 self->curConsumer = nil;
189 self->eventTap = nil;
190 self->runLoopSource = nil;
191 self->touches = nil;
192 self->lastTouchId = 0;
193
194 if (useEventTap) {
195 //
196 // Notes after fixing RT-23199:
197 //
198 // Don't use NSMachPort and NSRunLoop to integrate CFMachPortRef
199 // instance into run loop.
200 //
201 // Ignoring the above "don't"s results into performance degradation
202 // referenced in the bug.
203 //
204
205 self->eventTap = CGEventTapCreate(kCGHIDEventTap,
206 kCGHeadInsertEventTap,
207 kCGEventTapOptionListenOnly,
208 CGEventMaskBit(NSEventTypeGesture),
209 listenTouchEvents, nil);
210
211 LOG("TOUCHES: eventTap=%p\n", self->eventTap);
212
213 if (self->eventTap)
214 { // Create a run loop source.
215 self->runLoopSource = CFMachPortCreateRunLoopSource(
216 kCFAllocatorDefault,
217 self->eventTap, 0);
218
219 LOG("TOUCHES: runLoopSource=%p\n", self->runLoopSource);
220
221 // Add to the current run loop.
222 CFRunLoopAddSource(CFRunLoopGetCurrent(), self->runLoopSource,
223 kCFRunLoopCommonModes);
224 }
225 }
226 }
227 return self;
228 }
229
230 @end
231
232
233 @implementation GlassTouches (hidden)
234 - (void)terminateImpl
235 {
236 if (useEventTap) {
237 LOG("TOUCHES: terminateImpl eventTap=%p runLoopSource=%p\n", self->eventTap,
238 self->runLoopSource);
239
240 if (self->runLoopSource)
241 {
242 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), self->runLoopSource,
243 kCFRunLoopCommonModes);
244 CFRelease(self->runLoopSource);
245 self->runLoopSource = nil;
246 }
247
248 if (self->eventTap)
249 {
250 CFRelease(self->eventTap);
251 self->eventTap = nil;
252 }
253 }
254 [self releaseTouches];
255 }
256
257 - (void)enableTouchInputEventTap
258 {
259 if (useEventTap) {
260 CGEventTapEnable(self->eventTap, true);
261 }
262 }
263
264 - (void)sendJavaTouchEvent:(NSEvent *)theEvent
265 {
266 jint modifiers = GetJavaModifiers(theEvent);
267
268 const NSSet* touchPoints =
269 [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
270
271 //
272 // Known issues with OSX touch input:
273 // - multiple 'NSTouchPhaseBegan' for the same touch point;
274 // - missing 'NSTouchPhaseEnded' for released touch points
275 // (RT-20139, RT-20375);
276 //
277
278 //
279 // Find just released touch points that are not in the cache already.
280 // Don't send TouchEvent#TOUCH_RELEASED for these touch points.
281 //
|