Pourquoi ne fonctionnent-ils pas ?
D'après l'article d'ArchWiki que vous avez mentionné :
-
Le serveur X obtient les codes clés du périphérique d'entrée et les convertit à l'état et keysym .
-
état est le masque de bits des modificateurs X (Ctrl/Maj/etc).
-
keysym est (selon
/usr/include/X11/keysymdef.h
) l'entier quiidentifier les caractères ou les fonctions associées à chaque touche (par exemple, via la gravure visible) d'une disposition de clavier.
Chaque caractère imprimable a son propre keysym, comme
plus
,a
,A
, ouCyrillic_a
, mais d'autres clés génèrent également leurs keysyms, commeShift_L
,Left
ouF1
.
-
-
L'application dans les événements clés de presse/libération obtient toutes ces informations.
Certaines applications suivent les keysyms comme
Control_L
par eux-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 sur AltGr . L'application obtient l'événement KeyPressed avec keycode108 (
<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 le code clé 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>
/Left
avec les mêmes paramètres. -
Relâchez ensuite AltGr — Événement KeyRelease pour AltGr. (Au fait, l'état ici est toujours 0x80, mais cela n'a pas d'importance.)
Cela peut être vu si vous exécutez xev
utilitaire.
Donc, tout cela signifie que, bien que l'application obtienne le même code keysym (Left
) à partir de la clé normale <LEFT>
, il 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 modifier chaque programme pour ne pas rechercher de modificateurs. Alors la seule option pour échapper à cette situation est de ne pas générer les keysyms et les bits d'état des modificateurs.
1. Groupe séparé
La seule méthode qui me vient à l'esprit est la suivante :définir les touches de déplacement du curseur dans un groupe séparé et basculer, avec une touche distincte, vers ce groupe avant d'appuyer sur les touches j , k , l , je (h
,t
, n
, c
) (le verrouillage de groupe est la méthode préférée pour un changement de groupe ponctuel, si j'ai bien compris).
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 sur AltGr puis (séparément) une des touches de déplacement, cela devrait fonctionner.
Cependant, ce n'est pas très utile, il serait plus approprié de LockGroup
au lieu de verrouiller et appuyez sur AltGr avant et après le changement de groupe. Encore mieux peut-être à SetGroup
- alors AltGr sélectionnerait ce groupe uniquement lorsqu'il est pressé, mais cela divulgue aux applications le keysym(ISO_Group_Shift
/ISO_Group_Latch
/tout ce qui est défini) (mais l'état du modificateur reste propre).
Mais... il reste aussi une possibilité 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 "de bas niveau" serait la superposition (comme le décrit le même article).
Superposition signifie simplement qu'une touche (du clavier réel) renvoie le code d'une autre touche. Le serveur X modifie le code clé d'une clé et calcule l'état du modificateur et le keysym 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 un maximum de 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 à part :
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
signifie 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
, maisxkbcomp
me donne
Error: Unknown action LatchControls
sur la compilation du keymap.
(Au fait, j'utilise également dvorak et j'ai également remappé certaines touches de mouvement à des niveaux élevés de touches alphabétiques. Et j'ai également rencontré des fonctionnalités cassées (sélection dans les notes Xfce et commutateur de bureau par Ctrl-Alt-Gauche/Droite). Merci à votre question et cette réponse, maintenant je sais ce qu'est une superposition :).)
Comment les faire fonctionner - Solution 3
Utilisation de niveaux supplémentaires et d'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 de l'application). L'Alt gauche (Mod1) est supprimé de l'état du modificateur lorsque le bloc 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)"
};
};
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 mise en page xkb modifiée ?". Eh bien, je pense que le seul moyen est de corriger tous les programmes qui le font de manière incorrecte. Allons-y !
Eh bien, après avoir signalé ce bogue dans NetBeans (Mise à jour :j'ai essayé la dernière version et elle fonctionne maintenant ! ), j'ai pensé que je continuerai à signaler ce bogue pour chaque application. L'application suivante 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, super !
Après avoir lu les commentaires, vous comprendrez que ce bogue devrait être présent dans toutes les applications QT. Voici un rapport de bogue QT. Non 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 ceci :
key <SPCE> { [ ISO_Level3_Shift ] };
Ensuite, vous pouvez le remplacer par ceci :
key <SPCE> {
type[Group1]="ONE_LEVEL",
symbols[Group1] = [ ISO_Level3_Shift ]
};
Et cela résoudra en fait le problème pour certaines applications ! Par exemple, Speedcrunch fonctionne maintenant pour moi! Youpi !
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, cela est spécifique à l'application et vous devez soumettre un rapport de bogue.
MISE À JOUR (2017-09-23)
A ce jour, toutes les applications respectent la disposition de mon clavier. Tous sauf un.
Sérieusement, la gestion du clavier dans Chromium est une poubelle . Il y a plusieurs problèmes avec :
- Maj sélection ne fonctionne pas avec les touches fléchées personnalisées (mais les touches fléchées elles-mêmes fonctionnent correctement)
- Si vous avez plusieurs mises en page et que sur l'une des mises en page, une touche est spéciale (par exemple, flèches, retour arrière, etc.), alors sur une autre mise en page, cette touche sera fixée à ce que vous avez sur votre première mise en page. Par exemple, si vous avez deux mises en page :
foo
,bar
et une touche fait un retour arrière enfoo
, il continuera alors à fonctionner comme retour arrière dansbar
même s'il y est redéfini.
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 Chromium.
La bonne façon de résoudre ce problème serait de soumettre un rapport de bogue dans Chromium et d'espérer le meilleur. 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 avec ceci est que le chrome fonctionne bien avec neo(de)
disposition. La mise en page Neo a des touches fléchées au niveau 5, mais je n'arrive pas à la faire fonctionner dans ma mise en page personnalisée.
Rapports de bugs encore ouverts :
- Pluma – https://github.com/mate-desktop/pluma/issues/17