diff --git a/src/java/org/jnativehook/example/NativeHookDemo.java b/src/java/org/jnativehook/example/NativeHookDemo.java index b52c1f4b..88c60020 100644 --- a/src/java/org/jnativehook/example/NativeHookDemo.java +++ b/src/java/org/jnativehook/example/NativeHookDemo.java @@ -231,7 +231,11 @@ public void itemStateChanged(ItemEvent e) { GlobalScreen.unregisterNativeHook(); } - menuSubListeners.setEnabled(GlobalScreen.isNativeHookRegistered()); + // Set the enable menu item to the state of the hook. + menuItemEnable.setState(GlobalScreen.isNativeHookRegistered()); + + // Set enable/disable the sub-menus based on the enable menu item's state. + menuSubListeners.setEnabled(menuItemEnable.getState()); } else if (item == menuItemKeyboardEvents) { //Keyboard checkbox was changed, adjust listeners accordingly diff --git a/src/jni/jni_Errors.c b/src/jni/jni_Errors.c index 37613e37..61d76e7a 100644 --- a/src/jni/jni_Errors.c +++ b/src/jni/jni_Errors.c @@ -51,6 +51,12 @@ void jni_ThrowException(JNIEnv *env, const char *classname, const char *message) } void jni_ThrowNativeHookException(JNIEnv *env, short code, const char *message) { + jobject Exception_object = (*env)->NewObject(env, org_jnativehook_NativeHookException->cls, + org_jnativehook_NativeHookException->init, (jint) code, (*env)->NewStringUTF(env, message)); + (*env)->Throw(env, (jthrowable) Exception_object); + (*env)->DeleteLocalRef(env, Exception_object); + + /* // Locate our exception class. jclass Exception_class = (*env)->FindClass(env, "org/jnativehook/NativeHookException"); if (Exception_class != NULL) { @@ -65,7 +71,7 @@ void jni_ThrowNativeHookException(JNIEnv *env, short code, const char *message) env, Exception_class, init, - (jshort) code, + (jint) code, (*env)->NewStringUTF(env, message)); (*env)->Throw(env, (jthrowable) Exception_object); @@ -84,4 +90,5 @@ void jni_ThrowNativeHookException(JNIEnv *env, short code, const char *message) jni_ThrowException(env, "java/lang/ClassNotFoundException", "org.jnativehook.NativeHookException"); } + */ } diff --git a/src/jni/jni_Globals.c b/src/jni/jni_Globals.c index 72981222..dbdc116a 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; +NativeHookException *org_jnativehook_NativeHookException = NULL; NativeInputEvent *org_jnativehook_NativeInputEvent = NULL; NativeKeyEvent *org_jnativehook_keyboard_NativeKeyEvent = NULL; NativeMouseEvent *org_jnativehook_mouse_NativeMouseEvent = NULL; @@ -31,7 +32,6 @@ NativeMouseWheelEvent *org_jnativehook_mouse_NativeMouseWheelEvent = NULL; System *java_lang_System = NULL; Logger *java_util_logging_Logger = NULL; - static inline int create_GlobalScreen(JNIEnv *env) { int status = JNI_ERR; @@ -78,6 +78,48 @@ static inline void destroy_GlobalScreen(JNIEnv *env) { } +static inline int create_NativeHookException(JNIEnv *env) { + int status = JNI_ERR; + + // Class and Constructor for the NativeHookException Object. + jclass NativeHookException_class = (*env)->FindClass(env, "org/jnativehook/NativeHookException"); + if (NativeHookException_class != NULL) { + // Get the method ID for NativeInputEvent constructor. + jmethodID init = (*env)->GetMethodID(env, NativeHookException_class, "", "(ILjava/lang/String;)V"); + + if ((*env)->ExceptionCheck(env) == JNI_FALSE) { + org_jnativehook_NativeHookException = malloc(sizeof(NativeInputEvent)); + if (org_jnativehook_NativeHookException != NULL) { + // Populate our structure for later use. + org_jnativehook_NativeHookException->cls = (jclass) (*env)->NewGlobalRef(env, NativeHookException_class); + org_jnativehook_NativeHookException->init = init; + + status = JNI_OK; + } + else { + jni_ThrowException(env, "java/lang/OutOfMemoryError", "Failed to allocate native memory."); + status = JNI_ENOMEM; + } + } + } + + return status; +} + +static inline void destroy_NativeHookException(JNIEnv *env) { + if (org_jnativehook_NativeHookException != NULL) { + // The class *should* never be null if the struct was allocated, but we will check anyway. + if (org_jnativehook_NativeHookException->cls != NULL) { + (*env)->DeleteGlobalRef(env, org_jnativehook_NativeHookException->cls); + } + + // Free struct memory. + free(org_jnativehook_NativeHookException); + org_jnativehook_NativeHookException = NULL; + } +} + + static inline int create_NativeInputEvent(JNIEnv *env) { int status = JNI_ERR; @@ -347,6 +389,7 @@ static inline void destroy_System(JNIEnv *env) { } + static inline int create_Logger(JNIEnv *env) { int status = JNI_ERR; @@ -408,6 +451,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_NativeHookException(env); + } + if (status == JNI_OK && (*env)->ExceptionCheck(env) == JNI_FALSE) { status = create_NativeInputEvent(env); } @@ -442,6 +489,7 @@ int jni_CreateGlobals(JNIEnv *env) { int jni_DestroyGlobals(JNIEnv *env) { destroy_GlobalScreen(env); + destroy_NativeHookException(env); destroy_NativeInputEvent(env); destroy_NativeKeyEvent(env); destroy_NativeMouseEvent(env); diff --git a/src/jni/jni_Globals.h b/src/jni/jni_Globals.h index 40b15f8c..9e511120 100644 --- a/src/jni/jni_Globals.h +++ b/src/jni/jni_Globals.h @@ -38,6 +38,11 @@ typedef struct _org_jnativehook_GlobalScreen { jmethodID dispatchEvent; } GlobalScreen; +typedef struct _org_jnativehook_NativeHookException { + jclass cls; + jmethodID init; +} NativeHookException; + typedef struct _org_jnativehook_NativeInputEvent { jclass cls; jfieldID reserved; @@ -91,6 +96,7 @@ typedef struct _java_util_logging_Logger { // Global variables for Java object struct representation. extern GlobalScreen *org_jnativehook_GlobalScreen; +extern NativeHookException *org_jnativehook_NativeHookException; extern NativeInputEvent *org_jnativehook_NativeInputEvent; extern NativeKeyEvent *org_jnativehook_keyboard_NativeKeyEvent; extern NativeMouseEvent *org_jnativehook_mouse_NativeMouseEvent;