Comment faire en sorte que toutes les applications respectent ma disposition xkb modifiée?

15

Je n'aime pas sauter entre le clavier principal et les touches de mouvement, j'ai donc ajouté ce qui suit à mon fichier de mise en page 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      ] };
}

Ensuite, je les inclue dans la mise en page à un stade ultérieur du fichier. Maintenant, je devrais avoir les touches du curseur accessibles via AltGr + j, k, l, i (ou h, t, n, c car j'utilise dvorak) etc. Cela fonctionne dans de nombreux cas (comme Firefox, urxvt, Eclipse, le zone de texte principale de LyX) mais certains programmes ne font rien lorsque j'essaie, par exemple, de déplacer le curseur en utilisant ces "raccourcis" (comme les boîtes de dialogue NetBeans et LyX).

Alors, existe-t-il un moyen de faire en sorte que ces autres programmes respectent également mes souhaits? Et pourquoi ne travaillent-ils pas en premier lieu? Je n'utilise pas de DE; seulement le Awesome WM.

Éditer:

  • Voici un fichier de disposition de clavier complet mais simplifié. Je l'ai comme /usr/share/X11/xkb/symbols/nonpopet je le charge avec setxkbmap nonpop.
  • J'ai remarqué que dans MonoDevelop, le déplacement fonctionne, mais pas la sélection. Autrement dit, si j'appuie sur Maj + Droite, le texte est sélectionné comme d'habitude, mais si j'appuie sur AltGr + Maj + n, le curseur se déplace simplement sans sélection. Par exemple, dans Firefox, les deux méthodes peuvent être utilisées pour la sélection.
  • Ici, à la fin, ils parlent de superpositions qui ressemblent à quelque chose qui pourrait peut-être être une solution, mais je n'ai pas compris comment les utiliser.
non pop
la source
1
Je n'ai pas de solution, mais si vous n'arrivez pas à obtenir une réponse malgré la générosité que vous avez mise, vous pouvez essayer de demander à unix.SE , un site Stackexchange plus centré sur Unix / Linux.
Glutanimate

Réponses:

16

Pourquoi ne travaillent-ils pas

Selon l' article d'ArchWiki que vous avez mentionné:

  • Serveur X reçoit les codes d' activation du dispositif d'entrée et les convertit à l' état et keysym .

    • state est le masque binaire des modificateurs X (Ctrl / Shift / etc).

    • keysym est (selon /usr/include/X11/keysymdef.h) l'entier qui

      identifier les caractères ou fonctions associés à chaque touche (par exemple, via la gravure visible) d'une disposition de clavier.

      Chaque personnage a son propre imprimable keysym, comme plus, a, Aou Cyrillic_a, mais d' autres clés génèrent également leurs keysyms, comme Shift_L, Leftou F1.

  • L'application dans les événements clés de presse / libération obtient toutes ces informations.

    Certaines applications suivent les keyymes comme Control_Lpar elles-mêmes, d'autres recherchent simplement les bits de modification dans l' état .

Alors, que se passe-t-il lorsque vous appuyez sur AltGr+ j:

  • Vous appuyez AltGr. L'application obtient l'événement KeyPressed avec keycode 108 ( <RALT>) et keysym 0xfe03 ( ISO_Level3_Shift), l'état est 0.

  • Vous appuyez sur j(qui correspond à "h" dans dvorak sans modificateurs). L'application obtient l'événement KeyPressed avec keycode 44 ( <AC07>), keysym 0xff51 ( Left) et l'état 0x80 (le modificateur Mod5 est activé).

  • Vous relâchez j. L'application obtient l'événement KeyRelease pour la clé <AC07>/ Leftavec les mêmes paramètres.

  • Puis relâchez AltGr- événement KeyRelease pour AltGr. (Soit dit en passant, l'état ici est toujours 0x80, mais cela n'a pas d'importance.)

Cela peut être vu si vous exécutez l' xevutilitaire.

Donc, cela signifie que, bien que l'application obtienne le même code keysym ( Left) que la clé normale <LEFT>, elle obtient également le code keysym et l'état du modificateur de l'AltGr. Très probablement, ces programmes qui ne fonctionnent pas, surveillent les modificateurs et ne veulent pas fonctionner lorsque certains sont actifs.

Comment les faire fonctionner

Apparemment, nous ne pouvons pas changer chaque programme pour ne pas chercher de modificateurs. Ensuite, la seule option pour échapper à cette situation est de ne pas générer les clés de clés et les bits d'état des modificateurs.

1. Groupe distinct

La seule méthode qui me vient à l' esprit est: définir les touches de déplacement du curseur dans un groupe séparé et commutateur, avec appui sur une touche séparée, à ce groupe avant d'appuyer sur les touches j, k, l, i( h, t, n, c) (verrouillage groupe est la méthode préférée pour un changement de groupe de temps, si je comprends bien).

Par exemple:

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)" };
};

Maintenant, si vous appuyez d'abord AltGret ensuite (séparément) sur l'une des touches de mouvement, cela devrait fonctionner.

Cependant, ce n'est pas très utile, il serait plus approprié de LockGroup remplacer le verrouillage et d'appuyer sur AltGr avant et après le changement de groupe. Encore mieux peut-être SetGroup- alors AltGr sélectionnerait ce groupe uniquement en appuyant dessus, mais cela révèle aux applications le clavier de AltGr ( ISO_Group_Shift/ ISO_Group_Latch/ quoi que ce soit défini) (mais l'état du modificateur reste propre).

Mais ... il est également possible que l'application lise également les codes clés (les codes des vraies clés). Ensuite, il remarquera les «fausses» touches de curseur.

2. Superposition

La solution la plus «bas niveau» serait la superposition (comme le même article le décrit).

La superposition signifie simplement qu'une touche (clavier réel) renvoie le code de touche d'une autre touche. Le serveur X change le code clé d'une clé et calcule l'état du modificateur et le symbole de clé pour ce nouveau code clé, de sorte que l'application ne devrait pas remarquer le changement.

Mais les superpositions sont très limitées:

  • Il n'y a que 2 bits de contrôle de superposition dans le serveur X (c'est-à-dire qu'il peut y avoir au maximum 2 superpositions).
  • Chaque clé ne peut avoir qu'un seul code clé alternatif.

Pour le reste, l'implémentation est assez similaire à la méthode avec un groupe séparé:

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)" };
};

SetControlssignifie changer le bit de contrôle pendant que la touche est enfoncée et le restaurer au relâchement de la touche. Il devrait y avoir une fonction similaire LatchControls, mais xkbcompme donne

Error:            Unknown action LatchControls

sur la compilation de keymap.

(Soit dit en passant, j'utilise également dvorak et j'ai également remappé certaines touches de mouvement à des niveaux élevés de touches alphabétiques. votre question et cette réponse, maintenant je sais ce qu'est une superposition :).)

Chel
la source
Merci! J'ai en fait obtenu une autre réponse sur unix.se qui au premier abord semblait être parfait mais s'est avéré que certaines applications se comportaient toujours mal. Cette solution (superpositions) fonctionne également dans ces cas.
nonpop
Je viens de remarquer que google chrom [e | ium] s'en fiche non plus! :( Heureusement, je ne les utilise pas beaucoup.
nonpop
@nonpop goddamn chrome… J'ai ajouté une mise à jour à ma réponse superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko
Incroyable! Je recherche cela depuis des années! Il y a toujours un problème mineur avec Chromium où il interprète une pression sur Overlay1_Enable. J'ai le même symptôme qu'ici: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch
1
Je viens de résoudre le problème ci-dessus. Les touches fléchées de ma ligne d'accueil fonctionnent désormais également dans Chrome! J'avais besoin du changement suivant à cette réponse. gist.github.com/Tarrasch/1293692/…
Tarrasch
4

J'ai le même problème. C'est tellement douloureux.

Le titre est donc "Comment faire en sorte que toutes les applications respectent ma disposition xkb modifiée?". Eh bien, je pense que la seule façon est de corriger tous les programmes qui le font incorrectement. Faisons cela!

Eh bien, après avoir signalé ce bogue dans NetBeans ( mise à jour: j'ai essayé la dernière version et cela fonctionne maintenant! ), J'ai pensé que je continuerais à signaler ce bogue pour chaque application. La prochaine application sur la liste était Speedcrunch .

Cependant, après avoir recherché des rapports de bogues similaires, j'ai trouvé ce problème . Quelqu'un d'autre a le même problème, tant mieux!

Après avoir lu les commentaires, vous comprendrez que ce bug devrait être présent dans toutes les applications QT. Voici un rapport de bug QT . Pas résolu, mais il semble que le problème soit résolu dans Qt5 .

Cependant, si vous regardez les commentaires, il existe une solution de contournement! Voici comment cela fonctionne. Si vous faisiez cela:

key <SPCE> { [ ISO_Level3_Shift ] };

Ensuite, vous pouvez le changer en ceci:

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

Et cela résoudra le problème pour certaines applications! Par exemple, Speedcrunch fonctionne maintenant pour moi! Yay!

Résumé

À l'heure actuelle, toute application devrait fonctionner correctement. Si ce n'est pas le cas, vous devez utiliser type[Group1]="ONE_LEVEL". Si vous l'avez déjà, vous devez mettre à jour votre logiciel. Si cela ne fonctionne toujours pas, il est spécifique à l'application et vous devez soumettre un rapport de bogue.

MISE À JOUR (2017-09-23)

À ce jour, toutes les applications respectent ma disposition de clavier. Tous sauf un.

Sérieusement, la manipulation du clavier dans Chromium est une ordure . Il y a plusieurs problèmes avec:

  • La sélection de décalage ne fonctionne pas avec les touches fléchées personnalisées (mais les touches fléchées elles-mêmes fonctionnent bien)
  • Si vous avez plusieurs mises en page et sur l'une des mises en page, certaines touches sont spéciales (par exemple flèches, retour arrière, etc.), alors sur une autre mise en page, cette clé sera fixée sur tout ce que vous avez sur votre première mise en page. Par exemple, si vous avez deux dispositions: foo, baret une clé ne Backspace dans foo, alors il continuera à fonctionner comme dans Backspace barmême si elle y est redéfinie.

Pendant des années, j'ai ignoré ces problèmes en n'utilisant tout simplement pas de chrome. Cependant, de nos jours, les choses ont tendance à utiliser Electron , qui est malheureusement construit sur du chrome.

La bonne façon de résoudre ce problème serait de soumettre un rapport de bogue dans Chromium et d'espérer pour le mieux. Je ne sais pas combien de temps il leur faudra pour résoudre un problème qui n'affecte que quelques utilisateurs… mais cela semble être la seule issue. Le problème est que le chrome fonctionne bien avec la neo(de)mise en page. La disposition Neo a des touches fléchées au niveau 5, mais je ne peux pas la faire fonctionner dans ma disposition personnalisée.

Rapports de bogues encore ouverts:

Aleks-Daniel Jakimenko
la source
Merci pour l'info! La solution de contournement ne m'aide pas, donc je suppose que je devrai simplement signaler des bogues et attendre les conversions qt5.
nonpop
4

Comment les faire fonctionner - Solution 3

Utilisation de niveaux supplémentaires et d'une action RedirectKey

La solution suivante utilise la touche Alt gauche pour fournir des touches de curseur sur jkli, Home / End / PageUp / PageDown sur uopö et une suppression sur le retour arrière.

La touche Alt gauche reste utilisable à d'autres fins pour toutes les autres touches (comme pour le menu d'application). L'Alt gauche (Mod1) est supprimé de l'état du modificateur lorsque le bloc de curseur est utilisé afin que les applications ne puissent pas le voir.

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)" 
    };
};
mgl
la source
Holy moly! Cela fonctionne réellement! Il fonctionne autour des applications cassées comme Chrome. Pouvez-vous expliquer quelles sont ces définitions osf? Il semble qu'ils soient prédéfinis, vous ne pouvez donc pas les nommer au hasard.
Aleks-Daniel Jakimenko