【问题标题】:Get notifications when active X window changes using Python xlib使用 Python xlib 在活动 X 窗口更改时获取通知
【发布时间】:2020-02-09 20:33:03
【问题描述】:

我想监控在运行 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 事件,虽然我没有t 接收 ConfigureNotify 事件)。但是,尚不清楚所有窗口管理器是否都设置了此属性,并且仅在窗口调整大小时才会更改;它不会随着窗口移动而改变(任何其他属性也不会改变)。

【问题讨论】:

    标签: python x11 xlib


    【解决方案1】:

    这样做的方法是在根窗口上选择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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多