diff --git a/README.md b/README.md index 853f7ad5..28b6ec37 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,7 @@ GLFW. * Added `GLFW_VISIBLE` window hint and parameter for controlling and polling window visibility * Added `GLFW_REPEAT` key action for repeated keys + * Added key modifier parameter to key and mouse button callbacks * Added `windows` simple multi-window test program * Added `sharing` simple OpenGL object sharing test program * Added `modes` video mode enumeration and setting test program diff --git a/examples/boing.c b/examples/boing.c index 4518f1e6..29ffb3a7 100644 --- a/examples/boing.c +++ b/examples/boing.c @@ -43,7 +43,7 @@ void init( void ); void display( void ); void reshape( GLFWwindow* window, int w, int h ); -void key_callback( GLFWwindow* window, int key, int action ); +void key_callback( GLFWwindow* window, int key, int action, int mods ); void DrawBoingBall( void ); void BounceBall( double dt ); void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi ); @@ -245,7 +245,7 @@ void reshape( GLFWwindow* window, int w, int h ) 0.0, -1.0, 0.0 ); /* up vector */ } -void key_callback( GLFWwindow* window, int key, int action ) +void key_callback( GLFWwindow* window, int key, int action, int mods ) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); diff --git a/examples/gears.c b/examples/gears.c index 52ed41e2..1e5b1973 100644 --- a/examples/gears.c +++ b/examples/gears.c @@ -211,13 +211,13 @@ static void animate(void) /* change view angle, exit upon ESC */ -void key( GLFWwindow* window, int k, int action ) +void key( GLFWwindow* window, int k, int action, int mods ) { if( action != GLFW_PRESS ) return; switch (k) { case GLFW_KEY_Z: - if( glfwGetKey( window, GLFW_KEY_LEFT_SHIFT ) ) + if( mods & GLFW_MOD_SHIFT ) view_rotz -= 5.0; else view_rotz += 5.0; diff --git a/examples/heightmap.c b/examples/heightmap.c index 3e141b94..c98828d4 100644 --- a/examples/heightmap.c +++ b/examples/heightmap.c @@ -477,7 +477,7 @@ static void update_mesh(void) * GLFW callback functions *********************************************************************/ -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { switch(key) { diff --git a/examples/splitview.c b/examples/splitview.c index ea2c7eac..c09e7090 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -414,7 +414,7 @@ static void cursorPosFun(GLFWwindow* window, double x, double y) // Mouse button callback function //======================================================================== -static void mouseButtonFun(GLFWwindow* window, int button, int action) +static void mouseButtonFun(GLFWwindow* window, int button, int action, int mods) { if ((button == GLFW_MOUSE_BUTTON_LEFT) && action == GLFW_PRESS) { @@ -434,7 +434,7 @@ static void mouseButtonFun(GLFWwindow* window, int button, int action) do_redraw = 1; } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); diff --git a/examples/wave.c b/examples/wave.c index fc1ca0db..c7ab57ab 100644 --- a/examples/wave.c +++ b/examples/wave.c @@ -270,7 +270,7 @@ static void error_callback(int error, const char* description) // Handle key strokes //======================================================================== -void key_callback(GLFWwindow* window, int key, int action) +void key_callback(GLFWwindow* window, int key, int action, int mods) { if (action != GLFW_PRESS) return; @@ -313,7 +313,7 @@ void key_callback(GLFWwindow* window, int key, int action) // Callback function for mouse button events //======================================================================== -void mouse_button_callback(GLFWwindow* window, int button, int action) +void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { if (button != GLFW_MOUSE_BUTTON_LEFT) return; diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index aba6a049..a1451e3d 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -407,6 +407,21 @@ extern "C" { /*! @} */ +/*! @name keys Modifier key flags + * @{ */ + +/*! @ingroup input + */ +#define GLFW_MOD_SHIFT 0x0001 +/*! @ingroup input + */ +#define GLFW_MOD_CTRL 0x0002 +/*! @ingroup input + */ +#define GLFW_MOD_ALT 0x0004 + +/*! @} */ + /*! @defgroup buttons Mouse buttons * @ingroup input * @{ */ @@ -669,12 +684,13 @@ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); * @param[in] button The [mouse button](@ref buttons) that was pressed or * released. * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. + * @param[in] mods Bit field describing which modifier keys were held down. * * @sa glfwSetMouseButtonCallback * * @ingroup input */ -typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int); +typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); /*! @brief The function signature for cursor position callbacks. * @@ -725,12 +741,13 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); * @param[in] window The window that received the event. * @param[in] key The [keyboard key](@ref keys) that was pressed or released. * @param[in] action @ref GLFW_PRESS, @ref GLFW_RELEASE or @ref GLFW_REPEAT. + * @param[in] mods Bit field describing which modifier keys were held down. * * @sa glfwSetKeyCallback * * @ingroup input */ -typedef void (* GLFWkeyfun)(GLFWwindow*,int,int); +typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int); /*! @brief The function signature for Unicode character callbacks. * diff --git a/src/cocoa_window.m b/src/cocoa_window.m index fcc3c267..09634b1e 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -201,6 +201,22 @@ static void centerCursor(_GLFWwindow *window) @end +// Converts Mac OS X key modifiers into GLFW ones +// +static int convertKeyMods(NSUInteger flags) +{ + int mods = 0; + + if (flags & NSShiftKeyMask) + mods |= GLFW_MOD_SHIFT; + if (flags & NSControlKeyMask) + mods |= GLFW_MOD_CTRL; + if (flags & NSAlternateKeyMask) + mods |= GLFW_MOD_ALT; + + return mods; +} + // Converts a Mac OS X keycode to a GLFW keycode // static int convertMacKeyCode(unsigned int macKeyCode) @@ -413,7 +429,10 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)mouseDown:(NSEvent *)event { - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_LEFT, + GLFW_PRESS, + convertKeyMods([event modifierFlags])); } - (void)mouseDragged:(NSEvent *)event @@ -423,7 +442,10 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)mouseUp:(NSEvent *)event { - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_LEFT, + GLFW_RELEASE, + convertKeyMods([event modifierFlags])); } - (void)mouseMoved:(NSEvent *)event @@ -442,7 +464,10 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)rightMouseDown:(NSEvent *)event { - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS); + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_RIGHT, + GLFW_PRESS, + convertKeyMods([event modifierFlags])); } - (void)rightMouseDragged:(NSEvent *)event @@ -452,12 +477,18 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)rightMouseUp:(NSEvent *)event { - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE); + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_RIGHT, + GLFW_RELEASE, + convertKeyMods([event modifierFlags])); } - (void)otherMouseDown:(NSEvent *)event { - _glfwInputMouseClick(window, [event buttonNumber], GLFW_PRESS); + _glfwInputMouseClick(window, + [event buttonNumber], + GLFW_PRESS, + convertKeyMods([event modifierFlags])); } - (void)otherMouseDragged:(NSEvent *)event @@ -467,7 +498,10 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)otherMouseUp:(NSEvent *)event { - _glfwInputMouseClick(window, [event buttonNumber], GLFW_RELEASE); + _glfwInputMouseClick(window, + [event buttonNumber], + GLFW_RELEASE, + convertKeyMods([event modifierFlags])); } - (void)mouseExited:(NSEvent *)event @@ -503,7 +537,12 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)keyDown:(NSEvent *)event { - _glfwInputKey(window, convertMacKeyCode([event keyCode]), GLFW_PRESS); + const NSUInteger mods = [event modifierFlags]; + + _glfwInputKey(window, + convertMacKeyCode([event keyCode]), + GLFW_PRESS, + convertKeyMods(mods)); if ([event modifierFlags] & NSCommandKeyMask) return; @@ -530,12 +569,15 @@ static int convertMacKeyCode(unsigned int macKeyCode) key = convertMacKeyCode([event keyCode]); if (key != -1) - _glfwInputKey(window, key, action); + _glfwInputKey(window, key, action, convertKeyMods([event modifierFlags])); } - (void)keyUp:(NSEvent *)event { - _glfwInputKey(window, convertMacKeyCode([event keyCode]), GLFW_RELEASE); + _glfwInputKey(window, + convertMacKeyCode([event keyCode]), + GLFW_RELEASE, + convertKeyMods([event modifierFlags])); } - (void)scrollWheel:(NSEvent *)event diff --git a/src/input.c b/src/input.c index c350efb9..88cb3449 100644 --- a/src/input.c +++ b/src/input.c @@ -122,7 +122,7 @@ static void setStickyMouseButtons(_GLFWwindow* window, int enabled) ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwInputKey(_GLFWwindow* window, int key, int action) +void _glfwInputKey(_GLFWwindow* window, int key, int action, int mods) { GLboolean repeated = GL_FALSE; @@ -141,7 +141,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int action) action = GLFW_REPEAT; if (window->callbacks.key) - window->callbacks.key((GLFWwindow*) window, key, action); + window->callbacks.key((GLFWwindow*) window, key, action, mods); } void _glfwInputChar(_GLFWwindow* window, unsigned int character) @@ -162,7 +162,7 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); } -void _glfwInputMouseClick(_GLFWwindow* window, int button, int action) +void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) { if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) return; @@ -174,7 +174,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action) window->mouseButton[button] = (char) action; if (window->callbacks.mouseButton) - window->callbacks.mouseButton((GLFWwindow*) window, button, action); + window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); } void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y) diff --git a/src/internal.h b/src/internal.h index 80c8e388..6cb6cf18 100644 --- a/src/internal.h +++ b/src/internal.h @@ -591,9 +591,10 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window); * @param[in] window The window that received the event. * @param[in] key The key that was pressed or released. * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE. + * @param[in] mods The modifiers pressed when the event was generated. * @ingroup event */ -void _glfwInputKey(_GLFWwindow* window, int key, int action); +void _glfwInputKey(_GLFWwindow* window, int key, int action, int mods); /*! @brief Notifies shared code of a Unicode character input event. * @param[in] window The window that received the event. @@ -616,7 +617,7 @@ void _glfwInputScroll(_GLFWwindow* window, double x, double y); * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE. * @ingroup event */ -void _glfwInputMouseClick(_GLFWwindow* window, int button, int action); +void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); /*! @brief Notifies shared code of a cursor motion event. * @param[in] window The window that received the event. diff --git a/src/win32_window.c b/src/win32_window.c index 45111ab4..1b81ce9e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -104,6 +104,38 @@ static void showCursor(_GLFWwindow* window) } } +// Retrieves and translates modifier keys +// +static int getKeyMods(void) +{ + int mods = 0; + + if (GetKeyState(VK_SHIFT) & (1 << 31)) + mods |= GLFW_MOD_SHIFT; + if (GetKeyState(VK_CONTROL) & (1 << 31)) + mods |= GLFW_MOD_CTRL; + if (GetKeyState(VK_MENU) & (1 << 31)) + mods |= GLFW_MOD_ALT; + + return mods; +} + +// Retrieves and translates modifier keys +// +static int getAsyncKeyMods(void) +{ + int mods = 0; + + if (GetAsyncKeyState(VK_SHIFT) & (1 << 31)) + mods |= GLFW_MOD_SHIFT; + if (GetAsyncKeyState(VK_CONTROL) & (1 << 31)) + mods |= GLFW_MOD_CTRL; + if (GetAsyncKeyState(VK_MENU) & (1 << 31)) + mods |= GLFW_MOD_ALT; + + return mods; +} + // Translates a Windows key to the corresponding GLFW key // static int translateKey(WPARAM wParam, LPARAM lParam) @@ -433,7 +465,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_KEYDOWN: case WM_SYSKEYDOWN: { - _glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS); + _glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS, getKeyMods()); break; } @@ -461,20 +493,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_KEYUP: case WM_SYSKEYUP: { + const int mods = getKeyMods(); + if (wParam == VK_SHIFT) { // Special trick: release both shift keys on SHIFT up event - _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE); - _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE); + _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE, mods); + _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE, mods); } else if (wParam == VK_SNAPSHOT) { // Key down is not reported for the print screen key - _glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_PRESS); - _glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE); + _glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_PRESS, mods); + _glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE, mods); } else - _glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE); + _glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE, getKeyMods()); break; } @@ -484,20 +518,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: { + const int mods = getKeyMods(); + SetCapture(hWnd); if (uMsg == WM_LBUTTONDOWN) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); else if (uMsg == WM_RBUTTONDOWN) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); else if (uMsg == WM_MBUTTONDOWN) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); else { if (HIWORD(wParam) == XBUTTON1) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS, mods); else if (HIWORD(wParam) == XBUTTON2) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods); return TRUE; } @@ -510,20 +546,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MBUTTONUP: case WM_XBUTTONUP: { + const int mods = getKeyMods(); + ReleaseCapture(); if (uMsg == WM_LBUTTONUP) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods); else if (uMsg == WM_RBUTTONUP) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods); else if (uMsg == WM_MBUTTONUP) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods); else { if (HIWORD(wParam) == XBUTTON1) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE, mods); else if (HIWORD(wParam) == XBUTTON2) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods); return TRUE; } @@ -1017,19 +1055,19 @@ void _glfwPlatformPollEvents(void) // This is the only async event handling in GLFW, but it solves some // nasty problems { - int lshiftDown, rshiftDown; + const int mods = getAsyncKeyMods(); // Get current state of left and right shift keys - lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1; - rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1; + 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->key[GLFW_KEY_LEFT_SHIFT] == 1) - _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE); + _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE, mods); if (!rshiftDown && window->key[GLFW_KEY_RIGHT_SHIFT] == 1) - _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE); + _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE, mods); } // Did the cursor move in an focused window that has captured the cursor diff --git a/src/window.c b/src/window.c index 008501bb..4da35a0a 100644 --- a/src/window.c +++ b/src/window.c @@ -77,14 +77,14 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused) for (i = 0; i <= GLFW_KEY_LAST; i++) { if (window->key[i] == GLFW_PRESS) - _glfwInputKey(window, i, GLFW_RELEASE); + _glfwInputKey(window, i, GLFW_RELEASE, 0); } // Release all pressed mouse buttons for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { if (window->mouseButton[i] == GLFW_PRESS) - _glfwInputMouseClick(window, i, GLFW_RELEASE); + _glfwInputMouseClick(window, i, GLFW_RELEASE, 0); } } } diff --git a/src/x11_window.c b/src/x11_window.c index efe33f83..9365d863 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -58,6 +58,22 @@ typedef struct #define MWM_HINTS_DECORATIONS (1L << 1) +// Translates an X event modifier state mask +// +int translateState(int state) +{ + int mods = 0; + + if (state & ShiftMask) + mods |= GLFW_MOD_SHIFT; + if (state & ControlMask) + mods |= GLFW_MOD_CTRL; + if (state & Mod1Mask) + mods |= GLFW_MOD_ALT; + + return mods; +} + // Translates an X Window key to internal coding // static int translateKey(int keycode) @@ -511,31 +527,36 @@ static void processEvent(XEvent *event) { case KeyPress: { - _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_PRESS); + const int key = translateKey(event->xkey.keycode); + const int mods = translateState(event->xkey.state); - if (!(event->xkey.state & ControlMask) && - !(event->xkey.state & Mod1Mask /*Alt*/)) - { - _glfwInputChar(window, translateChar(&event->xkey)); - } + _glfwInputKey(window, key, GLFW_PRESS, mods); + + if (!(mods & GLFW_MOD_CTRL) && !(mods & GLFW_MOD_ALT)) + _glfwInputChar(window, translateChar(&event->xkey)); break; } case KeyRelease: { - _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_RELEASE); + const int key = translateKey(event->xkey.keycode); + const int mods = translateState(event->xkey.state); + + _glfwInputKey(window, key, GLFW_RELEASE, mods); break; } case ButtonPress: { + const int mods = translateState(event->xbutton.state); + if (event->xbutton.button == Button1) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); else if (event->xbutton.button == Button2) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); else if (event->xbutton.button == Button3) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS); + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); // Modern X provides scroll events as mouse button presses else if (event->xbutton.button == Button4) @@ -552,23 +573,28 @@ static void processEvent(XEvent *event) case ButtonRelease: { + const int mods = translateState(event->xbutton.state); + if (event->xbutton.button == Button1) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, - GLFW_RELEASE); + GLFW_RELEASE, + mods); } else if (event->xbutton.button == Button2) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, - GLFW_RELEASE); + GLFW_RELEASE, + mods); } else if (event->xbutton.button == Button3) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, - GLFW_RELEASE); + GLFW_RELEASE, + mods); } break; } diff --git a/tests/accuracy.c b/tests/accuracy.c index caefb474..0d046034 100644 --- a/tests/accuracy.c +++ b/tests/accuracy.c @@ -74,7 +74,7 @@ static void cursor_position_callback(GLFWwindow* window, double x, double y) cursor_y = y; } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) set_swap_interval(window, 1 - swap_interval); diff --git a/tests/clipboard.c b/tests/clipboard.c index 12903d2c..9b0a112b 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -39,18 +39,12 @@ static void usage(void) printf("Usage: clipboard [-h]\n"); } -static GLboolean control_is_down(GLFWwindow* window) -{ - return glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) || - glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL); -} - static void error_callback(int error, const char* description) { fprintf(stderr, "Error: %s\n", description); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (action != GLFW_PRESS) return; @@ -62,7 +56,7 @@ static void key_callback(GLFWwindow* window, int key, int action) break; case GLFW_KEY_V: - if (control_is_down(window)) + if (mods == GLFW_MOD_CTRL) { const char* string; @@ -75,7 +69,7 @@ static void key_callback(GLFWwindow* window, int key, int action) break; case GLFW_KEY_C: - if (control_is_down(window)) + if (mods == GLFW_MOD_CTRL) { const char* string = "Hello GLFW World!"; glfwSetClipboardString(window, string); diff --git a/tests/events.c b/tests/events.c index 768ed93d..aa27530a 100644 --- a/tests/events.c +++ b/tests/events.c @@ -36,6 +36,7 @@ #include #include #include +#include #include // These must match the input mode defaults @@ -206,6 +207,22 @@ static const char* get_button_name(int button) return NULL; } +static const char* get_mods_name(int mods) +{ + static char name[512]; + + name[0] = '\0'; + + if (mods & GLFW_MOD_SHIFT) + strcat(name, " shift"); + if (mods & GLFW_MOD_CTRL) + strcat(name, " control"); + if (mods & GLFW_MOD_ALT) + strcat(name, " alt"); + + return name; +} + static const char* get_character_string(int character) { // This assumes UTF-8, which is stupid @@ -278,16 +295,19 @@ static void window_iconify_callback(GLFWwindow* window, int iconified) iconified ? "iconified" : "restored"); } -static void mouse_button_callback(GLFWwindow* window, int button, int action) +static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { const char* name = get_button_name(button); printf("%08x at %0.3f: Mouse button %i", counter++, glfwGetTime(), button); if (name) - printf(" (%s) was %s\n", name, get_action_name(action)); - else - printf(" was %s\n", get_action_name(action)); + printf(" (%s)", name); + + if (mods) + printf(" (with%s)", get_mods_name(mods)); + + printf(" was %s\n", get_action_name(action)); } static void cursor_position_callback(GLFWwindow* window, double x, double y) @@ -308,16 +328,19 @@ static void scroll_callback(GLFWwindow* window, double x, double y) printf("%08x at %0.3f: Scroll: %0.3f %0.3f\n", counter++, glfwGetTime(), x, y); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { const char* name = get_key_name(key); printf("%08x at %0.3f: Key 0x%04x", counter++, glfwGetTime(), key); if (name) - printf(" (%s) was %s\n", name, get_action_name(action)); - else - printf(" was %s\n", get_action_name(action)); + printf(" (%s)", name); + + if (mods) + printf(" (with%s)", get_mods_name(mods)); + + printf(" was %s\n", get_action_name(action)); if (action != GLFW_PRESS) return; diff --git a/tests/fsaa.c b/tests/fsaa.c index 530b6c37..e7025886 100644 --- a/tests/fsaa.c +++ b/tests/fsaa.c @@ -48,17 +48,17 @@ static void window_size_callback(GLFWwindow* window, int width, int height) glViewport(0, 0, width, height); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { - if (action != GLFW_PRESS) - return; + if (action != GLFW_PRESS) + return; - switch (key) - { - case GLFW_KEY_SPACE: - glfwSetTime(0.0); - break; - } + switch (key) + { + case GLFW_KEY_SPACE: + glfwSetTime(0.0); + break; + } } static void usage(void) diff --git a/tests/gamma.c b/tests/gamma.c index 582b8594..6a2cda5f 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -60,7 +60,7 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (action != GLFW_PRESS) return; diff --git a/tests/iconify.c b/tests/iconify.c index 907ae13b..68b28523 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -45,7 +45,7 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { printf("%0.2f Key %s\n", glfwGetTime(), diff --git a/tests/modes.c b/tests/modes.c index 4e083d02..17d9fa0e 100644 --- a/tests/modes.c +++ b/tests/modes.c @@ -73,7 +73,7 @@ static void window_size_callback(GLFWwindow* window, int width, int height) glViewport(0, 0, width, height); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE); diff --git a/tests/peter.c b/tests/peter.c index 4bee8218..1dd87691 100644 --- a/tests/peter.c +++ b/tests/peter.c @@ -65,7 +65,7 @@ static void cursor_position_callback(GLFWwindow* window, double x, double y) cursor_y = y; } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { switch (key) { diff --git a/tests/reopen.c b/tests/reopen.c index 86f3c7fd..527f87a3 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -53,7 +53,7 @@ static void window_close_callback(GLFWwindow* window) printf("Close callback triggered\n"); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (action != GLFW_PRESS) return; diff --git a/tests/sharing.c b/tests/sharing.c index 656ce093..198003ab 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -44,7 +44,7 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE); diff --git a/tests/tearing.c b/tests/tearing.c index 8d46e63b..963ee612 100644 --- a/tests/tearing.c +++ b/tests/tearing.c @@ -64,7 +64,7 @@ static void window_size_callback(GLFWwindow* window, int width, int height) glViewport(0, 0, width, height); } -static void key_callback(GLFWwindow* window, int key, int action) +static void key_callback(GLFWwindow* window, int key, int action, int mods) { if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) set_swap_interval(window, 1 - swap_interval);