diff --git a/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/SimpleOSRBrowser.lpi b/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/SimpleOSRBrowser.lpi
index 84ba6405..1778801f 100644
--- a/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/SimpleOSRBrowser.lpi
+++ b/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/SimpleOSRBrowser.lpi
@@ -14,7 +14,7 @@
-
+
@@ -59,7 +59,7 @@
-
+
diff --git a/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/umainform.pas b/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/umainform.pas
index 5d163eeb..d9bfbc52 100644
--- a/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/umainform.pas
+++ b/demos/Lazarus_Linux_QT5/SimpleOSRBrowser/umainform.pas
@@ -119,6 +119,77 @@ implementation
{$R *.lfm}
+// This is a simple CEF browser in "off-screen rendering" mode (a.k.a OSR mode)
+
+// It uses the default CEF configuration with a multithreaded message loop and
+// that means that the TChromium events are executed in a CEF thread.
+
+// QT is not thread safe so we have to save all the information given in the
+// TChromium events and use it later in the main application thread. We use
+// critical sections to protect all that information.
+
+// For example, the browser updates the mouse cursor in the
+// TChromium.OnCursorChange event so we have to save the cursor in FPanelCursor
+// and use Application.QueueAsyncCall to update the Panel1.Cursor value in the
+// main application thread.
+
+// The raw bitmap information given in the TChromium.OnPaint event also needs to
+// be stored in a TCEFBitmapBitBuffer class instead of a simple TBitmap to avoid
+// issues with QT.
+
+// Chromium renders the web contents asynchronously. It uses multiple processes
+// and threads which makes it complicated to keep the correct browser size.
+
+// In one hand you have the main application thread where the form is resized by
+// the user. On the other hand, Chromium renders the contents asynchronously
+// with the last browser size available, which may have changed by the time
+// Chromium renders the page.
+
+// For this reason we need to keep checking the real size and call
+// TChromium.WasResized when we detect that Chromium has an incorrect size.
+
+// TChromium.WasResized triggers the TChromium.OnGetViewRect event to let CEF
+// read the current browser size and then it triggers TChromium.OnPaint when the
+// contents are finally rendered.
+
+// TChromium.WasResized --> (time passes) --> TChromium.OnGetViewRect --> (time passes) --> TChromium.OnPaint
+
+// You have to assume that the real browser size can change between those calls
+// and events.
+
+// This demo uses a couple of fields called "FResizing" and "FPendingResize" to
+// reduce the number of TChromium.WasResized calls.
+
+// FResizing is set to True before the TChromium.WasResized call and it's set to
+// False at the end of the TChromium.OnPaint event.
+
+// FPendingResize is set to True when the browser changed its size while
+// FResizing was True. The FPendingResize value is checked at the end of
+// TChromium.OnPaint to check the browser size again because it changed while
+// Chromium was rendering the page.
+
+// The TChromium.OnPaint event in the demo also calls
+// TBufferPanel.UpdateOrigBufferDimensions and TBufferPanel.BufferIsResized to check
+// the width and height of the buffer parameter, and the internal buffer size in
+// the TBufferPanel component.
+
+// Lazarus usually initializes the QT WidgetSet in the initialization section
+// of the "Interfaces" unit which is included in the LPR file. This causes
+// initialization problems in CEF and we need to call "CreateWidgetset" after
+// the GlobalCEFApp.StartMainProcess call.
+
+// Lazarus shows a warning if we remove the "Interfaces" unit from the LPR file
+// so we created a custom unit with the same name that includes two procedures
+// to initialize and finalize the WidgetSet at the right time.
+
+// This is the destruction sequence in OSR mode :
+// 1- FormCloseQuery sets CanClose to the initial FCanClose value (False) and
+// calls Chromium1.CloseBrowser(True) which will destroy the internal browser
+// immediately.
+// 2- Chromium1.OnBeforeClose is triggered because the internal browser was
+// destroyed. FCanClose is set to True and calls
+// SendCompMessage(CEF_BEFORECLOSE) to close the form asynchronously.
+
uses
Math,
uCEFMiscFunctions, uCEFApplication, uCEFConstants, uCEFBitmapBitBuffer,
@@ -145,7 +216,8 @@ begin
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
GlobalCEFApp.RootCache := 'RootCache';
GlobalCEFApp.SetCurrentDir := True;
- GlobalCEFApp.DisableZygote := True;
+ GlobalCEFApp.DisableZygote := True;
+ GlobalCEFApp.WindowlessRenderingEnabled := True;
GlobalCEFApp.OnContextInitialized := @GlobalCEFApp_OnContextInitialized;
end;
diff --git a/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.lfm b/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.lfm
index ed963bb5..6dd632e7 100644
--- a/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.lfm
+++ b/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.lfm
@@ -116,7 +116,6 @@ object MainForm: TMainForm
OnBeforePopup = Chromium1BeforePopup
OnAfterCreated = Chromium1AfterCreated
OnBeforeClose = Chromium1BeforeClose
- OnClose = Chromium1Close
OnOpenUrlFromTab = Chromium1OpenUrlFromTab
Left = 106
Top = 69
diff --git a/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.pas b/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.pas
index d30ead86..0383f85f 100644
--- a/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.pas
+++ b/demos/Lazarus_Linux_QT6/SimpleBrowser/umainform.pas
@@ -26,7 +26,6 @@ type
procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; popup_id: Integer; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean);
- procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
procedure Chromium1GotFocus(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1OpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean);
@@ -69,6 +68,33 @@ implementation
{$R *.lfm}
+// This is a demo with the simplest web browser you can build using CEF4Delphi and
+// it doesn't show any sign of progress like other web browsers do.
+
+// Remember that it may take a few seconds to load if Windows update, your antivirus or
+// any other windows service is using your hard drive.
+
+// Depending on your internet connection it may take longer than expected.
+
+// Please check that your firewall or antivirus are not blocking this application
+// or the domain "google.com". If you don't live in the US, you'll be redirected to
+// another domain which will take a little time too.
+
+// This demo uses a TChromium and a TCEFLinkedWindowParent
+
+// We need to use TCEFLinkedWindowParent in Linux to update the browser
+// visibility and size automatically.
+
+// Most of the TChromium events are executed in a CEF thread and this causes
+// issues with most QT API functions. If you need to update the GUI, store the
+// TChromium event parameters and use SendCompMessage (Application.QueueAsyncCall)
+// to do it in the main application thread.
+
+// Destruction steps
+// =================
+// 1. FormCloseQuery sets CanClose to FALSE, destroys CEFLinkedWindowParent1 and calls TChromium.CloseBrowser which triggers the TChromium.OnBeforeClose event.
+// 2. TChromium.OnBeforeClose sets FCanClose := True and sends CEF_BEFORECLOSE to close the form.
+
uses
Math,
uCEFMiscFunctions, uCEFApplication, uCEFLinuxFunctions, uCEFConstants;
@@ -145,9 +171,7 @@ begin
FClosing := True;
Visible := False;
Chromium1.CloseBrowser(True);
-
- if Chromium1.RuntimeStyle = CEF_RUNTIME_STYLE_CHROME then
- CEFLinkedWindowParent1.Free;
+ CEFLinkedWindowParent1.Free;
end;
end;
{%Endregion}
@@ -262,13 +286,6 @@ begin
Result := (targetDisposition in [CEF_WOD_NEW_FOREGROUND_TAB, CEF_WOD_NEW_BACKGROUND_TAB, CEF_WOD_NEW_POPUP, CEF_WOD_NEW_WINDOW]);
end;
-procedure TMainForm.Chromium1Close(Sender: TObject; const browser: ICefBrowser;
- var aAction: TCefCloseBrowserAction);
-begin
- // continue closing the browser
- aAction := cbaClose;
-end;
-
procedure TMainForm.Chromium1GotFocus(Sender: TObject;
const browser: ICefBrowser);
begin
diff --git a/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/SimpleOSRBrowser.lpi b/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/SimpleOSRBrowser.lpi
index b05b494f..9a76bdd6 100644
--- a/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/SimpleOSRBrowser.lpi
+++ b/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/SimpleOSRBrowser.lpi
@@ -80,9 +80,6 @@
-
-
-
diff --git a/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/umainform.pas b/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/umainform.pas
index 030f30d8..71bbe732 100644
--- a/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/umainform.pas
+++ b/demos/Lazarus_Linux_QT6/SimpleOSRBrowser/umainform.pas
@@ -119,6 +119,77 @@ implementation
{$R *.lfm}
+// This is a simple CEF browser in "off-screen rendering" mode (a.k.a OSR mode)
+
+// It uses the default CEF configuration with a multithreaded message loop and
+// that means that the TChromium events are executed in a CEF thread.
+
+// QT is not thread safe so we have to save all the information given in the
+// TChromium events and use it later in the main application thread. We use
+// critical sections to protect all that information.
+
+// For example, the browser updates the mouse cursor in the
+// TChromium.OnCursorChange event so we have to save the cursor in FPanelCursor
+// and use Application.QueueAsyncCall to update the Panel1.Cursor value in the
+// main application thread.
+
+// The raw bitmap information given in the TChromium.OnPaint event also needs to
+// be stored in a TCEFBitmapBitBuffer class instead of a simple TBitmap to avoid
+// issues with QT.
+
+// Chromium renders the web contents asynchronously. It uses multiple processes
+// and threads which makes it complicated to keep the correct browser size.
+
+// In one hand you have the main application thread where the form is resized by
+// the user. On the other hand, Chromium renders the contents asynchronously
+// with the last browser size available, which may have changed by the time
+// Chromium renders the page.
+
+// For this reason we need to keep checking the real size and call
+// TChromium.WasResized when we detect that Chromium has an incorrect size.
+
+// TChromium.WasResized triggers the TChromium.OnGetViewRect event to let CEF
+// read the current browser size and then it triggers TChromium.OnPaint when the
+// contents are finally rendered.
+
+// TChromium.WasResized --> (time passes) --> TChromium.OnGetViewRect --> (time passes) --> TChromium.OnPaint
+
+// You have to assume that the real browser size can change between those calls
+// and events.
+
+// This demo uses a couple of fields called "FResizing" and "FPendingResize" to
+// reduce the number of TChromium.WasResized calls.
+
+// FResizing is set to True before the TChromium.WasResized call and it's set to
+// False at the end of the TChromium.OnPaint event.
+
+// FPendingResize is set to True when the browser changed its size while
+// FResizing was True. The FPendingResize value is checked at the end of
+// TChromium.OnPaint to check the browser size again because it changed while
+// Chromium was rendering the page.
+
+// The TChromium.OnPaint event in the demo also calls
+// TBufferPanel.UpdateOrigBufferDimensions and TBufferPanel.BufferIsResized to check
+// the width and height of the buffer parameter, and the internal buffer size in
+// the TBufferPanel component.
+
+// Lazarus usually initializes the QT WidgetSet in the initialization section
+// of the "Interfaces" unit which is included in the LPR file. This causes
+// initialization problems in CEF and we need to call "CreateWidgetset" after
+// the GlobalCEFApp.StartMainProcess call.
+
+// Lazarus shows a warning if we remove the "Interfaces" unit from the LPR file
+// so we created a custom unit with the same name that includes two procedures
+// to initialize and finalize the WidgetSet at the right time.
+
+// This is the destruction sequence in OSR mode :
+// 1- FormCloseQuery sets CanClose to the initial FCanClose value (False) and
+// calls Chromium1.CloseBrowser(True) which will destroy the internal browser
+// immediately.
+// 2- Chromium1.OnBeforeClose is triggered because the internal browser was
+// destroyed. FCanClose is set to True and calls
+// SendCompMessage(CEF_BEFORECLOSE) to close the form asynchronously.
+
uses
Math,
uCEFMiscFunctions, uCEFApplication, uCEFConstants, uCEFBitmapBitBuffer,
@@ -143,6 +214,7 @@ begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.LogFile := 'debug.log';
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
+ GlobalCEFApp.WindowlessRenderingEnabled := True;
GlobalCEFApp.RootCache := 'RootCache';
GlobalCEFApp.SetCurrentDir := True;
GlobalCEFApp.DisableZygote := True;
diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json
index c7b1e6e8..d34dfc36 100644
--- a/update_CEF4Delphi.json
+++ b/update_CEF4Delphi.json
@@ -2,7 +2,7 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
- "InternalVersion" : 790,
+ "InternalVersion" : 791,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "140.1.14"
}