¿Por qué no funcionan?
Según el artículo de ArchWiki que mencionaste:
-
El servidor X obtiene códigos clave desde el dispositivo de entrada y los convierte al estado y keysym .
-
estado es la máscara de bits de los modificadores X (Ctrl/Shift/etc).
-
keysym es (según
/usr/include/X11/keysymdef.h
) el entero queidentificar caracteres o funciones asociadas con cada tecla (por ejemplo, a través del grabado visible) de un diseño de teclado.
Cada carácter imprimible tiene su propio keysym, como
plus
,a
,A
, oCyrillic_a
, pero otras claves también generan sus keysyms, comoShift_L
,Left
oF1
.
-
-
La aplicación en los eventos clave de pulsación/liberación obtiene toda esta información.
Algunas aplicaciones rastrean keysyms como
Control_L
por sí mismos, otros simplemente buscan los bits modificadores en el estado .
Entonces, ¿qué sucede cuando presionas AltGr? +j :
-
Presionas AltGr . La aplicación obtiene el evento KeyPressed con keycode108 (
<RALT>
) y keysym 0xfe03 (ISO_Level3_Shift
), el estado es 0. -
Presionas j (que se asigna a "h" en dvorak sin modificadores). La aplicación obtiene el evento KeyPressed con el código de tecla 44 (
<AC07>
), keysym 0xff51(Left
) y el estado 0x80 (el modificador Mod5 está activado). -
Sueltas j . La aplicación obtiene el evento KeyRelease para la clave
<AC07>
/Left
con los mismos parámetros. -
Luego suelte AltGr — Evento KeyRelease para AltGr. (Por cierto, el estado aquí sigue siendo 0x80, pero eso no importa).
Esto se puede ver si ejecuta xev
utilidad.
Entonces, todo eso significa que, aunque la aplicación obtiene el mismo código keysym (Left
) a partir de la tecla normal <LEFT>
, también obtiene el código keysym y el estado modificador de AltGr. Lo más probable es que aquellos programas que no funcionan, observen los modificadores y no quieran funcionar cuando algunos están activos.
Cómo hacer que funcionen
Aparentemente, no podemos cambiar todos los programas para que no busquen modificadores. Entonces, la única opción para escapar de esta situación es no generar modificadores de clave y bits de estado.
1. Grupo separado
El único método que se me ocurre es:definir las teclas de movimiento del cursor en un grupo separado y cambiar, presionando una tecla por separado, a ese grupo antes de presionar las teclas j , k , l , yo (h
,t
, n
, c
) (según tengo entendido, el enganche grupal es el método preferido para un cambio de grupo único).
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 AltGr y luego (por separado) una de las teclas de movimiento, esto debería funcionar.
Sin embargo, esto no es muy útil, más apropiado sería LockGroup
en lugar de pestillo y presione AltGr antes y después del cambio de grupo. Aún mejor tal vez a SetGroup
— entonces AltGr seleccionaría ese grupo solo mientras se presiona, pero eso revela a las aplicaciones el keysym de AltGr (ISO_Group_Shift
/ISO_Group_Latch
/lo que sea que esté definido) (pero el estado modificador permanece limpio).
Pero... también queda la posibilidad de que la aplicación también lea keycodes (los códigos de las llaves 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).
Superposición 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 símbolo clave 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 llave puede tener solo 1 código de llave alternativo.
Por lo demás, 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)" };
};
SetControls
significa 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 xkbcomp
me da
Error: Unknown action LatchControls
en la compilación del mapa de teclas.
(Por cierto, también uso dvorak y también he reasignado algunos símbolos de teclas de movimiento a niveles altos de teclas alfabéticas. 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 :).)
Cómo hacer que funcionen - Solución 3
Uso de niveles adicionales y Action RedirectKey
La siguiente solución utiliza la tecla Alt izquierda para proporcionar teclas de cursor en jkli, Inicio/Fin/RePág/AvPág en uopö y Eliminar en Retroceso.
La tecla Alt izquierda permanece 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 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)"
};
};
Tengo el mismo problema. Es tan 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. ¡Hagámoslo!
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 tiene el mismo problema, ¡genial!
Después de leer los comentarios, comprenderá que este error debería estar presente en todas las aplicaciones QT. Aquí hay un informe de error de QT. No resuelto, pero parece que el problema está resuelto en Qt5 .
Sin embargo, si miras los comentarios, ¡hay una solución! Así es como funciona. Si estuvieras haciendo esto:
key <SPCE> { [ ISO_Level3_Shift ] };
Entonces puedes cambiarlo a esto:
key <SPCE> {
type[Group1]="ONE_LEVEL",
symbols[Group1] = [ ISO_Level3_Shift ]
};
¡Y realmente resolverá el problema para algunas de las aplicaciones! Por ejemplo, Speedcrunch ahora me funciona! ¡Hurra!
Resumen
Ahora mismo cualquier aplicación debería funcionar correctamente. Si no es así, entonces tienes que usar type[Group1]="ONE_LEVEL"
. Si ya lo tienes, entonces tienes que actualizar tu 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 disposición de mi teclado. Todos excepto uno.
En serio, el manejo del teclado en Chromium es basura . Hay varios problemas con él:
- La selección de mayúsculas no funciona con las teclas de flecha personalizadas (pero las teclas de flecha funcionan bien)
- Si tiene varios diseños y en uno de ellos 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
,bar
y alguna tecla retrocede enfoo
, entonces seguirá funcionando como Retroceso enbar
incluso 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 lamentablemente se basa en Chromium.
La forma correcta de resolver esto sería enviar un informe de error en Chromium y esperar lo mejor. No sé cuánto tardarán en resolver un problema que solo afecta a un par de usuarios… pero parece que esa es la única salida. El problema con esto es que el cromo realmente funciona bien con neo(de)
diseño. El diseño de 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:
- Pluma:https://github.com/mate-desktop/pluma/issues/17