angelspie — управление окнами в X11, глобальные и не только горячие клавиши

Название - отсылка к devilspie, похожей утилитой. Она примечательна тем, что конфиг пишется на диалекте лисп, несмотря на это у неё весьма ограниченные возможности. Тем более у утилит типа wmctl и т.п.

С помощью библиотеки wnck можно делать куда больше, а ещё больше если задействовать gdk.

Для глобальный горячих клавиш я использовал libkeybinder, раньше я делал такое на "голой" xlib, но так удобней(и переносимей). Впрочем xlib/xtest тоже используется - чтобы эмулировать нажатие кнопок. Но эти функции опциональны.

В качестве формата конфига я выбрал yaml. Более старые версии использовали конфиг на питоне, но я решил что yaml удобней конечным пользователям. Тем более в него можно встраивать код на python и sh.

В детали реализации я вдаваться не буду. Там много магии и метапрограммирования, часть кода сгенерирована.

Лучше покажу пример конфига, который использует часть возможностей. Кстати, новые правила можно генерировать из командной строки, оно возьмет name и class_group активного окна.

click_with_F1:
  if:
    key: F1
  then:
    click: 3

Самый простой пример. При нажатии F1 будет эмулировать нажатие правой кнопки мыши.

save_image:
  if:
    key: F2
    class_group: Google-chrome
  then:
    - click: 3
    - sleep: 0.1
    - press: v
    - enable: autosave

При нажатии F2 нажмет правую кнопку, v(save as) и активирует правило autosave

# Would type "filename" and press alt+s to save when Save file dialog of chrome appears. But only after we pressed F2.
autosave:
  if:
    name: Save File
    class_group: Google-chrome
    enabled: false
  then:
    - press: f i l e n a m e Alt+S
# Disable autosaving every 2 secs.
timer_test:
  if:
    event: timer 2
  then:
    disable: autosave

При появлении окна Save File запомнит имя файла и сохранит. Через 2 секунды это правило отключается. Имя файла будет автоматически заполняться только при нажатии F2, а не у любых окон.

print_debug:
  if:
      event: never
  then:
    debug:
    
win_changed:
  if:
    event: active_window_changed
  then:
    echo: "window changed {name} {class_group}"
switched_to_xterm:
  if:
    name:
      contains: mc
    class_group: XTerm
  then:
    - maximize:
    - disable: win_changed
    - trigger: print_debug
not_in_mc:
  if:
    or:
      class_group:
        ne: xterm
      name:
        contains_not: mc
  then:
    - sh: date
    - py: from datetime import datetime;print(datetime.now())

print_debug можно вызвать только вручную с помощью trigger, остальное думаю очевидно. это просто пример. доступны все манипуляции с окнами из wnck и gdk. список методов есть в командной строке или доках по wnck. возможных условий в if тоже куча, включая вызов кода на питоне или sh.

Важно - если горячая клавиша прописана только для определенного окна или условий. она будет мапиться только при переключении на это окно. При потере фокуса, хоткей отключается и кнопка работает как обычно. Это то, чего не хватает многим глобальным менеджерам горячих клавиш.

Например у меня есть скрипт, который обрезает видео на текущем моменте, если активное окно - mpv. В других окнах такая функция была бы бесполезно, а кнопка бы не работала.

Кстати. хоть в коде и много магии, я думаю, там неплохая архитектура. Хотелось бы услышать критику. Но тут важен баланс между понятностью кода и его универсальностью / компактностью. Упор сделан на последнее.

Код доступен на github и pypi. Кстати. где бы ещё разместить программу? Хочется донести её для десктопных юзеров. Возможно, придется добавить gui, но там слишком много функций. Удобней просто редактировать конфиг.

@pawnhearts
11.06.2021 13:32 UTC
Первоисточник

Комментарии

@selivanov_pavel
12.06.2021 21:12 UTC
0
Кстати, где бы ещё разместить программу? Хочется донести её для десктопных юзеров.

Я бы советовал ppa-репозиторий или snap для самого популярного десктопного линукса — Ubuntu. На второе место я бы наверное поставил не Fedora/CentOS, а ArchLinux — там меньше пользователей, но больше тех, кто ценит вещи такого типа, где можно потрахаться, зато получить идеальный результат под себя. Для Fedora/CentOS — flatpack.


Десктопный линукс, увы, очень фрагментирован.


придется добавить gui, но там слишком много функций. Удобней просто редактировать конфиг.

ИМХО достаточно значка в трее, показывающего что программа работает, и позволяющего открыть активный конфиг в редакторе. Посмотрите на AutoKey, например: https://github.com/autokey/autokey


Вообще, интересная штука, может когда-нибудь дойдут руки попробовать.

@Jijiki
08.01.2025 17:07 UTC
0

с кнопками на Иксах интересные особенности например

Скрытый текст
        case KeyPress:
            XLookupString((XKeyEvent *)&win->ev, NULL, 0, &key, NULL);
            
            switch (key)
            {
            case XK_w:
            
                moveBy(1.0f);
                
                break;
            case XK_s:
                moveBy(-1.0f);
                break;
            case XK_d:
                rotateBy(1.0f);
                break;
            case XK_a:
                rotateBy(-1.0f);
                break;
            }
            break;

нажимаем w и она пошла пока держишь, следующий случай нажимаем w перестаём нажимать w, и следующий случай нажимаем w и резко начинаем держать w s обе и вот тут, примечательно что на машине с Иксами тоесть прям в линуксе что в этом окне кода который я привёл в последнем случае ws зажатых обоих кнопках зафиксируется кнопка s, простите если не в тему, но тема интересная