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

11

Eu não gosto de pular entre o teclado principal e as teclas de movimento, então 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      ] };
}

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

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

Editar:

  • Aqui é um arquivo de layout de teclado completo, mas simplificado. Eu tenho isso como /usr/share/X11/xkb/symbols/nonpop e eu carrego com setxkbmap nonpop .
  • Notei que no MonoDevelop a movimentação funciona, mas a seleção não. Ou seja, se eu pressionar Shift + Direita, o texto será selecionado como de costume, mas se pressionar AltGr + Shift + n, o cursor apenas se moverá sem selecionar. Por exemplo, no Firefox, as duas formas podem ser usadas para selecionar.
  • Aqui , no final, eles falam sobre sobreposições que parecem ser algo que talvez pudesse ser um solução, mas eu não descobri como usá-los.
por nonpop 22.08.2014 / 16:23

2 respostas

9

Por que eles não estão funcionando

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

  • O servidor X recebe códigos-chave do dispositivo de entrada e os converte para o estado e keysym .

    • estado é o bitmask dos modificadores X (Ctrl / Shift / etc).

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

      identify characters or functions associated with each key (e.g., via the visible engraving) of a keyboard layout.

      Cada caractere imprimível tem seu próprio keysym, como plus , a , A ou Cyrillic_a , mas outras chaves também geram seus keyyms, como Shift_L , Left ou F1 .

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

    Algumas aplicações controlam os keyyms como Control_L por si próprios, outros apenas procure pelos bits modificadores no estado .

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

  • Você pressiona AltGr . Aplicativo recebe evento KeyPressed com keycode 108 ( <RALT> ) e keysym 0xfe03 ( ISO_Level3_Shift ), o estado é 0.

  • Você pressiona j (que mapeia para “h” no dvorak sem modificadores). Aplicativo recebe o evento KeyPressed com o código de acesso 44 ( <AC07> ), keysym 0xff51 ( Left ) e estado 0x80 (o modificador Mod5 está ativado).

  • Você libera j . O aplicativo recebe o evento KeyRelease para a chave <AC07> / Left com 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 utilitário xev .

Então, isso tudo significa que, embora o aplicativo receba o mesmo código keysym ( Left ) a partir da chave normal <LEFT> , também obtém o código keysym e estado modificador do AltGr. Muito provavelmente, aqueles programas que não funcionam observe os modificadores e não queira trabalhar quando alguns estiverem ativos.

Como fazê-los funcionar

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

1. Grupo separado

O único método que me vem à mente é: definir as teclas de movimento do cursor em um grupo separado e alternar, com um pressionamento de tecla separado, para esse grupo antes de pressionando as teclas j , k , l , i ( h , t , n , c ) (o agrupamento de grupos é o método preferido para um grupo de tempos mudar, 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 AltGr pela primeira vez e, em seguida, (separadamente) um dos chaves de movimento, isso deve funcionar.

No entanto, isso não é muito útil, mais apropriado seria LockGroup em vez de travar e pressione AltGr antes e depois da troca de grupo. Ainda melhor pode seja para SetGroup - então AltGr selecionaria esse grupo somente enquanto pressionado, mas que divulga para as aplicações o keysym de AltGr ( ISO_Group_Shift / ISO_Group_Latch / whatever é definido) (mas estado modificador fica limpo).

Mas ... também existe uma possibilidade de que o aplicativo também leia códigos de teclas (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 tecla de outra chave. O servidor X altera o código de tecla de uma chave e calcula o modificador de estado e o keysym para esse novo código de acesso, então o aplicativo não deve notar a mudança.

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

  • Existem apenas 2 bits de controle de sobreposição no servidor X (isto é, pode haver máximo de 2 sobreposições).
  • Cada chave pode ter apenas 1 código de acesso 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)" };
};

SetControls significa alterar o bit de controle enquanto a tecla é pressionada e restaurar na liberação da chave. Deve haver uma função semelhante LatchControls , mas xkbcomp me dá

Error:            Unknown action LatchControls

na compilação de keymaps.

(A propósito, eu também uso dvorak e também remapeei alguns teclados de movimento para altos níveis de teclas alfabéticas. E também se deparou com algumas funcionalidades quebradas (seleção em notas Xfce e desktop switch por Ctrl-Alt-Esquerda / Direita). Graças a sua pergunta e esta resposta, agora eu sei o que é uma sobreposição:).

    
por 25.11.2014 / 06:38
3

Eu tenho o mesmo problema. É 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 o versão mais recente e funciona agora! ), eu pensei que vou continuar relatando esse bug para cada aplicativo. O próximo aplicativo na lista foi o Speedcrunch .

No entanto, depois de procurar por relatos de bugs semelhantes, encontrei questão . Alguém está tendo o mesmo problema, ótimo!

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

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

key <SPCE> { [ ISO_Level3_Shift ] };

Você pode alterá-lo 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!

Resumo

Neste momento, qualquer aplicativo deve funcionar corretamente. Se não, então você tem que usar type[Group1]="ONE_LEVEL" . Se você já tem, então você tem que atualizar seu software. Se ainda assim não funcionar, então é específico do aplicativo e você precisa enviar um relatório de bug.

UPDATE (2017-09-23)

A partir de hoje, todas as aplicações respeitam o layout do meu teclado. Todos, exceto um.

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

  • A seleção de deslocamento não ocorre com as teclas de seta personalizadas (mas as próprias teclas de seta funcionam bem)
  • Se você tiver vários layouts e em um dos layouts, alguma chave é especial (por exemplo, setas, Backspace, etc.), em outro layout essa chave será corrigida para o que você tiver em seu primeiro layout. Por exemplo, se você tiver dois layouts: foo , bar e alguma chave faz o Backspace em foo , ela continuará funcionando como Backspace em bar , mesmo que seja redefinida lá.

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

O jeito certo de resolver isso seria enviar um relatório de bug no Chromium e esperar pelo melhor. Não sei quanto tempo levará para resolver um problema que afeta apenas alguns usuários ... mas essa parece ser a única saída. O problema com isso é que o cromo realmente funciona bem com neo(de) layout. O layout Neo tem teclas de seta no nível 5, mas não consigo fazer isso funcionar no meu layout personalizado.

Relatórios de bugs ainda abertos:

por 13.11.2015 / 22:19