xkb_glfw.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. //========================================================================
  2. // GLFW 3.4 XKB - www.glfw.org
  3. //------------------------------------------------------------------------
  4. // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,
  11. // including commercial applications, and to alter it and redistribute it
  12. // freely, subject to the following restrictions:
  13. //
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would
  17. // be appreciated but is not required.
  18. //
  19. // 2. Altered source versions must be plainly marked as such, and must not
  20. // be misrepresented as being the original software.
  21. //
  22. // 3. This notice may not be removed or altered from any source
  23. // distribution.
  24. //
  25. //========================================================================
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include "internal.h"
  29. #include "xkb_glfw.h"
  30. #ifdef _GLFW_X11
  31. #include <X11/XKBlib.h>
  32. #endif
  33. #define debug debug_input
  34. #ifdef XKB_HAS_NO_UTF32
  35. #include "xkb-compat-shim.h"
  36. #else
  37. #define utf32_to_keysym xkb_utf32_to_keysym
  38. #endif
  39. static int
  40. glfw_key_for_sym(xkb_keysym_t key) {
  41. switch(key) {
  42. /* start xkb to glfw (auto generated by gen-key-constants.py do not edit) */
  43. case XKB_KEY_Escape: return GLFW_FKEY_ESCAPE;
  44. case XKB_KEY_Return: return GLFW_FKEY_ENTER;
  45. case XKB_KEY_Tab: return GLFW_FKEY_TAB;
  46. case XKB_KEY_BackSpace: return GLFW_FKEY_BACKSPACE;
  47. case XKB_KEY_Insert: return GLFW_FKEY_INSERT;
  48. case XKB_KEY_Delete: return GLFW_FKEY_DELETE;
  49. case XKB_KEY_Left: return GLFW_FKEY_LEFT;
  50. case XKB_KEY_Right: return GLFW_FKEY_RIGHT;
  51. case XKB_KEY_Up: return GLFW_FKEY_UP;
  52. case XKB_KEY_Down: return GLFW_FKEY_DOWN;
  53. case XKB_KEY_Page_Up: return GLFW_FKEY_PAGE_UP;
  54. case XKB_KEY_Page_Down: return GLFW_FKEY_PAGE_DOWN;
  55. case XKB_KEY_Home: return GLFW_FKEY_HOME;
  56. case XKB_KEY_End: return GLFW_FKEY_END;
  57. case XKB_KEY_Caps_Lock: return GLFW_FKEY_CAPS_LOCK;
  58. case XKB_KEY_Scroll_Lock: return GLFW_FKEY_SCROLL_LOCK;
  59. case XKB_KEY_Num_Lock: return GLFW_FKEY_NUM_LOCK;
  60. case XKB_KEY_Print: return GLFW_FKEY_PRINT_SCREEN;
  61. case XKB_KEY_Pause: return GLFW_FKEY_PAUSE;
  62. case XKB_KEY_Menu: return GLFW_FKEY_MENU;
  63. case XKB_KEY_F1: return GLFW_FKEY_F1;
  64. case XKB_KEY_F2: return GLFW_FKEY_F2;
  65. case XKB_KEY_F3: return GLFW_FKEY_F3;
  66. case XKB_KEY_F4: return GLFW_FKEY_F4;
  67. case XKB_KEY_F5: return GLFW_FKEY_F5;
  68. case XKB_KEY_F6: return GLFW_FKEY_F6;
  69. case XKB_KEY_F7: return GLFW_FKEY_F7;
  70. case XKB_KEY_F8: return GLFW_FKEY_F8;
  71. case XKB_KEY_F9: return GLFW_FKEY_F9;
  72. case XKB_KEY_F10: return GLFW_FKEY_F10;
  73. case XKB_KEY_F11: return GLFW_FKEY_F11;
  74. case XKB_KEY_F12: return GLFW_FKEY_F12;
  75. case XKB_KEY_F13: return GLFW_FKEY_F13;
  76. case XKB_KEY_F14: return GLFW_FKEY_F14;
  77. case XKB_KEY_F15: return GLFW_FKEY_F15;
  78. case XKB_KEY_F16: return GLFW_FKEY_F16;
  79. case XKB_KEY_F17: return GLFW_FKEY_F17;
  80. case XKB_KEY_F18: return GLFW_FKEY_F18;
  81. case XKB_KEY_F19: return GLFW_FKEY_F19;
  82. case XKB_KEY_F20: return GLFW_FKEY_F20;
  83. case XKB_KEY_F21: return GLFW_FKEY_F21;
  84. case XKB_KEY_F22: return GLFW_FKEY_F22;
  85. case XKB_KEY_F23: return GLFW_FKEY_F23;
  86. case XKB_KEY_F24: return GLFW_FKEY_F24;
  87. case XKB_KEY_F25: return GLFW_FKEY_F25;
  88. case XKB_KEY_F26: return GLFW_FKEY_F26;
  89. case XKB_KEY_F27: return GLFW_FKEY_F27;
  90. case XKB_KEY_F28: return GLFW_FKEY_F28;
  91. case XKB_KEY_F29: return GLFW_FKEY_F29;
  92. case XKB_KEY_F30: return GLFW_FKEY_F30;
  93. case XKB_KEY_F31: return GLFW_FKEY_F31;
  94. case XKB_KEY_F32: return GLFW_FKEY_F32;
  95. case XKB_KEY_F33: return GLFW_FKEY_F33;
  96. case XKB_KEY_F34: return GLFW_FKEY_F34;
  97. case XKB_KEY_F35: return GLFW_FKEY_F35;
  98. case XKB_KEY_KP_0: return GLFW_FKEY_KP_0;
  99. case XKB_KEY_KP_1: return GLFW_FKEY_KP_1;
  100. case XKB_KEY_KP_2: return GLFW_FKEY_KP_2;
  101. case XKB_KEY_KP_3: return GLFW_FKEY_KP_3;
  102. case XKB_KEY_KP_4: return GLFW_FKEY_KP_4;
  103. case XKB_KEY_KP_5: return GLFW_FKEY_KP_5;
  104. case XKB_KEY_KP_6: return GLFW_FKEY_KP_6;
  105. case XKB_KEY_KP_7: return GLFW_FKEY_KP_7;
  106. case XKB_KEY_KP_8: return GLFW_FKEY_KP_8;
  107. case XKB_KEY_KP_9: return GLFW_FKEY_KP_9;
  108. case XKB_KEY_KP_Decimal: return GLFW_FKEY_KP_DECIMAL;
  109. case XKB_KEY_KP_Divide: return GLFW_FKEY_KP_DIVIDE;
  110. case XKB_KEY_KP_Multiply: return GLFW_FKEY_KP_MULTIPLY;
  111. case XKB_KEY_KP_Subtract: return GLFW_FKEY_KP_SUBTRACT;
  112. case XKB_KEY_KP_Add: return GLFW_FKEY_KP_ADD;
  113. case XKB_KEY_KP_Enter: return GLFW_FKEY_KP_ENTER;
  114. case XKB_KEY_KP_Equal: return GLFW_FKEY_KP_EQUAL;
  115. case XKB_KEY_KP_Separator: return GLFW_FKEY_KP_SEPARATOR;
  116. case XKB_KEY_KP_Left: return GLFW_FKEY_KP_LEFT;
  117. case XKB_KEY_KP_Right: return GLFW_FKEY_KP_RIGHT;
  118. case XKB_KEY_KP_Up: return GLFW_FKEY_KP_UP;
  119. case XKB_KEY_KP_Down: return GLFW_FKEY_KP_DOWN;
  120. case XKB_KEY_KP_Page_Up: return GLFW_FKEY_KP_PAGE_UP;
  121. case XKB_KEY_KP_Page_Down: return GLFW_FKEY_KP_PAGE_DOWN;
  122. case XKB_KEY_KP_Home: return GLFW_FKEY_KP_HOME;
  123. case XKB_KEY_KP_End: return GLFW_FKEY_KP_END;
  124. case XKB_KEY_KP_Insert: return GLFW_FKEY_KP_INSERT;
  125. case XKB_KEY_KP_Delete: return GLFW_FKEY_KP_DELETE;
  126. case XKB_KEY_KP_Begin: return GLFW_FKEY_KP_BEGIN;
  127. case XKB_KEY_XF86AudioPlay: return GLFW_FKEY_MEDIA_PLAY;
  128. case XKB_KEY_XF86AudioPause: return GLFW_FKEY_MEDIA_PAUSE;
  129. case XKB_KEY_XF86AudioStop: return GLFW_FKEY_MEDIA_STOP;
  130. case XKB_KEY_XF86AudioForward: return GLFW_FKEY_MEDIA_FAST_FORWARD;
  131. case XKB_KEY_XF86AudioRewind: return GLFW_FKEY_MEDIA_REWIND;
  132. case XKB_KEY_XF86AudioNext: return GLFW_FKEY_MEDIA_TRACK_NEXT;
  133. case XKB_KEY_XF86AudioPrev: return GLFW_FKEY_MEDIA_TRACK_PREVIOUS;
  134. case XKB_KEY_XF86AudioRecord: return GLFW_FKEY_MEDIA_RECORD;
  135. case XKB_KEY_XF86AudioLowerVolume: return GLFW_FKEY_LOWER_VOLUME;
  136. case XKB_KEY_XF86AudioRaiseVolume: return GLFW_FKEY_RAISE_VOLUME;
  137. case XKB_KEY_XF86AudioMute: return GLFW_FKEY_MUTE_VOLUME;
  138. case XKB_KEY_Shift_L: return GLFW_FKEY_LEFT_SHIFT;
  139. case XKB_KEY_Control_L: return GLFW_FKEY_LEFT_CONTROL;
  140. case XKB_KEY_Alt_L: return GLFW_FKEY_LEFT_ALT;
  141. case XKB_KEY_Super_L: return GLFW_FKEY_LEFT_SUPER;
  142. case XKB_KEY_Hyper_L: return GLFW_FKEY_LEFT_HYPER;
  143. case XKB_KEY_Meta_L: return GLFW_FKEY_LEFT_META;
  144. case XKB_KEY_Shift_R: return GLFW_FKEY_RIGHT_SHIFT;
  145. case XKB_KEY_Control_R: return GLFW_FKEY_RIGHT_CONTROL;
  146. case XKB_KEY_Alt_R: return GLFW_FKEY_RIGHT_ALT;
  147. case XKB_KEY_Super_R: return GLFW_FKEY_RIGHT_SUPER;
  148. case XKB_KEY_Hyper_R: return GLFW_FKEY_RIGHT_HYPER;
  149. case XKB_KEY_Meta_R: return GLFW_FKEY_RIGHT_META;
  150. case XKB_KEY_ISO_Level3_Shift: return GLFW_FKEY_ISO_LEVEL3_SHIFT;
  151. case XKB_KEY_ISO_Level5_Shift: return GLFW_FKEY_ISO_LEVEL5_SHIFT;
  152. /* end xkb to glfw */
  153. default:
  154. return xkb_keysym_to_utf32(key);
  155. }
  156. }
  157. xkb_keysym_t
  158. glfw_xkb_sym_for_key(uint32_t key) {
  159. switch(key) {
  160. /* start glfw to xkb (auto generated by gen-key-constants.py do not edit) */
  161. case GLFW_FKEY_ESCAPE: return XKB_KEY_Escape;
  162. case GLFW_FKEY_ENTER: return XKB_KEY_Return;
  163. case GLFW_FKEY_TAB: return XKB_KEY_Tab;
  164. case GLFW_FKEY_BACKSPACE: return XKB_KEY_BackSpace;
  165. case GLFW_FKEY_INSERT: return XKB_KEY_Insert;
  166. case GLFW_FKEY_DELETE: return XKB_KEY_Delete;
  167. case GLFW_FKEY_LEFT: return XKB_KEY_Left;
  168. case GLFW_FKEY_RIGHT: return XKB_KEY_Right;
  169. case GLFW_FKEY_UP: return XKB_KEY_Up;
  170. case GLFW_FKEY_DOWN: return XKB_KEY_Down;
  171. case GLFW_FKEY_PAGE_UP: return XKB_KEY_Page_Up;
  172. case GLFW_FKEY_PAGE_DOWN: return XKB_KEY_Page_Down;
  173. case GLFW_FKEY_HOME: return XKB_KEY_Home;
  174. case GLFW_FKEY_END: return XKB_KEY_End;
  175. case GLFW_FKEY_CAPS_LOCK: return XKB_KEY_Caps_Lock;
  176. case GLFW_FKEY_SCROLL_LOCK: return XKB_KEY_Scroll_Lock;
  177. case GLFW_FKEY_NUM_LOCK: return XKB_KEY_Num_Lock;
  178. case GLFW_FKEY_PRINT_SCREEN: return XKB_KEY_Print;
  179. case GLFW_FKEY_PAUSE: return XKB_KEY_Pause;
  180. case GLFW_FKEY_MENU: return XKB_KEY_Menu;
  181. case GLFW_FKEY_F1: return XKB_KEY_F1;
  182. case GLFW_FKEY_F2: return XKB_KEY_F2;
  183. case GLFW_FKEY_F3: return XKB_KEY_F3;
  184. case GLFW_FKEY_F4: return XKB_KEY_F4;
  185. case GLFW_FKEY_F5: return XKB_KEY_F5;
  186. case GLFW_FKEY_F6: return XKB_KEY_F6;
  187. case GLFW_FKEY_F7: return XKB_KEY_F7;
  188. case GLFW_FKEY_F8: return XKB_KEY_F8;
  189. case GLFW_FKEY_F9: return XKB_KEY_F9;
  190. case GLFW_FKEY_F10: return XKB_KEY_F10;
  191. case GLFW_FKEY_F11: return XKB_KEY_F11;
  192. case GLFW_FKEY_F12: return XKB_KEY_F12;
  193. case GLFW_FKEY_F13: return XKB_KEY_F13;
  194. case GLFW_FKEY_F14: return XKB_KEY_F14;
  195. case GLFW_FKEY_F15: return XKB_KEY_F15;
  196. case GLFW_FKEY_F16: return XKB_KEY_F16;
  197. case GLFW_FKEY_F17: return XKB_KEY_F17;
  198. case GLFW_FKEY_F18: return XKB_KEY_F18;
  199. case GLFW_FKEY_F19: return XKB_KEY_F19;
  200. case GLFW_FKEY_F20: return XKB_KEY_F20;
  201. case GLFW_FKEY_F21: return XKB_KEY_F21;
  202. case GLFW_FKEY_F22: return XKB_KEY_F22;
  203. case GLFW_FKEY_F23: return XKB_KEY_F23;
  204. case GLFW_FKEY_F24: return XKB_KEY_F24;
  205. case GLFW_FKEY_F25: return XKB_KEY_F25;
  206. case GLFW_FKEY_F26: return XKB_KEY_F26;
  207. case GLFW_FKEY_F27: return XKB_KEY_F27;
  208. case GLFW_FKEY_F28: return XKB_KEY_F28;
  209. case GLFW_FKEY_F29: return XKB_KEY_F29;
  210. case GLFW_FKEY_F30: return XKB_KEY_F30;
  211. case GLFW_FKEY_F31: return XKB_KEY_F31;
  212. case GLFW_FKEY_F32: return XKB_KEY_F32;
  213. case GLFW_FKEY_F33: return XKB_KEY_F33;
  214. case GLFW_FKEY_F34: return XKB_KEY_F34;
  215. case GLFW_FKEY_F35: return XKB_KEY_F35;
  216. case GLFW_FKEY_KP_0: return XKB_KEY_KP_0;
  217. case GLFW_FKEY_KP_1: return XKB_KEY_KP_1;
  218. case GLFW_FKEY_KP_2: return XKB_KEY_KP_2;
  219. case GLFW_FKEY_KP_3: return XKB_KEY_KP_3;
  220. case GLFW_FKEY_KP_4: return XKB_KEY_KP_4;
  221. case GLFW_FKEY_KP_5: return XKB_KEY_KP_5;
  222. case GLFW_FKEY_KP_6: return XKB_KEY_KP_6;
  223. case GLFW_FKEY_KP_7: return XKB_KEY_KP_7;
  224. case GLFW_FKEY_KP_8: return XKB_KEY_KP_8;
  225. case GLFW_FKEY_KP_9: return XKB_KEY_KP_9;
  226. case GLFW_FKEY_KP_DECIMAL: return XKB_KEY_KP_Decimal;
  227. case GLFW_FKEY_KP_DIVIDE: return XKB_KEY_KP_Divide;
  228. case GLFW_FKEY_KP_MULTIPLY: return XKB_KEY_KP_Multiply;
  229. case GLFW_FKEY_KP_SUBTRACT: return XKB_KEY_KP_Subtract;
  230. case GLFW_FKEY_KP_ADD: return XKB_KEY_KP_Add;
  231. case GLFW_FKEY_KP_ENTER: return XKB_KEY_KP_Enter;
  232. case GLFW_FKEY_KP_EQUAL: return XKB_KEY_KP_Equal;
  233. case GLFW_FKEY_KP_SEPARATOR: return XKB_KEY_KP_Separator;
  234. case GLFW_FKEY_KP_LEFT: return XKB_KEY_KP_Left;
  235. case GLFW_FKEY_KP_RIGHT: return XKB_KEY_KP_Right;
  236. case GLFW_FKEY_KP_UP: return XKB_KEY_KP_Up;
  237. case GLFW_FKEY_KP_DOWN: return XKB_KEY_KP_Down;
  238. case GLFW_FKEY_KP_PAGE_UP: return XKB_KEY_KP_Page_Up;
  239. case GLFW_FKEY_KP_PAGE_DOWN: return XKB_KEY_KP_Page_Down;
  240. case GLFW_FKEY_KP_HOME: return XKB_KEY_KP_Home;
  241. case GLFW_FKEY_KP_END: return XKB_KEY_KP_End;
  242. case GLFW_FKEY_KP_INSERT: return XKB_KEY_KP_Insert;
  243. case GLFW_FKEY_KP_DELETE: return XKB_KEY_KP_Delete;
  244. case GLFW_FKEY_KP_BEGIN: return XKB_KEY_KP_Begin;
  245. case GLFW_FKEY_MEDIA_PLAY: return XKB_KEY_XF86AudioPlay;
  246. case GLFW_FKEY_MEDIA_PAUSE: return XKB_KEY_XF86AudioPause;
  247. case GLFW_FKEY_MEDIA_STOP: return XKB_KEY_XF86AudioStop;
  248. case GLFW_FKEY_MEDIA_FAST_FORWARD: return XKB_KEY_XF86AudioForward;
  249. case GLFW_FKEY_MEDIA_REWIND: return XKB_KEY_XF86AudioRewind;
  250. case GLFW_FKEY_MEDIA_TRACK_NEXT: return XKB_KEY_XF86AudioNext;
  251. case GLFW_FKEY_MEDIA_TRACK_PREVIOUS: return XKB_KEY_XF86AudioPrev;
  252. case GLFW_FKEY_MEDIA_RECORD: return XKB_KEY_XF86AudioRecord;
  253. case GLFW_FKEY_LOWER_VOLUME: return XKB_KEY_XF86AudioLowerVolume;
  254. case GLFW_FKEY_RAISE_VOLUME: return XKB_KEY_XF86AudioRaiseVolume;
  255. case GLFW_FKEY_MUTE_VOLUME: return XKB_KEY_XF86AudioMute;
  256. case GLFW_FKEY_LEFT_SHIFT: return XKB_KEY_Shift_L;
  257. case GLFW_FKEY_LEFT_CONTROL: return XKB_KEY_Control_L;
  258. case GLFW_FKEY_LEFT_ALT: return XKB_KEY_Alt_L;
  259. case GLFW_FKEY_LEFT_SUPER: return XKB_KEY_Super_L;
  260. case GLFW_FKEY_LEFT_HYPER: return XKB_KEY_Hyper_L;
  261. case GLFW_FKEY_LEFT_META: return XKB_KEY_Meta_L;
  262. case GLFW_FKEY_RIGHT_SHIFT: return XKB_KEY_Shift_R;
  263. case GLFW_FKEY_RIGHT_CONTROL: return XKB_KEY_Control_R;
  264. case GLFW_FKEY_RIGHT_ALT: return XKB_KEY_Alt_R;
  265. case GLFW_FKEY_RIGHT_SUPER: return XKB_KEY_Super_R;
  266. case GLFW_FKEY_RIGHT_HYPER: return XKB_KEY_Hyper_R;
  267. case GLFW_FKEY_RIGHT_META: return XKB_KEY_Meta_R;
  268. case GLFW_FKEY_ISO_LEVEL3_SHIFT: return XKB_KEY_ISO_Level3_Shift;
  269. case GLFW_FKEY_ISO_LEVEL5_SHIFT: return XKB_KEY_ISO_Level5_Shift;
  270. /* end glfw to xkb */
  271. default:
  272. return utf32_to_keysym(key);
  273. }
  274. }
  275. #ifdef _GLFW_X11
  276. bool
  277. glfw_xkb_set_x11_events_mask(void) {
  278. if (!XkbSelectEvents(_glfw.x11.display, XkbUseCoreKbd, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask)) {
  279. _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set XKB events mask");
  280. return false;
  281. }
  282. return true;
  283. }
  284. bool
  285. glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
  286. xkb->keyboard_device_id = -1;
  287. xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display);
  288. if (!conn) {
  289. _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve XCB connection");
  290. return false;
  291. }
  292. xkb->keyboard_device_id = xkb_x11_get_core_keyboard_device_id(conn);
  293. if (xkb->keyboard_device_id == -1) {
  294. _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve core keyboard device id");
  295. return false;
  296. }
  297. return true;
  298. }
  299. #define xkb_glfw_load_keymap(keymap, ...) {\
  300. xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \
  301. if (conn) keymap = xkb_x11_keymap_new_from_device(xkb->context, conn, xkb->keyboard_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); \
  302. }
  303. #define xkb_glfw_load_state(keymap, state) {\
  304. xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \
  305. if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \
  306. }
  307. static void
  308. glfw_xkb_update_masks(_GLFWXKBData *xkb) {
  309. // See https://github.com/kovidgoyal/kitty/pull/3430 for discussion
  310. bool succeeded = false;
  311. unsigned used_bits = 0; /* To avoid using the same bit twice */
  312. XkbDescPtr xkb_ptr = XkbGetMap( _glfw.x11.display, XkbVirtualModsMask | XkbVirtualModMapMask, XkbUseCoreKbd );
  313. /* shift, control, and capsLock are special; they cannot be identified reliably on X11 */
  314. #define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx; used_bits |= xkb->a##Mask;
  315. S(control, XKB_MOD_NAME_CTRL);
  316. S(shift, XKB_MOD_NAME_SHIFT);
  317. S(capsLock, XKB_MOD_NAME_CAPS);
  318. #undef S
  319. #define S( a ) xkb->a##Idx = XKB_MOD_INVALID; xkb->a##Mask = 0
  320. S(alt); S(super); S(hyper); S(meta); S(numLock);
  321. #undef S
  322. if (xkb_ptr) {
  323. Status status = XkbGetNames(_glfw.x11.display, XkbVirtualModNamesMask, xkb_ptr);
  324. if (status == Success) {
  325. for (int indx = 0; indx < XkbNumVirtualMods; ++indx) {
  326. Atom atom = xkb_ptr->names->vmods[indx];
  327. if (atom) {
  328. unsigned mask_rtn = 0;
  329. if (XkbVirtualModsToReal( xkb_ptr, 1<<indx, &mask_rtn) ) {
  330. const char *name = XGetAtomName(_glfw.x11.display, atom);
  331. #define S( a, s ) if (!(used_bits & mask_rtn) && strcmp(name, #s) == 0) xkb->a##Mask = mask_rtn, used_bits |= mask_rtn
  332. /* Note that the order matters here; earlier is higher priority. */
  333. S(alt, Alt);
  334. S(super, Super);
  335. S(numLock, NumLock);
  336. S(meta, Meta);
  337. S(hyper, Hyper);
  338. #undef S
  339. }
  340. }
  341. }
  342. succeeded = true;
  343. }
  344. XkbFreeNames(xkb_ptr, XkbVirtualModNamesMask, True);
  345. XkbFreeKeyboard(xkb_ptr, 0, True);
  346. }
  347. if (succeeded) {
  348. unsigned indx, shifted;
  349. for (indx = 0, shifted = 1; used_bits; ++indx, shifted <<= 1, used_bits >>= 1) {
  350. #define S( a ) if ( ( xkb->a##Mask & shifted ) == shifted ) xkb->a##Idx = indx
  351. S(alt); S(super); S(hyper); S(meta); S(numLock);
  352. #undef S
  353. }
  354. }
  355. #define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx;
  356. if (!succeeded) {
  357. S(numLock, XKB_MOD_NAME_NUM);
  358. S(alt, XKB_MOD_NAME_ALT);
  359. S(super, XKB_MOD_NAME_LOGO);
  360. }
  361. #undef S
  362. debug("Modifier indices alt: 0x%x super: 0x%x hyper: 0x%x meta: 0x%x numlock: 0x%x shift: 0x%x capslock: 0x%x\n",
  363. xkb->altIdx, xkb->superIdx, xkb->hyperIdx, xkb->metaIdx, xkb->numLockIdx, xkb->shiftIdx, xkb->capsLockIdx);
  364. }
  365. #else
  366. #define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
  367. #define xkb_glfw_load_state(keymap, state) state = xkb_state_new(keymap);
  368. typedef struct {
  369. struct xkb_state *state;
  370. int failed;
  371. xkb_mod_mask_t used_mods;
  372. xkb_mod_mask_t shift, control, capsLock, numLock, alt, super, meta, hyper;
  373. /* Combination modifiers to try */
  374. int try_shift;
  375. xkb_keycode_t shift_keycode;
  376. } modifier_mapping_algorithm_t;
  377. /* Algorithm for mapping virtual modifiers to real modifiers:
  378. * 1. create new state
  379. * 2. for each key in keymap
  380. * a. send key down to state
  381. * b. if it affected exactly one bit in modifier map
  382. * i) get keysym
  383. * ii) if keysym matches one of the known modifiers, save it for that modifier
  384. * iii) if modifier is latched, send key up and key down to toggle again
  385. * c. send key up to reset the state
  386. * 3. if shift key found in step 2, run step 2 with all shift+key for each key
  387. * 4. if shift, control, alt and super are not all found, declare failure
  388. * 5. if failure, use static mapping from xkbcommon-names.h
  389. *
  390. * Step 3 is needed because many popular keymaps map meta to alt+shift.
  391. *
  392. * We could do better by constructing a system of linear equations, but it should not be
  393. * needed in any sane system. We could also use this algorithm with X11, but X11
  394. * provides XkbVirtualModsToReal which is guaranteed to be accurate, while this
  395. * algorithm is only a heuristic.
  396. *
  397. * We don't touch level3 or level5 modifiers.
  398. */
  399. static void modifier_mapping_algorithm( struct xkb_keymap *keymap UNUSED, xkb_keycode_t key, void *data ) {
  400. modifier_mapping_algorithm_t *algorithm = ( modifier_mapping_algorithm_t * )data;
  401. if ( algorithm->failed )
  402. return;
  403. if ( algorithm->try_shift ) {
  404. if ( key == algorithm->shift_keycode ) return;
  405. xkb_state_update_key( algorithm->state, algorithm->shift_keycode, XKB_KEY_DOWN );
  406. }
  407. enum xkb_state_component changed_type = xkb_state_update_key( algorithm->state, key, XKB_KEY_DOWN );
  408. if ( changed_type & ( XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED ) ) {
  409. xkb_mod_mask_t mods = xkb_state_serialize_mods( algorithm->state,
  410. algorithm->try_shift ? XKB_STATE_MODS_EFFECTIVE : ( XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED ) );
  411. const xkb_keysym_t *keysyms;
  412. int num_keysyms = xkb_state_key_get_syms( algorithm->state, key, &keysyms );
  413. /* We can handle exactly one keysym with exactly one bit set in the implementation
  414. * below; with a lot more gymnastics, we could set up an 8x8 linear system and solve
  415. * for each modifier in case there are some modifiers that are only present in
  416. * combination with others, but it is not worth the effort. */
  417. if ( num_keysyms == 1 && mods && ( mods & ( mods-1 ) ) == 0 ) {
  418. #define S2( k, a ) \
  419. do { \
  420. if ( keysyms[0] == XKB_KEY_##k##_L || keysyms[0] == XKB_KEY_##k##_R ) { \
  421. if ( !algorithm->a ) \
  422. algorithm->a = mods; \
  423. else if ( algorithm->a != mods ) \
  424. algorithm->failed = 1; \
  425. } \
  426. } while ( 0 )
  427. #define S1( k, a ) if ( ( keysyms[0] == XKB_KEY_##k ) && !algorithm->a ) algorithm->a = mods
  428. S2( Shift, shift );
  429. S2( Control, control );
  430. S1( Caps_Lock, capsLock );
  431. S1( Shift_Lock, numLock );
  432. S2( Alt, alt );
  433. S2( Super, super );
  434. S2( Meta, meta );
  435. S2( Hyper, hyper );
  436. #undef S1
  437. #undef S2
  438. }
  439. if ( !algorithm->shift_keycode && ( keysyms[0] == XKB_KEY_Shift_L || keysyms[0] == XKB_KEY_Shift_R ) )
  440. algorithm->shift_keycode = key;
  441. /* If this is a lock, then up and down to remove lock state*/
  442. if ( changed_type & XKB_STATE_MODS_LOCKED ) { /* What should we do for LATCHED here? */
  443. xkb_state_update_key( algorithm->state, key, XKB_KEY_UP );
  444. xkb_state_update_key( algorithm->state, key, XKB_KEY_DOWN );
  445. }
  446. }
  447. xkb_state_update_key( algorithm->state, key, XKB_KEY_UP );
  448. if ( algorithm->try_shift ) {
  449. xkb_state_update_key( algorithm->state, algorithm->shift_keycode, XKB_KEY_UP );
  450. }
  451. }
  452. static int local_modifier_mapping(_GLFWXKBData *xkb) {
  453. modifier_mapping_algorithm_t algorithm;
  454. algorithm.failed = 0;
  455. algorithm.used_mods = 0;
  456. algorithm.shift = algorithm.control = algorithm.capsLock = algorithm.numLock = algorithm.alt = algorithm.super = algorithm.meta = algorithm.hyper = 0;
  457. algorithm.try_shift = 0;
  458. algorithm.shift_keycode = 0;
  459. algorithm.state = xkb_state_new( xkb->keymap );
  460. if ( algorithm.state != NULL )
  461. {
  462. xkb_keymap_key_for_each( xkb->keymap, &modifier_mapping_algorithm, &algorithm );
  463. if ( !algorithm.shift_keycode )
  464. algorithm.failed = 1;
  465. if ( !( algorithm.shift && algorithm.control && algorithm.alt && algorithm.super && algorithm.meta && algorithm.hyper )
  466. && !algorithm.failed ) {
  467. algorithm.try_shift = 1;
  468. xkb_keymap_key_for_each( xkb->keymap, &modifier_mapping_algorithm, &algorithm );
  469. }
  470. xkb_state_unref( algorithm.state );
  471. if ( !algorithm.failed && !( algorithm.shift && algorithm.control && algorithm.alt && algorithm.super ) )
  472. algorithm.failed = 1; /* must have found at least those 4 modifiers */
  473. }
  474. if ( !algorithm.failed ) {
  475. #define S( a ) xkb->a##Idx = XKB_MOD_INVALID; xkb->a##Mask = 0
  476. S(control); S(shift); S(capsLock); S(alt); S(super); S(hyper); S(meta); S(numLock);
  477. #undef S
  478. unsigned indx, shifted, used_bits = 0;
  479. for (indx = 0, shifted = 1; indx < 32; ++indx, shifted <<= 1) {
  480. #define S( a ) if ( (xkb->a##Idx == XKB_MOD_INVALID) && !( used_bits & shifted ) && algorithm.a == shifted ) xkb->a##Idx = indx, xkb->a##Mask = shifted, used_bits |= shifted
  481. S(control); S(shift); S(capsLock); S(alt); S(super); S(hyper); S(meta); S(numLock);
  482. #undef S
  483. }
  484. }
  485. if ( algorithm.failed )
  486. debug( "Wayland modifier autodetection algorithm failed; using defaults\n" );
  487. return !algorithm.failed;
  488. }
  489. static void
  490. glfw_xkb_update_masks(_GLFWXKBData *xkb) {
  491. // Should find better solution under Wayland
  492. // See https://github.com/kovidgoyal/kitty/pull/3943 for discussion
  493. if ( getenv( "KITTY_WAYLAND_DETECT_MODIFIERS" ) == NULL || !local_modifier_mapping( xkb ) ) {
  494. #define S( a ) xkb->a##Idx = XKB_MOD_INVALID; xkb->a##Mask = 0
  495. S(hyper); S(meta);
  496. #undef S
  497. #define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx;
  498. S(control, XKB_MOD_NAME_CTRL);
  499. S(shift, XKB_MOD_NAME_SHIFT);
  500. S(capsLock, XKB_MOD_NAME_CAPS);
  501. S(numLock, XKB_MOD_NAME_NUM);
  502. S(alt, XKB_MOD_NAME_ALT);
  503. S(super, XKB_MOD_NAME_LOGO);
  504. #undef S
  505. }
  506. debug("Modifier indices alt: 0x%x super: 0x%x hyper: 0x%x meta: 0x%x numlock: 0x%x shift: 0x%x capslock: 0x%x control: 0x%x\n",
  507. xkb->altIdx, xkb->superIdx, xkb->hyperIdx, xkb->metaIdx, xkb->numLockIdx, xkb->shiftIdx, xkb->capsLockIdx, xkb->controlIdx);
  508. }
  509. #endif
  510. static void
  511. release_keyboard_data(_GLFWXKBData *xkb) {
  512. #define US(group, state, unref) if (xkb->group.state) { unref(xkb->group.state); xkb->group.state = NULL; }
  513. #define UK(keymap) if(xkb->keymap) { xkb_keymap_unref(xkb->keymap); xkb->keymap = NULL; }
  514. US(states, composeState, xkb_compose_state_unref);
  515. UK(keymap);
  516. UK(default_keymap);
  517. US(states, state, xkb_state_unref);
  518. US(states, clean_state, xkb_state_unref);
  519. US(states, default_state, xkb_state_unref);
  520. #undef US
  521. #undef UK
  522. }
  523. void
  524. glfw_xkb_release(_GLFWXKBData *xkb) {
  525. release_keyboard_data(xkb);
  526. if (xkb->context) {
  527. xkb_context_unref(xkb->context);
  528. xkb->context = NULL;
  529. }
  530. glfw_ibus_terminate(&xkb->ibus);
  531. }
  532. bool
  533. glfw_xkb_create_context(_GLFWXKBData *xkb) {
  534. xkb->context = xkb_context_new(0);
  535. if (!xkb->context)
  536. {
  537. _glfwInputError(GLFW_PLATFORM_ERROR,
  538. "Failed to initialize XKB context");
  539. return false;
  540. }
  541. #ifndef _GLFW_WAYLAND
  542. glfw_connect_to_ibus(&xkb->ibus);
  543. #endif
  544. return true;
  545. }
  546. static const char*
  547. load_keymaps(_GLFWXKBData *xkb, const char *map_str) {
  548. (void)(map_str); // not needed on X11
  549. xkb_glfw_load_keymap(xkb->keymap, map_str);
  550. if (!xkb->keymap) return "Failed to compile XKB keymap";
  551. // The system default keymap, can be overridden by the XKB_DEFAULT_RULES
  552. // env var, see
  553. // https://xkbcommon.org/doc/current/structxkb__rule__names.html
  554. static struct xkb_rule_names default_rule_names = {0};
  555. xkb->default_keymap = xkb_keymap_new_from_names(xkb->context, &default_rule_names, XKB_KEYMAP_COMPILE_NO_FLAGS);
  556. if (!xkb->default_keymap) return "Failed to create default XKB keymap";
  557. return NULL;
  558. }
  559. static const char*
  560. load_states(_GLFWXKBData *xkb) {
  561. xkb_glfw_load_state(xkb->keymap, xkb->states.state);
  562. xkb->states.clean_state = xkb_state_new(xkb->keymap);
  563. xkb->states.default_state = xkb_state_new(xkb->default_keymap);
  564. if (!xkb->states.state || !xkb->states.clean_state || !xkb->states.default_state) return "Failed to create XKB state";
  565. return NULL;
  566. }
  567. static void
  568. load_compose_tables(_GLFWXKBData *xkb) {
  569. /* Look up the preferred locale, falling back to "C" as default. */
  570. struct xkb_compose_table* compose_table = NULL;
  571. const char *locale = getenv("LC_ALL");
  572. if (!locale) locale = getenv("LC_CTYPE");
  573. if (!locale) locale = getenv("LANG");
  574. if (!locale) locale = "C";
  575. // See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903373
  576. if (strcmp(locale, "en_IN") == 0) locale = "en_IN.UTF-8";
  577. compose_table = xkb_compose_table_new_from_locale(xkb->context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
  578. if (!compose_table) {
  579. _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose table for locale %s", locale);
  580. return;
  581. }
  582. xkb->states.composeState = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
  583. if (!xkb->states.composeState) {
  584. _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose state");
  585. }
  586. xkb_compose_table_unref(compose_table);
  587. }
  588. static xkb_mod_mask_t
  589. active_unknown_modifiers(_GLFWXKBData *xkb, struct xkb_state *state) {
  590. size_t i = 0;
  591. xkb_mod_mask_t ans = 0;
  592. while (xkb->unknownModifiers[i] != XKB_MOD_INVALID) {
  593. if (xkb_state_mod_index_is_active(state, xkb->unknownModifiers[i], XKB_STATE_MODS_EFFECTIVE)) ans |= (1 << xkb->unknownModifiers[i]);
  594. i++;
  595. }
  596. return ans;
  597. }
  598. static unsigned int
  599. update_one_modifier(XKBStateGroup *group, xkb_mod_mask_t mask,
  600. xkb_mod_index_t idx, unsigned int mod) {
  601. if ( idx == XKB_MOD_INVALID )
  602. return 0;
  603. /* Optimization in the case of a single real modifier */
  604. if ( mask && ( ( mask & ( mask-1 ) ) == 0 ) )
  605. return (xkb_state_mod_index_is_active(group->state, idx, XKB_STATE_MODS_EFFECTIVE) == 1) ? mod : 0;
  606. /* Multiple real mods map to the same virtual mod */
  607. for ( unsigned indx = 0; indx < 32 && mask; ++indx, mask >>= 1 )
  608. if ( ( mask & 1 ) && xkb_state_mod_index_is_active(group->state, indx, XKB_STATE_MODS_EFFECTIVE) == 1)
  609. return mod;
  610. return 0;
  611. }
  612. static void
  613. update_modifiers(_GLFWXKBData *xkb) {
  614. XKBStateGroup *group = &xkb->states;
  615. #define S(attr, name) group->modifiers |= update_one_modifier( group, xkb->attr##Mask, xkb->attr##Idx, GLFW_MOD_##name )
  616. S(control, CONTROL); S(alt, ALT); S(shift, SHIFT); S(super, SUPER); S(hyper, HYPER); S(meta, META); S(capsLock, CAPS_LOCK); S(numLock, NUM_LOCK);
  617. #undef S
  618. xkb->states.activeUnknownModifiers = active_unknown_modifiers(xkb, xkb->states.state);
  619. }
  620. bool
  621. glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
  622. const char *err;
  623. debug("Loading new XKB keymaps\n");
  624. release_keyboard_data(xkb);
  625. err = load_keymaps(xkb, map_str);
  626. if (err) {
  627. _glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
  628. release_keyboard_data(xkb);
  629. return false;
  630. }
  631. err = load_states(xkb);
  632. if (err) {
  633. _glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
  634. release_keyboard_data(xkb);
  635. return false;
  636. }
  637. load_compose_tables(xkb);
  638. glfw_xkb_update_masks(xkb);
  639. size_t capacity = arraysz(xkb->unknownModifiers), j = 0;
  640. for (xkb_mod_index_t i = 0; i < capacity; i++) xkb->unknownModifiers[i] = XKB_MOD_INVALID;
  641. for (xkb_mod_index_t i = 0; i < xkb_keymap_num_mods(xkb->keymap) && j < capacity - 1; i++) {
  642. if (i != xkb->controlIdx && i != xkb->altIdx && i != xkb->shiftIdx && i != xkb->superIdx && i != xkb->hyperIdx && i != xkb->metaIdx && i != xkb->capsLockIdx && i != xkb->numLockIdx) xkb->unknownModifiers[j++] = i;
  643. }
  644. xkb->states.modifiers = 0;
  645. xkb->states.activeUnknownModifiers = 0;
  646. update_modifiers(xkb);
  647. return true;
  648. }
  649. void
  650. glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group) {
  651. if (!xkb->keymap) return;
  652. xkb->states.modifiers = 0;
  653. xkb_state_update_mask(xkb->states.state, depressed, latched, locked, base_group, latched_group, locked_group);
  654. // We have to update the groups in clean_state, as they change for
  655. // different keyboard layouts, see https://github.com/kovidgoyal/kitty/issues/488
  656. xkb_state_update_mask(xkb->states.clean_state, 0, 0, 0, base_group, latched_group, locked_group);
  657. update_modifiers(xkb);
  658. }
  659. bool
  660. glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode) {
  661. #ifdef _GLFW_WAYLAND
  662. keycode += 8;
  663. #endif
  664. return xkb_keymap_key_repeats(xkb->keymap, keycode);
  665. }
  666. static xkb_keysym_t
  667. compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed, char *key_text, int n) {
  668. *compose_completed = 0;
  669. if (sym == XKB_KEY_NoSymbol || !composeState) return sym;
  670. if (xkb_compose_state_feed(composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED) return sym;
  671. switch (xkb_compose_state_get_status(composeState)) {
  672. case XKB_COMPOSE_COMPOSED:
  673. xkb_compose_state_get_utf8(composeState, key_text, n);
  674. *compose_completed = 1;
  675. return xkb_compose_state_get_one_sym(composeState);
  676. case XKB_COMPOSE_COMPOSING:
  677. case XKB_COMPOSE_CANCELLED:
  678. return XKB_KEY_NoSymbol;
  679. case XKB_COMPOSE_NOTHING:
  680. default:
  681. return sym;
  682. }
  683. }
  684. const char*
  685. glfw_xkb_keysym_name(xkb_keysym_t sym) {
  686. static char name[256];
  687. name[0] = 0;
  688. xkb_keysym_get_name(sym, name, sizeof(name));
  689. return name;
  690. }
  691. int
  692. glfw_xkb_keysym_from_name(const char *name, bool case_sensitive) {
  693. return (int)xkb_keysym_from_name(name, case_sensitive ? XKB_KEYSYM_NO_FLAGS : XKB_KEYSYM_CASE_INSENSITIVE);
  694. }
  695. static const char*
  696. format_mods(unsigned int mods) {
  697. static char buf[128];
  698. char *p = buf, *s;
  699. #define pr(x) p += snprintf(p, sizeof(buf) - (p - buf) - 1, "%s", x)
  700. pr("mods: ");
  701. s = p;
  702. if (mods & GLFW_MOD_CONTROL) pr("ctrl+");
  703. if (mods & GLFW_MOD_ALT) pr("alt+");
  704. if (mods & GLFW_MOD_SHIFT) pr("shift+");
  705. if (mods & GLFW_MOD_SUPER) pr("super+");
  706. if (mods & GLFW_MOD_META) pr("meta+");
  707. if (mods & GLFW_MOD_HYPER) pr("hyper+");
  708. if (mods & GLFW_MOD_CAPS_LOCK) pr("capslock+");
  709. if (mods & GLFW_MOD_NUM_LOCK) pr("numlock+");
  710. if (p == s) pr("none");
  711. else p--;
  712. pr(" ");
  713. #undef pr
  714. return buf;
  715. }
  716. static const char*
  717. format_xkb_mods(_GLFWXKBData *xkb, const char* name, xkb_mod_mask_t mods) {
  718. static char buf[512];
  719. char *p = buf, *s;
  720. #define pr(x) { \
  721. int num_needed = -1; \
  722. ssize_t space_left = sizeof(buf) - (p - buf) - 1; \
  723. if (space_left > 0) num_needed = snprintf(p, space_left, "%s", x); \
  724. if (num_needed > 0) p += num_needed; \
  725. }
  726. pr(name); pr(": ");
  727. s = p;
  728. for (xkb_mod_index_t i = 0; i < xkb_keymap_num_mods(xkb->keymap); i++) {
  729. xkb_mod_mask_t m = 1 << i;
  730. if (m & mods) { pr(xkb_keymap_mod_get_name(xkb->keymap, i)); pr("+"); }
  731. }
  732. if (p == s) { pr("none"); }
  733. else p--;
  734. pr(" ");
  735. #undef pr
  736. return buf;
  737. }
  738. void
  739. glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, const GLFWIMEUpdateEvent *ev) {
  740. int x = 0, y = 0;
  741. switch(ev->type) {
  742. case GLFW_IME_UPDATE_FOCUS:
  743. glfw_ibus_set_focused(&xkb->ibus, ev->focused);
  744. break;
  745. case GLFW_IME_UPDATE_CURSOR_POSITION:
  746. _glfwPlatformGetWindowPos(w, &x, &y);
  747. x += ev->cursor.left; y += ev->cursor.top;
  748. glfw_ibus_set_cursor_geometry(&xkb->ibus, x, y, ev->cursor.width, ev->cursor.height);
  749. break;
  750. }
  751. }
  752. void
  753. glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) {
  754. _GLFWwindow *window = _glfwWindowForId(ev->window_id);
  755. if (failed && window && window->callbacks.keyboard) {
  756. // notify application to remove any existing pre-edit text
  757. GLFWkeyevent fake_ev = {.action = GLFW_PRESS};
  758. fake_ev.ime_state = GLFW_IME_PREEDIT_CHANGED;
  759. window->callbacks.keyboard((GLFWwindow*) window, &fake_ev);
  760. }
  761. static xkb_keycode_t last_handled_press_keycode = 0;
  762. // We filter out release events that correspond to the last press event
  763. // handled by the IME system. This won't fix the case of multiple key
  764. // presses before a release, but is better than nothing. For that case
  765. // you'd need to implement a ring buffer to store pending key presses.
  766. xkb_keycode_t prev_handled_press = last_handled_press_keycode;
  767. last_handled_press_keycode = 0;
  768. bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
  769. debug("From IBUS: native_key: 0x%x name: %s is_release: %d handled_by_ime: %d\n", ev->glfw_ev.native_key, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release, handled_by_ime);
  770. if (window && !handled_by_ime && !(is_release && ev->glfw_ev.native_key == (int) prev_handled_press)) {
  771. debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
  772. ev->glfw_ev.native_key, _glfwGetKeyName(ev->glfw_ev.native_key), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key),
  773. (ev->glfw_ev.action == GLFW_RELEASE ? "RELEASE" : (ev->glfw_ev.action == GLFW_PRESS ? "PRESS" : "REPEAT")),
  774. format_mods(ev->glfw_ev.mods), ev->glfw_ev.text
  775. );
  776. ev->glfw_ev.ime_state = GLFW_IME_NONE;
  777. _glfwInputKeyboard(window, &ev->glfw_ev);
  778. } else debug("↳ discarded\n");
  779. if (!is_release && handled_by_ime)
  780. last_handled_press_keycode = ev->glfw_ev.native_key;
  781. }
  782. void
  783. glfw_xkb_forwarded_key_from_ime(xkb_keysym_t keysym, unsigned int glfw_mods) {
  784. _GLFWwindow *w = _glfwFocusedWindow();
  785. if (w && w->callbacks.keyboard) {
  786. GLFWkeyevent fake_ev = {.action = GLFW_PRESS};
  787. fake_ev.native_key = keysym;
  788. fake_ev.key = glfw_key_for_sym(keysym);
  789. fake_ev.mods = glfw_mods;
  790. fake_ev.ime_state = GLFW_IME_NONE;
  791. w->callbacks.keyboard((GLFWwindow*) w, &fake_ev);
  792. }
  793. }
  794. static bool
  795. is_switch_layout_key(xkb_keysym_t xkb_sym) {
  796. return xkb_sym == XKB_KEY_ISO_First_Group || xkb_sym == XKB_KEY_ISO_Last_Group || xkb_sym == XKB_KEY_ISO_Next_Group || xkb_sym == XKB_KEY_ISO_Prev_Group || xkb_sym == XKB_KEY_Mode_switch;
  797. }
  798. void
  799. glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t xkb_keycode, int action) {
  800. static char key_text[64] = {0};
  801. const xkb_keysym_t *syms, *clean_syms, *default_syms;
  802. xkb_keysym_t xkb_sym, shifted_xkb_sym = XKB_KEY_NoSymbol, alternate_xkb_sym = XKB_KEY_NoSymbol;
  803. xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode;
  804. GLFWkeyevent glfw_ev = {.action = GLFW_PRESS, .native_key_id = xkb_keycode};
  805. #ifdef _GLFW_WAYLAND
  806. code_for_sym += 8;
  807. #else
  808. ibus_keycode -= 8;
  809. #endif
  810. debug("%s xkb_keycode: 0x%x ", action == GLFW_RELEASE ? "\x1b[32mRelease\x1b[m" : "\x1b[31mPress\x1b[m", xkb_keycode);
  811. XKBStateGroup *sg = &xkb->states;
  812. int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms);
  813. int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms);
  814. key_text[0] = 0;
  815. // According to the documentation of xkb_compose_state_feed it does not
  816. // support multi-sym events, so we ignore them
  817. if (num_syms != 1 || num_clean_syms != 1) {
  818. debug("num_syms: %d num_clean_syms: %d ignoring event\n", num_syms, num_clean_syms);
  819. return;
  820. }
  821. xkb_sym = clean_syms[0];
  822. shifted_xkb_sym = syms[0];
  823. debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
  824. if (action == GLFW_PRESS || action == GLFW_REPEAT) {
  825. const char *text_type = "composed_text";
  826. int compose_completed;
  827. xkb_sym = compose_symbol(sg->composeState, syms[0], &compose_completed, key_text, sizeof(key_text));
  828. if (xkb_sym == XKB_KEY_NoSymbol && !compose_completed) {
  829. debug("compose not complete, ignoring.\n");
  830. return;
  831. }
  832. debug("composed_sym: %s ", glfw_xkb_keysym_name(xkb_sym));
  833. if (xkb_sym == syms[0]) { // composed sym is the same as non-composed sym
  834. // Only use the clean_sym if no mods other than the mods we report
  835. // are active (for example if ISO_Shift_Level_* mods are active
  836. // they are not reported by GLFW so the key should be the shifted
  837. // key). See https://github.com/kovidgoyal/kitty/issues/171#issuecomment-377557053
  838. xkb_mod_mask_t consumed_unknown_mods = xkb_state_key_get_consumed_mods(sg->state, code_for_sym) & sg->activeUnknownModifiers;
  839. if (sg->activeUnknownModifiers) debug("%s", format_xkb_mods(xkb, "active_unknown_mods", sg->activeUnknownModifiers));
  840. if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); }
  841. else if (!is_switch_layout_key(xkb_sym)) xkb_sym = clean_syms[0];
  842. // xkb returns text even if alt and/or super are pressed
  843. if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER | GLFW_MOD_HYPER | GLFW_MOD_META) & sg->modifiers) == 0) {
  844. xkb_state_key_get_utf8(sg->state, code_for_sym, key_text, sizeof(key_text));
  845. }
  846. text_type = "text";
  847. }
  848. if ((1 <= key_text[0] && key_text[0] <= 31) || key_text[0] == 127) {
  849. key_text[0] = 0; // don't send text for ascii control codes
  850. }
  851. if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
  852. }
  853. if (is_switch_layout_key(xkb_sym)) { debug(" is a keyboard layout shift key, ignoring.\n"); return; }
  854. if (sg->modifiers & GLFW_MOD_NUM_LOCK && XKB_KEY_KP_Space <= xkb_sym && xkb_sym <= XKB_KEY_KP_9) {
  855. xkb_sym = xkb_state_key_get_one_sym(sg->state, code_for_sym);
  856. }
  857. int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
  858. if (num_default_syms > 0) alternate_xkb_sym = default_syms[0];
  859. int glfw_sym = glfw_key_for_sym(xkb_sym);
  860. debug(
  861. "%s%s: %d (%s) xkb_key: %d (%s)",
  862. format_mods(sg->modifiers),
  863. "glfw_key", glfw_sym, _glfwGetKeyName(glfw_sym),
  864. xkb_sym, glfw_xkb_keysym_name(xkb_sym)
  865. );
  866. bool has_shifted_key = shifted_xkb_sym != xkb_sym && shifted_xkb_sym != XKB_KEY_NoSymbol;
  867. bool has_alternate_key = alternate_xkb_sym != xkb_sym && alternate_xkb_sym != XKB_KEY_NoSymbol;
  868. if (has_shifted_key) {
  869. glfw_ev.shifted_key = glfw_key_for_sym(shifted_xkb_sym);
  870. if (glfw_ev.shifted_key) debug(" shifted_key: %d (%s)", glfw_ev.shifted_key, _glfwGetKeyName(glfw_ev.shifted_key))
  871. }
  872. if (has_alternate_key) {
  873. glfw_ev.alternate_key = glfw_key_for_sym(alternate_xkb_sym);
  874. if (glfw_ev.alternate_key) debug(" alternate_key: %d (%s)", glfw_ev.alternate_key, _glfwGetKeyName(glfw_ev.alternate_key))
  875. }
  876. debug("\n");
  877. // NOTE: On linux, the reported native key identifier is the XKB keysym value.
  878. // Do not confuse `native_key` with `xkb_keycode` (the native keycode reported for the
  879. // glfw event VS the X internal code for a key).
  880. //
  881. // We use the XKB keysym instead of the X keycode to be able to go back-and-forth between
  882. // the GLFW keysym and the XKB keysym when needed, which is not possible using the X keycode,
  883. // because of the lost information when resolving the keycode to the keysym, like consumed
  884. // mods.
  885. glfw_ev.native_key = xkb_sym;
  886. glfw_ev.action = action;
  887. glfw_ev.key = glfw_sym;
  888. glfw_ev.mods = sg->modifiers;
  889. glfw_ev.text = key_text;
  890. _GLFWIBUSKeyEvent ibus_ev;
  891. ibus_ev.glfw_ev = glfw_ev;
  892. ibus_ev.ibus_keycode = ibus_keycode;
  893. ibus_ev.window_id = window->id;
  894. ibus_ev.ibus_keysym = syms[0];
  895. if (ibus_process_key(&ibus_ev, &xkb->ibus)) {
  896. debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods));
  897. } else {
  898. _glfwInputKeyboard(window, &glfw_ev);
  899. }
  900. }