使用 Python xlib 在活动 X 窗口更改时获取通知 [英] Get notifications when active X window changes using Python xlib

查看:35
本文介绍了使用 Python xlib 在活动 X 窗口更改时获取通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想监视在运行 X 的 Linux 系统上哪个窗口处于活动状态,以及该活动窗口何时调整大小或移动.我可以监视活动窗口(它保存在根窗口的 _NET_ACTIVE_WINDOW 属性中,我可以在根窗口上注册 PropertyNotify 事件以发现该属性何时发生变化).但是,我不知道如何监视活动窗口以了解它是否被调整大小或移动.

I'd like to monitor which window is active on a Linux system running X, and when that active window gets resized or moved. I can monitor the active window (it's held in the _NET_ACTIVE_WINDOW property on the root window, and I can register for PropertyNotify events on the root window to discover when that property changes). However, I don't know how to monitor the active window to know whether it gets resized or moved.

import Xlib
import Xlib.display

disp = Xlib.display.Display()
Xroot = disp.screen().root
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
Xroot.change_attributes(event_mask=Xlib.X.PropertyChangeMask)

while True:
    # loop until an event happens that we care about
    # we care about a change to which window is active
    # (NET_ACTIVE_WINDOW property changes on the root)
    # or about the currently active window changing
    # in size or position (don't know how to do this)
    event = disp.next_event()
    if (event.type == Xlib.X.PropertyNotify and
            event.atom == NET_ACTIVE_WINDOW):
        active = disp.get_input_focus().focus
        try:
            name = active.get_wm_class()[1]
        except TypeError:
            name = "unknown"
        print("The active window has changed! It is now", name)

有没有办法做到这一点?它可能涉及侦听当前活动窗口上的 ConfigureNotify 事件(并在该窗口变为活动状态时调用 change_attributes 以设置适当的掩码),但我无法让它工作.

Is there a way to do this? It might involve listening to ConfigureNotify events on the currently active window (and calling change_attributes on that window when it becomes active to set an appropriate mask), but I can't get this to work.

(注意:我没有使用 Gtk,所以请不要使用 Gtk 解决方案.)

(Note: I'm not using Gtk, so no Gtk solutions, please.)

更新:通过观察活动窗口的 _NET_WM_OPAQUE_REGION 属性值变化(因为我正确接收到 PropertyChange 事件),有一种相当可疑的方法来检测窗口 调整大小,虽然我没有收到 ConfigureNotify 事件).然而,并不是所有的窗口管理器都设置了这个属性,而且这只会在窗口大小调整时改变;它不会随着窗口移动而改变(也不会改变任何其他属性).

Update: there is a rather suspect approach to detecting window resizes, by watching the active window for the value of the _NET_WM_OPAQUE_REGION property changing (since I correctly receive PropertyChange events, although I don't receive ConfigureNotify events). However, it's not clear that all window managers set this property, and this only changes on a window resize; it does not change on a window move (and nor does any other property).

推荐答案

这样做的方法是在根窗口选择SubstructureNotifyMask,然后读取所有ConfigureNotify> 事件并忽略那些不是我们关心的窗口的事件,因此:

The way to do this is to select for SubstructureNotifyMask on the root window, and then read all ConfigureNotify events and ignore those that are not for the window we care about, thus:

import Xlib
import Xlib.display

disp = Xlib.display.Display()
Xroot = disp.screen().root
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
Xroot.change_attributes(event_mask=Xlib.X.PropertyChangeMask |
                        Xlib.X.SubstructureNotifyMask)

windows = []

while True:
    # loop until an event happens that we care about
    # we care about a change to which window is active
    # (NET_ACTIVE_WINDOW property changes on the root)
    # or about the currently active window changing
    # in size or position (ConfigureNotify event for
    # our window or one of its ancestors)
    event = disp.next_event()
    if (event.type == Xlib.X.PropertyNotify and
            event.atom == NET_ACTIVE_WINDOW):
        active = disp.get_input_focus().focus
        try:
            name = active.get_wm_class()[1]
        except TypeError:
            name = "unknown"
        print("The active window has changed! It is now", name)

        # Because an X window is not necessarily just what one thinks of
        # as a window (the window manager may add an invisible frame, and
        # so on), we record not just the active window but its ancestors
        # up to the root, and treat a ConfigureNotify on any of those
        # ancestors as meaning that the active window has been moved or resized
        pointer = active
        windows = []
        while pointer.id != Xroot.id:
            windows.append(pointer)
            pointer = pointer.query_tree().parent
    elif event.type == Xlib.X.ConfigureNotify and event.window in windows:
        print("Active window size/position is now", event.x, event.y,
              event.width, event.height)

这篇关于使用 Python xlib 在活动 X 窗口更改时获取通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆