В статье показана структура запросов к окнам Linux, позволяющая управлять уже запущенными окнами. Изначально утилита xdotool_xseticon была создана для динамического изменения значка окна в Astra Linux. Затем функционал утилиты был расширен для полного управления окнами и получения всей информации об окне Linux. Утилита xdotool_xseticon была протестирована в средах Wayland и X11 в Ubuntu 24.04 (KDE), в X11 Ubuntu 22.04 (KDE) и Astra Linux 1.8. Размер утилиты - 1000 строк.
Краткая предыстория
В ходе работы с Astra Linux понадобилось сделать информационную систему из старой ВЕБ-системы с ограничениями для пользователя. В связи с этим понадобилась утилита, которая управляет независимыми окнами. Далее с помощью Bash был сделан фреймворк для Astra Linux. По техническому заданию в системе нельзя было использовать нелицензионный софт , поэтому был сделан фреймворк WebDesktopGL, в состав которого и входит эта утилита xdotool_xseticon. Утилита xdotool_xseticon оказалась очень полезной ещё и как инструмент исправления ошибок в работе системы «Барьер-УВД».
Установка и сборка
Установку можно выполнить с помощью команды git clone, а сборку - с помощью скрипта Install_bash_Xdotool_xseticon.sh.
git clone https://github.com/PVE-Vladimir/xdotool\_xseticon.git # Использовать скрипт установки Install_bash_Xdotool_xseticon.sh ./xdotool_xseticon/Install_bash_Xdotool_xseticon.sh cd ./xdotool_xseticon
Сборка происходит через gcc. Команда сборки
sudo apt install libx11-dev gcc -o "$SCRIPT_DIR/xdotool_xseticon" "$SCRIPT_DIR/Xdotool_xseticon.c" -lX11
Результат сборки — утилита xdotool_xseticon.
Структура запросов к окнам Linux
Код утилиты xdotool_xseticon разбит на отдельные блоки, что позволяет в случае необходимости использовать отдельный блок функциональности в другом коде. Название функции вызова события окна совпадает с названием функции в справке утилиты xdotool_xseticon. Полезные материалы для работы с менеджерами окон
// отправить ClientMessage всем окнам void send_msg(Window w, Atom a, Atom b, Atom msg) { XEvent e = { .xclient = { .type = ClientMessage, .send_event = True, .display = display, .window = w, .message_type = msg, .format = 32, .data.l = { a, b, 0, 0, 0 } }}; XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask|SubstructureNotifyMask, &e); XFlush(display); }
Этот фрагмент кода реализует функцию отправки клиентского сообщения (ClientMessage) всем окнам (на самом деле — конкретному окну, указанному параметром w). Это часть кода для работы с окнами в среде (Linux/UNIX).
Сигнатура функции
void send_msg(Window w, Atom a, Atom b, Atom msg)
Window w — идентификатор целевого окна.
Atom a, b — атомы (идентификаторы), используемые как параметры сообщения (обычно это коды типа сообщения и дополнительные данные). <br> Atom msg — тип клиентского сообщения.
Конструкция сообщения
Создается структура XEvent e, в которую помещается:
.type = ClientMessage — сообщение типа "клиентский"
.xclient — вложенная структура с деталями
.display — контекст дисплея.
.window — целевое окно
.message_type = msg — тип сообщения (например, WM_COMMAND, WM_USER и т.д.)
.format = 32 — формат данных (32 бита)
.data.l — массив из 5 атомов.
Обычно используются только первые поля:
[0] — message_type (часто дублирует .message_type, но формально требуется)
[1] — атом a [2] — атом b
[3] и [4] — дополнительные параметры (здесь 0)
Отправка сообщения
XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask|SubstructureNotifyMask, &e);
Отправляет событие не целевому окну напрямую, а "в корневое окно" с флагами (чтобы гарантировать обработку). Фактически X11 не позволяет отправлять ClientMessage непосредственно произвольному окну без прав, но такой способ используется для массового рассылки сообщений (например, через RootWindow и обработчики на уровне окон).
XFlush(display) — синхронизация буфера, чтобы изменения вступили в силу.
Функционал xdotool_xseticon на русском языке.
Основные команды Использование: %s <-help> %s <команда> [опции] [аргументы] Команды: -help, --help, --h, -h Показать эту справку windowmove <win_id> <X> <Y> Перемещает окно по координатам (X, Y) Пример: %s windowmove 0x6000001 100 200 windowsize <win_id> <W> <H> Изменяет размер окна на ширину W и высоту H Пример: %s windowsize 0x6000001 800 600 getwindowgeometry <win_id> Получить позицию и размер окна Пример: %s getwindowgeometry 0x6000001 search (--name <заголовок> | --pid <pid>) Найти окна по заголовку или идентификатору процесса Пример: %s search --name "Терминал" Пример: %s search --pid 12345 xseticon <win_id> <данные_иконки...> Установить иконку окна (формат ARGB) Пример: %s xseticon 0x6000001 2 2 0xffff0000 0x0000ffff 0xcccc0b09 0x10101010 xseticon_gif <window_id> <файл> [<скорость_кадров 1-120> — опционально, иначе 20 (рекомендуется 20)] Файл icon.txt (массив bash в формате ARGB) создается скриптом make_window_icon_txt.sh Пример: %s xseticon_gif 0x6000001 /home/sysadmin/Desktop/test/imege_6/imege_6.txt _NET_WM <win_id> <действие> [аргументы] Действия: info [свойство] — Получить информацию об окне (заголовок, позиция, размер и т.д.) Свойства: xwininfo, AbsoluteX, AbsoluteY, RelativeX, RelativeY, Width, Height, Depth, Visual, VisualClass, Border, Class, Colormap, Bit, WindowGravity, Backing, Save, Map, Override, Corners, geometry, _NET_WM_STATE Операции диспетчера окон: info — Показать подробную информацию о окне info <свойство> — Показать конкретное свойство hide — Минимизировать окно, свернуть окно show — Восстановить окно show_raised — Восстановить и активировать окно maximize — Выравнивать окно в полный экран reduce — Свернуть окно в окно или минимизировать окно в окно rename — Переименовать окно fullscreen — Переключить в полноэкранный режим unfullscreen — Выйти из полноэкранного режима lower_window — Отправить окно ниже state_above[0/1] — Всегда поверх (0=убрать, 1=добавить) state_below[0/1] — Всегда под (0=убрать, 1=добавить) state_shade[0/1] — Проступ/выдвинуть окно (0=выдвинуть, 1=проступить) decorated[0/1] — Включить/выключить декорации окна (0=убрать, 1=добавить): без рамки close — Закрыть окно Примеры: %s _NET_WM 0x6000001 info %s _NET_WM 0x6000001 info Map %s _NET_WM 0x6000001 state_above1 %s _NET_WM 0x6000001 rename "Новый заголовок тест" _NET_WM_ICON <win_id> Показать пиксельные данные иконки окна Пример: %s _NET_WM_ICON 0x6000001
Пример использования утилиты
Чтобы узнать идентификатор окна (0x6000001), используйте команду search:
./xdotool_xseticon search --pid $(pgrep zabbix_replay) ./xdotool_xseticon search --name zabbix_replay | head -n1
Поменять параметры окна
./xdotool_xseticon xseticon 0x6000001 2 2 0xffff0000 0x0000ffff 0xcccc0b09 0x10101010
0x6000001 — идентификатор окна.
2 2 — размер иконки (2x2 пикселя).
0xffff0000 и т.д. — ARGB-значения цветов.
ARGB-значения цветов можно получить применив скрипт make_window_icon_txt.sh который создаст файл icon.txt (массив bash в формате ARGB). Подробнее в этой статье и в этой статье.
Итоговый пример использования утилиты xdotool_xseticon
./xdotool_xseticon xseticon $(./xdotool_xseticon search --name zabbix_replay | head -n1) 2 2 0xffff0000 0x0000ffff 0xcccc0b09 0x10101010 ./xdotool_xseticon _NET_WM $(./xdotool_xseticon search --name zabbix_replay | head -n1) rename "test xdotool_xseticon"

Пример использования утилиты с функцией xseticon_gif для анимирования иконки окна
./xdotool_xseticon xseticon_gif $(./xdotool_xseticon search \ --name zabbix_replay | head -n1) ./Images/Image.txt 20
Подробно об этой функции в этой статье

Просмотр параметров окон в разных запросах
./xdotool_xseticon getwindowgeometry $(./xdotool_xseticon search --name InfoDoc | head -n1)


Этот запрос всегда возвращает Position: 0, 0 (screen: 0) в некоторых дистрибутивах Linux. Это не недоработка: параметры Position можно получить с помощью другого, более подробного запроса info.
./xdotool_xseticon _NET_WM $(./xdotool_xseticon search --name InfoDoc | head -n1) info

Запрос getwindowgeometry использует функцию XGetGeometry(). Функция XGetGeometry() возвращает корневое окно и текущую геометрию отображаемого объекта, а также координаты x и y, определяющие местоположение отображаемого объекта. Для окна эти координаты указывают на верхний левый внешний угол относительно начала координат родительского окна. Для пиксельных карт эти координаты всегда равны нулю. Поэтому запрос getwindowgeometry предполагается использовать для анализа среды разработки.
Заключение
Утилита xdotool_xseticon работает с Wayland в Ubuntu 24.04, что подтверждено результатами тестов. В системах Wayland обычно запускается XWayland — сервер, эмулирующий протокол X11 поверх Wayland. Возможно, этого достаточно, чтобы xdotool_xseticon работала с Wayland. Утилита xdotool_xseticon помогла мне побороть проблему с пропадающим окном системы «Барьер-УВД» в Astra Linux 1.8. Причина была в том, что в Astra Linux происходила гонка между окнами за то, какое окно должно быть выше. Благодаря применению утилиты xdotool_xseticon через планировщик задач crontab удалось решить эту проблему. Возможно, ещё кому-то поможет код утилиты для автоматизации GUI-приложений, создания скриптов для управления окнами, интеграции с CI/CD (например, для тестирования UI) и разработки кастомных WM-менеджеров.