X11 - 如何使用 Python 引发另一个应用程序的窗口

发布于 2024-08-29 22:41:27 字数 237 浏览 3 评论 0原文

我希望能够使用 Python 启动另一个应用程序的窗口。

我确实看到了这个,我想我可以尝试:

X11: raise an通过命令行现有窗口?

但是,如果可能的话,我更愿意在 Python 中执行此操作。

I'd like to be able to raise another application's Window using Python.

I did see this, which I suppose I could try:

X11: raise an existing window via command line?

However, I'd prefer to do it in Python if at all possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无声无音无过去 2024-09-05 22:41:27

要激活另一个窗口,在 Xlib 协议层上正确的做法是发送 _NET_ACTIVE_WINDOW 消息,如 EWMH 规范中所述
http://standards.freedesktop.org/wm-spec/wm-spec -1.3.html

这可以通过 python-xlib (大概)或通过 pygtk 使用 GDK 在外国 GdkWindow 上使用 gdk_window_focus() 来完成

_NET_ACTIVE_WINDOW 优于 XRaiseWindow() 并且已经出现在许多重要的 WM 中年。

您应该避免 XSetInputFocus() ,这会导致问题(特别是如果您的时间戳错误)。问题是 WM 无法拦截 SetInputFocus(),因此会导致奇怪的竞争条件和 UI 不一致。

实际上只有 _NET_ACTIVE_WINDOW 可以正常工作,这就是它被发明的原因,因为以前的 hack 很糟糕。

有一个名为 libwnck 的库,可以让您激活窗口(除其他外),但不幸的是,它增加了相当多的开销,因为它总是跟踪任何应用程序中所有打开的窗口,即使您不需要这样做。但是,如果您想从其他应用程序跟踪窗口,无论如何,那么 libwnck 有一个函数可以激活那些执行正确操作的窗口,这将是一个不错的选择。

严格正确的方法是检查 EWMH _NET_ACTIVE_WINDOW 支持(EWMH 文档说明了如何执行此操作),如果 WM 没有 _NET_ACTIVE_WINDOW,则回退到 XRaiseWindow。然而,由于过去许多年积极开发的 WM 都具有 EWMH,因此许多人对传统 WM 的回退感到懒惰。

To activate another window, the right thing to do on the Xlib protocol layer is to send a _NET_ACTIVE_WINDOW message as described in the EWMH spec
http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html

This could be done with python-xlib (presumably) or with gdk_window_focus() on a foreign GdkWindow using GDK through pygtk

_NET_ACTIVE_WINDOW is superior to XRaiseWindow() and has been in all the important WMs for many many years.

You should avoid XSetInputFocus() which will cause problems (especially if you get the timestamp wrong). The issue is that the WM can't intercept the SetInputFocus() so it causes weird race conditions and UI inconsistencies.

Really only _NET_ACTIVE_WINDOW works properly, which is why it was invented, because the previous hacks were bad.

There is a library called libwnck that will let you activate windows (among other things) but unfortunately it adds quite a lot of overhead because it always tracks all open windows from any app, even if you don't need to do that. However if you want to track windows from other apps anyway, then libwnck has a function to activate those windows that does the right thing and would be a good choice.

The strictly correct approach is to check for EWMH _NET_ACTIVE_WINDOW support (EWMH documents how to do this) and fall back to XRaiseWindow if the WM doesn't have _NET_ACTIVE_WINDOW. However, since any WM that's been actively worked on in the last many years has EWMH, lots of people are lazy about the fallback for legacy WMs.

明媚如初 2024-09-05 22:41:27

您可以查看python ewmh 包文档包含示例,但以下是实现您想要的效果的方法:

from ewmh import EWMH
import random
ewmh = EWMH()

# get every displayed windows
wins = ewmh.getClientList()

# let's active one window randomly
ewmh.setActiveWindow(random.choice(wins))

# flush requests - that's actually do the real job
ewmh.display.flush()

You can have a look at the python ewmh package. Documentation contains examples, but here is how you can achieve what you want:

from ewmh import EWMH
import random
ewmh = EWMH()

# get every displayed windows
wins = ewmh.getClientList()

# let's active one window randomly
ewmh.setActiveWindow(random.choice(wins))

# flush requests - that's actually do the real job
ewmh.display.flush()
杀お生予夺 2024-09-05 22:41:27

您需要使用 python-xlib 并调用 .circulate(Xlib.X.RaiseLowest)< /code> 窗口对象(可以通过很多很多不同的方式来识别 - 无法从 Q 中有关它的零信息中猜测哪一个适合您;-)。有关使用 python-xlib 的绝佳示例,请查看 tinywm 窗口管理器-- 在 C 版本之后,作者给出了一个 Python 版本,该版本需要大约 30 个非空白、非注释行(对于一个可用的,虽然很小的窗口管理器...!-)。

You need to use python-xlib and call .circulate(Xlib.X.RaiseLowest) on the window object (which can be identified in many, many different ways -- can't guess which one is appropriate for you from the zero amount of info about it in your Q;-). For a great example of using python-xlib, check out the tinywm window manager -- after the C version, the author gives a Python version that takes about 30 non-blank, non-comment lines (for a usable, if tiny, window manager...!-).

因为看清所以看轻 2024-09-05 22:41:27

使用 python-xlib

# https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#id-1.4.10
from Xlib.xobject.drawable import Window
from Xlib.display import Display
from Xlib.protocol.event import ClientMessage
from Xlib.X import AnyPropertyType
from Xlib import X

display: Display = Display()
root: Window | None = display.screen().root
if root is None:
    raise NotImplementedError()

# your window hex id from wmctrl -l
hex_id = "0x07c0000c"

xwin: Window = display.create_resource_object('window', int(hex_id, 16))

# `source` is set to 1 with lib pyewmh but not working on KDE 5.103.0.
# When set to 0 it works on my system
source: int = 0
timestamp: int = X.CurrentTime
currently_active_window: int = 0
ev = ClientMessage(
    window=xwin,
    client_type=display.get_atom("_NET_ACTIVE_WINDOW"),
    data=(32, [source, timestamp, currently_active_window, 0, 0]))

root.send_event(
    ev,
    event_mask=(X.SubstructureRedirectMask | X.SubstructureNotifyMask))

display.flush()

Using python-xlib:

# https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#id-1.4.10
from Xlib.xobject.drawable import Window
from Xlib.display import Display
from Xlib.protocol.event import ClientMessage
from Xlib.X import AnyPropertyType
from Xlib import X

display: Display = Display()
root: Window | None = display.screen().root
if root is None:
    raise NotImplementedError()

# your window hex id from wmctrl -l
hex_id = "0x07c0000c"

xwin: Window = display.create_resource_object('window', int(hex_id, 16))

# `source` is set to 1 with lib pyewmh but not working on KDE 5.103.0.
# When set to 0 it works on my system
source: int = 0
timestamp: int = X.CurrentTime
currently_active_window: int = 0
ev = ClientMessage(
    window=xwin,
    client_type=display.get_atom("_NET_ACTIVE_WINDOW"),
    data=(32, [source, timestamp, currently_active_window, 0, 0]))

root.send_event(
    ev,
    event_mask=(X.SubstructureRedirectMask | X.SubstructureNotifyMask))

display.flush()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文