Уведомление об изменениях заголовка окна

… без опроса.

Я хочу определить, когда меняется окно, в котором происходит фокусировка, так что я могу обновить часть пользовательского графического интерфейса в моей системе.

Пункты интересов:

  • уведомления в режиме реального времени. Имея отставание 0,2 с в порядке, наличие отставания 1 с является мехом, с запасом 5 с совершенно неприемлемым.
  • ресурсоемкость: по этой причине я хочу избежать опроса. Запуск xdotool getactivewindow getwindowname каждые, скажем, полсекунды, работает вполне нормально … но порождает 2 процесса в секунду все, что мне нравится в моей системе?

В bspwm можно использовать bspc subscribe которая печатает строку с некоторыми (очень) базовыми статистическими bspc subscribe , каждый раз при изменении фокуса окна. Сначала этот подход кажется приятным, но прислушаться к этому не обнаружит, когда заголовок окна изменится сам по себе (например, изменение вкладок в веб-браузере останется незамеченным таким образом.)

Итак, каждый раз, когда на Linux появляется новый процесс, каждые полторы секунды, а если нет, как я могу сделать что-то лучше?

Одна вещь, которая приходит мне на ум – попытаться подражать тому, что делают окна-менеджеры. Но могу ли я писать крючки для таких событий, как «создание окна», «запрос на изменение названия» и т. Д. Независимо от рабочего диспетчера окон, или мне нужно стать самим оконным менеджером? Нужно ли мне root для этого?

(Еще одна вещь, которая пришла мне в голову, – это посмотреть на xdotool и подражать только тем, которые меня интересуют, чтобы я мог избежать всех шаблонов нереста процесса, но он все равно будет опросом.)

2 Solutions collect form web for “Уведомление об изменениях заголовка окна”

Я не мог заставить ваш подход сфокусироваться на надежную работу под Kwin 4.x, но современные оконные менеджеры поддерживают свойство _NET_ACTIVE_WINDOW в корневом окне, которое вы можете прослушать для изменений.

Вот реализация Python:

 #!/usr/bin/python from contextlib import contextmanager import Xlib import Xlib.display disp = Xlib.display.Display() root = disp.screen().root NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW') NET_WM_NAME = disp.intern_atom('_NET_WM_NAME') # UTF-8 WM_NAME = disp.intern_atom('WM_NAME') # Legacy encoding last_seen = { 'xid': None, 'title': None } @contextmanager def window_obj(win_id): """Simplify dealing with BadWindow (make it either valid or None)""" window_obj = None if win_id: try: window_obj = disp.create_resource_object('window', win_id) except Xlib.error.XError: pass yield window_obj def get_active_window(): win_id = root.get_full_property(NET_ACTIVE_WINDOW, Xlib.X.AnyPropertyType).value[0] focus_changed = (win_id != last_seen['xid']) if focus_changed: with window_obj(last_seen['xid']) as old_win: if old_win: old_win.change_attributes(event_mask=Xlib.X.NoEventMask) last_seen['xid'] = win_id with window_obj(win_id) as new_win: if new_win: new_win.change_attributes(event_mask=Xlib.X.PropertyChangeMask) return win_id, focus_changed def _get_window_name_inner(win_obj): """Simplify dealing with _NET_WM_NAME (UTF-8) vs. WM_NAME (legacy)""" for atom in (NET_WM_NAME, WM_NAME): try: window_name = win_obj.get_full_property(atom, 0) except UnicodeDecodeError: # Apparently a Debian distro package bug title = "<could not decode characters>" else: if window_name: win_name = window_name.value if isinstance(win_name, bytes): # Apparently COMPOUND_TEXT is so arcane that this is how # tools like xprop deal with receiving it these days win_name = win_name.decode('latin1', 'replace') return win_name else: title = "<unnamed window>" return "{} (XID: {})".format(title, win_obj.id) def get_window_name(win_id): if not win_id: last_seen['title'] = "<no window id>" return last_seen['title'] title_changed = False with window_obj(win_id) as wobj: if wobj: win_title = _get_window_name_inner(wobj) title_changed = (win_title != last_seen['title']) last_seen['title'] = win_title return last_seen['title'], title_changed def handle_xevent(event): if event.type != Xlib.X.PropertyNotify: return changed = False if event.atom == NET_ACTIVE_WINDOW: if get_active_window()[1]: changed = changed or get_window_name(last_seen['xid'])[1] elif event.atom in (NET_WM_NAME, WM_NAME): changed = changed or get_window_name(last_seen['xid'])[1] if changed: handle_change(last_seen) def handle_change(new_state): """Replace this with whatever you want to actually do""" print(new_state) if __name__ == '__main__': root.change_attributes(event_mask=Xlib.X.PropertyChangeMask) get_window_name(get_active_window()[0]) handle_change(last_seen) while True: # next_event() sleeps until we get an event handle_xevent(disp.next_event()) 

Более полная заявленная версия, которую я написал в качестве примера для кого-то, находится в этом контексте .

UPDATE: теперь он также демонстрирует вторую половину (прослушивание _NET_WM_NAME ), чтобы выполнить именно то, что было запрошено.

ОБНОВЛЕНИЕ # 2: … и третья часть: WM_NAME к WM_NAME если что-то вроде xterm не установило _NET_WM_NAME . (Последний кодируется в кодировке UTF-8, в то время как первый должен использовать кодировку устаревшего символа, называемую составным текстом, но, поскольку никто, похоже, не знает, как с ней работать, вы получаете программы, бросающие туда любой поток байтов, и xprop просто предполагая, что это будет ISO-8859-1.)

Хорошо, благодаря комментарию @ Basile, я многому научился и придумал следующий рабочий пример:

 #!/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: window_name = None print(window_name) event = disp.next_event() 

Вместо того, чтобы xdotool запускать xdotool , он синхронно слушает события, генерируемые X, и это именно то, что я получил после.

  • Как добиться быстрого переключения пользователей с помощью нескольких графических адаптеров, предотвратить использование виртуального терминала?
  • Перегрев ноутбука с использованием драйвера AMD / ATI с открытым исходным кодом
  • минимальная установка X.org xServer на Debian Wheezy
  • разрешение прилагаемого широкоэкранного
  • Должно ли приостановленное приложение в фоновом режиме (ctrl + z) запускаться или оно должно прекратиться?
  • Перезапускает ли Диспетчер дисплея (например, lightdm) перезапуск X-сервера?
  • Как отключить кнопки «Вперед» / «Назад» на моей мыши
  • Какие комбинации графических процессоров NVidia хорошо поддерживаются драйвером 319.82?
  • безопасная конфигурация xorg
  • OpenBSD X, только мышь прокрутки вниз
  • Как переадресовать окно (отображение) на другой компьютер в сети
  • Настройте графическую панель Wacom Intuos в Linux Mint 15
  • Interesting Posts

    Терминальный автозаполнение: цикл через предложения

    служба systemd все только для чтения, кроме 1 папки

    CentOS 7: ожидание ввода-вывода RAID 1

    Как удалить повторяющиеся строки в большом текстовом файле с несколькими GB?

    Защищенные версии multilib: openssl

    Как создать большой файл в UNIX?

    Измените состояние светодиодов клавиатуры, начиная с X сеанса, без доступа root

    rm не удаляет файл, считает его каталог

    Двойные внешние мониторы на док-станции Dell E-Port II зеркалируются друг с другом

    Yum update / install для любого пакета дает мне следующую ошибку. Какие действия я должен предпринять, чтобы преодолеть это?

    Удалить старые каталоги в соответствии с именем каталога?

    Как протестировать локаль

    Где rpmfusion? – CentOS7 в качестве настольной / мультимедийной системы

    замените `while` более подходящей функцией, поэтому цикл будет ждать завершения каждого процесса

    Как я могу grep определенный текст и отображать его строку и строку после

    Linux и Unix - лучшая ОС в мире.