50
51 #if !defined(kCGBitmapByteOrder32Host)
52 #define kCGBitmapByteOrder32Host 0
53 #endif
54
55 // In OS X, left and right mouse button share the same click count.
56 // That is, if one starts clicking the left button rapidly and then
57 // switches to the right button, then the click count will continue
58 // increasing, without dropping to 1 in between. The middle button,
59 // however, has its own click count.
60 // For robot, we aren't going to emulate all that complexity. All our
61 // synhtetic clicks share the same click count.
62 static int gsClickCount;
63 static NSTimeInterval gsLastClickTime;
64
65 // Apparently, for mouse up/down events we have to set an event number
66 // that is incremented on each button press. Otherwise, strange things
67 // happen with z-order.
68 static int gsEventNumber;
69 static int* gsButtonEventNumber;
70
71 static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
72
73 static void PostMouseEvent(const CGPoint point, CGMouseButton button,
74 CGEventType type, int clickCount, int eventNumber);
75
76 static int GetClickCount(BOOL isDown);
77
78 static void
79 CreateJavaException(JNIEnv* env, CGError err)
80 {
81 // Throw a java exception indicating what is wrong.
82 NSString* s = [NSString stringWithFormat:@"Robot: CGError: %d", err];
83 (*env)->ThrowNew(env, (*env)->FindClass(env, "java/awt/AWTException"),
84 [s UTF8String]);
85 }
86
87 /*
88 * Class: sun_lwawt_macosx_CRobot
89 * Method: initRobot
113 kCGEventFilterMaskPermitAllEvents,
114 kCGEventSupressionStateSupressionInterval);
115 CGSetLocalEventsFilterDuringSupressionState(
116 kCGEventFilterMaskPermitAllEvents,
117 kCGEventSupressionStateRemoteMouseDrag);
118
119 gsClickCount = 0;
120 gsLastClickTime = 0;
121 gsEventNumber = ROBOT_EVENT_NUMBER_START;
122
123 gsButtonEventNumber = (int*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(int), gNumberOfButtons);
124 if (gsButtonEventNumber == NULL) {
125 JNU_ThrowOutOfMemoryError(env, NULL);
126 return;
127 }
128
129 for (i = 0; i < gNumberOfButtons; ++i) {
130 gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
131 }
132 }
133 }
134
135 /*
136 * Class: sun_lwawt_macosx_CRobot
137 * Method: mouseEvent
138 * Signature: (IIIIZZ)V
139 */
140 JNIEXPORT void JNICALL
141 Java_sun_lwawt_macosx_CRobot_mouseEvent
142 (JNIEnv *env, jobject peer,
143 jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState,
144 jboolean isButtonsDownState, jboolean isMouseMove)
145 {
146 JNF_COCOA_ENTER(env);
147
148 // This is the native method called when Robot mouse events occur.
149 // The CRobot tracks the mouse position, and which button was
150 // pressed. The peer also tracks the mouse button desired state,
151 // the appropriate key modifier state, and whether the mouse action
152 // is simply a mouse move with no mouse button state changes.
327 }
328
329 /****************************************************
330 * Helper methods
331 ****************************************************/
332
333 static void PostMouseEvent(const CGPoint point, CGMouseButton button,
334 CGEventType type, int clickCount, int eventNumber)
335 {
336 CGEventRef mouseEvent = CGEventCreateMouseEvent(NULL, type, point, button);
337 if (mouseEvent != NULL) {
338 CGEventSetIntegerValueField(mouseEvent, kCGMouseEventClickState, clickCount);
339 CGEventSetIntegerValueField(mouseEvent, kCGMouseEventNumber, eventNumber);
340 CGEventPost(kCGSessionEventTap, mouseEvent);
341 CFRelease(mouseEvent);
342 }
343 }
344
345 static inline CGKeyCode GetCGKeyCode(jint javaKeyCode)
346 {
347 CRobotKeyCodeMapping *keyCodeMapping = [CRobotKeyCodeMapping sharedInstance];
348 return [keyCodeMapping getOSXKeyCodeForJavaKey:javaKeyCode];
349 }
350
351 static int GetClickCount(BOOL isDown) {
352 NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
353 NSTimeInterval clickInterval = now - gsLastClickTime;
354 BOOL isWithinTreshold = clickInterval < [NSEvent doubleClickInterval];
355
356 if (isDown) {
357 if (isWithinTreshold) {
358 gsClickCount++;
359 } else {
360 gsClickCount = 1;
361 }
362
363 gsLastClickTime = now;
364 } else {
365 // In OS X, a mouse up has the click count of the last mouse down
366 // if an interval between up and down is within the double click
367 // threshold, and 0 otherwise.
368 if (!isWithinTreshold) {
|
50
51 #if !defined(kCGBitmapByteOrder32Host)
52 #define kCGBitmapByteOrder32Host 0
53 #endif
54
55 // In OS X, left and right mouse button share the same click count.
56 // That is, if one starts clicking the left button rapidly and then
57 // switches to the right button, then the click count will continue
58 // increasing, without dropping to 1 in between. The middle button,
59 // however, has its own click count.
60 // For robot, we aren't going to emulate all that complexity. All our
61 // synhtetic clicks share the same click count.
62 static int gsClickCount;
63 static NSTimeInterval gsLastClickTime;
64
65 // Apparently, for mouse up/down events we have to set an event number
66 // that is incremented on each button press. Otherwise, strange things
67 // happen with z-order.
68 static int gsEventNumber;
69 static int* gsButtonEventNumber;
70 static CRobotKeyCodeMapping *keyCodeMapping;
71
72 static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
73
74 static void PostMouseEvent(const CGPoint point, CGMouseButton button,
75 CGEventType type, int clickCount, int eventNumber);
76
77 static int GetClickCount(BOOL isDown);
78
79 static void
80 CreateJavaException(JNIEnv* env, CGError err)
81 {
82 // Throw a java exception indicating what is wrong.
83 NSString* s = [NSString stringWithFormat:@"Robot: CGError: %d", err];
84 (*env)->ThrowNew(env, (*env)->FindClass(env, "java/awt/AWTException"),
85 [s UTF8String]);
86 }
87
88 /*
89 * Class: sun_lwawt_macosx_CRobot
90 * Method: initRobot
114 kCGEventFilterMaskPermitAllEvents,
115 kCGEventSupressionStateSupressionInterval);
116 CGSetLocalEventsFilterDuringSupressionState(
117 kCGEventFilterMaskPermitAllEvents,
118 kCGEventSupressionStateRemoteMouseDrag);
119
120 gsClickCount = 0;
121 gsLastClickTime = 0;
122 gsEventNumber = ROBOT_EVENT_NUMBER_START;
123
124 gsButtonEventNumber = (int*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(int), gNumberOfButtons);
125 if (gsButtonEventNumber == NULL) {
126 JNU_ThrowOutOfMemoryError(env, NULL);
127 return;
128 }
129
130 for (i = 0; i < gNumberOfButtons; ++i) {
131 gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
132 }
133 }
134 keyCodeMapping = [CRobotKeyCodeMapping sharedInstance];
135 }
136
137 /*
138 * Class: sun_lwawt_macosx_CRobot
139 * Method: mouseEvent
140 * Signature: (IIIIZZ)V
141 */
142 JNIEXPORT void JNICALL
143 Java_sun_lwawt_macosx_CRobot_mouseEvent
144 (JNIEnv *env, jobject peer,
145 jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState,
146 jboolean isButtonsDownState, jboolean isMouseMove)
147 {
148 JNF_COCOA_ENTER(env);
149
150 // This is the native method called when Robot mouse events occur.
151 // The CRobot tracks the mouse position, and which button was
152 // pressed. The peer also tracks the mouse button desired state,
153 // the appropriate key modifier state, and whether the mouse action
154 // is simply a mouse move with no mouse button state changes.
329 }
330
331 /****************************************************
332 * Helper methods
333 ****************************************************/
334
335 static void PostMouseEvent(const CGPoint point, CGMouseButton button,
336 CGEventType type, int clickCount, int eventNumber)
337 {
338 CGEventRef mouseEvent = CGEventCreateMouseEvent(NULL, type, point, button);
339 if (mouseEvent != NULL) {
340 CGEventSetIntegerValueField(mouseEvent, kCGMouseEventClickState, clickCount);
341 CGEventSetIntegerValueField(mouseEvent, kCGMouseEventNumber, eventNumber);
342 CGEventPost(kCGSessionEventTap, mouseEvent);
343 CFRelease(mouseEvent);
344 }
345 }
346
347 static inline CGKeyCode GetCGKeyCode(jint javaKeyCode)
348 {
349 if (keyCodeMapping) {
350 return [keyCodeMapping getOSXKeyCodeForJavaKey:javaKeyCode];
351 }
352 return OSX_Undefined;
353 }
354
355 static int GetClickCount(BOOL isDown) {
356 NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
357 NSTimeInterval clickInterval = now - gsLastClickTime;
358 BOOL isWithinTreshold = clickInterval < [NSEvent doubleClickInterval];
359
360 if (isDown) {
361 if (isWithinTreshold) {
362 gsClickCount++;
363 } else {
364 gsClickCount = 1;
365 }
366
367 gsLastClickTime = now;
368 } else {
369 // In OS X, a mouse up has the click count of the last mouse down
370 // if an interval between up and down is within the double click
371 // threshold, and 0 otherwise.
372 if (!isWithinTreshold) {
|