gpt4 book ai didi

java - 通过 JNA 使用 Xlib 移动窗口

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:50 25 4
gpt4 key购买 nike

我正在使用 JNA 通过发送 Xlib 消息来操纵 Linux 上的应用程序窗口,但似乎无法移动窗口。

我的原始实现在 shell 上执行 wmctrl 来移动窗口并成功移动了窗口。不幸的是,从 Java 调用 shell 程序会产生大量开销,所以现在我尝试使用 JNA 进行直接 API 调用。我正在使用 JNA 网站上提供的 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;
}

最佳答案

这可能是一个迟到的答案,但无论如何......

当您尝试移动窗口时发生的事情是窗口(称为“客户端”)向窗口管理器发送 XConfigureRequest。发生这种情况是因为窗口管理器告诉 X 服务器他是老板(通过在客户端的父级上设置子结构覆盖标志)。

绕过它的唯一方法是在您的客户端上设置覆盖重定向标志,执行移动,并禁用覆盖重定向标志(以便一切恢复“正常”)。

gl 和 hf。

关于java - 通过 JNA 使用 Xlib 移动窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2391043/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com