Added a conservative set of key modifiers.

This commit is contained in:
Camilla Berglund 2012-12-09 19:19:00 +01:00
parent 7f2eb7b15b
commit 2d1b835711
24 changed files with 238 additions and 96 deletions

View File

@ -309,6 +309,7 @@ GLFW.
* Added `GLFW_VISIBLE` window hint and parameter for controlling and polling * Added `GLFW_VISIBLE` window hint and parameter for controlling and polling
window visibility window visibility
* Added `GLFW_REPEAT` key action for repeated keys * 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 `windows` simple multi-window test program
* Added `sharing` simple OpenGL object sharing test program * Added `sharing` simple OpenGL object sharing test program
* Added `modes` video mode enumeration and setting test program * Added `modes` video mode enumeration and setting test program

View File

@ -43,7 +43,7 @@
void init( void ); void init( void );
void display( void ); void display( void );
void reshape( GLFWwindow* window, int w, int h ); 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 DrawBoingBall( void );
void BounceBall( double dt ); void BounceBall( double dt );
void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi ); 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 */ 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) if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE); glfwSetWindowShouldClose(window, GL_TRUE);

View File

@ -211,13 +211,13 @@ static void animate(void)
/* change view angle, exit upon ESC */ /* 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; if( action != GLFW_PRESS ) return;
switch (k) { switch (k) {
case GLFW_KEY_Z: case GLFW_KEY_Z:
if( glfwGetKey( window, GLFW_KEY_LEFT_SHIFT ) ) if( mods & GLFW_MOD_SHIFT )
view_rotz -= 5.0; view_rotz -= 5.0;
else else
view_rotz += 5.0; view_rotz += 5.0;

View File

@ -477,7 +477,7 @@ static void update_mesh(void)
* GLFW callback functions * 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) switch(key)
{ {

View File

@ -414,7 +414,7 @@ static void cursorPosFun(GLFWwindow* window, double x, double y)
// Mouse button callback function // 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) 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; 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) if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE); glfwSetWindowShouldClose(window, GL_TRUE);

View File

@ -270,7 +270,7 @@ static void error_callback(int error, const char* description)
// Handle key strokes // 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) if (action != GLFW_PRESS)
return; return;
@ -313,7 +313,7 @@ void key_callback(GLFWwindow* window, int key, int action)
// Callback function for mouse button events // 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) if (button != GLFW_MOUSE_BUTTON_LEFT)
return; return;

View File

@ -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 /*! @defgroup buttons Mouse buttons
* @ingroup input * @ingroup input
* @{ */ * @{ */
@ -669,12 +684,13 @@ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
* @param[in] button The [mouse button](@ref buttons) that was pressed or * @param[in] button The [mouse button](@ref buttons) that was pressed or
* released. * released.
* @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
* @param[in] mods Bit field describing which modifier keys were held down.
* *
* @sa glfwSetMouseButtonCallback * @sa glfwSetMouseButtonCallback
* *
* @ingroup input * @ingroup input
*/ */
typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int); typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
/*! @brief The function signature for cursor position callbacks. /*! @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] window The window that received the event.
* @param[in] key The [keyboard key](@ref keys) that was pressed or released. * @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] 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 * @sa glfwSetKeyCallback
* *
* @ingroup input * @ingroup input
*/ */
typedef void (* GLFWkeyfun)(GLFWwindow*,int,int); typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int);
/*! @brief The function signature for Unicode character callbacks. /*! @brief The function signature for Unicode character callbacks.
* *

View File

@ -201,6 +201,22 @@ static void centerCursor(_GLFWwindow *window)
@end @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 // Converts a Mac OS X keycode to a GLFW keycode
// //
static int convertMacKeyCode(unsigned int macKeyCode) static int convertMacKeyCode(unsigned int macKeyCode)
@ -413,7 +429,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)mouseDown:(NSEvent *)event - (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 - (void)mouseDragged:(NSEvent *)event
@ -423,7 +442,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)mouseUp:(NSEvent *)event - (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 - (void)mouseMoved:(NSEvent *)event
@ -442,7 +464,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)rightMouseDown:(NSEvent *)event - (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 - (void)rightMouseDragged:(NSEvent *)event
@ -452,12 +477,18 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)rightMouseUp:(NSEvent *)event - (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 - (void)otherMouseDown:(NSEvent *)event
{ {
_glfwInputMouseClick(window, [event buttonNumber], GLFW_PRESS); _glfwInputMouseClick(window,
[event buttonNumber],
GLFW_PRESS,
convertKeyMods([event modifierFlags]));
} }
- (void)otherMouseDragged:(NSEvent *)event - (void)otherMouseDragged:(NSEvent *)event
@ -467,7 +498,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)otherMouseUp:(NSEvent *)event - (void)otherMouseUp:(NSEvent *)event
{ {
_glfwInputMouseClick(window, [event buttonNumber], GLFW_RELEASE); _glfwInputMouseClick(window,
[event buttonNumber],
GLFW_RELEASE,
convertKeyMods([event modifierFlags]));
} }
- (void)mouseExited:(NSEvent *)event - (void)mouseExited:(NSEvent *)event
@ -503,7 +537,12 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)keyDown:(NSEvent *)event - (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) if ([event modifierFlags] & NSCommandKeyMask)
return; return;
@ -530,12 +569,15 @@ static int convertMacKeyCode(unsigned int macKeyCode)
key = convertMacKeyCode([event keyCode]); key = convertMacKeyCode([event keyCode]);
if (key != -1) if (key != -1)
_glfwInputKey(window, key, action); _glfwInputKey(window, key, action, convertKeyMods([event modifierFlags]));
} }
- (void)keyUp:(NSEvent *)event - (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 - (void)scrollWheel:(NSEvent *)event

View File

@ -122,7 +122,7 @@ static void setStickyMouseButtons(_GLFWwindow* window, int enabled)
////// GLFW event API ////// ////// 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; GLboolean repeated = GL_FALSE;
@ -141,7 +141,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int action)
action = GLFW_REPEAT; action = GLFW_REPEAT;
if (window->callbacks.key) 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) 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); 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) if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return; return;
@ -174,7 +174,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action)
window->mouseButton[button] = (char) action; window->mouseButton[button] = (char) action;
if (window->callbacks.mouseButton) 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) void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y)

View File

@ -591,9 +591,10 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window);
* @param[in] window The window that received the event. * @param[in] window The window that received the event.
* @param[in] key The key that was pressed or released. * @param[in] key The key that was pressed or released.
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE. * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
* @param[in] mods The modifiers pressed when the event was generated.
* @ingroup event * @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. /*! @brief Notifies shared code of a Unicode character input event.
* @param[in] window The window that received the 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. * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
* @ingroup event * @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. /*! @brief Notifies shared code of a cursor motion event.
* @param[in] window The window that received the event. * @param[in] window The window that received the event.

View File

@ -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 // Translates a Windows key to the corresponding GLFW key
// //
static int translateKey(WPARAM wParam, LPARAM lParam) static int translateKey(WPARAM wParam, LPARAM lParam)
@ -433,7 +465,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
{ {
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS); _glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS, getKeyMods());
break; break;
} }
@ -461,20 +493,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP: case WM_SYSKEYUP:
{ {
const int mods = getKeyMods();
if (wParam == VK_SHIFT) if (wParam == VK_SHIFT)
{ {
// Special trick: release both shift keys on SHIFT up event // Special trick: release both shift keys on SHIFT up event
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE); _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE, mods);
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE); _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE, mods);
} }
else if (wParam == VK_SNAPSHOT) else if (wParam == VK_SNAPSHOT)
{ {
// Key down is not reported for the print screen key // 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_PRESS, mods);
_glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE); _glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE, mods);
} }
else else
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE); _glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE, getKeyMods());
break; break;
} }
@ -484,20 +518,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
case WM_XBUTTONDOWN: case WM_XBUTTONDOWN:
{ {
const int mods = getKeyMods();
SetCapture(hWnd); SetCapture(hWnd);
if (uMsg == WM_LBUTTONDOWN) 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) 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) else if (uMsg == WM_MBUTTONDOWN)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
else else
{ {
if (HIWORD(wParam) == XBUTTON1) 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) else if (HIWORD(wParam) == XBUTTON2)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods);
return TRUE; return TRUE;
} }
@ -510,20 +546,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MBUTTONUP: case WM_MBUTTONUP:
case WM_XBUTTONUP: case WM_XBUTTONUP:
{ {
const int mods = getKeyMods();
ReleaseCapture(); ReleaseCapture();
if (uMsg == WM_LBUTTONUP) 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) 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) else if (uMsg == WM_MBUTTONUP)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods);
else else
{ {
if (HIWORD(wParam) == XBUTTON1) 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) else if (HIWORD(wParam) == XBUTTON2)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods);
return TRUE; return TRUE;
} }
@ -1017,19 +1055,19 @@ void _glfwPlatformPollEvents(void)
// This is the only async event handling in GLFW, but it solves some // This is the only async event handling in GLFW, but it solves some
// nasty problems // nasty problems
{ {
int lshiftDown, rshiftDown; const int mods = getAsyncKeyMods();
// Get current state of left and right shift keys // Get current state of left and right shift keys
lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1; const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1; const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
// See if this differs from our belief of what has happened // See if this differs from our belief of what has happened
// (we only have to check for lost key up events) // (we only have to check for lost key up events)
if (!lshiftDown && window->key[GLFW_KEY_LEFT_SHIFT] == 1) 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) 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 // Did the cursor move in an focused window that has captured the cursor

View File

@ -77,14 +77,14 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
for (i = 0; i <= GLFW_KEY_LAST; i++) for (i = 0; i <= GLFW_KEY_LAST; i++)
{ {
if (window->key[i] == GLFW_PRESS) if (window->key[i] == GLFW_PRESS)
_glfwInputKey(window, i, GLFW_RELEASE); _glfwInputKey(window, i, GLFW_RELEASE, 0);
} }
// Release all pressed mouse buttons // Release all pressed mouse buttons
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
{ {
if (window->mouseButton[i] == GLFW_PRESS) if (window->mouseButton[i] == GLFW_PRESS)
_glfwInputMouseClick(window, i, GLFW_RELEASE); _glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
} }
} }
} }

View File

@ -58,6 +58,22 @@ typedef struct
#define MWM_HINTS_DECORATIONS (1L << 1) #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 // Translates an X Window key to internal coding
// //
static int translateKey(int keycode) static int translateKey(int keycode)
@ -511,31 +527,36 @@ static void processEvent(XEvent *event)
{ {
case KeyPress: 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) && _glfwInputKey(window, key, GLFW_PRESS, mods);
!(event->xkey.state & Mod1Mask /*Alt*/))
{ if (!(mods & GLFW_MOD_CTRL) && !(mods & GLFW_MOD_ALT))
_glfwInputChar(window, translateChar(&event->xkey)); _glfwInputChar(window, translateChar(&event->xkey));
}
break; break;
} }
case KeyRelease: 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; break;
} }
case ButtonPress: case ButtonPress:
{ {
const int mods = translateState(event->xbutton.state);
if (event->xbutton.button == Button1) 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) 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) 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 // Modern X provides scroll events as mouse button presses
else if (event->xbutton.button == Button4) else if (event->xbutton.button == Button4)
@ -552,23 +573,28 @@ static void processEvent(XEvent *event)
case ButtonRelease: case ButtonRelease:
{ {
const int mods = translateState(event->xbutton.state);
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
{ {
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_LEFT,
GLFW_RELEASE); GLFW_RELEASE,
mods);
} }
else if (event->xbutton.button == Button2) else if (event->xbutton.button == Button2)
{ {
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_MIDDLE, GLFW_MOUSE_BUTTON_MIDDLE,
GLFW_RELEASE); GLFW_RELEASE,
mods);
} }
else if (event->xbutton.button == Button3) else if (event->xbutton.button == Button3)
{ {
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_RIGHT,
GLFW_RELEASE); GLFW_RELEASE,
mods);
} }
break; break;
} }

View File

@ -74,7 +74,7 @@ static void cursor_position_callback(GLFWwindow* window, double x, double y)
cursor_y = 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) if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
set_swap_interval(window, 1 - swap_interval); set_swap_interval(window, 1 - swap_interval);

View File

@ -39,18 +39,12 @@ static void usage(void)
printf("Usage: clipboard [-h]\n"); 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) static void error_callback(int error, const char* description)
{ {
fprintf(stderr, "Error: %s\n", 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) if (action != GLFW_PRESS)
return; return;
@ -62,7 +56,7 @@ static void key_callback(GLFWwindow* window, int key, int action)
break; break;
case GLFW_KEY_V: case GLFW_KEY_V:
if (control_is_down(window)) if (mods == GLFW_MOD_CTRL)
{ {
const char* string; const char* string;
@ -75,7 +69,7 @@ static void key_callback(GLFWwindow* window, int key, int action)
break; break;
case GLFW_KEY_C: case GLFW_KEY_C:
if (control_is_down(window)) if (mods == GLFW_MOD_CTRL)
{ {
const char* string = "Hello GLFW World!"; const char* string = "Hello GLFW World!";
glfwSetClipboardString(window, string); glfwSetClipboardString(window, string);

View File

@ -36,6 +36,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h>
#include <locale.h> #include <locale.h>
// These must match the input mode defaults // These must match the input mode defaults
@ -206,6 +207,22 @@ static const char* get_button_name(int button)
return NULL; 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) static const char* get_character_string(int character)
{ {
// This assumes UTF-8, which is stupid // This assumes UTF-8, which is stupid
@ -278,15 +295,18 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
iconified ? "iconified" : "restored"); 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); const char* name = get_button_name(button);
printf("%08x at %0.3f: Mouse button %i", counter++, glfwGetTime(), button); printf("%08x at %0.3f: Mouse button %i", counter++, glfwGetTime(), button);
if (name) if (name)
printf(" (%s) was %s\n", name, get_action_name(action)); printf(" (%s)", name);
else
if (mods)
printf(" (with%s)", get_mods_name(mods));
printf(" was %s\n", get_action_name(action)); printf(" was %s\n", get_action_name(action));
} }
@ -308,15 +328,18 @@ 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); 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); const char* name = get_key_name(key);
printf("%08x at %0.3f: Key 0x%04x", counter++, glfwGetTime(), key); printf("%08x at %0.3f: Key 0x%04x", counter++, glfwGetTime(), key);
if (name) if (name)
printf(" (%s) was %s\n", name, get_action_name(action)); printf(" (%s)", name);
else
if (mods)
printf(" (with%s)", get_mods_name(mods));
printf(" was %s\n", get_action_name(action)); printf(" was %s\n", get_action_name(action));
if (action != GLFW_PRESS) if (action != GLFW_PRESS)

View File

@ -48,7 +48,7 @@ static void window_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, 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) if (action != GLFW_PRESS)
return; return;

View File

@ -60,7 +60,7 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", 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) if (action != GLFW_PRESS)
return; return;

View File

@ -45,7 +45,7 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", 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", printf("%0.2f Key %s\n",
glfwGetTime(), glfwGetTime(),

View File

@ -73,7 +73,7 @@ static void window_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, 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) if (key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GL_TRUE); glfwSetWindowShouldClose(window, GL_TRUE);

View File

@ -65,7 +65,7 @@ static void cursor_position_callback(GLFWwindow* window, double x, double y)
cursor_y = 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) switch (key)
{ {

View File

@ -53,7 +53,7 @@ static void window_close_callback(GLFWwindow* window)
printf("Close callback triggered\n"); 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) if (action != GLFW_PRESS)
return; return;

View File

@ -44,7 +44,7 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", 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) if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GL_TRUE); glfwSetWindowShouldClose(window, GL_TRUE);

View File

@ -64,7 +64,7 @@ static void window_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, 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) if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
set_swap_interval(window, 1 - swap_interval); set_swap_interval(window, 1 - swap_interval);