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 »
Hey! Thanks a lot to Timo, Thomas, Byron, Lucas, Jason and Frank.
You were absolutely right. I have compiled the library using a 64-bit JVM (Java 7.0) and tested it on Windows Vista & 7 (x64). Everything should work fine now.
Please let me know if you encounter any further issues (especially with the dependencies Thomas mentioned).
I have this problem at compilation
C:\MouseHook\src\MouseHook>javac c:\MouseHook\test\de\ksquared\test\system\mouse\MouseHookTest.java
.\de\ksquared\system\mouse\GlobalMouseListener.java:35: cannot find symbol
symbol : class PoolHook
location: class de.ksquared.system.mouse.GlobalMouseListener
protected PoolHook hook;
^
.\de\ksquared\system\mouse\MouseAdapter.java:32: method does not override a method from its superclass
@Override public void mouseMoved(MouseEvent event) {}
^
.\de\ksquared\system\mouse\MouseAdapter.java:33: method does not override a method from its superclass
@Override public void mousePressed(MouseEvent event) {}
^
.\de\ksquared\system\mouse\MouseAdapter.java:34: method does not override a method from its superclass
@Override public void mouseReleased(MouseEvent event) {}
^
.\de\ksquared\system\mouse\GlobalMouseListener.java:36: cannot find symbol
symbol : class PoolHook
location: class de.ksquared.system.mouse.GlobalMouseListener
public GlobalMouseListener() { (hook=new PoolHook(this)).start(); }
^
5 errors
thanks
Alright heres how to solve the Unsatisfied Link thing:
Download the libraries. Then load the *.dll (beware of 64bit and 32bit OS)
f.e.:
add line directly under your main method:
System.load(“C:\\Downloads\\mousehook-win-amd64.dll”)
Hi, great piece of software! However, I would like to use keyboardhook on MAC OS X as well. Is it possible, can you compile libraries for other platforms? In your JAVA code, it seems to be prepared for other platforms.
Thanks a lot for great work!
V.
@rachid: The Java code is valid. There is no reason why there should be a compilation problem with it. Make sure you are using at least Java 6 and that the .jar file of the library is in your build path.
@derstormi: With version 0.3 nobody should have the “Unsatisfied” link error anymore. The method you suggested is basically correct, but in version 0.3 this is done automatically and platform independent. Your suggestion would only work on your computer, because you used a relative path and only on Windows x64 installations, because you didn’t check the processor’s architecture. This is all done by the “Native”-class automatically and without including the library files manually.
@wojtaw: Thanks! ;-) Anyways, generally as you said, the Java code is prepared to run on other platforms. Unfortunately compiling the C++ classes on Mac or Linux will not work. At the moment the library uses native Windows libraries to “hook” into the system. In Unix you will need to use a different method to read the mouse position and/or keyboard state. I plan to include all Unix based systems in future as well. Stay tuned for the new version.
Regards, Kristian
i have the unsatisfied link error with the code shown above like i see it now
btw:
i clicked “view raw code” and copied it into the files
Alright, I see. That would be great if working on other platforms. Keep me updated! Do you have any kind of donate button? I would like to send you some donation, if you would help me to run my app on Mac etc…
@derstormi: Please use the .jar file from the “Binary & example build” package, instead of just copying the source from the raw display. The Native-class loads the required libraries automatically if they are available. They are already included into the bundled jar files. Otherwise you would have to add the libraries manually to your project and adapt the Native-class to match the new relative path.
Adding another System.load() command using an absolute path is quite a bad idea when thinking about distributing your application.
@wojtaw: For sure, I will keep you updated. Please feel free to use the subscribe button below the comment area, so will be notified automatically. I would greatly appreciate a donation. Check out the about-page for details. Thank in advance for your support! :-)
if i use the binary & example build, am i able to vary the content?
want to make a mouse click counter with that, so i need the code, not the jar
@guest: Please check the Binary & example bundle. You do not need to modify any of the framework code to realize your task. The framework implements the so called “observer pattern”, so you are able to add a listener and “listen” to global mouse click events.
Hi…
I’m trying to read a scanner input by using your code… it works perfectly fine but I coudn’t find the virtual key for enter as my scanner put an ENTER at the end of code
What I’m want to do is :
((char) event.getVirtualKeyCode()==VK_ENTER)
{
add all the codes to gather in one string variable..
}
but am not able to find out the virtual key code for Enter key..
any help would be greatly appreciated…