// Sets the cursor mode for the specified window // static void setCursorMode(_GLFWwindow* window, int newMode) { int width, height, oldMode, centerPosX, centerPosY; if (newMode != GLFW_CURSOR_NORMAL && newMode != GLFW_CURSOR_HIDDEN && newMode != GLFW_CURSOR_CAPTURED) { _glfwInputError(GLFW_INVALID_ENUM, NULL); return; } oldMode = window->cursorMode; if (oldMode == newMode) return; _glfwPlatformGetWindowSize(window, &width, &height); centerPosX = width / 2; centerPosY = height / 2; if (oldMode == GLFW_CURSOR_CAPTURED || newMode == GLFW_CURSOR_CAPTURED) _glfwPlatformSetCursorPos(window, centerPosX, centerPosY); _glfwPlatformSetCursorMode(window, newMode); window->cursorMode = newMode; if (oldMode == GLFW_CURSOR_CAPTURED) _glfwInputCursorMotion(window, window->cursorPosX, window->cursorPosY); }
GLFWAPI void glfwSetCursorPos(GLFWwindow handle, int xpos, int ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); return; } if (_glfwLibrary.focusedWindow != window) return; // Don't do anything if the cursor position did not change if (xpos == window->cursorPosX && ypos == window->cursorPosY) return; // Set GLFW cursor position window->cursorPosX = xpos; window->cursorPosY = ypos; // Do not move physical cursor in locked cursor mode if (window->cursorMode == GLFW_CURSOR_CAPTURED) return; // Update physical cursor position _glfwPlatformSetCursorPos(window, xpos, ypos); }
void _glfwPlatformPollEvents(void) { _GLFWwindow* window; // Process all pending events while (XPending(_glfwLibrary.X11.display)) processSingleEvent(); // Did the cursor move in an active window that has captured the cursor window = _glfwLibrary.activeWindow; if (window) { if (window->cursorMode == GLFW_CURSOR_CAPTURED && !window->X11.cursorCentered) { _glfwPlatformSetCursorPos(window, window->width / 2, window->height / 2); window->X11.cursorCentered = GL_TRUE; // NOTE: This is a temporary fix. It works as long as you use // offsets accumulated over the course of a frame, instead of // performing the necessary actions per callback call. XFlush( _glfwLibrary.X11.display ); } } }
void _glfwPlatformPollEvents(void) { int count = XPending(_glfw.x11.display); while (count--) { XEvent event; XNextEvent(_glfw.x11.display, &event); processEvent(&event); } // Check whether the cursor has moved inside an focused window that has // captured the cursor (because then it needs to be re-centered) _GLFWwindow* window; window = _glfw.focusedWindow; if (window) { if (window->cursorMode == GLFW_CURSOR_CAPTURED && !window->x11.cursorCentered) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformSetCursorPos(window, width / 2, height / 2); window->x11.cursorCentered = GL_TRUE; // NOTE: This is a temporary fix. It works as long as you use // offsets accumulated over the course of a frame, instead of // performing the necessary actions per callback call. XFlush(_glfw.x11.display); } } }
void _glfwPlatformPollEvents(void) { XEvent event; _GLFWwindow* window; while (XCheckMaskEvent(_glfwLibrary.X11.display, ~0, &event) || XCheckTypedEvent(_glfwLibrary.X11.display, ClientMessage, &event)) { processEvent(&event); } // Check whether the cursor has moved inside an active window that has // captured the cursor (because then it needs to be re-centered) window = _glfwLibrary.activeWindow; if (window) { if (window->cursorMode == GLFW_CURSOR_CAPTURED && !window->X11.cursorCentered) { _glfwPlatformSetCursorPos(window, window->width / 2, window->height / 2); window->X11.cursorCentered = GL_TRUE; // NOTE: This is a temporary fix. It works as long as you use // offsets accumulated over the course of a frame, instead of // performing the necessary actions per callback call. XFlush( _glfwLibrary.X11.display ); } } }
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX || ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid cursor position %f %f", xpos, ypos); return; } if (!_glfwPlatformWindowFocused(window)) return; if (window->cursorMode == GLFW_CURSOR_DISABLED) { // Only update the accumulated position if the cursor is disabled window->virtualCursorPosX = xpos; window->virtualCursorPosY = ypos; } else { // Update system cursor position _glfwPlatformSetCursorPos(window, xpos, ypos); } }
void _glfwPlatformPollEvents(void) { MSG msg; _GLFWwindow* window; while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { // Treat WM_QUIT as a close on all windows // While GLFW does not itself post WM_QUIT, other processes may post // it to this one, for example Task Manager window = _glfw.windowListHead; while (window) { _glfwInputWindowCloseRequest(window); window = window->next; } } else { TranslateMessage(&msg); DispatchMessageW(&msg); } } window = _glfw.focusedWindow; if (window) { // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix) // This is the only async event handling in GLFW, but it solves some // nasty problems { const int mods = getAsyncKeyMods(); // Get current state of left and right shift keys const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1; const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1; // See if this differs from our belief of what has happened // (we only have to check for lost key up events) if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods); if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods); } // Did the cursor move in an focused window that has disabled the cursor if (window->cursorMode == GLFW_CURSOR_DISABLED) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformSetCursorPos(window, width / 2, height / 2); } } }
// Sets the cursor mode for the specified window // static void setCursorMode(_GLFWwindow* window, int newMode) { const int oldMode = window->cursorMode; if (newMode != GLFW_CURSOR_NORMAL && newMode != GLFW_CURSOR_HIDDEN && newMode != GLFW_CURSOR_DISABLED) { _glfwInputError(GLFW_INVALID_ENUM, NULL); return; } if (oldMode == newMode) return; window->cursorMode = newMode; if (_glfw.focusedWindow == window) { if (oldMode == GLFW_CURSOR_DISABLED) { _glfwPlatformSetCursorPos(window, _glfw.cursorPosX, _glfw.cursorPosY); } else if (newMode == GLFW_CURSOR_DISABLED) { int width, height; _glfwPlatformGetCursorPos(window, &_glfw.cursorPosX, &_glfw.cursorPosY); window->cursorPosX = _glfw.cursorPosX; window->cursorPosY = _glfw.cursorPosY; _glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformSetCursorPos(window, width / 2, height / 2); } _glfwPlatformApplyCursorMode(window); } }
void _glfwPlatformPollEvents(void) { int count = XPending(_glfw.x11.display); while (count--) { XEvent event; XNextEvent(_glfw.x11.display, &event); processEvent(&event); } _GLFWwindow* window = _glfw.focusedWindow; if (window && window->cursorMode == GLFW_CURSOR_DISABLED) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformSetCursorPos(window, width / 2, height / 2); } }
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT(); if (_glfw.focusedWindow != window) return; if (window->cursorMode == GLFW_CURSOR_DISABLED) { // Only update the accumulated position if the cursor is disabled window->cursorPosX = xpos; window->cursorPosY = ypos; } else { // Update system cursor position _glfwPlatformSetCursorPos(window, xpos, ypos); } }
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { if (mode == GLFW_CURSOR_DISABLED) { _glfw.win32.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, &_glfw.win32.restoreCursorPosX, &_glfw.win32.restoreCursorPosY); centerCursor(window); updateClipRect(window); } else if (_glfw.win32.disabledCursorWindow == window) { _glfw.win32.disabledCursorWindow = NULL; updateClipRect(NULL); _glfwPlatformSetCursorPos(window, _glfw.win32.restoreCursorPosX, _glfw.win32.restoreCursorPosY); } if (cursorInClientArea(window)) updateCursorImage(window); }
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT(); if (_glfw.focusedWindow != window) return; // Don't do anything if the cursor position did not change if (xpos == window->cursorPosX && ypos == window->cursorPosY) return; // Set GLFW cursor position window->cursorPosX = xpos; window->cursorPosY = ypos; // Do not move physical cursor if it is disabled if (window->cursorMode == GLFW_CURSOR_DISABLED) return; // Update physical cursor position _glfwPlatformSetCursorPos(window, xpos, ypos); }
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share) { _GLFWfbconfig fbconfig; _GLFWctxconfig ctxconfig; _GLFWwndconfig wndconfig; _GLFWwindow* window; _GLFWwindow* previous; assert(title != NULL); _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 (ctxconfig.share) { if (ctxconfig.share->context.api == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; } } 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->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; // Save the currently current context so it can be restored later previous = _glfwPlatformGetCurrentContext(); // Open the actual window and create its context if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } if (ctxconfig.api != GLFW_NO_API) { _glfwPlatformMakeContextCurrent(window); // Retrieve the actual (as opposed to requested) context attributes if (!_glfwRefreshContextAttribs(&ctxconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } // Restore the previously current context (or NULL) _glfwPlatformMakeContextCurrent(previous); } if (window->monitor) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); window->cursorPosX = width / 2; window->cursorPosY = height / 2; _glfwPlatformSetCursorPos(window, window->cursorPosX, window->cursorPosY); } else { if (wndconfig.visible) { _glfwPlatformShowWindow(window); if (wndconfig.focused) _glfwPlatformFocusWindow(window); } } return (GLFWwindow*) window; }
void _glfwPlatformPollEvents(void) { MSG msg; HWND handle; _GLFWwindow* window; while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { // Treat WM_QUIT as a close on all windows // While GLFW does not itself post WM_QUIT, other processes may post // it to this one, for example Task Manager window = _glfw.windowListHead; while (window) { _glfwInputWindowCloseRequest(window); window = window->next; } } else { TranslateMessage(&msg); DispatchMessageW(&msg); } } handle = GetActiveWindow(); if (handle) { // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix) // This is the only async event handling in GLFW, but it solves some // nasty problems window = GetPropW(handle, L"GLFW"); if (window) { const int mods = getAsyncKeyMods(); // Get current state of left and right shift keys const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1; const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1; // See if this differs from our belief of what has happened // (we only have to check for lost key up events) if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods); if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods); } } window = _glfw.win32.disabledCursorWindow; if (window) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); // NOTE: Re-center the cursor only if it has moved since the last call, // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE if (window->win32.lastCursorPosX != width / 2 || window->win32.lastCursorPosY != height / 2) { _glfwPlatformSetCursorPos(window, width / 2, height / 2); } } }
// Centers the cursor over the window client area // static void centerCursor(_GLFWwindow* window) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); }
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share) { _GLFWfbconfig fbconfig; _GLFWctxconfig ctxconfig; _GLFWwndconfig wndconfig; _GLFWwindow* window; _GLFWwindow* previous; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (width <= 0 || height <= 0) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid window size"); return NULL; } fbconfig = _glfw.hints.framebuffer; ctxconfig = _glfw.hints.context; wndconfig = _glfw.hints.window; wndconfig.width = width; wndconfig.height = height; wndconfig.title = title; wndconfig.monitor = (_GLFWmonitor*) monitor; ctxconfig.share = (_GLFWwindow*) share; if (wndconfig.monitor) { wndconfig.resizable = GLFW_TRUE; wndconfig.visible = GLFW_TRUE; wndconfig.focused = GLFW_TRUE; } // Check the OpenGL bits of the window config 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 = wndconfig.monitor; window->resizable = wndconfig.resizable; window->decorated = wndconfig.decorated; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; window->cursorMode = GLFW_CURSOR_NORMAL; // Save the currently current context so it can be restored later previous = _glfwPlatformGetCurrentContext(); // Open the actual window and create its context if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } _glfwPlatformMakeContextCurrent(window); // Retrieve the actual (as opposed to requested) context attributes if (!_glfwRefreshContextAttribs(&ctxconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } // Verify the context against the requested parameters if (!_glfwIsValidContext(&ctxconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } // Clearing the front buffer to black to avoid garbage pixels left over // from previous uses of our bit of VRAM window->Clear(GL_COLOR_BUFFER_BIT); _glfwPlatformSwapBuffers(window); // Restore the previously current context (or NULL) _glfwPlatformMakeContextCurrent(previous); if (wndconfig.monitor) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); window->cursorPosX = width / 2; window->cursorPosY = height / 2; _glfwPlatformSetCursorPos(window, window->cursorPosX, window->cursorPosY); } else { if (wndconfig.visible) { if (wndconfig.focused) _glfwPlatformShowWindow(window); else _glfwPlatformUnhideWindow(window); } } return (GLFWwindow*) window; }
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share) { _GLFWfbconfig fbconfig; _GLFWctxconfig ctxconfig; _GLFWwndconfig wndconfig; _GLFWwindow* window; _GLFWwindow* previous; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (width <= 0 || height <= 0) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid window size"); return NULL; } // Set up desired framebuffer config fbconfig.redBits = _glfw.hints.redBits; fbconfig.greenBits = _glfw.hints.greenBits; fbconfig.blueBits = _glfw.hints.blueBits; fbconfig.alphaBits = _glfw.hints.alphaBits; fbconfig.depthBits = _glfw.hints.depthBits; fbconfig.stencilBits = _glfw.hints.stencilBits; fbconfig.accumRedBits = _glfw.hints.accumRedBits; fbconfig.accumGreenBits = _glfw.hints.accumGreenBits; fbconfig.accumBlueBits = _glfw.hints.accumBlueBits; fbconfig.accumAlphaBits = _glfw.hints.accumAlphaBits; fbconfig.auxBuffers = _glfw.hints.auxBuffers; fbconfig.stereo = _glfw.hints.stereo ? GL_TRUE : GL_FALSE; fbconfig.samples = _glfw.hints.samples; fbconfig.sRGB = _glfw.hints.sRGB; fbconfig.doublebuffer = _glfw.hints.doublebuffer ? GL_TRUE : GL_FALSE; fbconfig.alphaMask = _glfw.hints.alphaMask ? GL_TRUE : GL_FALSE; // Set up desired window config wndconfig.width = width; wndconfig.height = height; wndconfig.title = title; wndconfig.resizable = _glfw.hints.resizable ? GL_TRUE : GL_FALSE; wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE; wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE; wndconfig.focused = _glfw.hints.focused ? GL_TRUE : GL_FALSE; wndconfig.autoIconify = _glfw.hints.autoIconify ? GL_TRUE : GL_FALSE; wndconfig.floating = _glfw.hints.floating ? GL_TRUE : GL_FALSE; wndconfig.monitor = (_GLFWmonitor*) monitor; wndconfig.alphaMask = _glfw.hints.alphaMask ? GL_TRUE : GL_FALSE; // Set up desired context config ctxconfig.api = _glfw.hints.api; ctxconfig.major = _glfw.hints.major; ctxconfig.minor = _glfw.hints.minor; ctxconfig.forward = _glfw.hints.forward ? GL_TRUE : GL_FALSE; ctxconfig.debug = _glfw.hints.debug ? GL_TRUE : GL_FALSE; ctxconfig.profile = _glfw.hints.profile; ctxconfig.robustness = _glfw.hints.robustness; ctxconfig.release = _glfw.hints.release; ctxconfig.share = (_GLFWwindow*) share; // Check the OpenGL bits of the window config if (!_glfwIsValidContextConfig(&ctxconfig)) return NULL; window = calloc(1, sizeof(_GLFWwindow)); window->next = _glfw.windowListHead; _glfw.windowListHead = window; if (wndconfig.monitor) { wndconfig.resizable = GL_TRUE; wndconfig.visible = GL_TRUE; wndconfig.focused = GL_TRUE; // Set up desired video mode window->videoMode.width = width; window->videoMode.height = height; window->videoMode.redBits = _glfw.hints.redBits; window->videoMode.greenBits = _glfw.hints.greenBits; window->videoMode.blueBits = _glfw.hints.blueBits; window->videoMode.refreshRate = _glfw.hints.refreshRate; } // Transfer window hints that are persistent settings and not // just initial states window->monitor = wndconfig.monitor; window->resizable = wndconfig.resizable; window->decorated = wndconfig.decorated; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; window->transparent = wndconfig.alphaMask; window->cursorMode = GLFW_CURSOR_NORMAL; // Save the currently current context so it can be restored later previous = _glfwPlatformGetCurrentContext(); // Open the actual window and create its context if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } _glfwPlatformMakeContextCurrent(window); // Retrieve the actual (as opposed to requested) context attributes if (!_glfwRefreshContextAttribs(&ctxconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } // Verify the context against the requested parameters if (!_glfwIsValidContext(&ctxconfig)) { glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(previous); return NULL; } // Clearing the front buffer to black to avoid garbage pixels left over // from previous uses of our bit of VRAM glClear(GL_COLOR_BUFFER_BIT); _glfwPlatformSwapBuffers(window); // Restore the previously current context (or NULL) _glfwPlatformMakeContextCurrent(previous); if (wndconfig.monitor) { int width, height; _glfwPlatformGetWindowSize(window, &width, &height); window->cursorPosX = width / 2; window->cursorPosY = height / 2; _glfwPlatformSetCursorPos(window, window->cursorPosX, window->cursorPosY); } else { if (wndconfig.visible) { if (wndconfig.focused) _glfwPlatformShowWindow(window); else _glfwPlatformUnhideWindow(window); } } return (GLFWwindow*) window; }