diff --git a/README.md b/README.md
index 37449b5..ff86283 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ You can include `system-hook` from this GitHub repository by adding this depende
lc.kra.system
system-hook
- 3.4
+ 3.5
```
diff --git a/appveyor.yml b/appveyor.yml
index ab3f5c0..5ee176e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 3.4.{build}
+version: 3.5.{build}
branches:
only:
diff --git a/pom.xml b/pom.xml
index 36bd125..39de76a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
lc.kra.system
system-hook
- 3.4
+ 3.5
Global Keyboard / Mouse Hook for Java applications.
https://github.com/kristian/system-hook
diff --git a/src/main/java/lc/kra/system/GlobalHookMode.java b/src/main/java/lc/kra/system/GlobalHookMode.java
new file mode 100644
index 0000000..28e2f5e
--- /dev/null
+++ b/src/main/java/lc/kra/system/GlobalHookMode.java
@@ -0,0 +1,16 @@
+package lc.kra.system;
+
+public enum GlobalHookMode {
+ /**
+ * capture events via the low-level system hook, after a event was captured any next hook registered will be called
+ */
+ DEFAULT,
+ /**
+ * capture events via the low-level system hook, this mode will not invoke any further hooks
+ */
+ FINAL,
+ /**
+ * capturing events in raw mode will provide you additional information of the device
+ */
+ RAW
+}
diff --git a/src/main/java/lc/kra/system/keyboard/GlobalKeyboardHook.java b/src/main/java/lc/kra/system/keyboard/GlobalKeyboardHook.java
index a988174..a398ea5 100644
--- a/src/main/java/lc/kra/system/keyboard/GlobalKeyboardHook.java
+++ b/src/main/java/lc/kra/system/keyboard/GlobalKeyboardHook.java
@@ -21,17 +21,19 @@
*/
package lc.kra.system.keyboard;
+import static lc.kra.system.GlobalHookMode.DEFAULT;
+import static lc.kra.system.GlobalHookMode.RAW;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.TS_DOWN;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_CONTROL;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_LCONTROL;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_LMENU;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_LSHIFT;
+import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_LWIN;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_MENU;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_RCONTROL;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_RMENU;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_RSHIFT;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_RWIN;
-import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_LWIN;
import static lc.kra.system.keyboard.event.GlobalKeyEvent.VK_SHIFT;
import java.util.List;
@@ -40,6 +42,7 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
+import lc.kra.system.GlobalHookMode;
import lc.kra.system.LibraryLoader;
import lc.kra.system.keyboard.event.GlobalKeyEvent;
import lc.kra.system.keyboard.event.GlobalKeyListener;
@@ -95,11 +98,22 @@ public void run() {
* @throws UnsatisfiedLinkError Thrown if loading the native library failed
* @throws RuntimeException Thrown if registering the low-level keyboard hook failed
*/
- public GlobalKeyboardHook(boolean raw) throws UnsatisfiedLinkError {
+ public GlobalKeyboardHook(boolean raw) throws UnsatisfiedLinkError { this(raw?RAW:DEFAULT); }
+
+ /**
+ * Instantiate a new GlobalKeyboardHook.
+ *
+ * @see #GlobalKeyboardHook()
+ *
+ * @param mode The mode to capture the input
+ * @throws UnsatisfiedLinkError Thrown if loading the native library failed
+ * @throws RuntimeException Thrown if registering the low-level keyboard hook failed
+ */
+ public GlobalKeyboardHook(GlobalHookMode mode) throws UnsatisfiedLinkError {
LibraryLoader.loadLibrary(); // load the library, in case it's not already loaded
// register a keyboard hook (throws a RuntimeException in case something goes wrong)
- keyboardHook = new NativeKeyboardHook(raw) {
+ keyboardHook = new NativeKeyboardHook(mode) {
/**
* Handle the input virtualKeyCode and transitionState, create event and add it to the inputBuffer
*/
@@ -178,13 +192,13 @@ public static Map listKeyboards() throws UnsatisfiedLinkError {
private static abstract class NativeKeyboardHook extends Thread {
private int status;
- private boolean raw;
+ private GlobalHookMode mode;
- public NativeKeyboardHook(boolean raw) {
+ public NativeKeyboardHook(GlobalHookMode mode) {
super("Global Keyboard Hook Thread");
setDaemon(false); setPriority(MAX_PRIORITY);
synchronized(this) {
- this.raw = raw;
+ this.mode = mode;
try { start(); wait(); }
catch (InterruptedException e) {
throw new RuntimeException(e);
@@ -196,12 +210,12 @@ public NativeKeyboardHook(boolean raw) {
}
@Override public void run() {
- status = registerHook(raw);
+ status = registerHook(mode.ordinal());
synchronized(this) {
notifyAll(); }
}
- public native final int registerHook(boolean raw);
+ public native final int registerHook(int mode);
public native final void unregisterHook();
public static native final Map listDevices();
diff --git a/src/main/java/lc/kra/system/mouse/GlobalMouseHook.java b/src/main/java/lc/kra/system/mouse/GlobalMouseHook.java
index a5125b1..99d44f0 100644
--- a/src/main/java/lc/kra/system/mouse/GlobalMouseHook.java
+++ b/src/main/java/lc/kra/system/mouse/GlobalMouseHook.java
@@ -21,6 +21,8 @@
*/
package lc.kra.system.mouse;
+import static lc.kra.system.GlobalHookMode.DEFAULT;
+import static lc.kra.system.GlobalHookMode.RAW;
import static lc.kra.system.mouse.event.GlobalMouseEvent.BUTTON_NO;
import static lc.kra.system.mouse.event.GlobalMouseEvent.TS_DOWN;
import static lc.kra.system.mouse.event.GlobalMouseEvent.TS_MOVE;
@@ -33,6 +35,7 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
+import lc.kra.system.GlobalHookMode;
import lc.kra.system.LibraryLoader;
import lc.kra.system.mouse.event.GlobalMouseEvent;
import lc.kra.system.mouse.event.GlobalMouseListener;
@@ -99,11 +102,22 @@ public void run() {
* @throws UnsatisfiedLinkError Thrown if loading the native library failed
* @throws RuntimeException Thrown if registering the low-level keyboard hook failed
*/
- public GlobalMouseHook(boolean raw) throws UnsatisfiedLinkError {
+ public GlobalMouseHook(boolean raw) throws UnsatisfiedLinkError { this(raw?RAW:DEFAULT); }
+
+ /**
+ * Instantiate a new GlobalMouseHook.
+ *
+ * @see #GlobalMouseHook()
+ *
+ * @param mode The mode to capture the input
+ * @throws UnsatisfiedLinkError Thrown if loading the native library failed
+ * @throws RuntimeException Thrown if registering the low-level keyboard hook failed
+ */
+ public GlobalMouseHook(GlobalHookMode mode) throws UnsatisfiedLinkError {
LibraryLoader.loadLibrary(); // load the library, in case it's not already loaded
// register a mouse hook (throws a RuntimeException in case something goes wrong)
- mouseHook = new NativeMouseHook(raw) {
+ mouseHook = new NativeMouseHook(mode) {
/**
* Handle the input transitionState create event and add it to the inputBuffer
*/
@@ -199,13 +213,13 @@ public static Map listMice() throws UnsatisfiedLinkError {
private static abstract class NativeMouseHook extends Thread {
private int status;
- private boolean raw;
+ private GlobalHookMode mode;
- public NativeMouseHook(boolean raw) {
+ public NativeMouseHook(GlobalHookMode mode) {
super("Global Mouse Hook Thread");
setDaemon(false); setPriority(MAX_PRIORITY);
synchronized(this) {
- this.raw = raw;
+ this.mode = mode;
try { start(); wait(); }
catch (InterruptedException e) {
throw new RuntimeException(e);
@@ -217,12 +231,12 @@ public NativeMouseHook(boolean raw) {
}
@Override public void run() {
- status = registerHook(raw);
+ status = registerHook(mode.ordinal());
synchronized(this) {
notifyAll(); }
}
- public native final int registerHook(boolean raw);
+ public native final int registerHook(int mode);
public native final void unregisterHook();
public static native final Map listDevices();
diff --git a/src/main/native/windows/SystemHook.c b/src/main/native/windows/SystemHook.c
index d39a1e0..1ef7512 100644
--- a/src/main/native/windows/SystemHook.c
+++ b/src/main/native/windows/SystemHook.c
@@ -68,7 +68,7 @@ DWORD hookThreadId[2] = { 0, 0 };
BYTE keyState[256];
WCHAR buffer[4];
-jint lOldX = (jint)SHRT_MIN, lOldY = (jint)SHRT_MIN;
+jint lMode = 0, lOldX = (jint)SHRT_MIN, lOldY = (jint)SHRT_MIN;
BOOL APIENTRY DllMain(HINSTANCE _hInst, DWORD reason, LPVOID reserved) {
switch(reason) {
@@ -112,7 +112,7 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
handleKey("LowLevelKeyboardProc", wParam, pStruct->vkCode, pStruct->scanCode, 0);
- return CallNextHookEx(NULL, nCode, wParam, lParam);
+ return nCode<0 || lMode != MODE_FINAL ? CallNextHookEx(NULL, nCode, wParam, lParam) : -1;
}
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if(nCode==HC_ACTION) {
@@ -163,7 +163,7 @@ LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
} else DEBUG_PRINT(("NATIVE: LowLevelMouseProc - Error on the attach current thread.\n"));
}
- return CallNextHookEx(NULL, nCode, wParam, lParam);
+ return nCode<0 || lMode != MODE_FINAL ? CallNextHookEx(NULL, nCode, wParam, lParam) : -1;
}
LRESULT CALLBACK WndProc(HWND hWndMain, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg){
@@ -291,7 +291,7 @@ static inline _Bool notifyHookObj(JNIEnv *env, size_t hook) {
return TRUE;
}
-static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const char *handleName, const char *handleSig, jboolean raw) {
+static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const char *handleName, const char *handleSig, jint mode) {
DEBUG_PRINT(("NATIVE: registerHook - Hook start\n"));
if(jvm==NULL) (*env)->GetJavaVM(env, &jvm);
@@ -306,8 +306,8 @@ static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const
}
HHOOK hHook; HWND hWnd;
- switch(raw) {
- case JNI_FALSE:
+ switch(lMode=mode) {
+ case MODE_DEFAULT: case MODE_FINAL:
switch(hook) {
case HOOK_KEYBOARD:
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0);
@@ -318,7 +318,7 @@ static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const
}
break;
- case JNI_TRUE: {
+ case MODE_RAW: {
WNDCLASS wndCls = {0};
wndCls.lpfnWndProc = WndProc;
wndCls.hInstance = hInst;
@@ -334,7 +334,7 @@ static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const
if(hHook==NULL&&hWnd==NULL) {
debugPrintLastError("NATIVE: registerHook - Hook failed");
return (jint)E_HOOK_FAILED;
- } else DEBUG_PRINT(("NATIVE: registerHook - %sHook success\n", raw?"Raw ":""));
+ } else DEBUG_PRINT(("NATIVE: registerHook - %sHook success\n", lMode==MODE_RAW?"Raw ":""));
if(!notifyHookObj(env, hook)) {
(*env)->ExceptionClear(env);
@@ -357,11 +357,11 @@ static inline jint registerHook(JNIEnv *env, jobject thisObj, size_t hook, const
return (jint)E_UNHOOK_FAILED;
}
}
-JNIEXPORT jint JNICALL Java_lc_kra_system_keyboard_GlobalKeyboardHook_00024NativeKeyboardHook_registerHook(JNIEnv *env, jobject thisObj, jboolean raw) {
- return registerHook(env, thisObj, HOOK_KEYBOARD, "handleKey", "(IICJ)V", raw);
+JNIEXPORT jint JNICALL Java_lc_kra_system_keyboard_GlobalKeyboardHook_00024NativeKeyboardHook_registerHook(JNIEnv *env, jobject thisObj, jint mode) {
+ return registerHook(env, thisObj, HOOK_KEYBOARD, "handleKey", "(IICJ)V", mode);
}
-JNIEXPORT jint JNICALL Java_lc_kra_system_mouse_GlobalMouseHook_00024NativeMouseHook_registerHook(JNIEnv *env, jobject thisObj, jboolean raw) {
- return registerHook(env, thisObj, HOOK_MOUSE, "handleMouse", "(IIIIIJ)V", raw);
+JNIEXPORT jint JNICALL Java_lc_kra_system_mouse_GlobalMouseHook_00024NativeMouseHook_registerHook(JNIEnv *env, jobject thisObj, jint mode) {
+ return registerHook(env, thisObj, HOOK_MOUSE, "handleMouse", "(IIIIIJ)V", mode);
}
static inline void unregisterHook(size_t hook) {
diff --git a/src/main/native/windows/SystemHook.h b/src/main/native/windows/SystemHook.h
index ae2e975..f97ef19 100644
--- a/src/main/native/windows/SystemHook.h
+++ b/src/main/native/windows/SystemHook.h
@@ -36,6 +36,12 @@ typedef enum {
E_NOTIFY_FAILED = -4
} GlobalHookError;
+typedef enum {
+ MODE_DEFAULT = 0,
+ MODE_FINAL = 1,
+ MODE_RAW = 2
+} GlobalHookMode;
+
typedef enum {
TS_UP = 0,
TS_DOWN = 1,
@@ -48,7 +54,7 @@ typedef enum {
* Method: registerHook
* Signature: (Z)I
*/
-JNIEXPORT jint JNICALL Java_lc_kra_system_keyboard_GlobalKeyboardHook_00024NativeKeyboardHook_registerHook(JNIEnv *,jobject,jboolean);
+JNIEXPORT jint JNICALL Java_lc_kra_system_keyboard_GlobalKeyboardHook_00024NativeKeyboardHook_registerHook(JNIEnv *,jobject,jint);
/*
* Class: GlobalKeyboardHook$NativeKeyboardHook
* Method: unregisterHook
@@ -67,7 +73,7 @@ JNIEXPORT jobject JNICALL Java_lc_kra_system_keyboard_GlobalKeyboardHook_00024Na
* Method: registerHook
* Signature: (Z)I
*/
-JNIEXPORT jint JNICALL Java_lc_kra_system_mouse_GlobalMouseHook_00024NativeMouseHook_registerHook(JNIEnv *,jobject,jboolean);
+JNIEXPORT jint JNICALL Java_lc_kra_system_mouse_GlobalMouseHook_00024NativeMouseHook_registerHook(JNIEnv *,jobject,jint);
/*
* Class: GlobalMouseHook$NativeMouseHook
* Method: unregisterHook