如何在linux中检测窗口状态?

时间:2016-05-03 12:19:22

标签: linux java-native-interface ubuntu-14.04 x11 jna

我需要找出在java程序中是否最大化或最小化本机linux应用程序窗口。 我尝试使用X11.XGetWindowProperty(),我也得到了一些结果,但我无法在其中找到任何有用的信息。

我在Ubuntu 14.04 LTS上使用JNA 4.2.1,Java 8 update72。任何指针都会非常有用。在此先感谢所有人。

[编辑]

我有下面的代码,它给了我需要的结果。但是每次调用的结果都不一样。为窗口返回的原子在调用中有所不同。有没有其他可靠的方法来获得窗口状态?

private static X11 x11 = X11.INSTANCE;
private static Display dispy = x11.XOpenDisplay(null);

public static void main(String[] args) {

    try {
        X11.Atom[] atoms = getAtomProperties(
                bytesToInt(getProperty(X11.XA_ATOM, X11.INSTANCE.XInternAtom(dispy, "_NET_WM_STATE", false))));

        boolean hidden = false;
        boolean vmax = false;
        boolean hmax = false;

        for (int i = 0; i < atoms.length; i++) {
            X11.Atom atom = atoms[i];
            if (atom == null)
                continue;

            String atomName = X11.INSTANCE.XGetAtomName(dispy, atom);
            if ("_NET_WM_STATE_HIDDEN".equals(atomName)) {
                hidden = true;
            } else if ("_NET_WM_STATE_MAXIMIZED_VERT".equals(atomName)) {
                vmax = true;
            } else if ("_NET_WM_STATE_MAXIMIZED_HORZ".equals(atomName)) {
                hmax = true;
            }
        }

        if (hidden)
            System.out.println("Window minimized");
        else if (vmax && hmax && !hidden)
            System.out.println("Window maximized");
        else
            System.out.println("Window normal");
    } catch (X11Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private static X11.Atom[] getAtomProperties(int[] ids) {
    X11.Atom[] atoms = new X11.Atom[ids.length];
    for (int i = 0; i < ids.length; i++) {
        if (ids[i] == 0)
            continue;
        atoms[i] = new X11.Atom(ids[i]);
    }
    return atoms;
}

private static int[] bytesToInt(byte[] prop) {
    if (prop == null)
        return null;
    int[] res = new int[prop.length / 4];
    for (int i = 0; i < res.length; i++) {
        res[i] = ((prop[i * 4 + 3] & 0xff) << 24) | ((prop[i * 4 + 2] & 0xff) << 16) | ((prop[i * 4 + 1] & 0xff) << 8)
                | ((prop[i * 4 + 0] & 0xff));

        if (res[i] != 0)
            continue;
    }
    return res;
}

private static byte[] getProperty(X11.Atom xa_prop_type, X11.Atom xa_prop_name) throws X11Exception {

    X11.Window window = new X11.Window(73400355);

    X11.AtomByReference xa_ret_type_ref = new X11.AtomByReference();
    IntByReference ret_format_ref = new IntByReference();
    NativeLongByReference ret_nitems_ref = new NativeLongByReference();
    NativeLongByReference ret_bytes_after_ref = new NativeLongByReference();
    PointerByReference ret_prop_ref = new PointerByReference();

    NativeLong long_offset = new NativeLong(0);
    NativeLong long_length = new NativeLong(4096 / 4);

    /*
     * MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage):
     *
     * long_length = Specifies the length in 32-bit multiples of the data to be retrieved.
     */
    if (x11.XGetWindowProperty(dispy, window, xa_prop_name, long_offset, long_length, false, xa_prop_type, xa_ret_type_ref,
            ret_format_ref, ret_nitems_ref, ret_bytes_after_ref, ret_prop_ref) != X11.Success) {
        String prop_name = x11.XGetAtomName(dispy, xa_prop_name);
        throw new X11Exception("Cannot get " + prop_name + " property.");
    }

    X11.Atom xa_ret_type = xa_ret_type_ref.getValue();
    Pointer ret_prop = ret_prop_ref.getValue();

    if (xa_ret_type == null) {
        // the specified property does not exist for the specified window
        return null;
    }

    if (xa_ret_type == null || xa_prop_type == null || !xa_ret_type.toNative().equals(xa_prop_type.toNative())) {
        x11.XFree(ret_prop);
        String prop_name = x11.XGetAtomName(dispy, xa_prop_name);
        throw new X11Exception("Invalid type of " + prop_name + " property");
    }

    int ret_format = ret_format_ref.getValue();
    long ret_nitems = ret_nitems_ref.getValue().longValue();

    // null terminate the result to make string handling easier
    int nbytes;
    if (ret_format == 32)
        nbytes = Native.LONG_SIZE;
    else if (ret_format == 16)
        nbytes = Native.LONG_SIZE / 2;
    else if (ret_format == 8)
        nbytes = 1;
    else if (ret_format == 0)
        nbytes = 0;
    else
        throw new X11Exception("Invalid return format");
    int length = Math.min((int) ret_nitems * nbytes, 4096);

    byte[] ret = ret_prop.getByteArray(0, length);

    x11.XFree(ret_prop);
    return ret;
} 

0 个答案:

没有答案
相关问题