Added character with modifiers callback.

The undefined behaviour changed with #40 has been reverted, making the
character-only callback again behave like a system text field.  This
behavior has now been documentated.

Fixes #203.
Fixes #305.
This commit is contained in:
Camilla Berglund 2014-06-12 23:04:20 +02:00
parent 9b6c14b7ae
commit 96b12ee504
9 changed files with 133 additions and 38 deletions

View File

@ -56,6 +56,7 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- Added `glfwPostEmptyEvent` for allowing secondary threads to cause
`glfwWaitEvents` to return
- Added `empty` test program for verifying posting of empty events
- Added `glfwSetCharModsCallback` for receiving character events with modifiers
- Added `glfwGetWindowFrameSize` for retrieving the size of the frame around
the client area of a window
- Added `GLFW_AUTO_ICONIFY` for controlling whether full screen windows

View File

@ -47,6 +47,14 @@ GLFW not supports floating windows, also called topmost or always on top, for
easier debugging, with the `GLFW_FLOATING` window hint.
@subsection news_31_charmods Character with modifiers callback
GLFW now provides a callback for character events with modifier key bits.
Unlike the regular character callback, this will report character events that
will not result in a character being input, for example if the Control key is
held down.
@subsection news_31_egl Stable EGL support
The support for EGL is now stable, successfully running on PandaBoards, Mesa,

View File

@ -788,6 +788,24 @@ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);
*/
typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
/*! @brief The function signature for Unicode character with modifiers
* callbacks.
*
* This is the function signature for Unicode character with modifiers callback
* functions. It is called for each input character, regardless of what
* modifier keys are held down.
*
* @param[in] window The window that received the event.
* @param[in] codepoint The Unicode code point of the character.
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down.
*
* @sa glfwSetCharModsCallback
*
* @ingroup input
*/
typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
/*! @brief The function signature for file drop callbacks.
*
* This is the function signature for file drop callbacks.
@ -2151,9 +2169,19 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
* This function sets the character callback of the specific window, which is
* called when a Unicode character is input.
*
* The character callback is intended for text input. If you want to know
* whether a specific key was pressed or released, use the
* [key callback](@ref glfwSetKeyCallback) instead.
* The character callback is intended for Unicode text input. As it deals with
* characters, it is keyboard layout dependent, whereas the
* [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1
* to physical keys, as a key may produce zero, one or more characters. If you
* want to know whether a specific physical key was pressed or released, see
* the key callback instead.
*
* The character callback behaves as system text input normally does and will
* not be called if modifier keys are held down that would prevent normal text
* input on that platform, for example a Super (Command) key on OS X or Alt key
* on Windows. There is a
* [character with modifiers callback](@ref glfwSetCharModsCallback) that
* receives these events.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@ -2167,6 +2195,33 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
*/
GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
/*! @brief Sets the Unicode character with modifiers callback.
*
* This function sets the character with modifiers callback of the specific
* window, which is called when a Unicode character is input regardless of what
* modifier keys are used.
*
* The character with modifiers callback is intended for implementing custom
* Unicode character input. For regular Unicode text input, see the
* [character callback](@ref glfwSetCharCallback). Like the character
* callback, the character with modifiers callback deals with characters and is
* keyboard layout dependent. Characters do not map 1:1 to physical keys, as
* a key may produce zero, one or more characters. If you want to know whether
* a specific physical key was pressed or released, see the
* [key callback](@ref glfwSetKeyCallback) instead.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new 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.
*
* @note This function may only be called from the main thread.
*
* @ingroup input
*/
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);
/*! @brief Sets the mouse button callback.
*
* This function sets the mouse button callback of the specified window, which

View File

@ -605,13 +605,15 @@ static int translateKey(unsigned int key)
{
const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
NSString* characters = [event characters];
NSUInteger i, length = [characters length];
const int plain = !(mods & GLFW_MOD_SUPER);
for (i = 0; i < length; i++)
_glfwInputChar(window, [characters characterAtIndex:i]);
_glfwInputChar(window, [characters characterAtIndex:i], mods, plain);
}
- (void)flagsChanged:(NSEvent *)event

View File

@ -153,13 +153,19 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
}
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint)
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, int plain)
{
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
return;
if (window->callbacks.charmods)
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
if (plain)
{
if (window->callbacks.character)
window->callbacks.character((GLFWwindow*) window, codepoint);
}
}
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
@ -439,6 +445,14 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
return cbfun;
}
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
return cbfun;
}
GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
GLFWmousebuttonfun cbfun)
{

View File

@ -262,6 +262,7 @@ struct _GLFWwindow
GLFWscrollfun scroll;
GLFWkeyfun key;
GLFWcharfun character;
GLFWcharmodsfun charmods;
GLFWdropfun drop;
} callbacks;
@ -700,9 +701,12 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
/*! @brief Notifies shared code of a Unicode character input event.
* @param[in] window The window that received the event.
* @param[in] codepoint The Unicode code point of the input character.
* @param[in] mods Bit field describing which modifier keys were held down.
* @param[in] plain `GL_TRUE` if the character is regular text input, or
* `GL_FALSE` otherwise.
* @ingroup event
*/
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint);
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, int plain);
/*! @brief Notifies shared code of a scroll event.
* @param[in] window The window that received the event.

View File

@ -526,9 +526,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
}
case WM_CHAR:
{
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
return 0;
}
case WM_SYSCHAR:
{
_glfwInputChar(window, (unsigned int) wParam);
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_FALSE);
return 0;
}
@ -543,7 +548,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return TRUE;
}
_glfwInputChar(window, (unsigned int) wParam);
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
return FALSE;
}

View File

@ -609,7 +609,10 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
if (character != -1)
_glfwInputChar(window, character);
{
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, character, mods, plain);
}
break;
}

View File

@ -187,9 +187,8 @@ static const char* get_key_name(int key)
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU";
case GLFW_KEY_UNKNOWN: return "UNKNOWN";
default: return NULL;
default: return "UNKNOWN";
}
}
@ -218,15 +217,22 @@ static const char* get_button_name(int button)
return "right";
case GLFW_MOUSE_BUTTON_MIDDLE:
return "middle";
default:
{
static char name[16];
sprintf(name, "%i", button);
return name;
}
}
return NULL;
}
static const char* get_mods_name(int mods)
{
static char name[512];
if (mods == 0)
return " no mods";
name[0] = '\0';
if (mods & GLFW_MOD_SHIFT)
@ -321,18 +327,11 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
Slot* slot = glfwGetWindowUserPointer(window);
const char* name = get_button_name(button);
printf("%08x to %i at %0.3f: Mouse button %i",
counter++, slot->number, glfwGetTime(), button);
if (name)
printf(" (%s)", name);
if (mods)
printf(" (with%s)", get_mods_name(mods));
printf(" was %s\n", get_action_name(action));
printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), button,
get_button_name(button),
get_mods_name(mods),
get_action_name(action));
}
static void cursor_position_callback(GLFWwindow* window, double x, double y)
@ -359,19 +358,13 @@ static void scroll_callback(GLFWwindow* window, double x, double y)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
const char* name = get_key_name(key);
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x",
counter++, slot->number, glfwGetTime(), key, scancode);
if (name)
printf(" (%s)", name);
if (mods)
printf(" (with%s)", get_mods_name(mods));
printf(" was %s\n", get_action_name(action));
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key),
get_mods_name(mods),
get_action_name(action));
if (action != GLFW_PRESS)
return;
@ -396,6 +389,15 @@ static void char_callback(GLFWwindow* window, unsigned int codepoint)
get_character_string(codepoint));
}
static void char_mods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Character 0x%08x (%s) (with%s) input\n",
counter++, slot->number, glfwGetTime(), codepoint,
get_character_string(codepoint),
get_mods_name(mods));
}
static void drop_callback(GLFWwindow* window, int count, const char** names)
{
int i;
@ -546,6 +548,7 @@ int main(int argc, char** argv)
glfwSetScrollCallback(slots[i].window, scroll_callback);
glfwSetKeyCallback(slots[i].window, key_callback);
glfwSetCharCallback(slots[i].window, char_callback);
glfwSetCharModsCallback(slots[i].window, char_mods_callback);
glfwSetDropCallback(slots[i].window, drop_callback);
glfwMakeContextCurrent(slots[i].window);