minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

window.c (35148B)


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