Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression (hg only, recent SDL_TOUCH_MOUSEID changes probably related): drag finger outside of screen and touch breaks #3224

Closed
SDLBugzilla opened this issue Feb 11, 2021 · 0 comments

Comments

@SDLBugzilla
Copy link
Collaborator

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: HG 2.0
Reported for operating system, platform: Linux, x86_64

Comments on the original bug report:

On 2019-04-06 14:39:50 +0000, Ellie wrote:

Since the recent changes which I suspect were the ones made for # 4572 there appears to be a new bug that breaks touch input on Android in certain situations:

Steps to reproduce:

  1. Launch your app that relies on SDL_TOUCH_MOUSEID for touch handling

  2. Place a single finger in the middle of screen (such that it touches it)

  3. Move your finger slowly to the side until it leaves the screen, without ever taking it off the surface

Touch is now broken (no further single finger events will lead to any input)

On 2019-04-06 15:39:10 +0000, Ellie wrote:

My theory is that SDL2 somehow doesn't get a finger up or loses it in some way internally, and therefore it thinks the one finger that left the screen is still pressed down forever - and this finger is treated as the "first" finger that controls SDL_TOUCH_MOUSEID, so all "real" fingers that follow later are 2nd+ and ignored

On 2019-04-06 16:48:40 +0000, Sylvain wrote:

This is possible but I would be suprised if that appeared.
What device are you using ? and which android version ?

Can you add some log after your poll event loop, like:

if (evt.type == SDL_MOUSEWHEEL)
{
const int normal = (evt.wheel.direction == SDL_MOUSEWHEEL_NORMAL);
const int y = evt.wheel.y;
SDL_Log("SDL Mouse Wheel y=%d normal=%d", y, normal);
}

if (evt.type == SDL_MOUSEBUTTONDOWN)
{
const int which = evt.button.which;
int x = evt.button.x;
int y = evt.button.y;
SDL_Log("SDL Mouse Down which=%d (%d, %d)", which, x, y);
}

if (evt.type == SDL_MOUSEMOTION) {
int x = evt.motion.x;
int y = evt.motion.y;
const int which = evt.motion.which;
SDL_Log("SDL Mouse Motion which=%d (%d, %d)", which, x, y);
}

if (evt.type == SDL_MOUSEBUTTONUP)
{
const int which = evt.button.which;
int x = evt.button.x;
int y = evt.button.y;
SDL_Log("SDL Mouse Up which=%d (%d, %d)", which, x, y);
}

if (evt.type == SDL_FINGERDOWN)
{
const SDL_TouchID touchId = evt.tfinger.touchId;
const SDL_FingerID fingerId = evt.tfinger.fingerId;
const int num_fingers = SDL_GetNumTouchFingers(touchId);
float x = evt.tfinger.x;
float y = evt.tfinger.y;

  SDL_Log("Finger Down [%lld,%lld]! num_fingers=%d  (%f, %f)", 
        touchId, fingerId, num_fingers, x, y);

}

if (evt.type == SDL_FINGERUP)
{
const SDL_TouchID touchId = evt.tfinger.touchId;
const SDL_FingerID fingerId = evt.tfinger.fingerId;
const int num_fingers = SDL_GetNumTouchFingers(touchId);
float x = evt.tfinger.x;
float y = evt.tfinger.y;

  SDL_Log("Finger Up [%lld,%lld]! num_fingers=%d (%f, %f)", 
        touchId, fingerId, num_fingers, x, y);

}

if (evt.type == SDL_FINGERMOTION)
{
const SDL_TouchID touchId = evt.tfinger.touchId;
const SDL_FingerID fingerId = evt.tfinger.fingerId;
const int num_fingers = SDL_GetNumTouchFingers(touchId);
float x = evt.tfinger.x;
float y = evt.tfinger.y;

  SDL_Log("Finger Motion [%lld,%lld]! num_fingers=%d (%f, %f)", 
        touchId, fingerId, num_fingers, x, y);
}

On 2019-04-06 18:36:36 +0000, Ellie wrote:

Created attachment 3732
SDL event log

I attached the requested event log of the bug happening

windowunknownevent-11 is an SDL_WindowEvent with type=11, which according to SDL2/SDL_video.h appears to be SDL_WINDOWEVENT_LEAVE. That is also right where the finger leaves the screen, and after which SDL_TOUCH_MOUSEID just breaks down forever. I can't remember ever seeing that before so while I haven't explicitly retested stable, I'm pretty sure this is a recent regression

The device is Android 7.1.1 / Gemini PDA

On 2019-04-06 18:38:13 +0000, Ellie wrote:

(sorry that the output is slightly different from the one you suggested, I just gave you the event log as wobblui already provides it. If you need some detail it doesn't have I'd be happy to add it)

On 2019-04-06 18:47:54 +0000, Sylvain wrote:

Even if SDL was missing a Finger Up, it will catch the next one in Log. Because the FingerId is always 0.

Maybe log also TouchId to see ...

You really you copy paste the previous log code, after your SDL_PollEvent method or enable the Event log, I think there is an hint:
see SDL_HINT_EVENT_LOGGING

On 2019-04-06 18:49:48 +0000, Sylvain wrote:

also it logs a mousemotion with which = 0

04-06 20:26:52.548 11594 11627 I python : DEBU 2019-4-6-18:26:52+0 wobblui: wobblui.init.py: DEBUG: sdl event: mousemotion(which:0,x:0,y:644)

whereas there should be -1 ?

On 2019-04-06 18:54:33 +0000, Ellie wrote:

Oh, fascinating find! The reason I haven't just pasted your code is because I'm actually doing everything in Python through PySDL2 lol, making this a bit more unusually complicated...

For what it's worth, SDL_TOUCH_MOUSEID is logged as 4294967295 (since the struct member is defined as unsigned if I recall) so which:0 should definitely mean it's sent as mouse event 0 and not SDL_TOUCH_MOUSEID. Really fascinating!

I'm just adding the touchId and numFingers info, will attach the new log with the info added

On 2019-04-06 19:21:59 +0000, Sylvain wrote:

I think when it goes out of the windows you have this WINDOW_LEAVE
with set mouse focus == NULL
( SDL_SetMouseFocus(NULL); )

and then you don't receive any the other mouse events

Try to call: SDL_SetMouseFocus(window);

On 2019-04-06 19:45:44 +0000, Sylvain wrote:

I've done an update:
https://hg.libsdl.org/SDL/rev/eabdcf59246a

So that the tracking is done even if there is no focus window.
It's a little bit more robust.
Can you try to see if it helps?

On 2019-04-06 20:47:35 +0000, Ellie wrote:

Sorry that my responses are taking so long, I had to fix issues with my debug terminal widget and my build time is a bit lengthy :-O

Nevertheless, regarding SDL_WINDOWEVENT_LEAVE, I'm just wondering:
No matter when I get SDL_TOUCH_MOUSEID or not, shouldn't I get SDL_WINDOWEVENT_ENTER if the window is tapped and no hw mouse is attached? (I guess it makes sense if I don't get any if there is a hw mouse with the mouse cursor still truly outside the window) That seems a bit of a weird behavior of the focus itself that may be worth changing/fixing

About to test the newer revision & a more detailed debug log when the build has run through

On 2019-04-06 21:14:41 +0000, Sylvain wrote:

I suspect that SDL_UpdateMouseFocus is having issue with the focus.
What about the patch below ?
if that works, it would be nice to see what happens in this SDL_UpdateMouseFocus function

diff -r 0cc2592ed0f4 src/events/SDL_mouse.c
--- a/src/events/SDL_mouse.c Sat Apr 06 21:52:51 2019 +0200
+++ b/src/events/SDL_mouse.c Sat Apr 06 23:12:49 2019 +0200
@@ -294,7 +294,7 @@
int
SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
{

  • if (window && !relative) {
  • if (window && !relative && mouseID != SDL_TOUCH_MOUSEID) {
    SDL_Mouse *mouse = SDL_GetMouse();
    if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
    return 0;

On 2019-04-06 21:39:13 +0000, Ellie wrote:

Created attachment 3733
SDL Event log of bug with revision d311fcb8066a (including touchId info)

Log now attached for still the old revision d311fcb8066a without patch, but now with better debug output that includes touchId (sorry I'm way too slow with my testing XD)

I will now test 0cc2592ed0f4 with that focus patch on top, unless you want me to test something else

On 2019-04-06 23:44:14 +0000, Ellie wrote:

Created attachment 3735
SDL Event log of bug with revision 0cc2592ed0f4 with patch in comment 11

Okay, ran the test now with latest revision + patch. The result is I no longer get any mouse leave or enter anymore, but it also works. Not sure if that is the intended behavior since after all a mouse leave doesn't seem so unreasonable, as long as there is a mouse enter once the finger/mouse returns

Anyway, I hope that helps you figure out if there is still something that needs changing!

On 2019-04-07 00:22:54 +0000, Ellie wrote:

(sorry, I was unclear: I do still get one initial SDL_WINDOWEVENT_ENTER when the app starts, but what I meant to say is that when the finger leaves the app area then I no longer get any more leave/enter events, not even a single leave as before. This was tested With revision d311fcb8066a combined with your patch in comment 11)

On 2019-04-07 00:25:39 +0000, Ellie wrote:

Meant 0cc2592ed0f4 (the newer one) with patch, regarding the previous comment 14, whoops! I'll stop now before I add any more conflicting info, sorry about that! lol

On 2019-04-07 07:32:37 +0000, Sylvain wrote:

So the patch seems to work right. We get closer. But I still can't reproduce it.

A few things to investigate :
Do you use SDL_WINDOW_FULLSCREEN or not ?
Do it happens for all borders ? bottom/top/left/right ?

It would be nice if you could patch SDL to add some debug:

in 'src/events/SDL_mouse.c' (line 256), where it sets:
inWindow = SDL_FALSE;

add (line 254), just after SDL_GetWindowSize(), something like
SDL_Log("inWindow==%d x=%d y=%d w=%d h=%d", inWindow, x, y, w, h);

also, before SDL_SetMouseFocus(NULL);
SDL_Log("call SDL_SetMouseFocus(NULL);");

On 2019-04-07 10:58:07 +0000, Ellie wrote:

Do you use SDL_WINDOW_FULLSCREEN or not ?

No it runs in windowed, with the action bar and status bar visible

Do it happens for all borders ? bottom/top/left/right ?

I tested side for which it happens, and also just moving the finger up onto the status bar (doesn't even need to leave the screen) where it also happens

It would be nice if you could patch SDL to add some debug:

Sure, can do. Should I test on the latest revision, or go back to the broken one to test this? With or without the patch in Comment 11?

On 2019-04-07 11:17:32 +0000, Sylvain wrote:

I tested side for which it happens, and also just moving the finger up onto the status bar
(doesn't even need to leave the screen) where it also happens

Not sure I still even understand the issue.
You lose the mouse events, while keeping the finger in the screen ?

I thought you have to move the finger outside the screen. This is why I asked if that happens,
crossing the left egde, right edge, bottom edge or top edge ?

Sure, can do. Should I test on the latest revision, or go back to the
broken one to test this? With or without the patch in Comment 11?

Please try with the head (so 0cc2592ed0f4) which is still broken, right ?

Don't try with the patch from comment 11. Just to confirm, the patch would solve the issue ?

On 2019-04-07 11:24:58 +0000, Ellie wrote:

With older revision d311fcb8066a and NO PATCH, the issue is:

  1. I get SDL_WINDOWEVENT_LEAVE once the finger leaves the screen
  2. I DON'T get SDL_WINDOWEVENT_ENTER once it returns
  3. From then on, SDL_TOUCH_MOUSEID just isn't sent anymore

With newer revision 0cc2592ed0f4 with patch in comment 11 I get:

  1. Once the finger leaves the screen I see no event in indicating it, and SDL_TOUCH_MOUSEID is consistently sent
  2. Otherwise it works fine and SDL_TOUCH_MOUSEID works fine, but no SDL_WINDOWEVENT_LEAVE/SDL_WINDOWEVENT_ENTER anymore which probably are useful to have

That's all the combinations I tested so far. So yes, the newest revision with patch kinda solves it but at the cost of leave/enter events

On 2019-04-07 11:33:22 +0000, Sylvain wrote:

Ok, I would like to know with newer revision 0cc2592ed0f4 without patch in comment 11.
(and the log to see why updatefocus is broken or if it does a SetFocus(NULL) ... )

I think we can't receive the enter/leave window event because the mouse event are duplicated from the touch event.
so when your finger reach the border, it just becomes up. and so the simulated mouse becomes also up at this very instant.

On 2019-04-07 16:33:46 +0000, Ellie wrote:

Created attachment 3737
SDL Event log of bug with revision 0cc2592ed0f4 WITHOUT patch, but WITH debug info

Ok, attached SDL Event log of bug with revision 0cc2592ed0f4 WITHOUT patch, but WITH debug info in the following form:

--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -252,6 +252,7 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
int w, h;
SDL_GetWindowSize(window, &w, &h);

  •    SDL_Log("inWindow==%d x=%d y=%d w=%d h=%d", inWindow, x, y, w, h);
       if (x < 0 || y < 0 || x >= w || y >= h) {
           inWindow = SDL_FALSE;
       }
    

@@ -276,6 +277,7 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
printf("Mouse left window, synthesizing move & focus lost event\n");
#endif
SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);

  •        SDL_Log("call SDL_SetMouseFocus(NULL);");
           SDL_SetMouseFocus(NULL);
       }
       return SDL_FALSE;
    

@@ -285,6 +287,7 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
#ifdef DEBUG_MOUSE
printf("Mouse entered window, synthesizing focus gain & move event\n");
#endif

  •    SDL_Log("call SDL_SetMouseFocus(%p);", window);
       SDL_SetMouseFocus(window);
       SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
    
    }

(the result of that test being also that the bug occurs, that is when the finger leaves the screen you can also see in the event log that no SDL_TOUCH_MOUSEID mouse events no longer occur)

On 2019-04-07 17:18:12 +0000, Sylvain wrote:

So it seems there are negative values for the touch events:

04-07 17:58:52.611 29676 29716 I python : DEBU 2019-4-7-15:58:52+0 wobblui: wobblui.init.py: DEBUG: sdl event: fingermotion(fingerId:0,touchId:1,numFingers:1,x:-0.0016459295293316245,y: 0.6993396878242493)

So it leads to negative value for synthetic mouse events:

04-07 17:58:52.592 29676 29676 I SDL/APP : inWindow==1 x=-1 y=712 w=1006 h=1019

and it calls:
04-07 17:58:52.592 29676 29676 I SDL/APP : call SDL_SetMouseFocus(NULL);

Hence, the WINDOW_LEAVE event ..

Not sure why there are negative touch motion (That would be in SDLActivity, onTouch() -> ACTION_MOVE )

And when you touch in the right direction, maybe you go greater than "width window" and there is also a window leave event.
maybe this answer will help :

"Try using getRawX() and getRawY() instead of getX() and getY()."
( https://stackoverflow.com/questions/6237200/motionevent-gety-and-getx-return-incorrect-values )

On 2019-04-07 20:43:26 +0000, Sylvain wrote:

I achieved to get also negative value by touching under the status bar, and I got the same issue.

The issue wasn't appearing with the former version, because we always gave the unique Android window. Now we use a generic code and it uses the focused window.
The focus gets out when the synthetic mouse leave the window.

And there is no focus-window information coming from the touch event.

Maybe the best way to fix this is to filter out the synthetic mouse event, to prevent from removing the focus window ? (eg previous patch).

Sam ? Ryan ?

On 2019-04-07 20:59:39 +0000, Ellie wrote:

But then what if an actual hw mouse connected (with SDL_TOUCH_MOUSEID) leaves the window? Wouldn't that still break touch as a consequence with your patch above for the duration the hardware mouse cursor is outside of the window?

In fact, it sounds a little like for any application with 2+ windows, touch currently only works in the one window where the actual hardware mouse is (= which has mouse focus) which doesn't seem like a reasonable filter criteria. I don't know how to test that on Android though where you can only have one

I could be wrong of course, I'm just extrapolating/guessing so ignore me if that makes no sense :-D

On 2019-04-07 21:00:39 +0000, Ellie wrote:

But then what if an actual hw mouse connected (with SDL_TOUCH_MOUSEID)

Sorry, I meant: NOT with SDL_TOUCH_MOUSEID

On 2019-04-08 08:49:11 +0000, Sylvain wrote:

it shouldn't disturb hw mouse.

I'm not sure sure how we should fix the issue:

  • maybe we should discard focus handling for virtual mouse.
  • but we may lose enter/leave event.

On 2019-04-08 09:13:11 +0000, Ellie wrote:

it shouldn't disturb hw mouse.
I was really thinking of hw mouse disturbing the SDL_TOUCH_MOUSEID handling rather than the other way around

Anyway, isn't this a general problem with mouse focus & multiple mouses?

If all mouses including the SDL_TOUCH_MOUSEID "virtual mouse" had their focus separately tracked by SDL2, and SDL_WINDOWEVENT_ENTER was sent as soon as ANY mouse is inside the window, and SLD_WINDOWEVENT_LEAVE was sent as soon as ALL mouses left the window, thten this should work fine right? Of course that would mean multiple windows could get SDL_WINDOWEVENT_ENTER (without leave in between) as soon as 2+ mouses are involved

On 2019-04-08 09:23:36 +0000, Ellie wrote:

I am right guessing that on most platforms, multiple mouses will use multiple mouse cursors, right? If not then what I just said makes no sense and please ignore it :-D

On 2019-04-08 09:31:30 +0000, Sylvain wrote:

A configuration with several mice isn't really usual. And all this is a little bit theoretical.
The simulated mouse is somehow a degraded/fallback mode, so that app that were designed for mouse, could also work when using a touchscreen.

On 2019-04-08 09:39:51 +0000, Ellie wrote:

Okay, this is the most simple suggestion I can come up with:

What if

  • no mouse events are never filtered for mouse focus (= essentially what you suggested as in just ignoring the entire concept when producing the mouse events themselves)

  • and any mouse event ever on a window will simply cause SDL_WINDOWEVENT_ENTER if that window hasn't had that yet, and SDL_WINDOWEVENT_LEAVE on all others

That would work with an infinite amount of independent mouse cursors, while being pretty simple to implement (all you need is a flag on each window if it was sent SDL_WINDOWEVENT_ENTER without a leave afterwards) while never possibly leading to mouse events being lost ever

On 2019-04-08 09:41:25 +0000, Ellie wrote:

  • no mouse events are never filtered

the double negation was unintentional, I'm really brilliant at typoing my comments apparently

On 2019-04-08 19:28:14 +0000, Sylvain wrote:

Virtual mouse events should never leave the window or change focus for single window applications.

Fixed https://hg.libsdl.org/SDL/rev/1223f50edde3

On 2019-04-09 00:15:53 +0000, Ellie wrote:

Created attachment 3739
SDL Event log with revision 1223f50edde3 WITHOUT patches

Ok I tested the latest revision 1223f50edde3 with zero patches, and it works BETTER but there is still a problem:

The attached log is me dragging the finger out at the top (over the status bar) and afterwards I tap somewhere onto the lower half of the screen

  • As you can see, the latest SDL_TOUCH_MOUSEID mouse MOTION event is at x:447,y:0 when my drag reaches the upper window border
  • Then there are a lot of touch only events, followed by a touch finger UP (but no mouse up!) as I let go somewhere over the statusbar
  • Then there is another SDL_TOUCH_MOUSEID mouse MOTION event at x:160,y:712 caused by my the single tap

There is no mouse up/down in between! Therefore, an application may reasonably perceive this as a sudden super fast drag from x:447,y:0 to x:160,y:712 in a single event jump. It would be good if there was an actual mouse up in between, at the very latest when there is the coinciding finger up event!

On 2019-04-09 08:41:10 +0000, Sylvain wrote:

Created attachment 3740
patch

Then, here's a patch to try. So that simulated mouse events are contained in the window.
And there would be mouse up/down even if the finger is outside.

On 2019-04-10 01:51:28 +0000, Ellie wrote:

Okay, finally got around to test the patch in Comment 34 on top of revision 1223f50edde3 and from all I can see it appears to be working perfectly! No more issues, touch input continues working, and when letting the finger to onto the status bar I still get the SDL_TOUCH_MOUSEID mouse up as expected and it's all working nicely. Thanks for all the fixes!

On 2019-04-10 09:01:19 +0000, Sylvain wrote:

Ok ! so hopefully the bug is resolved !
https://hg.libsdl.org/SDL/rev/3477a301a5a8
Thanks a lot for the report, feedback and helping with the various patch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant