revolver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

window.c (33265B)


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