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