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