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

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 以设置适当的掩码),但我无法让它工作。

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

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

请您参考如下方法:

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

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) 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!