1 //========================================================================
2 // Event linter (event spewer)
3 // Copyright (c) Camilla Löwy <elmindreda@glfw.org>
4 //
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any damages
7 // arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it
11 // freely, subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented; you must not
14 // claim that you wrote the original software. If you use this software
15 // in a product, an acknowledgment in the product documentation would
16 // be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such, and must not
19 // be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source
22 // distribution.
23 //
24 //========================================================================
25 //
26 // This test hooks every available callback and outputs their arguments
27 //
28 // Log messages go to stdout, error messages to stderr
29 //
30 // Every event also gets a (sequential) number to aid discussion of logs
31 //
32 //========================================================================
33
34 #include <glad/gl.h>
35 #define GLFW_INCLUDE_NONE
36 #include <GLFW/glfw3.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <locale.h>
43
44 #include "getopt.h"
45
46 // Event index
47 static unsigned int counter = 0;
48
49 typedef struct
50 {
51 GLFWwindow* window;
52 int number;
53 int closeable;
54 } Slot;
55
usage(void)56 static void usage(void)
57 {
58 printf("Usage: events [-f] [-h] [-n WINDOWS]\n");
59 printf("Options:\n");
60 printf(" -f use full screen\n");
61 printf(" -h show this help\n");
62 printf(" -n the number of windows to create\n");
63 }
64
get_key_name(int key)65 static const char* get_key_name(int key)
66 {
67 switch (key)
68 {
69 // Printable keys
70 case GLFW_KEY_A: return "A";
71 case GLFW_KEY_B: return "B";
72 case GLFW_KEY_C: return "C";
73 case GLFW_KEY_D: return "D";
74 case GLFW_KEY_E: return "E";
75 case GLFW_KEY_F: return "F";
76 case GLFW_KEY_G: return "G";
77 case GLFW_KEY_H: return "H";
78 case GLFW_KEY_I: return "I";
79 case GLFW_KEY_J: return "J";
80 case GLFW_KEY_K: return "K";
81 case GLFW_KEY_L: return "L";
82 case GLFW_KEY_M: return "M";
83 case GLFW_KEY_N: return "N";
84 case GLFW_KEY_O: return "O";
85 case GLFW_KEY_P: return "P";
86 case GLFW_KEY_Q: return "Q";
87 case GLFW_KEY_R: return "R";
88 case GLFW_KEY_S: return "S";
89 case GLFW_KEY_T: return "T";
90 case GLFW_KEY_U: return "U";
91 case GLFW_KEY_V: return "V";
92 case GLFW_KEY_W: return "W";
93 case GLFW_KEY_X: return "X";
94 case GLFW_KEY_Y: return "Y";
95 case GLFW_KEY_Z: return "Z";
96 case GLFW_KEY_1: return "1";
97 case GLFW_KEY_2: return "2";
98 case GLFW_KEY_3: return "3";
99 case GLFW_KEY_4: return "4";
100 case GLFW_KEY_5: return "5";
101 case GLFW_KEY_6: return "6";
102 case GLFW_KEY_7: return "7";
103 case GLFW_KEY_8: return "8";
104 case GLFW_KEY_9: return "9";
105 case GLFW_KEY_0: return "0";
106 case GLFW_KEY_SPACE: return "SPACE";
107 case GLFW_KEY_MINUS: return "MINUS";
108 case GLFW_KEY_EQUAL: return "EQUAL";
109 case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET";
110 case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET";
111 case GLFW_KEY_BACKSLASH: return "BACKSLASH";
112 case GLFW_KEY_SEMICOLON: return "SEMICOLON";
113 case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
114 case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT";
115 case GLFW_KEY_COMMA: return "COMMA";
116 case GLFW_KEY_PERIOD: return "PERIOD";
117 case GLFW_KEY_SLASH: return "SLASH";
118 case GLFW_KEY_WORLD_1: return "WORLD 1";
119 case GLFW_KEY_WORLD_2: return "WORLD 2";
120
121 // Function keys
122 case GLFW_KEY_ESCAPE: return "ESCAPE";
123 case GLFW_KEY_F1: return "F1";
124 case GLFW_KEY_F2: return "F2";
125 case GLFW_KEY_F3: return "F3";
126 case GLFW_KEY_F4: return "F4";
127 case GLFW_KEY_F5: return "F5";
128 case GLFW_KEY_F6: return "F6";
129 case GLFW_KEY_F7: return "F7";
130 case GLFW_KEY_F8: return "F8";
131 case GLFW_KEY_F9: return "F9";
132 case GLFW_KEY_F10: return "F10";
133 case GLFW_KEY_F11: return "F11";
134 case GLFW_KEY_F12: return "F12";
135 case GLFW_KEY_F13: return "F13";
136 case GLFW_KEY_F14: return "F14";
137 case GLFW_KEY_F15: return "F15";
138 case GLFW_KEY_F16: return "F16";
139 case GLFW_KEY_F17: return "F17";
140 case GLFW_KEY_F18: return "F18";
141 case GLFW_KEY_F19: return "F19";
142 case GLFW_KEY_F20: return "F20";
143 case GLFW_KEY_F21: return "F21";
144 case GLFW_KEY_F22: return "F22";
145 case GLFW_KEY_F23: return "F23";
146 case GLFW_KEY_F24: return "F24";
147 case GLFW_KEY_F25: return "F25";
148 case GLFW_KEY_UP: return "UP";
149 case GLFW_KEY_DOWN: return "DOWN";
150 case GLFW_KEY_LEFT: return "LEFT";
151 case GLFW_KEY_RIGHT: return "RIGHT";
152 case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
153 case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
154 case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
155 case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
156 case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
157 case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
158 case GLFW_KEY_TAB: return "TAB";
159 case GLFW_KEY_ENTER: return "ENTER";
160 case GLFW_KEY_BACKSPACE: return "BACKSPACE";
161 case GLFW_KEY_INSERT: return "INSERT";
162 case GLFW_KEY_DELETE: return "DELETE";
163 case GLFW_KEY_PAGE_UP: return "PAGE UP";
164 case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
165 case GLFW_KEY_HOME: return "HOME";
166 case GLFW_KEY_END: return "END";
167 case GLFW_KEY_KP_0: return "KEYPAD 0";
168 case GLFW_KEY_KP_1: return "KEYPAD 1";
169 case GLFW_KEY_KP_2: return "KEYPAD 2";
170 case GLFW_KEY_KP_3: return "KEYPAD 3";
171 case GLFW_KEY_KP_4: return "KEYPAD 4";
172 case GLFW_KEY_KP_5: return "KEYPAD 5";
173 case GLFW_KEY_KP_6: return "KEYPAD 6";
174 case GLFW_KEY_KP_7: return "KEYPAD 7";
175 case GLFW_KEY_KP_8: return "KEYPAD 8";
176 case GLFW_KEY_KP_9: return "KEYPAD 9";
177 case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
178 case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTIPLY";
179 case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
180 case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
181 case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
182 case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
183 case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
184 case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
185 case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
186 case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
187 case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
188 case GLFW_KEY_PAUSE: return "PAUSE";
189 case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
190 case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
191 case GLFW_KEY_MENU: return "MENU";
192
193 default: return "UNKNOWN";
194 }
195 }
196
get_action_name(int action)197 static const char* get_action_name(int action)
198 {
199 switch (action)
200 {
201 case GLFW_PRESS:
202 return "pressed";
203 case GLFW_RELEASE:
204 return "released";
205 case GLFW_REPEAT:
206 return "repeated";
207 }
208
209 return "caused unknown action";
210 }
211
get_button_name(int button)212 static const char* get_button_name(int button)
213 {
214 switch (button)
215 {
216 case GLFW_MOUSE_BUTTON_LEFT:
217 return "left";
218 case GLFW_MOUSE_BUTTON_RIGHT:
219 return "right";
220 case GLFW_MOUSE_BUTTON_MIDDLE:
221 return "middle";
222 default:
223 {
224 static char name[16];
225 snprintf(name, sizeof(name), "%i", button);
226 return name;
227 }
228 }
229 }
230
get_mods_name(int mods)231 static const char* get_mods_name(int mods)
232 {
233 static char name[512];
234
235 if (mods == 0)
236 return " no mods";
237
238 name[0] = '\0';
239
240 if (mods & GLFW_MOD_SHIFT)
241 strcat(name, " shift");
242 if (mods & GLFW_MOD_CONTROL)
243 strcat(name, " control");
244 if (mods & GLFW_MOD_ALT)
245 strcat(name, " alt");
246 if (mods & GLFW_MOD_SUPER)
247 strcat(name, " super");
248 if (mods & GLFW_MOD_CAPS_LOCK)
249 strcat(name, " capslock-on");
250 if (mods & GLFW_MOD_NUM_LOCK)
251 strcat(name, " numlock-on");
252
253 return name;
254 }
255
encode_utf8(char * s,unsigned int ch)256 static size_t encode_utf8(char* s, unsigned int ch)
257 {
258 size_t count = 0;
259
260 if (ch < 0x80)
261 s[count++] = (char) ch;
262 else if (ch < 0x800)
263 {
264 s[count++] = (ch >> 6) | 0xc0;
265 s[count++] = (ch & 0x3f) | 0x80;
266 }
267 else if (ch < 0x10000)
268 {
269 s[count++] = (ch >> 12) | 0xe0;
270 s[count++] = ((ch >> 6) & 0x3f) | 0x80;
271 s[count++] = (ch & 0x3f) | 0x80;
272 }
273 else if (ch < 0x110000)
274 {
275 s[count++] = (ch >> 18) | 0xf0;
276 s[count++] = ((ch >> 12) & 0x3f) | 0x80;
277 s[count++] = ((ch >> 6) & 0x3f) | 0x80;
278 s[count++] = (ch & 0x3f) | 0x80;
279 }
280
281 return count;
282 }
283
error_callback(int error,const char * description)284 static void error_callback(int error, const char* description)
285 {
286 fprintf(stderr, "Error: %s\n", description);
287 }
288
window_pos_callback(GLFWwindow * window,int x,int y)289 static void window_pos_callback(GLFWwindow* window, int x, int y)
290 {
291 Slot* slot = glfwGetWindowUserPointer(window);
292 printf("%08x to %i at %0.3f: Window position: %i %i\n",
293 counter++, slot->number, glfwGetTime(), x, y);
294 }
295
window_size_callback(GLFWwindow * window,int width,int height)296 static void window_size_callback(GLFWwindow* window, int width, int height)
297 {
298 Slot* slot = glfwGetWindowUserPointer(window);
299 printf("%08x to %i at %0.3f: Window size: %i %i\n",
300 counter++, slot->number, glfwGetTime(), width, height);
301 }
302
framebuffer_size_callback(GLFWwindow * window,int width,int height)303 static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
304 {
305 Slot* slot = glfwGetWindowUserPointer(window);
306 printf("%08x to %i at %0.3f: Framebuffer size: %i %i\n",
307 counter++, slot->number, glfwGetTime(), width, height);
308 }
309
window_content_scale_callback(GLFWwindow * window,float xscale,float yscale)310 static void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
311 {
312 Slot* slot = glfwGetWindowUserPointer(window);
313 printf("%08x to %i at %0.3f: Window content scale: %0.3f %0.3f\n",
314 counter++, slot->number, glfwGetTime(), xscale, yscale);
315 }
316
window_close_callback(GLFWwindow * window)317 static void window_close_callback(GLFWwindow* window)
318 {
319 Slot* slot = glfwGetWindowUserPointer(window);
320 printf("%08x to %i at %0.3f: Window close\n",
321 counter++, slot->number, glfwGetTime());
322
323 glfwSetWindowShouldClose(window, slot->closeable);
324 }
325
window_refresh_callback(GLFWwindow * window)326 static void window_refresh_callback(GLFWwindow* window)
327 {
328 Slot* slot = glfwGetWindowUserPointer(window);
329 printf("%08x to %i at %0.3f: Window refresh\n",
330 counter++, slot->number, glfwGetTime());
331
332 glfwMakeContextCurrent(window);
333 glClear(GL_COLOR_BUFFER_BIT);
334 glfwSwapBuffers(window);
335 }
336
window_focus_callback(GLFWwindow * window,int focused)337 static void window_focus_callback(GLFWwindow* window, int focused)
338 {
339 Slot* slot = glfwGetWindowUserPointer(window);
340 printf("%08x to %i at %0.3f: Window %s\n",
341 counter++, slot->number, glfwGetTime(),
342 focused ? "focused" : "defocused");
343 }
344
window_iconify_callback(GLFWwindow * window,int iconified)345 static void window_iconify_callback(GLFWwindow* window, int iconified)
346 {
347 Slot* slot = glfwGetWindowUserPointer(window);
348 printf("%08x to %i at %0.3f: Window was %s\n",
349 counter++, slot->number, glfwGetTime(),
350 iconified ? "iconified" : "uniconified");
351 }
352
window_maximize_callback(GLFWwindow * window,int maximized)353 static void window_maximize_callback(GLFWwindow* window, int maximized)
354 {
355 Slot* slot = glfwGetWindowUserPointer(window);
356 printf("%08x to %i at %0.3f: Window was %s\n",
357 counter++, slot->number, glfwGetTime(),
358 maximized ? "maximized" : "unmaximized");
359 }
360
mouse_button_callback(GLFWwindow * window,int button,int action,int mods)361 static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
362 {
363 Slot* slot = glfwGetWindowUserPointer(window);
364 printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n",
365 counter++, slot->number, glfwGetTime(), button,
366 get_button_name(button),
367 get_mods_name(mods),
368 get_action_name(action));
369 }
370
cursor_position_callback(GLFWwindow * window,double x,double y)371 static void cursor_position_callback(GLFWwindow* window, double x, double y)
372 {
373 Slot* slot = glfwGetWindowUserPointer(window);
374 printf("%08x to %i at %0.3f: Cursor position: %f %f\n",
375 counter++, slot->number, glfwGetTime(), x, y);
376 }
377
cursor_enter_callback(GLFWwindow * window,int entered)378 static void cursor_enter_callback(GLFWwindow* window, int entered)
379 {
380 Slot* slot = glfwGetWindowUserPointer(window);
381 printf("%08x to %i at %0.3f: Cursor %s window\n",
382 counter++, slot->number, glfwGetTime(),
383 entered ? "entered" : "left");
384 }
385
scroll_callback(GLFWwindow * window,double x,double y)386 static void scroll_callback(GLFWwindow* window, double x, double y)
387 {
388 Slot* slot = glfwGetWindowUserPointer(window);
389 printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f\n",
390 counter++, slot->number, glfwGetTime(), x, y);
391 }
392
key_callback(GLFWwindow * window,int key,int scancode,int action,int mods)393 static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
394 {
395 Slot* slot = glfwGetWindowUserPointer(window);
396 const char* name = glfwGetKeyName(key, scancode);
397
398 if (name)
399 {
400 printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n",
401 counter++, slot->number, glfwGetTime(), key, scancode,
402 get_key_name(key),
403 name,
404 get_mods_name(mods),
405 get_action_name(action));
406 }
407 else
408 {
409 printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n",
410 counter++, slot->number, glfwGetTime(), key, scancode,
411 get_key_name(key),
412 get_mods_name(mods),
413 get_action_name(action));
414 }
415
416 if (action != GLFW_PRESS)
417 return;
418
419 switch (key)
420 {
421 case GLFW_KEY_C:
422 {
423 slot->closeable = !slot->closeable;
424
425 printf("(( closing %s ))\n", slot->closeable ? "enabled" : "disabled");
426 break;
427 }
428
429 case GLFW_KEY_L:
430 {
431 const int state = glfwGetInputMode(window, GLFW_LOCK_KEY_MODS);
432 glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, !state);
433
434 printf("(( lock key mods %s ))\n", !state ? "enabled" : "disabled");
435 break;
436 }
437 }
438 }
439
char_callback(GLFWwindow * window,unsigned int codepoint)440 static void char_callback(GLFWwindow* window, unsigned int codepoint)
441 {
442 Slot* slot = glfwGetWindowUserPointer(window);
443 char string[5] = "";
444
445 encode_utf8(string, codepoint);
446 printf("%08x to %i at %0.3f: Character 0x%08x (%s) input\n",
447 counter++, slot->number, glfwGetTime(), codepoint, string);
448 }
449
drop_callback(GLFWwindow * window,int count,const char * paths[])450 static void drop_callback(GLFWwindow* window, int count, const char* paths[])
451 {
452 int i;
453 Slot* slot = glfwGetWindowUserPointer(window);
454
455 printf("%08x to %i at %0.3f: Drop input\n",
456 counter++, slot->number, glfwGetTime());
457
458 for (i = 0; i < count; i++)
459 printf(" %i: \"%s\"\n", i, paths[i]);
460 }
461
monitor_callback(GLFWmonitor * monitor,int event)462 static void monitor_callback(GLFWmonitor* monitor, int event)
463 {
464 if (event == GLFW_CONNECTED)
465 {
466 int x, y, widthMM, heightMM;
467 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
468
469 glfwGetMonitorPos(monitor, &x, &y);
470 glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
471
472 printf("%08x at %0.3f: Monitor %s (%ix%i at %ix%i, %ix%i mm) was connected\n",
473 counter++,
474 glfwGetTime(),
475 glfwGetMonitorName(monitor),
476 mode->width, mode->height,
477 x, y,
478 widthMM, heightMM);
479 }
480 else if (event == GLFW_DISCONNECTED)
481 {
482 printf("%08x at %0.3f: Monitor %s was disconnected\n",
483 counter++,
484 glfwGetTime(),
485 glfwGetMonitorName(monitor));
486 }
487 }
488
joystick_callback(int jid,int event)489 static void joystick_callback(int jid, int event)
490 {
491 if (event == GLFW_CONNECTED)
492 {
493 int axisCount, buttonCount, hatCount;
494
495 glfwGetJoystickAxes(jid, &axisCount);
496 glfwGetJoystickButtons(jid, &buttonCount);
497 glfwGetJoystickHats(jid, &hatCount);
498
499 printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes, %i buttons, and %i hats\n",
500 counter++, glfwGetTime(),
501 jid,
502 glfwGetJoystickName(jid),
503 axisCount,
504 buttonCount,
505 hatCount);
506 }
507 else
508 {
509 printf("%08x at %0.3f: Joystick %i was disconnected\n",
510 counter++, glfwGetTime(), jid);
511 }
512 }
513
main(int argc,char ** argv)514 int main(int argc, char** argv)
515 {
516 Slot* slots;
517 GLFWmonitor* monitor = NULL;
518 int ch, i, width, height, count = 1;
519
520 glfwSetErrorCallback(error_callback);
521
522 if (!glfwInit())
523 exit(EXIT_FAILURE);
524
525 printf("Library initialized\n");
526
527 glfwSetMonitorCallback(monitor_callback);
528 glfwSetJoystickCallback(joystick_callback);
529
530 while ((ch = getopt(argc, argv, "hfn:")) != -1)
531 {
532 switch (ch)
533 {
534 case 'h':
535 usage();
536 exit(EXIT_SUCCESS);
537
538 case 'f':
539 monitor = glfwGetPrimaryMonitor();
540 break;
541
542 case 'n':
543 count = (int) strtoul(optarg, NULL, 10);
544 break;
545
546 default:
547 usage();
548 exit(EXIT_FAILURE);
549 }
550 }
551
552 if (monitor)
553 {
554 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
555
556 glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
557 glfwWindowHint(GLFW_RED_BITS, mode->redBits);
558 glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
559 glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
560
561 width = mode->width;
562 height = mode->height;
563 }
564 else
565 {
566 width = 640;
567 height = 480;
568 }
569
570 slots = calloc(count, sizeof(Slot));
571
572 for (i = 0; i < count; i++)
573 {
574 char title[128];
575
576 slots[i].closeable = GLFW_TRUE;
577 slots[i].number = i + 1;
578
579 snprintf(title, sizeof(title), "Event Linter (Window %i)", slots[i].number);
580
581 if (monitor)
582 {
583 printf("Creating full screen window %i (%ix%i on %s)\n",
584 slots[i].number,
585 width, height,
586 glfwGetMonitorName(monitor));
587 }
588 else
589 {
590 printf("Creating windowed mode window %i (%ix%i)\n",
591 slots[i].number,
592 width, height);
593 }
594
595 slots[i].window = glfwCreateWindow(width, height, title, monitor, NULL);
596 if (!slots[i].window)
597 {
598 free(slots);
599 glfwTerminate();
600 exit(EXIT_FAILURE);
601 }
602
603 glfwSetWindowUserPointer(slots[i].window, slots + i);
604
605 glfwSetWindowPosCallback(slots[i].window, window_pos_callback);
606 glfwSetWindowSizeCallback(slots[i].window, window_size_callback);
607 glfwSetFramebufferSizeCallback(slots[i].window, framebuffer_size_callback);
608 glfwSetWindowContentScaleCallback(slots[i].window, window_content_scale_callback);
609 glfwSetWindowCloseCallback(slots[i].window, window_close_callback);
610 glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
611 glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);
612 glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback);
613 glfwSetWindowMaximizeCallback(slots[i].window, window_maximize_callback);
614 glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback);
615 glfwSetCursorPosCallback(slots[i].window, cursor_position_callback);
616 glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback);
617 glfwSetScrollCallback(slots[i].window, scroll_callback);
618 glfwSetKeyCallback(slots[i].window, key_callback);
619 glfwSetCharCallback(slots[i].window, char_callback);
620 glfwSetDropCallback(slots[i].window, drop_callback);
621
622 glfwMakeContextCurrent(slots[i].window);
623 gladLoadGL(glfwGetProcAddress);
624 glfwSwapInterval(1);
625 }
626
627 printf("Main loop starting\n");
628
629 for (;;)
630 {
631 for (i = 0; i < count; i++)
632 {
633 if (glfwWindowShouldClose(slots[i].window))
634 break;
635 }
636
637 if (i < count)
638 break;
639
640 glfwWaitEvents();
641
642 // Workaround for an issue with msvcrt and mintty
643 fflush(stdout);
644 }
645
646 free(slots);
647 glfwTerminate();
648 exit(EXIT_SUCCESS);
649 }
650
651