picoe / Eto

Cross platform GUI framework for desktop and mobile applications in .NET
Other
3.66k stars 333 forks source link

UITimer in Eto doesn't work when Mouse is down #2253

Closed WileyNg closed 2 years ago

WileyNg commented 2 years ago

Expected Behavior

UITimer in Eto should work even when Mouse down

Actual Behavior

UITimer.Start() doesn't start until Mouse button is released

I found this out when I tried to use Eto.UITimer to make a animation whenever a Ctrl key is pressed during a MouseDown Event. It doesn't start like the System.Timer does.

System.Timer https://user-images.githubusercontent.com/5993201/178802950-9e3b3cff-6d62-44e1-8415-5dce30cea142.mp4

Eto.UITimer https://user-images.githubusercontent.com/5993201/178802957-0bf9eddc-1967-4262-a08c-0bfd5a167ca2.mp4

As you can see in the second video, UITimer took like 7 seconds until the Timer-Stop message, which was actually 2 seconds after I released the mouse button.

WileyNg commented 2 years ago

image

@cwensley However, if I am using System.Timer, putting the Invalidate() function inside no longer works.

cwensley commented 2 years ago

If you want to call methods/properties on a UI object from a background thread (which Timer uses), you need to use Application.Instance.Invoke/AsyncInvoke so it calls it on the UI thread. E.g. Application.Instance.Invoke(Invalidate) would work there.

As for the UITimer, is this on Windows or Mac? Do you have some sample code to reproduce the issue?

WileyNg commented 2 years ago

I zipped the 6 codes into here: these are the codes to be run in Rhino with the GetPoint Command MouseEventsForTest.zip

Below is a test. I tried to do an addition every time there is a MouseDown Event, and a subtraction whenever CtrlKeyDown is triggered with MouseDown. You could see the Control stops invalidating at 152, then lags for quite a while, then picks back up till 544. All the while I had the MouseDown Triggered, as proven in the Command Prompt. Is this a bug? Any advice or help from you would be most appreciated!

https://user-images.githubusercontent.com/5993201/178918880-77e0e859-1c11-4cfe-890a-6acfa00c52af.mp4

WileyNg commented 2 years ago

Invalidate lags heavily with MouseDown, while UITimer doesn't work at all during a MouseDown event.

cwensley commented 2 years ago

This is likely due to this code, which you are doing while listening to mouse events:

            while(true)
            {
                var result = flattenMesh.Get(true);

                if (result == GetResult.Point)
                {
                    continue;
                }
                break;
            }

Here, you're not pumping the UI message loop so there's no way for the UI to respond. Try adding a call to Application.Instance.RunIteration() in there so that the message loop gets some time to do its thing.

WileyNg commented 2 years ago

Thanks so much Curtis! I will look at it when I have time. I will also test the UITimer out with your method. I think it's a similar issue, hopefully. In my code, I actually set a UITimer to allow time for the next Invalidate to execute. But it didn't work because it stopped when Mouse is down

cwensley commented 2 years ago

It makes sense that it doesn't work, doing a loop in the UI thread is dangerous and will make the UI non responsive (including UITimer), though Rhino APIs tend to require it sometimes. Thus the problem.