Ahora, estoy trabajando en el desarrollo de aplicaciones en Linux y quiero capturar el evento de cambio de diseño del teclado (cambiar el diseño del teclado a través de UI/widget/shell/programación, etc.) y obtener/configurar la nueva información de diseño del teclado para continuar con el proceso. Creo que esta no es una pregunta nueva, pero busco en stackoverflow una y otra vez, pero no hay respuesta. ¡Espero poder obtener la respuesta correcta aquí!
La solución principal que quiero aprender se describe aquí. En Windows, el mensaje de Windows WM_INPUTLANGCHANGE podría capturarse en WinProc, que contiene información sobre el diseño del teclado. Y podríamos usar la API GetKeyboardLayout() para obtener información actual sobre el diseño del teclado. Finalmente, si quiero usar mi diseño de teclado preferido, podría usar ActivateKeyboardLayout() para activar el diseño de teclado.
En resumen, espero encontrar los mensajes de notificación y cómo capturar el mensaje en código (es mejor que me muestre un ejemplo) en Linux, la API Obtener diseño de teclado y la API Establecer diseño de teclado en Linux. El lenguaje de desarrollo es C/C++, también.
Gracias por adelantado.
La otra respuesta no me funciona. Se compila y ejecuta, pero el evento MappingNotify no ocurre cuando cambio los diseños. Aquí hay una modificación que funciona para mí.
#include <stdio.h> #include <X11/Xutil.h> #include <X11/XKBlib.h> int main(int argc, char **argv) { XEvent e; Display *d; if (!(d = XOpenDisplay(NULL))) { fprintf(stderr, "cannot open display\n"); return 1; } XKeysymToKeycode(d, XK_F1); int xkbEventType; XkbQueryExtension(d, 0, &xkbEventType, 0, 0, 0); XkbSelectEvents(d, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask); XSync(d, False); while (1) { XNextEvent(d, &e); if (e.type == xkbEventType) { XkbEvent* xkbEvent = (XkbEvent*) &e; if (xkbEvent->any.xkb_type == XkbStateNotify) { int lang = xkbEvent->state.group; if (lang == 1) { fprintf(stdout, "1\n"); fflush(stdout); } else { fprintf(stdout, "0\n"); fflush(stdout); } } } } return(0); }Compilar con:
gcc -Wall -O2 xmappingnotify.c -o xmappingnotify -lX11Yo lo uso así:
xmappingnotify | xargs -I {} my-custom-command {} & entonces my-custom-command [number_of_the_layout] se ejecuta cuando cambio los diseños. Tengo 2 diseños, xmappingnotify genera "1" para un diseño y "0" para el otro.
Respuesta para X11:
Detectar cambios a través del evento MappingNotify
Cambiar o consultar el diseño a través de setxkbmap
Aquí hay un ejemplo básico de xlib para detectar eventos de MappingNotify:
#include <stdio.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> int main(int argc, char **argv) { XEvent event; Display *dpy; if (!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, "cannot open display\n"); return 1; } /** * Note: We might never get a MappingNotify event if the * modifier and keymap information was never cached in Xlib. * The next line makes sure that this happens initially. */ XKeysymToKeycode(dpy, XK_F1); while (1) { XNextEvent(dpy, &event); if (event.type == MappingNotify) { XMappingEvent *e = (XMappingEvent *) &event; if (e->request == MappingKeyboard) { fprintf(stderr, "The keyboard mapping was changed!\n"); } XRefreshKeyboardMapping(e); } } return(0); }Comando construido:
gcc -Wall -O2 xmappingnotify.c -o xmappingnotify -lX11Utilicé la respuesta de @gvlasov como una notificación de diseño de teclado en la barra dwm de Suckless con un parche de diseño de teclado por ventana. Funciona correctamente con respecto al resultado, pero produce demasiados eventos (ctrl, mod, teclas de mayúsculas, presionar y soltar y el movimiento de la rueda de desplazamiento del mouse genera el diseño; el correcto, pero esto no es necesario, solo cuando se cambia el diseño debe devolver el diseño ). Probablemente sea lo mencionado por el comentario de @matanster. Así que hice un cambio que detuvo la salida del movimiento de la rueda del mouse, aunque todavía se produce la salida de las teclas ctrl, mod, shift y pulsaciones. No es ideal, es un poco mejor:
Cambió la línea:
XkbSelectEvents(d, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask);con este:
XkbSelectEventDetails(d, XkbUseCoreKbd, XkbMapNotifyMask, XkbAllEventsMask, XkbAllEventsMask);Si alguien tiene alguna idea de cómo obtener resultados / resultados solo en el cambio de diseño del teclado y no en las teclas ctrl, mod, shift, presione y suelte, es bienvenido.
Actualizar, usando esto:
XkbSelectEventDetails(d, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);Obtuve el resultado esperado. El único evento notificado es el cambio de distribución del teclado, ni las pulsaciones ni las liberaciones de teclas. El único inconveniente en comparación con mi línea anterior es que los cambios de mayúsculas no se notifican, lo que era posible antes.