Sounds like you want to hook global mouse events on OSX.
I've done it in Windows, with great success. I know what to look for.
Here is the best stuff I could find on it after a quick search:
https://code.google.com/p/jnativehook/
https://code.google.com/p/jnativehook/source/browse/branches/1.1/src/native/osx/NativeThread.c
Basically the JNativeHook does the following:
It creates a c thread with the correct callback to the system functions that handle the mouse. As the mouse (and keyboard) are handled by the system, the callback, gets the information. The information then gets forwarded on into the java side of the code through a call back.
You need to create a thread, hook it to the system properly, and then get the information out to where you want to log or display it. Over 90% of that work is accomplished in the NativeThread.c link above. Here are some key parts to it.
Lines 305 to 552 have the following:
switch (type) {
//...
case kCGEventLeftMouseDown:
button = kVK_LBUTTON;
SetModifierMask(kCGEventFlagMaskButtonLeft);
goto BUTTONDOWN;
case kCGEventRightMouseDown:
button = kVK_RBUTTON;
SetModifierMask(kCGEventFlagMaskButtonRight);
goto BUTTONDOWN;
case kCGEventOtherMouseDown:
button = CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber);
if (button == kVK_MBUTTON) {
SetModifierMask(kCGEventFlagMaskButtonCenter);
}
else if (button == kVK_XBUTTON1) {
SetModifierMask(kCGEventFlagMaskXButton1);
}
else if (button == kVK_XBUTTON2) {
SetModifierMask(kCGEventFlagMaskXButton2);
}
BUTTONDOWN:
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Button Pressed (%i)\n", (unsigned int) button);
#endif
// Track the number of clicks.
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Click Time (%lli)\n", (CGEventGetTimestamp(event) - click_time) / 1000000);
#endif
if ((long) (CGEventGetTimestamp(event) - click_time) / 1000000 <= GetMultiClickTime()) {
click_count++;
}
else {
click_count = 1;
}
click_time = CGEventGetTimestamp(event);
event_point = CGEventGetLocation(event);
jbutton = NativeToJButton(button);
jmodifiers = NativeToJEventMask(GetModifiers());
// Fire mouse pressed event.
objMouseEvent = (*env)->NewObject(
env,
clsMouseEvent,
idMouseButtonEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_PRESSED,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count,
jbutton);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseEvent);
(*env)->DeleteLocalRef(env, objMouseEvent);
break;
case kCGEventLeftMouseUp:
button = kVK_LBUTTON;
UnsetModifierMask(kCGEventFlagMaskButtonLeft);
goto BUTTONUP;
case kCGEventRightMouseUp:
button = kVK_RBUTTON;
UnsetModifierMask(kCGEventFlagMaskButtonRight);
goto BUTTONUP;
case kCGEventOtherMouseUp:
button = CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber);
if (button == kVK_MBUTTON) {
UnsetModifierMask(kCGEventFlagMaskButtonCenter);
}
else if (button == kVK_XBUTTON1) {
UnsetModifierMask(kCGEventFlagMaskXButton1);
}
else if (button == kVK_XBUTTON2) {
UnsetModifierMask(kCGEventFlagMaskXButton2);
}
BUTTONUP:
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Button Released (%i)\n", (unsigned int) button);
#endif
event_point = CGEventGetLocation(event);
jbutton = NativeToJButton(button);
jmodifiers = NativeToJEventMask(GetModifiers());
// Fire mouse released event.
objMouseEvent = (*env)->NewObject(
env,
clsMouseEvent,
idMouseButtonEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_RELEASED,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count,
jbutton);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseEvent);
(*env)->DeleteLocalRef(env, objMouseEvent);
if (mouse_dragged != true) {
// Fire mouse clicked event.
objMouseEvent = (*env)->NewObject(
env,
clsMouseEvent,
idMouseButtonEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_CLICKED,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count,
jbutton);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseEvent);
(*env)->DeleteLocalRef(env, objMouseEvent);
}
break;
case kCGEventLeftMouseDragged:
case kCGEventRightMouseDragged:
case kCGEventOtherMouseDragged:
event_point = CGEventGetLocation(event);
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Motion Notified (%f, %f)\n", event_point.x, event_point.y);
#endif
// Reset the click count.
if (click_count != 0 && (long) (CGEventGetTimestamp(event) - click_time) / 1000000 > GetMultiClickTime()) {
click_count = 0;
}
jmodifiers = NativeToJEventMask(GetModifiers());
// Set the mouse dragged flag.
mouse_dragged = true;
// Fire mouse dragged event.
objMouseEvent = (*env)->NewObject(
env,
clsMouseEvent,
idMouseMotionEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_DRAGGED,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseEvent);
(*env)->DeleteLocalRef(env, objMouseEvent);
break;
case kCGEventMouseMoved:
event_point = CGEventGetLocation(event);
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Motion Notified (%f, %f)\n", event_point.x, event_point.y);
#endif
// Reset the click count.
if (click_count != 0 && (long) (CGEventGetTimestamp(event) - click_time) / 1000000 > GetMultiClickTime()) {
click_count = 0;
}
jmodifiers = NativeToJEventMask(GetModifiers());
// Set the mouse dragged flag.
mouse_dragged = false;
// Fire mouse moved event.
objMouseEvent = (*env)->NewObject(
env,
clsMouseEvent,
idMouseMotionEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_MOVED,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseEvent);
(*env)->DeleteLocalRef(env, objMouseEvent);
break;
case kCGEventScrollWheel:
event_point = CGEventGetLocation(event);
// TODO Figure out of kCGScrollWheelEventDeltaAxis2 causes mouse events with zero rotation.
if (CGEventGetIntegerValueField(event, kCGScrollWheelEventIsContinuous) == 0) {
jscrollType = (jint) org_jnativehook_mouse_NativeMouseWheelEvent_WHEEL_UNIT_SCROLL;
}
else {
jscrollType = (jint) org_jnativehook_mouse_NativeMouseWheelEvent_WHEEL_BLOCK_SCROLL;
}
// Scrolling data uses a fixed-point 16.16 signed integer format (Ex: 1.0 = 0x00010000).
jwheelRotation = (jint) CGEventGetIntegerValueField(event, kCGScrollWheelEventDeltaAxis1) * -1;
/* TODO Figure out the scroll wheel amounts are correct. I
* suspect that Apples Java implementation maybe reporting a
* static "1" inaccurately.
*/
jscrollAmount = (jint) CGEventGetIntegerValueField(event, kCGScrollWheelEventPointDeltaAxis1) * -1;
#ifdef DEBUG
fprintf(stdout, "LowLevelProc(): Mouse Wheel Moved (%i, %i, %i)\n", (int) jscrollType, (int) jscrollAmount, (int) jwheelRotation);
#endif
// Track the number of clicks.
if ((long) (CGEventGetTimestamp(event) - click_time) / 1000000 <= GetMultiClickTime()) {
click_count++;
}
else {
click_count = 1;
}
click_time = CGEventGetTimestamp(event);
jmodifiers = NativeToJEventMask(GetModifiers());
// Fire mouse wheel event.
objMouseWheelEvent = (*env)->NewObject(
env,
clsMouseWheelEvent,
idMouseWheelEvent,
org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_WHEEL,
(jlong) event_time,
jmodifiers,
(jint) event_point.x,
(jint) event_point.y,
(jint) click_count,
jscrollType,
jscrollAmount,
jwheelRotation);
(*env)->CallVoidMethod(env, objGlobalScreen, idDispatchEvent, objMouseWheelEvent);
(*env)->DeleteLocalRef(env, objMouseWheelEvent);
break;
#ifdef DEBUG
default:
fprintf(stderr, "LowLevelProc(): Unhandled Event Type: 0x%X\n", type);
break;
#endif
}
That should get you started.
Hope that helps.