1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-09-30 21:28:55 +02:00

Fixed missing GlobalCEFApp property in SimpleOSRBrowser for QT

Removed TChromiumCore.OnClose from SimpleBrowser for QT6
Added code comments to all QT demos
This commit is contained in:
Salvador Díaz Fau
2025-09-21 16:18:10 +02:00
parent f893242ad0
commit ed15f1cca3
7 changed files with 176 additions and 19 deletions

View File

@@ -14,7 +14,7 @@
<Icon Value="0"/>
</General>
<MacroValues Count="1">
<Macro2 Name="LCLWidgetType" Value="qt5"/>
<Macro1 Name="LCLWidgetType" Value="qt5"/>
</MacroValues>
<BuildModes>
<Item Name="Default" Default="True"/>
@@ -59,7 +59,7 @@
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="../../../bin/SimpleOSRBrowserQT"/>
<Filename Value="../../../bin/SimpleOSRBrowser"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>

View File

@@ -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,
@@ -146,6 +217,7 @@ begin
GlobalCEFApp.RootCache := 'RootCache';
GlobalCEFApp.SetCurrentDir := True;
GlobalCEFApp.DisableZygote := True;
GlobalCEFApp.WindowlessRenderingEnabled := True;
GlobalCEFApp.OnContextInitialized := @GlobalCEFApp_OnContextInitialized;
end;

View File

@@ -116,7 +116,6 @@ object MainForm: TMainForm
OnBeforePopup = Chromium1BeforePopup
OnAfterCreated = Chromium1AfterCreated
OnBeforeClose = Chromium1BeforeClose
OnClose = Chromium1Close
OnOpenUrlFromTab = Chromium1OpenUrlFromTab
Left = 106
Top = 69

View File

@@ -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

View File

@@ -80,9 +80,6 @@
<IgnoredMessages idx5024="True"/>
</CompilerMessages>
<CustomOptions Value="-dUseCThreads"/>
<OtherDefines Count="1">
<Define0 Value="UseCThreads"/>
</OtherDefines>
</Other>
</CompilerOptions>
<Debugging>

View File

@@ -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;

View File

@@ -2,7 +2,7 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
"InternalVersion" : 790,
"InternalVersion" : 791,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "140.1.14"
}