| //======================================================================== |
| // GLFW - An OpenGL library |
| // Platform: Any |
| // API version: 3.0 |
| // WWW: http://www.glfw.org/ |
| //------------------------------------------------------------------------ |
| // Copyright (c) 2002-2006 Marcus Geelnard |
| // Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org> |
| // |
| // 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" |
| |
| |
| //======================================================================== |
| // Sets the cursor mode for the specified window |
| //======================================================================== |
| |
| static void setCursorMode(_GLFWwindow* window, int newMode) |
| { |
| int oldMode, centerPosX, centerPosY; |
| |
| if (newMode != GLFW_CURSOR_NORMAL && |
| newMode != GLFW_CURSOR_HIDDEN && |
| newMode != GLFW_CURSOR_CAPTURED) |
| { |
| _glfwSetError(GLFW_INVALID_ENUM, NULL); |
| return; |
| } |
| |
| oldMode = window->cursorMode; |
| if (oldMode == newMode) |
| return; |
| |
| centerPosX = window->width / 2; |
| centerPosY = window->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); |
| } |
| |
| |
| //======================================================================== |
| // Set sticky keys mode for the specified window |
| //======================================================================== |
| |
| static void setStickyKeys(_GLFWwindow* window, int enabled) |
| { |
| if (window->stickyKeys == enabled) |
| return; |
| |
| if (!enabled) |
| { |
| int i; |
| |
| // Release all sticky keys |
| for (i = 0; i <= GLFW_KEY_LAST; i++) |
| { |
| if (window->key[i] == GLFW_STICK) |
| window->key[i] = GLFW_RELEASE; |
| } |
| } |
| |
| window->stickyKeys = enabled; |
| } |
| |
| |
| //======================================================================== |
| // Set sticky mouse buttons mode for the specified window |
| //======================================================================== |
| |
| static void setStickyMouseButtons(_GLFWwindow* window, int enabled) |
| { |
| if (window->stickyMouseButtons == enabled) |
| return; |
| |
| if (!enabled) |
| { |
| int i; |
| |
| // Release all sticky mouse buttons |
| for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) |
| { |
| if (window->mouseButton[i] == GLFW_STICK) |
| window->mouseButton[i] = GLFW_RELEASE; |
| } |
| } |
| |
| window->stickyMouseButtons = enabled; |
| } |
| |
| |
| //======================================================================== |
| // Set system keys for the specified window |
| //======================================================================== |
| |
| static void setSystemKeys(_GLFWwindow* window, int enabled) |
| { |
| if (window->systemKeys == enabled) |
| return; |
| |
| if (enabled) |
| _glfwPlatformEnableSystemKeys(window); |
| else |
| _glfwPlatformDisableSystemKeys(window); |
| |
| window->systemKeys = enabled; |
| } |
| |
| |
| //======================================================================== |
| // Set key repeat for the specified window |
| //======================================================================== |
| |
| static void setKeyRepeat(_GLFWwindow* window, int enabled) |
| { |
| window->keyRepeat = enabled; |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////////// |
| ////// GLFW internal API ////// |
| ////////////////////////////////////////////////////////////////////////// |
| |
| //======================================================================== |
| // Register keyboard activity |
| //======================================================================== |
| |
| void _glfwInputKey(_GLFWwindow* window, int key, int action) |
| { |
| GLboolean repeated = GL_FALSE; |
| |
| if (key < 0 || key > GLFW_KEY_LAST) |
| return; |
| |
| // Are we trying to release an already released key? |
| if (action == GLFW_RELEASE && window->key[key] != GLFW_PRESS) |
| return; |
| |
| // Register key action |
| if (action == GLFW_RELEASE && window->stickyKeys) |
| window->key[key] = GLFW_STICK; |
| else |
| { |
| repeated = (window->key[key] == GLFW_PRESS) && (action == GLFW_PRESS); |
| window->key[key] = (char) action; |
| } |
| |
| // Call user callback function |
| if (_glfwLibrary.keyCallback && (window->keyRepeat || !repeated)) |
| _glfwLibrary.keyCallback(window, key, action); |
| } |
| |
| |
| //======================================================================== |
| // Register (keyboard) character activity |
| //======================================================================== |
| |
| void _glfwInputChar(_GLFWwindow* window, int character) |
| { |
| // Valid Unicode (ISO 10646) character? |
| if (!((character >= 32 && character <= 126) || character >= 160)) |
| return; |
| |
| if (_glfwLibrary.charCallback) |
| _glfwLibrary.charCallback(window, character); |
| } |
| |
| |
| //======================================================================== |
| // Register scroll events |
| //======================================================================== |
| |
| void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) |
| { |
| window->scrollX += xoffset; |
| window->scrollY += yoffset; |
| |
| if (_glfwLibrary.scrollCallback) |
| _glfwLibrary.scrollCallback(window, xoffset, yoffset); |
| } |
| |
| |
| //======================================================================== |
| // Register mouse button clicks |
| //======================================================================== |
| |
| void _glfwInputMouseClick(_GLFWwindow* window, int button, int action) |
| { |
| if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) |
| return; |
| |
| // Register mouse button action |
| if (action == GLFW_RELEASE && window->stickyMouseButtons) |
| window->mouseButton[button] = GLFW_STICK; |
| else |
| window->mouseButton[button] = (char) action; |
| |
| if (_glfwLibrary.mouseButtonCallback) |
| _glfwLibrary.mouseButtonCallback(window, button, action); |
| } |
| |
| |
| //======================================================================== |
| // Register cursor moves |
| //======================================================================== |
| |
| void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y) |
| { |
| if (window->cursorMode == GLFW_CURSOR_CAPTURED) |
| { |
| if (!x && !y) |
| return; |
| |
| window->cursorPosX += x; |
| window->cursorPosY += y; |
| } |
| else |
| { |
| if (window->cursorPosX == x && window->cursorPosY == y) |
| return; |
| |
| window->cursorPosX = x; |
| window->cursorPosY = y; |
| } |
| |
| if (_glfwLibrary.cursorPosCallback) |
| { |
| _glfwLibrary.cursorPosCallback(window, |
| window->cursorPosX, |
| window->cursorPosY); |
| } |
| } |
| |
| |
| //======================================================================== |
| // Register cursor enter/leave events |
| //======================================================================== |
| |
| void _glfwInputCursorEnter(_GLFWwindow* window, int entered) |
| { |
| if (_glfwLibrary.cursorEnterCallback) |
| _glfwLibrary.cursorEnterCallback(window, entered); |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////////// |
| ////// GLFW public API ////// |
| ////////////////////////////////////////////////////////////////////////// |
| |
| //======================================================================== |
| // Returns the specified input mode of the specified window |
| //======================================================================== |
| |
| GLFWAPI int glfwGetInputMode(GLFWwindow handle, int mode) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return 0; |
| } |
| |
| switch (mode) |
| { |
| case GLFW_CURSOR_MODE: |
| return window->cursorMode; |
| case GLFW_STICKY_KEYS: |
| return window->stickyKeys; |
| case GLFW_STICKY_MOUSE_BUTTONS: |
| return window->stickyMouseButtons; |
| case GLFW_SYSTEM_KEYS: |
| return window->systemKeys; |
| case GLFW_KEY_REPEAT: |
| return window->keyRepeat; |
| default: |
| _glfwSetError(GLFW_INVALID_ENUM, NULL); |
| return 0; |
| } |
| } |
| |
| |
| //======================================================================== |
| // Sets the specified input mode of the specified window |
| //======================================================================== |
| |
| GLFWAPI void glfwSetInputMode(GLFWwindow handle, int mode, int value) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| switch (mode) |
| { |
| case GLFW_CURSOR_MODE: |
| setCursorMode(window, value); |
| break; |
| case GLFW_STICKY_KEYS: |
| setStickyKeys(window, value ? GL_TRUE : GL_FALSE); |
| break; |
| case GLFW_STICKY_MOUSE_BUTTONS: |
| setStickyMouseButtons(window, value ? GL_TRUE : GL_FALSE); |
| break; |
| case GLFW_SYSTEM_KEYS: |
| setSystemKeys(window, value ? GL_TRUE : GL_FALSE); |
| break; |
| case GLFW_KEY_REPEAT: |
| setKeyRepeat(window, value ? GL_TRUE : GL_FALSE); |
| break; |
| default: |
| _glfwSetError(GLFW_INVALID_ENUM, NULL); |
| break; |
| } |
| } |
| |
| |
| //======================================================================== |
| // Returns the state of the specified key for the specified window |
| //======================================================================== |
| |
| GLFWAPI int glfwGetKey(GLFWwindow handle, int key) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return GLFW_RELEASE; |
| } |
| |
| if (key < 0 || key > GLFW_KEY_LAST) |
| { |
| _glfwSetError(GLFW_INVALID_ENUM, |
| "glfwGetKey: The specified key is invalid"); |
| return GLFW_RELEASE; |
| } |
| |
| if (window->key[key] == GLFW_STICK) |
| { |
| // Sticky mode: release key now |
| window->key[key] = GLFW_RELEASE; |
| return GLFW_PRESS; |
| } |
| |
| return (int) window->key[key]; |
| } |
| |
| |
| //======================================================================== |
| // Returns the state of the specified mouse button for the specified window |
| //======================================================================== |
| |
| GLFWAPI int glfwGetMouseButton(GLFWwindow handle, int button) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return GLFW_RELEASE; |
| } |
| |
| if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) |
| { |
| _glfwSetError(GLFW_INVALID_ENUM, |
| "glfwGetMouseButton: The specified mouse button is invalid"); |
| return GLFW_RELEASE; |
| } |
| |
| if (window->mouseButton[button] == GLFW_STICK) |
| { |
| // Sticky mode: release mouse button now |
| window->mouseButton[button] = GLFW_RELEASE; |
| return GLFW_PRESS; |
| } |
| |
| return (int) window->mouseButton[button]; |
| } |
| |
| |
| //======================================================================== |
| // Returns the last reported cursor position for the specified window |
| //======================================================================== |
| |
| GLFWAPI void glfwGetCursorPos(GLFWwindow handle, int* xpos, int* ypos) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| if (xpos != NULL) |
| *xpos = window->cursorPosX; |
| |
| if (ypos != NULL) |
| *ypos = window->cursorPosY; |
| } |
| |
| |
| //======================================================================== |
| // Sets the cursor position relative to the position of the client area of |
| // the specified window |
| //======================================================================== |
| |
| GLFWAPI void glfwSetCursorPos(GLFWwindow handle, int xpos, int ypos) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| if (_glfwLibrary.activeWindow != window) |
| { |
| _glfwSetError(GLFW_WINDOW_NOT_ACTIVE, NULL); |
| 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); |
| } |
| |
| |
| //======================================================================== |
| // Returns the scroll offset for the specified window |
| //======================================================================== |
| |
| GLFWAPI void glfwGetScrollOffset(GLFWwindow handle, double* xoffset, double* yoffset) |
| { |
| _GLFWwindow* window = (_GLFWwindow*) handle; |
| |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| if (xoffset) |
| *xoffset = window->scrollX; |
| |
| if (yoffset) |
| *yoffset = window->scrollY; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for keyboard input |
| //======================================================================== |
| |
| GLFWAPI void glfwSetKeyCallback(GLFWkeyfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.keyCallback = cbfun; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for character input |
| //======================================================================== |
| |
| GLFWAPI void glfwSetCharCallback(GLFWcharfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.charCallback = cbfun; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for mouse clicks |
| //======================================================================== |
| |
| GLFWAPI void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.mouseButtonCallback = cbfun; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for mouse moves |
| //======================================================================== |
| |
| GLFWAPI void glfwSetCursorPosCallback(GLFWcursorposfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.cursorPosCallback = cbfun; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for cursor enter/leave events |
| //======================================================================== |
| |
| GLFWAPI void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.cursorEnterCallback = cbfun; |
| } |
| |
| |
| //======================================================================== |
| // Set callback function for scroll events |
| //======================================================================== |
| |
| GLFWAPI void glfwSetScrollCallback(GLFWscrollfun cbfun) |
| { |
| if (!_glfwInitialized) |
| { |
| _glfwSetError(GLFW_NOT_INITIALIZED, NULL); |
| return; |
| } |
| |
| _glfwLibrary.scrollCallback = cbfun; |
| } |
| |