Как заставить все приложения уважать мой измененный макет xkb?

1668
nonpop

Мне не нравится прыгать между основной клавиатурой и клавишами перемещения, поэтому я добавил следующее в свой файл макета xkb.

hidden partial xkb_symbols "movement" { key <AD08> { [ NoSymbol, NoSymbol, Up, Up ] }; key <AC08> { [ NoSymbol, NoSymbol, Down, Down ] }; key <AC07> { [ NoSymbol, NoSymbol, Left, Left ] }; key <AC09> { [ NoSymbol, NoSymbol, Right, Right ] }; key <AD09> { [ NoSymbol, NoSymbol, Prior, Prior ] }; key <AB09> { [ NoSymbol, NoSymbol, Next, Next ] }; key <AB07> { [ NoSymbol, NoSymbol, Home, Home ] }; key <AB08> { [ NoSymbol, NoSymbol, End, End ] }; key <AC06> { [ NoSymbol, NoSymbol, Delete, Delete ] }; } 

Затем я включаю их в макет на более позднем этапе файла. Теперь у меня должны быть клавиши курсора, доступные через AltGr + j, k, l, i (или h, t, n, c, поскольку я использую dvorak) и т. Д. Это работает во многих случаях (например, Firefox, urxvt, Eclipse, основной текстовой области LyX), но некоторые программы ничего не делают, когда я пытаюсь, скажем, переместить курсор с помощью этих «горячих клавиш» (например, диалогов NetBeans и LyX).

Итак, есть ли способ заставить эти другие программы также уважать мои желания? И почему они не работают в первую очередь? Я не использую DE; только Awesome WM.

Редактировать:

  • Вот полный, но упрощенный файл раскладки клавиатуры. У меня есть это, /usr/share/X11/xkb/symbols/nonpopи я загружаю его setxkbmap nonpop.
  • Я заметил, что в MonoDevelop передвижение работает, а выбор - нет. То есть, если я нажимаю Shift + вправо, текст выделяется как обычно, но если я нажимаю AltGr + Shift + n, курсор просто перемещается без выбора. Например, в Firefox оба способа могут быть использованы для выбора.
  • Здесь, в конце, они говорят о наложениях, которые выглядят как нечто, что может быть решением, но я не понял, как их использовать.
11
У меня нет решения, но если вам не удастся получить ответ, несмотря на предоставленную вами награду, вы можете попробовать обратиться по адресу [unix.SE] (https://unix.stackexchange.com/), более Unix / Linux-ориентированный сайт Stackexchange. Glutanimate 9 лет назад 1

2 ответа на вопрос

9
Chel

Почему они не работают

Согласно статье 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). Благодаря Ваш вопрос и этот ответ, теперь я знаю, что такое оверлей :).)

Спасибо! Я действительно получил другой ответ на [unix.se] (http://unix.stackexchange.com/questions/153841/how-to-make-altgri-jkl-work-properly-as-cursor-keys), который на первый взгляд казался быть идеальным, но оказалось, что некоторые приложения по-прежнему плохо себя ведут. Это решение (оверлеи) работает и в этих случаях. nonpop 9 лет назад 0
Я только что заметил, что Google Chrom [e | ium] тоже не заботится об этом! :( К счастью, я не использую их много. nonpop 9 лет назад 0
@nonpop проклятый хром… Я добавил обновление в свой ответ https://superuser.com/a/1000320/521612 Aleks-Daniel Jakimenko 6 лет назад 0
Удивительно! Я искал это годами! Есть еще небольшая проблема с Chromium, где он интерпретирует нажатие клавиши Overlay1_Enable. У меня тот же симптом, что и здесь: https://github.com/GalliumOS/galliumos-distro/issues/362 Tarrasch 6 лет назад 0
Мне просто удалось исправить вышеуказанную проблему. Клавиши со стрелками моего домашнего ряда теперь работают и в Chromium! Мне нужно было внести следующие изменения в этот ответ. https://gist.github.com/Tarrasch/1293692/revisions?diff=unified#diff-170987db8deaa0865033ae2715f45dce Tarrasch 6 лет назад 0
3
Aleks-Daniel Jakimenko

I have the same problem. It is so painful.

So the title is “How to make all applications respect my modified xkb layout?“. Well, I think the only way is to fix all of the programs that do it incorrectly. Let's do that!

Well, after reporting that bug in NetBeans (Update: I've tried the latest version and it works now!), I thought that I will just keep reporting this bug for every application. Next application on the list was Speedcrunch.

However, after looking for similar bug reports I found this issue. Someone else is having the same problem, great!

After reading the comments you will understand that this bug should be present in all QT apps. Here is a QT bug report. Not resolved, but it seems like the issue is solved in Qt5.

However, if you look at the comments, there's a workaround! Here is how it works. If you were doing this:

key <SPCE> { [ ISO_Level3_Shift ] }; 

Then you can change it to this:

key <SPCE> { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; 

And it will actually solve the problem for some of the applications! For example, Speedcrunch now works for me! Yay!

Summary

Right now any application should work correctly. If it doesn't, then you have to use type[Group1]="ONE_LEVEL". If you already have it, then you have to update your software. If it still does not work, then it is app-specific and you have to submit a bug report.

UPDATE (2017-09-23)

As of today, all applications respect my keyboard layout. All except one.

Seriously, keyboard handling in Chromium is garbage. There are several problems with it:

  • Shift selection does not with custom arrow keys (but arrow keys themselves work OK)
  • If you have multiple layouts and on one of the layouts some key is special (e.g. arrows, Backspace, etc.), then on another layout this key will be fixed to whatever you have on your first layout. For example, if you have two layouts: foo,bar and some key does Backspace in foo, then it will keep working as Backspace in bar even if it is redefined there.

For years I ignored these problems by simply not using chromium. However, nowadays things tend to use Electron, which is unfortunately built on Chromium.

The right way to resolve this would be to submit a bug report in Chromium and hope for the best. I don't know how long it will take them to resolve an issue that is only affecting a couple of users… but that seems to be the only way out. The problem with this is that chromium actually works fine with neo(de) layout. Neo layout has arrow keys on level5, but I can't get it to work in my custom layout.

Still-open bug reports:

Спасибо за информацию! Обходной путь не помогает мне, поэтому я думаю, что мне придется просто сообщать об ошибках и ждать преобразований qt5. nonpop 8 лет назад 0

Похожие вопросы