I think there's something already available for macOS but I don't know
how complete / working this code is.
FL_ZOOM_GESTURE = 26,
I'm personally not working on this and I'm too busy with other stuff to
start yet another "project". I don't know of any other dev working on
touch and gesture events.
Thanks to Albrecht's direction, I parroted this commit by Matthias Melcher to add support for a couple other MacOS gestures, two-finger rotate and two-finger scroll. I can add three finger swype, but my application does not need it, so I'll hold off to see how this is received first.
Changes pushed up here:
This was done in a monkey-see monkey-do way -- I do not claim to have any understanding of Apple's API's. I have never used Objective-C and will continue to make that claim after doing this work. I followed Matthias' example and read this bit of Apple documentation as well as a few other bits of their terrible API docs...
In the end, it works for my application and is pretty cool. It would be great if other OS support could be similarly added.
The rotate gesture is pretty straightforward. Apple returns the rotation angle in floating point degrees. I followed Matthias' example and multiplied by 1000.0 and returned it the dy integer.
I also added handling for two-finger scroll on the trackpad. Apple actually fires the same event for this as for a mouse scroll wheel -- but with tiny magnitude dx,dy such that it seems like nothing is actually happening. In my application (involving 3D manipulation), I wanted to have different behavior for the scroll wheel (zoom) as for two-finger scroll (pan). So, I needed to differentiate between these different kinds of scrolls.
I eventually found NSEventSubtype which is equal to NSEventSubtypeMouseEvent when the event originates from a mouse rather than other hardware. There seemed to be other similar things to check for slightly different API versions. I don't know if we want to add a bunch of conditionals to know which variable to test.
With this change, FLTK will issue separate FL_MOUSEWHEEL and FL_SCROLL_GESTURE events depending on this value. Existing applications should be OK with this because the dx,dy returned by two-finger scroll via FL_MOUSEWHEEL is probably getting ignored (unless you do some really angry scrolling in the y-direction only).
I wasn't sure if the float s = Fl::screen_driver()->scale(0); scale value needs to be applied to the scroll gesture. I'm not sure where it comes from and how I would get it to have different values for testing on my machine.
I also wasn't sure if and where to add to unit tests, test applications, documentation, etc.
Finally, as this adds some new event types, I am not sure how to add protections to existing applications that still need to be able to compile against older versions of FLTK that do not have these defined.
On 10/9/21 7:22 AM Rob McDonald wrote:
Thanks to Albrecht's direction, I parroted this commit by Matthias Melcher to add support for a couple other MacOS gestures, two-finger rotate and two-finger scroll. I can add three finger swype, but my application does not need it, so I'll hold off to see how this is received first.
Changes pushed up here:
Thanks, I took a quick look ... looks good, thank you very much!
I still need to test it though.
I took a look into the Windows documentation you posted in another message. I couldn't resist and tried what I could get. Took me (way too many) hours but I'm now at a point where I get the gesture messages and I can interpret the data partly - not yet finished though.
The tricky part will be to integrate it with the FLTK event system (for now I'm only logging the messages) and to create the *correct* FLTK event data to have identical events and associated data on all platforms. ...
On 10/9/21 10:58 PM Albrecht Schlosser wrote:
On 10/9/21 7:22 AM Rob McDonald wrote:
Thanks to Albrecht's direction, I parroted this commit by Matthias Melcher to add support for a couple other MacOS gestures, two-finger rotate and two-finger scroll. I can add three finger swype, but my application does not need it, so I'll hold off to see how this is received first.
Changes pushed up here:
Thanks, I took a quick look ... looks good, thank you very much!
I still need to test it though.
Unfortunately I can't test it. My MacBook Air doesn't generate gesture events on the built-in touchpad (trackpad), I don't have an external tablet device for testing, and the MacBook Air doesn't have a touchscreen. :-(
The next part would be to create a suitable cross-platform FLTK event system that is able to provide the user with compatible events on all platforms.
I don't know yet how Linux/Unix provides multi-touch events to the user program, i.e. FLTK.
Thanks, I took a quick look ... looks good, thank you very much!
I still need to test it though.
I took a look into the Windows documentation you posted in another message. I couldn't resist and tried what I could get. Took me (way too many) hours but I'm now at a point where I get the gesture messages and I can interpret the data partly - not yet finished though.
The tricky part will be to integrate it with the FLTK event system (for now I'm only logging the messages) and to create the *correct* FLTK event data to have identical events and associated data on all platforms. Example:
Of course the rotation angle must have the same units and orientation on all platforms etc..
How is the "rotation angle" on macOS defined? Is it relative (per event) or is it some kind of absolute angle? Clockwise or counter-clockwise? My observations on Windows seem to indicate that it's the absolute angle of the two fingers, 0° = "north", increasing counter-clockwise (more tests needed, I didn't find it in the docs - docs are AFAICT incomplete and confusing).
BTW: after reading the macOS docs I believe that the zoom value issued on macOS by FLTK's FL_ZOOM_GESTURE event is not "correct" (whatever "correct" means here). The docs say you need to add 1 to the "magnification" value (you can still multiply with 1000). But what exactly is that value?
Some questions:
(1) What zoom values do you see on your macOS system? Do they make sense?
(2) What hardware did you use?
(3) I have a macBook Air with touch-/trackpad (no external device). Does it work with this config?
I think here we have an issue with backwards compatibility. If I read your statements correctly (but this may be not the case) then "splitting" in different event types may be an issue. IIRC I used my built-in (macBook Air) touchpad with two-finger scrolling as a replacement for scrolling with the mousewheel - because I don't use a mouse with my macBook. If this would be "converted" to FL_SCROLL_GESTURE then it could break existing apps that rely on FL_MOUSEWHEEL simulation. But, again, this needs testing...
You can define the env variable FLTK_SCALING_FACTOR=1.5 or similar before starting your program. Then all your FLTK programs should start zoomed by 150% and you could use cmd/+/- on a Mac to change scaling (ctrl/+/- on other systems).
Finally, as this adds some new event types, I am not sure how to add protections to existing applications that still need to be able to compile against older versions of FLTK that do not have these defined.
That's not an issue. Additional events are ignored by existing programs. But changing the semantics like changing a working event to another one (which would be ignored) is problematic (see my notes above).
Progress report:
Unfortunately I can't test it. My MacBook Air doesn't generate gesture events on the built-in touchpad (trackpad), I don't have an external tablet device for testing, and the MacBook Air doesn't have a touchscreen. :-(
Sorry, that statement above was an error. Testing with the built-in touchpad works fine. :-(
I can now see the events and proceed...
One issue I noticed so far is as I wrote before: using the touchpad with two-finger scroll gestures does no longer scroll in the FLTK test apps with the proposed macOS patch. Mouse wheel spinning does still scroll fine. This is because the touchpad gestures send the event "FL_SCROLL_GESTURE" which is unknown/ignored rather than sending "FL_MOUSEWHEEL" which would do the scrolling in, for instance, Fl_Text_Display in test/editor.
This is something we need to find a solution for (backwards compatibility).
To clarify the above statement: before we can develop cross-platform events for multi-touch gestures we need to investigate what the different platforms offer. AFAICT the Windows and macOS platforms are slightly different (Linux not yet investigated).
We need a specification that can be used for all platforms. As I wrote before, the events, types, variables and values (units, magnitude, etc.) should be as close as possible on all supported platforms.
So far I can imagine two generally different approaches:
(1) We define only one FL_MULTI_TOUCH[_GESTURE] (?) event (like Microsoft does) and send different event types (pan, zoom, rotate, ...) together with some corresponding variables (maybe a struct). The user code needs to handle only one additional event but needs to dispatch the different types.
(2) We define one FLTK event per multi-touch event type. This is like the early "FL_ZOOM_GESTURE" event and the proposed patch has been done with additional events: "FL_ZOOM_GESTURE", "FL_ROTATE_GESTURE", "FL_SCROLL_GESTURE", ... and maybe more in the future.
Currently I tend to prefer (1), but I'd like to read about others' opinions.
This is under investigation but links to documentation (or even code snippets) would be appreciated.
I'll keep you updated.
--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/63300AF9-10DD-4DE4-B598-B049CCBB3F70%40gmail.com.
On Saturday, October 9, 2021 at 1:58:37 PM UTC-7 Albrecht Schlosser wrote:
Thanks, I took a quick look ... looks good, thank you very much!
I still need to test it though.
Thanks for checking it out.
I took a look into the Windows documentation you posted in another message. I couldn't resist and tried what I could get. Took me (way too many) hours but I'm now at a point where I get the gesture messages and I can interpret the data partly - not yet finished though.
This looks like a great start to me.
The tricky part will be to integrate it with the FLTK event system (for now I'm only logging the messages) and to create the *correct* FLTK event data to have identical events and associated data on all platforms. Example:
Agreed, we want to make all platforms behave as much the same as possible to a FLTK developer / user.
BTW: after reading the macOS docs I believe that the zoom value issued on macOS by FLTK's FL_ZOOM_GESTURE event is not "correct" (whatever "correct" means here). The docs say you need to add 1 to the "magnification" value (you can still multiply with 1000). But what exactly is that value?
The pinch zoom also gave deltas
Some questions:
(1) What zoom values do you see on your macOS system? Do they make sense?
I'll go back and set up a test program to look into this. I needed some sign flips to make zoom work right on my machine -- but I'm feeding it into an OpenGL zoom parameter that may be counter intuitive.
I think it is valuable to be able to have an application specify that it wants to treat a scroll gesture differently from a mouse wheel scroll -- while keeping the default the same for compatibility. Are there examples in FLTK of specifying this kind of behavior?
Ideally, in a 3D manipulation program, if you use two-finger scroll for Pan, you would want the object to track with your fingers -- like you were physically moving it. No matter the zoom level, etc.
Do we have a 3D OpenGL test program? It might provide a good example to make a test case out of.
We could also do a 2D version -- pan, zoom, and rotate some simple objects on a screen. Perhaps an image manipulation, or a simple map interface.
Finally, as this adds some new event types, I am not sure how to add protections to existing applications that still need to be able to compile against older versions of FLTK that do not have these defined.
That's not an issue. Additional events are ignored by existing programs. But changing the semantics like changing a working event to another one (which would be ignored) is problematic (see my notes above).
I meant for the situation where my open source application is sometimes compiled by end users on old versions of FLTK bundled with Linux distributions. I'd like for these cases to still build and work - even if they lose this functionality.
I suppose a simple
#ifndef FL_ROTATE_GESTURE
#define FL_ROTATE_GESTURE=28
#endif
somewhere in my application will work.
On 10/11/21 4:28 AM Rob McDonald wrote:
The pinch zoom also gave deltas ...
I'll go back and set up a test program to look into this. I needed some sign flips to make zoom work right on my machine -- but I'm feeding it into an OpenGL zoom parameter that may be counter intuitive.
Note that the two WM_MOUSEHWHEEL messages at the beginning of the log are really that. However, I don't know where exactly the other ewo interspersed WM_MOUSEHWHEEL messages came from. I think that's a Windows "feature", some gestures are sent as normal mousewheel events for backwards compatibility (more tests required).
I wrote a small demo program (test/gestures.cxx). We can certainly improve it, but it works as expected (by me) on macOS with my latest changes in my private fork:
https://github.com/Albrecht-S/fltk/commits/MacOS_Gestures
You can either use CMake or fltk-config to build the demo program (Makefiles not updated).
Changes: positive angles in FL_ROTATE_GESTURE are now clockwise.
FL_ZOOM_GESTURE is in this test version not compatible with the 1.3 version. This is intentional and will be fixed in a later version.
On 10/12/21 7:13 PM Rob McDonald wrote:
> https://github.com/ramcdona/fltk/tree/MacOS_Gestures
Yep, found it. The only "real" issue is in draw(): you're pushing the
matrix at the wrong place in the code. You need to move
'fl_push_matrix();' up before 'fl_translate(...);' and it should work
... with some minor issues. Cute!
What I saw so far: the rotation is "inverted". I'm leaving this one up
to you (unless this was intended).
There was also one problem with event delivery (missing FL_ZOOM_GESTURE
in Fl_Group::handle(). I added it and now it works - at least as I'd expect.
On Tuesday, October 12, 2021 at 3:13:23 PM UTC-7 Albrecht Schlosser wrote:
On 10/12/21 7:13 PM Rob McDonald wrote:
> https://github.com/ramcdona/fltk/tree/MacOS_Gestures
Yep, found it. The only "real" issue is in draw(): you're pushing the
matrix at the wrong place in the code. You need to move
'fl_push_matrix();' up before 'fl_translate(...);' and it should work
... with some minor issues. Cute!
That would have taken me a long time to figure out -- drawing the first time works, but I suppose it quickly out-runs the stack depth of 4 and stops working...
FLTK's fl_rotate() is positive CCW whereas FL_ROTATE_GESTURE is positive CW. The sign flip is expected.
The handling of FL_SCROLL_GESTURE had a negative inherited from the FL_MOUSEWHEEL code -- since it seemed quite counterintuitive for this use, I removed it there.
I've updated my branch with all these fixes together. It makes for a little 2D app that responds in all the ways I would want it to -- rotate, pan, zoom.
It looks like MacOS and Windows both also support a swype gesture -- I hadn't looked into it because I don't see a use in my application. However, as long as we're at it, we should probably be complete.
The handling of FL_SCROLL_GESTURE had a negative inherited from the FL_MOUSEWHEEL code -- since it seemed quite counterintuitive for this use, I removed it there.
This one is tricky on macOS. You can use the system preferences for trackball and mouse, respectively, to enable "natural scrolling". No matter which one you use, both trackball and mouse are affected! I would have expected that these are different settings, and when I switched to "natural" my Mac did what I expected with the trackpad but the mouse scrolling change was not expected. With this *user preference* the sign of the scrolling delta is inverted (again, in both cases). It's not yet clear to me which sign convention we should apply taking this into account. Do (can) we access the system preference to compensate this? Is it useful to do so? I don't know.
I assume your setting is "natural" - please try to use your program after switching "natural scrollling" off. Is it still intuitive? I don't think so.
Yep, that's great. Your addition is really helpful. Thanks. I pulled all your changes into my own fork.
Yes, probably. My next step will be to add the Windows implementation. Once that is done we can see which sign conventions we should use and how "cross platform" compatible this all will be. Windows seem to call the swipe gesture "Flicks" if I interpret their docs correctly. It's hard for a non-native English speaker like me to interpret these gestures and the particular naming in the docs.
https://docs.microsoft.com/en-us/windows/win32/wintouch/windows-touch-gestures-overview
The macOS docs state: "Three fingers brushing across the trackpad surface in a common direction is a swipe gesture."
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/HandlingTouchEvents/HandlingTouchEvents.html
Finally, one important note: please don't rely on this experimental code for your "real" applications. I'm sure we will change the API before we go into production (release). For instance, one major change would be to add new Fl_event_*() accessor methods for a better interface to gestures. Some of these variables obviously need to be floats or doubles so the user doesn't need to divide by 1,000 or 100,000 or any other factor.
I think trackpad scrolling (and eventually touch-screen) will need to be able to detect the 'natural' scroll setting. In a touch-screen environment, you certainly don't want to click-and-drag something and have it fly the wrong way...
It may not be practical to map all OS gestures to a common set of FLTK gestures. While that would be ideal (if all OS's supported a wide set of gestures), it would not be a useful feature if there is not a useful common set.
Should we map Windows one-finger Flick and MacOS three-finger swype to the same event? I say probably not. Although they could reasonably be used for the same purpose (say turning pages in a virtual book), what would we do if MacOS later supports a one-finger flick and Windows a 3-finger swype?
Another approach would be to add support for all OS supported gestures -- mapping common gestures to common events. That allows the application to decide to interpret flick and swype in the same way (or not).
I see this as analogous to the two-finger scroll being different from mouse wheel scroll -- it is nice for a default behavior for them to be the same -- but there is cool opportunity in separating them out.
On 10/13/21 6:48 PM Rob McDonald wrote:
I think trackpad scrolling (and eventually touch-screen) will need to be able to detect the 'natural' scroll setting. In a touch-screen environment, you certainly don't want to click-and-drag something and have it fly the wrong way...As I was told Apple doesn't produce systems (MacBooks) with touch-screens. Are touch-screens supported by macOS? If not we won't know how to deal with them until Apple will produce and/or support systems with touch-screens. I'm saying this for a reason: if we design an API today it may be wrong in the future once touch-screens are working with Apple systems. Currently I know that my tests with my notebook's touch-screen worked on Windows.
Well put, all good points. My conclusion from your writing is that we should indeed let "different things" be separate FLTK events. The one-finger-flick vs. three-finger-swipe argument is compelling.
For all new (and documented) events we can tell the user that they can and should handle FL_FLICK and FL_SWIPE events in the same 'case' statement, for instance. With a note that this may change in the future...
I see this as analogous to the two-finger scroll being different from mouse wheel scroll -- it is nice for a default behavior for them to be the same -- but there is cool opportunity in separating them out.Agreed. However this is a little different because of backwards compatibility. Currently all FLTK programs that handle FL_MOUSEWHEEL events continue to work with trackpad scroll events if these are mapped to FL_MOUSEWHEEL events. As soon as we separate them out programs need to be modified. That's why I think we need a backwards compatible way to deal with these two event types. Let's see ...
Here's a new idea (untested): we could first send an FL_SCROLL_GESTURE event and if this is not handled by any widget, send an FL_MOUSEWHEEL event. This way "new" programs can handle the FL_SCROLL_GESTURE event and "old" programs can still handle FL_MOUSEWHEEL events. It's similar to FL_KEYBOARD events that are converted to FL_SHORTCUT (if not handled) and finally to FL_SHORTCUT with flipped case. Does that sound sensible?
On Wednesday, October 13, 2021 at 1:58:14 PM UTC-7 Albrecht Schlosser wrote:
On 10/13/21 6:48 PM Rob McDonald wrote:
I don't have a touch screen Windows machine -- I'm glad that you have such a machine to test on.
I see this as analogous to the two-finger scroll being different from mouse wheel scroll -- it is nice for a default behavior for them to be the same -- but there is cool opportunity in separating them out.
Agreed. However this is a little different because of backwards compatibility. Currently all FLTK programs that handle FL_MOUSEWHEEL events continue to work with trackpad scroll events if these are mapped to FL_MOUSEWHEEL events. As soon as we separate them out programs need to be modified. That's why I think we need a backwards compatible way to deal with these two event types. Let's see ...
Compatibility is merely a matter of foresight. If we make them the same event now and want to change it later, we then have a compatibility problem (:
[Albrecht:] Here's a new idea (untested): we could first send an FL_SCROLL_GESTURE event and if this is not handled by any widget, send an FL_MOUSEWHEEL event. This way "new" programs can handle the FL_SCROLL_GESTURE event and "old" programs can still handle FL_MOUSEWHEEL events. It's similar to FL_KEYBOARD events that are converted to FL_SHORTCUT (if not handled) and finally to FL_SHORTCUT with flipped case. Does that sound sensible?
[Rob:] Devious and clever -- I never would have thought of this.
If that works, I think it will be a great solution.
Under all circumstances, I think a "real mousewheel" should always send "real mousewheel" events. I.e. we should differentiate the event type - only send gesture scroll events if the OS event originates from a non-mousehweel source -- then re-send as a mousewheel if nothing down the line handled the gesture event.
--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/dc3f77e3-ba4b-be0a-dd7f-e6bffab08da3%40online.de.
[Albrecht:] Here's a new idea (untested): we could first send an FL_SCROLL_GESTURE event and if this is not handled by any widget, send an FL_MOUSEWHEEL event. This way "new" programs can handle the FL_SCROLL_GESTURE event and "old" programs can still handle FL_MOUSEWHEEL events. It's similar to FL_KEYBOARD events that are converted to FL_SHORTCUT (if not handled) and finally to FL_SHORTCUT with flipped case. Does that sound sensible?
I hope it will. We have the precedent of FL_KEYBOARD and FL_SHORTCUT, so I believe it should (a) be doable and (b) work for users. It's a little overhead to send an event that nobody uses (if both FL_SCROLL_GESTURE *and* FL_MOUSEWHEEL are not used). But that's a small price.
Hi Matthias,
great to see you "back here" again.
Thanks for your confirmation. Unfortunately I've been too busy lately to proceed with this on Windows (before I can see how this is done best cross-platform) but I'll go ahead with this soon.
If you or anybody else have a good idea (and docs and/or code) how to use multi touch gestures on Linux this would be appreciated as well.