zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

window.c (32919B)


      1 //========================================================================
      2 // GLFW 3.3 - 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 = 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_COCOA_GRAPHICS_SWITCHING:
    367             _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
    368             return;
    369         case GLFW_SCALE_TO_MONITOR:
    370             _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
    371             return;
    372         case GLFW_CENTER_CURSOR:
    373             _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
    374             return;
    375         case GLFW_FOCUS_ON_SHOW:
    376             _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
    377             return;
    378         case GLFW_CLIENT_API:
    379             _glfw.hints.context.client = value;
    380             return;
    381         case GLFW_CONTEXT_CREATION_API:
    382             _glfw.hints.context.source = value;
    383             return;
    384         case GLFW_CONTEXT_VERSION_MAJOR:
    385             _glfw.hints.context.major = value;
    386             return;
    387         case GLFW_CONTEXT_VERSION_MINOR:
    388             _glfw.hints.context.minor = value;
    389             return;
    390         case GLFW_CONTEXT_ROBUSTNESS:
    391             _glfw.hints.context.robustness = value;
    392             return;
    393         case GLFW_OPENGL_FORWARD_COMPAT:
    394             _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
    395             return;
    396         case GLFW_OPENGL_DEBUG_CONTEXT:
    397             _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
    398             return;
    399         case GLFW_CONTEXT_NO_ERROR:
    400             _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
    401             return;
    402         case GLFW_OPENGL_PROFILE:
    403             _glfw.hints.context.profile = value;
    404             return;
    405         case GLFW_CONTEXT_RELEASE_BEHAVIOR:
    406             _glfw.hints.context.release = value;
    407             return;
    408         case GLFW_REFRESH_RATE:
    409             _glfw.hints.refreshRate = value;
    410             return;
    411     }
    412 
    413     _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
    414 }
    415 
    416 GLFWAPI void glfwWindowHintString(int hint, const char* value)
    417 {
    418     assert(value != NULL);
    419 
    420     _GLFW_REQUIRE_INIT();
    421 
    422     switch (hint)
    423     {
    424         case GLFW_COCOA_FRAME_NAME:
    425             strncpy(_glfw.hints.window.ns.frameName, value,
    426                     sizeof(_glfw.hints.window.ns.frameName) - 1);
    427             return;
    428         case GLFW_X11_CLASS_NAME:
    429             strncpy(_glfw.hints.window.x11.className, value,
    430                     sizeof(_glfw.hints.window.x11.className) - 1);
    431             return;
    432         case GLFW_X11_INSTANCE_NAME:
    433             strncpy(_glfw.hints.window.x11.instanceName, value,
    434                     sizeof(_glfw.hints.window.x11.instanceName) - 1);
    435             return;
    436     }
    437 
    438     _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
    439 }
    440 
    441 GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
    442 {
    443     _GLFWwindow* window = (_GLFWwindow*) handle;
    444 
    445     _GLFW_REQUIRE_INIT();
    446 
    447     // Allow closing of NULL (to match the behavior of free)
    448     if (window == NULL)
    449         return;
    450 
    451     // Clear all callbacks to avoid exposing a half torn-down window object
    452     memset(&window->callbacks, 0, sizeof(window->callbacks));
    453 
    454     // The window's context must not be current on another thread when the
    455     // window is destroyed
    456     if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
    457         glfwMakeContextCurrent(NULL);
    458 
    459     _glfwPlatformDestroyWindow(window);
    460 
    461     // Unlink window from global linked list
    462     {
    463         _GLFWwindow** prev = &_glfw.windowListHead;
    464 
    465         while (*prev != window)
    466             prev = &((*prev)->next);
    467 
    468         *prev = window->next;
    469     }
    470 
    471     free(window);
    472 }
    473 
    474 GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
    475 {
    476     _GLFWwindow* window = (_GLFWwindow*) handle;
    477     assert(window != NULL);
    478 
    479     _GLFW_REQUIRE_INIT_OR_RETURN(0);
    480     return window->shouldClose;
    481 }
    482 
    483 GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
    484 {
    485     _GLFWwindow* window = (_GLFWwindow*) handle;
    486     assert(window != NULL);
    487 
    488     _GLFW_REQUIRE_INIT();
    489     window->shouldClose = value;
    490 }
    491 
    492 GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
    493 {
    494     _GLFWwindow* window = (_GLFWwindow*) handle;
    495     assert(window != NULL);
    496     assert(title != NULL);
    497 
    498     _GLFW_REQUIRE_INIT();
    499     _glfwPlatformSetWindowTitle(window, title);
    500 }
    501 
    502 GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
    503                                int count, const GLFWimage* images)
    504 {
    505     _GLFWwindow* window = (_GLFWwindow*) handle;
    506     assert(window != NULL);
    507     assert(count >= 0);
    508     assert(count == 0 || images != NULL);
    509 
    510     _GLFW_REQUIRE_INIT();
    511     _glfwPlatformSetWindowIcon(window, count, images);
    512 }
    513 
    514 GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
    515 {
    516     _GLFWwindow* window = (_GLFWwindow*) handle;
    517     assert(window != NULL);
    518 
    519     if (xpos)
    520         *xpos = 0;
    521     if (ypos)
    522         *ypos = 0;
    523 
    524     _GLFW_REQUIRE_INIT();
    525     _glfwPlatformGetWindowPos(window, xpos, ypos);
    526 }
    527 
    528 GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
    529 {
    530     _GLFWwindow* window = (_GLFWwindow*) handle;
    531     assert(window != NULL);
    532 
    533     _GLFW_REQUIRE_INIT();
    534 
    535     if (window->monitor)
    536         return;
    537 
    538     _glfwPlatformSetWindowPos(window, xpos, ypos);
    539 }
    540 
    541 GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
    542 {
    543     _GLFWwindow* window = (_GLFWwindow*) handle;
    544     assert(window != NULL);
    545 
    546     if (width)
    547         *width = 0;
    548     if (height)
    549         *height = 0;
    550 
    551     _GLFW_REQUIRE_INIT();
    552     _glfwPlatformGetWindowSize(window, width, height);
    553 }
    554 
    555 GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
    556 {
    557     _GLFWwindow* window = (_GLFWwindow*) handle;
    558     assert(window != NULL);
    559     assert(width >= 0);
    560     assert(height >= 0);
    561 
    562     _GLFW_REQUIRE_INIT();
    563 
    564     window->videoMode.width  = width;
    565     window->videoMode.height = height;
    566 
    567     _glfwPlatformSetWindowSize(window, width, height);
    568 }
    569 
    570 GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
    571                                      int minwidth, int minheight,
    572                                      int maxwidth, int maxheight)
    573 {
    574     _GLFWwindow* window = (_GLFWwindow*) handle;
    575     assert(window != NULL);
    576 
    577     _GLFW_REQUIRE_INIT();
    578 
    579     if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
    580     {
    581         if (minwidth < 0 || minheight < 0)
    582         {
    583             _glfwInputError(GLFW_INVALID_VALUE,
    584                             "Invalid window minimum size %ix%i",
    585                             minwidth, minheight);
    586             return;
    587         }
    588     }
    589 
    590     if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)
    591     {
    592         if (maxwidth < 0 || maxheight < 0 ||
    593             maxwidth < minwidth || maxheight < minheight)
    594         {
    595             _glfwInputError(GLFW_INVALID_VALUE,
    596                             "Invalid window maximum size %ix%i",
    597                             maxwidth, maxheight);
    598             return;
    599         }
    600     }
    601 
    602     window->minwidth  = minwidth;
    603     window->minheight = minheight;
    604     window->maxwidth  = maxwidth;
    605     window->maxheight = maxheight;
    606 
    607     if (window->monitor || !window->resizable)
    608         return;
    609 
    610     _glfwPlatformSetWindowSizeLimits(window,
    611                                      minwidth, minheight,
    612                                      maxwidth, maxheight);
    613 }
    614 
    615 GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
    616 {
    617     _GLFWwindow* window = (_GLFWwindow*) handle;
    618     assert(window != NULL);
    619     assert(numer != 0);
    620     assert(denom != 0);
    621 
    622     _GLFW_REQUIRE_INIT();
    623 
    624     if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
    625     {
    626         if (numer <= 0 || denom <= 0)
    627         {
    628             _glfwInputError(GLFW_INVALID_VALUE,
    629                             "Invalid window aspect ratio %i:%i",
    630                             numer, denom);
    631             return;
    632         }
    633     }
    634 
    635     window->numer = numer;
    636     window->denom = denom;
    637 
    638     if (window->monitor || !window->resizable)
    639         return;
    640 
    641     _glfwPlatformSetWindowAspectRatio(window, numer, denom);
    642 }
    643 
    644 GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
    645 {
    646     _GLFWwindow* window = (_GLFWwindow*) handle;
    647     assert(window != NULL);
    648 
    649     if (width)
    650         *width = 0;
    651     if (height)
    652         *height = 0;
    653 
    654     _GLFW_REQUIRE_INIT();
    655     _glfwPlatformGetFramebufferSize(window, width, height);
    656 }
    657 
    658 GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
    659                                     int* left, int* top,
    660                                     int* right, int* bottom)
    661 {
    662     _GLFWwindow* window = (_GLFWwindow*) handle;
    663     assert(window != NULL);
    664 
    665     if (left)
    666         *left = 0;
    667     if (top)
    668         *top = 0;
    669     if (right)
    670         *right = 0;
    671     if (bottom)
    672         *bottom = 0;
    673 
    674     _GLFW_REQUIRE_INIT();
    675     _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
    676 }
    677 
    678 GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
    679                                        float* xscale, float* yscale)
    680 {
    681     _GLFWwindow* window = (_GLFWwindow*) handle;
    682     assert(window != NULL);
    683 
    684     if (xscale)
    685         *xscale = 0.f;
    686     if (yscale)
    687         *yscale = 0.f;
    688 
    689     _GLFW_REQUIRE_INIT();
    690     _glfwPlatformGetWindowContentScale(window, xscale, yscale);
    691 }
    692 
    693 GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
    694 {
    695     _GLFWwindow* window = (_GLFWwindow*) handle;
    696     assert(window != NULL);
    697 
    698     _GLFW_REQUIRE_INIT_OR_RETURN(1.f);
    699     return _glfwPlatformGetWindowOpacity(window);
    700 }
    701 
    702 GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
    703 {
    704     _GLFWwindow* window = (_GLFWwindow*) handle;
    705     assert(window != NULL);
    706     assert(opacity == opacity);
    707     assert(opacity >= 0.f);
    708     assert(opacity <= 1.f);
    709 
    710     _GLFW_REQUIRE_INIT();
    711 
    712     if (opacity != opacity || opacity < 0.f || opacity > 1.f)
    713     {
    714         _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
    715         return;
    716     }
    717 
    718     _glfwPlatformSetWindowOpacity(window, opacity);
    719 }
    720 
    721 GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
    722 {
    723     _GLFWwindow* window = (_GLFWwindow*) handle;
    724     assert(window != NULL);
    725 
    726     _GLFW_REQUIRE_INIT();
    727     _glfwPlatformIconifyWindow(window);
    728 }
    729 
    730 GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
    731 {
    732     _GLFWwindow* window = (_GLFWwindow*) handle;
    733     assert(window != NULL);
    734 
    735     _GLFW_REQUIRE_INIT();
    736     _glfwPlatformRestoreWindow(window);
    737 }
    738 
    739 GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
    740 {
    741     _GLFWwindow* window = (_GLFWwindow*) handle;
    742     assert(window != NULL);
    743 
    744     _GLFW_REQUIRE_INIT();
    745 
    746     if (window->monitor)
    747         return;
    748 
    749     _glfwPlatformMaximizeWindow(window);
    750 }
    751 
    752 GLFWAPI void glfwShowWindow(GLFWwindow* handle)
    753 {
    754     _GLFWwindow* window = (_GLFWwindow*) handle;
    755     assert(window != NULL);
    756 
    757     _GLFW_REQUIRE_INIT();
    758 
    759     if (window->monitor)
    760         return;
    761 
    762     _glfwPlatformShowWindow(window);
    763 
    764     if (window->focusOnShow)
    765         _glfwPlatformFocusWindow(window);
    766 }
    767 
    768 GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
    769 {
    770     _GLFWwindow* window = (_GLFWwindow*) handle;
    771     assert(window != NULL);
    772 
    773     _GLFW_REQUIRE_INIT();
    774 
    775     _glfwPlatformRequestWindowAttention(window);
    776 }
    777 
    778 GLFWAPI void glfwHideWindow(GLFWwindow* handle)
    779 {
    780     _GLFWwindow* window = (_GLFWwindow*) handle;
    781     assert(window != NULL);
    782 
    783     _GLFW_REQUIRE_INIT();
    784 
    785     if (window->monitor)
    786         return;
    787 
    788     _glfwPlatformHideWindow(window);
    789 }
    790 
    791 GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
    792 {
    793     _GLFWwindow* window = (_GLFWwindow*) handle;
    794     assert(window != NULL);
    795 
    796     _GLFW_REQUIRE_INIT();
    797 
    798     _glfwPlatformFocusWindow(window);
    799 }
    800 
    801 GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
    802 {
    803     _GLFWwindow* window = (_GLFWwindow*) handle;
    804     assert(window != NULL);
    805 
    806     _GLFW_REQUIRE_INIT_OR_RETURN(0);
    807 
    808     switch (attrib)
    809     {
    810         case GLFW_FOCUSED:
    811             return _glfwPlatformWindowFocused(window);
    812         case GLFW_ICONIFIED:
    813             return _glfwPlatformWindowIconified(window);
    814         case GLFW_VISIBLE:
    815             return _glfwPlatformWindowVisible(window);
    816         case GLFW_MAXIMIZED:
    817             return _glfwPlatformWindowMaximized(window);
    818         case GLFW_HOVERED:
    819             return _glfwPlatformWindowHovered(window);
    820         case GLFW_FOCUS_ON_SHOW:
    821             return window->focusOnShow;
    822         case GLFW_TRANSPARENT_FRAMEBUFFER:
    823             return _glfwPlatformFramebufferTransparent(window);
    824         case GLFW_RESIZABLE:
    825             return window->resizable;
    826         case GLFW_DECORATED:
    827             return window->decorated;
    828         case GLFW_FLOATING:
    829             return window->floating;
    830         case GLFW_AUTO_ICONIFY:
    831             return window->autoIconify;
    832         case GLFW_CLIENT_API:
    833             return window->context.client;
    834         case GLFW_CONTEXT_CREATION_API:
    835             return window->context.source;
    836         case GLFW_CONTEXT_VERSION_MAJOR:
    837             return window->context.major;
    838         case GLFW_CONTEXT_VERSION_MINOR:
    839             return window->context.minor;
    840         case GLFW_CONTEXT_REVISION:
    841             return window->context.revision;
    842         case GLFW_CONTEXT_ROBUSTNESS:
    843             return window->context.robustness;
    844         case GLFW_OPENGL_FORWARD_COMPAT:
    845             return window->context.forward;
    846         case GLFW_OPENGL_DEBUG_CONTEXT:
    847             return window->context.debug;
    848         case GLFW_OPENGL_PROFILE:
    849             return window->context.profile;
    850         case GLFW_CONTEXT_RELEASE_BEHAVIOR:
    851             return window->context.release;
    852         case GLFW_CONTEXT_NO_ERROR:
    853             return window->context.noerror;
    854     }
    855 
    856     _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
    857     return 0;
    858 }
    859 
    860 GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
    861 {
    862     _GLFWwindow* window = (_GLFWwindow*) handle;
    863     assert(window != NULL);
    864 
    865     _GLFW_REQUIRE_INIT();
    866 
    867     value = value ? GLFW_TRUE : GLFW_FALSE;
    868 
    869     if (attrib == GLFW_AUTO_ICONIFY)
    870         window->autoIconify = value;
    871     else if (attrib == GLFW_RESIZABLE)
    872     {
    873         if (window->resizable == value)
    874             return;
    875 
    876         window->resizable = value;
    877         if (!window->monitor)
    878             _glfwPlatformSetWindowResizable(window, value);
    879     }
    880     else if (attrib == GLFW_DECORATED)
    881     {
    882         if (window->decorated == value)
    883             return;
    884 
    885         window->decorated = value;
    886         if (!window->monitor)
    887             _glfwPlatformSetWindowDecorated(window, value);
    888     }
    889     else if (attrib == GLFW_FLOATING)
    890     {
    891         if (window->floating == value)
    892             return;
    893 
    894         window->floating = value;
    895         if (!window->monitor)
    896             _glfwPlatformSetWindowFloating(window, value);
    897     }
    898     else if (attrib == GLFW_FOCUS_ON_SHOW)
    899         window->focusOnShow = value;
    900     else
    901         _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
    902 }
    903 
    904 GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
    905 {
    906     _GLFWwindow* window = (_GLFWwindow*) handle;
    907     assert(window != NULL);
    908 
    909     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    910     return (GLFWmonitor*) window->monitor;
    911 }
    912 
    913 GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
    914                                   GLFWmonitor* mh,
    915                                   int xpos, int ypos,
    916                                   int width, int height,
    917                                   int refreshRate)
    918 {
    919     _GLFWwindow* window = (_GLFWwindow*) wh;
    920     _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
    921     assert(window != NULL);
    922     assert(width >= 0);
    923     assert(height >= 0);
    924 
    925     _GLFW_REQUIRE_INIT();
    926 
    927     if (width <= 0 || height <= 0)
    928     {
    929         _glfwInputError(GLFW_INVALID_VALUE,
    930                         "Invalid window size %ix%i",
    931                         width, height);
    932         return;
    933     }
    934 
    935     if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
    936     {
    937         _glfwInputError(GLFW_INVALID_VALUE,
    938                         "Invalid refresh rate %i",
    939                         refreshRate);
    940         return;
    941     }
    942 
    943     window->videoMode.width       = width;
    944     window->videoMode.height      = height;
    945     window->videoMode.refreshRate = refreshRate;
    946 
    947     _glfwPlatformSetWindowMonitor(window, monitor,
    948                                   xpos, ypos, width, height,
    949                                   refreshRate);
    950 }
    951 
    952 GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
    953 {
    954     _GLFWwindow* window = (_GLFWwindow*) handle;
    955     assert(window != NULL);
    956 
    957     _GLFW_REQUIRE_INIT();
    958     window->userPointer = pointer;
    959 }
    960 
    961 GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
    962 {
    963     _GLFWwindow* window = (_GLFWwindow*) handle;
    964     assert(window != NULL);
    965 
    966     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    967     return window->userPointer;
    968 }
    969 
    970 GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
    971                                                   GLFWwindowposfun cbfun)
    972 {
    973     _GLFWwindow* window = (_GLFWwindow*) handle;
    974     assert(window != NULL);
    975 
    976     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    977     _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
    978     return cbfun;
    979 }
    980 
    981 GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
    982                                                     GLFWwindowsizefun cbfun)
    983 {
    984     _GLFWwindow* window = (_GLFWwindow*) handle;
    985     assert(window != NULL);
    986 
    987     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    988     _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
    989     return cbfun;
    990 }
    991 
    992 GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
    993                                                       GLFWwindowclosefun cbfun)
    994 {
    995     _GLFWwindow* window = (_GLFWwindow*) handle;
    996     assert(window != NULL);
    997 
    998     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    999     _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
   1000     return cbfun;
   1001 }
   1002 
   1003 GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
   1004                                                           GLFWwindowrefreshfun cbfun)
   1005 {
   1006     _GLFWwindow* window = (_GLFWwindow*) handle;
   1007     assert(window != NULL);
   1008 
   1009     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1010     _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
   1011     return cbfun;
   1012 }
   1013 
   1014 GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
   1015                                                       GLFWwindowfocusfun cbfun)
   1016 {
   1017     _GLFWwindow* window = (_GLFWwindow*) handle;
   1018     assert(window != NULL);
   1019 
   1020     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1021     _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
   1022     return cbfun;
   1023 }
   1024 
   1025 GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
   1026                                                           GLFWwindowiconifyfun cbfun)
   1027 {
   1028     _GLFWwindow* window = (_GLFWwindow*) handle;
   1029     assert(window != NULL);
   1030 
   1031     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1032     _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
   1033     return cbfun;
   1034 }
   1035 
   1036 GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
   1037                                                             GLFWwindowmaximizefun cbfun)
   1038 {
   1039     _GLFWwindow* window = (_GLFWwindow*) handle;
   1040     assert(window != NULL);
   1041 
   1042     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1043     _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
   1044     return cbfun;
   1045 }
   1046 
   1047 GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
   1048                                                               GLFWframebuffersizefun cbfun)
   1049 {
   1050     _GLFWwindow* window = (_GLFWwindow*) handle;
   1051     assert(window != NULL);
   1052 
   1053     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1054     _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
   1055     return cbfun;
   1056 }
   1057 
   1058 GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
   1059                                                                     GLFWwindowcontentscalefun cbfun)
   1060 {
   1061     _GLFWwindow* window = (_GLFWwindow*) handle;
   1062     assert(window != NULL);
   1063 
   1064     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   1065     _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
   1066     return cbfun;
   1067 }
   1068 
   1069 GLFWAPI void glfwPollEvents(void)
   1070 {
   1071     _GLFW_REQUIRE_INIT();
   1072     _glfwPlatformPollEvents();
   1073 }
   1074 
   1075 GLFWAPI void glfwWaitEvents(void)
   1076 {
   1077     _GLFW_REQUIRE_INIT();
   1078     _glfwPlatformWaitEvents();
   1079 }
   1080 
   1081 GLFWAPI void glfwWaitEventsTimeout(double timeout)
   1082 {
   1083     _GLFW_REQUIRE_INIT();
   1084     assert(timeout == timeout);
   1085     assert(timeout >= 0.0);
   1086     assert(timeout <= DBL_MAX);
   1087 
   1088     if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
   1089     {
   1090         _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
   1091         return;
   1092     }
   1093 
   1094     _glfwPlatformWaitEventsTimeout(timeout);
   1095 }
   1096 
   1097 GLFWAPI void glfwPostEmptyEvent(void)
   1098 {
   1099     _GLFW_REQUIRE_INIT();
   1100     _glfwPlatformPostEmptyEvent();
   1101 }
   1102