¿Cómo hacer que todas las aplicaciones respeten mi diseño xkb modificado?


15

No me gusta saltar entre el teclado principal y las teclas de movimiento, así que agregué lo siguiente a mi archivo de diseño 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      ] };
}

Luego los incluyo en el diseño en un momento posterior del archivo. Ahora debería tener las teclas de cursor accesibles a través de AltGr + j, k, l, i (o h, t, n, c, ya que estoy usando dvorak), etc. Esto funciona en muchos casos (como Firefox, urxvt, Eclipse, el área de texto principal de LyX), pero algunos programas no hacen nada cuando intento, por ejemplo, mover el cursor usando estos "accesos directos" (como los diálogos de NetBeans y LyX).

Entonces, ¿hay alguna manera de hacer que estos otros programas también respeten mis deseos? ¿Y por qué no están trabajando en primer lugar? No estoy usando un DE; solo el Awesome WM.

Editar:

  • Aquí hay un archivo de diseño de teclado completo pero simplificado. Tengo esto como /usr/share/X11/xkb/symbols/nonpopy lo cargo con setxkbmap nonpop.
  • Noté que en MonoDevelop moverse funciona, pero seleccionar no. Es decir, si presiono Shift + Derecha, el texto se selecciona como de costumbre, pero si presiono AltGr + Shift + n, entonces el cursor simplemente se mueve sin seleccionar. Por ejemplo, en Firefox se pueden usar ambas formas para seleccionar.
  • Aquí, al final, hablan de superposiciones que parecen algo que quizás podría ser una solución, pero no he descubierto cómo usarlas.

1
No tengo una solución, pero si no logras obtener una respuesta a pesar de la generosidad que ofreces , puedes intentar preguntar en unix.SE , un sitio Stackexchange más centrado en Unix / Linux.
Glutanimate

Respuestas:


16

¿Por qué no están trabajando?

Según el artículo de ArchWiki que mencionaste:

  • El servidor X obtiene códigos de clave del dispositivo de entrada y los convierte al estado y keyym .

    • El estado es la máscara de bits de los modificadores X (Ctrl / Shift / etc).

    • keyym es (según /usr/include/X11/keysymdef.h) el entero que

      identificar caracteres o funciones asociadas con cada tecla (por ejemplo, a través del grabado visible) de una distribución de teclado.

      Cada personaje tiene su propia imprimible keysym, como plus, a, A, o Cyrillic_a, pero otras teclas también generan sus teclas keysyms, como Shift_L, Lefto F1.

  • La aplicación en los eventos de pulsación / liberación de teclas obtiene toda esta información.

    Algunas aplicaciones rastrean los símbolos de teclas como Control_Lsi fueran ellos mismos, otras solo buscan los bits modificadores en el estado .

Entonces, ¿qué sucede cuando presionas AltGr+ j:

  • Se presiona AltGr. La aplicación obtiene el evento KeyPressed con el código de tecla 108 ( <RALT>) y keyym 0xfe03 ( ISO_Level3_Shift), el estado es 0.

  • Presiona j(que se asigna a "h" en dvorak sin modificadores). La aplicación obtiene el evento KeyPressed con el código <AC07>clave 44 ( ), keyym 0xff51 ( Left) y el estado 0x80 (el modificador Mod5 está activado).

  • Tu liberas j. La aplicación obtiene el evento KeyRelease para la clave <AC07>/ Leftcon los mismos parámetros.

  • Luego AltGr, suelte el evento KeyRelease para AltGr. (Por cierto, el estado aquí sigue siendo 0x80, pero eso no importa).

Esto se puede ver si ejecuta la xevutilidad.

Entonces, todo eso significa que, aunque la aplicación obtiene el mismo código keyym ( Left) que la clave normal <LEFT>, también obtiene el código keyym y el estado modificador del AltGr. Lo más probable es que los programas que no funcionan, miren los modificadores y no quieran funcionar cuando algunos están activos.

Cómo hacer que funcionen

Aparentemente, no podemos cambiar todos los programas para no buscar modificadores. Entonces, la única opción para escapar de esta situación es no generar los keyyms de los modificadores y los bits de estado.

1. grupo separado

El único método que viene a la mente es: definir teclas de movimiento del cursor en un grupo y un interruptor separado, con una pulsación de tecla por separado, a ese grupo antes de pulsar las teclas j, k, l, i( h, t, n, c) (grupo de bloqueo es el método preferido por un cambio de grupo de tiempo, según tengo entendido).

Por ejemplo:

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

Ahora, si primero presiona AltGry luego (por separado) una de las teclas de movimiento, esto debería funcionar.

Sin embargo, esto no es muy útil, sería más apropiado en LockGroup lugar de enganchar y presionar AltGr antes y después del cambio de grupo. Incluso puede ser mejor SetGroup, entonces AltGr seleccionaría ese grupo solo mientras se presiona, pero eso revela a las aplicaciones el teclado de AltGr ( ISO_Group_Shift/ ISO_Group_Latch/ lo que sea que esté definido) (pero el estado del modificador se mantiene limpio).

Pero ... también queda la posibilidad de que la aplicación también lea códigos clave (los códigos de las claves reales). Entonces notará las teclas de cursor "falsas".

2. Superposición

La solución más "de bajo nivel" sería la superposición (como se describe en el mismo artículo ).

Superponer simplemente significa que alguna tecla (teclado real) devuelve el código de otra tecla. El servidor X cambia el código clave de una clave y calcula el estado del modificador y el keyym para ese nuevo código clave, por lo que la aplicación no debería notar el cambio.

Pero las superposiciones son muy limitadas:

  • Solo hay 2 bits de control de superposición en el servidor X (es decir, puede haber un máximo de 2 superposiciones).
  • Cada clave puede tener solo 1 código clave alternativo.

En cuanto al resto, la implementación es bastante similar al método con un 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 cambiar el bit de control mientras se presiona la tecla y restaurarlo al soltar la tecla. Debería haber una función similar LatchControls, pero xkbcompme da

Error:            Unknown action LatchControls

en la compilación de mapas de teclas.

(Por cierto, también uso dvorak y también he reasignado algunos keyyms de movimiento a altos niveles de teclas alfabéticas. Y también encontré algunas funciones rotas (selección en notas Xfce y cambio de escritorio con Ctrl-Alt-Izquierda / Derecha). Gracias a su pregunta y esta respuesta, ahora sé lo que es una superposición :).)


¡Gracias! De hecho, obtuve otra respuesta en unix.se que al principio parecía ser perfecta, pero resultó que algunas aplicaciones todavía se portaban mal. Esta solución (superposiciones) también funciona en esos casos.
popular

¡Acabo de notar que google chrom [e | ium] tampoco se preocupa por esto! :( Por suerte no los uso mucho.
nonpop

@nonpop maldito cromo ... He agregado una actualización a mi respuesta superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko

¡Increíble! ¡He buscado esto por años! Todavía hay un problema menor con Chromium donde interpreta una pulsación de tecla Overlay1_Enable. Tengo el mismo síntoma que aquí: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch

1
Me las arreglé para solucionar el problema anterior. ¡Mis teclas de flecha de la fila de inicio ahora también funcionan en Chromium! Necesitaba el siguiente cambio para esta respuesta. gist.github.com/Tarrasch/1293692/…
Tarrasch

4

Tengo el mismo problema. Es muy doloroso

Entonces el título es "¿Cómo hacer que todas las aplicaciones respeten mi diseño xkb modificado?". Bueno, creo que la única forma es arreglar todos los programas que lo hacen incorrectamente. ¡Vamos a hacer eso!

Bueno, después de informar ese error en NetBeans ( Actualización: ¡he probado la última versión y funciona ahora! ), Pensé que seguiría informando este error para cada aplicación. La siguiente aplicación en la lista fue Speedcrunch .

Sin embargo, después de buscar informes de errores similares, encontré este problema . Alguien más está teniendo el mismo problema, ¡genial!

Después de leer los comentarios, comprenderá que este error debe estar presente en todas las aplicaciones QT. Aquí hay un informe de error QT . No resuelto, pero parece que el problema está resuelto en Qt5 .

Sin embargo, si nos fijamos en los comentarios, ¡hay una solución alternativa! Así es como funciona. Si estabas haciendo esto:

key <SPCE> { [ ISO_Level3_Shift ] };

Entonces puedes cambiarlo a esto:

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

¡Y en realidad resolverá el problema para algunas de las aplicaciones! ¡Por ejemplo, Speedcrunch ahora funciona para mí! ¡Hurra!

Resumen

En este momento, cualquier aplicación debería funcionar correctamente. Si no es así, entonces tienes que usar type[Group1]="ONE_LEVEL". Si ya lo tiene, debe actualizar su software. Si aún no funciona, entonces es específico de la aplicación y debe enviar un informe de error.

ACTUALIZACIÓN (2017-09-23)

A partir de hoy, todas las aplicaciones respetan la distribución de mi teclado. Todos menos uno.

En serio, el manejo del teclado en Chromium es basura . Hay varios problemas con esto:

  • La selección de desplazamiento no funciona con las teclas de flecha personalizadas (pero las teclas de flecha funcionan bien)
  • Si tiene varios diseños y en uno de los diseños alguna tecla es especial (por ejemplo, flechas, Retroceso, etc.), en otro diseño, esta tecla se fijará a lo que tenga en su primer diseño. Por ejemplo, si tiene dos diseños: foo, bary algunos de claves se tratara de retroceso en foo, entonces será seguir trabajando como Retroceso en barincluso si se redefine allí.

Durante años ignoré estos problemas simplemente por no usar cromo. Sin embargo, hoy en día las cosas tienden a usar Electron , que desafortunadamente está construido sobre Chromium.

La forma correcta de resolver esto sería enviar un informe de error en Chromium y esperar lo mejor. No sé cuánto tiempo les llevará resolver un problema que solo afecta a un par de usuarios ... pero esa parece ser la única salida. El problema con esto es que el cromo realmente funciona bien con el neo(de)diseño. El diseño Neo tiene teclas de flecha en el nivel 5, pero no puedo hacer que funcione en mi diseño personalizado.

Informes de errores aún abiertos:


Gracias por la info! La solución alternativa no me ayuda, así que supongo que tendré que informar de errores y esperar las conversiones de qt5.
nonpop

4

Cómo hacer que funcionen - Solución 3

Uso de niveles adicionales y acción RedirectKey

La siguiente solución utiliza la tecla Alt izquierda para proporcionar teclas de cursor en jkli, Inicio / Fin / Re Pág / Av Pág en uopö y una Suprimir en el Retroceso.

La tecla Alt izquierda sigue siendo utilizable para otros fines para todas las demás teclas (como para el menú de la aplicación). El Alt izquierdo (Mod1) se elimina del estado del modificador cuando se usa el bloque de cursor para que las aplicaciones no puedan verlo.

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 molio! Eso realmente funciona! Funciona alrededor de aplicaciones rotas como Chromium. ¿Puedes explicar cuáles son estas definiciones de osf? Parece que están predefinidos, por lo que no puedes nombrarlos al azar.
Aleks-Daniel Jakimenko
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.