Исключая некоторые ключи из XGrabKeyboard

Рассмотрим приложение, в котором желательно захватить клавиатуру, когда она сфокусирована, чтобы захватить все команды менеджера окон (Alt+F4 и еще много чего) для обработки. Теперь у этого есть недостаток, заключающийся в том, что у пользователя нет возможности переключаться на другое приложение или виртуальный рабочий стол через клавиатуру, когда клавиатура захватывается. Я хотел бы иметь определенный пользователем белый список комбинаций клавиш (скажем, комбинаций клавиш для переключения виртуальных рабочих столов), которые исключены из захвата.

Я могу думать о двух возможных подходах. При получении ключевого события из белого списка либо

  1. Каким-то образом скажите X, чтобы она продолжала обрабатываться как обычно Это звучит как более естественный способ сделать это, но я не могу найти способ сделать это, или
  2. Отключите клавиатуру и повторно отправьте событие вручную оконному менеджеру для обработки, однако я не знаю, куда его отправить (корневое окно?) Или это будет работать.

Кто-нибудь может заполнить пробелы в тех? Любые другие предложения?

Если нет способа исключить клавиши из захвата, я думаю, мне придется довольствоваться наличием "клавиши выхода", которая при нажатии нажимает на клавиатуру. Пользователь должен будет нажать и то, и другое, а затем команду менеджера окон, что не так приятно.

1 ответ

Решение

Я не думаю, что есть способ сделать это. Ни один из механизмов не работает так, как вам нужно.

Подход 1 является своего рода тем, что делает оконный менеджер, если он решает, например, не перехватывать щелчок или клавишу. Однако WM использует "пассивные" захваты для определенных ключей (XGrabKey= пассивный XGrabKeyboard=active), а затем XAllowEvents(). XAllowEvents() не работает с XGrabKeyboard(). также, когда вы выполняете XAllowEvents с одним из режимов воспроизведения, событие воспроизведения игнорирует все пассивные захваты в окне, в котором был исходный захват, и во всех его родительских окнах. Захваты WM будут находиться в корневом окне, которое всегда будет родительским, поэтому я не знаю, как воспроизвести его в корневом окне. В любом случае выполнение XGrabKey для каждого возможного ключа было бы своего рода психом.

Во втором подходе могут возникнуть проблемы с плохим состоянием гонки, потому что другие события, связанные с клавишами и мышью, могут быть обработаны до того, как вы сможете отправить их повторно, поэтому вы переупорядочиваете ключи и отправляете события в разрушенные окна и другие проблемы. Кроме того, нет хорошего способа отправить ключевое событие. XSendEvent() игнорируется многими клиентами (он устанавливает флаг send_event в событии, позволяющем это). Расширение XTest может быть использовано, но может быть отключено на производственных X-серверах, и в нем по-прежнему возникают проблемы с условиями гонки

Вероятно, вам понадобится расширение протокола, которое позволит вам выполнять AllowEvents(mode=ReplayKeyboard) после GrabKeyboard и без обхода пассивных захватов в родительских окнах.

Одно предостережение в том, что я не знаю всех диких вещей, которые можно сделать с помощью XKB и XInput2, поэтому, возможно, что-то есть в этих расширениях.

В любом случае, насколько я знаю, вы должны согласиться с "escape-ключом", хотя в конечном итоге было бы неплохо, чтобы спецификации X-сервера и / или оконного менеджера имели "VMWare/VNC-type-thing осведомленность", которая выиграла не поможет вам в краткосрочной перспективе. Расширение спецификации EWMH может быть таким же простым, как новый _NET_WM_WINDOW_TYPE для vnc/vmware/stuff-like-that, и диспетчер окон может уменьшить свои привязки клавиш или добавить дополнительный модификатор к ним или что-то еще, когда это окно было сфокусировано, например.

Другие вопросы по тегам