checkkeys.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any damages
  5. arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it
  8. freely.
  9. */
  10. /* Simple program: Loop, watching keystrokes
  11. Note that you need to call SDL_PollEvent() or SDL_WaitEvent() to
  12. pump the event loop and catch keystrokes.
  13. */
  14. #include <SDL3/SDL.h>
  15. #include <SDL3/SDL_main.h>
  16. #include <SDL3/SDL_test.h>
  17. #ifdef SDL_PLATFORM_EMSCRIPTEN
  18. #include <emscripten/emscripten.h>
  19. #endif
  20. static SDLTest_CommonState *state;
  21. static SDLTest_TextWindow *textwin;
  22. static int done;
  23. static void print_string(char **text, size_t *maxlen, const char *fmt, ...)
  24. {
  25. int len;
  26. va_list ap;
  27. va_start(ap, fmt);
  28. len = SDL_vsnprintf(*text, *maxlen, fmt, ap);
  29. if (len > 0) {
  30. *text += len;
  31. if (((size_t)len) < *maxlen) {
  32. *maxlen -= (size_t)len;
  33. } else {
  34. *maxlen = 0;
  35. }
  36. }
  37. va_end(ap);
  38. }
  39. static void print_modifiers(char **text, size_t *maxlen, SDL_Keymod mod)
  40. {
  41. print_string(text, maxlen, " modifiers:");
  42. if (mod == SDL_KMOD_NONE) {
  43. print_string(text, maxlen, " (none)");
  44. return;
  45. }
  46. if ((mod & SDL_KMOD_SHIFT) == SDL_KMOD_SHIFT) {
  47. print_string(text, maxlen, " SHIFT");
  48. } else {
  49. if (mod & SDL_KMOD_LSHIFT) {
  50. print_string(text, maxlen, " LSHIFT");
  51. }
  52. if (mod & SDL_KMOD_RSHIFT) {
  53. print_string(text, maxlen, " RSHIFT");
  54. }
  55. }
  56. if ((mod & SDL_KMOD_CTRL) == SDL_KMOD_CTRL) {
  57. print_string(text, maxlen, " CTRL");
  58. } else {
  59. if (mod & SDL_KMOD_LCTRL) {
  60. print_string(text, maxlen, " LCTRL");
  61. }
  62. if (mod & SDL_KMOD_RCTRL) {
  63. print_string(text, maxlen, " RCTRL");
  64. }
  65. }
  66. if ((mod & SDL_KMOD_ALT) == SDL_KMOD_ALT) {
  67. print_string(text, maxlen, " ALT");
  68. } else {
  69. if (mod & SDL_KMOD_LALT) {
  70. print_string(text, maxlen, " LALT");
  71. }
  72. if (mod & SDL_KMOD_RALT) {
  73. print_string(text, maxlen, " RALT");
  74. }
  75. }
  76. if ((mod & SDL_KMOD_GUI) == SDL_KMOD_GUI) {
  77. print_string(text, maxlen, " GUI");
  78. } else {
  79. if (mod & SDL_KMOD_LGUI) {
  80. print_string(text, maxlen, " LGUI");
  81. }
  82. if (mod & SDL_KMOD_RGUI) {
  83. print_string(text, maxlen, " RGUI");
  84. }
  85. }
  86. if (mod & SDL_KMOD_NUM) {
  87. print_string(text, maxlen, " NUM");
  88. }
  89. if (mod & SDL_KMOD_CAPS) {
  90. print_string(text, maxlen, " CAPS");
  91. }
  92. if (mod & SDL_KMOD_MODE) {
  93. print_string(text, maxlen, " MODE");
  94. }
  95. if (mod & SDL_KMOD_SCROLL) {
  96. print_string(text, maxlen, " SCROLL");
  97. }
  98. }
  99. static void PrintKeymap(void)
  100. {
  101. SDL_Keymod mods[] = {
  102. SDL_KMOD_NONE,
  103. SDL_KMOD_SHIFT,
  104. SDL_KMOD_CAPS,
  105. (SDL_KMOD_SHIFT | SDL_KMOD_CAPS),
  106. SDL_KMOD_ALT,
  107. (SDL_KMOD_ALT | SDL_KMOD_SHIFT),
  108. (SDL_KMOD_ALT | SDL_KMOD_CAPS),
  109. (SDL_KMOD_ALT | SDL_KMOD_SHIFT | SDL_KMOD_CAPS),
  110. SDL_KMOD_MODE,
  111. (SDL_KMOD_MODE | SDL_KMOD_SHIFT),
  112. (SDL_KMOD_MODE | SDL_KMOD_CAPS),
  113. (SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS)
  114. };
  115. int i, m;
  116. SDL_Log("Differences from the default keymap:\n");
  117. for (m = 0; m < SDL_arraysize(mods); ++m) {
  118. for (i = 0; i < SDL_NUM_SCANCODES; ++i) {
  119. SDL_Keycode key = SDL_GetKeyFromScancode((SDL_Scancode)i, mods[m]);
  120. SDL_Keycode default_key = SDL_GetDefaultKeyFromScancode((SDL_Scancode)i, mods[m]);
  121. if (key != default_key) {
  122. char message[512];
  123. char *spot;
  124. size_t left;
  125. spot = message;
  126. left = sizeof(message);
  127. print_string(&spot, &left, "Scancode %s", SDL_GetScancodeName((SDL_Scancode)i));
  128. print_modifiers(&spot, &left, mods[m]);
  129. print_string(&spot, &left, ": %s 0x%x (default: %s 0x%x)", SDL_GetKeyName(key), key, SDL_GetKeyName(default_key), default_key);
  130. SDL_Log("%s", message);
  131. }
  132. }
  133. }
  134. }
  135. static void PrintModifierState(void)
  136. {
  137. char message[512];
  138. char *spot;
  139. size_t left;
  140. spot = message;
  141. left = sizeof(message);
  142. print_modifiers(&spot, &left, SDL_GetModState());
  143. SDL_Log("Initial state:%s\n", message);
  144. }
  145. static void PrintKey(SDL_KeyboardEvent *event)
  146. {
  147. char message[512];
  148. char *spot;
  149. size_t left;
  150. spot = message;
  151. left = sizeof(message);
  152. /* Print the keycode, name and state */
  153. if (event->key) {
  154. print_string(&spot, &left,
  155. "Key %s: raw 0x%.2x, scancode %d = %s, keycode 0x%08X = %s ",
  156. event->state ? "pressed " : "released",
  157. event->raw,
  158. event->scancode,
  159. event->scancode == SDL_SCANCODE_UNKNOWN ? "UNKNOWN" : SDL_GetScancodeName(event->scancode),
  160. event->key, SDL_GetKeyName(event->key));
  161. } else {
  162. print_string(&spot, &left,
  163. "Unknown Key (raw 0x%.2x, scancode %d = %s) %s ",
  164. event->raw,
  165. event->scancode,
  166. event->scancode == SDL_SCANCODE_UNKNOWN ? "UNKNOWN" : SDL_GetScancodeName(event->scancode),
  167. event->state ? "pressed " : "released");
  168. }
  169. print_modifiers(&spot, &left, event->mod);
  170. if (event->repeat) {
  171. print_string(&spot, &left, " (repeat)");
  172. }
  173. SDL_Log("%s\n", message);
  174. }
  175. static void PrintText(const char *eventtype, const char *text)
  176. {
  177. const char *spot;
  178. char expanded[1024];
  179. expanded[0] = '\0';
  180. for (spot = text; *spot; ++spot) {
  181. size_t length = SDL_strlen(expanded);
  182. (void)SDL_snprintf(expanded + length, sizeof(expanded) - length, "\\x%.2x", (unsigned char)*spot);
  183. }
  184. SDL_Log("%s Text (%s): \"%s%s\"\n", eventtype, expanded, *text == '"' ? "\\" : "", text);
  185. }
  186. static void CountKeysDown(void)
  187. {
  188. int i, count = 0, max_keys = 0;
  189. const Uint8 *keystate = SDL_GetKeyboardState(&max_keys);
  190. for (i = 0; i < max_keys; ++i) {
  191. if (keystate[i]) {
  192. ++count;
  193. }
  194. }
  195. SDL_Log("Keys down: %d\n", count);
  196. }
  197. static void loop(void)
  198. {
  199. SDL_Event event;
  200. int i;
  201. /* Check for events */
  202. /*SDL_WaitEvent(&event); emscripten does not like waiting*/
  203. while (SDL_PollEvent(&event)) {
  204. switch (event.type) {
  205. case SDL_EVENT_KEY_DOWN:
  206. case SDL_EVENT_KEY_UP:
  207. PrintKey(&event.key);
  208. if (event.type == SDL_EVENT_KEY_DOWN) {
  209. switch (event.key.key) {
  210. case SDLK_BACKSPACE:
  211. SDLTest_TextWindowAddText(textwin, "\b");
  212. break;
  213. case SDLK_RETURN:
  214. SDLTest_TextWindowAddText(textwin, "\n");
  215. break;
  216. default:
  217. break;
  218. }
  219. }
  220. CountKeysDown();
  221. break;
  222. case SDL_EVENT_TEXT_EDITING:
  223. PrintText("EDIT", event.edit.text);
  224. break;
  225. case SDL_EVENT_TEXT_INPUT:
  226. PrintText("INPUT", event.text.text);
  227. SDLTest_TextWindowAddText(textwin, "%s", event.text.text);
  228. break;
  229. case SDL_EVENT_FINGER_DOWN:
  230. if (SDL_TextInputActive()) {
  231. SDL_Log("Stopping text input\n");
  232. SDL_StopTextInput();
  233. } else {
  234. SDL_Log("Starting text input\n");
  235. SDL_StartTextInput();
  236. }
  237. break;
  238. case SDL_EVENT_MOUSE_BUTTON_DOWN:
  239. /* Left button quits the app, other buttons toggles text input */
  240. if (event.button.button == SDL_BUTTON_LEFT) {
  241. done = 1;
  242. } else {
  243. if (SDL_TextInputActive()) {
  244. SDL_Log("Stopping text input\n");
  245. SDL_StopTextInput();
  246. } else {
  247. SDL_Log("Starting text input\n");
  248. SDL_StartTextInput();
  249. }
  250. }
  251. break;
  252. case SDL_EVENT_KEYMAP_CHANGED:
  253. SDL_Log("Keymap changed!\n");
  254. PrintKeymap();
  255. break;
  256. case SDL_EVENT_QUIT:
  257. done = 1;
  258. break;
  259. default:
  260. break;
  261. }
  262. }
  263. for (i = 0; i < state->num_windows; i++) {
  264. SDL_SetRenderDrawColor(state->renderers[i], 0, 0, 0, 255);
  265. SDL_RenderClear(state->renderers[i]);
  266. SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255);
  267. SDLTest_TextWindowDisplay(textwin, state->renderers[i]);
  268. SDL_RenderPresent(state->renderers[i]);
  269. }
  270. /* Slow down framerate */
  271. SDL_Delay(100);
  272. #ifdef SDL_PLATFORM_EMSCRIPTEN
  273. if (done) {
  274. emscripten_cancel_main_loop();
  275. }
  276. #endif
  277. }
  278. int main(int argc, char *argv[])
  279. {
  280. int w, h;
  281. SDL_Rect input_rect;
  282. SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1");
  283. /* Initialize test framework */
  284. state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
  285. if (!state) {
  286. return 1;
  287. }
  288. state->window_title = "CheckKeys Test";
  289. /* Enable standard application logging */
  290. SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  291. /* Parse commandline */
  292. if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
  293. return 1;
  294. }
  295. /* Disable mouse emulation */
  296. SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
  297. /* Initialize SDL */
  298. if (!SDLTest_CommonInit(state)) {
  299. SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
  300. return 1;
  301. }
  302. SDL_GetWindowSize(state->windows[0], &w, &h);
  303. textwin = SDLTest_TextWindowCreate(0.f, 0.f, (float)w, (float)h);
  304. #ifdef SDL_PLATFORM_IOS
  305. {
  306. int i;
  307. /* Creating the context creates the view, which we need to show keyboard */
  308. for (i = 0; i < state->num_windows; i++) {
  309. SDL_GL_CreateContext(state->windows[i]);
  310. }
  311. }
  312. #endif
  313. /* Enable showing IME candidates */
  314. SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
  315. /* Set an input rectangle in the center of the window */
  316. input_rect.x = w / 4;
  317. input_rect.y = h / 4;
  318. input_rect.w = w / 2;
  319. input_rect.h = h / 2;
  320. SDL_SetTextInputRect(&input_rect);
  321. SDL_StartTextInput();
  322. /* Print initial state */
  323. SDL_PumpEvents();
  324. PrintKeymap();
  325. PrintModifierState();
  326. /* Watch keystrokes */
  327. done = 0;
  328. #ifdef SDL_PLATFORM_EMSCRIPTEN
  329. emscripten_set_main_loop(loop, 0, 1);
  330. #else
  331. while (!done) {
  332. loop();
  333. }
  334. #endif
  335. SDLTest_TextWindowDestroy(textwin);
  336. SDLTest_CleanupTextDrawing();
  337. SDLTest_CommonQuit(state);
  338. return 0;
  339. }