Kristian Kraljić You may compare programming with poetry,
a harmonic script is a piece of creativity which will last forever.
- Kristian Kraljić

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!

system-hook-logo

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 the GlobalMouseListener.
  • 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 and GlobalMouseHook constructors will now throw a UnsatisfiedLinkError if the native libraries can not be loaded or a RuntimeException 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

  1. Ladislav says:

    Hi Kristian, library is really cool, thanks for it
    is there a way to capture key pressed in the ssh terminal?
    Like moba xterm?

    • Hey Ladislav, it higly depends how your SSH Terminal captures keypresses. In case the terminal you are using (e.g. moba xterm) is also using the low level hook functionallity used in this library and they do not forward the event to downstream listeners it’ll not work. The Windows low-level hook works much like a chain of events. It depends on the order of when the handler has been registered. E.g. if you start the global system hook first, then run the terminal, your handler will be registered first and will capture the event. If the event is not even captured then, it is cached at an “even lower” level. Then there is one option left, if you enable the “raw” option in the constructor, an even lower level API of windows will be used to capture the input events. Hope this helps! Regards, Kristian

  2. John says:

    Hi, How could I have an error:
    Exception in thread “main” java.lang.UnsatisfiedLinkError: lib: systemhook-windows-amd64.dll not found in lib directory
    at lc.kra.system.LibraryLoader.loadLibrary(LibraryLoader.java:86)
    at lc.kra.system.keyboard.GlobalKeyboardHook.(GlobalKeyboardHook.java:113)
    at lc.kra.system.keyboard.GlobalKeyboardHook.(GlobalKeyboardHook.java:101)

    what should I do?

  3. shui says:

    can you tell us why are we getting )
    Caused by: org.apache.tools.ant.BuildException: The following error occurred whi
    le executing this line:
    j:\system-hook-master\build.xml:109: gcc failed
    with return code 1

    thanks,

    • Please make sure you have a C99 compatible compiler / linker installed to build the native libraries, see MSYS2. Also please note that you can only build the libraries on Windows!

  4. Víctor says:

    Hey, I’m working on a project for which i need absolute position for trackpad contact. Meaning, i want ot use my laptop’s trackpad as a drawing tablet.

    I know it is possible, since I already tested a linux version I made myself, so I am sure that the hardware sends the data. However, porting it to windows has turned out to be quite difficult.

    This library however, is the closest thing I have found to what I need. I was wondering if there is any way of getting this data using your library, instead of pointer coordinates or relative motion. I mean, if I touch the top left corner of the trackpad I should get (0, 0) and if I touch any other point I should get the respective coordinates.

    If not, is there anyway you think I could modify its source in order to get the result I want?

    Thank you for your time.

    • Hey Victor, glad you are considering to be using my library. Generally the library is based on two different mechanisms to capture input: LowLevelMouseProc and WndProc with a RIDEV_INPUTSINK (and a usUsage = 2 to capture mouse inputs). The WndProc can be enabled by setting raw = true the Java library. These are two low-level Windows functions, you can check out in the SystemHook.c implementation file. Please refer to the Microsoft documentation to find details, what information is provided by the low-level functions of LowLevelMouseProc and RAWINPUTDEVICE. In case the information you are looking for is generally provided by the low-level APIs, it should be pretty simple to pass them onto my Java listener. Hope this helps!

  5. rok says:

    Hi, I’m using your library on a small project, where I need to capture all the events on the external screen. Your library works great for mouse, you really did an awesome job here. But I have a problem with touch – is there anyway that I could hook to touch events as well? Treating taps as mouse clicks isn’t an option btw. Thanks.

    • Hey Rok, sorry for my late reply. Currently the library does not support touch input. I assume that the Windows library treats touch inputs as another type of event. Unfortunately on my side, I don’t even own a device, which I would be able to test the touch support with, thus I don’t think I will be able to add it anytime soon. Feel free to add a issue on he JSystemHook GitHub page though and I maybe will treat it as a feature to implement in any of the next releases. Sorry for that & best regards, Kristian

  6. Vincenzo says:

    Hi Kristian,
    I did a smal project using your library to intercept the input form a barcode scanner and it works like a charm on windows but when I tryied to install it on my raspberry pi I got the error

    java.lang.UnsatisfiedLinkError: lib: libsystemhook-linux-arm.so not found in lib directory

    So than I understood there was no support for linux… :(
    Are you actually working on it, or you can suggest me the right direction to build the libsystemhook library on my own for linux arm?

    Thanks

    • Hey Vincenzo, unfortunately I am currently unable to work on any of my open source projects, due to some personal time constraints. Thus I am also not working on a Linux port for my Java system hook library. Unfortunately the library is not easy to “cross-compile”, as the system libraries to capture keyboard / mouse inputs differ between operating systems. For Linux a reimplementation of the native part of my library would be required. Have a look into the native Windows part if you want to know more. Also there are a couple of ways to deal with it on Linux. E.g. one could hook into the X window system, to capture mouse and keyboard events, however that wouldn’t cover every Linux distribution. If you seriously consider contributing Linux support, let’s have another chat, discussing the options.