Search code examples
javax11jna

What is the correct JNA mapping for XGetInputFocus


I am trying to map X11 XGetInputFocus through JNA. The original method signature is

XGetInputFocus(Display *display, Window *focus_return, int *revert_to_return)

Which I assumed could be mapped to the following in Java, using the already defined JNA platform types.

void XGetInputFocus(Display display, Window focus_return, IntByReference revert_to_return);

Which correlates to the recommendation described in the documentation. I now invoke it using the following code

final X11 XLIB = X11.INSTANCE;
Window current = new Window();
Display display = XLIB.XOpenDisplay(null);
if (display != null) {
   IntByReference revert_to_return = new IntByReference();
   XLIB.XGetInputFocus(display, current, revert_to_return);
}

However, it crashes the JVM with

# Problematic frame:
# C  [libX11.so.6+0x285b7]  XGetInputFocus+0x57

What am I missing?


Solution

  • In the native X11 function

    XGetInputFocus(Display *display, Window *focus_return, int *revert_to_return)
    

    the parameter Window *focus_return is used to return a Window. JNA implemented Window very much like an immutable type, because in C language it is defined by typedef XID Window;. Therefore type Window* in C needs to be mapped to WindowByReference in JNA.
    (This is essentially the same reason why int* in C needed to be mapped to IntByReference in JNA.)

    Then the extended X11 interface can look like this:

    public interface X11Extended extends X11 {
        X11Extended INSTANCE = (X11Extended) Native.loadLibrary("X11", X11Extended.class);
    
        void XGetInputFocus(Display display, WindowByReference focus_return, IntByReference revert_to_return);
    }
    

    And your code should be modified accordingly:

    X11Extended xlib = X11Extended.INSTANCE;
    WindowByReference current_ref = new WindowByReference();
    Display display = xlib.XOpenDisplay(null);
    if (display != null) {
        IntByReference revert_to_return = new IntByReference();
        xlib.XGetInputFocus(display, current_ref, revert_to_return);
        Window current = current_ref.getValue();
        System.out.println(current);
    }
    

    Now the program doesn't crash anymore. For me it prints 0x3c00605.