kwhat / jnativehook

Global keyboard and mouse listeners for Java.
Other
1.73k stars 344 forks source link

SIGSEGV when registering hook in JavaFX application #442

Open Vitaspiros opened 1 year ago

Vitaspiros commented 1 year ago

Title basically. I have a JavaFX application that throws SIGSEGV in line GlobalScreen.registerNativeHook();. When I remove that line, it doesn't exit but then the application doesn't work. I am running it with Java 17 on Ubuntu 20.04 64-bit. Also I'm using Maven to build it and JNativeHook 2.2.2. Here's the crash log if that helps: https://pastebin.com/hU6ahhaR

vincemann commented 4 months ago

do it like this

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        // ...all your init stuff

        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            registerHook();
        }).start();
    }

   private void registerHook(){
        try {
            com.github.kwhat.jnativehook.GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            System.err.println("There was a problem registering the native hook.");
            System.err.println(ex.getMessage());

            System.exit(1);
        }
    }
}

Also the problem goes away in old versions: // https://mvnrepository.com/artifact/com.1stleg/jnativehook implementation 'com.1stleg:jnativehook:2.1.0'

Also register your Listeners in the same way:

@Inject
    public GlobalHotKeyListener(EventBus eventBus) {
        this.eventBus = eventBus;
        // ugly workaround for bug in jnativehook - keep it like that
        registerListener();
    }

    private void registerListener(){
        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            GlobalScreen.addNativeKeyListener(this);
        }).start();
    }

Had the same issue, this is my (very pretty) workaround. Works on: openjdk 17.0.8 2023-07-18 LTS Linux debian 5.10.0-28-amd64 #1 SMP Debian 5.10.209-2 (2024-01-31) x86_64 GNU/Linux javafx version 17.0.1

vincemann commented 4 months ago

I ended up simplifying like this: Note that the registration of the listeners should take place in the same thread as hook registration, right after hook registration.


public class Main extends Application{
    @Override
    public void start(Stage primaryStage) throws Exception {
        //  ...
        // only for jnativehook 2.2.2:
        // needs to be run on diff thread, otherwise segfault
        Platform.runLater(this::registerHook);
    }

    private void registerHook() {
        try {
            GlobalScreen.registerNativeHook();
            // must register here bc of thread issues and race conditions in jnativehook
            GlobalScreen.addNativeMouseListener(myMouseListener);
            GlobalScreen.addNativeKeyListener(myHotKeyListener);
        } catch (NativeHookException e) {
            log.error("Failed to register native hook", e);
            System.exit(1);
        }
    }
}