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