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