It's a general recommendation. If only letter keys were concerned,
using
Fl::event_key() could probably
be used. But you don't know which key the user will press, do you?
Or if your users use international keyboards (unlikely if your app
is not public; is it?).
For other keys on the keyboard
Fl::event_key()
is not clearly defined (i.e. not documented) whereas the text
produced by the key is. Unfortunately there's really no
documentation, and it's definitely not uniform across platforms -
and there may be real bugs in the library (although nothing can be
called a bug if there's no definition of what it *should* return,
it's just undefined behavior). This has all been much easier when
FLTK was developed and used in the US with US keyboards only, and
particularly before UTF-8 was introduced in FLTK.
The documentation on Fl::event_key() is pretty vague but it says (at
least):
"The returned integer 'key code' is not necessarily a text
equivalent for the keystroke. For instance: if someone presses
'5' on the numeric keypad with numlock on, Fl::event_key()
may return the 'key code' for this key, and NOT the character
'5'. To always get the '5', use Fl::event_text()
instead."
https://www.fltk.org/doc-1.4/group__fl__events.html#ga1ac131e3cd5ca674cc022b1f77233449
According to this existing documentation alone it's sensible not to
use
Fl::event_key() for "text"
processing at all.
Matthias and I discussed that we want to improve the keyboard
handling (documentation and behavior) in FLTK 1.5. Before we can
make event key handling really cross-platform we need to define -
and document - the rules, particularly for international keyboards.
If your program is only for people living in the US (and speaking
English) you
*may* not be concerned, but even the UK
keyboard differs from the US keyboard.
As an example, take a look at the output of
test/handle_keys.cxx
(another test program) below. I switched my German (DE) keyboard to
different keyboard layouts (US, UK, and French) just as an example.
For all sequences I pressed and held Shift and then all number keys
(1, 2, ..., 9, 0). Note how ambiguous the columns of
Fl::event_key() aka 'Key' and 'Name' are,
compared to the 'Text', 'Unicode', and 'UTF-8' columns):
--- DE ---
[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex
[ 14] FL_KEYDOWN 0xffe2 FL_Shift_R . . . . . . ''
[ 15] FL_KEYDOWN 0x0031 '1' . . S . . . '!' U+0021 21
[ 16] FL_KEYDOWN 0x0032 '2' . . S . . . '"' U+0022 22
[ 17] FL_KEYDOWN 0x0033 '3' . . S . . . '§' U+00a7 c2 a7
[ 18] FL_KEYDOWN 0x0034 '4' . . S . . . '$' U+0024 24
[ 19] FL_KEYDOWN 0x0035 '5' . . S . . . '%' U+0025 25
[ 20] FL_KEYDOWN 0x0036 '6' . . S . . . '&' U+0026 26
[ 21] FL_KEYDOWN 0x0037 '7' . . S . . . '/' U+002f 2f
[ 22] FL_KEYDOWN 0x0038 '8' . . S . . . '(' U+0028 28
[ 23] FL_KEYDOWN 0x0039 '9' . . S . . . ')' U+0029 29
[ 24] FL_KEYDOWN 0x0030 '0' . . S . . . '=' U+003d 3d
--- US ---
[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex
[ 28] FL_KEYDOWN 0xffe2 FL_Shift_R . . . . . . ''
[ 29] FL_KEYDOWN 0x0031 '1' . . S . . . '!' U+0021 21
[ 30] FL_KEYDOWN 0x0032 '2' . . S . . . '@' U+0040 40
[ 31] FL_KEYDOWN 0x0033 '3' . . S . . . '#' U+0023 23
[ 32] FL_KEYDOWN 0x0034 '4' . . S . . . '$' U+0024 24
[ 33] FL_KEYDOWN 0x0035 '5' . . S . . . '%' U+0025 25
[ 34] FL_KEYDOWN 0x0036 '6' . . S . . . '^' U+005e 5e
[ 35] FL_KEYDOWN 0x0037 '7' . . S . . . '&' U+0026 26
[ 36] FL_KEYDOWN 0x0038 '8' . . S . . . '*' U+002a 2a
[ 37] FL_KEYDOWN 0x0039 '9' . . S . . . '(' U+0028 28
[ 38] FL_KEYDOWN 0x0030 '0' . . S . . . ')' U+0029 29
--- UK ---
[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex
[ 41] FL_KEYDOWN 0xffe2 FL_Shift_R . . . . . . ''
[ 44] FL_KEYDOWN 0x0031 '1' . . S . . . '!' U+0021 21
[ 45] FL_KEYDOWN 0x0032 '2' . . S . . . '"' U+0022 22
[ 46] FL_KEYDOWN 0x0033 '3' . . S . . . '£' U+00a3 c2 a3
[ 47] FL_KEYDOWN 0x0034 '4' . . S . . . '$' U+0024 24
[ 48] FL_KEYDOWN 0x0035 '5' . . S . . . '%' U+0025 25
[ 49] FL_KEYDOWN 0x0036 '6' . . S . . . '^' U+005e 5e
[ 50] FL_KEYDOWN 0x0037 '7' . . S . . . '&' U+0026 26
[ 51] FL_KEYDOWN 0x0038 '8' . . S . . . '*' U+002a 2a
[ 52] FL_KEYDOWN 0x0039 '9' . . S . . . '(' U+0028 28
[ 53] FL_KEYDOWN 0x0030 '0' . . S . . . ')' U+0029 29
--- FR ---
[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex
[ 56] FL_KEYDOWN 0xffe2 FL_Shift_R . . . . . . ''
[ 57] FL_KEYDOWN 0x0031 '1' . . S . . . '1' U+0031 31
[ 58] FL_KEYDOWN 0x0032 '2' . . S . . . '2' U+0032 32
[ 59] FL_KEYDOWN 0x0033 '3' . . S . . . '3' U+0033 33
[ 60] FL_KEYDOWN 0x0034 '4' . . S . . . '4' U+0034 34
[ 61] FL_KEYDOWN 0x0035 '5' . . S . . . '5' U+0035 35
[ 62] FL_KEYDOWN 0x0036 '6' . . S . . . '6' U+0036 36
[ 63] FL_KEYDOWN 0x0037 '7' . . S . . . '7' U+0037 37
[ 64] FL_KEYDOWN 0x0038 '8' . . S . . . '8' U+0038 38
[ 65] FL_KEYDOWN 0x0039 '9' . . S . . . '9' U+0039 39
[ 66] FL_KEYDOWN 0x0030 '0' . . S . . . '0' U+0030 30
You can also see that the French keyboard has the number keys in the
upper position - hence all the numbers in Fl::event_text() - whereas
the other keyboards have special characters in the shifted position.
Note also that Shift-3 issues non-ASCII values in Fl::event_text()
on some keyboards.
That all said, you may get away with Fl::event_key() in your case,
but using Fl::event_text() would make things cleaner and less
error-prone (if you think of later program changes).
BTW, regarding Fl::event_key() on macOS and other platforms: I
tested macOS, Windows (MinGW cross-compiled), Linux (X11) and Linux
(Wayland), and on all tested platforms I could see that
Fl::event_key() contains the lowercase value of the letter key
that's pressed, like this output from macOS shows:
[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex
[ 1] FL_KEYDOWN 0x0061 'a' . . . . . . 'a' U+0061 61
[ 2] FL_KEYDOWN 0xffe2 FL_Shift_R . . S . . . ''
[ 3] FL_KEYDOWN 0x0061 'a' . . S . . . 'A' U+0041 41
After these tests I wonder why you (Rob) struggled with the
upper/lower key value, and why Gonzalo recommended to use tolower().
That shouldn't be necessary...
Final note: it is well-known that programs on some Windows platforms
(Visual Studio either in Release or Debug mode) may crash (with an
assert()) if you feed tolower() with a value > 127 which can
potentially happen if non-ASCII keys are pressed by the user and you
use the suggested code:
Note: I didn't test this particularly, but that's what I remember,
and I suggest not to use this code w/o checking that
`key < 128` is true.
Appendix: French keyboard layout as known on Linux:
If you wonder why there are four symbols on some keys: there's
another "shift" key ("Level 3") - on German keyboards it's called
"alt gr" (alternate graphics symbol IIRC) - that switches the keys
to the symbol on the right side (both with and w/o shift). Note that
the French/Switzerland keyboard is different! Getting it right on
all platforms and for all international keyboards is not trivial.