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