Come fare in modo che tutte le applicazioni rispettino il mio layout xkb modificato?


15

Non mi piace saltare tra la tastiera principale e i tasti di movimento, quindi ho aggiunto quanto segue al mio file di layout 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      ] };
}

Quindi li includo nel layout in un momento successivo del file. Ora dovrei avere i tasti cursore accessibili tramite AltGr + j, k, l, i (o h, t, n, c mentre sto usando dvorak) ecc. Funziona in molti casi (come Firefox, urxvt, Eclipse, il area di testo principale di LyX) ma alcuni programmi non fanno nulla quando provo, per esempio, a spostare il cursore usando queste "scorciatoie" (come le finestre di dialogo NetBeans e LyX).

Quindi, c'è un modo per fare in modo che anche questi altri programmi rispettino i miei desideri? E perché non stanno lavorando in primo luogo? Non sto usando un DE; solo il fantastico WM.

Modificare:

  • Ecco un file di layout di tastiera completo ma semplificato. Ho questo come /usr/share/X11/xkb/symbols/nonpope lo carico con setxkbmap nonpop.
  • Ho notato che in MonoDevelop lo spostamento funziona ma la selezione no. Cioè, se premo Maiusc + Destra, il testo viene selezionato come al solito, ma se premo AltGr + Maiusc + n, il cursore si sposta semplicemente senza selezionare. Ad esempio, in Firefox è possibile utilizzare entrambi i modi per selezionare.
  • Qui alla fine parlano di sovrapposizioni che sembrano qualcosa che potrebbe forse essere una soluzione ma non ho capito come usarle.

1
Non ho una soluzione, ma se non riesci a ottenere una risposta nonostante la taglia che hai messo, potresti provare a chiedere a unix.SE , un sito Stackexchange più centrato su Unix / Linux.
Glutanimate,

Risposte:


16

Perché non funzionano?

Secondo l' articolo di ArchWiki che hai citato:

  • Il server X ottiene i codici chiave dal dispositivo di input e li converte nello stato e nel keyym .

    • state è la maschera di bit dei modificatori X (Ctrl / Shift / etc).

    • keysym è (secondo /usr/include/X11/keysymdef.h) il numero intero che

      identificare i caratteri o le funzioni associate a ciascun tasto (ad es. tramite l'incisione visibile) di un layout di tastiera.

      Ogni carattere stampabile ha un proprio keysym, come plus, a, A, o Cyrillic_a, ma altri tasti generare anche i loro keysyms, come Shift_L, Lefto F1.

  • L'applicazione nel tasto premi / rilascia eventi ottiene tutte queste informazioni.

    Alcune applicazioni tengono traccia delle key palestra come Control_Lda sole, altre cercano semplicemente i bit modificatori nello stato .

Quindi cosa succede quando si preme AltGr+ j:

  • Tu premi AltGr. L'applicazione ottiene l'evento KeyPressed con keycode 108 ( <RALT>) e keysym 0xfe03 ( ISO_Level3_Shift), lo stato è 0.

  • Si preme j(che mappa su "h" in dvorak senza modificatori). L'applicazione ottiene l'evento KeyPressed con keycode 44 ( <AC07>), keysym 0xff51 ( Left) e stato 0x80 (il modificatore Mod5 è attivo).

  • Rilasci j. L'applicazione ottiene l'evento KeyRelease per la chiave <AC07>/ Leftcon gli stessi parametri.

  • Quindi rilasciare AltGr- Evento KeyRelease per AltGr. (A proposito, lo stato qui è ancora 0x80, ma non importa.)

Questo può essere visto se si esegue l' xevutilità.

Quindi, tutto ciò significa che, sebbene l'applicazione ottenga lo stesso codice keysym ( Left) della chiave normale <LEFT>, ottiene anche il codice keysym e lo stato modificatore da AltGr. Molto probabilmente, quei programmi che non funzionano, guardano i modificatori e non vogliono lavorare quando alcuni sono attivi.

Come farli funzionare

Apparentemente, non possiamo cambiare ogni programma per non cercare modificatori. Quindi l'unica opzione per sfuggire a questa situazione è quella di non generare i keymont dei modificatori e i bit di stato.

1. Gruppo separato

L'unico metodo che viene in mente è: definire tasti di movimento del cursore in un gruppo e interruttore separato, premendo un tasto separato, a quel gruppo prima premendo i tasti j, k, l, i( h, t, n, c) (gruppo di bloccaggio è il metodo preferito per una volta il cambio di gruppo, come ho capito).

Per esempio:

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

Ora, se prima premi AltGre poi (separatamente) uno dei tasti di movimento, questo dovrebbe funzionare.

Tuttavia, questo non è molto utile, sarebbe più appropriato LockGroup invece di agganciare e premere AltGr prima e dopo il cambio di gruppo. Ancora meglio potrebbe essere SetGroup- allora AltGr selezionerebbe quel gruppo solo mentre viene premuto, ma questo rivela alle applicazioni il keyym di AltGr ( ISO_Group_Shift/ ISO_Group_Latch/ qualunque cosa sia definito) (ma lo stato del modificatore rimane pulito).

Ma ... c'è anche la possibilità che l'applicazione legga anche i codici chiave (i codici delle chiavi reali). Quindi noterà i tasti cursore "falso".

2. Sovrapposizione

La soluzione più "di basso livello" sarebbe la sovrapposizione (come descritto nello stesso articolo ).

Overlay significa semplicemente che un tasto (tastiera reale) restituisce il codice tasto di un altro tasto. Il server X cambia il codice chiave di una chiave e calcola lo stato del modificatore e il keyym per quel nuovo codice chiave, quindi l'applicazione non dovrebbe notare la modifica.

Ma le sovrapposizioni sono molto limitate:

  • Esistono solo 2 bit di controllo overlay nel server X (ovvero possono esserci al massimo 2 overlay).
  • Ogni chiave può avere solo 1 codice chiave alternativo.

Per il resto, l'implementazione è abbastanza simile al metodo con un gruppo separato:

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

SetControlssignifica cambiare il bit di controllo mentre il tasto è premuto e ripristinarlo al rilascio del tasto. Dovrebbe esserci una funzione simile LatchControls, ma xkbcompmi dà

Error:            Unknown action LatchControls

sulla compilazione di keymap.

(A proposito, uso anche dvorak e ho anche rimappato alcune tastiere di movimento ad alti livelli di chiavi alfabetiche. E ho anche riscontrato alcune funzionalità rotte (selezione nelle note di Xfce e cambio desktop da Ctrl-Alt-Sinistra / Destra). Grazie a la tua domanda e questa risposta, ora so cos'è un overlay :).)


Grazie! In realtà ho ottenuto un'altra risposta su unix.se che all'inizio sembrava essere perfetto, ma alcune applicazioni si sono comportate in modo errato . Questa soluzione (overlay) funziona anche in questi casi.
nonpop

Ho appena notato che google chrom [e | ium] non si preoccupa neanche di questo! :( Fortunatamente non li uso molto.
Nonpop

@nonpop dannato cromo ... ho aggiunto un aggiornamento alla mia risposta superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko,

Sorprendente! Ho cercato questo per anni! C'è ancora un piccolo problema con Chromium in cui interpreta un tasto premuto Overlay1_Enable. Ho lo stesso sintomo di qui: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch,

1
Sono appena riuscito a risolvere il problema sopra. I tasti freccia della mia riga home ora funzionano anche in Chromium! Avevo bisogno della seguente modifica a questa risposta. gist.github.com/Tarrasch/1293692/…
Tarrasch

4

Ho lo stesso problema. È così doloroso.

Quindi il titolo è "Come fare in modo che tutte le applicazioni rispettino il mio layout xkb modificato?". Bene, penso che l'unico modo sia riparare tutti i programmi che lo fanno in modo errato. Facciamolo!

Bene, dopo aver segnalato quel bug in NetBeans ( Aggiornamento: ho provato l'ultima versione e funziona ora! ), Ho pensato che continuerò a segnalare questo bug per ogni applicazione. La prossima applicazione nell'elenco fu Speedcrunch .

Tuttavia, dopo aver cercato segnalazioni di bug simili, ho riscontrato questo problema . Qualcun altro ha lo stesso problema, fantastico!

Dopo aver letto i commenti capirai che questo bug dovrebbe essere presente in tutte le app QT. Ecco una segnalazione di bug QT . Non risolto, ma sembra che il problema sia stato risolto in Qt5 .

Tuttavia, se guardi i commenti, c'è una soluzione alternativa! Ecco come funziona. Se lo facessi:

key <SPCE> { [ ISO_Level3_Shift ] };

Quindi puoi cambiarlo in questo:

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

E risolverà effettivamente il problema per alcune applicazioni! Ad esempio, Speedcrunch ora funziona per me! Sìì!

Sommario

In questo momento qualsiasi applicazione dovrebbe funzionare correttamente. In caso contrario, è necessario utilizzare type[Group1]="ONE_LEVEL". Se lo possiedi già, devi aggiornare il tuo software. Se continua a non funzionare, è specifico dell'app e devi inviare una segnalazione di bug.

AGGIORNAMENTO (23-09-2017)

Ad oggi, tutte le applicazioni rispettano il layout della mia tastiera. Tutti tranne uno.

Scherzi a parte, la gestione della tastiera in Chromium è spazzatura . Ci sono diversi problemi con esso:

  • La selezione dei turni non funziona con i tasti freccia personalizzati (ma i tasti freccia stessi funzionano correttamente)
  • Se si dispone di più layout e su uno dei layout alcuni tasti sono speciali (ad es. Frecce, Backspace, ecc.), Quindi su un altro layout questo tasto verrà fissato a qualsiasi cosa si abbia sul primo layout. Ad esempio, se si dispone di due layout: foo, bare qualche chiave non Backspace in foo, allora sarà continuare a lavorare come Backspace in baranche se è ridefinito lì.

Per anni ho ignorato questi problemi semplicemente non usando il cromo. Tuttavia, oggigiorno le cose tendono ad usare Electron , che purtroppo è costruito su Chromium.

Il modo giusto per risolvere questo problema sarebbe inviare una segnalazione di bug in Chromium e sperare per il meglio. Non so quanto tempo impiegheranno per risolvere un problema che riguarda solo un paio di utenti ... ma sembra essere l'unica via d'uscita. Il problema è che il cromo funziona davvero bene con il neo(de)layout. Neo layout ha i tasti freccia al livello 5, ma non riesco a farlo funzionare nel mio layout personalizzato.

Segnalazioni di bug ancora aperte:


Grazie per le informazioni! La soluzione alternativa non mi aiuta, quindi immagino che dovrò solo segnalare bug e attendere conversioni qt5.
nonpop

4

Come farli funzionare - Soluzione 3

Utilizzo di livelli aggiuntivi e azione RedirectKey

La seguente soluzione utilizza il tasto Alt sinistro per fornire i tasti cursore su jkli, Home / Fine / Pagina su / Pagina giù su uopö e una Elimina sullo spazio posteriore.

Il tasto Alt sinistro rimane utilizzabile per altri scopi per tutti gli altri tasti (come per il menu dell'applicazione). L'Alt sinistra (Mod1) viene rimosso dallo stato modificatore quando viene utilizzato il blocco cursore in modo che le applicazioni non possano vederlo.

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

Santo Moly! Funziona davvero! Funziona con applicazioni rotte come Chromium. Puoi spiegare quali sono queste definizioni osf? Sembra che siano predefiniti, quindi non puoi nominarli a caso.
Aleks-Daniel Jakimenko,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.