// JNI exit point, This is executed when the Java virtual machine detaches from the native library. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { // Grab the currently JNI interface pointer so we can cleanup the // system properties set on load. JNIEnv *env = NULL; if ((*jvm)->GetEnv(jvm, (void **)(&env), jni_version) == JNI_OK) { // Clear java properties from native sources. jni_ClearProperties(env); } else { // It is not critical that these values are cleared so no exception // will be thrown. jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to call jni_ClearProperties()!\n", __FUNCTION__, __LINE__); } jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: JNI Unloaded.\n", __FUNCTION__, __LINE__); // Unset the hook callback function to dispatch events. hook_set_dispatch_proc(NULL); // Unset Java logger for native code messages. hook_set_logger_proc(NULL); if (env != NULL) { jni_DestroyGlobals(env); } }
int jni_CreateGlobals(JNIEnv *env) { int status = JNI_ERR; // Allocate memory for the Java object structure representation. org_jnativehook_GlobalScreen = malloc(sizeof(GlobalScreen)); org_jnativehook_NativeInputEvent = malloc(sizeof(NativeInputEvent)); org_jnativehook_keyboard_NativeKeyEvent = malloc(sizeof(NativeKeyEvent)); org_jnativehook_mouse_NativeMouseEvent = malloc(sizeof(NativeMouseEvent)); org_jnativehook_mouse_NativeMouseWheelEvent = malloc(sizeof(NativeMouseWheelEvent)); java_lang_System = malloc(sizeof(System)); java_util_logging_Logger = malloc(sizeof(Logger)); // Check to make sure memory was allocated properly. if (org_jnativehook_GlobalScreen != NULL && org_jnativehook_NativeInputEvent != NULL && org_jnativehook_keyboard_NativeKeyEvent != NULL && org_jnativehook_mouse_NativeMouseEvent != NULL && org_jnativehook_mouse_NativeMouseWheelEvent != NULL && java_lang_System != NULL && java_util_logging_Logger != NULL) { // Lookup a local reference for the GlobalScreen class and create a global reference. jclass GlobalScreen_class = (*env)->FindClass(env, "org/jnativehook/GlobalScreen"); if (GlobalScreen_class != NULL) { org_jnativehook_GlobalScreen->cls = (jclass) (*env)->NewGlobalRef(env, GlobalScreen_class); // Get the method ID for GlobalScreen.getInstance() org_jnativehook_GlobalScreen->getInstance = (*env)->GetStaticMethodID( env, org_jnativehook_GlobalScreen->cls, "getInstance", "()Lorg/jnativehook/GlobalScreen;"); if (org_jnativehook_GlobalScreen->getInstance == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for GlobalScreen.getInstance()Lorg/jnativehook/GlobalScreen;!\n", __FUNCTION__, __LINE__); } // Get the method ID for GlobalScreen.dispatchEvent(). org_jnativehook_GlobalScreen->dispatchEvent = (*env)->GetMethodID( env, org_jnativehook_GlobalScreen->cls, "dispatchEvent", "(Lorg/jnativehook/NativeInputEvent;)V"); if (org_jnativehook_GlobalScreen->dispatchEvent == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for GlobalScreen.dispatchEvent(Lorg/jnativehook/NativeInputEvent;)V!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the GlobalScreen class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the NativeInputEvent Object. jclass NativeInputEvent_class = (*env)->FindClass(env, "org/jnativehook/NativeInputEvent"); if (NativeInputEvent_class != NULL) { org_jnativehook_NativeInputEvent->cls = (jclass) (*env)->NewGlobalRef(env, NativeInputEvent_class); // Get the field ID for NativeInputEvent.reserved. org_jnativehook_NativeInputEvent->reserved = (*env)->GetFieldID( env, org_jnativehook_NativeInputEvent->cls, "reserved", "S"); if (org_jnativehook_NativeInputEvent->reserved == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the field ID for NativeInputEvent.reserved S!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeInputEvent constructor. org_jnativehook_NativeInputEvent->init = (*env)->GetMethodID( env, org_jnativehook_NativeInputEvent->cls, "<init>", "(Lorg/jnativehook/GlobalScreen;IJI)V"); if (org_jnativehook_NativeInputEvent->init == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeInputEvent.<init>(Lorg.jnativehook.GlobalScreen;IJI)V!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeInputEvent.getID(). org_jnativehook_NativeInputEvent->getID = (*env)->GetMethodID( env, org_jnativehook_NativeInputEvent->cls, "getID", "()I"); if (org_jnativehook_NativeInputEvent->getID == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeInputEvent.getID()I!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeInputEvent.getModifiers(). org_jnativehook_NativeInputEvent->getModifiers = (*env)->GetMethodID( env, org_jnativehook_NativeInputEvent->cls, "getModifiers", "()I"); if (org_jnativehook_NativeInputEvent->getModifiers == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeInputEvent.getModifiers()I!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the NativeInputEvent class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the NativeKeyEvent Object. jclass NativeKeyEvent_class = (*env)->FindClass(env, "org/jnativehook/keyboard/NativeKeyEvent"); if (NativeKeyEvent_class != NULL) { org_jnativehook_keyboard_NativeKeyEvent->cls = (jclass) (*env)->NewGlobalRef(env, NativeKeyEvent_class); // Super class struct of the NativeKeyEvent. org_jnativehook_keyboard_NativeKeyEvent->parent = org_jnativehook_NativeInputEvent; // Get the method ID for NativeKeyEvent constructor. org_jnativehook_keyboard_NativeKeyEvent->init = (*env)->GetMethodID( env, org_jnativehook_keyboard_NativeKeyEvent->cls, "<init>", "(IJIIICI)V"); if (org_jnativehook_keyboard_NativeKeyEvent->init == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeKeyEvent.<init>(IJIIICI)V!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeKeyEvent.getKeyCode(). org_jnativehook_keyboard_NativeKeyEvent->getKeyCode = (*env)->GetMethodID( env, org_jnativehook_keyboard_NativeKeyEvent->cls, "getKeyCode", "()I"); if (org_jnativehook_keyboard_NativeKeyEvent->getKeyCode == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeKeyEvent.getKeyCode()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeKeyEvent.getKeyLocation(). org_jnativehook_keyboard_NativeKeyEvent->getKeyLocation = (*env)->GetMethodID( env, org_jnativehook_keyboard_NativeKeyEvent->cls, "getKeyLocation", "()I"); if (org_jnativehook_keyboard_NativeKeyEvent->getKeyLocation == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeKeyEvent.getKeyLocation()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeKeyEvent.getKeyChar(). org_jnativehook_keyboard_NativeKeyEvent->getKeyChar = (*env)->GetMethodID( env, org_jnativehook_keyboard_NativeKeyEvent->cls, "getKeyChar", "()C"); if (org_jnativehook_keyboard_NativeKeyEvent->getKeyChar == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeKeyEvent.getKeyChar()!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the NativeKeyEvent class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the NativeMouseEvent Object. jclass NativeMouseEvent_class = (*env)->FindClass(env, "org/jnativehook/mouse/NativeMouseEvent"); if (NativeMouseEvent_class != NULL) { org_jnativehook_mouse_NativeMouseEvent->cls = (jclass) (*env)->NewGlobalRef(env, NativeMouseEvent_class); // Super class struct of the NativeKeyEvent. org_jnativehook_mouse_NativeMouseEvent->parent = org_jnativehook_NativeInputEvent; // Get the method ID for NativeMouseEvent constructor. org_jnativehook_mouse_NativeMouseEvent->init = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseEvent->cls, "<init>", "(IJIIIII)V"); if (org_jnativehook_mouse_NativeMouseEvent->init == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.<init>(IJIIIII)V!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getButton(). org_jnativehook_mouse_NativeMouseEvent->getButton = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseEvent->cls, "getButton", "()I"); if (org_jnativehook_mouse_NativeMouseEvent->getButton == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.getButton()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getClickCount(). org_jnativehook_mouse_NativeMouseEvent->getClickCount = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseEvent->cls, "getClickCount", "()I"); if (org_jnativehook_mouse_NativeMouseEvent->getClickCount == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.getClickCount()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getX(). org_jnativehook_mouse_NativeMouseEvent->getX = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseEvent->cls, "getX", "()I"); if (org_jnativehook_mouse_NativeMouseEvent->getX == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.getX()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getY(). org_jnativehook_mouse_NativeMouseEvent->getY = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseEvent->cls, "getY", "()I"); if (org_jnativehook_mouse_NativeMouseEvent->getY == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.getY()!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the NativeMouseEvent class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the NativeMouseWheelEvent Object. jclass NativeMouseWheelEvent_class = (*env)->FindClass(env, "org/jnativehook/mouse/NativeMouseWheelEvent"); if (NativeMouseWheelEvent_class != NULL) { org_jnativehook_mouse_NativeMouseWheelEvent->cls = (jclass) (*env)->NewGlobalRef(env, NativeMouseWheelEvent_class); // Super class struct of the NativeMouseEvent. org_jnativehook_mouse_NativeMouseWheelEvent->parent = org_jnativehook_mouse_NativeMouseEvent; // Get the method ID for NativeMouseWheelEvent constructor. org_jnativehook_mouse_NativeMouseWheelEvent->init = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, "<init>", "(IJIIIIIII)V"); if (org_jnativehook_mouse_NativeMouseWheelEvent->init == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseEvent.<init>(IJIIIIIII)V!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getButton(). org_jnativehook_mouse_NativeMouseWheelEvent->getScrollAmount = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, "getScrollAmount", "()I"); if (org_jnativehook_mouse_NativeMouseWheelEvent->getScrollAmount == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseWheelEvent.getScrollAmount()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getScrollType(). org_jnativehook_mouse_NativeMouseWheelEvent->getScrollType = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, "getScrollType", "()I"); if (org_jnativehook_mouse_NativeMouseWheelEvent->getScrollType == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseWheelEvent.getScrollType()!\n", __FUNCTION__, __LINE__); } // Get the method ID for NativeMouseEvent.getWheelRotation(). org_jnativehook_mouse_NativeMouseWheelEvent->getWheelRotation = (*env)->GetMethodID( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, "getWheelRotation", "()I"); if (org_jnativehook_mouse_NativeMouseWheelEvent->getWheelRotation == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for NativeMouseWheelEvent.getWheelRotation()!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the NativeMouseWheelEvent class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the Logger Object. jclass System_class = (*env)->FindClass(env, "java/lang/System"); if (System_class != NULL) { java_lang_System->cls = (jclass) (*env)->NewGlobalRef(env, System_class); // Get the method ID for System.setProperty(). java_lang_System->setProperty = (*env)->GetStaticMethodID( env, java_lang_System->cls, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); if (java_lang_System->setProperty == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for System.setProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;!\n", __FUNCTION__, __LINE__); } // Get the method ID for System.setProperty(). java_lang_System->clearProperty = (*env)->GetStaticMethodID( env, java_lang_System->cls, "clearProperty", "(Ljava/lang/String;)Ljava/lang/String;"); if (java_lang_System->clearProperty == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for System.clearProperty(Ljava/lang/String;)Ljava/lang/String;!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the System class!\n", __FUNCTION__, __LINE__); } // Class and Constructor for the Logger Object. jclass Logger_class = (*env)->FindClass(env, "java/util/logging/Logger"); if (Logger_class != NULL) { java_util_logging_Logger->cls = (jclass) (*env)->NewGlobalRef(env, Logger_class); // Get the method ID for Logger.getLogger constructor. java_util_logging_Logger->getLogger = (*env)->GetStaticMethodID( env, java_util_logging_Logger->cls, "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;"); if (java_util_logging_Logger->getLogger == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for Logger.getLogger(Ljava/lang/String;)Ljava/util/logging/Logger;!\n", __FUNCTION__, __LINE__); } java_util_logging_Logger->fine = (*env)->GetMethodID( env, java_util_logging_Logger->cls, "fine", "(Ljava/lang/String;)V"); if (java_util_logging_Logger->fine == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for Logger.fine(Ljava/lang/String;)V!\n", __FUNCTION__, __LINE__); } java_util_logging_Logger->info = (*env)->GetMethodID( env, java_util_logging_Logger->cls, "info", "(Ljava/lang/String;)V"); if (java_util_logging_Logger->info == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for Logger.info(Ljava/lang/String;)V!\n", __FUNCTION__, __LINE__); } java_util_logging_Logger->warning = (*env)->GetMethodID( env, java_util_logging_Logger->cls, "warning", "(Ljava/lang/String;)V"); if (java_util_logging_Logger->warning == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for Logger.warning(Ljava/lang/String;)V!\n", __FUNCTION__, __LINE__); } java_util_logging_Logger->severe = (*env)->GetMethodID( env, java_util_logging_Logger->cls, "severe", "(Ljava/lang/String;)V"); if (java_util_logging_Logger->severe == NULL) { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire the method ID for Logger.severe(Ljava/lang/String;)V!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to locate the Logger class!\n", __FUNCTION__, __LINE__); } } else { status = JNI_ENOMEM; jni_Logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to allocate memory for JNI structures!\n", __FUNCTION__, __LINE__); // FIXME Throw java.lang.OutOfMemoryError } // Check and make sure everything is correct. if ((*env)->ExceptionCheck(env) == JNI_FALSE) { status = JNI_OK; } return status; }
// JNI entry point, This is executed when the Java virtual machine attaches to the native library. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { /* Grab the currently running virtual machine so we can attach to it in * functions that are not called from java. */ jvm = vm; JNIEnv *env = NULL; if ((*jvm)->GetEnv(jvm, (void **)(&env), jni_version) == JNI_OK) { // Create all the global class references onload to prevent class loader // issues with JNLP and some IDE's. if (jni_CreateGlobals(env) != JNI_OK) { #ifndef USE_QUIET fprintf(stderr, "%s [%u]: CreateJNIGlobals() failed!\n", __FUNCTION__, __LINE__); #endif jni_ThrowFatalError(env, "Failed to locate one or more required classes."); } #ifndef USE_QUIET jclass PrintStream_class = (*env)->FindClass(env, "java/io/PrintStream"); jfieldID out_id = (*env)->GetStaticFieldID(env, java_lang_System->cls, "out", "Ljava/io/PrintStream;"); if (PrintStream_class != NULL && out_id != NULL) { jmethodID println_id = (*env)->GetMethodID(env, PrintStream_class, "println", "(Ljava/lang/String;)V"); jobject out = (*env)->GetStaticObjectField(env, PrintStream_class, out_id); if (println_id != NULL && out_id != NULL) { jstring copyright = (*env)->NewStringUTF(env, "\n" "JNativeHook: Global keyboard and mouse hooking for Java.\n" "Copyright (C) 2006-2014 Alexander Barker. All Rights Received.\n" "https://github.com/kwhat/jnativehook/\n" "\n" "JNativeHook is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU Lesser General Public License as published\n" "by the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "JNativeHook is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU Lesser General Public License\n" "along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); (*env)->CallVoidMethod(env, out, println_id, copyright); } } #endif // Set Java logger for native code messages. hook_set_logger_proc(&jni_Logger); // Set java properties from native sources. jni_SetProperties(env); // Set the hook callback function to dispatch events. hook_set_dispatch_proc(&jni_EventDispatcher); } else { #ifndef USE_QUIET fprintf(stderr, "%s [%u]: GetEnv() failed!\n", __FUNCTION__, __LINE__); #endif jni_ThrowFatalError(env, "Failed to acquire JNI interface pointer"); } jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: JNI Loaded.\n", __FUNCTION__, __LINE__); return jni_version; }
// NOTE: This function executes on the hook thread! If you need to block // please do so on another thread via your own event dispatcher. void jni_EventDispatcher(uiohook_event * const event) { jobject NativeInputEvent_object = NULL; switch (event->type) { /* The following start and stop functions are less than ideal for attaching JNI. * TODO Consider moving threads out of the lib and into Java. */ case EVENT_THREAD_STARTED: if ((*jvm)->GetEnv(jvm, (void **)(&env), jvm_attach_args.version) == JNI_EDETACHED) { (*jvm)->AttachCurrentThread(jvm, (void **)(&env), &jvm_attach_args); } break; case EVENT_THREAD_STOPPED: // NOTE This callback may note be called from Windows under some circumstances. if ((*jvm)->GetEnv(jvm, (void **)(&env), jvm_attach_args.version) == JNI_OK) { if ((*jvm)->DetachCurrentThread(jvm) == JNI_OK) { env = NULL; } } break; case EVENT_HOOK_ENABLED: case EVENT_HOOK_DISABLED: break; case EVENT_KEY_PRESSED: if (env != NULL) { jint location; if (jni_ConvertToJavaLocation(event->data.keyboard.keycode, &location) == JNI_OK) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_PRESSED, (jlong) event->time, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) event->data.keyboard.keycode, (jchar) org_jnativehook_keyboard_NativeKeyEvent_CHAR_UNDEFINED, location); } } break; case EVENT_KEY_RELEASED: if (env != NULL) { jint location; if (jni_ConvertToJavaLocation(event->data.keyboard.keycode, &location) == JNI_OK) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_RELEASED, (jlong) event->time, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) event->data.keyboard.keycode, (jchar) org_jnativehook_keyboard_NativeKeyEvent_CHAR_UNDEFINED, location); } } break; case EVENT_KEY_TYPED: if (env != NULL) { jint location; if (jni_ConvertToJavaLocation(event->data.keyboard.keycode, &location) == JNI_OK) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_TYPED, (jlong) event->time, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) org_jnativehook_keyboard_NativeKeyEvent_VK_UNDEFINED, (jchar) event->data.keyboard.keychar, location); } } break; case EVENT_MOUSE_PRESSED: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_PRESSED, (jlong) event->time, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); } break; case EVENT_MOUSE_RELEASED: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_RELEASED, (jlong) event->time, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); } break; case EVENT_MOUSE_CLICKED: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_CLICKED, (jlong) event->time, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); } break; case EVENT_MOUSE_MOVED: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_MOVED, (jlong) event->time, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); } break; case EVENT_MOUSE_DRAGGED: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_DRAGGED, (jlong) event->time, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); } break; case EVENT_MOUSE_WHEEL: if (env != NULL) { NativeInputEvent_object = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, org_jnativehook_mouse_NativeMouseWheelEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_WHEEL, (jlong) event->time, (jint) event->mask, (jint) event->data.wheel.x, (jint) event->data.wheel.y, (jint) event->data.wheel.clicks, (jint) event->data.wheel.type, (jint) event->data.wheel.amount, (jint) event->data.wheel.rotation); } break; } // NOTE It is assumed that we do not need to check env* for null because NativeInputEvent_object // cannot be assigned if env* is NULL. if (NativeInputEvent_object != NULL) { // Create the global screen references up front to save time in the callback. jobject GlobalScreen_object = (*env)->CallStaticObjectMethod( env, org_jnativehook_GlobalScreen->cls, org_jnativehook_GlobalScreen->getInstance); if (GlobalScreen_object != NULL) { (*env)->CallVoidMethod( env, GlobalScreen_object, org_jnativehook_GlobalScreen->dispatchEvent, NativeInputEvent_object); // Set the propagate flag from java. event->reserved = (unsigned short) (*env)->GetShortField( env, NativeInputEvent_object, org_jnativehook_NativeInputEvent->reserved); (*env)->DeleteLocalRef(env, GlobalScreen_object); } else { jni_Logger(env, LOG_LEVEL_ERROR, "%s [%u]: Failed to acquire GlobalScreen singleton!\n", __FUNCTION__, __LINE__); jni_ThrowException(env, "java/lang/NullPointerException", "GlobalScreen singleton is null."); } (*env)->DeleteLocalRef(env, NativeInputEvent_object); } }
void jni_SetProperties(JNIEnv *env) { // Create a buffer for converting numbers to strings. char buffer[16]; // Set the native keyboard auto repeat rate. long rate = hook_get_auto_repeat_rate(); if (rate >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_auto_repeat_rate(): successful. (%li)\n", __FUNCTION__, __LINE__, rate); if (snprintf(buffer, sizeof(buffer), "%li", rate) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.autoRepeatRate"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert auto repeat rate to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_auto_repeat_rate()!\n", __FUNCTION__, __LINE__); } long delay = hook_get_auto_repeat_delay(); if (delay >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_auto_repeat_delay(): successful. (%li)\n", __FUNCTION__, __LINE__, delay); if (snprintf(buffer, sizeof(buffer), "%li", delay) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.autoRepeatDelay"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert auto repeat delay to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_auto_repeat_delay()!\n", __FUNCTION__, __LINE__); } // 0-Threshold X, 1-Threshold Y and 2-Speed. long multiplier = hook_get_pointer_acceleration_multiplier(); if (multiplier >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_acceleration_multiplier(): successful. (%li)\n", __FUNCTION__, __LINE__, multiplier); if (snprintf(buffer, sizeof(buffer), "%li", multiplier) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerAccelerationMultiplier"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer acceleration multiplier to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_acceleration_multiplier()!\n", __FUNCTION__, __LINE__); } // 0-Threshold X, 1-Threshold Y and 2-Speed. long threshold = hook_get_pointer_acceleration_threshold(); if (threshold >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_acceleration_threshold(): successful. (%li)\n", __FUNCTION__, __LINE__, threshold); if (snprintf(buffer, sizeof(buffer), "%li", threshold) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerAccelerationThreshold"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer acceleration threshold to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_acceleration_threshold()!\n", __FUNCTION__, __LINE__); } long sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_sensitivity(): successful. (%li)\n", __FUNCTION__, __LINE__, sensitivity); if (snprintf(buffer, sizeof(buffer), "%li", sensitivity) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerSensitivity"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer sensitivity to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_sensitivity()!\n", __FUNCTION__, __LINE__); } long clicktime = hook_get_multi_click_time(); if (clicktime >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_multi_click_time(): successful. (%li)\n", __FUNCTION__, __LINE__, clicktime); if (snprintf(buffer, sizeof(buffer), "%li", clicktime) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.multiClickInterval"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert multi click time to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_multi_click_time()!\n", __FUNCTION__, __LINE__); } }
// NOTE: This function executes on the hook thread! If you need to block // please do so on another thread via your own event dispatcher. void jni_EventDispatcher(uiohook_event * const event) { JNIEnv *env; if ((*jvm)->GetEnv(jvm, (void **)(&env), jvm_attach_args.version) == JNI_OK) { jobject NativeInputEvent_obj = NULL; jint location = org_jnativehook_keyboard_NativeKeyEvent_LOCATION_UNKNOWN; switch (event->type) { case EVENT_HOOK_DISABLED: case EVENT_HOOK_ENABLED: notifyHookThread(env); return; case EVENT_KEY_PRESSED: if (jni_ConvertToJavaLocation(event->data.keyboard.keycode, &location) == JNI_OK) { NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_PRESSED, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) event->data.keyboard.keycode, (jchar) org_jnativehook_keyboard_NativeKeyEvent_CHAR_UNDEFINED, location); } break; case EVENT_KEY_RELEASED: if (jni_ConvertToJavaLocation(event->data.keyboard.keycode, &location) == JNI_OK) { NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_RELEASED, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) event->data.keyboard.keycode, (jchar) org_jnativehook_keyboard_NativeKeyEvent_CHAR_UNDEFINED, location); } break; case EVENT_KEY_TYPED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_keyboard_NativeKeyEvent->cls, org_jnativehook_keyboard_NativeKeyEvent->init, org_jnativehook_keyboard_NativeKeyEvent_NATIVE_KEY_TYPED, (jint) event->mask, (jint) event->data.keyboard.rawcode, (jint) org_jnativehook_keyboard_NativeKeyEvent_VC_UNDEFINED, (jchar) event->data.keyboard.keychar, location); break; case EVENT_MOUSE_PRESSED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_PRESSED, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); break; case EVENT_MOUSE_RELEASED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_RELEASED, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); break; case EVENT_MOUSE_CLICKED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_CLICKED, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); break; case EVENT_MOUSE_MOVED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_MOVED, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); break; case EVENT_MOUSE_DRAGGED: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseEvent->cls, org_jnativehook_mouse_NativeMouseEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_DRAGGED, (jint) event->mask, (jint) event->data.mouse.x, (jint) event->data.mouse.y, (jint) event->data.mouse.clicks, (jint) event->data.mouse.button); break; case EVENT_MOUSE_WHEEL: NativeInputEvent_obj = (*env)->NewObject( env, org_jnativehook_mouse_NativeMouseWheelEvent->cls, org_jnativehook_mouse_NativeMouseWheelEvent->init, org_jnativehook_mouse_NativeMouseEvent_NATIVE_MOUSE_WHEEL, (jint) event->mask, (jint) event->data.wheel.x, (jint) event->data.wheel.y, (jint) event->data.wheel.clicks, (jint) event->data.wheel.type, (jint) event->data.wheel.amount, (jint) event->data.wheel.rotation, (jint) event->data.wheel.direction); break; default: jni_Logger(env, LOG_LEVEL_WARN, "%s [%u]: Unknown native event type: %#X\n", __FUNCTION__, __LINE__, event->type); break; } if (NativeInputEvent_obj != NULL) { // Set the private when field to the native event time. (*env)->SetShortField( env, NativeInputEvent_obj, org_jnativehook_NativeInputEvent->when, (jlong) event->time); // Dispatch the event. (*env)->CallStaticVoidMethod( env, org_jnativehook_GlobalScreen->cls, org_jnativehook_GlobalScreen->dispatchEvent, NativeInputEvent_obj); // Set the propagate flag from java. event->reserved = (unsigned short) (*env)->GetShortField( env, NativeInputEvent_obj, org_jnativehook_NativeInputEvent->reserved); // Make sure our object is garbage collected. (*env)->DeleteLocalRef(env, NativeInputEvent_obj); } } }