Key-mouse combined event on Mac

19 views
Skip to first unread message

Rob McDonald

unread,
Aug 8, 2025, 8:04:08 PMAug 8
to fltk.general
In my program, I allow holding down a key while click-and-dragging the mouse to change what happens.  This is interacting with a 3D environment.

For example:
left-button drag -- rotate
shift lb-drag -- select a region box
alt lb-drag -- pan
ctrl lb-drag -- zoom

To do this, I first check Fl::event_button1() and then check Fl::event_alt(), Fl::event_shift(), etc.

This all works fine and has worked for years.

Recently, we tried to add a new combination -- where you press Z while dragging.  We check for this with Fl::event_key('z') or Fl::get_key('z') (I've tried both).

This works fine on Windows, but it does not trigger on MacOS.

Is there something special you have to do to get a normal keypress & mouse drag combination to work on MacOS?

Rob


Gonzalo Garramuño

unread,
Aug 8, 2025, 8:08:11 PMAug 8
to fltkg...@googlegroups.com

El 8/8/25 a las 21:04, Rob McDonald escribió:
>
> Is there something special you have to do to get a normal keypress &
> mouse drag combination to work on MacOS?

It is likely a bug, returning uppercase keys, so try:

unsigned key = Fl::event_key();
key = tolower(key);  // not utf-8 safe, but oh well...
if (key == 'z')
{

}

That seems to work for me on all platforms.

--
ggar...@gmail.com

Rob McDonald

unread,
Aug 8, 2025, 9:27:22 PMAug 8
to fltk.general
Interesting, that does help.

Thanks!

Rob

 

Albrecht Schlosser

unread,
Aug 8, 2025, 9:55:10 PMAug 8
to fltkg...@googlegroups.com
On 8/9/25 02:04 Rob McDonald wrote:
> In my program, I allow holding down a key while click-and-dragging the
> mouse to change what happens.  This is interacting with a 3D environment.
>
> ...
>
> Recently, we tried to add a new combination -- where you press Z while
> dragging.  We check for this with Fl::event_key('z')
> or Fl::get_key('z') (I've tried both).
>
> This works fine on Windows, but it does not trigger on MacOS.
>
> Is there something special you have to do to get a normal keypress &
> mouse drag combination to work on MacOS?

Despite what others wrote, it's generally a bad idea to use
Fl::event_key() if you want to read and interpret text. Please use
Fl::event_text() instead. Fl::event_key() is appropriate if you want to
test function keys and other special (e.g. media) keys.

Note also that one keypress can deliver more than one byte of text, for
instance if you press the '€' key on an international keyboard like my
German one, that's three bytes (in UTF-8 encoding).

If you need to check only ASCII characters (as in your example 'z') then
you can safely test Fl::event_text()[0] when handling a keypress
(FL_KEYBOARD event). You can still get uppercase letters, but only if
the user also presses the Shift key.

Hint: see test/handle_events.cxx for basic event handling, including
text. Lowercase letters will be output as "text: " whereas everything
else will display "ignored".

PS: I tested this also /successfully/ on macOS, pressing keys while
dragging.

Rob McDonald

unread,
Aug 8, 2025, 11:58:52 PMAug 8
to fltk.general
On Friday, August 8, 2025 at 6:55:10 PM UTC-7 Albrecht-S wrote:
On 8/9/25 02:04 Rob McDonald wrote:
Despite what others wrote, it's generally a bad idea to use
Fl::event_key() if you want to read and interpret text. Please use
Fl::event_text() instead. Fl::event_key() is appropriate if you want to
test function keys and other special (e.g. media) keys.

Is this recommendation based mainly on UTF-8 concerns?  Or is there something else I'm missing?

In this case, am specifically only interested in 'single' keypresses, not strings of text -- so event_key naively appears to be the right choice. 

Rob 

Albrecht Schlosser

unread,
Aug 9, 2025, 8:44:39 AMAug 9
to fltkg...@googlegroups.com
On 8/9/25 05:58 Rob McDonald wrote:
On Friday, August 8, 2025 at 6:55:10 PM UTC-7 Albrecht-S wrote:
... it's generally a bad idea to use Fl::event_key() if you want to read and interpret

text. Please use Fl::event_text() instead. Fl::event_key() is appropriate if you want
to test function keys and other special (e.g. media) keys.

Is this recommendation based mainly on UTF-8 concerns?  Or is there something else I'm missing?

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.


In this case, am specifically only interested in 'single' keypresses, not strings of text -- so event_key naively appears to be the right choice.

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:

  unsigned key = Fl::event_key();
  key = tolower(key);  // not utf-8 safe, but oh well...

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.

Gonzalo Garramuño

unread,
Aug 9, 2025, 10:15:50 AMAug 9
to 'Albrecht Schlosser' via fltk.general

El 9/8/25 a las 9:44, 'Albrecht Schlosser' via fltk.general escribió:
>
> 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...
I recommended to use tolower() as on Wayland, the key value used to be
uppercase.  At least previous to latest changes.

--
ggar...@gmail.com

pvr...@btinternet.com

unread,
Aug 9, 2025, 10:16:41 AMAug 9
to fltkg...@googlegroups.com
<QUOTE>


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.

</QUOTE>

Yes the fact that US and UK keyboards differ is seared in my memory, having been locked out of work by including the double-quote character in a password. On the Windows machine I had then, password handling happened while the keyboard handling was in its default (i.e. US) state, and not in the UK state I was expecting. 

Regards Phil.




Ian MacArthur

unread,
Aug 11, 2025, 5:59:22 AMAug 11
to fltk.general
On Saturday, 9 August 2025 at 15:16:41 UTC+1 Phill wrote:

Yes the fact that US and UK keyboards differ is seared in my memory, having been locked out of work by including the double-quote character in a password. On the Windows machine I had then, password handling happened while the keyboard handling was in its default (i.e. US) state, and not in the UK state I was expecting. 

As a rider to Phil's jolly little anecdote (which will be familiar in its form to many users of UK keyboards having to use s/w written by folks who imagine all English-language keyboards are alike...) it's worth noting that a lot of English-language keyboard layouts are (at least in part) informed by layouts that predate the widespread adoption of computers, and don't really follow the US-ANSI pattern all that closely. Any (or all) of  @ " # \ | ~ ¬  are liable to be in the "wrong place" for example - many of which can occur in fancy passwords and trigger the "helpful" effect Phil describes.

Indeed, in my experience, I've found that the Japanese JIS and the Chinese layouts are more US-ANSI-like in practice than the stock UK layout! Which always seems odd to me.

 
Reply all
Reply to author
Forward
0 new messages