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