Generate unshifted Unicode key codes in wxEVT_KEY_XXX events in wxGTK.

wxGTK generated wxEVT_KEY_XXX with key codes corresponding to the unshifted
state of the key (except for the letters) but Unicode key codes corresponding
to the current shift state. This was inconsistent with wxMSW and also with the
idea that key events, unlike char ones, don't depend on the modifiers states.

Change wxGTK to behave as wxMSW and use unshifted values for Unicode key codes
as well.

Remove the now unnecessary workaround for different key event Unicode codes
from test.

Also try to explain the difference between normal and Unicode keys and key and
char events even better and mention that the Unicode key codes for the key
events are also untranslated in the documentation.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65526 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-09-11 10:19:07 +00:00
parent 5844ad30dd
commit 7333c0ef82
3 changed files with 88 additions and 66 deletions

View File

@@ -1181,49 +1181,81 @@ enum wxKeyCategoryFlags
This event class contains information about key press and release events. This event class contains information about key press and release events.
Notice that there are three different kinds of keyboard events in wxWidgets: The main information carried by this event is the key being pressed or
key down and up events and char events. The difference between the first two released. It can be accessed using either GetKeyCode() function or
is clear - the first corresponds to a key press and the second to a key GetUnicodeKey(). For the printable characters, the latter should be used as
release - otherwise they are identical. Just note that if the key is it works for any keys, including non-Latin-1 characters that can be entered
maintained in a pressed state you will typically get a lot of (automatically when using national keyboard layouts. GetKeyCode() should be used to handle
generated) down events but only one up so it is wrong to assume that there is special characters (such as cursor arrows keys or @c HOME or @c INS and so
one up event corresponding to each down one. on) which correspond to ::wxKeyCode enum elements above the @c WXK_START
constant. While GetKeyCode() also returns the character code for Latin-1
keys for compatibility, it doesn't work for Unicode characters in general
and will return @c WXK_NONE for any non-Latin-1 ones. For this reason, it's
recommended to always use GetUnicodeKey() and only fall back to GetKeyCode()
if GetUnicodeKey() returned @c WXK_NONE meaning that the event corresponds
to a non-printable special keys.
Both key down and up events provide untranslated key codes while the char While both of these functions can be used with the events of @c
event carries the translated one. The untranslated code for alphanumeric wxEVT_KEY_DOWN, @c wxEVT_KEY_UP and @c wxEVT_CHAR types, the values
keys is always an upper case value. For the other keys it is one of @c returned by them are different for the first two events and the last one.
WXK_XXX values from the ::wxKeyCode enumeration. The translated key is, in For the latter, the key returned corresponds to the character that would
general, the character the user expects to appear as the result of the key appear in e.g. a text zone if the user pressed the key in it. As such, its
combination when typing the text into a text entry zone, for example. value depends on the current state of the Shift key and, for the letters,
on the state of Caps Lock modifier. For example, if @c A key is pressed
without Shift being held down, wxKeyEvent of type @c wxEVT_CHAR generated
for this key press will return (from either GetKeyCode() or GetUnicodeKey()
as their meanings coincide for ASCII characters) key code of 97
corresponding the ASCII value of @c a. And if the same key is pressed but
with Shift being held (or Caps Lock being active), then the key could would
be 65, i.e. ASCII value of capital @c A.
A few examples to clarify this (all assume that CAPS LOCK is unpressed However for the key down and up events the returned key code will instead
and the standard US keyboard): when the @c 'A' key is pressed, the key down be @c A independently of the state of the modifier keys i.e. it depends
event key code is equal to @c ASCII A == 65. But the char event key code only on physical key being pressed and is not translated to its logical
is @c ASCII a == 97. On the other hand, if you press both SHIFT and representation using the current keyboard state. Such untranslated key
@c 'A' keys simultaneously , the key code in key down event will still be codes are defined as follows:
just @c 'A' while the char event key code parameter will now be @c 'A' - For the letters they correspond to the @e upper case value of the
as well. letter.
- For the other alphanumeric keys (e.g. @c 7 or @c +), the untranslated
key code corresponds to the character produced by the key when it is
pressed without Shift. E.g. in standard US keyboard layout the
untranslated key code for the key @c =/+ in the upper right corner of
the keyboard is 61 which is the ASCII value of @c =.
- For the rest of the keys (i.e. special non-printable keys) it is the
same as the normal key code as no translation is used anyhow.
Although in this simple case it is clear that the correct key code could be Notice that the first rule applies to all Unicode letters, not just the
found in the key down event handler by checking the value returned by usual Latin-1 ones. However for non-Latin-1 letters only GetUnicodeKey()
wxKeyEvent::ShiftDown(), in general you should use @c EVT_CHAR if you need can be used to retrieve the key code as GetKeyCode() just returns @c
the translated key as for non-alphanumeric keys the translation is WXK_NONE in this case.
keyboard-layout dependent and can only be done properly by the system
itself.
Another kind of translation is done when the control key is pressed: for To summarize: you should handle @c wxEVT_CHAR if you need the translated
example, for CTRL-A key press the key down event still carries the key and @c wxEVT_KEY_DOWN if you only need the value of the key itself,
same key code @c 'a' as usual but the char event will have key code of 1, independent of the current keyboard state.
the ASCII value of this key combination.
Notice that while pressing any key will generate a key down event (except @note Not all key down events may be generated by the user. As an example,
in presence of IME perhaps) a few special keys don't generate a char event: @c wxEVT_KEY_DOWN with @c = key code can be generated using the
currently, Shift, Control (or Command), Alt (or Menu or Meta) and Caps, Num standard US keyboard layout but not using the German one because the @c
and Scroll Lock keys don't do it. For all the other keys you have the = key corresponds to Shift-0 key combination in this layout and the key
choice about whether to choose key down or char event for handling it and code for it is @c 0, not @c =. Because of this you should avoid
either can be used. However it is advised to use char events only for the requiring your users to type key events that might be impossible to
keys that are supposed to generate characters on screen and key down events enter on their keyboard.
for all the rest.
Another difference between key and char events is that another kind of
translation is done for the latter ones when the Control key is pressed:
char events for ASCII letters in this case carry codes corresponding to the
ASCII value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until
26 for Ctrl-Z. This is convenient for terminal-like applications and can be
completely ignored by all the other ones (if you need to handle Ctrl-A it
is probably a better idea to use the key event rather than the char one).
Notice that currently no translation is done for the presses of @c [, @c
\\, @c ], @c ^ and @c _ keys which might be mapped to ASCII values from 27
to 31.
Finally, modifier keys only generate key events but no char events at all.
The modifiers keys are @c WXK_SHIFT, @c WXK_CONTROL, @c WXK_ALT and various
@c WXK_WINDOWS_XXX from ::wxKeyCode enum.
You may discover how the other keys on your system behave interactively by You may discover how the other keys on your system behave interactively by

View File

@@ -686,16 +686,6 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0; event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0;
event.m_rawCode = (wxUint32) gdk_event->keyval; event.m_rawCode = (wxUint32) gdk_event->keyval;
event.m_rawFlags = 0; event.m_rawFlags = 0;
#if wxUSE_UNICODE
event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
if ( !event.m_uniChar && event.m_keyCode <= WXK_DELETE )
{
// Set Unicode key code to the ASCII equivalent for compatibility. E.g.
// let RETURN generate the key event with both key and Unicode key
// codes of 13.
event.m_uniChar = event.m_keyCode;
}
#endif // wxUSE_UNICODE
wxGetMousePosition( &x, &y ); wxGetMousePosition( &x, &y );
win->ScreenToClient( &x, &y ); win->ScreenToClient( &x, &y );
event.m_x = x; event.m_x = x;
@@ -800,6 +790,17 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
event.m_keyCode = key_code; event.m_keyCode = key_code;
#if wxUSE_UNICODE
event.m_uniChar = gdk_keyval_to_unicode(key_code ? key_code : keysym);
if ( !event.m_uniChar && event.m_keyCode <= WXK_DELETE )
{
// Set Unicode key code to the ASCII equivalent for compatibility. E.g.
// let RETURN generate the key event with both key and Unicode key
// codes of 13.
event.m_uniChar = event.m_keyCode;
}
#endif // wxUSE_UNICODE
// now fill all the other fields // now fill all the other fields
wxFillOtherKeyEventFields(event, win, gdk_event); wxFillOtherKeyEventFields(event, win, gdk_event);

View File

@@ -188,27 +188,16 @@ void TestEvent(int line, const wxKeyEvent& ev, const KeyDesc& desc)
ev.GetKeyCode() ); ev.GetKeyCode() );
#if wxUSE_UNICODE #if wxUSE_UNICODE
if ( desc.m_keycode < 0x80 ) if ( desc.m_keycode < WXK_START )
{ {
// FIXME: Currently wxMSW generates 'A' key code for key down/up events // For Latin-1 our key code is the same as Unicode character value.
// for the 'a' physical key while wxGTK and wxOSX/Cocoa generate them CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong Unicode key in " + msg,
// with 'a' and it's not clear which behaviour is more correct so don't (char)desc.m_keycode,
// test this for those events, only test it for EVT_CHAR where the (char)ev.GetUnicodeKey() );
// correct behaviour is clear.
if ( t == wxEVT_CHAR )
{
// For 7-bit ASCII Unicode keys are the same as normal key codes.
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong Unicode key in " + msg,
(char)desc.m_keycode,
(char)ev.GetUnicodeKey() );
}
} }
else else // Special key
{ {
// In this test we don't use any really Unicode characters so far so // Key codes above WXK_START don't correspond to printable characters.
// anything above 0x80 must be special keys (e.g. WXK_CONTROL &c) which
// don't have any Unicode equivalent.
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong non-zero Unicode key in " + msg, CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong non-zero Unicode key in " + msg,
0, 0,
(int)ev.GetUnicodeKey() ); (int)ev.GetUnicodeKey() );