X11 - 如何用Python提升另一个应用的窗口

8 投票
3 回答
7772 浏览
提问于 2025-04-15 21:50

我想用Python来提升另一个应用程序的窗口。

我看到这个内容,我想我可以试试:

X11:通过命令行提升一个已有的窗口?

不过,如果可以的话,我更想用Python来实现。

3 个回答

6

你需要使用 python-xlib 这个库,并在窗口对象上调用 .circulate(Xlib.X.RaiseLowest) 方法(这个窗口对象可以通过很多不同的方式来识别——根据你提供的信息,我无法猜测哪种方式适合你;所以这部分就留给你自己去探索了)。如果你想看看如何使用 python-xlib 的一个很好的例子,可以去看看 tinywm 这个窗口管理器——在C语言版本之后,作者还提供了一个Python版本,大约只需要30行非空的、非注释的代码(就能实现一个可用的、虽然很小的 窗口管理器...!-)。

7

你可以看看这个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()
9

要激活另一个窗口,正确的方法是在Xlib协议层发送一个_NET_ACTIVE_WINDOW消息,这个消息的具体内容可以在EWMH规范中找到,链接在这里:http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html

你可以用python-xlib来实现这个功能,或者通过pygtk使用GDK中的gdk_window_focus()来操作其他GdkWindow。

_NET_ACTIVE_WINDOW比XRaiseWindow()更好用,很多重要的窗口管理器(WM)已经使用这个方法很多年了。

你应该避免使用XSetInputFocus(),因为这会引发一些问题,尤其是当你时间戳设置错误时。问题在于窗口管理器无法拦截SetInputFocus(),这会导致一些奇怪的竞争条件和用户界面不一致。

实际上,只有_NET_ACTIVE_WINDOW能正常工作,这也是它被发明的原因,因为之前的解决方案都不好。

有一个叫libwnck的库可以让你激活窗口(还有其他功能),但不幸的是,它会增加很多额外的负担,因为它会一直跟踪所有应用程序打开的窗口,即使你不需要这样做。不过,如果你确实想跟踪其他应用的窗口,libwnck有一个可以激活这些窗口的函数,这样做是正确的,值得考虑。

严格来说,正确的做法是检查是否支持EWMH _NET_ACTIVE_WINDOW(EWMH文档中有说明如何检查),如果窗口管理器不支持_NET_ACTIVE_WINDOW,就退回到使用XRaiseWindow。不过,很多最近几年积极维护的窗口管理器都支持EWMH,所以很多人对老旧窗口管理器的退回处理就比较懒了。

撰写回答