From e3f1a0902d582c85adcb631b5f19fc924135247d Mon Sep 17 00:00:00 2001 From: Salvador Diaz Fau Date: Fri, 1 Jan 2021 17:51:09 +0100 Subject: [PATCH] Added Printing support in Linux Added the GlobalCEFApp.DisableZygote property Added the GlobalCEFApp.OnPrintStart event. Added the GlobalCEFApp.OnPrintSettings event. Added the GlobalCEFApp.OnPrintDialog event. Added the GlobalCEFApp.OnPrintJob event. Added the GlobalCEFApp.OnPrintReset event. Added the GlobalCEFApp.OnGetPDFPaperSize event. --- .../ExternalPumpBrowser.lps | 8 +- .../uExternalPumpBrowser.pas | 5 +- .../SimpleBrowser2/SimpleBrowser2.lps | 162 ++++----- .../SimpleBrowser2/usimplebrowser2.lfm | 4 +- .../SimpleBrowser2/usimplebrowser2.pas | 1 - packages/CEF4Delphi.dpk | 5 +- packages/CEF4Delphi_D7.dpk | 5 +- packages/CEF4Delphi_FMX.dpk | 5 +- packages/CEF4Delphi_FMX.dproj | 3 + packages/cef4delphi_lazarus.lpk | 14 +- packages/cef4delphi_lazarus.pas | 1 + source/uCEFApplicationCore.pas | 101 +++++- source/uCEFBrowserProcessHandler.pas | 28 +- source/uCEFInterfaces.pas | 15 +- source/uCEFPrintDialogCallback.pas | 87 +++++ source/uCEFPrintHandler.pas | 319 ++++++++++++++++++ source/uCEFPrintJobCallback.pas | 81 +++++ update_CEF4Delphi.json | 2 +- 18 files changed, 720 insertions(+), 126 deletions(-) create mode 100644 source/uCEFPrintDialogCallback.pas create mode 100644 source/uCEFPrintHandler.pas create mode 100644 source/uCEFPrintJobCallback.pas diff --git a/demos/Lazarus_Linux/ExternalPumpBrowser/ExternalPumpBrowser.lps b/demos/Lazarus_Linux/ExternalPumpBrowser/ExternalPumpBrowser.lps index e5729894..c1e8c995 100644 --- a/demos/Lazarus_Linux/ExternalPumpBrowser/ExternalPumpBrowser.lps +++ b/demos/Lazarus_Linux/ExternalPumpBrowser/ExternalPumpBrowser.lps @@ -19,12 +19,12 @@ - - + + - - + + diff --git a/demos/Lazarus_Linux/ExternalPumpBrowser/uExternalPumpBrowser.pas b/demos/Lazarus_Linux/ExternalPumpBrowser/uExternalPumpBrowser.pas index 24695d55..26fad6df 100644 --- a/demos/Lazarus_Linux/ExternalPumpBrowser/uExternalPumpBrowser.pas +++ b/demos/Lazarus_Linux/ExternalPumpBrowser/uExternalPumpBrowser.pas @@ -138,8 +138,6 @@ begin // GlobalCEFApp.StartMainProcess call. GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil); - //sleep(1000); - GlobalCEFApp := TCefApplication.Create; GlobalCEFApp.ExternalMessagePump := True; GlobalCEFApp.MultiThreadedMessageLoop := False; @@ -147,7 +145,7 @@ begin // This is a workaround for the 'GPU is not usable error' issue : // https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef - GlobalCEFApp.AddCustomCommandLine('--no-zygote'); + GlobalCEFApp.DisableZygote := True; // this property adds the "--no-zygote" command line switch { GlobalCEFApp.LogFile := 'cef.log'; GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE; @@ -170,6 +168,7 @@ end; procedure TForm1.Timer1Timer(Sender: TObject); begin Timer1.Enabled := False; + if not(Chromium1.CreateBrowser(CEFLinkedWindowParent1.Handle, CEFLinkedWindowParent1.BoundsRect)) and not(Chromium1.Initialized) then Timer1.Enabled := True; diff --git a/demos/Lazarus_Linux/SimpleBrowser2/SimpleBrowser2.lps b/demos/Lazarus_Linux/SimpleBrowser2/SimpleBrowser2.lps index 850d37a5..d83991b6 100644 --- a/demos/Lazarus_Linux/SimpleBrowser2/SimpleBrowser2.lps +++ b/demos/Lazarus_Linux/SimpleBrowser2/SimpleBrowser2.lps @@ -3,14 +3,14 @@ - + - + @@ -19,10 +19,12 @@ - - + + + + - + @@ -32,7 +34,7 @@ - + @@ -106,11 +108,10 @@ - + - @@ -140,16 +141,14 @@ - - - + + - @@ -235,11 +234,10 @@ - + - + - @@ -265,22 +263,22 @@ - - - + + + - + - - + + @@ -413,128 +411,90 @@ + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.lfm b/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.lfm index fc229b62..2504cd88 100644 --- a/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.lfm +++ b/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.lfm @@ -1,7 +1,7 @@ object Form1: TForm1 - Left = 768 + Left = 380 Height = 589 - Top = 220 + Top = 222 Width = 967 Caption = 'Initializing browser. Please wait...' ClientHeight = 589 diff --git a/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.pas b/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.pas index 9bd82d29..ec2859d6 100644 --- a/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.pas +++ b/demos/Lazarus_Linux/SimpleBrowser2/usimplebrowser2.pas @@ -130,7 +130,6 @@ uses { TForm1 } - procedure CreateGlobalCEFApp; begin GlobalCEFApp := TCefApplication.Create; diff --git a/packages/CEF4Delphi.dpk b/packages/CEF4Delphi.dpk index ff7b6fcb..e7542ad0 100644 --- a/packages/CEF4Delphi.dpk +++ b/packages/CEF4Delphi.dpk @@ -218,7 +218,10 @@ contains uCEFDevToolsMessageObserver in '..\source\uCEFDevToolsMessageObserver.pas', uCEFMediaSinkDeviceInfoCallback in '..\source\uCEFMediaSinkDeviceInfoCallback.pas', uCEFJson in '..\source\uCEFJson.pas', - uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas'; + uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas', + uCEFPrintHandler in '..\source\uCEFPrintHandler.pas', + uCEFPrintDialogCallback in '..\source\uCEFPrintDialogCallback.pas', + uCEFPrintJobCallback in '..\source\uCEFPrintJobCallback.pas'; end. diff --git a/packages/CEF4Delphi_D7.dpk b/packages/CEF4Delphi_D7.dpk index 1ceb5eb8..4a902724 100644 --- a/packages/CEF4Delphi_D7.dpk +++ b/packages/CEF4Delphi_D7.dpk @@ -215,6 +215,9 @@ contains uCEFDevToolsMessageObserver in '..\source\uCEFDevToolsMessageObserver.pas', uCEFMediaSinkDeviceInfoCallback in '..\source\uCEFMediaSinkDeviceInfoCallback.pas', uCEFJson in '..\source\uCEFJson.pas', - uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas'; + uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas', + uCEFPrintHandler in '..\source\uCEFPrintHandler.pas', + uCEFPrintDialogCallback in '..\source\uCEFPrintDialogCallback.pas', + uCEFPrintJobCallback in '..\source\uCEFPrintJobCallback.pas'; end. diff --git a/packages/CEF4Delphi_FMX.dpk b/packages/CEF4Delphi_FMX.dpk index 58d6f454..4eea22d1 100644 --- a/packages/CEF4Delphi_FMX.dpk +++ b/packages/CEF4Delphi_FMX.dpk @@ -223,7 +223,10 @@ contains uCEFDevToolsMessageObserver in '..\source\uCEFDevToolsMessageObserver.pas', uCEFMediaSinkDeviceInfoCallback in '..\source\uCEFMediaSinkDeviceInfoCallback.pas', uCEFJson in '..\source\uCEFJson.pas', - uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas'; + uCEFBitmapBitBuffer in '..\source\uCEFBitmapBitBuffer.pas', + uCEFPrintHandler in '..\source\uCEFPrintHandler.pas', + uCEFPrintDialogCallback in '..\source\uCEFPrintDialogCallback.pas', + uCEFPrintJobCallback in '..\source\uCEFPrintJobCallback.pas'; end. diff --git a/packages/CEF4Delphi_FMX.dproj b/packages/CEF4Delphi_FMX.dproj index e415e85d..45df72e4 100644 --- a/packages/CEF4Delphi_FMX.dproj +++ b/packages/CEF4Delphi_FMX.dproj @@ -339,6 +339,9 @@ + + + Base diff --git a/packages/cef4delphi_lazarus.lpk b/packages/cef4delphi_lazarus.lpk index 7cd89483..09048a4b 100644 --- a/packages/cef4delphi_lazarus.lpk +++ b/packages/cef4delphi_lazarus.lpk @@ -22,7 +22,7 @@ - + @@ -799,6 +799,18 @@ + + + + + + + + + + + + diff --git a/packages/cef4delphi_lazarus.pas b/packages/cef4delphi_lazarus.pas index a38dda1e..ad1542a6 100644 --- a/packages/cef4delphi_lazarus.pas +++ b/packages/cef4delphi_lazarus.pas @@ -63,6 +63,7 @@ uses uCEFScrollViewComponent, uCEFTextfieldComponent, uCEFViewComponent, uCEFViewsFrameworkEvents, uCEFAudioHandler, uCEFDevToolsMessageObserver, uCEFMediaSinkDeviceInfoCallback, uCEFJson, uCEFBitmapBitBuffer, + uCEFPrintDialogCallback, uCEFPrintHandler, uCEFPrintJobCallback, LazarusPackageIntf; implementation diff --git a/source/uCEFApplicationCore.pas b/source/uCEFApplicationCore.pas index a37a2d0a..ab6c5649 100644 --- a/source/uCEFApplicationCore.pas +++ b/source/uCEFApplicationCore.pas @@ -172,6 +172,7 @@ type FDevToolsProtocolLogFile : ustring; FDeviceScaleFactor : single; FForcedDeviceScaleFactor : single; + FDisableZygote : boolean; FPluginPolicy : TCefPluginPolicySwitch; FDefaultEncoding : ustring; @@ -197,6 +198,7 @@ type FMustCreateBrowserProcessHandler : boolean; FMustCreateRenderProcessHandler : boolean; FMustCreateLoadHandler : boolean; + FMustCreatePrintHandler : boolean; // ICefBrowserProcessHandler FOnGetCookieableSchemes : TOnGetCookieableSchemesEvent; @@ -229,6 +231,14 @@ type FOnLoadEnd : TOnRenderLoadEnd; FOnLoadError : TOnRenderLoadError; + // ICefPrintHandler + FOnPrintStart : TOnPrintStartEvent; + FOnPrintSettings : TOnPrintSettingsEvent; + FOnPrintDialog : TOnPrintDialogEvent; + FOnPrintJob : TOnPrintJobEvent; + FOnPrintReset : TOnPrintResetEvent; + FOnGetPDFPaperSize : TOnGetPDFPaperSizeEvent; + procedure SetCache(const aValue : ustring); procedure SetRootCache(const aValue : ustring); procedure SetUserDataPath(const aValue : ustring); @@ -246,6 +256,7 @@ type function GetMustCreateBrowserProcessHandler : boolean; virtual; function GetMustCreateRenderProcessHandler : boolean; virtual; function GetMustCreateLoadHandler : boolean; virtual; + function GetMustCreatePrintHandler : boolean; virtual; function GetGlobalContextInitialized : boolean; function GetChildProcessesCount : integer; function GetUsedMemory : uint64; @@ -345,9 +356,9 @@ type procedure QuitMessageLoop; procedure UpdateDeviceScaleFactor; virtual; - // Internal procedures. Only TInternalApp, TCefCustomBrowserProcessHandler, - // ICefResourceBundleHandler, ICefRenderProcessHandler, ICefRegisterCDMCallback - // and ICefLoadHandler should use them. + // Internal procedures. Only ICefApp, ICefBrowserProcessHandler, + // ICefResourceBundleHandler, ICefRenderProcessHandler, ICefRegisterCDMCallback, + // ICefLoadHandler and ICefPrintHandler should use them. procedure Internal_OnBeforeCommandLineProcessing(const processType: ustring; const commandLine: ICefCommandLine); procedure Internal_OnRegisterCustomSchemes(const registrar: TCefSchemeRegistrarRef); procedure Internal_OnContextInitialized; @@ -371,6 +382,12 @@ type procedure Internal_OnLoadError(const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure Internal_GetCookieableSchemes(var schemes: TStringList; var include_defaults : boolean); procedure Internal_GetDefaultClient(var aClient : ICefClient); + procedure Internal_OnPrintStart(const browser: ICefBrowser); + procedure Internal_OnPrintSettings(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean); + procedure Internal_OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult : boolean); + procedure Internal_OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult : boolean); + procedure Internal_OnPrintReset(const browser: ICefBrowser); + procedure Internal_OnGetPDFPaperSize(deviceUnitsPerInch: Integer; var aResult : TCefSize); // Properties used to populate TCefSettings (cef_settings_t) property NoSandbox : Boolean read FNoSandbox write FNoSandbox; @@ -454,6 +471,7 @@ type property DisableNewBrowserInfoTimeout : boolean read FDisableNewBrowserInfoTimeout write FDisableNewBrowserInfoTimeout; // --disable-new-browser-info-timeout property DevToolsProtocolLogFile : ustring read FDevToolsProtocolLogFile write FDevToolsProtocolLogFile; // --devtools-protocol-log-file property ForcedDeviceScaleFactor : single read FForcedDeviceScaleFactor write FForcedDeviceScaleFactor; // --device-scale-factor + property DisableZygote : boolean read FDisableZygote write FDisableZygote; // --no-zygote // Properties used during the CEF initialization property WindowsSandboxInfo : Pointer read FWindowsSandboxInfo write FWindowsSandboxInfo; @@ -487,6 +505,7 @@ type property MustCreateBrowserProcessHandler : boolean read GetMustCreateBrowserProcessHandler write FMustCreateBrowserProcessHandler; property MustCreateRenderProcessHandler : boolean read GetMustCreateRenderProcessHandler write FMustCreateRenderProcessHandler; property MustCreateLoadHandler : boolean read GetMustCreateLoadHandler write FMustCreateLoadHandler; + property MustCreatePrintHandler : boolean read GetMustCreatePrintHandler write FMustCreatePrintHandler; property OsmodalLoop : boolean write SetOsmodalLoop; property Status : TCefAplicationStatus read FStatus; property MissingLibFiles : string read FMissingLibFiles; @@ -535,6 +554,16 @@ type property OnLoadStart : TOnRenderLoadStart read FOnLoadStart write FOnLoadStart; property OnLoadEnd : TOnRenderLoadEnd read FOnLoadEnd write FOnLoadEnd; property OnLoadError : TOnRenderLoadError read FOnLoadError write FOnLoadError; + + // ICefPrintHandler + {$IFDEF LINUX} + property OnPrintStart : TOnPrintStartEvent read FOnPrintStart write FOnPrintStart; + property OnPrintSettings : TOnPrintSettingsEvent read FOnPrintSettings write FOnPrintSettings; + property OnPrintDialog : TOnPrintDialogEvent read FOnPrintDialog write FOnPrintDialog; + property OnPrintJob : TOnPrintJobEvent read FOnPrintJob write FOnPrintJob; + property OnPrintReset : TOnPrintResetEvent read FOnPrintReset write FOnPrintReset; + property OnGetPDFPaperSize : TOnGetPDFPaperSizeEvent read FOnGetPDFPaperSize write FOnGetPDFPaperSize; + {$ENDIF} end; TCEFDirectoryDeleterThread = class(TThread) @@ -697,6 +726,7 @@ begin FDisableNewBrowserInfoTimeout := False; FDevToolsProtocolLogFile := ''; FForcedDeviceScaleFactor := 0; + FDisableZygote := False; FDisableJavascriptCloseWindows := False; FDisableJavascriptAccessClipboard := False; @@ -719,6 +749,7 @@ begin FMustCreateBrowserProcessHandler := True; FMustCreateRenderProcessHandler := False; FMustCreateLoadHandler := False; + FMustCreatePrintHandler := False; // ICefBrowserProcessHandler FOnGetCookieableSchemes := nil; @@ -751,6 +782,14 @@ begin FOnLoadEnd := nil; FOnLoadError := nil; + // ICefPrintHandler + FOnPrintStart := nil; + FOnPrintSettings := nil; + FOnPrintDialog := nil; + FOnPrintJob := nil; + FOnPrintReset := nil; + FOnGetPDFPaperSize := nil; + UpdateDeviceScaleFactor; FillChar(FAppSettings, SizeOf(TCefSettings), 0); @@ -1699,6 +1738,42 @@ begin FOnGetDefaultClient(aClient); end; +procedure TCefApplicationCore.Internal_OnPrintStart(const browser: ICefBrowser); +begin + if assigned(FOnPrintStart) then + FOnPrintStart(browser); +end; + +procedure TCefApplicationCore.Internal_OnPrintSettings(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean); +begin + if assigned(FOnPrintSettings) then + FOnPrintSettings(browser, settings, getDefaults); +end; + +procedure TCefApplicationCore.Internal_OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult : boolean); +begin + if assigned(FOnPrintDialog) then + FOnPrintDialog(browser, hasSelection, callback, aResult); +end; + +procedure TCefApplicationCore.Internal_OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult : boolean); +begin + if assigned(FOnPrintJob) then + FOnPrintJob(browser, documentName, PDFFilePath, callback, aResult); +end; + +procedure TCefApplicationCore.Internal_OnPrintReset(const browser: ICefBrowser); +begin + if assigned(FOnPrintReset) then + FOnPrintReset(browser); +end; + +procedure TCefApplicationCore.Internal_OnGetPDFPaperSize(deviceUnitsPerInch: Integer; var aResult : TCefSize); +begin + if assigned(FOnGetPDFPaperSize) then + FOnGetPDFPaperSize(deviceUnitsPerInch, aResult); +end; + procedure TCefApplicationCore.AppendSwitch(var aKeys, aValues : TStringList; const aNewKey, aNewValue : ustring); var TempKey : ustring; @@ -1940,6 +2015,9 @@ begin ReplaceSwitch(aKeys, aValues, '--force-device-scale-factor', FloatToStr(FForcedDeviceScaleFactor, TempFormatSettings)); end; + if FDisableZygote then + ReplaceSwitch(aKeys, aValues, '--no-zygote'); + // The list of features you can enable is here : // https://chromium.googlesource.com/chromium/src/+/master/chrome/common/chrome_features.cc if (length(FEnableFeatures) > 0) then @@ -2050,6 +2128,7 @@ function TCefApplicationCore.GetMustCreateBrowserProcessHandler : boolean; begin Result := ((FSingleProcess or (FProcessType = ptBrowser)) and (FMustCreateBrowserProcessHandler or + MustCreatePrintHandler or assigned(FOnGetCookieableSchemes) or assigned(FOnContextInitialized) or assigned(FOnBeforeChildProcessLaunch) or @@ -2082,6 +2161,22 @@ begin assigned(FOnLoadError))); end; +function TCefApplicationCore.GetMustCreatePrintHandler : boolean; +begin + {$IFDEF LINUX} + Result := ((FSingleProcess or (FProcessType = ptBrowser)) and + (FMustCreatePrintHandler or + assigned(FOnPrintStart) or + assigned(FOnPrintSettings) or + assigned(FOnPrintDialog) or + assigned(FOnPrintJob) or + assigned(FOnPrintReset) or + assigned(FOnGetPDFPaperSize))); + {$ELSE} + Result := False; + {$ENDIF} +end; + function TCefApplicationCore.GetGlobalContextInitialized : boolean; begin Result := FGlobalContextInitialized or not(MustCreateBrowserProcessHandler); diff --git a/source/uCEFBrowserProcessHandler.pas b/source/uCEFBrowserProcessHandler.pas index 02679c43..8b8eaf1f 100644 --- a/source/uCEFBrowserProcessHandler.pas +++ b/source/uCEFBrowserProcessHandler.pas @@ -74,11 +74,13 @@ type TCefCustomBrowserProcessHandler = class(TCefBrowserProcessHandlerOwn) protected - FCefApp : TCefApplicationCore; + FCefApp : TCefApplicationCore; + FPrintHandler : ICefPrintHandler; procedure GetCookieableSchemes(var schemes: TStringList; var include_defaults : boolean); override; procedure OnContextInitialized; override; procedure OnBeforeChildProcessLaunch(const commandLine: ICefCommandLine); override; + procedure GetPrintHandler(var aHandler : ICefPrintHandler); override; procedure OnScheduleMessagePumpWork(const delayMs: Int64); override; procedure GetDefaultClient(var aClient : ICefClient); override; @@ -97,7 +99,8 @@ uses {$ELSE} SysUtils, {$ENDIF} - uCEFMiscFunctions, uCEFLibFunctions, uCEFCommandLine, uCEFListValue, uCEFConstants, uCEFStringList; + uCEFMiscFunctions, uCEFLibFunctions, uCEFCommandLine, uCEFListValue, uCEFConstants, uCEFStringList, + uCEFPrintHandler; procedure cef_browser_process_handler_get_cookieable_schemes(self : PCefBrowserProcessHandler; schemes : TCefStringList; @@ -228,7 +231,7 @@ end; procedure TCefBrowserProcessHandlerOwn.GetPrintHandler(var aHandler : ICefPrintHandler); begin - aHandler := nil; // only linux + aHandler := nil; end; procedure TCefBrowserProcessHandlerOwn.GetDefaultClient(var aClient : ICefClient); @@ -245,6 +248,11 @@ begin inherited Create; FCefApp := aCefApp; + + if (FCefApp <> nil) and FCefApp.MustCreatePrintHandler then + FPrintHandler := TCustomPrintHandler.Create(FCefApp) + else + FPrintHandler := nil; end; destructor TCefCustomBrowserProcessHandler.Destroy; @@ -256,7 +264,11 @@ end; procedure TCefCustomBrowserProcessHandler.RemoveReferences; begin - FCefApp := nil; + if (FPrintHandler <> nil) then + FPrintHandler.RemoveReferences; + + FCefApp := nil; + FPrintHandler := nil; end; procedure TCefCustomBrowserProcessHandler.GetCookieableSchemes(var schemes : TStringList; @@ -289,6 +301,14 @@ begin if CustomExceptionHandler('TCefCustomBrowserProcessHandler.OnBeforeChildProcessLaunch', e) then raise; end; end; + +procedure TCefCustomBrowserProcessHandler.GetPrintHandler(var aHandler : ICefPrintHandler); +begin + if (FPrintHandler <> nil) then + aHandler := FPrintHandler + else + inherited GetPrintHandler(aHandler); +end; procedure TCefCustomBrowserProcessHandler.OnScheduleMessagePumpWork(const delayMs: Int64); begin diff --git a/source/uCEFInterfaces.pas b/source/uCEFInterfaces.pas index c6fb48ec..fe47868e 100644 --- a/source/uCEFInterfaces.pas +++ b/source/uCEFInterfaces.pas @@ -154,6 +154,7 @@ type ICefAudioHandler = interface; ICefDevToolsMessageObserver = interface; ICefValue = interface; + ICefPrintSettings = interface; TCefv8ValueArray = array of ICefv8Value; TCefX509CertificateArray = array of ICefX509Certificate; @@ -219,6 +220,12 @@ type TOnRenderLoadEnd = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; TOnRenderLoadError = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; const frame: ICefFrame; errorCode: TCefErrorCode; const errorText, failedUrl: ustring) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; TOnRenderLoadingStateChange = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnPrintStartEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnPrintSettingsEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnPrintDialogEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult : boolean) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnPrintJobEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult : boolean) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnPrintResetEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser: ICefBrowser) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; + TOnGetPDFPaperSizeEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(deviceUnitsPerInch: Integer; var aResult : TCefSize) {$IFNDEF DELPHI12_UP}{$IFNDEF FPC}of object{$ENDIF}{$ENDIF}; // ******************************************* // **** Callback procedures and functions **** @@ -2322,10 +2329,12 @@ type ['{2831D5C9-6E2B-4A30-A65A-0F4435371EFC}'] procedure OnPrintStart(const browser: ICefBrowser); procedure OnPrintSettings(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean); - function OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback): boolean; - function OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback): boolean; + procedure OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult: boolean); + procedure OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult: boolean); procedure OnPrintReset(const browser: ICefBrowser); - function GetPDFPaperSize(deviceUnitsPerInch: Integer): TCefSize; + procedure GetPDFPaperSize(deviceUnitsPerInch: integer; var aResult: TCefSize); + + procedure RemoveReferences; // custom procedure to clear all references end; // TCefNavigationEntry diff --git a/source/uCEFPrintDialogCallback.pas b/source/uCEFPrintDialogCallback.pas new file mode 100644 index 00000000..55873378 --- /dev/null +++ b/source/uCEFPrintDialogCallback.pas @@ -0,0 +1,87 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2021 Salvador Diaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +unit uCEFPrintDialogCallback; + +{$IFDEF FPC} + {$MODE OBJFPC}{$H+} +{$ENDIF} + +{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF} +{$MINENUMSIZE 4} + +{$I cef.inc} + +interface + +uses + uCEFBaseRefCounted, uCEFInterfaces, uCEFTypes; + +type + TCefPrintDialogCallbackRef = class(TCefBaseRefCountedRef, ICefPrintDialogCallback) + protected + procedure cont(const settings: ICefPrintSettings); + procedure cancel; + + public + class function UnWrap(data: Pointer): ICefPrintDialogCallback; + end; + +implementation + +uses + uCEFMiscFunctions, uCEFLibFunctions; + +procedure TCefPrintDialogCallbackRef.cancel; +begin + PCefPrintDialogCallback(FData)^.cancel(PCefPrintDialogCallback(FData)); +end; + +procedure TCefPrintDialogCallbackRef.cont(const settings: ICefPrintSettings); +begin + PCefPrintDialogCallback(FData)^.cont(PCefPrintDialogCallback(FData), CefGetData(settings)); +end; + +class function TCefPrintDialogCallbackRef.UnWrap(data: Pointer): ICefPrintDialogCallback; +begin + if (data <> nil) then + Result := Create(data) as ICefPrintDialogCallback + else + Result := nil; +end; + +end. diff --git a/source/uCEFPrintHandler.pas b/source/uCEFPrintHandler.pas new file mode 100644 index 00000000..b0ca71b1 --- /dev/null +++ b/source/uCEFPrintHandler.pas @@ -0,0 +1,319 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2021 Salvador Diaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +unit uCEFPrintHandler; + +{$IFDEF FPC} + {$MODE OBJFPC}{$H+} +{$ENDIF} + +{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF} +{$MINENUMSIZE 4} + +{$I cef.inc} + +interface + +uses + uCEFBaseRefCounted, uCEFInterfaces, uCEFTypes, uCEFApplicationCore; + +type + TCefPrintHandlerOwn = class(TCefBaseRefCountedOwn, ICefPrintHandler) + protected + procedure OnPrintStart(const browser: ICefBrowser); virtual; abstract; + procedure OnPrintSettings(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean); virtual; abstract; + procedure OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult: boolean); virtual; + procedure OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult: boolean); virtual; + procedure OnPrintReset(const browser: ICefBrowser); virtual; abstract; + procedure GetPDFPaperSize(deviceUnitsPerInch: Integer; var aResult: TCefSize); virtual; + + procedure RemoveReferences; virtual; abstract; + + public + constructor Create; virtual; + end; + + TCustomPrintHandler = class(TCefPrintHandlerOwn) + protected + FCefApp : TCefApplicationCore; + + procedure OnPrintStart(const browser: ICefBrowser); override; + procedure OnPrintSettings(const browser: ICefBrowser; const settings: ICefPrintSettings; getDefaults: boolean); override; + procedure OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult: boolean); override; + procedure OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult: boolean); override; + procedure OnPrintReset(const browser: ICefBrowser); override; + procedure GetPDFPaperSize(deviceUnitsPerInch: Integer; var aResult: TCefSize); override; + + procedure RemoveReferences; override; + + public + constructor Create(const aCefApp : TCefApplicationCore); reintroduce; virtual; + destructor Destroy; override; + end; + +implementation + +uses + {$IFDEF DELPHI16_UP} + System.SysUtils, + {$ELSE} + SysUtils, + {$ENDIF} + uCEFMiscFunctions, uCEFLibFunctions, uCEFBrowser, uCEFPrintSettings, + uCEFPrintDialogCallback, uCEFPrintJobCallback; + + +// TCefPrintHandlerOwn + +procedure cef_print_handler_on_print_start(self: PCefPrintHandler; browser: PCefBrowser); stdcall; +var + TempObject : TObject; +begin + TempObject := CefGetObject(self); + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).OnPrintStart(TCefBrowserRef.UnWrap(browser)); +end; + +procedure cef_print_handler_on_print_settings(self : PCefPrintHandler; + browser : PCefBrowser; + settings : PCefPrintSettings; + get_defaults : Integer); stdcall; +var + TempObject : TObject; +begin + TempObject := CefGetObject(self); + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).OnPrintSettings(TCefBrowserRef.UnWrap(browser), + TCefPrintSettingsRef.UnWrap(settings), + get_defaults <> 0); +end; + +function cef_print_handler_on_print_dialog(self : PCefPrintHandler; + browser : PCefBrowser; + has_selection : Integer; + callback : PCefPrintDialogCallback): Integer; stdcall; +var + TempObject : TObject; + TempResult : boolean; +begin + TempResult := False; + TempObject := CefGetObject(self); + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).OnPrintDialog(TCefBrowserRef.UnWrap(browser), + has_selection <> 0, + TCefPrintDialogCallbackRef.UnWrap(callback), + TempResult); + + Result := ord(TempResult); +end; + +function cef_print_handler_on_print_job( self : PCefPrintHandler; + browser : PCefBrowser; + const document_name : PCefString; + const pdf_file_path : PCefString; + callback : PCefPrintJobCallback): Integer; stdcall; +var + TempObject : TObject; + TempResult : boolean; +begin + TempResult := False; + TempObject := CefGetObject(self); + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).OnPrintJob(TCefBrowserRef.UnWrap(browser), + CefString(document_name), + CefString(pdf_file_path), + TCefPrintJobCallbackRef.UnWrap(callback), + TempResult); + + Result := ord(TempResult); +end; + +procedure cef_print_handler_on_print_reset(self : PCefPrintHandler; + browser : PCefBrowser); stdcall; +var + TempObject : TObject; +begin + TempObject := CefGetObject(self); + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).OnPrintReset(TCefBrowserRef.UnWrap(browser)); +end; + +function cef_print_handler_get_pdf_paper_size(self : PCefPrintHandler; + device_units_per_inch : Integer): TCefSize; stdcall; +var + TempObject : TObject; + TempSize : TCefSize; +begin + TempObject := CefGetObject(self); + TempSize.Width := 0; + TempSize.Height := 0; + + if (TempObject <> nil) and (TempObject is TCefPrintHandlerOwn) then + TCefPrintHandlerOwn(TempObject).GetPDFPaperSize(device_units_per_inch, TempSize); + + Result := TempSize; +end; + +constructor TCefPrintHandlerOwn.Create; +begin + inherited CreateData(SizeOf(TCefPrintHandler)); + + with PCefPrintHandler(FData)^ do + begin + on_print_start := {$IFDEF FPC}@{$ENDIF}cef_print_handler_on_print_start; + on_print_settings := {$IFDEF FPC}@{$ENDIF}cef_print_handler_on_print_settings; + on_print_dialog := {$IFDEF FPC}@{$ENDIF}cef_print_handler_on_print_dialog; + on_print_job := {$IFDEF FPC}@{$ENDIF}cef_print_handler_on_print_job; + on_print_reset := {$IFDEF FPC}@{$ENDIF}cef_print_handler_on_print_reset; + get_pdf_paper_size := {$IFDEF FPC}@{$ENDIF}cef_print_handler_get_pdf_paper_size; + end; +end; + +procedure TCefPrintHandlerOwn.OnPrintDialog(const browser: ICefBrowser; hasSelection: boolean; const callback: ICefPrintDialogCallback; var aResult: boolean); +begin + aResult := False; +end; + +procedure TCefPrintHandlerOwn.OnPrintJob(const browser: ICefBrowser; const documentName, PDFFilePath: ustring; const callback: ICefPrintJobCallback; var aResult: boolean); +begin + aResult := False; +end; + +procedure TCefPrintHandlerOwn.GetPDFPaperSize(deviceUnitsPerInch: Integer; var aResult: TCefSize); +begin + aResult.Width := 0; + aResult.Height := 0; +end; + + +// TCustomPrintHandler + +constructor TCustomPrintHandler.Create(const aCefApp : TCefApplicationCore); +begin + inherited Create; + + FCefApp := aCefApp; +end; + +destructor TCustomPrintHandler.Destroy; +begin + RemoveReferences; + + inherited Destroy; +end; + +procedure TCustomPrintHandler.RemoveReferences; +begin + FCefApp := nil; +end; + +procedure TCustomPrintHandler.OnPrintStart(const browser : ICefBrowser); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnPrintStart(browser); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.OnPrintStart', e) then raise; + end; +end; + +procedure TCustomPrintHandler.OnPrintSettings(const browser : ICefBrowser; + const settings : ICefPrintSettings; + getDefaults : boolean); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnPrintSettings(browser, settings, getDefaults); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.OnPrintSettings', e) then raise; + end; +end; + +procedure TCustomPrintHandler.OnPrintDialog(const browser : ICefBrowser; + hasSelection : boolean; + const callback : ICefPrintDialogCallback; + var aResult : boolean); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnPrintDialog(browser, hasSelection, callback, aResult); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.OnPrintDialog', e) then raise; + end; +end; + +procedure TCustomPrintHandler.OnPrintJob(const browser : ICefBrowser; + const documentName : ustring; + const PDFFilePath : ustring; + const callback : ICefPrintJobCallback; + var aResult : boolean); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnPrintJob(browser, documentName, PDFFilePath, callback, aResult); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.OnPrintJob', e) then raise; + end; +end; + +procedure TCustomPrintHandler.OnPrintReset(const browser : ICefBrowser); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnPrintReset(browser); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.OnPrintReset', e) then raise; + end; +end; + +procedure TCustomPrintHandler.GetPDFPaperSize( deviceUnitsPerInch : Integer; + var aResult : TCefSize); +begin + try + if (FCefApp <> nil) then FCefApp.Internal_OnGetPDFPaperSize(deviceUnitsPerInch, aResult); + except + on e : exception do + if CustomExceptionHandler('TCustomPrintHandler.GetPDFPaperSize', e) then raise; + end; +end; + +end. diff --git a/source/uCEFPrintJobCallback.pas b/source/uCEFPrintJobCallback.pas new file mode 100644 index 00000000..1dec190f --- /dev/null +++ b/source/uCEFPrintJobCallback.pas @@ -0,0 +1,81 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2021 Salvador Diaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +unit uCEFPrintJobCallback; + +{$IFDEF FPC} + {$MODE OBJFPC}{$H+} +{$ENDIF} + +{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF} +{$MINENUMSIZE 4} + +{$I cef.inc} + +interface + +uses + uCEFBaseRefCounted, uCEFInterfaces, uCEFTypes; + +type + TCefPrintJobCallbackRef = class(TCefBaseRefCountedRef, ICefPrintJobCallback) + protected + procedure cont; + + public + class function UnWrap(data: Pointer): ICefPrintJobCallback; + end; + +implementation + +uses + uCEFMiscFunctions, uCEFLibFunctions; + +procedure TCefPrintJobCallbackRef.cont; +begin + PCefPrintJobCallback(FData)^.cont(PCefPrintJobCallback(FData)); +end; + +class function TCefPrintJobCallbackRef.UnWrap(data: Pointer): ICefPrintJobCallback; +begin + if (data <> nil) then + Result := Create(data) as ICefPrintJobCallback + else + Result := nil; +end; + +end. diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json index 1dc7c41b..83438384 100644 --- a/update_CEF4Delphi.json +++ b/update_CEF4Delphi.json @@ -2,7 +2,7 @@ "UpdateLazPackages" : [ { "ForceNotify" : true, - "InternalVersion" : 217, + "InternalVersion" : 218, "Name" : "cef4delphi_lazarus.lpk", "Version" : "87.1.12.0" }