python xlib发生更改焦点事件时如何“正确”检测应用程序名称

Pat*_*ker 4 python focus detect xlib application-name

我想在使用 python xlib 发生更改焦点事件时检测应用程序窗口名称,因此在第一步中我使用以下代码:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import Xlib.display
import time


display = Xlib.display.Display()
while True:
    window = display.get_input_focus().focus
    wmname = window.get_wm_name()
    wmclass = window.get_wm_class()
    if wmclass is None and wmname is None:
        window = window.query_tree().parent
        wmname = window.get_wm_name()
    print "WM Name: %s" % ( wmname, )
    time.sleep(3)
Run Code Online (Sandbox Code Playgroud)

但我想要一个正确的方法,然后我研究 xlib 事件并找到Input Focus Events并编写以下代码:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import Xlib.display
from Xlib import X

def main():
    display = Xlib.display.Display(':0')
    root = display.screen().root
    root.change_attributes(event_mask=Xlib.X.FocusChangeMask)

    while True:
        event = root.display.next_event()
        #if event.type == X.FocusIn or event.type == X.FocusOut:
        if event.type == X.FocusOut :
            window = display.get_input_focus().focus
            wmname = window.get_wm_name()
            wmclass = window.get_wm_class()
            if wmclass is None and wmname is None:
                window = window.query_tree().parent
                wmname = window.get_wm_name()
            print "WM Name: %s" % ( wmname, )

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

可悲的是,它不能正常工作,尤其是在 google chrome 和 firefox 上的标签式浏览中,所以这种情况有正确的方法吗?

rr-*_*rr- 7

你的代码几乎是正确的,但它遗漏了两件事:

  • 与其只侦听焦点更改,它还应该侦听包含WM_NAME属性更改的窗口属性事件,这也会在您在浏览器中循环选项卡时发生。
  • 而不是只在根窗口中侦听,它应该侦听每个窗口(获得焦点)。您可以使用与根窗口相同的方式附加事件处理程序。

话虽如此,这是一个工作示例:

#!/usr/bin/python3
import Xlib
import Xlib.display

disp = Xlib.display.Display()
root = disp.screen().root

NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')

root.change_attributes(event_mask=Xlib.X.FocusChangeMask)
while True:
    try:
        window_id = root.get_full_property(NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType).value[0]
        window = disp.create_resource_object('window', window_id)
        window.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
        window_name = window.get_full_property(NET_WM_NAME, 0).value
    except Xlib.error.XError: #simplify dealing with BadWindow
        window_name = None
    print(window_name)
    event = disp.next_event()
Run Code Online (Sandbox Code Playgroud)