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