Como fazer com que todos os aplicativos respeitem meu layout xkb modificado?

15

Como não gosto de pular entre o teclado principal e as teclas de movimento, adicionei o seguinte ao meu arquivo de 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      ] };
}

Em seguida, incluo-os no layout posteriormente no arquivo. Agora eu deveria ter as teclas de cursor acessíveis por AltGr + j, k, l, i (ou h, t, n, c, como estou usando o dvorak) etc. Isso funciona em muitos casos (como Firefox, urxvt, Eclipse, principal área de texto do LyX), mas alguns programas não fazem nada quando tento, por exemplo, mover o cursor usando esses "atalhos" (como as caixas de diálogo NetBeans e LyX).

Então, existe uma maneira de fazer esses outros programas também respeitarem meus desejos? E por que eles não estão trabalhando em primeiro lugar? Eu não estou usando um DE; somente o WM impressionante.

Editar:

  • Aqui está um arquivo de layout de teclado completo, mas simplificado. Eu tenho isso /usr/share/X11/xkb/symbols/nonpope carrego-o setxkbmap nonpop.
  • Percebi que, no MonoDevelop, mover-se funciona, mas selecionar não. Ou seja, se eu pressionar Shift + Direita, o texto será selecionado como de costume, mas se eu pressionar AltGr + Shift + n, o cursor se moverá sem selecionar. Por exemplo, no Firefox, os dois modos podem ser usados ​​para a seleção.
  • Aqui, no final, eles falam sobre sobreposições que parecem algo que talvez possa ser uma solução, mas ainda não descobri como usá-las.
não popular
fonte
1
Eu não tenho uma solução, mas se você não conseguir obter uma resposta, apesar da recompensa oferecida, tente perguntar no unix.SE , um site Stackexchange mais centrado em Unix / Linux.
Glutanimate

Respostas:

16

Por que eles não estão trabalhando?

De acordo com o artigo do ArchWiki que você mencionou:

  • O servidor X obtém códigos de chave do dispositivo de entrada e os converte em estado e código de chave .

    • state é a máscara de bit dos modificadores X (Ctrl / Shift / etc).

    • keysym é (de acordo com /usr/include/X11/keysymdef.h) o número inteiro que

      identifique caracteres ou funções associadas a cada tecla (por exemplo, através da gravação visível) de um layout de teclado.

      Cada personagem de impressão tem a sua própria keysym, como plus, a, A, ou Cyrillic_a, mas outras teclas também gerar os seus keysyms, como Shift_L, Leftou F1.

  • O aplicativo nos principais eventos de imprensa / liberação obtém todas essas informações.

    Alguns aplicativos rastreiam academias de teclas como Control_Leles mesmos, outros apenas procuram os bits modificadores no estado .

Então, o que acontece, quando você pressiona AltGr+ j:

  • Você pressiona AltGr. O aplicativo obtém o evento KeyPressed com o código de chave 108 ( <RALT>) e o código de chave 0xfe03 ( ISO_Level3_Shift), o estado é 0.

  • Você pressiona j(que mapeia para "h" no dvorak sem modificadores). O aplicativo obtém o evento KeyPressed com o código de chave 44 ( <AC07>), keysym 0xff51 ( Left) e o estado 0x80 (o modificador Mod5 está ativado).

  • Você solta j. O aplicativo obtém o evento KeyRelease da chave <AC07>/ Leftcom os mesmos parâmetros.

  • Em seguida, libere AltGr- evento KeyRelease para AltGr. (A propósito, o estado aqui ainda é 0x80, mas isso não importa.)

Isso pode ser visto se você executar o xevutilitário.

Portanto, isso significa que, embora o aplicativo obtenha o mesmo código Leftde chave de chave ( ) da chave normal <LEFT>, ele também obtém o código de chave de chave e o estado modificador do AltGr. Provavelmente, aqueles programas que não funcionam, assistem aos modificadores e não querem trabalhar quando alguns estão ativos.

Como fazê-los funcionar

Aparentemente, não podemos mudar todos os programas para não procurar modificadores. Então, a única opção para escapar dessa situação é não gerar as classes de teclas e os bits de estado dos modificadores.

1. Grupo separado

O único método que vem à cabeça é: definir teclas de movimento do cursor num grupo e comutador separado, com uma prensa de chave separada, para que o grupo antes de pressionar as teclas j, k, l, i( h, t, n, c) (grupo de bloqueio é o método preferido por uma mudança de grupo de tempo, como eu entendo).

Por exemplo:

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

Agora, se você pressionar primeiro AltGre depois (separadamente) uma das teclas de movimento, isso funcionará.

No entanto, isso não é muito útil, seria mais apropriado, em LockGroup vez de travar, e pressionar AltGr antes e depois da troca de grupo. Ainda melhor SetGroup: AltGr selecionaria esse grupo apenas enquanto pressionado, mas isso revela aos aplicativos o keyym do AltGr ( ISO_Group_Shift/ ISO_Group_Latch/ o que for definido) (mas o estado do modificador permanece limpo).

Mas ... existe também a possibilidade de o aplicativo também ler códigos de chave (os códigos das chaves reais). Então ele notará as teclas do cursor "falsas".

2. Sobreposição

A solução mais "de baixo nível" seria a sobreposição (como o mesmo artigo descreve).

Overlay significa simplesmente que alguma tecla (teclado real) retorna o código de outra tecla. O servidor X altera o código de chave de uma chave e calcula o estado do modificador e o código de chave desse novo código de chave, para que o aplicativo não note a alteração.

Mas as sobreposições são muito limitadas:

  • Existem apenas 2 bits de controle de sobreposição no servidor X (ou seja, pode haver no máximo 2 sobreposições).
  • Cada chave pode ter apenas 1 código de chave alternativo.

Quanto ao resto, a implementação é bastante semelhante ao método com um grupo separado:

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 mudar o bit de controle enquanto a tecla é pressionada e restaurá-lo na liberação da tecla. Deve haver função semelhante LatchControls, mas xkbcompme dá

Error:            Unknown action LatchControls

na compilação de mapas de teclado.

(A propósito, eu também uso o dvorak e também remapeei algumas academias de teclas de movimento para altos níveis de teclas alfabéticas. E também deparei com algumas funcionalidades quebradas (seleção nas notas do Xfce e alternância na área de trabalho por Ctrl-Alt-Esquerda / Direita). sua pergunta e esta resposta, agora eu sei o que é uma sobreposição :).)

Chel
fonte
Obrigado! Na verdade, recebi outra resposta no unix.se que, a princípio, parecia perfeita, mas algumas aplicações ainda se comportaram mal. Essa solução (sobreposições) também funciona nesses casos.
Nonpop
Acabei de notar que o google chrom [e | ium] também não se importa com isso! :( Felizmente eu não os uso muito.
nonpop
@nonpop maldita cromo ... Eu adicionei uma atualização para a minha resposta superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko
Surpreendente! Eu procurei por isso há anos! Ainda existe um pequeno problema no Chromium, no qual ele interpreta um pressionamento de tecla Overlay1_Enable. Eu tenho o mesmo sintoma que aqui: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch
1
Acabei de corrigir o problema acima. As teclas de seta da minha linha de casa agora também funcionam no Chromium! Eu precisava da seguinte alteração nesta resposta. gist.github.com/Tarrasch/1293692/…
Tarrasch
4

Eu tenho o mesmo problema. Isso é tão doloroso.

Portanto, o título é "Como fazer com que todos os aplicativos respeitem meu layout xkb modificado?". Bem, acho que a única maneira é consertar todos os programas que fazem isso incorretamente. Vamos fazer isso!

Bem, depois de relatar esse bug no NetBeans ( atualização: tentei a versão mais recente e funciona agora! ), Pensei em continuar relatando esse bug para todos os aplicativos. O próximo aplicativo da lista foi o Speedcrunch .

No entanto, depois de procurar relatórios de erros semelhantes, encontrei esse problema . Outra pessoa está tendo o mesmo problema, ótimo!

Depois de ler os comentários, você entenderá que esse bug deve estar presente em todos os aplicativos QT. Aqui está um relatório de bug do QT . Não resolvido, mas parece que o problema foi resolvido no Qt5 .

No entanto, se você olhar para os comentários, há uma solução alternativa! Aqui está como isso funciona. Se você estava fazendo isso:

key <SPCE> { [ ISO_Level3_Shift ] };

Então você pode mudar para isso:

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

E isso realmente resolverá o problema de algumas das aplicações! Por exemplo, o Speedcrunch agora funciona para mim! Yay!

Sumário

No momento, qualquer aplicativo deve funcionar corretamente. Caso contrário, você precisará usar type[Group1]="ONE_LEVEL". Se você já o possui, é necessário atualizar seu software. Se ainda assim não funcionar, é específico do aplicativo e você deve enviar um relatório de erro.

ATUALIZAÇÃO (23-09-2017)

Atualmente, todos os aplicativos respeitam meu layout de teclado. Todos, exceto um.

Sério, o manuseio do teclado no Chromium é lixo . Existem vários problemas com isso:

  • A seleção de turno não funciona com as teclas de seta personalizadas (mas as próprias teclas de seta funcionam bem)
  • Se você possui vários layouts e em um dos layouts alguma tecla é especial (por exemplo, setas, Backspace etc.), em outro layout, essa chave será fixada no que você tiver no seu primeiro layout. Por exemplo, se você tem dois layouts: foo, bare alguns tecla faz Backspace em foo, então ele vai continuar trabalhando como Backspace no barmesmo que seja redefinido lá.

Durante anos, eu ignorei esses problemas simplesmente não usando cromo. No entanto, hoje em dia as coisas tendem a usar o Electron , que infelizmente é construído no Chromium.

A maneira correta de resolver isso seria enviar um relatório de erro no Chromium e esperar o melhor. Não sei quanto tempo levará para resolver um problema que está afetando apenas alguns usuários ... mas essa parece ser a única saída. O problema é que o cromo realmente funciona bem com o neo(de)layout. O layout neo tem teclas de seta no nível 5, mas não consigo que ele funcione no meu layout personalizado.

Relatórios de bugs ainda abertos:

Daniel Jakimenko, Aleks
fonte
Obrigado pela informação! A solução alternativa não me ajuda, então acho que vou ter que relatar bugs e esperar pelas conversões de qt5.
Nonpop
4

Como fazê-los funcionar - Solução 3

Usando níveis adicionais e ação RedirectKey

A solução a seguir usa a tecla Alt esquerda para fornecer as teclas de cursor em jkli, Home / End / PageUp / PageDown no uopö e um Delete no Backspace.

A tecla Alt esquerda permanece utilizável para outros fins em todas as outras teclas (como no menu do aplicativo). O Alt esquerdo (Mod1) é removido do estado do modificador quando o bloco do cursor é usado para que os aplicativos não possam vê-lo.

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
fonte
Santo Moly! Isso realmente funciona! Ele funciona com aplicativos quebrados, como o Chromium. Você pode explicar quais são essas definições de OSF? Parece que eles são predefinidos, então você não pode nomeá-los aleatoriamente.
Aleks-Daniel Jakimenko