¿Cómo se emula un teclado numérico/teclado para usarlo con software de diseño (como Blender)?

¿Cómo se emula un teclado numérico/teclado para usarlo con software de diseño (como Blender)?

Problema

Cuando se utiliza cierto software comoLicuadora, es importante poder utilizar el teclado numérico para que el usuario pueda hacer cosas como orientarse en el espacio de diseño, pero muchas computadoras portátiles no vienen con un teclado numérico físico.. Esto se complica aún más por el hecho de que las entradas regulares de la barra numérica (del 1 al 9 en la parte superior del teclado) en realidad representan diferentes "símbolos" para la computadora, por lo que a menudo tienen funciones completamente diferentes en este tipo de software.

Soluciones intentadas

Dado que muchas computadoras portátiles no vienen con un teclado numérico,una solución común en muchas plataformas es emular el teclado numérico, por ejemplo, manteniendo presionada una tecla mientras usa otras teclas del teclado (como jkluio789 para representar 123456789). Muchas computadoras portátiles implementan esto a nivel de BIOS (como usar la tecla Fn). Sin embargo, sin una implementación de tan bajo nivel, implementar esta emulación es muy difícil.

Algunas soluciones existen en línea, peroA menudo son insuficientes para su uso con software de diseño.(ya que no implementan el símbolo correcto y también requieren el uso de teclas modificadoras), ono se explican en profundidad. La mayoría de las soluciones se centran en el usoxkb, que es una arquitectura complicada y notoriamente difícil de empezar a utilizar.

Requisitos para una buena solución

Una buena solución a este problema será un teclado emulado que el software de gráficos acepte como entrada de teclado real y que sea fácil de usar. Una limitación adicional es el hecho de que Blender detecta el uso de teclas modificadoras (como Shift, Alt, Super("Comando", "Tecla de Windows", etc.), Hyper) incluso cuando xkbse le indica borrar modificadores y, por lo tanto, interpretará una "emulación de teclado mientras mantener una solución de tecla modificadora como una entrada completamente diferente (es decir, [ Numpad1+ Alt] en lugar de solo Numpad1). Por lo tanto, una solución ideal implicaría en realidad un mecanismo de bloqueo (por ejemplo, mayúsculas de bloqueo de mayúsculas) en lugar de un mecanismo de retención (por ejemplo, mayúsculas de mayúsculas) para que no se pasen modificadores accidentalmente al software.

Respuesta1

Inicio rápido

Si no te importa ninguna de las explicaciones (sé que puedo ser prolijo), simplemente sigue las{números en negrita entre llaves}al comienzo de algunos párrafos. Siga cada uno de estos pasos en orden y probablemente podrá implementarlo en unos minutos. Tenga en cuenta que esta guía asume cierta competencia en Unix (poder crear directorios, crear archivos, sudoacceder al acceso raíz, etc.). También tenga en cuenta queel acceso root solo es necesario donde se indica, por lo que no es necesario utilizarlo sudoa menos que se lo indiquen.

Descripción general de la solución

Usaremos xkb para agregar una emulación de teclado numérico de "bloqueo" (como Bloq Mayús) a Linux. Me gustaría que mis claves "jkluio789" representaran las representaciones del teclado numérico de los números "123456789", así como algunas otras inclusiones ("m,"->"0", "-=[]"->[numpad]" -+*", "."->[teclado numérico]"."). Alternaré este "modo de teclado numérico" usando la combinación de teclas de [ Shift+ Mod4+ [key]] donde Mod4está el código modificador para la tecla de mi sistema operativo (también llamado "Comando" o "Tecla de Windows", y a veces asignado al código modificador de Supero Hyper) , y [key]es cualquiera de las teclas utilizadas en mi teclado numérico emulado (como "j" o "["). Las modificaciones simples a esta configuración deberían ser relativamente simples después de leer la solución completa.

Para hacer esto, definiremos un archivo de "tipo" xkb personalizado, que le dice a xkb cómo interpretar las diversas teclas modificadoras que usaremos para inicializar nuestra emulación de teclado, así como un archivo de "símbolos" xkb personalizado, que le dice a xkb cómo cada La tecla que presionamos debe comportarse normalmente (Grupo 1), cómo debe comportarse durante la emulación del teclado numérico (Grupo 2) y cómo alternar entre los dos (acción de Nivel 3 para ambos grupos). Finalmente, haremos que nuestra solución sea permanente integrándola en el xkbmap actual sedcada vez que iniciemos una nueva sesión (para que nuestra solución no se borre cada vez que xkbse actualice).

Descripción detallada de la solución

Estructura de directorios

{1}Lo primero que haremos será definir un directorio en el que guardaremos nuestros diversos archivos. El tuyo puede parecerse prácticamente a cualquier cosa, pero el mío se ve así.

/home
  +-<username>
    +-.xkb
      +-symbols
      +-types
      +-keymap
      +-log

Tipo de archivo

Una vez que tengamos nuestro árbol de directorios, definamos los archivos reales en nuestra solución. Lo primero que haremos será definir nuestro archivo "tipo". Este archivo le indicará xkbcómo moverse entre "niveles" (como cómo Shiftponer en mayúscula una letra, pasar del primer nivel de una letra minúscula a un nivel mayúsculo de la letra mayúscula). Estos niveles son un poco difíciles de comprender, especialmente para los hablantes nativos de inglés, pero los teclados internacionales los utilizan con gran efecto para letras y símbolos alternativos, así como para signos diacríticos.

Lo usaremos para definir cómo pretendemos indicar un cambio en nuestras claves. En otras palabras, le decimos que esperamos un comportamiento de "nivel 1" cuando no se presiona ningún modificador (normalmente, una letra minúscula estándar cuando estamos en nuestro "modo normal"), un comportamiento de "nivel 2" cuando mantenemos pulsada la Shifttecla (normalmente, una letra mayúscula estándar en nuestro "modo normal") y comportamiento de "nivel 3" cuando mantenemos presionados ambos Shift+ Mod4(un caso especial para nuestros propósitos, que usamos para indicar que, cuando se usa para modificar una clave, la clave ahora cambiar entre modos).

{2}Abre un nuevo archivo, al que llamaremos togglekeypad. Copie el siguiente bloque de código y guárdelo en su typesdirectorio en \home\<username>\.xkb\types. NOTA: Es posible que deba cambiar todas las instancias de Mod4cualquier modificador al que corresponda su botón "Comando"/"Tecla de Windows" (es posible que deba experimentar, consulteesta página web en Teclas modificadorascomo orientación) o cualquier otro modificador que desee.

partial default xkb_types "togglekeypad" { // Name of this type file
        type "TOGGLEKEYPAD" { // Name of this "type"
                modifiers = Shift+Mod4; // The modifiers that this type concerns itself with
                map[Shift] = level2; // Shift brings us to level 2
                map[Mod4+Shift] = level3; // Windows key plus shift brings us to level 3
                level_name[Level1] = "Base"; // Human-readable names for each level (not really used, but convenient)
                level_name[Level2] = "Shift";
                level_name[Level3] = "Transfer";
        };
};

{3}También debemos copiar este archivo al directorio /usr/share/X11/xkb/types/. Esto requerirá privilegios de root, lo que desafortunadamente anula el propósito de xkbser una aplicación de espacio de usuario, pero parece que no puedo setxkbmapreconocer el archivo sin hacer esto. ¡Se aceptan sugerencias!

Archivo de símbolos

Lo siguiente que haremos será indicar xkbqué debe hacer cada clave cuando se modifica en cada una de las formas que describimos en el archivo de tipos.

Diremos que queremos utilizar dos Grupos en nuestro archivo de símbolos. Esto significa que cada tecla tiene dos comportamientos generales diferentes entre los que cambiaremos de alguna manera, siendo esos comportamientos el comportamiento de escritura normal y el nuevo comportamiento de emulación del teclado numérico. Para cada clave, diremos que 1) queremos usar el TOGGLEKEYPADtipo, 2) definiremos los símbolos (es decir, lo que ve la computadora) asociados con cada una de las claves físicas en ambos Grupos para todos los Niveles, y 3) defina cualquier acción (cualquier cosa especial que xkbdeba hacer) asociada con cada tecla para ambos grupos en todos los niveles. Esto suena bastante confuso, pero debería tener un poco más de sentido si miramos un ejemplo.

La primera clave que vemos en el archivo de símbolos que pegué a continuación es la <AC07>clave. Esto corresponde a la tecla "J" en la mayoría de los teclados,según el mapa visto aquí(Figura 2). Para esta clave física, estamos diciendo que, en modo normal: en el nivel 1 (sin modificadores, según nuestro archivo de tipo) simplemente escribirá "j", y en el nivel 2 ( Shiftmodificador) solo escribirá "J". En el nivel 3, hace algo especial: no hay ningún símbolo asociado con el nivel 3, pero hay una acción, y esa acción es LockGroup(group=2). En otras palabras, cámbianos a nuestro segundo grupo, nuestro grupo "Teclado". Si miramos las siguientes líneas vemos que tenemos más símbolos y acciones definidas para el grupo 2 para esta misma tecla. Dice que, en el nivel 1 (sin modificadores), no escriba ningún símbolo, pero RedirectKey(keycode=<KP1>). Es decir, registrar esta tecla como si realmente acabáramos de pulsar la <KP1>tecla, que corresponde al "1" de un teclado. (Nota: podríamos haber puesto nuevamente NoAction() y haber usado el símbolo KP_1, que es el símbolo al que <KP1>corresponde esa clave, pero pensé que esto daría la mejor compatibilidad). Para el nivel 2, haga lo mismo, pero agregue el Shiftmodificador a la clave. Finalmente, para el nivel 3, nos encerramos nuevamente en el Grupo 1, modo "Estándar".

{4}Abre un nuevo archivo, al que llamaremos togglekeypad_symbols. Copie el siguiente bloque de código y guárdelo en su symbolsdirectorio en \home\<username>\.xkb\symbols.

default partial
xkb_symbols "togglekeypad" {
    name[Group1]= "Standard";
    name[Group2]= "Keypad";

    key <AC07> { // J
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ j,  J, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP1>), RedirectKey(keyCode=<KP1>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AC08> { // K
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ k,  K, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP2>), RedirectKey(keyCode=<KP2>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AC09> { // L
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ l,  L, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP3>), RedirectKey(keyCode=<KP3>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD07> { // U
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ u,  U, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP4>), RedirectKey(keyCode=<KP4>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD08> { // I
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ i,  I, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP5>), RedirectKey(keyCode=<KP5>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD09> { // O
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ o,  O, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP6>), RedirectKey(keyCode=<KP6>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE07> { // 7
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 7,  ampersand, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP7>), RedirectKey(keyCode=<KP7>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE08> { // 8
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 8,  asterisk, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP8>), RedirectKey(keyCode=<KP8>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE09> { // 9
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 9,  parenleft, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP9>), RedirectKey(keyCode=<KP9>), LockGroup(group=1)]
    };
    
    // NumLock
    key <AE06> { // 6
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 6,  asciicircum, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<NMLK>), RedirectKey(keyCode=<NMLK>), LockGroup(group=1)]
    };
    
    // Bottom Row (and zero)
    key <AB07> { // M
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ m,  M, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP0>), RedirectKey(keyCode=<KP0>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE10> { // 0
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 0,  parenright, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP0>), RedirectKey(keyCode=<KP0>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AB09> { // .
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ period,  greater, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPDL>), RedirectKey(keyCode=<KPDL>, modifiers=Shift), LockGroup(group=1)]
    };
    
    // Arithmetic Operators
    key <AE11> { // -
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ minus,  underscore, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPSU>), RedirectKey(keyCode=<KPSU>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE12> { // +
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ equal,  plus, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPAD>), RedirectKey(keyCode=<KPAD>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD12> { // [
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ bracketleft,  braceleft, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPDV>), RedirectKey(keyCode=<KPDV>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD12> { // ]
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ bracketright,  braceright, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPMU>), RedirectKey(keyCode=<KPMU>, modifiers=Shift), LockGroup(group=1)]
    };
};

Prueba nuestro teclado

{5}Para probar la configuración del teclado tal como está, abra una Terminalventana y escriba

setxkbmap -types complete+togglekeypad -print | sed -e '/xkb_symbols/s/"[[:space:]]/+togglekeypad_symbols(togglekeypad)&/' > $HOME/.xkb/keymap/customMap
xkbcomp -I$HOME/.xkb -R$HOME/.xkb keymap/customMap $DISPLAY

Esto tomará la configuración actual de nuestro xkbmapa (usando setxkbmap - print) mientras configura los tipos utilizados complete+togglekeypad(todo lo que está en el archivo /usr/share/X11/xkb/types/completey también incluido nuestro archivo de tipos en /usr/share/X11/xkb/types/togglekeypad). Luego introducirá esto en sed, que agregará nuestros símbolos togglekeypadde nuestro archivo togglekeypad_symbolsa los archivos de símbolos utilizados. Finalmente, utilizamos xkbcomppara compilar el nuevo mapa de teclas.

Tenga en cuenta que, en mi máquina, se supone que NumLock está desactivado (porque no hay teclado numérico en mi máquina), por lo que las teclas del teclado numérico en realidad enviarán sus funciones principales a la computadora, es decir, Inicio, Fin, PG Up, PG Down, etc. Para obtener los números escritos cuando se utiliza el teclado numérico emulado, mantenga presionada la tecla Mayús. He probado varios métodos para cambiar este comportamiento (intercambiando el modifersargumento entre niveles en el archivo de símbolos, asignando una nueva clave para emular la tecla Bloq Num <NMLK>y cambiándola), pero nada ha funcionado todavía para mí. Afortunadamente, sin embargo, cuando se prueba en Blender, funciona exactamente como se esperaba sin necesidad de mantener presionada la tecla Mayús.

{6}Si las cosas han ido terriblemente mal en este punto, entonces no se preocupe, simplemente cierre sesión/inicie sesión (o en el peor de los casos reinicie), depure e intente nuevamente. Si todo funciona, hagámoslo permanente.

Hacer que la solución sea permanente

Ciertamente, existen algunas formas más elegantes de hacer que nuestra solución sea persistente entre sesiones, pero el método más fácil y confiable para mí fue simplemente poner los comandos anteriores al final de mi ~/.bashrcarchivo. utilicé elsolución propuesta aquílo que agrega un poco de verificación de errores y agregó un poco más (para poder ver los resultados de error).

{7}Abre el archivo ~/.bashrc. Agregue el siguiente script al final:

    # Setup custom keyboard remapping to emulate a number pad when "Shift+Cmd+numap_key" is pressed to initialize
if [ -d $HOME/.xkb/keymap ]; then
  setxkbmap -types complete+togglekeypad -print | \
    sed -e '/xkb_symbols/s/"[[:space:]]/+togglekeypad_symbols(togglekeypad)&/' > $HOME/.xkb/keymap/customMap 2> $HOME/.xkb/log/sedErrors
  xkbcomp -w0 -I$HOME/.xkb -R$HOME/.xkb keymap/customMap $DISPLAY > $HOME/.xkb/log/outputOfCommand 2>&1
fi

{8}Al reiniciar, la emulación del teclado numérico debería hacerse permanente.

Conclusión

Si bien la explicación es larga, el método en sí es relativamente corto. Las deficiencias son que Blender requiere un método de bloqueo para funcionar correctamente, mientras que yo hubiera preferido un método de retención, y también que requiere acceso de root para reconocer xkbnuestro archivo de tipos personalizados por alguna razón. Sin embargo, en general, esto parece funcionar bien para mí. Si tiene alguna pregunta o sugerencia, ¡no dude en dejarla a continuación!

información relacionada