mirror of
https://github.com/gwm17/glfw.git
synced 2025-06-14 22:58:50 -04:00
Scroll events do not represent an absolute state, but rather an interpretation of a relative change in state, like character input. So, like character input, there is no sane 'current state' to return. The here removed solution, that of accumulating an offset since the last call to event processing, is at best mildly confusing. If a user wishes to implement this solution, it is better for it to be explicit in client code than implicit in GLFW calls.
448 lines
12 KiB
C
448 lines
12 KiB
C
//========================================================================
|
|
// 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 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);
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// 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;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////// GLFW event API //////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
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
|
|
{
|
|
if (action == GLFW_PRESS && window->key[key] == GLFW_PRESS)
|
|
repeated = GL_TRUE;
|
|
|
|
window->key[key] = (char) action;
|
|
}
|
|
|
|
// Call user callback function
|
|
if (window->callbacks.key && !repeated)
|
|
window->callbacks.key((GLFWwindow*) window, key, action);
|
|
}
|
|
|
|
void _glfwInputChar(_GLFWwindow* window, int character)
|
|
{
|
|
// Valid Unicode (ISO 10646) character?
|
|
if (!((character >= 32 && character <= 126) || character >= 160))
|
|
return;
|
|
|
|
if (window->callbacks.character)
|
|
window->callbacks.character((GLFWwindow*) window, character);
|
|
}
|
|
|
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
|
{
|
|
if (window->callbacks.scroll)
|
|
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
|
}
|
|
|
|
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 (window->callbacks.mouseButton)
|
|
window->callbacks.mouseButton((GLFWwindow*) window, button, action);
|
|
}
|
|
|
|
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 (window->callbacks.cursorPos)
|
|
{
|
|
window->callbacks.cursorPos((GLFWwindow*) window,
|
|
window->cursorPosX,
|
|
window->cursorPosY);
|
|
}
|
|
}
|
|
|
|
void _glfwInputCursorEnter(_GLFWwindow* window, int entered)
|
|
{
|
|
if (window->callbacks.cursorEnter)
|
|
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////// GLFW public API //////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(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;
|
|
default:
|
|
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(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;
|
|
default:
|
|
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return GLFW_RELEASE;
|
|
}
|
|
|
|
if (key < 0 || key > GLFW_KEY_LAST)
|
|
{
|
|
_glfwInputError(GLFW_INVALID_ENUM, "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];
|
|
}
|
|
|
|
GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return GLFW_RELEASE;
|
|
}
|
|
|
|
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
|
{
|
|
_glfwInputError(GLFW_INVALID_ENUM,
|
|
"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];
|
|
}
|
|
|
|
GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, int* xpos, int* ypos)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
if (xpos != NULL)
|
|
*xpos = window->cursorPosX;
|
|
|
|
if (ypos != NULL)
|
|
*ypos = window->cursorPosY;
|
|
}
|
|
|
|
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, int xpos, int ypos)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
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 in locked cursor mode
|
|
if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
|
return;
|
|
|
|
// Update physical cursor position
|
|
_glfwPlatformSetCursorPos(window, xpos, ypos);
|
|
}
|
|
|
|
GLFWAPI void glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.key = cbfun;
|
|
}
|
|
|
|
GLFWAPI void glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.character = cbfun;
|
|
}
|
|
|
|
GLFWAPI void glfwSetMouseButtonCallback(GLFWwindow* handle, GLFWmousebuttonfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.mouseButton = cbfun;
|
|
}
|
|
|
|
GLFWAPI void glfwSetCursorPosCallback(GLFWwindow* handle, GLFWcursorposfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.cursorPos = cbfun;
|
|
}
|
|
|
|
GLFWAPI void glfwSetCursorEnterCallback(GLFWwindow* handle, GLFWcursorenterfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.cursorEnter = cbfun;
|
|
}
|
|
|
|
GLFWAPI void glfwSetScrollCallback(GLFWwindow* handle, GLFWscrollfun cbfun)
|
|
{
|
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
|
|
if (!_glfwInitialized)
|
|
{
|
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL);
|
|
return;
|
|
}
|
|
|
|
window->callbacks.scroll = cbfun;
|
|
}
|
|
|