Як зробити так, щоб усі програми поважали мій модифікований макет xkb?


15

Мені не подобається стрибати між головною клавіатурою та клавішами руху, тому я додав наступне у свій файл макета 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, як я використовую дворак) тощо. Це працює у багатьох випадках (як Firefox, urxvt, Eclipse, основна текстова область LyX), але деякі програми нічого не роблять, коли я намагаюся, скажімо, переміщувати курсор за допомогою цих "ярликів" (наприклад, діалогових вікон NetBeans та LyX).

Отже, чи є спосіб, щоб ці інші програми також поважали мої побажання? І чому вони працюють не в першу чергу? Я не використовую DE; тільки Awesome WM.

Редагувати:

  • Ось повний, але спрощений файл розкладки клавіатури. У мене це є, /usr/share/X11/xkb/symbols/nonpopі я його завантажую setxkbmap nonpop.
  • Я помітив, що в MonoDevelop переміщення працює, але вибір не відбувається. Тобто, якщо я натискаю Shift + Right, тоді текст вибирається як зазвичай, але якщо я натискаю AltGr + Shift + n, курсор просто рухається, не вибираючи. Наприклад, у Firefox обидва способи вибору можуть бути використані.
  • Тут , в кінці кінців , вони говорять про накладках , які виглядають як - то , що може бути , можливо , рішенням , але я не зрозумів, як використовувати їх.

1
У мене немає рішення, але якщо вам не вдасться отримати відповідь, незважаючи на виграшну суму, ви можете спробувати запитати на unix.SE , більш орієнтованому на Unix / Linux сервері Stackexchange.
Glutanimate

Відповіді:


16

Чому вони не працюють

Відповідно до статті Аркі Вікі, яку ви згадали:

  • X сервер отримує клавішні коди від пристрою введення та перетворює їх у стан та keyym .

    • стан - це бітова маска модифікаторів X (Ctrl / Shift / тощо).

    • keyym - це (відповідно /usr/include/X11/keysymdef.h) ціле число, яке

      ідентифікуйте символи або функції, пов’язані з кожною клавішею (наприклад, через видиму гравію) макета клавіатури.

      Кожен друкований символ має свій власний символ клавіші, як plus, a, Aабо Cyrillic_a, але інші клавіші також генерують свої символи клавіш, як Shift_L, Leftабо F1.

  • Програма в ключових подіях преси / випуску отримує всю цю інформацію.

    Деякі програми відслідковують ключові ключі, як Control_Lсамі по собі, інші просто шукають біти модифікатора в стані .

Що ж станеться, натиснувши AltGr+ j:

  • Ви натискаєте AltGr. Програма отримує KeyPress подія з кодом 108 ( <RALT>) та keyym 0xfe03 ( ISO_Level3_Shift), стан 0.

  • Ви натискаєте j(яка відображає "h" у двораку без модифікаторів). Програма отримує подію KeyPress із кодом 44 ( <AC07>), keyym 0xff51 ( Left) та станом 0x80 (модифікатор Mod5 увімкнено).

  • Ви звільняєте j. Додаток отримує KeyRelease подія для ключа <AC07>/ Leftз тими ж параметрами.

  • Потім випуск AltGr- подія KeyRelease для AltGr. (До речі, стан тут все ще 0x80, але це не має значення.)

Це можна побачити, якщо ви запускаєте xevутиліту.

Отже, це все означає, що, хоча програма отримує той самий keyym-код ( Left), як і від звичайного ключа <LEFT>, він також отримує код keyym та стан модифікатора від 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

при складанні ключових карт

(До речі, я також користуюся двораком, а також перекомпонував деякі клавіші руху на високі рівні алфавітних клавіш. А також натрапив на деякий невдалий функціонал (вибір у примітках Xfce та комутатор на робочому столі Ctrl-Alt-Left / Right). Завдяки ваше запитання та ця відповідь, тепер я знаю, що таке накладення :).)


Спасибі! Насправді я отримав ще одну відповідь на unix.se, яка спочатку здавалася ідеальною, але виявилося, що деякі додатки все ще не поводилися. Це рішення (накладки) працює і в цих випадках.
nonpop

Я щойно помітила, що Google Chrome [e | ium] теж не переймається цим питанням! :( На щастя, я їх не дуже використовую.
nonpop

@nonpop проклятий хром ... Я додав оновлення до своєї відповіді superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko

Дивовижний! Я шукав це протягом багатьох років! Існує ще незначна проблема з Chromium, де він інтерпретує натискання клавіш Overlay1_Enable. У мене такий же симптом, як і тут: github.com/GalliumOS/galliumos-distro/isissue/362
Тарраш

1
Мені просто вдалося виправити вищезазначене питання. Мої клавіші зі стрілками для домашнього ряду зараз також працюють у Chromium! Мені потрібна наступна зміна цієї відповіді. gist.github.com/Tarrasch/1293692/…
Тарраш

4

У мене така ж проблема. Це так боляче.

Отже, заголовок "Як змусити всі програми дотримуватися моєї модифікованої схеми xkb?". Ну, я думаю, єдиний спосіб - це виправити всі програми, які роблять це неправильно. Зробимо це!

Ну, після повідомлення про цю помилку в NetBeans ( оновлення: я спробував останню версію, і вона працює зараз! ), Я подумав, що я буду постійно повідомляти про цю помилку для кожної програми. Наступною заявкою у списку була Speedcrunch .

Однак, шукаючи подібні повідомлення про помилки, я знайшов цю проблему . У когось іншого є така ж проблема, чудово!

Прочитавши коментарі, ви зрозумієте, що ця помилка повинна бути присутнім у всіх QT-програмах. Ось звіт про помилки QT . Не вирішено, але, схоже, питання вирішено в Qt5 .

Однак якщо ви подивитесь на коментарі, є рішення! Ось як це працює. Якщо ви робили це:

key <SPCE> { [ ISO_Level3_Shift ] };

Тоді ви можете змінити це на це:

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

І це фактично вирішить проблему для деяких додатків! Наприклад, Speedcrunch зараз працює для мене! Так!

Підсумок

Зараз будь-яка програма повинна працювати коректно. Якщо цього немає, то вам доведеться скористатися type[Group1]="ONE_LEVEL". Якщо у вас вже є, то вам доведеться оновити програмне забезпечення. Якщо вона все ще не працює, це специфічно для додатка, і вам потрібно надіслати звіт про помилку.

ОНОВЛЕННЯ (2017-09-23)

На сьогоднішній день всі програми поважають мою клавіатуру. Усі, крім одного.

Серйозно, керування клавіатурою в Chromium - це сміття . З цим є кілька проблем:

  • Вибір Shift не відбувається за допомогою спеціальних клавіш зі стрілками (але самі клавіші зі стрілками працюють ОК)
  • Якщо у вас є декілька макетів і на одному з макетів якась клавіша є спеціальною (наприклад, стрілками, Backspace тощо), то в іншому макеті ця клавіша буде зафіксована на тому, що ви маєте на своєму першому макеті. Наприклад, якщо у вас є дві розкладки: foo, barі деякі ключові робить Backspace в foo, то він буде продовжувати працювати , як Backspace в barнавіть якщо він перевизначений там.

Протягом багатьох років я ігнорував ці проблеми, просто не використовуючи хром. Однак сьогодні тенденція використовує Електрон , який, на жаль, побудований на Chromium.

Правильним способом вирішити це буде подання звіту про помилки в Chromium та сподівання на найкраще. Я не знаю, скільки часу знадобиться їм, щоб вирішити проблему, яка зачіпає лише пару користувачів ... але, здається, це єдиний вихід. Проблема в цьому полягає в тому, що хром насправді добре справляється з neo(de)компонуванням. У Neo layout є клавіші зі стрілками на рівні 5, але я не можу змусити його працювати в моєму власному макеті.

Досі відкриті звіти про помилки:


Дякую за інформацію! Вирішення проблеми не допомагає мені, тому, мабуть, доведеться просто повідомляти про помилки та чекати перетворення qt5.
nonpop

4

Як змусити їх працювати - Рішення 3

Використання додаткових рівнів та дій RedirectKey

Наступне рішення використовує ліву клавішу Alt для надання клавіш курсору на jkli, Home / End / PageUp / PageDown on uopö та Delete on Backspace.

Ліва клавіша Alt залишається доступною для інших цілей для всіх інших клавіш (наприклад, у меню програми). Лівий Alt (Mod1) видаляється зі стану модифікатора, коли використовується блок курсору, тому програми не можуть його бачити.

xkb_keymap {
    xkb_keycodes { 
        include "evdev+aliases(qwertz)" 
    };
    xkb_types { 
        include "complete"  
    };
    xkb_compat { 
        include "complete"
        interpret osfLeft {
            action = RedirectKey(keycode=<LEFT>, clearmodifiers=Mod1);
        };
        interpret osfRight {
            action = RedirectKey(keycode=<RGHT>, clearmodifiers=Mod1);
        };
        interpret osfUp {
            action = RedirectKey(keycode=<UP>, clearmodifiers=Mod1);
        };
        interpret osfDown {
            action = RedirectKey(keycode=<DOWN>, clearmodifiers=Mod1);
        };
        interpret osfBeginLine {
            action = RedirectKey(keycode=<HOME>, clearmodifiers=Mod1);
        };
        interpret osfEndLine {
            action = RedirectKey(keycode=<END>, clearmodifiers=Mod1);
        };
        interpret osfPageUp {
            action = RedirectKey(keycode=<PGUP>, clearmodifiers=Mod1);
        };
        interpret osfPageDown {
            action = RedirectKey(keycode=<PGDN>, clearmodifiers=Mod1);
        };
        interpret osfDelete {
            action = RedirectKey(keycode=<DELE>, clearmodifiers=Mod1);
        };
    };
    xkb_symbols { 
        include "pc+de(nodeadkeys)"
        include "inet(evdev)"
        include "compose(rwin)"
        key <LALT> {
            type[Group1] = "ONE_LEVEL",
            symbols[Group1] = [ ISO_Level5_Shift ]
        };
        modifier_map Mod1 { <LALT> };
        key <AC07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ j, J, dead_belowdot, dead_abovedot, osfLeft, osfLeft, osfLeft, osfLeft ]
        };
        key <AC08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ k, K, kra, ampersand, osfDown, osfDown, osfDown, osfDown ]
        };
        key <AC09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ l, L, lstroke, Lstroke, osfRight, osfRight, osfRight, osfRight ]
        };
        key <AC10> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ odiaeresis, Odiaeresis, doubleacute, doubleacute, osfPageDown, osfPageDown, osfPageDown, osfPageDown ]
        };
        key <AD07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ u, U, downarrow, uparrow, osfBeginLine, osfBeginLine, osfBeginLine, osfBeginLine ]
        };
        key <AD08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ i, I, rightarrow, idotless, osfUp, osfUp, osfUp, osfUp ]
        };
        key <AD09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ o, O, oslash, Oslash, osfEndLine, osfEndLine, osfEndLine, osfEndLine ]
        };
        key <AD10> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ p, P, thorn, THORN, osfPageUp, osfPageUp, osfPageUp, osfPageUp ]
        };
        key <BKSP> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ BackSpace, BackSpace, BackSpace, BackSpace, osfDelete, osfDelete, osfDelete, osfDelete ] 
        };
    };
    xkb_geometry { 
        include "pc(pc105)" 
    };
};

Святий молі! Це насправді працює! Він працює навколо зламаних програм, таких як Chromium. Чи можете ви пояснити, що це за визначення OSF? Здається, що вони заздалегідь визначені, тому ви не можете назвати їх випадковим чином.
Алекс-Даніель Якименко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.