0

For a cross-platform project with much legacy code, my Cocoa app uses only one NSWindow with a custom NSView that captures all the mouse events and draws all my app graphic details.

I need to implement a local modal behavior and so I use inside the main thread:

CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, false);

inside a locale loop. The function returns after 0.01 sec as expected with a value of kCFRunLoopRunTimedOut. However, the mouse events are during that time no more received by the custom NSView and so my app looks like it is frozen (with the color mouse cursor going round and round).

Timer events still arrive to the custom NSView, but not mouse events.

Apple specifies that this function can be called recursively. Is there anything else I should do so that the NSView still receives the user mouse inputs ?

Dominique
  • 33
  • 5
  • Put a breakpoint on the line that calls `CFRunLoopRunInMode`. When the breakpoint is hit, copy the stack trace. Edit your question and paste in the stack trace. – rob mayoff Jun 17 '17 at 20:34

1 Answers1

1

The event loop is built on top of a run loop, but it's more than that. Merely running the run loop is not enough to receive and handle events.

You can perhaps achieve some of what you're trying to do by building a loop around -[NSWindow nextEventMatchingMask:untilDate:inMode:dequeue:] and -sendEvent:, but really it's not clear what your objective is. If you explain that, there are probably superior approaches.

For example, if you want to present a modal dialog, you should use -[NSApplication runModalForWindow:].

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Thanks Ken, indeed it works perfectly as expected by simply using the following two lines inside my local loop : – Dominique Jun 19 '17 at 21:36
  • `event = [mainWindow nextEventMatchingMask:NSUIntegerMax untilDate:[NSDate dateWithTimeIntervalSinceNow:0.010] inMode:NSDefaultRunLoopMode dequeue:YES]; if (event) [mainWindow sendEvent:event];` – Dominique Jun 19 '17 at 21:37
  • The main problem I face in this legacy code (300,000 lines of C++ code) is that there are plenty of "modal" loops all included inside their function. Most of these functions are specific (but quite complex) handler of one user action starting with a mouse down, handling the flow of mouse moves and only exit the function on the mouse up event. Refactoring the whole code to separate the handling of each mouse action would be a real big work and would most probably introduce bugs in a part of the code that works well, as these interactions are quite complex. – Dominique Jun 19 '17 at 21:47
  • But your solution works perfectly for this purpose, thanks a lot ! – Dominique Jun 19 '17 at 21:47
  • You're welcome! If these loops are for mouse tracking, you should read [this](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW18). For example, one tweak would be to use `NSEventTrackingRunLoopMode` instead of `NSDefaultRunLoopMode`. You might want to call `-sendEvent:` on `event.window` instead of `mainWindow`, just to be safe. You might also want to specify a real event mask, too. – Ken Thomases Jun 19 '17 at 22:12
  • Thanks for the additional information. In fact there are other cases too where I need this modal behaviour, so the above solution seems to work ok. I keep your information in case I find a more complex case. – Dominique Jun 20 '17 at 14:00