StumpWM как вершина ручного тайлинга
StumpWM — это ручной тайловый менеджер, написанный на Common Lisp. Со стороны эта фраза ничего не значит, но на деле это оконный менеджер с огромным потенциалом для превращения его в удобную рабочую среду, альтернатив которой почти нет (если есть вообще).
Прежде всего, что такое ручной тайлинг (или manual tiling, или static tiling). Это тайлинг, где расположением окон управляет пользователь, а не оконный менеджер. В случае со StumpWM, пользователь делает сетку из фреймов (или тайлов), куда будут распологаться окна. Окна распологаются друг над другом и занимают фрейм полностью. Можно привести аналогию с картами, где окно — это карта и эта карта складывается в общую пачку в виде фрейма и, эти несколько пачек, располагающиеся напротив друг друга — это итоговая сетка из фреймов. По опыту, это самое безболезненное решение из всех, если окон очень много.
Сам оконный менеджер написан на Common Lisp и, благодаря этому, позволяет переконфигурировать его на лету через Emacs+SLIME/Sly. Сам конфиг тоже на лиспе, что удобно. У меня, например, накопилось около 2000 строк кода. WM позиционирует себя как Emacs среди оконных менеджеров. Не в плане того, что может полностью зависнуть, если какой-то из плагинов будет долго думать, а в плане способствования хакам.
Кстати об имаксе. Как и у Emacs, у StumpWM хоткеи работают по принципу цепочки аккордов (chord chain). Например, можно реализовать такой хоткей: нажатие Ctrl+C, отпускание и нажатие таба — это может считаться одним хоткеем и быть забиндено на, скажем, вызов терминала. В конфиге выглядеть это будет примерно так:
(set-prefix-key (kbd "C-c"))
(define-key *root-map* (kbd "Tab") "run-shell-command sakura")
Из кода получается, что при нажатии на Ctrl+C оконный менеджер переключит лейаут клавиатуры на root-map и будет ожидать следующей клавиши. А на этом лейауте будет таб, при нажатии на который будет вызываться команда sakura. Мап, по факту, является раскладкой клавиатуры для оконного менеджера, на котором расположены бинды команд для него. И подобных map-ов может быть, в целом, до бесконечности и можно даже подсунуть мап в хоткей другого мапа:
(set-prefix-key (kbd "C-c"))
(register-kmap *layout-map* nil)
(define-key *root-map* (kbd "w") '*layout-map*)
Тут при переходе на рутовый мап мы можем нажать на W и перейти на следующий мап — layout-map.
Говоря простым языком, мы можем определять потенциально бесконечное число цепочек аккордов для хоткея. И это замечательно в плане эргономики — руки меньше напрягаются для хоткеев.
Я использую патченный StumpWM, т.к. мне не удалось найти, можно ли в лиспе в рантайме менять атрибуты класса. Но у патчей есть свои предпосылки. Ванильный StumpWM для перемещения по лейауту предлагает переключение фреймов по принципу «ближайший в заданном направлении», что неудобно и занимает время при переключении (особенно на мультимониторных конфигурациях). Так что мне удалось встроить в StumpWM свой принцип переключения фреймов, который заключается в тегировании фреймов. Схему в общем виде можно наблюдать на второй пикче. Суть в том, что на фрейм накладывается определённый тег, который привязывается к определённому хоткею. И, соответственно, при нажатии будет немедленное переключение на соответствующий тег. Патч был нужен лишь для добавления атрибута тега в класс фрейма. Функции по работе с этим реализованы на уровне конфига. Теги создаются динамически и также динамически привязываются к хоткеям. Они могут по-разному называться и их может быть до бесконечности.
Весь этот текст — фиксация того, что можно найти в StumpWM, т.к. с него я ухожу. Это один из лучших оконных менеджеров, но в нём есть свои проблемы:
-
Плохая поддержка мультимониторной конфигурации. Если в каком-нибудь herbstluftwm на один монитор даётся один воркспейс, то у StumpWM один воркспейс на все мониторы. Это порождает разного рода проблемы, например, если второй монитор служит информационным дисплеем, то при переключении воркспейсов, воркспейс переключается на всех мониторах, соответственно, убирая информацию со второго монитора.
-
Позиционирование а-ля имакс. Субъективщина, но модульность кажется более лучшим решением, чем всё в одном решении.
-
Мне не удалось придумать как решить проблему, если в воркспейсе накопилось слишком много окон. Ты начинаешь в них утопать, переключая в поисках нужного. То, как это всё реализовано в StumpWM сейчас — лучшее из того, что мне доводилось пробовать. Но хочется лучше. У меня была идея делать субворкспейсы — это обычные воркспейсы, но они условно привязаны к какому-либо из воркспейсов. По типу того, что есть воркспейс anyame и мы создаём подворкспейсы: anyame1, anyame2, etc… И все окна раскидываем по ним. Главное тут во всём: переключение подворкспейсов должно быть максимально доступным, как Alt+Tab, только в два хоткея: вперёд по цепочке и обратно. Но вся идея упёрлась в первый пункт проблем. И это стало малоиспользуемым, по итогу.
-
Просто мелкие баги, которые могут доставлять дискомфорт. Например, может быть так, что WM может застрять между двумя воркспейсами и показывать окна с них одновременно — лечится переключением обратно.
Проблема с большим количеством окон для меня сильно актуальна, т.к. я стараюсь отказываться от табов в приложении в пользу отдельных окон, т.к. окнами должен управлять оконный менеджер. И у меня уже есть идея улучшенного тайлинга, который должен быть лучше классического. Но это если и будет, то не на тайловом WM.
А так, в плане кастомизации под свои нужды, этот WM — вершина ручного тайлинга.
Дальнейшие ресурсы для изучения: