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