Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX: How to detect mouse/key events anywhere on screen?

I´m trying to catch mouse/key events in Java(fx), even if the application window isn´t focused... I´m creating something like a screenrecorder and I want to stop the recording by pressing a key like "F9", so I need to detect the event. Is this possible? Is there something like a system listener I can use?

~Henri

like image 209
MeineHTMLCodes Avatar asked Dec 24 '22 14:12

MeineHTMLCodes


2 Answers

It is possible but standard Java does not have access to key-strokes or mouse events if the registered component is not in focus.

In order to achieve this you need to use native code via the Java Native Interface (JNI). This enables Java code to call native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C and C++.

Luckily, there is a third party library JNativeHook that was designed exactly for what you need. You can find it here: https://github.com/kwhat/jnativehook

If you are using Maven for dependency management you can install it easily. Here is a working example:

App.java

package com.sotest.globalkeylistener;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;

public class App 
{
    public static void main(String[] args) {
        try {
            GlobalScreen.registerNativeHook();
        }
        catch (NativeHookException ex) {
            System.exit(1);
        }

        GlobalScreen.addNativeKeyListener(new GlobalKeyListener());
    }
}

GlobalKeyListener.java

package com.sotest.globalkeylistener;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class GlobalKeyListener implements NativeKeyListener {

    public void nativeKeyPressed(NativeKeyEvent e) {
        System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

        if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
            try {
                GlobalScreen.unregisterNativeHook();
            } catch (NativeHookException e1) {
                e1.printStackTrace();
            }
        }
    }

    public void nativeKeyReleased(NativeKeyEvent e) {
        System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
    }

    public void nativeKeyTyped(NativeKeyEvent e) {
        System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
    }
}

Key Output: Global key listener output

Mouse Output

Global mouse listener output

This way you can detect the event even if your Java application is minimised.

Hope this helps.

like image 136
Zain Avatar answered Dec 26 '22 02:12

Zain


Unfortunately you cannot do this. JavaFX requires a focused window. There is no easy way to achieve what you want with Java, as it gives you very little control over the OS for security purposes. The best thing to do would be to write a C application to do this, then hook into it from Java using JNI.

You would want to do two things.

  1. Write a C program that listens for global events on your OS. For Windows you can find more info about this on MSDN, and for mac and linux you will need to use the X11 libraries.

  2. Use JNI to link your C code in Java. This isn't as difficult as it may sound, here is a pretty good tutorial on it: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

Of course you don't have to do all that work yourself, there are libraries for just about everything out there. This library does the hard work for you and you can use it to achieve your goal: https://github.com/kwhat/jnativehook

like image 20
BossLetsPlays Avatar answered Dec 26 '22 02:12

BossLetsPlays