Jak sprawić, by wszystkie aplikacje przestrzegały mojego zmodyfikowanego układu xkb?

15

Nie lubię przeskakiwać między klawiaturą główną a klawiszami ruchu, więc do mojego pliku układu xkb dodałem następujące elementy.

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

Następnie dołączam je do układu w późniejszym punkcie pliku. Teraz powinienem mieć klawisze kursora dostępne za pośrednictwem AltGr + j, k, l, i (lub h, t, n, c, ponieważ używam dvorak) itp. Działa to w wielu przypadkach (takich jak Firefox, urxvt, Eclipse, główny obszar tekstowy LyX), ale niektóre programy nic nie robią, gdy próbuję, powiedzmy, przesunąć kursor za pomocą tych „skrótów” (takich jak okna dialogowe NetBeans i LyX).

Czy istnieje sposób, aby te inne programy również szanowały moje życzenia? A dlaczego oni w ogóle nie działają? Nie używam DE; tylko niesamowite WM.

Edytować:

  • Oto pełny, ale uproszczony plik układu klawiatury. Mam to /usr/share/X11/xkb/symbols/nonpopi ładuję setxkbmap nonpop.
  • Zauważyłem, że w MonoDevelop poruszanie się działa, ale wybieranie nie. To znaczy, jeśli naciśniesz Shift + prawo, wtedy tekst zostanie zaznaczony jak zwykle, ale jeśli naciśniesz AltGr + Shift + n, wtedy kursor po prostu przesunie się bez wybierania. Na przykład w przeglądarce Firefox można wybrać oba sposoby.
  • Tutaj w końcu mówią o nakładkach który wygląda jak coś, co mogłoby być może rozwiązanie, ale nie zorientowali się, jak z nich korzystać.
nonpop
źródło
1
Nie mam rozwiązania, ale jeśli nie uda ci się uzyskać odpowiedzi pomimo włożonej nagrody, możesz spróbować zapytać w unix.SE , bardziej ukierunkowanej na Unix / Linux witrynie Stackexchange.
Glutanimate

Odpowiedzi:

16

Dlaczego nie działają?

Zgodnie z artykułem ArchWiki, o którym wspomniałeś:

  • Serwer X pobiera kody dostępu z urządzenia wejściowego i konwertuje je do stanu i klucza .

    • state jest maską bitową modyfikatorów X (Ctrl / Shift / etc).

    • keysym jest (zgodnie /usr/include/X11/keysymdef.h) liczbą całkowitą

      identyfikować znaki lub funkcje związane z każdym klawiszem (np. poprzez widoczne grawerowanie) układu klawiatury.

      Każda postać ma swój własny nadruk keysym, jak plus, a, A, lub Cyrillic_a, ale również inne klawisze generują swoje klawsymy, jak Shift_L, Leftlub F1.

  • Aplikacja w kluczowych wydarzeniach związanych z naciśnięciem / zwolnieniem otrzymuje wszystkie te informacje.

    Niektóre aplikacje śledzą takie Control_Lsame klucze , inne po prostu szukają bitów modyfikatora w stanie .

Co się stanie, gdy naciśniesz AltGr+ j:

  • Ty naciskasz AltGr. Aplikacja otrzymuje zdarzenie KeyPressed z kodem <RALT>klucza 108 ( ) i kluczem 0xfe03 ( ISO_Level3_Shift), stan to 0.

  • Naciśnięcie j(który mapuje do „h” w Dvorak bez modyfikatorów). Aplikacja otrzymuje zdarzenie KeyPressed z kodem <AC07>klucza 44 ( ), kluczem 0xff51 ( Left) i stanem 0x80 (modyfikator Mod5 jest włączony).

  • Ty wypuszczasz j. Aplikacja otrzymuje zdarzenie KeyRelease dla klucza <AC07>/ Lefto tych samych parametrach.

  • Następnie zwolnij AltGr- zdarzenie KeyRelease dla AltGr. (Nawiasem mówiąc, stan tutaj wciąż wynosi 0x80, ale to nie ma znaczenia.)

Można to zobaczyć po uruchomieniu xevnarzędzia.

To wszystko oznacza, że ​​chociaż aplikacja otrzymuje taki sam kod Leftklucza ( ) jak z normalnego klucza <LEFT>, otrzymuje również kod klucza i stan modyfikatora z AltGr. Najprawdopodobniej te programy, które nie działają, obserwują modyfikatory i nie chcą działać, gdy niektóre są aktywne.

Jak sprawić, by działały

Najwyraźniej nie możemy zmienić każdego programu, aby nie szukał modyfikatorów. Wtedy jedyną opcją na wyjście z tej sytuacji jest nie generowanie kluczy i bitów stanu modyfikatorów.

1. Oddzielna grupa

Jedyną metodą, która przychodzi mi do głowy to: definiowanie klawiszy ruchu kursora w oddzielnej grupie i przełącznikiem, z oddzielnym naciśnięciu przycisku, do tej grupy przed naciskając klawisze j, k, l, i( h, t, n, c) (grupa zatrzaskowy jest preferowaną metodą na jedną zmianę grupy, jak rozumiem).

Na przykład:

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

Teraz, jeśli najpierw naciśniesz, AltGra następnie (osobno) jeden z klawiszy ruchu, to powinno działać.

Jednak nie jest to bardzo przydatne, bardziej odpowiednie byłoby LockGroup zamiast zatrzasnąć i nacisnąć AltGr przed i po przełączeniu grupy. Jeszcze lepiej może być SetGroup- wtedy AltGr wybiera tę grupę tylko podczas naciskania, ale to ujawnia aplikacjom klawisz AltGr ( ISO_Group_Shift/ ISO_Group_Latch/ cokolwiek zdefiniowano) (ale stan modyfikatora pozostaje czysty).

Ale ... istnieje również możliwość, że aplikacja odczytuje również kody klawiszy (kody prawdziwych kluczy). Wtedy zauważy „fałszywe” klawisze kursora.

2. Nakładka

Bardziej „niskopoziomowym” rozwiązaniem byłaby nakładka (jak opisano w tym samym artykule ).

Nakładka oznacza po prostu, że jakiś klawisz (prawdziwa klawiatura) zwraca kod innego klawisza. Serwer X zmienia kod klucza klucza i oblicza stan modyfikatora oraz klucz dla tego nowego kodu klucza, więc aplikacja nie powinna zauważyć zmiany.

Ale nakładki są bardzo ograniczone:

  • Na serwerze X są tylko 2 bity kontrolne nakładki (tzn. Maksymalnie 2 nakładki).
  • Każdy klucz może mieć tylko 1 alternatywny kod.

Co do reszty, implementacja jest dość podobna do metody z osobną grupą:

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

SetControlsoznacza zmianę bitu kontrolnego podczas naciskania klawisza i przywrócenie go po zwolnieniu klawisza. Powinna być podobna funkcja LatchControls, ale xkbcompdaje mi

Error:            Unknown action LatchControls

na kompilacji mapy klawiszy.

(Nawiasem mówiąc, używam również dvorak, a także przypisałem niektóre klawisze ruchów do wysokich poziomów klawiszy alfabetycznych. I natknąłem się również na niektóre zepsute funkcje (wybór w notatkach Xfce i przełączanie pulpitu przez Ctrl-Alt-Lewo / Prawo). Dzięki twoje pytanie i ta odpowiedź, teraz wiem, co to jest nakładka :).)

Chel
źródło
Dzięki! Właściwie otrzymałem kolejną odpowiedź na unix.se, która początkowo wydawała się idealna, ale okazało się, że niektóre aplikacje są nadal źle zachowane. To rozwiązanie (nakładki) działa również w tych przypadkach.
nonpop
Właśnie zauważyłem, że Google Chrome [e | ium] też się tym nie przejmuje! :( Na szczęście nie używam ich zbyt często.
nonpop
@nonpop cholerny chromium… Dodałem aktualizację do mojej odpowiedzi superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko
Niesamowity! Szukałem tego przez lata! Nadal występuje niewielki problem z Chromium, który interpretuje naciśnięcie klawisza Overlay1_Enable. Mam ten sam objaw jak tutaj: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch
1
Właśnie udało mi się naprawić powyższy problem. Moje klawisze strzałek w głównym wierszu działają teraz również w Chromium! Potrzebowałem następującej zmiany w tej odpowiedzi. gist.github.com/Tarrasch/1293692/…
Tarrasch
4

Mam ten sam problem. To takie bolesne.

Więc tytuł brzmi „Jak sprawić, by wszystkie aplikacje szanowały mój zmodyfikowany układ xkb?”. Myślę, że jedynym sposobem jest naprawienie wszystkich programów, które robią to niepoprawnie. Zróbmy to!

Cóż, po zgłoszeniu tego błędu w NetBeans ( aktualizacja: Wypróbowałem najnowszą wersję i działa teraz! ), Pomyślałem, że będę po prostu zgłaszał ten błąd dla każdej aplikacji. Kolejną aplikacją na liście była Speedcrunch .

Jednak po wyszukaniu podobnych zgłoszeń błędów znalazłem ten problem . Ktoś inny ma ten sam problem, świetnie!

Po przeczytaniu komentarzy zrozumiesz, że ten błąd powinien występować we wszystkich aplikacjach QT. Oto raport o błędzie QT . Nie rozwiązano, ale wygląda na to, że problem został rozwiązany w Qt5 .

Jeśli jednak spojrzysz na komentarze, istnieje obejście! Oto jak to działa. Jeśli to robisz:

key <SPCE> { [ ISO_Level3_Shift ] };

Następnie możesz zmienić to na:

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

I faktycznie rozwiąże problem niektórych aplikacji! Na przykład Speedcrunch działa teraz dla mnie! Tak!

streszczenie

W tej chwili każda aplikacja powinna działać poprawnie. Jeśli tak nie jest, musisz użyć type[Group1]="ONE_LEVEL". Jeśli już go masz, musisz zaktualizować oprogramowanie. Jeśli nadal nie działa, jest to zależne od aplikacji i musisz przesłać raport o błędzie.

AKTUALIZACJA (23.09.2017)

Na dzień dzisiejszy wszystkie aplikacje są zgodne z moim układem klawiatury. Wszystkie oprócz jednego.

Poważnie, obsługa klawiatury w Chromium to śmieci . Jest z tym kilka problemów:

  • Wybór Shift nie działa w przypadku niestandardowych klawiszy strzałek (ale same klawisze strzałek działają OK)
  • Jeśli masz wiele układów i na jednym z układów jakiś klucz jest wyjątkowy (np. Strzałki, Backspace itp.), To w innym układzie ten klucz zostanie ustawiony na cokolwiek, co masz na pierwszym układzie. Na przykład, jeśli masz dwa układy: foo, bara niektóre robi każdy klawisz Backspace w foo, to będzie pracował jako Backspace w barnawet jeśli jest tam nowo.

Przez lata ignorowałem te problemy, po prostu nie używając chromu. Jednak obecnie rzeczy zwykle używają elektronu , który niestety jest zbudowany na chromie.

Właściwym sposobem rozwiązania tego problemu byłoby przesłanie raportu o błędzie w Chromium i nadzieja na najlepsze. Nie wiem, ile czasu zajmie im rozwiązanie problemu, który dotyczy tylko kilku użytkowników… ale wydaje się, że to jedyne wyjście. Problem polega na tym, że chrom faktycznie działa dobrze z neo(de)układem. Układ Neo ma klawisze strzałek na poziomie 5, ale nie mogę go uruchomić w moim niestandardowym układzie.

Nadal otwarte zgłoszenia błędów:

Aleks-Daniel Jakimenko
źródło
Dzięki za informację! Obejście nie pomaga mi, więc chyba będę musiał po prostu zgłaszać błędy i czekać na konwersje qt5.
nonpop
4

Jak sprawić, by działały - Rozwiązanie 3

Korzystanie z dodatkowych poziomów i akcji RedirectKey

Poniższe rozwiązanie wykorzystuje lewy klawisz Alt do zapewnienia klawiszy kursora na jkli, Home / End / PageUp / PageDown na uopö i Delete na Backspace.

Lewy klawisz Alt pozostaje użyteczny do innych celów dla wszystkich innych klawiszy (np. W menu aplikacji). Lewy Alt (Mod1) jest usuwany ze stanu modyfikatora, gdy używany jest blok kursora, aby aplikacje go nie widziały.

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
źródło
Święty moli! To faktycznie działa! Działa z uszkodzonymi aplikacjami, takimi jak Chromium. Czy możesz wyjaśnić, jakie są te definicje OSF? Wygląda na to, że są predefiniowane, więc nie można nazwać ich losowo.
Aleks-Daniel Jakimenko