1

Xlib メッセージを送信して Linux 上のアプリケーション ウィンドウを操作するために JNA を使用していますが、ウィンドウを移動できないようです。

私の元の実装では、シェルで wmctrl を実行してウィンドウを移動し、ウィンドウを正常に移動しました。残念ながら、Java からのシェル プログラムの呼び出しに関連するかなりの量のオーバーヘッドがあるため、現在、JNA を使用して直接 API 呼び出しを行うことを試みています。私は JNA Web サイトから入手できる X11 の例を使用しており、ウィンドウ ID の列挙やウィンドウ プロパティの読み取りなど、いくつかのトリックを正常に実行できるため、JNA+Xlib が少なくとも部分的に機能していることがわかります。

最初に使用してウィンドウを直接移動しようとしましたXMoveWindow()が、ウィンドウマネージャーがそれらの呼び出しをブロックしていたようです。

を使用してクライアント メッセージを送信する必要があることを示唆するスレッドに出くわしたので、以下で実行しましたが、ウィンドウが移動せず、戻り値が返されるため、XSendMessage()明らかに失敗しています。明らかなことを省略したと思いますが、それを完全に理解することはできません。助言がありますか?XSendMessage()0

この例では、main メソッドにはウィンドウ ID がハードコーディングされていることに注意してください。これは、移動しようとしているウィンドウのウィンドウ ID です (wmctrl -lコンソールで使用して取得)。

import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.examples.unix.X11;
import com.sun.jna.examples.unix.X11.Atom;
import com.sun.jna.examples.unix.X11.AtomByReference;
import com.sun.jna.examples.unix.X11.Display;
import com.sun.jna.examples.unix.X11.Window;
import com.sun.jna.examples.unix.X11.WindowByReference;
import com.sun.jna.examples.unix.X11.XEvent;
import com.sun.jna.examples.unix.X11.XTextProperty;
import com.sun.jna.examples.unix.X11.XWindowAttributes;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;

private static final int FALSE = 0; /** C-style boolean "false" */
private static final int TRUE  = 1; /** C-style boolean "true" */

public static void main(String[] args) {
    setWindowPos(new Window(0x01300007), 100, 100, 600, 400); // update the Window constructor with the appropriate ID given by wmctrl -l
}


public static boolean setWindowPos(Window window, int x, int y, int w, int h) {
    final X11 x11 = X11.INSTANCE;
    Display display = x11.XOpenDisplay(null);

    NativeLong mask = new NativeLong(X11.SubstructureRedirectMask | X11.SubstructureNotifyMask | X11.ResizeRedirectMask);

    XEvent event = new XEvent();

    String msg = "_NET_MOVERESIZE_WINDOW"; //$NON-NLS-1$

    long grflags = 0l; // use the default gravity of the window
    if (x != -1) grflags |= (1 << 8);
    if (y != -1) grflags |= (1 << 9);
    if (w != -1) grflags |= (1 << 10);
    if (h != -1) grflags |= (1 << 11);

    event.xclient.type = X11.ClientMessage;
    event.xclient.serial = new NativeLong(0l);
    event.xclient.send_event = TRUE;
    event.xclient.message_type = x11.XInternAtom(display, msg, false);
    event.xclient.window = window;
    event.xclient.format = 32;
    event.xclient.data.l[0] = new NativeLong(grflags); // gravity flags
    event.xclient.data.l[1] = new NativeLong(x);
    event.xclient.data.l[2] = new NativeLong(y);
    event.xclient.data.l[3] = new NativeLong(w);
    event.xclient.data.l[4] = new NativeLong(h);

    int status = x11.XSendEvent(display, x11.XDefaultRootWindow(display), FALSE, mask, event);
    x11.XFlush(display); // need to XFlush if we're not reading X events

    if (status == 0) { // 0 indicates XSendEvent failed
        logger.error("setWindowPos: XSendEvent failed (" + msg + ")"); //$NON-NLS-1$
        return false;
    }

    return true;
}
4

2 に答える 2

3

これは少し遅い答えかもしれませんが、とにかく...

ウィンドウを移動しようとすると、ウィンドウ(「クライアント」と呼ばれる)がXConfigureRequestをウィンドウマネージャーに送信します。これは、ウィンドウマネージャーがXサーバーに自分が上司であることを通知するために発生します(クライアントの親に部分構造オーバーライドフラグを設定することにより)。

これを回避する唯一の方法は、クライアントにオーバーライドリダイレクトフラグを設定し、移動を実行して、オーバーライドリダイレクトフラグを無効にすることです(すべてが「通常」に戻るようにします)。

GL HF。

于 2011-04-22T11:16:03.363 に答える
1

XConfigureWindow を見たことがありますか?

今夜実装したばかりで、Windowsで開発しているので、実際にはまだテストしていませんが、試してみる価値はあります....

public static interface X11Ext extends Library
    {
        public static X11Ext INSTANCE = (X11Ext)Native.loadLibrary("X11", X11Ext.class);

        public int XConfigureWindow(X11.Display display, X11.Window window, int value_mask, XWindowChanges changes);

        /**
         * Use value_mask flags:
         * CWX
         * CWY
         * CWWidth
         * CWHeight
         * CWBorderWidth
         * CWSibling
         * CWStackMode
         */
        public class XWindowChanges extends Structure
        {
            public int x;
            public int y;
            public int width;
            public int height;
            public int border_width;
            public X11.Window sibling;
            public int stack_mode;
        }
    }
于 2010-03-13T06:50:08.663 に答える