keymap.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. static int
  9. valid_layout_or_variant(char *sym)
  10. {
  11. size_t i;
  12. /* invalid symbols from xkb rules config */
  13. static const char *invalid[] = { "evdev", "inet", "pc", "base" };
  14. for (i = 0; i < LEN(invalid); i++) {
  15. if (!strncmp(sym, invalid[i], strlen(invalid[i]))) {
  16. return 0;
  17. }
  18. }
  19. return 1;
  20. }
  21. static char *
  22. get_layout(char *syms, int grp_num)
  23. {
  24. char *tok, *layout;
  25. int grp;
  26. layout = NULL;
  27. tok = strtok(syms, "+:");
  28. for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) {
  29. if (!valid_layout_or_variant(tok)) {
  30. continue;
  31. } else if (strlen(tok) == 1 && isdigit(tok[0])) {
  32. /* ignore :2, :3, :4 (additional layout groups) */
  33. continue;
  34. }
  35. layout = tok;
  36. grp++;
  37. }
  38. return layout;
  39. }
  40. const char *
  41. keymap(void)
  42. {
  43. Display *dpy;
  44. XkbDescRec *desc;
  45. XkbStateRec state;
  46. char *symbols, *layout;
  47. layout = NULL;
  48. if (!(dpy = XOpenDisplay(NULL))) {
  49. warn("XOpenDisplay: Failed to open display");
  50. return NULL;
  51. }
  52. if (!(desc = XkbAllocKeyboard())) {
  53. warn("XkbAllocKeyboard: Failed to allocate keyboard");
  54. goto end;
  55. }
  56. if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {
  57. warn("XkbGetNames: Failed to retrieve key symbols");
  58. goto end;
  59. }
  60. if (XkbGetState(dpy, XkbUseCoreKbd, &state)) {
  61. warn("XkbGetState: Failed to retrieve keyboard state");
  62. goto end;
  63. }
  64. if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) {
  65. warn("XGetAtomName: Failed to get atom name");
  66. goto end;
  67. }
  68. layout = (char *)bprintf("%s", get_layout(symbols, state.group));
  69. XFree(symbols);
  70. end:
  71. XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
  72. if (XCloseDisplay(dpy)) {
  73. warn("XCloseDisplay: Failed to close display");
  74. }
  75. return layout;
  76. }