diff --git a/README.md b/README.md index 174bbe832..b65b9afe0 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ skills. - Cameron King - Peter Knut - Eric Larson + - Quinten Lansu - Robin Leffmann - Glenn Lewis - Shane Liesegang diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9a7ca1764..1b83e04f7 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -638,6 +638,7 @@ extern "C" { #define GLFW_CURSOR 0x00033001 #define GLFW_STICKY_KEYS 0x00033002 #define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 +#define GLFW_TOUCH 0x00030004 #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 @@ -961,6 +962,27 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); +/*! @brief The function signature for touch start/end callbacks. + * @param[in] window The window that received the event. + * @param[in] touch The touch that started or ended. + * @param[in] action One of @ref GLFW_PRESS or @ref GLFW_RELEASE. + * @ingroup input + * + * @sa glfwSetTouchCallback + */ +typedef void (* GLFWtouchfun)(GLFWwindow*,int,int); + +/*! @brief The function signature for touch position callbacks. + * @param[in] window The window that received the event. + * @param[in] touch The touch that moved. + * @param[in] xpos The new x-coordinate of the touch. + * @param[in] ypos The new y-coordinate of the touch. + * @ingroup input + * + * @sa glfwSetTouchPosCallback + */ +typedef void (* GLFWtouchposfun)(GLFWwindow*,int,double,double); + /*! @brief The function signature for monitor configuration callbacks. * * This is the function signature for monitor configuration callback functions. @@ -2947,6 +2969,36 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb */ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun); +/*! @brief Sets the touch start/end callback. + * + * This function sets the touch callback, which is called when a touch is + * started or ended. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently + * set callback. + * @return The previously set callback, or `NULL` if no callback was set or an + * error occurred. + * + * @ingroup input + */ +GLFWAPI GLFWtouchfun glfwSetTouchCallback(GLFWwindow* window, GLFWtouchfun cbfun); + +/*! @brief Sets the touch position callback. + * + * This function sets the touch position callback, which is called when a touch + * moves. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently + * set callback. + * @return The previously set callback, or `NULL` if no callback was set or an + * error occurred. + * + * @ingroup input + */ +GLFWAPI GLFWtouchposfun glfwSetTouchPosCallback(GLFWwindow* window, GLFWtouchposfun cbfun); + /*! @brief Returns whether the specified joystick is present. * * This function returns whether the specified joystick is present. diff --git a/src/cocoa_window.m b/src/cocoa_window.m index fbd73bc8f..3b3d84a2a 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1147,6 +1147,10 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) *ypos = contentRect.size.height - pos.y - 1; } +void _glfwPlatformSetTouchInput(_GLFWwindow* window, int enabled) +{ +} + void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) { updateModeCursor(window); diff --git a/src/input.c b/src/input.c index e899e715d..3eb82155c 100644 --- a/src/input.c +++ b/src/input.c @@ -126,6 +126,18 @@ static void setStickyMouseButtons(_GLFWwindow* window, int enabled) window->stickyMouseButtons = enabled; } +// Set touch input for the specified window +// +static void setTouchInput(_GLFWwindow* window, int enabled) +{ + if (window->touchInput == enabled) + return; + + _glfwPlatformSetTouchInput(window, enabled); + + window->touchInput = enabled; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// @@ -222,6 +234,18 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) window->callbacks.drop((GLFWwindow*) window, count, paths); } +void _glfwInputTouch(_GLFWwindow* window, int touch, int action) +{ + if (window->callbacks.touch) + window->callbacks.touch((GLFWwindow*) window, touch, action); +} + +void _glfwInputTouchPos(_GLFWwindow* window, int touch, double xpos, double ypos) +{ + if (window->callbacks.touchPos) + window->callbacks.touchPos((GLFWwindow*) window, touch, xpos, ypos); +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// @@ -241,6 +265,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) return window->stickyKeys; case GLFW_STICKY_MOUSE_BUTTONS: return window->stickyMouseButtons; + case GLFW_TOUCH: + return window->touchInput; default: _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode"); return 0; @@ -264,6 +290,9 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) case GLFW_STICKY_MOUSE_BUTTONS: setStickyMouseButtons(window, value ? GL_TRUE : GL_FALSE); break; + case GLFW_TOUCH: + setTouchInput(window, value ? GL_TRUE : GL_FALSE); + break; default: _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode"); break; @@ -579,6 +608,22 @@ GLFWAPI const char* glfwGetJoystickName(int joy) return _glfwPlatformGetJoystickName(joy); } +GLFWAPI GLFWtouchfun glfwSetTouchCallback(GLFWwindow* handle, GLFWtouchfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(window->callbacks.touch, cbfun); + return cbfun; +} + +GLFWAPI GLFWtouchposfun glfwSetTouchPosCallback(GLFWwindow* handle, GLFWtouchposfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(window->callbacks.touchPos, cbfun); + return cbfun; +} + GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/internal.h b/src/internal.h index c2fac3c5b..ef7cb4303 100644 --- a/src/internal.h +++ b/src/internal.h @@ -244,6 +244,7 @@ struct _GLFWwindow GLboolean stickyKeys; GLboolean stickyMouseButtons; double cursorPosX, cursorPosY; + GLboolean touchInput; int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1]; @@ -278,6 +279,8 @@ struct _GLFWwindow GLFWcharfun character; GLFWcharmodsfun charmods; GLFWdropfun drop; + GLFWtouchfun touch; + GLFWtouchposfun touchPos; } callbacks; // This is defined in the window API's platform.h @@ -395,6 +398,14 @@ void _glfwPlatformTerminate(void); */ const char* _glfwPlatformGetVersionString(void); +/*! @brief Sets whether touch input is enabled for the specified window. + * @param[in] window The window whose touch input status to change. + * @param[in] enabled @c GL_TRUE to enable touch input, or @c GL_FALSE to + * disable it. + * @ingroup platform + */ +void _glfwPlatformSetTouchInput(_GLFWwindow* window, int enabled); + /*! @copydoc glfwGetCursorPos * @ingroup platform */ @@ -753,6 +764,23 @@ void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y); */ void _glfwInputCursorEnter(_GLFWwindow* window, int entered); +/*! @brief Notifies shared code of a touch start/end event. + * @param[in] window The window that received the event. + * @param[in] touch The touch that started or ended. + * @param[in] action One of @c GLFW_PRESS or @c GLFW_RELEASE. + * @ingroup event + */ +void _glfwInputTouch(_GLFWwindow* window, int touch, int action); + +/*! @brief Notifies shared code of a touch movement event. + * @param[in] window The window that received the event. + * @param[in] touch The touch that moved. + * @param[in] xpos The new x-coordinate of the touch. + * @param[in] ypos The new y-coordinate of the touch. + * @ingroup event + */ +void _glfwInputTouchPos(_GLFWwindow* window, int touch, double xpos, double ypos); + /*! @ingroup event */ void _glfwInputMonitorChange(void); diff --git a/src/win32_window.c b/src/win32_window.c old mode 100644 new mode 100755 index d120ebf07..df3ae6d5e --- a/src/win32_window.c +++ b/src/win32_window.c @@ -522,6 +522,55 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return 0; } + case WM_TOUCH: + { + TOUCHINPUT* inputs; + UINT count = LOWORD(wParam); + + inputs = (TOUCHINPUT*) malloc(sizeof(TOUCHINPUT) * count); + + if (GetTouchInputInfo((HTOUCHINPUT) lParam, + count, inputs, sizeof(TOUCHINPUT))) + { + int i, width, height; + + _glfwPlatformGetWindowSize(window, &width, &height); + + for (i = 0; i < count; i++) + { + POINT pos; + + // Discard any points that lie outside of the client area + + pos.x = TOUCH_COORD_TO_PIXEL(inputs[i].x); + pos.y = TOUCH_COORD_TO_PIXEL(inputs[i].y); + ScreenToClient(window->win32.handle, &pos); + + if (pos.x < 0 || pos.x >= width || + pos.y < 0 || pos.y >= height) + { + continue; + } + + if (inputs[i].dwFlags & TOUCHEVENTF_DOWN) + _glfwInputTouch(window, (int) inputs[i].dwID, GLFW_PRESS); + else if (inputs[i].dwFlags & TOUCHEVENTF_UP) + _glfwInputTouch(window, (int) inputs[i].dwID, GLFW_RELEASE); + else if (inputs[i].dwFlags & TOUCHEVENTF_MOVE) + { + _glfwInputTouchPos(window, (int) inputs[i].dwID, + inputs[i].x / 100.0, + inputs[i].y / 100.0); + } + } + + CloseTouchInputHandle((HTOUCHINPUT) lParam); + } + + free(inputs); + break; + } + case WM_PAINT: { _glfwInputWindowDamage(window); @@ -1044,6 +1093,14 @@ void _glfwPlatformPostEmptyEvent(void) PostMessage(window->win32.handle, WM_NULL, 0, 0); } +void _glfwPlatformSetTouchInput(_GLFWwindow* window, int enabled) +{ + if (enabled) + RegisterTouchWindow(window->win32.handle, 0); + else + UnregisterTouchWindow(window->win32.handle); +} + void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) { POINT pos; diff --git a/src/x11_window.c b/src/x11_window.c index 33e517082..33ceff8d3 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1756,6 +1756,10 @@ void _glfwPlatformPostEmptyEvent(void) XFlush(_glfw.x11.display); } +void _glfwPlatformSetTouchInput(_GLFWwindow* window, int enabled) +{ +} + void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) { Window root, child; diff --git a/tests/events.c b/tests/events.c index f40576d46..f545c325d 100644 --- a/tests/events.c +++ b/tests/events.c @@ -437,6 +437,16 @@ static void monitor_callback(GLFWmonitor* monitor, int event) } } +static void touch_callback(GLFWwindow* window, int touch, int action, double x, double y) +{ + printf("%08x at %0.3f: Touch %i %s at %0.3f %0.3f\n", + counter++, + glfwGetTime(), + touch, + get_action_name(action), + x, y); +} + int main(int argc, char** argv) { Slot* slots; @@ -550,6 +560,7 @@ int main(int argc, char** argv) glfwSetCharCallback(slots[i].window, char_callback); glfwSetCharModsCallback(slots[i].window, char_mods_callback); glfwSetDropCallback(slots[i].window, drop_callback); + glfwSetTouchCallback(slots[i].window, touch_callback); glfwMakeContextCurrent(slots[i].window); glfwSwapInterval(1);