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