4

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)

しかし、正しい方法が必要なので、xlib イベントについて調査し、入力フォーカス イベントを見つけて、次のコードを記述します。

#!/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()

悲しいことに、特に google chrome と firefox のタブ ブラウジングでは正しく動作しません。この状況の正しい方法はありますか?

4

2 に答える 2

7

あなたのコードはほぼ正しいですが、次の 2 つの点が欠けています。

  • フォーカスの変更だけをリッスンするのではなく、プロパティの変更を含むウィンドウ プロパティ イベントもリッスンする必要があります。これは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()
于 2015-07-09T19:20:45.717 に答える