1 | /* |
2 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
3 | |
4 | This software is provided 'as-is', without any express or implied |
5 | warranty. In no event will the authors be held liable for any damages |
6 | arising from the use of this software. |
7 | |
8 | Permission is granted to anyone to use this software for any purpose, |
9 | including commercial applications, and to alter it and redistribute it |
10 | freely. |
11 | */ |
12 | |
13 | /* Simple program: Loop, watching keystrokes |
14 | Note that you need to call SDL_PollEvent() or SDL_WaitEvent() to |
15 | pump the event loop and catch keystrokes. |
16 | */ |
17 | |
18 | #include <stdio.h> |
19 | #include <stdlib.h> |
20 | #include <string.h> |
21 | |
22 | #ifdef __EMSCRIPTEN__ |
23 | #include <emscripten/emscripten.h> |
24 | #endif |
25 | |
26 | #include "SDL.h" |
27 | |
28 | int done; |
29 | |
30 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
31 | static void |
32 | quit(int rc) |
33 | { |
34 | SDL_Quit(); |
35 | exit(rc); |
36 | } |
37 | |
38 | static void |
39 | print_string(char **text, size_t *maxlen, const char *fmt, ...) |
40 | { |
41 | int len; |
42 | va_list ap; |
43 | |
44 | va_start(ap, fmt); |
45 | len = SDL_vsnprintf(*text, *maxlen, fmt, ap); |
46 | if (len > 0) { |
47 | *text += len; |
48 | if ( ((size_t) len) < *maxlen ) { |
49 | *maxlen -= (size_t) len; |
50 | } else { |
51 | *maxlen = 0; |
52 | } |
53 | } |
54 | va_end(ap); |
55 | } |
56 | |
57 | static void |
58 | print_modifiers(char **text, size_t *maxlen) |
59 | { |
60 | int mod; |
61 | print_string(text, maxlen, " modifiers:" ); |
62 | mod = SDL_GetModState(); |
63 | if (!mod) { |
64 | print_string(text, maxlen, " (none)" ); |
65 | return; |
66 | } |
67 | if (mod & KMOD_LSHIFT) |
68 | print_string(text, maxlen, " LSHIFT" ); |
69 | if (mod & KMOD_RSHIFT) |
70 | print_string(text, maxlen, " RSHIFT" ); |
71 | if (mod & KMOD_LCTRL) |
72 | print_string(text, maxlen, " LCTRL" ); |
73 | if (mod & KMOD_RCTRL) |
74 | print_string(text, maxlen, " RCTRL" ); |
75 | if (mod & KMOD_LALT) |
76 | print_string(text, maxlen, " LALT" ); |
77 | if (mod & KMOD_RALT) |
78 | print_string(text, maxlen, " RALT" ); |
79 | if (mod & KMOD_LGUI) |
80 | print_string(text, maxlen, " LGUI" ); |
81 | if (mod & KMOD_RGUI) |
82 | print_string(text, maxlen, " RGUI" ); |
83 | if (mod & KMOD_NUM) |
84 | print_string(text, maxlen, " NUM" ); |
85 | if (mod & KMOD_CAPS) |
86 | print_string(text, maxlen, " CAPS" ); |
87 | if (mod & KMOD_MODE) |
88 | print_string(text, maxlen, " MODE" ); |
89 | } |
90 | |
91 | static void |
92 | PrintModifierState() |
93 | { |
94 | char message[512]; |
95 | char *spot; |
96 | size_t left; |
97 | |
98 | spot = message; |
99 | left = sizeof(message); |
100 | |
101 | print_modifiers(&spot, &left); |
102 | SDL_Log("Initial state:%s\n" , message); |
103 | } |
104 | |
105 | static void |
106 | PrintKey(SDL_Keysym * sym, SDL_bool pressed, SDL_bool repeat) |
107 | { |
108 | char message[512]; |
109 | char *spot; |
110 | size_t left; |
111 | |
112 | spot = message; |
113 | left = sizeof(message); |
114 | |
115 | /* Print the keycode, name and state */ |
116 | if (sym->sym) { |
117 | print_string(&spot, &left, |
118 | "Key %s: scancode %d = %s, keycode 0x%08X = %s " , |
119 | pressed ? "pressed " : "released" , |
120 | sym->scancode, |
121 | SDL_GetScancodeName(sym->scancode), |
122 | sym->sym, SDL_GetKeyName(sym->sym)); |
123 | } else { |
124 | print_string(&spot, &left, |
125 | "Unknown Key (scancode %d = %s) %s " , |
126 | sym->scancode, |
127 | SDL_GetScancodeName(sym->scancode), |
128 | pressed ? "pressed " : "released" ); |
129 | } |
130 | print_modifiers(&spot, &left); |
131 | if (repeat) { |
132 | print_string(&spot, &left, " (repeat)" ); |
133 | } |
134 | SDL_Log("%s\n" , message); |
135 | } |
136 | |
137 | static void |
138 | PrintText(char *eventtype, char *text) |
139 | { |
140 | char *spot, expanded[1024]; |
141 | |
142 | expanded[0] = '\0'; |
143 | for ( spot = text; *spot; ++spot ) |
144 | { |
145 | size_t length = SDL_strlen(expanded); |
146 | SDL_snprintf(expanded + length, sizeof(expanded) - length, "\\x%.2x" , (unsigned char)*spot); |
147 | } |
148 | SDL_Log("%s Text (%s): \"%s%s\"\n" , eventtype, expanded, *text == '"' ? "\\" : "" , text); |
149 | } |
150 | |
151 | void |
152 | loop() |
153 | { |
154 | SDL_Event event; |
155 | /* Check for events */ |
156 | /*SDL_WaitEvent(&event); emscripten does not like waiting*/ |
157 | |
158 | while (SDL_PollEvent(&event)) { |
159 | switch (event.type) { |
160 | case SDL_KEYDOWN: |
161 | case SDL_KEYUP: |
162 | PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE); |
163 | break; |
164 | case SDL_TEXTEDITING: |
165 | PrintText("EDIT" , event.text.text); |
166 | break; |
167 | case SDL_TEXTINPUT: |
168 | PrintText("INPUT" , event.text.text); |
169 | break; |
170 | case SDL_MOUSEBUTTONDOWN: |
171 | /* Left button quits the app, other buttons toggles text input */ |
172 | if (event.button.button == SDL_BUTTON_LEFT) { |
173 | done = 1; |
174 | } else { |
175 | if (SDL_IsTextInputActive()) { |
176 | SDL_Log("Stopping text input\n" ); |
177 | SDL_StopTextInput(); |
178 | } else { |
179 | SDL_Log("Starting text input\n" ); |
180 | SDL_StartTextInput(); |
181 | } |
182 | } |
183 | break; |
184 | case SDL_QUIT: |
185 | done = 1; |
186 | break; |
187 | default: |
188 | break; |
189 | } |
190 | } |
191 | #ifdef __EMSCRIPTEN__ |
192 | if (done) { |
193 | emscripten_cancel_main_loop(); |
194 | } |
195 | #endif |
196 | } |
197 | |
198 | int |
199 | main(int argc, char *argv[]) |
200 | { |
201 | SDL_Window *window; |
202 | |
203 | /* Enable standard application logging */ |
204 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
205 | |
206 | /* Initialize SDL */ |
207 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { |
208 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n" , SDL_GetError()); |
209 | return (1); |
210 | } |
211 | |
212 | /* Set 640x480 video mode */ |
213 | window = SDL_CreateWindow("CheckKeys Test" , |
214 | SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, |
215 | 640, 480, 0); |
216 | if (!window) { |
217 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n" , |
218 | SDL_GetError()); |
219 | quit(2); |
220 | } |
221 | |
222 | #if __IPHONEOS__ |
223 | /* Creating the context creates the view, which we need to show keyboard */ |
224 | SDL_GL_CreateContext(window); |
225 | #endif |
226 | |
227 | SDL_StartTextInput(); |
228 | |
229 | /* Print initial modifier state */ |
230 | SDL_PumpEvents(); |
231 | PrintModifierState(); |
232 | |
233 | /* Watch keystrokes */ |
234 | done = 0; |
235 | |
236 | #ifdef __EMSCRIPTEN__ |
237 | emscripten_set_main_loop(loop, 0, 1); |
238 | #else |
239 | while (!done) { |
240 | loop(); |
241 | } |
242 | #endif |
243 | |
244 | SDL_Quit(); |
245 | return (0); |
246 | } |
247 | |
248 | /* vi: set ts=4 sw=4 expandtab: */ |
249 | |