1 //========================================================================
2 // GLFW 3.5 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
6 // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would
19 // be appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not
22 // be misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
26 //
27 //========================================================================
28
29 #include "internal.h"
30
31 #include <assert.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <float.h>
35
36
37 //////////////////////////////////////////////////////////////////////////
38 ////// GLFW event API //////
39 //////////////////////////////////////////////////////////////////////////
40
41 // Notifies shared code that a window has lost or received input focus
42 //
_glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)43 void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
44 {
45 assert(window != NULL);
46 assert(focused == GLFW_TRUE || focused == GLFW_FALSE);
47
48 if (window->callbacks.focus)
49 window->callbacks.focus((GLFWwindow*) window, focused);
50
51 if (!focused)
52 {
53 int key, button;
54
55 for (key = 0; key <= GLFW_KEY_LAST; key++)
56 {
57 if (window->keys[key] == GLFW_PRESS)
58 {
59 const int scancode = _glfw.platform.getKeyScancode(key);
60 _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
61 }
62 }
63
64 for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
65 {
66 if (window->mouseButtons[button] == GLFW_PRESS)
67 _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
68 }
69 }
70 }
71
72 // Notifies shared code that a window has moved
73 // The position is specified in content area relative screen coordinates
74 //
_glfwInputWindowPos(_GLFWwindow* window, int x, int y)75 void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
76 {
77 assert(window != NULL);
78
79 if (window->callbacks.pos)
80 window->callbacks.pos((GLFWwindow*) window, x, y);
81 }
82
83 // Notifies shared code that a window has been resized
84 // The size is specified in screen coordinates
85 //
_glfwInputWindowSize(_GLFWwindow* window, int width, int height)86 void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
87 {
88 assert(window != NULL);
89 assert(width >= 0);
90 assert(height >= 0);
91
92 if (window->callbacks.size)
93 window->callbacks.size((GLFWwindow*) window, width, height);
94 }
95
96 // Notifies shared code that a window has been iconified or restored
97 //
_glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)98 void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
99 {
100 assert(window != NULL);
101 assert(iconified == GLFW_TRUE || iconified == GLFW_FALSE);
102
103 if (window->callbacks.iconify)
104 window->callbacks.iconify((GLFWwindow*) window, iconified);
105 }
106
107 // Notifies shared code that a window has been maximized or restored
108 //
_glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)109 void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
110 {
111 assert(window != NULL);
112 assert(maximized == GLFW_TRUE || maximized == GLFW_FALSE);
113
114 if (window->callbacks.maximize)
115 window->callbacks.maximize((GLFWwindow*) window, maximized);
116 }
117
118 // Notifies shared code that a window framebuffer has been resized
119 // The size is specified in pixels
120 //
_glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)121 void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
122 {
123 assert(window != NULL);
124 assert(width >= 0);
125 assert(height >= 0);
126
127 if (window->callbacks.fbsize)
128 window->callbacks.fbsize((GLFWwindow*) window, width, height);
129 }
130
131 // Notifies shared code that a window content scale has changed
132 // The scale is specified as the ratio between the current and default DPI
133 //
_glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)134 void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
135 {
136 assert(window != NULL);
137 assert(xscale > 0.f);
138 assert(xscale < FLT_MAX);
139 assert(yscale > 0.f);
140 assert(yscale < FLT_MAX);
141
142 if (window->callbacks.scale)
143 window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
144 }
145
146 // Notifies shared code that the window contents needs updating
147 //
_glfwInputWindowDamage(_GLFWwindow* window)148 void _glfwInputWindowDamage(_GLFWwindow* window)
149 {
150 assert(window != NULL);
151
152 if (window->callbacks.refresh)
153 window->callbacks.refresh((GLFWwindow*) window);
154 }
155
156 // Notifies shared code that the user wishes to close a window
157 //
_glfwInputWindowCloseRequest(_GLFWwindow* window)158 void _glfwInputWindowCloseRequest(_GLFWwindow* window)
159 {
160 assert(window != NULL);
161
162 window->shouldClose = GLFW_TRUE;
163
164 if (window->callbacks.close)
165 window->callbacks.close((GLFWwindow*) window);
166 }
167
168 // Notifies shared code that a window has changed its desired monitor
169 //
_glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)170 void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
171 {
172 assert(window != NULL);
173 window->monitor = monitor;
174 }
175
176 //////////////////////////////////////////////////////////////////////////
177 ////// GLFW public API //////
178 //////////////////////////////////////////////////////////////////////////
179
glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share)180 GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
181 const char* title,
182 GLFWmonitor* monitor,
183 GLFWwindow* share)
184 {
185 _GLFWfbconfig fbconfig;
186 _GLFWctxconfig ctxconfig;
187 _GLFWwndconfig wndconfig;
188 _GLFWwindow* window;
189
190 assert(title != NULL);
191 assert(width >= 0);
192 assert(height >= 0);
193
194 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
195
196 if (width <= 0 || height <= 0)
197 {
198 _glfwInputError(GLFW_INVALID_VALUE,
199 "Invalid window size %ix%i",
200 width, height);
201
202 return NULL;
203 }
204
205 fbconfig = _glfw.hints.framebuffer;
206 ctxconfig = _glfw.hints.context;
207 wndconfig = _glfw.hints.window;
208
209 wndconfig.width = width;
210 wndconfig.height = height;
211 wndconfig.title = title;
212 ctxconfig.share = (_GLFWwindow*) share;
213
214 if (!_glfwIsValidContextConfig(&ctxconfig))
215 return NULL;
216
217 window = _glfw_calloc(1, sizeof(_GLFWwindow));
218 window->next = _glfw.windowListHead;
219 _glfw.windowListHead = window;
220
221 window->videoMode.width = width;
222 window->videoMode.height = height;
223 window->videoMode.redBits = fbconfig.redBits;
224 window->videoMode.greenBits = fbconfig.greenBits;
225 window->videoMode.blueBits = fbconfig.blueBits;
226 window->videoMode.refreshRate = _glfw.hints.refreshRate;
227
228 window->monitor = (_GLFWmonitor*) monitor;
229 window->resizable = wndconfig.resizable;
230 window->decorated = wndconfig.decorated;
231 window->autoIconify = wndconfig.autoIconify;
232 window->floating = wndconfig.floating;
233 window->focusOnShow = wndconfig.focusOnShow;
234 window->mousePassthrough = wndconfig.mousePassthrough;
235 window->cursorMode = GLFW_CURSOR_NORMAL;
236
237 window->doublebuffer = fbconfig.doublebuffer;
238
239 window->minwidth = GLFW_DONT_CARE;
240 window->minheight = GLFW_DONT_CARE;
241 window->maxwidth = GLFW_DONT_CARE;
242 window->maxheight = GLFW_DONT_CARE;
243 window->numer = GLFW_DONT_CARE;
244 window->denom = GLFW_DONT_CARE;
245 window->title = _glfw_strdup(title);
246
247 if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig))
248 {
249 glfwDestroyWindow((GLFWwindow*) window);
250 return NULL;
251 }
252
253 return (GLFWwindow*) window;
254 }
255
glfwDefaultWindowHints(void)256 void glfwDefaultWindowHints(void)
257 {
258 _GLFW_REQUIRE_INIT();
259
260 // The default is OpenGL with minimum version 1.0
261 memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
262 _glfw.hints.context.client = GLFW_OPENGL_API;
263 _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
264 _glfw.hints.context.major = 1;
265 _glfw.hints.context.minor = 0;
266
267 // The default is a focused, visible, resizable window with decorations
268 memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
269 _glfw.hints.window.resizable = GLFW_TRUE;
270 _glfw.hints.window.visible = GLFW_TRUE;
271 _glfw.hints.window.decorated = GLFW_TRUE;
272 _glfw.hints.window.focused = GLFW_TRUE;
273 _glfw.hints.window.autoIconify = GLFW_TRUE;
274 _glfw.hints.window.centerCursor = GLFW_TRUE;
275 _glfw.hints.window.focusOnShow = GLFW_TRUE;
276 _glfw.hints.window.xpos = GLFW_ANY_POSITION;
277 _glfw.hints.window.ypos = GLFW_ANY_POSITION;
278 _glfw.hints.window.scaleFramebuffer = GLFW_TRUE;
279
280 // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
281 // double buffered
282 memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
283 _glfw.hints.framebuffer.redBits = 8;
284 _glfw.hints.framebuffer.greenBits = 8;
285 _glfw.hints.framebuffer.blueBits = 8;
286 _glfw.hints.framebuffer.alphaBits = 8;
287 _glfw.hints.framebuffer.depthBits = 24;
288 _glfw.hints.framebuffer.stencilBits = 8;
289 _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
290
291 // The default is to select the highest available refresh rate
292 _glfw.hints.refreshRate = GLFW_DONT_CARE;
293 }
294
glfwWindowHint(int hint, int value)295 GLFWAPI void glfwWindowHint(int hint, int value)
296 {
297 _GLFW_REQUIRE_INIT();
298
299 switch (hint)
300 {
301 case GLFW_RED_BITS:
302 _glfw.hints.framebuffer.redBits = value;
303 return;
304 case GLFW_GREEN_BITS:
305 _glfw.hints.framebuffer.greenBits = value;
306 return;
307 case GLFW_BLUE_BITS:
308 _glfw.hints.framebuffer.blueBits = value;
309 return;
310 case GLFW_ALPHA_BITS:
311 _glfw.hints.framebuffer.alphaBits = value;
312 return;
313 case GLFW_DEPTH_BITS:
314 _glfw.hints.framebuffer.depthBits = value;
315 return;
316 case GLFW_STENCIL_BITS:
317 _glfw.hints.framebuffer.stencilBits = value;
318 return;
319 case GLFW_ACCUM_RED_BITS:
320 _glfw.hints.framebuffer.accumRedBits = value;
321 return;
322 case GLFW_ACCUM_GREEN_BITS:
323 _glfw.hints.framebuffer.accumGreenBits = value;
324 return;
325 case GLFW_ACCUM_BLUE_BITS:
326 _glfw.hints.framebuffer.accumBlueBits = value;
327 return;
328 case GLFW_ACCUM_ALPHA_BITS:
329 _glfw.hints.framebuffer.accumAlphaBits = value;
330 return;
331 case GLFW_AUX_BUFFERS:
332 _glfw.hints.framebuffer.auxBuffers = value;
333 return;
334 case GLFW_STEREO:
335 _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
336 return;
337 case GLFW_DOUBLEBUFFER:
338 _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
339 return;
340 case GLFW_TRANSPARENT_FRAMEBUFFER:
341 _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
342 return;
343 case GLFW_SAMPLES:
344 _glfw.hints.framebuffer.samples = value;
345 return;
346 case GLFW_SRGB_CAPABLE:
347 _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
348 return;
349 case GLFW_RESIZABLE:
350 _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
351 return;
352 case GLFW_DECORATED:
353 _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
354 return;
355 case GLFW_FOCUSED:
356 _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
357 return;
358 case GLFW_AUTO_ICONIFY:
359 _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
360 return;
361 case GLFW_FLOATING:
362 _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
363 return;
364 case GLFW_MAXIMIZED:
365 _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
366 return;
367 case GLFW_VISIBLE:
368 _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
369 return;
370 case GLFW_POSITION_X:
371 _glfw.hints.window.xpos = value;
372 return;
373 case GLFW_POSITION_Y:
374 _glfw.hints.window.ypos = value;
375 return;
376 case GLFW_WIN32_KEYBOARD_MENU:
377 _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
378 return;
379 case GLFW_WIN32_SHOWDEFAULT:
380 _glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE;
381 return;
382 case GLFW_COCOA_GRAPHICS_SWITCHING:
383 _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
384 return;
385 case GLFW_SCALE_TO_MONITOR:
386 _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
387 return;
388 case GLFW_SCALE_FRAMEBUFFER:
389 case GLFW_COCOA_RETINA_FRAMEBUFFER:
390 _glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE;
391 return;
392 case GLFW_CENTER_CURSOR:
393 _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
394 return;
395 case GLFW_FOCUS_ON_SHOW:
396 _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
397 return;
398 case GLFW_MOUSE_PASSTHROUGH:
399 _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
400 return;
401 case GLFW_CLIENT_API:
402 _glfw.hints.context.client = value;
403 return;
404 case GLFW_CONTEXT_CREATION_API:
405 _glfw.hints.context.source = value;
406 return;
407 case GLFW_CONTEXT_VERSION_MAJOR:
408 _glfw.hints.context.major = value;
409 return;
410 case GLFW_CONTEXT_VERSION_MINOR:
411 _glfw.hints.context.minor = value;
412 return;
413 case GLFW_CONTEXT_ROBUSTNESS:
414 _glfw.hints.context.robustness = value;
415 return;
416 case GLFW_OPENGL_FORWARD_COMPAT:
417 _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
418 return;
419 case GLFW_CONTEXT_DEBUG:
420 _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
421 return;
422 case GLFW_CONTEXT_NO_ERROR:
423 _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
424 return;
425 case GLFW_OPENGL_PROFILE:
426 _glfw.hints.context.profile = value;
427 return;
428 case GLFW_CONTEXT_RELEASE_BEHAVIOR:
429 _glfw.hints.context.release = value;
430 return;
431 case GLFW_REFRESH_RATE:
432 _glfw.hints.refreshRate = value;
433 return;
434 }
435
436 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
437 }
438
glfwWindowHintString(int hint, const char* value)439 GLFWAPI void glfwWindowHintString(int hint, const char* value)
440 {
441 assert(value != NULL);
442
443 _GLFW_REQUIRE_INIT();
444
445 switch (hint)
446 {
447 case GLFW_COCOA_FRAME_NAME:
448 strncpy(_glfw.hints.window.ns.frameName, value,
449 sizeof(_glfw.hints.window.ns.frameName) - 1);
450 return;
451 case GLFW_X11_CLASS_NAME:
452 strncpy(_glfw.hints.window.x11.className, value,
453 sizeof(_glfw.hints.window.x11.className) - 1);
454 return;
455 case GLFW_X11_INSTANCE_NAME:
456 strncpy(_glfw.hints.window.x11.instanceName, value,
457 sizeof(_glfw.hints.window.x11.instanceName) - 1);
458 return;
459 case GLFW_WAYLAND_APP_ID:
460 strncpy(_glfw.hints.window.wl.appId, value,
461 sizeof(_glfw.hints.window.wl.appId) - 1);
462 return;
463 }
464
465 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
466 }
467
glfwDestroyWindow(GLFWwindow* handle)468 GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
469 {
470 _GLFW_REQUIRE_INIT();
471
472 _GLFWwindow* window = (_GLFWwindow*) handle;
473
474 // Allow closing of NULL (to match the behavior of free)
475 if (window == NULL)
476 return;
477
478 // Clear all callbacks to avoid exposing a half torn-down window object
479 memset(&window->callbacks, 0, sizeof(window->callbacks));
480
481 // The window's context must not be current on another thread when the
482 // window is destroyed
483 if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
484 glfwMakeContextCurrent(NULL);
485
486 _glfw.platform.destroyWindow(window);
487
488 // Unlink window from global linked list
489 {
490 _GLFWwindow** prev = &_glfw.windowListHead;
491
492 while (*prev != window)
493 prev = &((*prev)->next);
494
495 *prev = window->next;
496 }
497
498 _glfw_free(window->title);
499 _glfw_free(window);
500 }
501
glfwWindowShouldClose(GLFWwindow* handle)502 GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
503 {
504 _GLFW_REQUIRE_INIT_OR_RETURN(0);
505
506 _GLFWwindow* window = (_GLFWwindow*) handle;
507 assert(window != NULL);
508
509 return window->shouldClose;
510 }
511
glfwSetWindowShouldClose(GLFWwindow* handle, int value)512 GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
513 {
514 _GLFW_REQUIRE_INIT();
515
516 _GLFWwindow* window = (_GLFWwindow*) handle;
517 assert(window != NULL);
518
519 window->shouldClose = value;
520 }
521
glfwGetWindowTitle(GLFWwindow* handle)522 GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle)
523 {
524 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
525
526 _GLFWwindow* window = (_GLFWwindow*) handle;
527 assert(window != NULL);
528
529 return window->title;
530 }
531
glfwSetWindowTitle(GLFWwindow* handle, const char* title)532 GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
533 {
534 assert(title != NULL);
535
536 _GLFW_REQUIRE_INIT();
537
538 _GLFWwindow* window = (_GLFWwindow*) handle;
539 assert(window != NULL);
540
541 char* prev = window->title;
542 window->title = _glfw_strdup(title);
543
544 _glfw.platform.setWindowTitle(window, title);
545 _glfw_free(prev);
546 }
547
glfwSetWindowIcon(GLFWwindow* handle, int count, const GLFWimage* images)548 GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
549 int count, const GLFWimage* images)
550 {
551 int i;
552
553 assert(count >= 0);
554 assert(count == 0 || images != NULL);
555
556 _GLFW_REQUIRE_INIT();
557
558 _GLFWwindow* window = (_GLFWwindow*) handle;
559 assert(window != NULL);
560
561 if (count < 0)
562 {
563 _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");
564 return;
565 }
566
567 for (i = 0; i < count; i++)
568 {
569 assert(images[i].pixels != NULL);
570
571 if (images[i].width <= 0 || images[i].height <= 0)
572 {
573 _glfwInputError(GLFW_INVALID_VALUE,
574 "Invalid image dimensions for window icon");
575 return;
576 }
577 }
578
579 _glfw.platform.setWindowIcon(window, count, images);
580 }
581
glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)582 GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
583 {
584 if (xpos)
585 *xpos = 0;
586 if (ypos)
587 *ypos = 0;
588
589 _GLFW_REQUIRE_INIT();
590
591 _GLFWwindow* window = (_GLFWwindow*) handle;
592 assert(window != NULL);
593
594 _glfw.platform.getWindowPos(window, xpos, ypos);
595 }
596
glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)597 GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
598 {
599 _GLFW_REQUIRE_INIT();
600
601 _GLFWwindow* window = (_GLFWwindow*) handle;
602 assert(window != NULL);
603
604 if (window->monitor)
605 return;
606
607 _glfw.platform.setWindowPos(window, xpos, ypos);
608 }
609
glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)610 GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
611 {
612 if (width)
613 *width = 0;
614 if (height)
615 *height = 0;
616
617 _GLFW_REQUIRE_INIT();
618
619 _GLFWwindow* window = (_GLFWwindow*) handle;
620 assert(window != NULL);
621
622 _glfw.platform.getWindowSize(window, width, height);
623 }
624
glfwSetWindowSize(GLFWwindow* handle, int width, int height)625 GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
626 {
627 assert(width >= 0);
628 assert(height >= 0);
629
630 _GLFW_REQUIRE_INIT();
631
632 _GLFWwindow* window = (_GLFWwindow*) handle;
633 assert(window != NULL);
634
635 window->videoMode.width = width;
636 window->videoMode.height = height;
637
638 _glfw.platform.setWindowSize(window, width, height);
639 }
640
glfwSetWindowSizeLimits(GLFWwindow* handle, int minwidth, int minheight, int maxwidth, int maxheight)641 GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
642 int minwidth, int minheight,
643 int maxwidth, int maxheight)
644 {
645 _GLFW_REQUIRE_INIT();
646
647 _GLFWwindow* window = (_GLFWwindow*) handle;
648 assert(window != NULL);
649
650 if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
651 {
652 if (minwidth < 0 || minheight < 0)
653 {
654 _glfwInputError(GLFW_INVALID_VALUE,
655 "Invalid window minimum size %ix%i",
656 minwidth, minheight);
657 return;
658 }
659 }
660
661 if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)
662 {
663 if (maxwidth < 0 || maxheight < 0 ||
664 maxwidth < minwidth || maxheight < minheight)
665 {
666 _glfwInputError(GLFW_INVALID_VALUE,
667 "Invalid window maximum size %ix%i",
668 maxwidth, maxheight);
669 return;
670 }
671 }
672
673 window->minwidth = minwidth;
674 window->minheight = minheight;
675 window->maxwidth = maxwidth;
676 window->maxheight = maxheight;
677
678 if (window->monitor || !window->resizable)
679 return;
680
681 _glfw.platform.setWindowSizeLimits(window,
682 minwidth, minheight,
683 maxwidth, maxheight);
684 }
685
glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)686 GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
687 {
688 assert(numer != 0);
689 assert(denom != 0);
690
691 _GLFW_REQUIRE_INIT();
692
693 _GLFWwindow* window = (_GLFWwindow*) handle;
694 assert(window != NULL);
695
696 if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
697 {
698 if (numer <= 0 || denom <= 0)
699 {
700 _glfwInputError(GLFW_INVALID_VALUE,
701 "Invalid window aspect ratio %i:%i",
702 numer, denom);
703 return;
704 }
705 }
706
707 window->numer = numer;
708 window->denom = denom;
709
710 if (window->monitor || !window->resizable)
711 return;
712
713 _glfw.platform.setWindowAspectRatio(window, numer, denom);
714 }
715
glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)716 GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
717 {
718 if (width)
719 *width = 0;
720 if (height)
721 *height = 0;
722
723 _GLFW_REQUIRE_INIT();
724
725 _GLFWwindow* window = (_GLFWwindow*) handle;
726 assert(window != NULL);
727
728 _glfw.platform.getFramebufferSize(window, width, height);
729 }
730
glfwGetWindowFrameSize(GLFWwindow* handle, int* left, int* top, int* right, int* bottom)731 GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
732 int* left, int* top,
733 int* right, int* bottom)
734 {
735 if (left)
736 *left = 0;
737 if (top)
738 *top = 0;
739 if (right)
740 *right = 0;
741 if (bottom)
742 *bottom = 0;
743
744 _GLFW_REQUIRE_INIT();
745
746 _GLFWwindow* window = (_GLFWwindow*) handle;
747 assert(window != NULL);
748
749 _glfw.platform.getWindowFrameSize(window, left, top, right, bottom);
750 }
751
glfwGetWindowContentScale(GLFWwindow* handle, float* xscale, float* yscale)752 GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
753 float* xscale, float* yscale)
754 {
755 if (xscale)
756 *xscale = 0.f;
757 if (yscale)
758 *yscale = 0.f;
759
760 _GLFW_REQUIRE_INIT();
761
762 _GLFWwindow* window = (_GLFWwindow*) handle;
763 assert(window != NULL);
764
765 _glfw.platform.getWindowContentScale(window, xscale, yscale);
766 }
767
glfwGetWindowOpacity(GLFWwindow* handle)768 GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
769 {
770 _GLFW_REQUIRE_INIT_OR_RETURN(0.f);
771
772 _GLFWwindow* window = (_GLFWwindow*) handle;
773 assert(window != NULL);
774
775 return _glfw.platform.getWindowOpacity(window);
776 }
777
glfwSetWindowOpacity(GLFWwindow* handle, float opacity)778 GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
779 {
780 assert(opacity == opacity);
781 assert(opacity >= 0.f);
782 assert(opacity <= 1.f);
783
784 _GLFW_REQUIRE_INIT();
785
786 _GLFWwindow* window = (_GLFWwindow*) handle;
787 assert(window != NULL);
788
789 if (opacity != opacity || opacity < 0.f || opacity > 1.f)
790 {
791 _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
792 return;
793 }
794
795 _glfw.platform.setWindowOpacity(window, opacity);
796 }
797
glfwIconifyWindow(GLFWwindow* handle)798 GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
799 {
800 _GLFW_REQUIRE_INIT();
801
802 _GLFWwindow* window = (_GLFWwindow*) handle;
803 assert(window != NULL);
804
805 _glfw.platform.iconifyWindow(window);
806 }
807
glfwRestoreWindow(GLFWwindow* handle)808 GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
809 {
810 _GLFW_REQUIRE_INIT();
811
812 _GLFWwindow* window = (_GLFWwindow*) handle;
813 assert(window != NULL);
814
815 _glfw.platform.restoreWindow(window);
816 }
817
glfwMaximizeWindow(GLFWwindow* handle)818 GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
819 {
820 _GLFW_REQUIRE_INIT();
821
822 _GLFWwindow* window = (_GLFWwindow*) handle;
823 assert(window != NULL);
824
825 if (window->monitor)
826 return;
827
828 _glfw.platform.maximizeWindow(window);
829 }
830
glfwShowWindow(GLFWwindow* handle)831 GLFWAPI void glfwShowWindow(GLFWwindow* handle)
832 {
833 _GLFW_REQUIRE_INIT();
834
835 _GLFWwindow* window = (_GLFWwindow*) handle;
836 assert(window != NULL);
837
838 if (window->monitor)
839 return;
840
841 _glfw.platform.showWindow(window);
842
843 if (window->focusOnShow)
844 _glfw.platform.focusWindow(window);
845 }
846
glfwRequestWindowAttention(GLFWwindow* handle)847 GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
848 {
849 _GLFW_REQUIRE_INIT();
850
851 _GLFWwindow* window = (_GLFWwindow*) handle;
852 assert(window != NULL);
853
854 _glfw.platform.requestWindowAttention(window);
855 }
856
glfwHideWindow(GLFWwindow* handle)857 GLFWAPI void glfwHideWindow(GLFWwindow* handle)
858 {
859 _GLFW_REQUIRE_INIT();
860
861 _GLFWwindow* window = (_GLFWwindow*) handle;
862 assert(window != NULL);
863
864 if (window->monitor)
865 return;
866
867 _glfw.platform.hideWindow(window);
868 }
869
glfwFocusWindow(GLFWwindow* handle)870 GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
871 {
872 _GLFW_REQUIRE_INIT();
873
874 _GLFWwindow* window = (_GLFWwindow*) handle;
875 assert(window != NULL);
876
877 _glfw.platform.focusWindow(window);
878 }
879
glfwGetWindowAttrib(GLFWwindow* handle, int attrib)880 GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
881 {
882 _GLFW_REQUIRE_INIT_OR_RETURN(0);
883
884 _GLFWwindow* window = (_GLFWwindow*) handle;
885 assert(window != NULL);
886
887 switch (attrib)
888 {
889 case GLFW_FOCUSED:
890 return _glfw.platform.windowFocused(window);
891 case GLFW_ICONIFIED:
892 return _glfw.platform.windowIconified(window);
893 case GLFW_VISIBLE:
894 return _glfw.platform.windowVisible(window);
895 case GLFW_MAXIMIZED:
896 return _glfw.platform.windowMaximized(window);
897 case GLFW_HOVERED:
898 return _glfw.platform.windowHovered(window);
899 case GLFW_FOCUS_ON_SHOW:
900 return window->focusOnShow;
901 case GLFW_MOUSE_PASSTHROUGH:
902 return window->mousePassthrough;
903 case GLFW_TRANSPARENT_FRAMEBUFFER:
904 return _glfw.platform.framebufferTransparent(window);
905 case GLFW_RESIZABLE:
906 return window->resizable;
907 case GLFW_DECORATED:
908 return window->decorated;
909 case GLFW_FLOATING:
910 return window->floating;
911 case GLFW_AUTO_ICONIFY:
912 return window->autoIconify;
913 case GLFW_DOUBLEBUFFER:
914 return window->doublebuffer;
915 case GLFW_CLIENT_API:
916 return window->context.client;
917 case GLFW_CONTEXT_CREATION_API:
918 return window->context.source;
919 case GLFW_CONTEXT_VERSION_MAJOR:
920 return window->context.major;
921 case GLFW_CONTEXT_VERSION_MINOR:
922 return window->context.minor;
923 case GLFW_CONTEXT_REVISION:
924 return window->context.revision;
925 case GLFW_CONTEXT_ROBUSTNESS:
926 return window->context.robustness;
927 case GLFW_OPENGL_FORWARD_COMPAT:
928 return window->context.forward;
929 case GLFW_CONTEXT_DEBUG:
930 return window->context.debug;
931 case GLFW_OPENGL_PROFILE:
932 return window->context.profile;
933 case GLFW_CONTEXT_RELEASE_BEHAVIOR:
934 return window->context.release;
935 case GLFW_CONTEXT_NO_ERROR:
936 return window->context.noerror;
937 }
938
939 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
940 return 0;
941 }
942
glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)943 GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
944 {
945 _GLFW_REQUIRE_INIT();
946
947 _GLFWwindow* window = (_GLFWwindow*) handle;
948 assert(window != NULL);
949
950 value = value ? GLFW_TRUE : GLFW_FALSE;
951
952 switch (attrib)
953 {
954 case GLFW_AUTO_ICONIFY:
955 window->autoIconify = value;
956 return;
957
958 case GLFW_RESIZABLE:
959 window->resizable = value;
960 if (!window->monitor)
961 _glfw.platform.setWindowResizable(window, value);
962 return;
963
964 case GLFW_DECORATED:
965 window->decorated = value;
966 if (!window->monitor)
967 _glfw.platform.setWindowDecorated(window, value);
968 return;
969
970 case GLFW_FLOATING:
971 window->floating = value;
972 if (!window->monitor)
973 _glfw.platform.setWindowFloating(window, value);
974 return;
975
976 case GLFW_FOCUS_ON_SHOW:
977 window->focusOnShow = value;
978 return;
979
980 case GLFW_MOUSE_PASSTHROUGH:
981 window->mousePassthrough = value;
982 _glfw.platform.setWindowMousePassthrough(window, value);
983 return;
984 }
985
986 _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
987 }
988
glfwGetWindowMonitor(GLFWwindow* handle)989 GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
990 {
991 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
992
993 _GLFWwindow* window = (_GLFWwindow*) handle;
994 assert(window != NULL);
995
996 return (GLFWmonitor*) window->monitor;
997 }
998
glfwSetWindowMonitor(GLFWwindow* wh, GLFWmonitor* mh, int xpos, int ypos, int width, int height, int refreshRate)999 GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
1000 GLFWmonitor* mh,
1001 int xpos, int ypos,
1002 int width, int height,
1003 int refreshRate)
1004 {
1005 assert(width >= 0);
1006 assert(height >= 0);
1007
1008 _GLFW_REQUIRE_INIT();
1009
1010 _GLFWwindow* window = (_GLFWwindow*) wh;
1011 _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
1012 assert(window != NULL);
1013
1014 if (width <= 0 || height <= 0)
1015 {
1016 _glfwInputError(GLFW_INVALID_VALUE,
1017 "Invalid window size %ix%i",
1018 width, height);
1019 return;
1020 }
1021
1022 if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
1023 {
1024 _glfwInputError(GLFW_INVALID_VALUE,
1025 "Invalid refresh rate %i",
1026 refreshRate);
1027 return;
1028 }
1029
1030 window->videoMode.width = width;
1031 window->videoMode.height = height;
1032 window->videoMode.refreshRate = refreshRate;
1033
1034 _glfw.platform.setWindowMonitor(window, monitor,
1035 xpos, ypos, width, height,
1036 refreshRate);
1037 }
1038
glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)1039 GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
1040 {
1041 _GLFW_REQUIRE_INIT();
1042
1043 _GLFWwindow* window = (_GLFWwindow*) handle;
1044 assert(window != NULL);
1045
1046 window->userPointer = pointer;
1047 }
1048
glfwGetWindowUserPointer(GLFWwindow* handle)1049 GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
1050 {
1051 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1052
1053 _GLFWwindow* window = (_GLFWwindow*) handle;
1054 assert(window != NULL);
1055
1056 return window->userPointer;
1057 }
1058
glfwSetWindowPosCallback(GLFWwindow* handle, GLFWwindowposfun cbfun)1059 GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
1060 GLFWwindowposfun cbfun)
1061 {
1062 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1063
1064 _GLFWwindow* window = (_GLFWwindow*) handle;
1065 assert(window != NULL);
1066
1067 _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun);
1068 return cbfun;
1069 }
1070
glfwSetWindowSizeCallback(GLFWwindow* handle, GLFWwindowsizefun cbfun)1071 GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
1072 GLFWwindowsizefun cbfun)
1073 {
1074 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1075
1076 _GLFWwindow* window = (_GLFWwindow*) handle;
1077 assert(window != NULL);
1078
1079 _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun);
1080 return cbfun;
1081 }
1082
glfwSetWindowCloseCallback(GLFWwindow* handle, GLFWwindowclosefun cbfun)1083 GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
1084 GLFWwindowclosefun cbfun)
1085 {
1086 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1087
1088 _GLFWwindow* window = (_GLFWwindow*) handle;
1089 assert(window != NULL);
1090
1091 _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun);
1092 return cbfun;
1093 }
1094
glfwSetWindowRefreshCallback(GLFWwindow* handle, GLFWwindowrefreshfun cbfun)1095 GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
1096 GLFWwindowrefreshfun cbfun)
1097 {
1098 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1099
1100 _GLFWwindow* window = (_GLFWwindow*) handle;
1101 assert(window != NULL);
1102
1103 _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun);
1104 return cbfun;
1105 }
1106
glfwSetWindowFocusCallback(GLFWwindow* handle, GLFWwindowfocusfun cbfun)1107 GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
1108 GLFWwindowfocusfun cbfun)
1109 {
1110 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1111
1112 _GLFWwindow* window = (_GLFWwindow*) handle;
1113 assert(window != NULL);
1114
1115 _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun);
1116 return cbfun;
1117 }
1118
glfwSetWindowIconifyCallback(GLFWwindow* handle, GLFWwindowiconifyfun cbfun)1119 GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
1120 GLFWwindowiconifyfun cbfun)
1121 {
1122 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1123
1124 _GLFWwindow* window = (_GLFWwindow*) handle;
1125 assert(window != NULL);
1126
1127 _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun);
1128 return cbfun;
1129 }
1130
glfwSetWindowMaximizeCallback(GLFWwindow* handle, GLFWwindowmaximizefun cbfun)1131 GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
1132 GLFWwindowmaximizefun cbfun)
1133 {
1134 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1135
1136 _GLFWwindow* window = (_GLFWwindow*) handle;
1137 assert(window != NULL);
1138
1139 _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun);
1140 return cbfun;
1141 }
1142
glfwSetFramebufferSizeCallback(GLFWwindow* handle, GLFWframebuffersizefun cbfun)1143 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
1144 GLFWframebuffersizefun cbfun)
1145 {
1146 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1147
1148 _GLFWwindow* window = (_GLFWwindow*) handle;
1149 assert(window != NULL);
1150
1151 _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun);
1152 return cbfun;
1153 }
1154
glfwSetWindowContentScaleCallback(GLFWwindow* handle, GLFWwindowcontentscalefun cbfun)1155 GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
1156 GLFWwindowcontentscalefun cbfun)
1157 {
1158 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1159
1160 _GLFWwindow* window = (_GLFWwindow*) handle;
1161 assert(window != NULL);
1162
1163 _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun);
1164 return cbfun;
1165 }
1166
glfwPollEvents(void)1167 GLFWAPI void glfwPollEvents(void)
1168 {
1169 _GLFW_REQUIRE_INIT();
1170 _glfw.platform.pollEvents();
1171 }
1172
glfwWaitEvents(void)1173 GLFWAPI void glfwWaitEvents(void)
1174 {
1175 _GLFW_REQUIRE_INIT();
1176 _glfw.platform.waitEvents();
1177 }
1178
glfwWaitEventsTimeout(double timeout)1179 GLFWAPI void glfwWaitEventsTimeout(double timeout)
1180 {
1181 _GLFW_REQUIRE_INIT();
1182 assert(timeout == timeout);
1183 assert(timeout >= 0.0);
1184 assert(timeout <= DBL_MAX);
1185
1186 if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
1187 {
1188 _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
1189 return;
1190 }
1191
1192 _glfw.platform.waitEventsTimeout(timeout);
1193 }
1194
glfwPostEmptyEvent(void)1195 GLFWAPI void glfwPostEmptyEvent(void)
1196 {
1197 _GLFW_REQUIRE_INIT();
1198 _glfw.platform.postEmptyEvent();
1199 }
1200
1201