使用 Python xlib 在活动 X window 更改时获取通知
Get notifications when active X window changes using Python xlib
我想监控哪个 window 在 Linux 系统 运行 X 上处于活动状态,以及活动 window 何时调整大小或移动。我可以监视活动 window(它保存在根 window 上的 _NET_ACTIVE_WINDOW
属性 中,我可以在根 [=] 上注册 PropertyNotify
事件28=] 发现 属性 何时发生变化)。但是,我不知道如何监视活动 window 以了解它是否调整大小或移动。
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)
有办法吗?它可能涉及在当前活动的 window 上监听 ConfigureNotify 事件(并在 window 变为活动状态时调用 change_attributes
以设置适当的掩码),但我无法做到这一点工作。
(注意:我没有使用 Gtk,所以没有 Gtk 解决方案,请。)
更新:有一个相当可疑的方法来检测 window resizes,通过观察活动 window 的值 _NET_WM_OPAQUE_REGION
属性 正在更改(因为我正确地收到了 PropertyChange 事件,尽管我没有收到 ConfigureNotify 事件)。但是,尚不清楚是否所有 window 经理都设置了这个 属性,并且这只会在 window 调整大小时发生变化;它不会在 window 移动中改变(也不会在任何其他 属性 移动)。
方法是在根window上select for SubstructureNotifyMask
,然后读取所有ConfigureNotify
事件,忽略那些不是window 我们关心,因此:
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)
我想监控哪个 window 在 Linux 系统 运行 X 上处于活动状态,以及活动 window 何时调整大小或移动。我可以监视活动 window(它保存在根 window 上的 _NET_ACTIVE_WINDOW
属性 中,我可以在根 [=] 上注册 PropertyNotify
事件28=] 发现 属性 何时发生变化)。但是,我不知道如何监视活动 window 以了解它是否调整大小或移动。
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)
有办法吗?它可能涉及在当前活动的 window 上监听 ConfigureNotify 事件(并在 window 变为活动状态时调用 change_attributes
以设置适当的掩码),但我无法做到这一点工作。
(注意:我没有使用 Gtk,所以没有 Gtk 解决方案,请。)
更新:有一个相当可疑的方法来检测 window resizes,通过观察活动 window 的值 _NET_WM_OPAQUE_REGION
属性 正在更改(因为我正确地收到了 PropertyChange 事件,尽管我没有收到 ConfigureNotify 事件)。但是,尚不清楚是否所有 window 经理都设置了这个 属性,并且这只会在 window 调整大小时发生变化;它不会在 window 移动中改变(也不会在任何其他 属性 移动)。
方法是在根window上select for SubstructureNotifyMask
,然后读取所有ConfigureNotify
事件,忽略那些不是window 我们关心,因此:
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)