]> git.sesse.net Git - pistorm/blobdiff - raylib_pi4_test/external/glfw/src/window.c
[MEGA-WIP] Raylib-based RTG output
[pistorm] / raylib_pi4_test / external / glfw / src / window.c
diff --git a/raylib_pi4_test/external/glfw/src/window.c b/raylib_pi4_test/external/glfw/src/window.c
new file mode 100644 (file)
index 0000000..efcb412
--- /dev/null
@@ -0,0 +1,1122 @@
+//========================================================================
+// GLFW 3.4 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//    claim that you wrote the original software. If you use this software
+//    in a product, an acknowledgment in the product documentation would
+//    be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+//    be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+//    distribution.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code that a window has lost or received input focus
+//
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
+{
+    if (window->callbacks.focus)
+        window->callbacks.focus((GLFWwindow*) window, focused);
+
+    if (!focused)
+    {
+        int key, button;
+
+        for (key = 0;  key <= GLFW_KEY_LAST;  key++)
+        {
+            if (window->keys[key] == GLFW_PRESS)
+            {
+                const int scancode = _glfwPlatformGetKeyScancode(key);
+                _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
+            }
+        }
+
+        for (button = 0;  button <= GLFW_MOUSE_BUTTON_LAST;  button++)
+        {
+            if (window->mouseButtons[button] == GLFW_PRESS)
+                _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
+        }
+    }
+}
+
+// Notifies shared code that a window has moved
+// The position is specified in content area relative screen coordinates
+//
+void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
+{
+    if (window->callbacks.pos)
+        window->callbacks.pos((GLFWwindow*) window, x, y);
+}
+
+// Notifies shared code that a window has been resized
+// The size is specified in screen coordinates
+//
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
+{
+    if (window->callbacks.size)
+        window->callbacks.size((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window has been iconified or restored
+//
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
+{
+    if (window->callbacks.iconify)
+        window->callbacks.iconify((GLFWwindow*) window, iconified);
+}
+
+// Notifies shared code that a window has been maximized or restored
+//
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
+{
+    if (window->callbacks.maximize)
+        window->callbacks.maximize((GLFWwindow*) window, maximized);
+}
+
+// Notifies shared code that a window framebuffer has been resized
+// The size is specified in pixels
+//
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
+{
+    if (window->callbacks.fbsize)
+        window->callbacks.fbsize((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window content scale has changed
+// The scale is specified as the ratio between the current and default DPI
+//
+void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
+{
+    if (window->callbacks.scale)
+        window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
+}
+
+// Notifies shared code that the window contents needs updating
+//
+void _glfwInputWindowDamage(_GLFWwindow* window)
+{
+    if (window->callbacks.refresh)
+        window->callbacks.refresh((GLFWwindow*) window);
+}
+
+// Notifies shared code that the user wishes to close a window
+//
+void _glfwInputWindowCloseRequest(_GLFWwindow* window)
+{
+    window->shouldClose = GLFW_TRUE;
+
+    if (window->callbacks.close)
+        window->callbacks.close((GLFWwindow*) window);
+}
+
+// Notifies shared code that a window has changed its desired monitor
+//
+void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
+{
+    window->monitor = monitor;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
+                                     const char* title,
+                                     GLFWmonitor* monitor,
+                                     GLFWwindow* share)
+{
+    _GLFWfbconfig fbconfig;
+    _GLFWctxconfig ctxconfig;
+    _GLFWwndconfig wndconfig;
+    _GLFWwindow* window;
+
+    assert(title != NULL);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (width <= 0 || height <= 0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE,
+                        "Invalid window size %ix%i",
+                        width, height);
+
+        return NULL;
+    }
+
+    fbconfig  = _glfw.hints.framebuffer;
+    ctxconfig = _glfw.hints.context;
+    wndconfig = _glfw.hints.window;
+
+    wndconfig.width   = width;
+    wndconfig.height  = height;
+    wndconfig.title   = title;
+    ctxconfig.share   = (_GLFWwindow*) share;
+
+    if (!_glfwIsValidContextConfig(&ctxconfig))
+        return NULL;
+
+    window = calloc(1, sizeof(_GLFWwindow));
+    window->next = _glfw.windowListHead;
+    _glfw.windowListHead = window;
+
+    window->videoMode.width       = width;
+    window->videoMode.height      = height;
+    window->videoMode.redBits     = fbconfig.redBits;
+    window->videoMode.greenBits   = fbconfig.greenBits;
+    window->videoMode.blueBits    = fbconfig.blueBits;
+    window->videoMode.refreshRate = _glfw.hints.refreshRate;
+
+    window->monitor          = (_GLFWmonitor*) monitor;
+    window->resizable        = wndconfig.resizable;
+    window->decorated        = wndconfig.decorated;
+    window->autoIconify      = wndconfig.autoIconify;
+    window->floating         = wndconfig.floating;
+    window->focusOnShow      = wndconfig.focusOnShow;
+    window->mousePassthrough = wndconfig.mousePassthrough;
+    window->cursorMode       = GLFW_CURSOR_NORMAL;
+
+    window->minwidth    = GLFW_DONT_CARE;
+    window->minheight   = GLFW_DONT_CARE;
+    window->maxwidth    = GLFW_DONT_CARE;
+    window->maxheight   = GLFW_DONT_CARE;
+    window->numer       = GLFW_DONT_CARE;
+    window->denom       = GLFW_DONT_CARE;
+
+    // Open the actual window and create its context
+    if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
+    {
+        glfwDestroyWindow((GLFWwindow*) window);
+        return NULL;
+    }
+
+    if (ctxconfig.client != GLFW_NO_API)
+    {
+        if (!_glfwRefreshContextAttribs(window, &ctxconfig))
+        {
+            glfwDestroyWindow((GLFWwindow*) window);
+            return NULL;
+        }
+    }
+
+    if (wndconfig.mousePassthrough)
+        _glfwPlatformSetWindowMousePassthrough(window, GLFW_TRUE);
+
+    if (window->monitor)
+    {
+        if (wndconfig.centerCursor)
+            _glfwCenterCursorInContentArea(window);
+    }
+    else
+    {
+        if (wndconfig.visible)
+        {
+            _glfwPlatformShowWindow(window);
+            if (wndconfig.focused)
+                _glfwPlatformFocusWindow(window);
+        }
+    }
+
+    return (GLFWwindow*) window;
+}
+
+void glfwDefaultWindowHints(void)
+{
+    _GLFW_REQUIRE_INIT();
+
+    // The default is OpenGL with minimum version 1.0
+    memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
+    _glfw.hints.context.client = GLFW_OPENGL_API;
+    _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
+    _glfw.hints.context.major  = 1;
+    _glfw.hints.context.minor  = 0;
+
+    // The default is a focused, visible, resizable window with decorations
+    memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
+    _glfw.hints.window.resizable    = GLFW_TRUE;
+    _glfw.hints.window.visible      = GLFW_TRUE;
+    _glfw.hints.window.decorated    = GLFW_TRUE;
+    _glfw.hints.window.focused      = GLFW_TRUE;
+    _glfw.hints.window.autoIconify  = GLFW_TRUE;
+    _glfw.hints.window.centerCursor = GLFW_TRUE;
+    _glfw.hints.window.focusOnShow  = GLFW_TRUE;
+
+    // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
+    // double buffered
+    memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
+    _glfw.hints.framebuffer.redBits      = 8;
+    _glfw.hints.framebuffer.greenBits    = 8;
+    _glfw.hints.framebuffer.blueBits     = 8;
+    _glfw.hints.framebuffer.alphaBits    = 8;
+    _glfw.hints.framebuffer.depthBits    = 24;
+    _glfw.hints.framebuffer.stencilBits  = 8;
+    _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
+
+    // The default is to select the highest available refresh rate
+    _glfw.hints.refreshRate = GLFW_DONT_CARE;
+
+    // The default is to use full Retina resolution framebuffers
+    _glfw.hints.window.ns.retina = GLFW_TRUE;
+}
+
+GLFWAPI void glfwWindowHint(int hint, int value)
+{
+    _GLFW_REQUIRE_INIT();
+
+    switch (hint)
+    {
+        case GLFW_RED_BITS:
+            _glfw.hints.framebuffer.redBits = value;
+            return;
+        case GLFW_GREEN_BITS:
+            _glfw.hints.framebuffer.greenBits = value;
+            return;
+        case GLFW_BLUE_BITS:
+            _glfw.hints.framebuffer.blueBits = value;
+            return;
+        case GLFW_ALPHA_BITS:
+            _glfw.hints.framebuffer.alphaBits = value;
+            return;
+        case GLFW_DEPTH_BITS:
+            _glfw.hints.framebuffer.depthBits = value;
+            return;
+        case GLFW_STENCIL_BITS:
+            _glfw.hints.framebuffer.stencilBits = value;
+            return;
+        case GLFW_ACCUM_RED_BITS:
+            _glfw.hints.framebuffer.accumRedBits = value;
+            return;
+        case GLFW_ACCUM_GREEN_BITS:
+            _glfw.hints.framebuffer.accumGreenBits = value;
+            return;
+        case GLFW_ACCUM_BLUE_BITS:
+            _glfw.hints.framebuffer.accumBlueBits = value;
+            return;
+        case GLFW_ACCUM_ALPHA_BITS:
+            _glfw.hints.framebuffer.accumAlphaBits = value;
+            return;
+        case GLFW_AUX_BUFFERS:
+            _glfw.hints.framebuffer.auxBuffers = value;
+            return;
+        case GLFW_STEREO:
+            _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_DOUBLEBUFFER:
+            _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_TRANSPARENT_FRAMEBUFFER:
+            _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_SAMPLES:
+            _glfw.hints.framebuffer.samples = value;
+            return;
+        case GLFW_SRGB_CAPABLE:
+            _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_RESIZABLE:
+            _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_DECORATED:
+            _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FOCUSED:
+            _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_AUTO_ICONIFY:
+            _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FLOATING:
+            _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_MAXIMIZED:
+            _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_VISIBLE:
+            _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_COCOA_RETINA_FRAMEBUFFER:
+            _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_WIN32_KEYBOARD_MENU:
+            _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_COCOA_GRAPHICS_SWITCHING:
+            _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_SCALE_TO_MONITOR:
+            _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CENTER_CURSOR:
+            _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FOCUS_ON_SHOW:
+            _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_MOUSE_PASSTHROUGH:
+            _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CLIENT_API:
+            _glfw.hints.context.client = value;
+            return;
+        case GLFW_CONTEXT_CREATION_API:
+            _glfw.hints.context.source = value;
+            return;
+        case GLFW_CONTEXT_VERSION_MAJOR:
+            _glfw.hints.context.major = value;
+            return;
+        case GLFW_CONTEXT_VERSION_MINOR:
+            _glfw.hints.context.minor = value;
+            return;
+        case GLFW_CONTEXT_ROBUSTNESS:
+            _glfw.hints.context.robustness = value;
+            return;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CONTEXT_DEBUG:
+            _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CONTEXT_NO_ERROR:
+            _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_OPENGL_PROFILE:
+            _glfw.hints.context.profile = value;
+            return;
+        case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+            _glfw.hints.context.release = value;
+            return;
+        case GLFW_REFRESH_RATE:
+            _glfw.hints.refreshRate = value;
+            return;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
+}
+
+GLFWAPI void glfwWindowHintString(int hint, const char* value)
+{
+    assert(value != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    switch (hint)
+    {
+        case GLFW_COCOA_FRAME_NAME:
+            strncpy(_glfw.hints.window.ns.frameName, value,
+                    sizeof(_glfw.hints.window.ns.frameName) - 1);
+            return;
+        case GLFW_X11_CLASS_NAME:
+            strncpy(_glfw.hints.window.x11.className, value,
+                    sizeof(_glfw.hints.window.x11.className) - 1);
+            return;
+        case GLFW_X11_INSTANCE_NAME:
+            strncpy(_glfw.hints.window.x11.instanceName, value,
+                    sizeof(_glfw.hints.window.x11.instanceName) - 1);
+            return;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
+}
+
+GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+
+    _GLFW_REQUIRE_INIT();
+
+    // Allow closing of NULL (to match the behavior of free)
+    if (window == NULL)
+        return;
+
+    // Clear all callbacks to avoid exposing a half torn-down window object
+    memset(&window->callbacks, 0, sizeof(window->callbacks));
+
+    // The window's context must not be current on another thread when the
+    // window is destroyed
+    if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
+        glfwMakeContextCurrent(NULL);
+
+    _glfwPlatformDestroyWindow(window);
+
+    // Unlink window from global linked list
+    {
+        _GLFWwindow** prev = &_glfw.windowListHead;
+
+        while (*prev != window)
+            prev = &((*prev)->next);
+
+        *prev = window->next;
+    }
+
+    free(window);
+}
+
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(0);
+    return window->shouldClose;
+}
+
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    window->shouldClose = value;
+}
+
+GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(title != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformSetWindowTitle(window, title);
+}
+
+GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
+                               int count, const GLFWimage* images)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(count >= 0);
+    assert(count == 0 || images != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformSetWindowIcon(window, count, images);
+}
+
+GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (xpos)
+        *xpos = 0;
+    if (ypos)
+        *ypos = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformSetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (width)
+        *width = 0;
+    if (height)
+        *height = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowSize(window, width, height);
+}
+
+GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _GLFW_REQUIRE_INIT();
+
+    window->videoMode.width  = width;
+    window->videoMode.height = height;
+
+    _glfwPlatformSetWindowSize(window, width, height);
+}
+
+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
+                                     int minwidth, int minheight,
+                                     int maxwidth, int maxheight)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
+    {
+        if (minwidth < 0 || minheight < 0)
+        {
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid window minimum size %ix%i",
+                            minwidth, minheight);
+            return;
+        }
+    }
+
+    if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)
+    {
+        if (maxwidth < 0 || maxheight < 0 ||
+            maxwidth < minwidth || maxheight < minheight)
+        {
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid window maximum size %ix%i",
+                            maxwidth, maxheight);
+            return;
+        }
+    }
+
+    window->minwidth  = minwidth;
+    window->minheight = minheight;
+    window->maxwidth  = maxwidth;
+    window->maxheight = maxheight;
+
+    if (window->monitor || !window->resizable)
+        return;
+
+    _glfwPlatformSetWindowSizeLimits(window,
+                                     minwidth, minheight,
+                                     maxwidth, maxheight);
+}
+
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(numer != 0);
+    assert(denom != 0);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
+    {
+        if (numer <= 0 || denom <= 0)
+        {
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid window aspect ratio %i:%i",
+                            numer, denom);
+            return;
+        }
+    }
+
+    window->numer = numer;
+    window->denom = denom;
+
+    if (window->monitor || !window->resizable)
+        return;
+
+    _glfwPlatformSetWindowAspectRatio(window, numer, denom);
+}
+
+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (width)
+        *width = 0;
+    if (height)
+        *height = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetFramebufferSize(window, width, height);
+}
+
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
+                                    int* left, int* top,
+                                    int* right, int* bottom)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (left)
+        *left = 0;
+    if (top)
+        *top = 0;
+    if (right)
+        *right = 0;
+    if (bottom)
+        *bottom = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
+}
+
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
+                                       float* xscale, float* yscale)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (xscale)
+        *xscale = 0.f;
+    if (yscale)
+        *yscale = 0.f;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowContentScale(window, xscale, yscale);
+}
+
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(1.f);
+    return _glfwPlatformGetWindowOpacity(window);
+}
+
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(opacity == opacity);
+    assert(opacity >= 0.f);
+    assert(opacity <= 1.f);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (opacity != opacity || opacity < 0.f || opacity > 1.f)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
+        return;
+    }
+
+    _glfwPlatformSetWindowOpacity(window, opacity);
+}
+
+GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformIconifyWindow(window);
+}
+
+GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformRestoreWindow(window);
+}
+
+GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformMaximizeWindow(window);
+}
+
+GLFWAPI void glfwShowWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformShowWindow(window);
+
+    if (window->focusOnShow)
+        _glfwPlatformFocusWindow(window);
+}
+
+GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformRequestWindowAttention(window);
+}
+
+GLFWAPI void glfwHideWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformHideWindow(window);
+}
+
+GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformFocusWindow(window);
+}
+
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+    switch (attrib)
+    {
+        case GLFW_FOCUSED:
+            return _glfwPlatformWindowFocused(window);
+        case GLFW_ICONIFIED:
+            return _glfwPlatformWindowIconified(window);
+        case GLFW_VISIBLE:
+            return _glfwPlatformWindowVisible(window);
+        case GLFW_MAXIMIZED:
+            return _glfwPlatformWindowMaximized(window);
+        case GLFW_HOVERED:
+            return _glfwPlatformWindowHovered(window);
+        case GLFW_FOCUS_ON_SHOW:
+            return window->focusOnShow;
+        case GLFW_MOUSE_PASSTHROUGH:
+            return window->mousePassthrough;
+        case GLFW_TRANSPARENT_FRAMEBUFFER:
+            return _glfwPlatformFramebufferTransparent(window);
+        case GLFW_RESIZABLE:
+            return window->resizable;
+        case GLFW_DECORATED:
+            return window->decorated;
+        case GLFW_FLOATING:
+            return window->floating;
+        case GLFW_AUTO_ICONIFY:
+            return window->autoIconify;
+        case GLFW_CLIENT_API:
+            return window->context.client;
+        case GLFW_CONTEXT_CREATION_API:
+            return window->context.source;
+        case GLFW_CONTEXT_VERSION_MAJOR:
+            return window->context.major;
+        case GLFW_CONTEXT_VERSION_MINOR:
+            return window->context.minor;
+        case GLFW_CONTEXT_REVISION:
+            return window->context.revision;
+        case GLFW_CONTEXT_ROBUSTNESS:
+            return window->context.robustness;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            return window->context.forward;
+        case GLFW_CONTEXT_DEBUG:
+            return window->context.debug;
+        case GLFW_OPENGL_PROFILE:
+            return window->context.profile;
+        case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+            return window->context.release;
+        case GLFW_CONTEXT_NO_ERROR:
+            return window->context.noerror;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
+    return 0;
+}
+
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    value = value ? GLFW_TRUE : GLFW_FALSE;
+
+    if (attrib == GLFW_AUTO_ICONIFY)
+        window->autoIconify = value;
+    else if (attrib == GLFW_RESIZABLE)
+    {
+        if (window->resizable == value)
+            return;
+
+        window->resizable = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowResizable(window, value);
+    }
+    else if (attrib == GLFW_DECORATED)
+    {
+        if (window->decorated == value)
+            return;
+
+        window->decorated = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowDecorated(window, value);
+    }
+    else if (attrib == GLFW_FLOATING)
+    {
+        if (window->floating == value)
+            return;
+
+        window->floating = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowFloating(window, value);
+    }
+    else if (attrib == GLFW_FOCUS_ON_SHOW)
+        window->focusOnShow = value;
+    else if (attrib == GLFW_MOUSE_PASSTHROUGH)
+    {
+        if (window->mousePassthrough == value)
+            return;
+
+        window->mousePassthrough = value;
+        _glfwPlatformSetWindowMousePassthrough(window, value);
+    }
+    else
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
+}
+
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return (GLFWmonitor*) window->monitor;
+}
+
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
+                                  GLFWmonitor* mh,
+                                  int xpos, int ypos,
+                                  int width, int height,
+                                  int refreshRate)
+{
+    _GLFWwindow* window = (_GLFWwindow*) wh;
+    _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
+    assert(window != NULL);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (width <= 0 || height <= 0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE,
+                        "Invalid window size %ix%i",
+                        width, height);
+        return;
+    }
+
+    if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE,
+                        "Invalid refresh rate %i",
+                        refreshRate);
+        return;
+    }
+
+    window->videoMode.width       = width;
+    window->videoMode.height      = height;
+    window->videoMode.refreshRate = refreshRate;
+
+    _glfwPlatformSetWindowMonitor(window, monitor,
+                                  xpos, ypos, width, height,
+                                  refreshRate);
+}
+
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    window->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return window->userPointer;
+}
+
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
+                                                  GLFWwindowposfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
+                                                    GLFWwindowsizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
+                                                      GLFWwindowclosefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
+                                                          GLFWwindowrefreshfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
+                                                      GLFWwindowfocusfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
+                                                          GLFWwindowiconifyfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
+                                                            GLFWwindowmaximizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
+                                                              GLFWframebuffersizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
+                                                                    GLFWwindowcontentscalefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
+    return cbfun;
+}
+
+GLFWAPI void glfwPollEvents(void)
+{
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformPollEvents();
+}
+
+GLFWAPI void glfwWaitEvents(void)
+{
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformWaitEvents();
+}
+
+GLFWAPI void glfwWaitEventsTimeout(double timeout)
+{
+    _GLFW_REQUIRE_INIT();
+    assert(timeout == timeout);
+    assert(timeout >= 0.0);
+    assert(timeout <= DBL_MAX);
+
+    if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
+        return;
+    }
+
+    _glfwPlatformWaitEventsTimeout(timeout);
+}
+
+GLFWAPI void glfwPostEmptyEvent(void)
+{
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformPostEmptyEvent();
+}
+