Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.

Cef4D on Mac with Fpc - Help needed

User avatar
salvadordf
Posts: 4016
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Cef4D on Mac with Fpc - Help needed

Post by salvadordf »

I just saw all your work on the "fpc-for-discussion-context-init" branch and it looks really nice! :)

I don't think Delphi has a TMethodList class out of the box but it seems to be a good solution to the initialization.

Let me know when the MacOS demos are stable to remove the "experimental" label in the readme.
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

When you have some time (and I know I have been pushing a lot / i.e. pushing work your direction, not "git push") let me know where you want the latest commits to go. So no hurry.

I understand, you may not have the time to adapt the Lazarus work to be Delphi compatible. Or you may not like the concept of some of them. If so, that is ok. I can put them in a separate repro.
I can also put them in a separate repro and you can later decide to incorporate individual bits, as you see fit.

I would ask for the changes to existing components (such as new virtual methods in TBufferPanel) to be merged. As without some of my code can not work. (And I don't want to publish a copy of TBufferPanel).
I can create a new cut-down pull request, just for that.

Since you already merged "LazBrowserWindow", I would include changes to that.
Alternatively you can "un-merge" it, and I maintain it in a new repro.
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

salvadordf wrote: Sat Mar 06, 2021 1:54 pm I just saw all your work on the "fpc-for-discussion-context-init" branch and it looks really nice! :)

I don't think Delphi has a TMethodList class out of the box but it seems to be a good solution to the initialization.

Let me know when the MacOS demos are stable to remove the "experimental" label in the readme.
Did only see this post of yours now.

MacOS:

Both ExternalPumpBrowsers (Mac & any_OS) are fine.
BrowserWindow and BrowserWindowEx and BrowserWindowDow demo work fine for me (and need a larger test group)

The DOM examples both have one feature missing, while walking the DOM nodes there is no check for a 2nd overlapping node. So it takes the first node at the x/y pos, even if that is hidden by another node (google "I agree" screen).
However, it is a demo. It shows how to access DOM cross platform. So it serves its purpose.

OSR (BrowserWindowOsrDom) is not 100% supported on Mac.
On all OS, the user must add the SysKeys. But on Mac there also seems to be other keys (cursor movement) that I did not get working.
For all OS, the user would have to add sys-key handling if they needs it.
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

One observation about MacOS:

Any interaction (such as closing a browser) that requires CEF to send an event to the app, can only finish when the main event loop is running.

That is, CEF will not sent the required event, while the app is in a ButtonClick (or any other) event.
So the Button click has to finish, give control back to the main event loop, and then CEF will send the event.
Hence Application.ProcessMessages (and/or DoMessagePumpWork) do not have much of an effect in those cases.

This has an impact when it comes to modal windows (and must be addressed by the user, in their code).
Most modal windows are opened in ButtonPress or KeyPress events. But even though the modal form then runs it's own message loop, CEF still sees that the code is in the outer event. So until the ButtonPress returns any browser in the Modal form can not be closed.
The demo (BrowserWindowEx) works around this by opening the modal form in QueueAsyncCall. (not an event, does not block cef).

In theory modal forms could leave their browsers to be destroyed after they closed (at least on Mac).
I.e. On Mac it is possible to destroy the containing view, while the browser is still active (Somewhere in the docs, I found a reference that suggests this is possible for all OS, but at least Windows does not like that)
The TLazChromiumWrapper was planned for that purpose. But while I was fixing unrelated issue I moved away from keeping the browser open in such cases. So currently it's not doing much. But it could later serve as a base to re-establish such behaviour.
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

salvadordf wrote: Sat Mar 06, 2021 1:54 pm I don't think Delphi has a TMethodList class out of the box but it seems to be a good solution to the initialization.
It probably can be done by specializing a TGenericList<TNotifyEvent> / whatever it is called.

The important thing is, when calling the events, to start at the last event.

Code: Select all

c := count-1;
while c >= 0 do begin
  // call 
  if c > count then c := count;
  dec(c);
 end;
That way, if the event removes itself from the list while it is called, it will not affect the index of events still to be called.

Maybe iterators can deal with that in an even smarter way, don't know.
User avatar
salvadordf
Posts: 4016
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Cef4D on Mac with Fpc - Help needed

Post by salvadordf »

Thanks for all the new code and demos! :D

I'm still busy but II'll take a look at it in the weekend. Sorry for the delay.
User avatar
salvadordf
Posts: 4016
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Cef4D on Mac with Fpc - Help needed

Post by salvadordf »

martin_fr wrote: Thu Mar 11, 2021 4:04 pm When you have some time (and I know I have been pushing a lot / i.e. pushing work your direction, not "git push") let me know where you want the latest commits to go. So no hurry.

I understand, you may not have the time to adapt the Lazarus work to be Delphi compatible. Or you may not like the concept of some of them. If so, that is ok. I can put them in a separate repro.
I can also put them in a separate repro and you can later decide to incorporate individual bits, as you see fit.

I would ask for the changes to existing components (such as new virtual methods in TBufferPanel) to be merged. As without some of my code can not work. (And I don't want to publish a copy of TBufferPanel).
I can create a new cut-down pull request, just for that.

Since you already merged "LazBrowserWindow", I would include changes to that.
Alternatively you can "un-merge" it, and I maintain it in a new repro.
I merged all your code. Thanks again!!! :D

I'll try to incorporate everything I can into the Delphi components too but that requires time. Meanwhile, if you need to set some method as virtual to use them in the new components don't hesitate to create a pull request with that modification or just ask here.
martin_fr wrote: Thu Mar 11, 2021 4:45 pm OSR (BrowserWindowOsrDom) is not 100% supported on Mac.
On all OS, the user must add the SysKeys. But on Mac there also seems to be other keys (cursor movement) that I did not get working.
For all OS, the user would have to add sys-key handling if they needs it.
I can only show you that the official CEF sample application (cefclient) handles the key events for Mac here :
https://bitbucket.org/chromiumembedded/cef/src/4389/tests/cefclient/browser/browser_window_osr_mac.mm
https://bitbucket.org/chromiumembedded/cef/src/4389/tests/cefclient/browser/text_input_client_osr_mac.mm

Keyboard handling works perfectly in Windows but it has known issues in Linux. Try cefclient on your Mac to see if those keys work as expected before trying to support them in your demos.
martin_fr wrote: Thu Mar 11, 2021 5:05 pm
salvadordf wrote: Sat Mar 06, 2021 1:54 pm I don't think Delphi has a TMethodList class out of the box but it seems to be a good solution to the initialization.
It probably can be done by specializing a TGenericList<TNotifyEvent> / whatever it is called.

The important thing is, when calling the events, to start at the last event.

Code: Select all

c := count-1;
while c >= 0 do begin
  // call 
  if c > count then c := count;
  dec(c);
 end;
That way, if the event removes itself from the list while it is called, it will not affect the index of events still to be called.

Maybe iterators can deal with that in an even smarter way, don't know.
There are some interesting discussions about this here too :
https://www.delphipraxis.net/140952-methodenaufruf-ueber-adresse.html
https://groups.google.com/g/borland.public.delphi.objectpascal/c/ffosUBfosj8
https://www.summerswell.co.za/2013/09/tmethodlist-for-pre-generics-delphi/

I'll try to add this feature to the Delphi components when I have some time. I'll have to do it without generics to keep it working in the old Delphi versions.
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

Should I rename the TLazarusBrowserWindow and other classes/units that have Laz/Lazarus in there name?

If they are going to be usable for Delphi, then it would be better to rename them now.
User avatar
salvadordf
Posts: 4016
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Cef4D on Mac with Fpc - Help needed

Post by salvadordf »

martin_fr wrote: Fri Mar 19, 2021 9:15 pm Should I rename the TLazarusBrowserWindow and other classes/units that have Laz/Lazarus in there name?
If they are going to be usable for Delphi, then it would be better to rename them now.
Yes. Please rename it to TBrowserWindow.

I'll move some of the TLazChromium code to TChromiumCore as soon as I have time. :oops:

Thank you!!! :)
martin_fr
Posts: 30
Joined: Wed Jan 27, 2021 5:56 pm

Re: Cef4D on Mac with Fpc - Help needed

Post by martin_fr »

Just an observation... It works, but....

Setting

Code: Select all

  MultiThreadedMessageLoop  := False;
  MultiBrowserMode := true;
Means that AddBrowser is called twice for the same browser.
Anyway AddBrowser checks if the ID is already in the list. So the 2nd call does not do any harm.

But then why have code like

Code: Select all

procedure TChromiumCore.doOnAfterCreated(const browser: ICefBrowser);
begin
  if MultithreadApp or MultiBrowserMode then
    AddBrowser(browser);
Why not always call AddBrowser?
In case of "MultiThreadedMessageLoop := False;" the following is run.

Code: Select all

function TChromiumCore.CreateBrowserHostSync(      ....
begin
  TempURL     := CefString(aURL);
  TempBrowser := TCefBrowserRef.UnWrap(cef_browser_host_create_browser_sync(aWindowInfo, FHandler.Wrap, @TempURL, aSettings, CefGetData(aExtraInfo), CefGetData(aContext)));
  Result      := AddBrowser(TempBrowser);
Which adds the browser from the Main-Thread of the App (because in single thread mode that is the "browser process UI thread").

However, the only benefit (that I can think of) is, that by the time "CreateBrowser" returns, the browser has definitely been added.
Without this, or in Multi-Thread mode the browser is only added when the OnBrowserCreated event (in the UI thread) was executed. And that can be at a later time.

However the downside is, OnBrowserCreated can be called before the "CreateBrowser" call returns. In that case, any code running in the event does not see the browser as being added (and Chromium.Initialized may return false).

If "doOnAfterCreated" would call "AddBrowser" unconditionally, the browser would always be added at the earliest time possible (which ever comes first).

In my tests, in single-thread mode, on Windows, the event is actually called before the cef_browser_host_create_browser_sync call returns.
But that may not be guaranteed.
Post Reply