Recent

Author Topic: Problem with receiving events NSApplication  (Read 3233 times)

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Problem with receiving events NSApplication
« on: February 24, 2021, 04:46:30 pm »
I have a subclass of NSApplication, processing events. In another thread I send events by calling postEvent_atStart()

Problem: in certain situations my events from thread #2 were never received.
It happens when:
- Toggle fullscreen window mode (during animation).
- Or when click X close button and hold the mouse button before release the button.
- Or when call a modal NSOpenPanel/NSSavePanel.

It seems that my application loop is paused at these moments and I can't receive any events.

I attach a simple test app. Another thread sends events calling postEvent_atStart every 1000 ms and the main thread writes numbers on the window title.

The question is: how to process events in these situation?
« Last Edit: February 24, 2021, 06:29:19 pm by Igor Kokarev »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Problem with receiving events NSApplication
« Reply #1 on: February 26, 2021, 10:17:52 pm »
It seems that my application loop is paused at these moments and I can't receive any events.
...
I attach a simple test app. Another thread sends events calling postEvent_atStart every 1000 ms and the main thread writes numbers on the window title.
...
The question is: how to process events in these situation?
That's the because the event queue in Cocoa is not exactly identical to Windows event loop.

Cocoa events processing has an extra layer of complexity. There are loop "run modes": Normal, Modal (for dialogs), Tracking (for mouse down). Certain events might not be processed in a certain mode. I.e. timer and mouse events will be processed at all times, while over events might be postponed.

Just posting an event doesn't guarantee it will be executed immediately, Cocoa might wait while the current mode is finished and only then execute the event.

If the purpose is only to synchronize threads, I'd suggest to try using performOnMainThread method. It has a slightly less overhead than creating an Event.  It also gives an option to control during what modes the selector can be performed.
This is what LCL does. Explained here

It should also prevent you from the need of overriding NSApplication class to get the event executed properly.
« Last Edit: February 26, 2021, 10:25:40 pm by skalogryz »

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Re: Problem with receiving events NSApplication
« Reply #2 on: February 27, 2021, 11:46:39 am »
Hi,

Thanks for your message and advice! We'll try performOnMainThread() method.

I'd like to explain that any custom event sent via postEvent_atStart() will NEVER arrive to our main loop when it sent in certain moments:

1. Resizing of main window by user with a mouse.
2. Clicking toggle fullscreen button.
3. Clicking green X close button.

Event processing is not delayed, it simply is getting lost. It seems to be a  serious bug in macOS. We can't rely on custom events mechanism, because we can send an important custom event and at this moment user decides to adjust main window size and this event is lost. Our sample test app shows this problem.
« Last Edit: February 27, 2021, 11:48:36 am by Igor Kokarev »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Problem with receiving events NSApplication
« Reply #3 on: February 27, 2021, 07:22:23 pm »
Event processing is not delayed, it simply is getting lost. It seems to be a  serious bug in macOS. We can't rely on custom events mechanism, because we can send an important custom event and at this moment user decides to adjust main window size and this event is lost. Our sample test app shows this problem.
I don't think they're lost but discarded intentionally by Cocoa processing.

For example, instead of pressing X, you might want to start resizing window. Don't release the mouse for some time to let the events accumulate.
After you release the mouse you might see the events were sent in the reverse order of them being posted.

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Re: Problem with receiving events NSApplication
« Reply #4 on: March 01, 2021, 07:43:29 pm »
We found a workaround for posting custom messages:

NSApplication > performSelectorOnMainThread_withObject_waitUntilDone()
(with sub-classing)

Our task is posting custom messages between our threads with a guaranted delivery.

I attach a new test app to show how it works. With a define  ASYNC_CALL.

P.S. It's not problem with delaying of our custom messages (accumulation) with a standard main loop. The problem in a fact that custom message can be lost (not delayed) with event loop.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Problem with receiving events NSApplication
« Reply #5 on: March 01, 2021, 10:36:46 pm »
NSApplication > performSelectorOnMainThread_withObject_waitUntilDone()
(with sub-classing)
You don't need to subclass the application.

Any object's selector can be scheduled for to perform on the main thread
Code: Pascal  [Select][+][-]
  1. type
  2.   TEventObject = obcclass(NSObject)
  3.     procedure runEvent; message 'runEvent';
  4.   end;
  5.  
  6. ...
  7.   obj := TEventObject.alloc.init;
  8.   obj.performSelectorOnMainThread( objcselector('runEvent') ...);
  9.   obj.release;
  10.  

 

TinyPortal © 2005-2018