Java – Global (low level) Keyboard / Mouse Hook
by Kristian Kraljic, February 9, 2016
About five years ago I started this blog by picking up an idea of Johannes Schüth (Jotschi) about a global keyboard and mouse listener for Java. Today I am very happy to announce the next major version of the library now available on GitHub!
Keyboard and mouse events in Java only work, if the registered component is in focus. For example, in case a window looses its focus (e.g. when minimized), it stops receiving any more events. Through a low-level system-wide hook it’s possible to deliver those events regardless. You’ll find all sources of the latest release, as well as binary bundles / prepackaged Java archives (JAR) on the GitHub project page.
The old post describes all changes I did to the initial version by Johannes (Jotschi). For the new major release I again reworked nearly every part of the library, to make it more stable and versatile. Here is what I did:
- Optimized the native library C code, fixed bugs and removed all parts requireing a C++ compiler in the first place.
- Renamed the event classes and listener interfaces and prepended
Global
to avoid conflicts with existing (Swing) event listeners. - Added support for
mouseWheel
events to theGlobalMouseListener
. - Again allowed negative "out of bounds" values for
GlobalMouseEvents
, to also track the mouse pointer off screen (e.g. on multi-monitor setups). - Improved the threading concept and implemented a native error handling. The
GlobalKeyboardHook
andGlobalMouseHook
constructors will now throw aUnsatisfiedLinkError
if the native libraries can not be loaded or aRuntimeException
in case hooking fails. - All the code has been moved to GitHub and binaries are now beeing continuously built by AppVeyor. Feel free to contribute on GitHub!
(Again) Last but not least, please share your ideas and problems in the comments. I will try to enhance the Global Keyboard / Mouse Hook based on your feedback. For the next release let’s see if we can get Linux and / or Mac OSX support going.
202 Comments
« Older CommentsNewer Comments »
« Older CommentsNewer Comments »
Hi,
First of thanks for this tutorial. I want a java keyloger which can install in windows silently and start when windows start. Can you tell me how your code works.
No…, no I’m sorry. ;-) Regards, Kristian
Dear Sir,
Is it work in MAC and Linux OS?
Thanks
Sajedur Rahman Tareq
Dear Tareq. No unfortunately not at the moment. I plan to do that.
Regards,
Kristian
Very nicely done, helps alot.
Found one bug however:
I’m using two monitors right now, with the main monitor to the right.
When I move the mose to the left monitor the x value will be 0 over the entire monitor, while it’s expected to show negative values, like java.awt.MouseInfo.
hi Kristian,
thank you so much for you code, that is brilliant. I am using it in my project.
Could you help me add WM_MOUSEWHEEL message in your code? It was a long time since I coded C++.
really appreciate
Thanks you for your work, this is awesome.
btw it seems not working on some maximized application (games etc). Is it possible? Please tell me how.
is there a way that i can use the mouse and keylisner at the same time?
o sorry my fault i had already imported the awt keyevent methet
Very nice code. I have updated your GlobalKeyListener class with the singleton pattern. So only one hook is needed.
/*
* the singleton instance
*/
private static volatile GlobalKeyListener instance = null;
/**
* Returns the singleton instance.
*
* @return the singleton instance.
*/
public synchronized static GlobalKeyListener getInstance() {
// double check locking
if (instance == null) {
synchronized (GlobalKeyListener.class) {
if (instance == null) {
instance = new GlobalKeyListener();
}
}
}
return instance;
}
Hi Kristian,
I am trying to compile your KeyboardHook at the moment with a new getTime method to get a high-resolution time from the system as well as when a key was pressed. However when I am trying to build the lib on a 64bit system I always get an UnsatisfiedLinkError just as you did (no valid Win32 application). I also set the flags as you described (however O0, g3, fmessage-length=0 and mno-cygwin are ignored). I am using MS Visual Studio to compile. It seems to be a compiler problem since most of the flags are ignored. Can you give me and advice?
All the best and thanks,
Chiang
Trying to compile it now with mingw64 with all flags set except -mno-cygwin and I still have the same issue when loading the lib in Java: UnsatisfiedLinkError no valid Win32 application.
compiling like the following: g++ -Wall -c -D_JNI_IMPLEMENTATION_ -Wl,-kill-at -O0 -g3 -fmessage-length=0 -static-libgcc -I”%JAVA_HOME%\include” -m64 -I”%JAVA_HOME%\include\win32″ -shared -o keylib.lib KeyboardHook.cpp
Hi Kristian,
Great library/package. It looks really easy to use.
In addition to Keyboard and Mouse events, I need to when window is locked/unlocked or screen saver comes on. I think they all belong together. Is that something you could add to this library?
Thanks again.
Rahul
Hey Rahul,
the library is just to track keyboard and mouse events, not to track any other system events, such as window locks etc. To track this, you would need to access other low-level API’s of windows.
Regards,
Kristian
How we can capture keypress time by this hook
Hello Kornal,
the simplest solution I can think about right now is to register for both the keyPressed and keyReleased event. Call System.currentTimeMillis() in both and subtract the time from keyPressed from the time taken in keyReleased. This should do the trick.
Regards,
Kristian
Not yet… Sorry for that one.
Hello there!! I have a problem. When I close my application and start again mouse hook doesn’t start. How should I do?
hi , thank you for this a good exercice ;
when i tried to compile this project i have this
Exception in thread “Thread-0” java.lang.UnsatisfiedLinkError: de.ksquared.system.keyboard.KeyboardHook.registerHook(Lde/ksquared/system/keyboard/GlobalKeyListener;)V
at de.ksquared.system.keyboard.KeyboardHook.registerHook(Native Method)
at de.ksquared.system.keyboard.PoolHook.run(KeyboardHook.java:52)
please you can telle me what’s a wrong!
thanks , best regards