< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m

Print this page




  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) {
< prev index next >