From fd7382a35ff0bbb3ea9fa78fc4f3aa2b471954bd Mon Sep 17 00:00:00 2001 From: Alexander Barker Date: Wed, 26 Oct 2016 22:32:28 -0700 Subject: [PATCH] Small refactoring. --- src/java/org/jnativehook/GlobalScreen.java | 102 ++++++++++----------- src/jni/jni_EventDispatcher.c | 4 +- src/jni/jni_Globals.c | 52 ++++++++++- src/jni/jni_Globals.h | 7 +- 4 files changed, 102 insertions(+), 63 deletions(-) diff --git a/src/java/org/jnativehook/GlobalScreen.java b/src/java/org/jnativehook/GlobalScreen.java index 7c3d6c4a..d2b58735 100644 --- a/src/java/org/jnativehook/GlobalScreen.java +++ b/src/java/org/jnativehook/GlobalScreen.java @@ -325,6 +325,27 @@ public NativeHookException getException() { * Native implementation to stop the input hook. There is no other way to stop the hook. */ public native void disable() throws NativeHookException; + + /** + * Dispatches an event to the appropriate processor. This method is + * generally called by the native library but may be used to synthesize + * native events from Java without replaying them on the native system. If + * you would like to send events to other applications, please use + * {@link #postNativeEvent}, + *

+ * + * Note: This method executes on the native system's event queue. + * It is imperative that all processing be off-loaded to other threads. + * Failure to do so might result in the delay of user input and the automatic + * removal of the native hook. + * + * @param event the NativeInputEvent sent to the registered event listeners. + */ + protected static void dispatchEvent(NativeInputEvent event) { + if (eventExecutor != null) { + eventExecutor.execute(new EventDispatchTask(event)); + } + } } @@ -500,24 +521,20 @@ else if (event instanceof NativeMouseWheelEvent) { private void processKeyEvent(NativeKeyEvent e) { NativeKeyListener[] listeners = eventListeners.getListeners(NativeKeyListener.class); - switch (e.getID()) { - case NativeKeyEvent.NATIVE_KEY_PRESSED: - for (int i = 0; i < listeners.length; i++) { + for (int i = 0; i < listeners.length; i++) { + switch (e.getID()) { + case NativeKeyEvent.NATIVE_KEY_PRESSED: listeners[i].nativeKeyPressed(e); - } - break; + break; - case NativeKeyEvent.NATIVE_KEY_TYPED: - for (int i = 0; i < listeners.length; i++) { + case NativeKeyEvent.NATIVE_KEY_TYPED: listeners[i].nativeKeyTyped(e); - } - break; + break; - case NativeKeyEvent.NATIVE_KEY_RELEASED: - for (int i = 0; i < listeners.length; i++) { + case NativeKeyEvent.NATIVE_KEY_RELEASED: listeners[i].nativeKeyReleased(e); - } - break; + break; + } } } @@ -533,24 +550,20 @@ private void processKeyEvent(NativeKeyEvent e) { private void processButtonEvent(NativeMouseEvent e) { NativeMouseListener[] listeners = eventListeners.getListeners(NativeMouseListener.class); - switch (e.getID()) { - case NativeMouseEvent.NATIVE_MOUSE_CLICKED: - for (int i = 0; i < listeners.length; i++) { + for (int i = 0; i < listeners.length; i++) { + switch (e.getID()) { + case NativeMouseEvent.NATIVE_MOUSE_CLICKED: listeners[i].nativeMouseClicked(e); - } - break; + break; - case NativeMouseEvent.NATIVE_MOUSE_PRESSED: - for (int i = 0; i < listeners.length; i++) { + case NativeMouseEvent.NATIVE_MOUSE_PRESSED: listeners[i].nativeMousePressed(e); - } - break; + break; - case NativeMouseEvent.NATIVE_MOUSE_RELEASED: - for (int i = 0; i < listeners.length; i++) { + case NativeMouseEvent.NATIVE_MOUSE_RELEASED: listeners[i].nativeMouseReleased(e); - } - break; + break; + } } } @@ -566,18 +579,16 @@ private void processButtonEvent(NativeMouseEvent e) { private void processMouseEvent(NativeMouseEvent e) { NativeMouseMotionListener[] listeners = eventListeners.getListeners(NativeMouseMotionListener.class); - switch (e.getID()) { - case NativeMouseEvent.NATIVE_MOUSE_MOVED: - for (int i = 0; i < listeners.length; i++) { + for (int i = 0; i < listeners.length; i++) { + switch (e.getID()) { + case NativeMouseEvent.NATIVE_MOUSE_MOVED: listeners[i].nativeMouseMoved(e); - } - break; + break; - case NativeMouseEvent.NATIVE_MOUSE_DRAGGED: - for (int i = 0; i < listeners.length; i++) { + case NativeMouseEvent.NATIVE_MOUSE_DRAGGED: listeners[i].nativeMouseDragged(e); - } - break; + break; + } } } @@ -600,27 +611,6 @@ private void processMouseWheelEvent(NativeMouseWheelEvent e) { } } - /** - * Dispatches an event to the appropriate processor. This method is - * generally called by the native library but may be used to synthesize - * native events from Java without replaying them on the native system. If - * you would like to send events to other applications, please use - * {@link #postNativeEvent}, - *

- * - * Note: This method executes on the native system's event queue. - * It is imperative that all processing be off-loaded to other threads. - * Failure to do so might result in the delay of user input and the automatic - * removal of the native hook. - * - * @param event the NativeInputEvent sent to the registered event listeners. - */ - protected static void dispatchEvent(NativeInputEvent event) { - if (eventExecutor != null) { - eventExecutor.execute(new EventDispatchTask(event)); - } - } - /** * Set a different executor service for native event delivery. By default, * JNativeHook utilizes a single thread executor to dispatch events from diff --git a/src/jni/jni_EventDispatcher.c b/src/jni/jni_EventDispatcher.c index e05d621a..b6ee18b9 100644 --- a/src/jni/jni_EventDispatcher.c +++ b/src/jni/jni_EventDispatcher.c @@ -204,8 +204,8 @@ void jni_EventDispatcher(uiohook_event * const event) { // Dispatch the event. (*env)->CallStaticVoidMethod( env, - org_jnativehook_GlobalScreen->cls, - org_jnativehook_GlobalScreen->dispatchEvent, + org_jnativehook_GlobalScreen$NativeHookThread->cls, + org_jnativehook_GlobalScreen$NativeHookThread->dispatchEvent, NativeInputEvent_obj); // Set the propagate flag from java. diff --git a/src/jni/jni_Globals.c b/src/jni/jni_Globals.c index 99223fe9..346f913f 100644 --- a/src/jni/jni_Globals.c +++ b/src/jni/jni_Globals.c @@ -24,6 +24,7 @@ #include "jni_Logger.h" GlobalScreen *org_jnativehook_GlobalScreen = NULL; +NativeHookThread *org_jnativehook_GlobalScreen$NativeHookThread = NULL; NativeHookException *org_jnativehook_NativeHookException = NULL; NativeMonitorInfo *org_jnativehook_NativeMonitorInfo = NULL; NativeInputEvent *org_jnativehook_NativeInputEvent = NULL; @@ -44,16 +45,12 @@ static int create_GlobalScreen(JNIEnv *env) { // Get the field ID for hookThread. jfieldID hookThread = (*env)->GetStaticFieldID(env, GlobalScreen_class, "hookThread", "Lorg/jnativehook/GlobalScreen$NativeHookThread;"); - // Get the method ID for GlobalScreen.dispatchEvent(). - jmethodID dispatchEvent = (*env)->GetStaticMethodID(env, GlobalScreen_class, "dispatchEvent", "(Lorg/jnativehook/NativeInputEvent;)V"); - if ((*env)->ExceptionCheck(env) == JNI_FALSE) { org_jnativehook_GlobalScreen = malloc(sizeof(GlobalScreen)); if (org_jnativehook_GlobalScreen != NULL) { // Populate our structure for later use. org_jnativehook_GlobalScreen->cls = (jclass) (*env)->NewGlobalRef(env, GlobalScreen_class); org_jnativehook_GlobalScreen->hookThread = hookThread; - org_jnativehook_GlobalScreen->dispatchEvent = dispatchEvent; status = JNI_OK; } @@ -81,6 +78,48 @@ static void destroy_GlobalScreen(JNIEnv *env) { } +static int create_NativeHookThread(JNIEnv *env) { + int status = JNI_ERR; + + // Class and Constructor for the GlobalScreen Object. + jclass NativeHookThread_class = (*env)->FindClass(env, "org/jnativehook/GlobalScreen$NativeHookThread"); + if (NativeHookThread_class != NULL) { + // Get the method ID for GlobalScreen.dispatchEvent(). + jmethodID dispatchEvent = (*env)->GetStaticMethodID(env, NativeHookThread_class, "dispatchEvent", "(Lorg/jnativehook/NativeInputEvent;)V"); + + if ((*env)->ExceptionCheck(env) == JNI_FALSE) { + org_jnativehook_GlobalScreen$NativeHookThread = malloc(sizeof(NativeHookThread)); + if (org_jnativehook_GlobalScreen$NativeHookThread != NULL) { + // Populate our structure for later use. + org_jnativehook_GlobalScreen$NativeHookThread->cls = (jclass) (*env)->NewGlobalRef(env, NativeHookThread_class); + org_jnativehook_GlobalScreen$NativeHookThread->dispatchEvent = dispatchEvent; + + status = JNI_OK; + } + else { + jni_ThrowException(env, "java/lang/OutOfMemoryError", "Failed to allocate native memory."); + status = JNI_ENOMEM; + } + } + } + + return status; +} + +static void destroy_NativeHookThread(JNIEnv *env) { + if (org_jnativehook_GlobalScreen != NULL) { + // The class *should* never be null if the struct was allocated, but we will check anyway. + if (org_jnativehook_GlobalScreen$NativeHookThread->cls != NULL) { + (*env)->DeleteGlobalRef(env, org_jnativehook_GlobalScreen$NativeHookThread->cls); + } + + // Free struct memory. + free(org_jnativehook_GlobalScreen$NativeHookThread); + org_jnativehook_GlobalScreen$NativeHookThread = NULL; + } +} + + static int create_NativeHookException(JNIEnv *env) { int status = JNI_ERR; @@ -581,6 +620,10 @@ static inline void destroy_Logger(JNIEnv *env) { int jni_CreateGlobals(JNIEnv *env) { int status = create_GlobalScreen(env); + if (status == JNI_OK && (*env)->ExceptionCheck(env) == JNI_FALSE) { + status = create_NativeHookThread(env); + } + if (status == JNI_OK && (*env)->ExceptionCheck(env) == JNI_FALSE) { status = create_NativeHookException(env); } @@ -631,6 +674,7 @@ int jni_CreateGlobals(JNIEnv *env) { int jni_DestroyGlobals(JNIEnv *env) { destroy_GlobalScreen(env); + destroy_NativeHookThread(env); destroy_NativeHookException(env); destroy_NativeMonitorInfo(env); destroy_NativeInputEvent(env); diff --git a/src/jni/jni_Globals.h b/src/jni/jni_Globals.h index 084abef1..f3a562cf 100644 --- a/src/jni/jni_Globals.h +++ b/src/jni/jni_Globals.h @@ -35,9 +35,13 @@ extern JavaVMAttachArgs jvm_attach_args; typedef struct _org_jnativehook_GlobalScreen { jclass cls; jfieldID hookThread; - jmethodID dispatchEvent; } GlobalScreen; +typedef struct org_jnativehook_GlobalScreen$NativeHookThread { + jclass cls; + jmethodID dispatchEvent; +} NativeHookThread; + typedef struct _org_jnativehook_NativeHookException { jclass cls; jmethodID init; @@ -112,6 +116,7 @@ typedef struct _java_util_logging_Logger { // Global variables for Java object struct representation. extern GlobalScreen *org_jnativehook_GlobalScreen; +extern NativeHookThread *org_jnativehook_GlobalScreen$NativeHookThread; extern NativeHookException *org_jnativehook_NativeHookException; extern NativeMonitorInfo *org_jnativehook_NativeMonitorInfo; extern NativeInputEvent *org_jnativehook_NativeInputEvent;