Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/awt/CRobot.m
38829 views
1
/*
2
* Copyright (c) 2011, 2014, 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
23
* questions.
24
*/
25
26
27
#import "jni_util.h"
28
29
#import <JavaNativeFoundation/JavaNativeFoundation.h>
30
#import <ApplicationServices/ApplicationServices.h>
31
32
#import "LWCToolkit.h"
33
#import "sun_lwawt_macosx_CRobot.h"
34
#import "java_awt_event_InputEvent.h"
35
#import "sizecalc.h"
36
37
38
// Starting number for event numbers generated by Robot.
39
// Apple docs don't mention at all what are the requirements
40
// for these numbers. It seems that they must be higher
41
// than event numbers from real events, which start at some
42
// value close to zero. There is no API for obtaining current
43
// event number, so we have to start from some random number.
44
// 32000 as starting value works for me, let's hope that it will
45
// work for others as well.
46
#define ROBOT_EVENT_NUMBER_START 32000
47
48
#define k_JAVA_ROBOT_WHEEL_COUNT 1
49
50
#if !defined(kCGBitmapByteOrder32Host)
51
#define kCGBitmapByteOrder32Host 0
52
#endif
53
54
// In OS X, left and right mouse button share the same click count.
55
// That is, if one starts clicking the left button rapidly and then
56
// switches to the right button, then the click count will continue
57
// increasing, without dropping to 1 in between. The middle button,
58
// however, has its own click count.
59
// For robot, we aren't going to emulate all that complexity. All our
60
// synhtetic clicks share the same click count.
61
static int gsClickCount;
62
static NSTimeInterval gsLastClickTime;
63
64
// Apparently, for mouse up/down events we have to set an event number
65
// that is incremented on each button press. Otherwise, strange things
66
// happen with z-order.
67
static int gsEventNumber;
68
static int* gsButtonEventNumber;
69
70
static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
71
72
static void PostMouseEvent(const CGPoint point, CGMouseButton button,
73
CGEventType type, int clickCount, int eventNumber);
74
75
static int GetClickCount(BOOL isDown);
76
77
static void
78
CreateJavaException(JNIEnv* env, CGError err)
79
{
80
// Throw a java exception indicating what is wrong.
81
NSString* s = [NSString stringWithFormat:@"Robot: CGError: %d", err];
82
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/awt/AWTException"),
83
[s UTF8String]);
84
}
85
86
/*
87
* Class: sun_lwawt_macosx_CRobot
88
* Method: initRobot
89
* Signature: (V)V
90
*/
91
JNIEXPORT void JNICALL
92
Java_sun_lwawt_macosx_CRobot_initRobot
93
(JNIEnv *env, jobject peer)
94
{
95
// Set things up to let our app act like a synthetic keyboard and mouse.
96
// Always set all states, in case Apple ever changes default behaviors.
97
static int setupDone = 0;
98
if (!setupDone) {
99
int i;
100
jint* tmp;
101
jboolean copy = JNI_FALSE;
102
103
setupDone = 1;
104
// Don't block local events after posting ours
105
CGSetLocalEventsSuppressionInterval(0.0);
106
107
// Let our event's modifier key state blend with local hardware events
108
CGEnableEventStateCombining(TRUE);
109
110
// Don't let our events block local hardware events
111
CGSetLocalEventsFilterDuringSupressionState(
112
kCGEventFilterMaskPermitAllEvents,
113
kCGEventSupressionStateSupressionInterval);
114
CGSetLocalEventsFilterDuringSupressionState(
115
kCGEventFilterMaskPermitAllEvents,
116
kCGEventSupressionStateRemoteMouseDrag);
117
118
gsClickCount = 0;
119
gsLastClickTime = 0;
120
gsEventNumber = ROBOT_EVENT_NUMBER_START;
121
122
gsButtonEventNumber = (int*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(int), gNumberOfButtons);
123
if (gsButtonEventNumber == NULL) {
124
JNU_ThrowOutOfMemoryError(env, NULL);
125
return;
126
}
127
128
for (i = 0; i < gNumberOfButtons; ++i) {
129
gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
130
}
131
}
132
}
133
134
/*
135
* Class: sun_lwawt_macosx_CRobot
136
* Method: mouseEvent
137
* Signature: (IIIIZZ)V
138
*/
139
JNIEXPORT void JNICALL
140
Java_sun_lwawt_macosx_CRobot_mouseEvent
141
(JNIEnv *env, jobject peer,
142
jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState,
143
jboolean isButtonsDownState, jboolean isMouseMove)
144
{
145
JNF_COCOA_ENTER(env);
146
147
// This is the native method called when Robot mouse events occur.
148
// The CRobot tracks the mouse position, and which button was
149
// pressed. The peer also tracks the mouse button desired state,
150
// the appropriate key modifier state, and whether the mouse action
151
// is simply a mouse move with no mouse button state changes.
152
153
// volatile, otherwise it warns that it might be clobbered by 'longjmp'
154
volatile CGPoint point;
155
156
point.x = mouseLastX;
157
point.y = mouseLastY;
158
159
__block CGMouseButton button = kCGMouseButtonLeft;
160
__block CGEventType type = kCGEventMouseMoved;
161
162
void (^HandleRobotButton)(CGMouseButton, CGEventType, CGEventType, CGEventType) =
163
^(CGMouseButton cgButton, CGEventType cgButtonUp, CGEventType cgButtonDown,
164
CGEventType cgButtonDragged) {
165
166
button = cgButton;
167
type = cgButtonUp;
168
169
if (isButtonsDownState) {
170
if (isMouseMove) {
171
type = cgButtonDragged;
172
} else {
173
type = cgButtonDown;
174
}
175
}
176
};
177
178
// Left
179
if (buttonsState & java_awt_event_InputEvent_BUTTON1_MASK ||
180
buttonsState & java_awt_event_InputEvent_BUTTON1_DOWN_MASK ) {
181
182
HandleRobotButton(kCGMouseButtonLeft, kCGEventLeftMouseUp,
183
kCGEventLeftMouseDown, kCGEventLeftMouseDragged);
184
}
185
186
// Other
187
if (buttonsState & java_awt_event_InputEvent_BUTTON2_MASK ||
188
buttonsState & java_awt_event_InputEvent_BUTTON2_DOWN_MASK ) {
189
190
HandleRobotButton(kCGMouseButtonCenter, kCGEventOtherMouseUp,
191
kCGEventOtherMouseDown, kCGEventOtherMouseDragged);
192
}
193
194
// Right
195
if (buttonsState & java_awt_event_InputEvent_BUTTON3_MASK ||
196
buttonsState & java_awt_event_InputEvent_BUTTON3_DOWN_MASK ) {
197
198
HandleRobotButton(kCGMouseButtonRight, kCGEventRightMouseUp,
199
kCGEventRightMouseDown, kCGEventRightMouseDragged);
200
}
201
202
// Extra
203
if (gNumberOfButtons > 3) {
204
int extraButton;
205
for (extraButton = 3; extraButton < gNumberOfButtons; ++extraButton) {
206
if ((buttonsState & gButtonDownMasks[extraButton])) {
207
HandleRobotButton(extraButton, kCGEventOtherMouseUp,
208
kCGEventOtherMouseDown, kCGEventOtherMouseDragged);
209
}
210
}
211
}
212
213
int clickCount = 0;
214
int eventNumber = gsEventNumber;
215
216
if (isMouseMove) {
217
// any mouse movement resets click count
218
gsLastClickTime = 0;
219
} else {
220
clickCount = GetClickCount(isButtonsDownState);
221
222
if (isButtonsDownState) {
223
gsButtonEventNumber[button] = gsEventNumber++;
224
}
225
eventNumber = gsButtonEventNumber[button];
226
}
227
228
PostMouseEvent(point, button, type, clickCount, eventNumber);
229
230
JNF_COCOA_EXIT(env);
231
}
232
233
/*
234
* Class: sun_lwawt_macosx_CRobot
235
* Method: mouseWheel
236
* Signature: (I)V
237
*/
238
JNIEXPORT void JNICALL
239
Java_sun_lwawt_macosx_CRobot_mouseWheel
240
(JNIEnv *env, jobject peer, jint wheelAmt)
241
{
242
CGEventRef event = CGEventCreateScrollWheelEvent(NULL,
243
kCGScrollEventUnitLine,
244
k_JAVA_ROBOT_WHEEL_COUNT, wheelAmt);
245
246
if (event != NULL) {
247
CGEventPost(kCGSessionEventTap, event);
248
CFRelease(event);
249
}
250
}
251
252
/*
253
* Class: sun_lwawt_macosx_CRobot
254
* Method: keyEvent
255
* Signature: (IZ)V
256
*/
257
JNIEXPORT void JNICALL
258
Java_sun_lwawt_macosx_CRobot_keyEvent
259
(JNIEnv *env, jobject peer, jint javaKeyCode, jboolean keyPressed)
260
{
261
/*
262
* Well, using CGEventCreateKeyboardEvent/CGEventPost would have been
263
* a better solution, however, it gives me all kinds of trouble and I have
264
* no idea how to solve them without inserting delays between simulated
265
* events. So, I've ended up disabling it and opted for another approach
266
* that uses Accessibility API instead.
267
*/
268
CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
269
AXUIElementRef elem = AXUIElementCreateSystemWide();
270
AXUIElementPostKeyboardEvent(elem, (CGCharCode)0, keyCode, keyPressed);
271
CFRelease(elem);
272
273
274
#if 0
275
CGEventRef event = CGEventCreateKeyboardEvent(NULL, keyCode, keyPressed);
276
if (event != NULL) {
277
CGEventPost(kCGSessionEventTap, event);
278
CFRelease(event);
279
}
280
#endif
281
}
282
283
/*
284
* Class: sun_lwawt_macosx_CRobot
285
* Method: nativeGetScreenPixels
286
* Signature: (IIIII[I)V
287
*/
288
JNIEXPORT void JNICALL
289
Java_sun_lwawt_macosx_CRobot_nativeGetScreenPixels
290
(JNIEnv *env, jobject peer,
291
jint x, jint y, jint width, jint height, jintArray pixels)
292
{
293
JNF_COCOA_ENTER(env);
294
295
jint picX = x;
296
jint picY = y;
297
jint picWidth = width;
298
jint picHeight = height;
299
300
CGRect screenRect = CGRectMake(picX, picY, picWidth, picHeight);
301
CGImageRef screenPixelsImage = CGWindowListCreateImage(screenRect,
302
kCGWindowListOptionOnScreenOnly,
303
kCGNullWindowID, kCGWindowImageDefault);
304
305
if (screenPixelsImage == NULL) {
306
return;
307
}
308
309
// get a pointer to the Java int array
310
void *jPixelData = (*env)->GetPrimitiveArrayCritical(env, pixels, 0);
311
CHECK_NULL(jPixelData);
312
313
// create a graphics context around the Java int array
314
CGColorSpaceRef picColorSpace = CGColorSpaceCreateWithName(
315
kCGColorSpaceGenericRGB);
316
CGContextRef jPicContextRef = CGBitmapContextCreate(
317
jPixelData,
318
picWidth, picHeight,
319
8, picWidth * sizeof(jint),
320
picColorSpace,
321
kCGBitmapByteOrder32Host |
322
kCGImageAlphaPremultipliedFirst);
323
324
CGColorSpaceRelease(picColorSpace);
325
326
// flip, scale, and color correct the screen image into the Java pixels
327
CGRect bounds = { { 0, 0 }, { picWidth, picHeight } };
328
CGContextDrawImage(jPicContextRef, bounds, screenPixelsImage);
329
CGContextFlush(jPicContextRef);
330
331
// cleanup
332
CGContextRelease(jPicContextRef);
333
CGImageRelease(screenPixelsImage);
334
335
// release the Java int array back up to the JVM
336
(*env)->ReleasePrimitiveArrayCritical(env, pixels, jPixelData, 0);
337
338
JNF_COCOA_EXIT(env);
339
}
340
341
/****************************************************
342
* Helper methods
343
****************************************************/
344
345
static void PostMouseEvent(const CGPoint point, CGMouseButton button,
346
CGEventType type, int clickCount, int eventNumber)
347
{
348
CGEventRef mouseEvent = CGEventCreateMouseEvent(NULL, type, point, button);
349
if (mouseEvent != NULL) {
350
CGEventSetIntegerValueField(mouseEvent, kCGMouseEventClickState, clickCount);
351
CGEventSetIntegerValueField(mouseEvent, kCGMouseEventNumber, eventNumber);
352
CGEventPost(kCGSessionEventTap, mouseEvent);
353
CFRelease(mouseEvent);
354
}
355
}
356
357
// NOTE: Don't modify this table directly. It is machine generated. See below.
358
static const unsigned char javaToMacKeyCode[] = {
359
127, // 0 0 VK_UNDEFINED No_Equivalent
360
127, // 1 0x1 Not_Used
361
127, // 2 0x2 Not_Used
362
127, // 3 0x3 VK_CANCEL No_Equivalent
363
127, // 4 0x4 Not_Used
364
127, // 5 0x5 Not_Used
365
127, // 6 0x6 Not_Used
366
127, // 7 0x7 Not_Used
367
51, // 8 0x8 VK_BACK_SPACE
368
48, // 9 0x9 VK_TAB
369
36, // 10 0xa VK_ENTER
370
127, // 11 0xb Not_Used
371
71, // 12 0xc VK_CLEAR
372
127, // 13 0xd Not_Used
373
127, // 14 0xe Not_Used
374
127, // 15 0xf Not_Used
375
56, // 16 0x10 VK_SHIFT
376
59, // 17 0x11 VK_CONTROL
377
58, // 18 0x12 VK_ALT
378
113, // 19 0x13 VK_PAUSE
379
57, // 20 0x14 VK_CAPS_LOCK
380
127, // 21 0x15 VK_KANA No_Equivalent
381
127, // 22 0x16 Not_Used
382
127, // 23 0x17 Not_Used
383
127, // 24 0x18 VK_FINAL No_Equivalent
384
127, // 25 0x19 VK_KANJI No_Equivalent
385
127, // 26 0x1a Not_Used
386
53, // 27 0x1b VK_ESCAPE
387
127, // 28 0x1c VK_CONVERT No_Equivalent
388
127, // 29 0x1d VK_NONCONVERT No_Equivalent
389
127, // 30 0x1e VK_ACCEPT No_Equivalent
390
127, // 31 0x1f VK_MODECHANGE No_Equivalent
391
49, // 32 0x20 VK_SPACE
392
116, // 33 0x21 VK_PAGE_UP
393
121, // 34 0x22 VK_PAGE_DOWN
394
119, // 35 0x23 VK_END
395
115, // 36 0x24 VK_HOME
396
123, // 37 0x25 VK_LEFT
397
126, // 38 0x26 VK_UP
398
124, // 39 0x27 VK_RIGHT
399
125, // 40 0x28 VK_DOWN
400
127, // 41 0x29 Not_Used
401
127, // 42 0x2a Not_Used
402
127, // 43 0x2b Not_Used
403
43, // 44 0x2c VK_COMMA
404
27, // 45 0x2d VK_MINUS
405
47, // 46 0x2e VK_PERIOD
406
44, // 47 0x2f VK_SLASH
407
29, // 48 0x30 VK_0
408
18, // 49 0x31 VK_1
409
19, // 50 0x32 VK_2
410
20, // 51 0x33 VK_3
411
21, // 52 0x34 VK_4
412
23, // 53 0x35 VK_5
413
22, // 54 0x36 VK_6
414
26, // 55 0x37 VK_7
415
28, // 56 0x38 VK_8
416
25, // 57 0x39 VK_9
417
127, // 58 0x3a Not_Used
418
41, // 59 0x3b VK_SEMICOLON
419
127, // 60 0x3c Not_Used
420
24, // 61 0x3d VK_EQUALS
421
127, // 62 0x3e Not_Used
422
127, // 63 0x3f Not_Used
423
127, // 64 0x40 Not_Used
424
0, // 65 0x41 VK_A
425
11, // 66 0x42 VK_B
426
8, // 67 0x43 VK_C
427
2, // 68 0x44 VK_D
428
14, // 69 0x45 VK_E
429
3, // 70 0x46 VK_F
430
5, // 71 0x47 VK_G
431
4, // 72 0x48 VK_H
432
34, // 73 0x49 VK_I
433
38, // 74 0x4a VK_J
434
40, // 75 0x4b VK_K
435
37, // 76 0x4c VK_L
436
46, // 77 0x4d VK_M
437
45, // 78 0x4e VK_N
438
31, // 79 0x4f VK_O
439
35, // 80 0x50 VK_P
440
12, // 81 0x51 VK_Q
441
15, // 82 0x52 VK_R
442
1, // 83 0x53 VK_S
443
17, // 84 0x54 VK_T
444
32, // 85 0x55 VK_U
445
9, // 86 0x56 VK_V
446
13, // 87 0x57 VK_W
447
7, // 88 0x58 VK_X
448
16, // 89 0x59 VK_Y
449
6, // 90 0x5a VK_Z
450
33, // 91 0x5b VK_OPEN_BRACKET
451
42, // 92 0x5c VK_BACK_SLASH
452
30, // 93 0x5d VK_CLOSE_BRACKET
453
127, // 94 0x5e Not_Used
454
127, // 95 0x5f Not_Used
455
82, // 96 0x60 VK_NUMPAD0
456
83, // 97 0x61 VK_NUMPAD1
457
84, // 98 0x62 VK_NUMPAD2
458
85, // 99 0x63 VK_NUMPAD3
459
86, // 100 0x64 VK_NUMPAD4
460
87, // 101 0x65 VK_NUMPAD5
461
88, // 102 0x66 VK_NUMPAD6
462
89, // 103 0x67 VK_NUMPAD7
463
91, // 104 0x68 VK_NUMPAD8
464
92, // 105 0x69 VK_NUMPAD9
465
67, // 106 0x6a VK_MULTIPLY
466
69, // 107 0x6b VK_ADD
467
127, // 108 0x6c VK_SEPARATER No_Equivalent
468
78, // 109 0x6d VK_SUBTRACT
469
65, // 110 0x6e VK_DECIMAL
470
75, // 111 0x6f VK_DIVIDE
471
122, // 112 0x70 VK_F1
472
120, // 113 0x71 VK_F2
473
99, // 114 0x72 VK_F3
474
118, // 115 0x73 VK_F4
475
96, // 116 0x74 VK_F5
476
97, // 117 0x75 VK_F6
477
98, // 118 0x76 VK_F7
478
100, // 119 0x77 VK_F8
479
101, // 120 0x78 VK_F9
480
109, // 121 0x79 VK_F10
481
103, // 122 0x7a VK_F11
482
111, // 123 0x7b VK_F12
483
127, // 124 0x7c Not_Used
484
127, // 125 0x7d Not_Used
485
127, // 126 0x7e Not_Used
486
117, // 127 0x7f VK_DELETE
487
127, // 128 0x80 VK_DEAD_GRAVE No_Equivalent
488
127, // 129 0x81 VK_DEAD_ACUTE No_Equivalent
489
127, // 130 0x82 VK_DEAD_CIRCUMFLEX No_Equivalent
490
127, // 131 0x83 VK_DEAD_TILDE No_Equivalent
491
127, // 132 0x84 VK_DEAD_MACRON No_Equivalent
492
127, // 133 0x85 VK_DEAD_BREVE No_Equivalent
493
127, // 134 0x86 VK_DEAD_ABOVEDOT No_Equivalent
494
127, // 135 0x87 VK_DEAD_DIAERESIS No_Equivalent
495
127, // 136 0x88 VK_DEAD_ABOVERING No_Equivalent
496
127, // 137 0x89 VK_DEAD_DOUBLEACUTE No_Equivalent
497
127, // 138 0x8a VK_DEAD_CARON No_Equivalent
498
127, // 139 0x8b VK_DEAD_CEDILLA No_Equivalent
499
127, // 140 0x8c VK_DEAD_OGONEK No_Equivalent
500
127, // 141 0x8d VK_DEAD_IOTA No_Equivalent
501
127, // 142 0x8e VK_DEAD_VOICED_SOUND No_Equivalent
502
127, // 143 0x8f VK_DEAD_SEMIVOICED_SOUND No_Equivalent
503
127, // 144 0x90 VK_NUM_LOCK No_Equivalent
504
107, // 145 0x91 VK_SCROLL_LOCK
505
127, // 146 0x92 Not_Used
506
127, // 147 0x93 Not_Used
507
127, // 148 0x94 Not_Used
508
127, // 149 0x95 Not_Used
509
127, // 150 0x96 VK_AMPERSAND No_Equivalent
510
127, // 151 0x97 VK_ASTERISK No_Equivalent
511
127, // 152 0x98 VK_QUOTEDBL No_Equivalent
512
127, // 153 0x99 VK_LESS No_Equivalent
513
105, // 154 0x9a VK_PRINTSCREEN
514
127, // 155 0x9b VK_INSERT No_Equivalent
515
114, // 156 0x9c VK_HELP
516
55, // 157 0x9d VK_META
517
127, // 158 0x9e Not_Used
518
127, // 159 0x9f Not_Used
519
127, // 160 0xa0 VK_GREATER No_Equivalent
520
127, // 161 0xa1 VK_BRACELEFT No_Equivalent
521
127, // 162 0xa2 VK_BRACERIGHT No_Equivalent
522
127, // 163 0xa3 Not_Used
523
127, // 164 0xa4 Not_Used
524
127, // 165 0xa5 Not_Used
525
127, // 166 0xa6 Not_Used
526
127, // 167 0xa7 Not_Used
527
127, // 168 0xa8 Not_Used
528
127, // 169 0xa9 Not_Used
529
127, // 170 0xaa Not_Used
530
127, // 171 0xab Not_Used
531
127, // 172 0xac Not_Used
532
127, // 173 0xad Not_Used
533
127, // 174 0xae Not_Used
534
127, // 175 0xaf Not_Used
535
127, // 176 0xb0 Not_Used
536
127, // 177 0xb1 Not_Used
537
127, // 178 0xb2 Not_Used
538
127, // 179 0xb3 Not_Used
539
127, // 180 0xb4 Not_Used
540
127, // 181 0xb5 Not_Used
541
127, // 182 0xb6 Not_Used
542
127, // 183 0xb7 Not_Used
543
127, // 184 0xb8 Not_Used
544
127, // 185 0xb9 Not_Used
545
127, // 186 0xba Not_Used
546
127, // 187 0xbb Not_Used
547
127, // 188 0xbc Not_Used
548
127, // 189 0xbd Not_Used
549
127, // 190 0xbe Not_Used
550
127, // 191 0xbf Not_Used
551
50, // 192 0xc0 VK_BACK_QUOTE
552
127, // 193 0xc1 Not_Used
553
127, // 194 0xc2 Not_Used
554
127, // 195 0xc3 Not_Used
555
127, // 196 0xc4 Not_Used
556
127, // 197 0xc5 Not_Used
557
127, // 198 0xc6 Not_Used
558
127, // 199 0xc7 Not_Used
559
127, // 200 0xc8 Not_Used
560
127, // 201 0xc9 Not_Used
561
127, // 202 0xca Not_Used
562
127, // 203 0xcb Not_Used
563
127, // 204 0xcc Not_Used
564
127, // 205 0xcd Not_Used
565
127, // 206 0xce Not_Used
566
127, // 207 0xcf Not_Used
567
127, // 208 0xd0 Not_Used
568
127, // 209 0xd1 Not_Used
569
127, // 210 0xd2 Not_Used
570
127, // 211 0xd3 Not_Used
571
127, // 212 0xd4 Not_Used
572
127, // 213 0xd5 Not_Used
573
127, // 214 0xd6 Not_Used
574
127, // 215 0xd7 Not_Used
575
127, // 216 0xd8 Not_Used
576
127, // 217 0xd9 Not_Used
577
127, // 218 0xda Not_Used
578
127, // 219 0xdb Not_Used
579
127, // 220 0xdc Not_Used
580
127, // 221 0xdd Not_Used
581
39 // 222 0xde VK_QUOTE
582
};
583
584
// NOTE: All values above 222 don't have an equivalent on MacOSX.
585
static inline CGKeyCode GetCGKeyCode(jint javaKeyCode)
586
{
587
if (javaKeyCode > 222) {
588
return 127;
589
} else {
590
return javaToMacKeyCode[javaKeyCode];
591
}
592
}
593
594
static int GetClickCount(BOOL isDown) {
595
NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
596
NSTimeInterval clickInterval = now - gsLastClickTime;
597
BOOL isWithinTreshold = clickInterval < [NSEvent doubleClickInterval];
598
599
if (isDown) {
600
if (isWithinTreshold) {
601
gsClickCount++;
602
} else {
603
gsClickCount = 1;
604
}
605
606
gsLastClickTime = now;
607
} else {
608
// In OS X, a mouse up has the click count of the last mouse down
609
// if an interval between up and down is within the double click
610
// threshold, and 0 otherwise.
611
if (!isWithinTreshold) {
612
gsClickCount = 0;
613
}
614
}
615
616
return gsClickCount;
617
}
618
619