Recent

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

freq

  • New Member
  • *
  • Posts: 22
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: 2770
    • havefunsoft.com
your assessment is correct.

when your library is used. Are windows created by the library or by the host application?

freq

  • New Member
  • *
  • Posts: 22
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: 2770
    • 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

freq

  • New Member
  • *
  • Posts: 22
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: 2770
    • 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.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: NSApp.sendEvent call on cocoa based libraries - keyboard event problem
« Reply #6 on: August 06, 2020, 05:41:22 am »
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.
This is actually depends on the Host process.
If the Host process is initializing using the bundle. (i.e. LCL is a bit harsh at this moment), then you should be able to specify "TCocoaApplication" as  NSPrincipleClass in the info.plist of the application bundle.

If everything goes as it should, the launching service should be able to find TCocoaApplication in your library and initialize the class.
As a result, you should have your keyboard events working again.

It is KNOWN how non-LCL controls will react on TCocoaApplication (never tested) Yet, there's a chance that everything will work fine out of the box.

Inspired by https://bugs.freepascal.org/view.php?id=37487
« Last Edit: August 06, 2020, 05:53:03 am by skalogryz »

 

TinyPortal © 2005-2018