aseprite / laf

A C++ library to create desktop applications
https://aseprite.github.io/laf/
MIT License
274 stars 58 forks source link

macOS event queue won't wakeup under certain circumstances #89

Open martincapello opened 2 months ago

martincapello commented 2 months ago

I've found that when a laf client calls os::queue_event(ev) on macOS there is a chance that the event is not processed until some other OS event "wakes up" the queue. This can be seen when the getEvent() method is called from the main thread without a timeout, because when using a timeout, the timeout wakes up the queue and the issue is not perceived.

The issue can happen when the os::queue_event(ev) call takes place after line 77 and before line 82 in the following fragment of code: https://github.com/aseprite/laf/blob/695bb59d1a7de36747236f3f46854b614725da77/os/osx/event_queue.mm#L77-L86

Because the m_sleeping flag is still false in that moment, the queueEvent() method won't call the wakeUpQueue() method. Then the event got queued (in m_events queue) but then the queue will go to sleep (call to nextEventMatchingMask with untilDate=distantFuture because we are not using a timeout), waiting for any OS event to wake it up.

I think I've a fix for this which is basically a different approach, I'll try it with Aseprite and then create a PR.

EDIT: I've been trying this for a bit with Aseprite and it seems to work fine. Also I want to clarify why I need this fix: While developing our laf based UI library I wanted to let the main thread just read all the OS events and if there is no OS events then just wait for the next one, no timeout, just sit and wait. When an OS event is available I just translate it to an app event and then push it to the app event queue. This is because in a background thread I keep reading the app queue to then send app events to the appropriate widgets. Still lots of work to do, but I just wanted to let you know which was the use case made the current implementation fail.