使用JNA XLib在X11环境中获取所有Windows

时间:2014-07-22 21:49:55

标签: java linux x11 jna xlib

基本上我的目标是获取所有窗口(我正在谈论每一个窗口,而不是附加到我的程序中的窗口)并将它们编译成列表。我正在尝试使我的应用程序尽可能跨平台友好,所以我正在为Windows和Linux移植JNA。在Windows中使用JNA非常简单容易。但是,JNA使用XLib时缺少文档和示例并没有使编码过程变得更容易。

This question, regarding to coding with XLib in C++,确实提供了如何使用XLib在X11环境中获取窗口的一些信息。 我基本上需要在Java中实现XQueryTree 。我缺乏知识使我无法轻易地使用此代码,因为我在Java中编码。我从来没有用C ++编写代码,也没试过用XLib编写代码。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

XQueryTree在platform.jar中定义。

int XQueryTree(Display display, Window window, WindowByReference root, WindowByReference parent, PointerByReference children, IntByReference childCount);

使用XOpenDisplay()获取显示。

由于您需要所有窗口,因此您应该使用根窗口作为父窗口(使用XRootWindow()进行查找)。

通话结束后,children.getValue()将有一个指向窗口ID块的指针;在root用户,这些是原生long类型,因此请基于Pointer.getIntArray(0, size)使用Pointer.getLongArray(0, size)Native.LONG_SIZE,其中sizechildCount中返回的值}。然后,您可以使用该ID数组来初始化可能传递给其他X11函数的Window个对象。

使用XFree后,您需要手动释放返回的阵列内存。

答案 1 :(得分:1)

我发现我需要减速。在Ubuntu 16.04中,许多Windows并没有直接从顶层生成,而是出现了几层...例如

null
  null
    xeyes
null
  null
    user@user-virtual-machine: ~
null
  null
    workspace-test - Java - JnaTest/src/FindWindows.java - Eclipse 
  • 有时候childrenRef返回null

代码

public static void main(String[] args) {
    X11 x11 = X11.INSTANCE;
    Display display = x11.XOpenDisplay(null);

    Window root = x11.XDefaultRootWindow(display);
    recurse(x11, display, root, 0);
}

private static void recurse(X11 x11, Display display, Window root, int depth) {
    X11.WindowByReference windowRef = new X11.WindowByReference();
    X11.WindowByReference parentRef = new X11.WindowByReference();
    PointerByReference childrenRef = new PointerByReference();
    IntByReference childCountRef = new IntByReference();

    x11.XQueryTree(display, root, windowRef, parentRef, childrenRef, childCountRef);
    if (childrenRef.getValue() == null) {
        return;
    }

    long[] ids;

    if (Native.LONG_SIZE == Long.BYTES) {
        ids = childrenRef.getValue().getLongArray(0, childCountRef.getValue());
    } else if (Native.LONG_SIZE == Integer.BYTES) {
        int[] intIds = childrenRef.getValue().getIntArray(0, childCountRef.getValue());
        ids = new long[intIds.length];
        for (int i = 0; i < intIds.length; i++) {
            ids[i] = intIds[i];
        }
    } else {
        throw new IllegalStateException("Unexpected size for Native.LONG_SIZE" + Native.LONG_SIZE);
    }

    for (long id : ids) {
        if (id == 0) {
            continue;
        }
        Window window = new Window(id);
        X11.XTextProperty name = new X11.XTextProperty();
        x11.XGetWMName(display, window, name);

        System.out.println(String.join("", Collections.nCopies(depth, "  ")) + name.value);
        x11.XFree(name.getPointer());

        recurse(x11, display, window, depth + 1);
    }
}