Почему они не работают
Согласно статье ArchWiki, которую вы упомянули:
X-сервер получает коды клавиш с устройства ввода и преобразует их в состояние и keyym .
состояние - битовая маска модификаторов X (Ctrl / Shift / и т. д.).
KeySime (в соответствии с
/usr/include/X11/keysymdef.h
) целое число, котороеидентифицировать символы или функции, связанные с каждой клавишей (например, посредством видимой гравировки) раскладки клавиатуры.
Каждый печатный символ имеет свой собственный символ клавиши, как
plus
,a
,A
, илиCyrillic_a
, но другие клавиши также генерируют свои символы клавиш, какShift_L
,Left
илиF1
.
Приложение в ключе события нажатия / выпуска получает всю эту информацию.
Некоторые приложения отслеживают ключевые символы как они
Control_L
сами, другие просто ищут биты модификатора в состоянии .
Итак, что происходит, когда вы нажимаете AltGr+ j:
Вы нажимаете AltGr. Приложение получает событие KeyPressed с
<RALT>
ключевым кодом 108 ( ) и keysym 0xfe03 (ISO_Level3_Shift
), состояние 0.Вы нажимаете j(что соответствует «h» в двораке без модификаторов). Приложение получает событие KeyPressed с
<AC07>
ключевым кодом 44 ( ), keysym 0xff51 (Left
) и состоянием 0x80 (модификатор Mod5 включен).Вы отпускаете j. Приложение получает событие KeyRelease для ключа
<AC07>
/Left
с такими же параметрами.Затем отпустите AltGr- событие KeyRelease для AltGr. (Кстати, состояние здесь все еще 0x80, но это не имеет значения.)
Это можно увидеть, если вы запустите xev
утилиту.
Таким образом, все это означает, что, хотя приложение получает тот же код keysym ( Left
), что и от обычного ключа <LEFT>
, оно также получает код keysym и состояние модификатора из AltGr. Скорее всего, те программы, которые не работают, следят за модификаторами и не хотят работать, когда некоторые активны.
Как заставить их работать
Очевидно, мы не можем изменить каждую программу, чтобы не искать модификаторы. Тогда единственная возможность избежать этой ситуации - не генерировать ключи и биты состояния модификаторов.
1. Отдельная группа
Единственный способ, который приходит на ум: определить клавиши перемещения курсора в отдельной группе и переключателе, с отдельным нажатием клавиши, к этой группе до нажатия клавиш j, k, l, i( h
, t
, n
, c
) (группа фиксирующего является предпочтительным методом за один раз смена группы, как я понял).
Например:
xkb_keymap { xkb_keycodes { include "evdev+aliases(qwerty)" }; xkb_types { include "complete" }; xkb_compatibility { include "complete" interpret ISO_Group_Latch { action = LatchGroup(group=2); }; }; xkb_symbols { include "pc+us(dvorak)+inet(evdev)" key <RALT> { [ ISO_Group_Latch ] }; key <AC07> { type[Group2] = "ONE_LEVEL", symbols[Group2] = [ Left ] }; key <AC08> { type[Group2] = "ONE_LEVEL", symbols[Group2] = [ Down ] }; key <AC09> { type[Group2] = "ONE_LEVEL", symbols[Group2] = [ Right ] }; key <AD08> { type[Group2] = "ONE_LEVEL", symbols[Group2] = [ Up ] }; }; xkb_geometry { include "pc(pc104)" }; };
Теперь, если вы сначала нажмете, AltGrа затем (отдельно) одну из клавиш перемещения, это должно работать.
Однако это не очень полезно, более уместно было бы LockGroup
вместо защелки и нажатия AltGr до и после группового переключения. Еще лучше может быть SetGroup
- тогда AltGr выберет эту группу только во время нажатия, но это откроет keyym приложения AltGr ( ISO_Group_Shift
/ ISO_Group_Latch
/ независимо от того, что определено) (но состояние модификатора остается чистым).
Но ... также существует вероятность того, что приложение также считывает коды клавиш (коды реальных ключей). Затем он заметит «поддельные» клавиши курсора.
2. Наложение
Более «низкоуровневым» решением будет оверлей (как описано в той же статье ).
Наложение просто означает, что некоторая (настоящая клавиатура) клавиша возвращает код клавиши другой клавиши. X-сервер изменяет код ключа ключа и вычисляет состояние модификатора и код ключа для этого нового кода ключа, поэтому приложение не должно замечать это изменение.
Но оверлеи очень ограничены:
- В X-сервере есть только 2 управляющих бита наложения (т. Е. Может быть максимум 2 наложения).
- Каждый ключ может иметь только 1 альтернативный код ключа.
В остальном реализация очень похожа на метод с отдельной группой:
xkb_keymap { xkb_keycodes { include "evdev+aliases(qwerty)" }; xkb_types { include "complete" }; xkb_compatibility { include "complete" interpret Overlay1_Enable { action = SetControls(controls=overlay1); }; }; xkb_symbols { include "pc+us(dvorak)+inet(evdev)" key <RALT> { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Overlay1_Enable ] }; key <AC07> { overlay1 = <LEFT> }; key <AC08> { overlay1 = <DOWN> }; key <AC09> { overlay1 = <RGHT> }; key <AD08> { overlay1 = <UP> }; }; xkb_geometry { include "pc(pc104)" }; };
SetControls
означает изменить бит управления, пока клавиша нажата, и восстановить его при отпускании клавиши. Должна быть похожая функция LatchControls
, но xkbcomp
дает мне
Error: Unknown action LatchControls
на компиляции раскладки.
(Между прочим, я также использую dvorak, а также переназначил некоторые ключевые символы движения на высокий уровень буквенных клавиш. А также натолкнулся на некоторую нарушенную функциональность (выбор в примечаниях Xfce и переключение рабочего стола с помощью Ctrl-Alt-Left / Right). Благодаря Ваш вопрос и этот ответ, теперь я знаю, что такое оверлей :).)