Wie kann ich dafür sorgen, dass alle Anwendungen mein geändertes xkb-Layout respektieren?

15

Ich mag es nicht, zwischen der Haupttastatur und den Bewegungstasten zu springen, deshalb habe ich meiner xkb-Layoutdatei Folgendes hinzugefügt.

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      ] };
}

Dann füge ich diese zu einem späteren Zeitpunkt in die Datei ein. Jetzt sollte ich die Cursortasten über AltGr + j, k, l, i (oder h, t, n, c, wie ich dvorak verwende) usw. haben. Dies funktioniert in vielen Fällen (wie Firefox, urxvt, Eclipse, the Haupttextbereich von LyX), aber einige Programme tun nichts, wenn ich beispielsweise versuche, den Cursor mit diesen "Verknüpfungen" zu bewegen (wie NetBeans- und LyX-Dialoge).

Gibt es eine Möglichkeit, diese anderen Programme dazu zu bringen, auch meine Wünsche zu respektieren? Und warum arbeiten sie überhaupt nicht? Ich benutze kein DE; nur die Awesome WM.

Bearbeiten:

  • Hier ist eine vollständige, aber vereinfachte Tastaturlayoutdatei. Ich habe das als /usr/share/X11/xkb/symbols/nonpopund lade es mit setxkbmap nonpop.
  • Mir ist aufgefallen, dass in MonoDevelop das Bewegen funktioniert, das Auswählen jedoch nicht. Das heißt, wenn ich Umschalt + Rechts drücke, wird der Text wie gewohnt ausgewählt, aber wenn ich AltGr + Umschalt + n drücke, bewegt sich der Cursor nur ohne Auswahl. In Firefox können beispielsweise beide Möglichkeiten zur Auswahl verwendet werden.
  • Hier sprechen sie am Ende über Overlays, die wie eine Lösung aussehen könnten, aber ich habe nicht herausgefunden, wie man sie verwendet.
nonpop
quelle
1
Ich habe keine Lösung, aber wenn Sie trotz der von Ihnen bereitgestellten Prämie keine Antwort erhalten, können Sie versuchen, bei unix.SE , einer stärker auf Unix / Linux ausgerichteten Stackexchange-Site, nachzufragen.
Glutanimate

Antworten:

16

Warum funktionieren sie nicht?

Laut dem von Ihnen erwähnten Artikel im ArchWiki :

  • Der X-Server erhält Schlüsselcodes vom Eingabegerät und konvertiert sie in den Status und das Keysym .

    • state ist die Bitmaske der X-Modifikatoren (Strg / Umschalt / etc).

    • Keysym ist (nach /usr/include/X11/keysymdef.h) der ganzen Zahl, die

      Identifizieren von Zeichen oder Funktionen, die jeder Taste zugeordnet sind (z. B. über die sichtbare Gravur) eines Tastaturlayouts.

      Jedes druckbare Zeichen hat seine eigene keysym, wie plus, a, Aoder Cyrillic_a, aber auch andere Schlüssel erzeugen auch ihre Keysyms, wie Shift_L, Leftoder F1.

  • Die Anwendung in den wichtigsten Presse- / Release-Ereignissen erhält alle diese Informationen.

    Einige Anwendungen verfolgen Keysyms wie Control_Lvon selbst, andere suchen nur nach den Modifikatorbits im Status .

Was passiert also, wenn Sie AltGr+ drücken j:

  • Sie drücken AltGr. Die Anwendung erhält das KeyPressed-Ereignis mit dem Schlüsselcode 108 ( <RALT>) und dem Keysym 0xfe03 ( ISO_Level3_Shift). Der Status ist 0.

  • Sie drücken j(was in dvorak ohne Modifikatoren „h“ zugeordnet ist). Die Anwendung erhält das KeyPressed-Ereignis mit dem Schlüsselcode 44 ( <AC07>), dem Keysym 0xff51 ( Left) und dem Status 0x80 (Modifikator Mod5 ist aktiviert).

  • Sie freigeben j. Die Anwendung erhält das KeyRelease-Ereignis für den Schlüssel <AC07>/ Leftmit denselben Parametern.

  • Dann Release AltGr- KeyRelease-Ereignis für AltGr. (Übrigens ist der Zustand hier immer noch 0x80, aber das spielt keine Rolle.)

Dies wird angezeigt, wenn Sie das xevDienstprogramm ausführen .

Das alles bedeutet also, dass die Anwendung zwar denselben Keysym-Code ( Left) wie der normale Schlüssel <LEFT>erhält, aber auch den Keysym-Code und den Modifikatorstatus von AltGr. Höchstwahrscheinlich beobachten Programme, die nicht funktionieren, die Modifikatoren und möchten nicht funktionieren, wenn einige aktiv sind.

Wie man sie zum Laufen bringt

Anscheinend können wir nicht jedes Programm so ändern, dass es nicht nach Modifikatoren sucht. Die einzige Möglichkeit, dieser Situation zu entkommen, besteht darin, keine Schlüsselsymbole und Statusbits der Modifikatoren zu generieren.

1. Separate Gruppe

Die einzige Methode, die mir einfällt , ist: Cursor - Bewegungstasten in einer separaten Gruppe und Schalter, mit einer separaten Taste drücken, um die Gruppe zu definieren , bevor die Schlüssel zu drücken j, k, l, i( h, t, n, c) (Gruppe Rast ist die bevorzugte Methode für einen einmaligen Gruppenwechsel, wie ich verstehe).

Beispielsweise:

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

Wenn Sie jetzt zuerst AltGrund dann (separat) eine der Bewegungstasten drücken , sollte dies funktionieren.

Dies ist jedoch nicht sehr nützlich. Besser wäre es, LockGroup vor und nach dem Gruppenwechsel anstelle von Latch AltGr zu drücken und zu drücken. Auch kann besser sein, SetGroup- dann AltGr diese Gruppe wählen würde nur während gedrückt wird, aber das ist bekannt , auf die Anwendungen AltGr des keysym ( ISO_Group_Shift/ ISO_Group_Latch/ was auch immer definiert ist) (aber Modifikator Zustand bleibt sauber).

Aber ... es besteht auch die Möglichkeit, dass die Anwendung auch Schlüsselcodes (die Codes der realen Schlüssel) liest. Dann werden die "falschen" Cursortasten bemerkt.

2. Überlagerung

Die "Low-Level" -Lösung wäre das Overlay (wie im selben Artikel beschrieben).

Überlagerung bedeutet einfach, dass eine (echte Tastatur-) Taste den Schlüsselcode einer anderen Taste zurückgibt. Der X-Server ändert den Schlüsselcode eines Schlüssels und berechnet den Modifikatorstatus und das Schlüsselsymbol für diesen neuen Schlüsselcode, sodass die Anwendung die Änderung nicht bemerken sollte.

Überlagerungen sind jedoch sehr begrenzt:

  • Es gibt nur 2 Overlay-Steuerbits im X-Server (dh es können maximal 2 Overlays vorhanden sein).
  • Jeder Schlüssel kann nur einen alternativen Schlüsselcode haben.

Im Übrigen ähnelt die Implementierung der Methode mit einer separaten Gruppe:

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

SetControlsbedeutet, das Steuerbit zu ändern, während die Taste gedrückt wird, und es bei der Tastenfreigabe wiederherzustellen. Es sollte eine ähnliche Funktion geben LatchControls, xkbcompgibt mir aber

Error:            Unknown action LatchControls

auf Keymap-Kompilierung.

(Übrigens verwende ich auch dvorak und habe einige Bewegungstasten auf hohe Ebenen alphabetischer Tasten neu zugeordnet. Außerdem bin ich auf einige Funktionsstörungen gestoßen (Auswahl in Xfce-Notizen und Desktop-Schalter durch Strg-Alt-Links / Rechts). Dank deine Frage und diese Antwort, jetzt weiß ich was ein Overlay ist :).)

Chel
quelle
Vielen Dank! Ich habe tatsächlich eine andere Antwort auf unix.se erhalten, die zunächst perfekt zu sein schien, sich aber herausstellte, dass sich einige Anwendungen immer noch schlecht benahmen . Diese Lösung (Overlays) funktioniert auch in diesen Fällen.
Nonpop
Mir ist gerade aufgefallen, dass Google Chrom [e | ium] sich auch nicht darum kümmert! :( Zum Glück benutze ich sie nicht viel.
nonpop
@nonpop goddamn Chrom ... Ich habe ein Update auf meine Antwort hinzugefügt superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko
Tolle! Ich habe jahrelang danach gesucht! Es gibt immer noch ein kleines Problem mit Chromium, bei dem ein Tastendruck von interpretiert wird Overlay1_Enable. Ich habe das gleiche Symptom wie hier: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch
1
Ich habe es gerade geschafft, das obige Problem zu beheben. Meine Pfeiltasten in der Startzeile funktionieren jetzt auch in Chrom! Ich brauchte die folgende Änderung an dieser Antwort. gist.github.com/Tarrasch/1293692/…
Tarrasch
4

Ich habe das gleiche Problem. Es ist so schmerzhaft.

Der Titel lautet also „Wie können alle Anwendungen mein geändertes xkb-Layout respektieren?“. Nun, ich denke, der einzige Weg ist, alle Programme zu reparieren, die es falsch machen. Lass uns das tun!

Nachdem ich diesen Fehler in NetBeans gemeldet hatte ( Update: Ich habe die neueste Version ausprobiert und sie funktioniert jetzt! ), Dachte ich, dass ich diesen Fehler weiterhin für jede Anwendung melden werde. Die nächste Anwendung auf der Liste war Speedcrunch .

Nachdem ich nach ähnlichen Fehlerberichten gesucht hatte, fand ich dieses Problem . Jemand anderes hat das gleiche Problem, großartig!

Nachdem Sie die Kommentare gelesen haben, werden Sie verstehen, dass dieser Fehler in allen QT-Apps vorhanden sein sollte. Hier ist ein QT-Fehlerbericht . Nicht gelöst, aber es scheint, dass das Problem in Qt5 gelöst ist .

Wenn Sie sich jedoch die Kommentare ansehen, gibt es eine Problemumgehung! So funktioniert es. Wenn Sie dies taten:

key <SPCE> { [ ISO_Level3_Shift ] };

Dann können Sie es folgendermaßen ändern:

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

Und es wird tatsächlich das Problem für einige der Anwendungen lösen! Zum Beispiel funktioniert Speedcrunch jetzt für mich! Yay!

Zusammenfassung

Im Moment sollte jede Anwendung korrekt funktionieren. Wenn nicht, müssen Sie verwenden type[Group1]="ONE_LEVEL". Wenn Sie es bereits haben, müssen Sie Ihre Software aktualisieren. Wenn es immer noch nicht funktioniert, ist es app-spezifisch und Sie müssen einen Fehlerbericht einreichen.

UPDATE (23.09.2017)

Ab heute respektieren alle Anwendungen mein Tastaturlayout. Alle bis auf einen.

Im Ernst, die Handhabung der Tastatur in Chrom ist Müll . Es gibt mehrere Probleme damit:

  • Die Umschaltauswahl funktioniert nicht mit benutzerdefinierten Pfeiltasten (aber die Pfeiltasten selbst funktionieren in Ordnung).
  • Wenn Sie mehrere Layouts haben und in einem der Layouts ein Schlüssel speziell ist (z. B. Pfeile, Rücktaste usw.), wird dieser Schlüssel in einem anderen Layout auf das festgelegt, was Sie in Ihrem ersten Layout haben. Zum Beispiel, wenn Sie zwei Layouts haben: foo, barund einige Schlüssel tun Rück in foo, dann wird es halten , wie Rück arbeitet in , barauch wenn es dort neu definiert wird.

Ich habe diese Probleme jahrelang ignoriert, indem ich einfach kein Chrom verwendet habe. Heutzutage tendieren die Dinge jedoch dazu, Electron zu verwenden , das leider auf Chrom aufgebaut ist.

Der richtige Weg, dies zu beheben, wäre, einen Fehlerbericht in Chromium einzureichen und auf das Beste zu hoffen. Ich weiß nicht, wie lange sie brauchen werden, um ein Problem zu lösen, das nur einige Benutzer betrifft… aber das scheint der einzige Ausweg zu sein. Das Problem dabei ist, dass Chrom tatsächlich gut mit dem neo(de)Layout funktioniert . Das Neo-Layout verfügt über Pfeiltasten auf Ebene 5, aber ich kann es in meinem benutzerdefinierten Layout nicht zum Laufen bringen.

Noch offene Fehlerberichte:

Aleks-Daniel Jakimenko
quelle
Danke für die Information! Die Problemumgehung hilft mir nicht weiter. Ich denke, ich muss nur Fehler melden und auf qt5-Konvertierungen warten.
Nonpop
4

So funktionieren sie - Lösung 3

Verwenden zusätzlicher Ebenen und Aktion RedirectKey

Die folgende Lösung verwendet die linke Alt-Taste, um Cursortasten auf jkli, Home / End / PageUp / PageDown auf uopö und Löschen auf der Rücktaste bereitzustellen.

Die linke Alt-Taste kann für alle anderen Tasten (wie für das Anwendungsmenü) für andere Zwecke verwendet werden. Das linke Alt (Mod1) wird aus dem Modifikatorstatus entfernt, wenn der Cursorblock verwendet wird, sodass Anwendungen ihn nicht sehen können.

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
quelle
Heiliger Moly! Das funktioniert tatsächlich! Es funktioniert um kaputte Anwendungen wie Chromium. Können Sie erklären, was diese OSF-Definitionen sind? Es scheint, dass sie vordefiniert sind, sodass Sie sie nicht zufällig benennen können.
Aleks-Daniel Jakimenko