keymap.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* See LICENSE file for copyright and license details. */
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <X11/XKBlib.h>
  6. #include <X11/Xlib.h>
  7. #include "../util.h"
  8. #define LAYOUT_MAX 256
  9. /* Given a token (sym) from the xkb_symbols string
  10. * check whether it is a valid layout/variant. The
  11. * EXCLUDES array contains invalid layouts/variants
  12. * that are part of the xkb rules config.
  13. */
  14. static int
  15. IsLayoutOrVariant(char *sym)
  16. {
  17. static const char* EXCLUDES[] = { "evdev", "inet", "pc", "base" };
  18. size_t i;
  19. for (i = 0; i < sizeof(EXCLUDES)/sizeof(EXCLUDES[0]); ++i) {
  20. if (strstr(sym, EXCLUDES[i])) {
  21. return 0;
  22. }
  23. }
  24. return 1;
  25. }
  26. static void
  27. GetKeyLayout(char *syms, char layout[], int groupNum)
  28. {
  29. char *token, *copy, *delims;
  30. int group;
  31. delims = "+:";
  32. group = 0;
  33. copy = strdup(syms);
  34. token = strtok(copy, delims);
  35. while (token != NULL && group <= groupNum) {
  36. /* Ignore :2,:3,:4 which represent additional layout
  37. * groups
  38. */
  39. if (IsLayoutOrVariant(token)
  40. && !(strlen(token) == 1 && isdigit(token[0]))) {
  41. strncpy (layout, token, LAYOUT_MAX);
  42. group++;
  43. }
  44. token = strtok(NULL,delims);
  45. }
  46. free(copy);
  47. }
  48. const char *
  49. keymap(void)
  50. {
  51. static char layout[LAYOUT_MAX];
  52. Display *dpy;
  53. char *symbols = NULL;
  54. XkbDescRec* desc = NULL;
  55. memset(layout, '\0', LAYOUT_MAX);
  56. if (!(dpy = XOpenDisplay(NULL))) {
  57. warn("XOpenDisplay: Failed to open display");
  58. return NULL;
  59. }
  60. ;
  61. if (!(desc = XkbAllocKeyboard())) {
  62. warn("XkbAllocKeyboard: failed to allocate keyboard");
  63. XCloseDisplay(dpy);
  64. return NULL;
  65. }
  66. XkbGetNames(dpy, XkbSymbolsNameMask, desc);
  67. if (desc->names) {
  68. XkbStateRec state;
  69. XkbGetState(dpy, XkbUseCoreKbd, &state);
  70. symbols = XGetAtomName(dpy, desc->names->symbols);
  71. GetKeyLayout(symbols, layout, state.group);
  72. XFree(symbols);
  73. } else {
  74. warn("XkbGetNames: failed to retrieve symbols for keys");
  75. return NULL;
  76. }
  77. XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
  78. XCloseDisplay(dpy);
  79. return layout;
  80. }