Recent

Author Topic: NSApp.sendEvent call on cocoa based libraries - keyboard event problem  (Read 717 times)

freq

  • New Member
  • *
  • Posts: 13
Hi,
I’m having troubles with keyboard events in the recent 2.x Cocoa widgetset implementation that I didn’t had while using older 1.x Cocoa widgetset implementations. I’m using lazarus to create a library with an own LCL based UI.

I understand that keyboard events are coming in centralized via the TCocoaWidgetSet.AppRunMessages routine (line 80 cocoaobject.inc) and then are dispatched with the NSApp.sendEvent call. On a stand-alone app this is calling the overrided procedure TCocoaApplication.sendEvent that dispatching the message to the windows. That works great for stand-alone apps.

But for a library one will not get a TCocoaApplication instance from the FNSApp := TCocoaApplication.sharedApplication call (TCocoaWidgetSet.AppInit, line 39, cocoaobject.inc) but instead one will get the basic NSApp instance that was already created by the host process. That means the sendEvent call will not call the TCocoaApplication.sendEvent override and therefore the keyboard events will never been populated to the target forms or controls.
To my understanding an earlier development of the Cocoa Widgetset (around 2017) didn’t followed that centralized keyboard routing approach but populated the Cocoa events directly to the forms. So the problem didn’t exists in earlier 1.x versions of the cocoa widgetset.

Happy of every hint, insight, idea how to receive proper keyboard event on UI elements for a cocoa library.
Best
freq


skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2465
    • havefunsoft.com
your assessment is correct.

when your library is used. Are windows created by the library or by the host application?
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

freq

  • New Member
  • *
  • Posts: 13
Many thanks for the reply!

The window is created by the host application, I create a parented window and do the following sequence to show it:

...
  Application.Initialize;           // will be done only once on first load of plug-in
  WakeMainThread := nil;      // prevent for extra async (crashed some hosts)
...

  FEditorWindow := TfMain.CreateParented({%H-}HWnd(systemWindow));
  FEditorWindow.Handle; 
  FEditorWindow.ExtInit;     // init the windows controls
  FEditorWindow.Visible := True; 

Best
freq
« Last Edit: May 07, 2020, 02:01:12 pm by freq »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2465
    • havefunsoft.com
unfortunately parented window won't really help.

With the latest changes, keyboard handling event has been moved from each control processing, to NSApplication / NSWindow processing.

That helps to simplify handling of keyboard events. LCL doesn't have to override the method of every class it uses, but can keep all the code in one (two) places.

The downside for your project, is that you are loosing all the keyboard. Neither NSApplication, nor NSWindow are based upon LCL code, so nothing it transferred back to your controls.

It might be possible to make the latest version work for you, if keyboard event handling is done via global event monitors. But it still needs to be implemented.
I'm afraid, that the best option for you, is to stay on previous version
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

freq

  • New Member
  • *
  • Posts: 13
Mmm, this is bad news. I understand the rationale to centralize the keyboard handling but to make the event distribution NSApp.sendEvent dependent creates issues for macOS component/library developers. What if we would hook the keyboard events and distribute them independently from the NSApp class via e.g. a helper?

Thanks for any hint

Best
freq

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2465
    • havefunsoft.com
What if we would hook the keyboard events and distribute them independently from the NSApp class via e.g. a helper?
I'm not sure how a helper could do that.

Again, the best shot is using a local monitor
The problem is that API requires blocks. And blocks are supported by FPC nativity only for macOS 10.7 and later.
(blocks were introduced in 10.6, but run-time support is too limited)

Another issue is that monitor will not allow blocking of the event. But if you're using LCL code for library, it should not be problem.
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

 

TinyPortal © 2005-2018