Почему они не работают
Согласно статье ArchWiki, которую вы упомянули:
X-сервер получает коды клавиш от устройства ввода и преобразует их в
состояние и KeySym .
состояние - это битовая маска модификаторов X (Ctrl / Shift / и т. д.).
KeySym (в соответствии с /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 выберет эту группу только во время нажатия, но это откроет клавише 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). Благодаря ваш вопрос и этот ответ, теперь я знаю, что такое оверлей :).)