CEF initialization with FMXLinux

Issue #254 open
Salvador Diaz Fau created an issue

Hi,

We are trying to embed a CEF browser with CEF4Delphi in FMXLinux applications and we are having problems in the Chromium initialization.

Chromium requires that there only be a single thread during initialization and FMXLinux is initializing GTK even before the app executes the first code line in the DPR file.

We see several threads after the FmuxInit call in TPlatformLinux.Create, which is called inside RegisterCorePlatformServices.

The problem is that RegisterCorePlatformServices is called inside the “initialization” section of FMX.Platform and we can’t modify or delay any of this.

We also tried calling g_application_quit, gtk_main_quit and FmuxTerminate before the CEF initialization without success.

We would like to know if there’s any way to delay the GTK initialization with the current FMXLinux version or if you could add this possibility in the next FMXLinux release.

Thank you for your help!

Salvador Diaz Fau,
Maintainer of the CEF4Delphi project.

Comments (10)

  1. Salvador Diaz Fau reporter

    We found a way to initialize CEF in another "initialization" section of another unit and using a different executable for the CEF processes.

    However, this is just a workaround that forces us to always use a different executable for the CEF processes.

    It would be great if you could suggest another solution.

  2. Eugene Kryukov repo owner

    How is DPR file looks in CEF project ?

    We can add callback calling, but this will require adding some IFDEFs for Linux (since we can’t change FireMonkey sources).

    For example we can declare procedure variable BeforeStart to FMX.Platform.Linux and call this function before GTK initialization. What do you thing ?

    I guess better to discuss this directly by email support@ksdev.com

  3. Salvador Diaz Fau reporter

    We’ll upload a demo this afternoon and I’ll send you an email message.
    Thank you again!

  4. Salvador Diaz Fau reporter
    • changed status to open

    We've uploaded a beta version of the first demo working in FMXLinux : https://github.com/salvadordf/CEF4Delphi/tree/master/demos/Delphi_FMX/FMXExternalPumpBrowser2

    Some features are still missing like keyboard input, cursor change, etc.

    The current DPR file for the main executable is this : https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Delphi_FMX/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2.dpr

    As you can see, uCEFLoader.pas is the first unit in the uses section to avoid initialization problems with GTK.

    This solution forces us to always use a different executable (called FMXExternalPumpBrowser2_sp in this demo) for the CEF subprocesses.

    In other demos we use the same executable for the main application process and all the subprocesses. The DPR file in that case is this : https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Delphi_FMX/SimpleFMXBrowser/SimpleFMXBrowser.dpr

    Each time Chromium needs to create another subprocess it executes the main executable again but the execution remains inside "GlobalCEFApp.StartMainProcess" and returns false to avoid creating another instance of the application.

    I don't know all the details about the FMXLinux code but I see 2 possible solutions :

    • Adding a callback as you suggested. This would make things easier to initialize CEF although we would still be limited to use a different executable for the subprocesses.
    • Adding a IFNDEF in the TPlatformLinux.Create constructor to avoid the FmuxInit call.

    I don't know if the second solution is possible. Perhaps other parts of the FMX initialization code requires the FmuxInit call before the Application.Initialize call but in case it's not needed we would only have to call it manually like this :

    CreateGlobalCEFApp; // This function only creates and configures a class used globally by the application but it doesn't initialize Chromium.

      if GlobalCEFApp.StartMainProcess then // This function initializes Chromium and returns true immediately for the main application process only.
        begin
          FmuxInit(0); // This line would only be called in the main application process before the first form is created
          Application.Initialize;
          Application.CreateForm(TSimpleFMXBrowserFrm, SimpleFMXBrowserFrm);
          Application.Run;
    
          SimpleFMXBrowserFrm.Free;
        end;
    
      DestroyGlobalCEFApp;
    

    This is a similar solution that we used to support Lazarus in Linux. We had the exact same problem with the GTK initialization and we had to create a couple of custom functions to initialize GTK manually after the CEF initialization : https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Lazarus_Linux/SimpleBrowser2/SimpleBrowser2.lpr

      CreateGlobalCEFApp;
    
      if GlobalCEFApp.StartMainProcess then
        begin
          CustomWidgetSetInitialization; // This is the custom function used to initialize GTK in Lazarus
          RequireDerivedFormResource:=True;
          Application.Scaled:=True;
          Application.Initialize;
          Application.CreateForm(TForm1, Form1);
          Application.Run;               
          CustomWidgetSetFinalization;
        end;
    
      DestroyGlobalCEFApp;
    

    The second solution would be the best for all Chromium configurations but you know better than anyone else the FMXLinux code and perhaps it's not possible to implement.

    Let us know if you need more information about CEF4Delphi, CEF or Chromium and thank you again for your help!!!

  5. Eugene Kryukov repo owner

    What if add “DoNoCallFmuxInit” boolean variable to Fmx.Platform.Linux.pas (or FMUX.API.pas) ? Since uCEFLoader is a first unit, you can set this variable in uCEFLoader.initialization ? Do you think this will work ?

  6. Eugene Kryukov repo owner

    I’ve made simple test and variable in Fmx.Platform.Linux & FMUX.API doesn’t work. But, i works if we create new FMUX.Config.pas without any other dependents. So, in this case in your uCEFLoader you add FMUX.Config.pas and set DoNotCallFmuxInit variable to True.

  7. Salvador Diaz Fau reporter
    • changed status to open

    Hi,

    A user reported that the latest CEF4Delphi demo in Linux was having an initialization issue when he updated FMXLinux.

    The FMX.Platform.Linux.pas unit is calling FmuxSetLog in the initialization section and that's creating an access violation when DoNotCallFmuxInit is true.

    Could you check the DoNotCallFmuxInit value before calling FmuxSetLog?

    initialization
      {$IFDEF FmxRuntimePackage}
      LoadLib;
      InitControls;
      {$ENDIF}
      if not DoNotCallFmuxInit then
        FmuxSetLog(FmuxLog);
    
  8. Log in to comment