2020-12-13 18:36:10 +01:00
|
|
|
|
// ************************************************************************
|
|
|
|
|
// ***************************** 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
|
|
|
|
|
//
|
2022-01-01 10:41:21 +01:00
|
|
|
|
// Copyright <20> 2022 Salvador Diaz Fau. All rights reserved.
|
2020-12-13 18:36:10 +01:00
|
|
|
|
//
|
|
|
|
|
// ************************************************************************
|
|
|
|
|
// ************ 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 <hgourvest@gmail.com>
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*)
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
unit uCEFBrowserThread;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
|
|
|
|
{$MODE Delphi}
|
|
|
|
|
|
|
|
|
|
{$I cef.inc}
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
{$IFDEF DELPHI16_UP}
|
|
|
|
|
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, System.SyncObjs, System.Math,
|
|
|
|
|
{$ELSE}
|
|
|
|
|
Windows, Messages, SysUtils, Classes, Graphics, SyncObjs, Math,
|
|
|
|
|
{$ENDIF}
|
|
|
|
|
uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFChromiumCore, uCEFMiscFunctions;
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TCEFBrowserThread = class(TThread)
|
|
|
|
|
protected
|
|
|
|
|
FBrowser : TChromium;
|
2020-12-20 12:28:56 +01:00
|
|
|
|
FPanel : TBufferPanel;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
FPanelSize : TSize;
|
|
|
|
|
FScreenScale : single;
|
|
|
|
|
FPopUpBitmap : TBitmap;
|
|
|
|
|
FPopUpRect : TRect;
|
|
|
|
|
FResizeCS : TCriticalSection;
|
|
|
|
|
FBrowserInfoCS : TCriticalSection;
|
|
|
|
|
FShowPopUp : boolean;
|
|
|
|
|
FClosing : boolean;
|
|
|
|
|
FResizing : boolean;
|
|
|
|
|
FPendingResize : boolean;
|
|
|
|
|
FInitialized : boolean;
|
|
|
|
|
FDefaultURL : ustring;
|
|
|
|
|
FSnapshot : TBitmap;
|
|
|
|
|
FDelayMs : integer;
|
|
|
|
|
FOnSnapshotAvailable : TNotifyEvent;
|
|
|
|
|
FOnError : TNotifyEvent;
|
|
|
|
|
FErrorCode : integer;
|
|
|
|
|
FErrorText : ustring;
|
|
|
|
|
FFailedUrl : ustring;
|
|
|
|
|
FPendingUrl : ustring;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FSyncEvents : boolean;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
|
|
|
|
function GetErrorCode : integer;
|
|
|
|
|
function GetErrorText : ustring;
|
|
|
|
|
function GetFailedUrl : ustring;
|
|
|
|
|
function GetInitialized : boolean;
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
procedure SetErrorText(const aValue : ustring);
|
|
|
|
|
|
2020-12-13 18:36:10 +01:00
|
|
|
|
procedure Panel_OnResize(Sender: TObject);
|
|
|
|
|
|
|
|
|
|
procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
|
|
|
|
|
procedure Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
|
|
|
|
|
procedure Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
|
|
|
|
|
procedure Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
|
|
|
|
|
procedure Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean);
|
|
|
|
|
procedure Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
|
|
|
|
|
procedure Browser_OnPopupSize(Sender: TObject; const browser: ICefBrowser; const rect: PCefRect);
|
|
|
|
|
procedure Browser_OnBeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; 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 Browser_OnBeforeClose(Sender: TObject; const browser: ICefBrowser);
|
|
|
|
|
procedure Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
|
|
|
|
|
procedure Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean);
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
procedure DoOnError;
|
|
|
|
|
procedure DoOnSnapshotAvailable;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
procedure Resize;
|
|
|
|
|
function CreateBrowser : boolean;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
function TakeSnapshot : boolean;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
procedure CloseBrowser;
|
|
|
|
|
procedure InitError;
|
|
|
|
|
procedure WebpagePostProcessing;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
procedure WebpageError;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
procedure LoadPendingURL;
|
|
|
|
|
procedure Execute; override;
|
|
|
|
|
|
|
|
|
|
public
|
|
|
|
|
constructor Create(const aDefaultURL : ustring; aWidth, aHeight : integer; aDelayMs : integer = 500; const aScreenScale : single = 1);
|
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
procedure AfterConstruction; override;
|
|
|
|
|
function TerminateBrowserThread : boolean;
|
|
|
|
|
function CopySnapshot(var aSnapshot : TBitmap) : boolean;
|
|
|
|
|
function SaveSnapshotToFile(const aPath : ustring) : boolean;
|
|
|
|
|
procedure LoadUrl(const aURL : ustring);
|
|
|
|
|
|
|
|
|
|
property ErrorCode : integer read GetErrorCode;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
property ErrorText : ustring read GetErrorText write SetErrorText;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
property FailedUrl : ustring read GetFailedUrl;
|
|
|
|
|
property Initialized : boolean read GetInitialized;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
property Closing : boolean read FClosing;
|
|
|
|
|
property SyncEvents : boolean read FSyncEvents write FSyncEvents;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
|
|
|
|
property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable;
|
|
|
|
|
property OnError : TNotifyEvent read FOnError write FOnError;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
const
|
|
|
|
|
CEF_WEBPAGE_LOADED_MSG = WM_APP + 1;
|
|
|
|
|
CEF_WEBPAGE_ERROR_MSG = WM_APP + 2;
|
|
|
|
|
CEF_CLOSE_BROWSER_MSG = WM_APP + 3;
|
|
|
|
|
CEF_LOAD_PENDING_URL_MSG = WM_APP + 4;
|
|
|
|
|
|
|
|
|
|
constructor TCEFBrowserThread.Create(const aDefaultURL : ustring; aWidth, aHeight, aDelayMs : integer; const aScreenScale : single);
|
|
|
|
|
begin
|
|
|
|
|
inherited Create(True);
|
|
|
|
|
|
|
|
|
|
FreeOnTerminate := False;
|
|
|
|
|
FInitialized := False;
|
|
|
|
|
FBrowser := nil;
|
|
|
|
|
FPanel := nil;
|
|
|
|
|
FPanelSize.cx := aWidth;
|
|
|
|
|
FPanelSize.cy := aHeight;
|
|
|
|
|
FScreenScale := aScreenScale;
|
|
|
|
|
FDefaultURL := aDefaultURL;
|
|
|
|
|
FPopUpBitmap := nil;
|
|
|
|
|
FPopUpRect := rect(0, 0, 0, 0);
|
|
|
|
|
FShowPopUp := False;
|
|
|
|
|
FResizing := False;
|
|
|
|
|
FPendingResize := False;
|
|
|
|
|
FResizeCS := nil;
|
|
|
|
|
FBrowserInfoCS := nil;
|
|
|
|
|
FSnapshot := nil;
|
|
|
|
|
FDelayMs := aDelayMs;
|
|
|
|
|
FOnSnapshotAvailable := nil;
|
|
|
|
|
FOnError := nil;
|
|
|
|
|
FClosing := False;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FSyncEvents := False;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor TCEFBrowserThread.Destroy;
|
|
|
|
|
begin
|
|
|
|
|
if (FBrowser <> nil) then
|
|
|
|
|
FreeAndNil(FBrowser);
|
|
|
|
|
|
|
|
|
|
if (FPanel <> nil) then
|
|
|
|
|
FreeAndNil(FPanel);
|
|
|
|
|
|
|
|
|
|
if (FPopUpBitmap <> nil) then
|
|
|
|
|
FreeAndNil(FPopUpBitmap);
|
|
|
|
|
|
|
|
|
|
if (FSnapshot <> nil) then
|
|
|
|
|
FreeAndNil(FSnapshot);
|
|
|
|
|
|
|
|
|
|
if (FResizeCS <> nil) then
|
|
|
|
|
FreeAndNil(FResizeCS);
|
|
|
|
|
|
|
|
|
|
if (FBrowserInfoCS <> nil) then
|
|
|
|
|
FreeAndNil(FBrowserInfoCS);
|
|
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.AfterConstruction;
|
|
|
|
|
begin
|
|
|
|
|
inherited AfterConstruction;
|
|
|
|
|
|
2020-12-20 12:28:56 +01:00
|
|
|
|
FResizeCS := TCriticalSection.Create;
|
|
|
|
|
FBrowserInfoCS := TCriticalSection.Create;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-20 12:28:56 +01:00
|
|
|
|
FPanel := TBufferPanel.Create(nil);
|
|
|
|
|
FPanel.ForcedDeviceScaleFactor := FScreenScale;
|
|
|
|
|
FPanel.Width := FPanelSize.cx;
|
|
|
|
|
FPanel.Height := FPanelSize.cy;
|
|
|
|
|
FPanel.OnResize := Panel_OnResize;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
|
|
|
|
FBrowser := TChromium.Create(nil);
|
|
|
|
|
FBrowser.DefaultURL := FDefaultURL;
|
|
|
|
|
FBrowser.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF);
|
|
|
|
|
FBrowser.OnAfterCreated := Browser_OnAfterCreated;
|
|
|
|
|
FBrowser.OnPaint := Browser_OnPaint;
|
|
|
|
|
FBrowser.OnGetViewRect := Browser_OnGetViewRect;
|
|
|
|
|
FBrowser.OnGetScreenPoint := Browser_OnGetScreenPoint;
|
|
|
|
|
FBrowser.OnGetScreenInfo := Browser_OnGetScreenInfo;
|
|
|
|
|
FBrowser.OnPopupShow := Browser_OnPopupShow;
|
|
|
|
|
FBrowser.OnPopupSize := Browser_OnPopupSize;
|
|
|
|
|
FBrowser.OnBeforePopup := Browser_OnBeforePopup;
|
|
|
|
|
FBrowser.OnBeforeClose := Browser_OnBeforeClose;
|
|
|
|
|
FBrowser.OnLoadError := Browser_OnLoadError;
|
|
|
|
|
FBrowser.OnLoadingStateChange := Browser_OnLoadingStateChange;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.GetErrorCode : integer;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
Result := FErrorCode;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
Result := 0;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.GetErrorText : ustring;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
Result := FErrorText;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
Result := '';
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.GetFailedUrl : ustring;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
Result := FFailedUrl;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
Result := '';
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.GetInitialized : boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
|
|
if assigned(FBrowserInfoCS) and assigned(FBrowser) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
Result := FInitialized and FBrowser.Initialized;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
procedure TCEFBrowserThread.SetErrorText(const aValue : ustring);
|
|
|
|
|
begin
|
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
FErrorText := aValue;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-12-13 18:36:10 +01:00
|
|
|
|
function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := False;
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
2020-12-13 18:36:10 +01:00
|
|
|
|
try
|
2020-12-14 13:27:19 +01:00
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FSnapshot) and not(FSnapshot.Empty) then
|
|
|
|
|
begin
|
|
|
|
|
if (aSnapshot = nil) then
|
|
|
|
|
begin
|
|
|
|
|
aSnapshot := TBitmap.Create;
|
|
|
|
|
aSnapshot.PixelFormat := pf32bit;
|
|
|
|
|
aSnapshot.HandleType := bmDIB;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if (aSnapshot.Width <> FSnapshot.Width) then
|
|
|
|
|
aSnapshot.Width := FSnapshot.Width;
|
|
|
|
|
|
|
|
|
|
if (aSnapshot.Height <> FSnapshot.Height) then
|
|
|
|
|
aSnapshot.Height := FSnapshot.Height;
|
|
|
|
|
|
|
|
|
|
aSnapshot.Canvas.Draw(0, 0, FSnapshot);
|
|
|
|
|
Result := True;
|
|
|
|
|
end;
|
|
|
|
|
except
|
|
|
|
|
on e : exception do
|
|
|
|
|
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := False;
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) and (length(aPath) > 0) then
|
2020-12-13 18:36:10 +01:00
|
|
|
|
try
|
2020-12-14 13:27:19 +01:00
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FSnapshot) and not(FSnapshot.Empty) then
|
|
|
|
|
begin
|
|
|
|
|
FSnapshot.SaveToFile(aPath);
|
|
|
|
|
Result := True;
|
|
|
|
|
end;
|
|
|
|
|
except
|
|
|
|
|
on e : exception do
|
|
|
|
|
if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.LoadUrl(const aURL : ustring);
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
2020-12-13 18:36:10 +01:00
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
FPendingUrl := aURL;
|
|
|
|
|
PostThreadMessage(ThreadID, CEF_LOAD_PENDING_URL_MSG, 0, 0);
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.TerminateBrowserThread : boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := Initialized and
|
|
|
|
|
PostThreadMessage(ThreadID, CEF_CLOSE_BROWSER_MSG, 0, 0);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Panel_OnResize(Sender: TObject);
|
|
|
|
|
begin
|
|
|
|
|
Resize;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
FInitialized := True;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
|
|
|
|
|
var
|
|
|
|
|
src, dst: PByte;
|
|
|
|
|
i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride : Integer;
|
|
|
|
|
n : NativeUInt;
|
|
|
|
|
TempWidth, TempHeight : integer;
|
|
|
|
|
TempBufferBits : Pointer;
|
|
|
|
|
TempForcedResize : boolean;
|
|
|
|
|
TempBitmap : TBitmap;
|
|
|
|
|
TempSrcRect : TRect;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FResizeCS) and assigned(FPanel) then
|
|
|
|
|
try
|
|
|
|
|
FResizeCS.Acquire;
|
|
|
|
|
TempForcedResize := False;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FPanel.BeginBufferDraw then
|
|
|
|
|
begin
|
|
|
|
|
if (kind = PET_POPUP) then
|
|
|
|
|
begin
|
|
|
|
|
if (FPopUpBitmap = nil) or
|
|
|
|
|
(aWidth <> FPopUpBitmap.Width) or
|
|
|
|
|
(aHeight <> FPopUpBitmap.Height) then
|
|
|
|
|
begin
|
|
|
|
|
if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
|
|
|
|
|
|
|
|
|
|
FPopUpBitmap := TBitmap.Create;
|
|
|
|
|
FPopUpBitmap.PixelFormat := pf32bit;
|
|
|
|
|
FPopUpBitmap.HandleType := bmDIB;
|
|
|
|
|
FPopUpBitmap.Width := aWidth;
|
|
|
|
|
FPopUpBitmap.Height := aHeight;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TempBitmap := FPopUpBitmap;
|
|
|
|
|
TempBitmap.BeginUpdate;
|
|
|
|
|
|
|
|
|
|
TempWidth := FPopUpBitmap.Width;
|
|
|
|
|
TempHeight := FPopUpBitmap.Height;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False));
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
TempBitmap := FPanel.Buffer;
|
|
|
|
|
TempBitmap.BeginUpdate;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
TempWidth := FPanel.BufferWidth;
|
|
|
|
|
TempHeight := FPanel.BufferHeight;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
SrcStride := aWidth * SizeOf(TRGBQuad);
|
|
|
|
|
n := 0;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
while (n < dirtyRectsCount) do
|
|
|
|
|
begin
|
|
|
|
|
if (dirtyRects^[n].x >= 0) and (dirtyRects^[n].y >= 0) then
|
|
|
|
|
begin
|
|
|
|
|
TempLineSize := min(dirtyRects^[n].width, TempWidth - dirtyRects^[n].x) * SizeOf(TRGBQuad);
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if (TempLineSize > 0) then
|
|
|
|
|
begin
|
|
|
|
|
TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad);
|
|
|
|
|
TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad));
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
src := @PByte(buffer)[TempSrcOffset];
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
i := 0;
|
|
|
|
|
j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y);
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
while (i < j) do
|
|
|
|
|
begin
|
|
|
|
|
TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i];
|
|
|
|
|
dst := @PByte(TempBufferBits)[TempDstOffset];
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
Move(src^, dst^, TempLineSize);
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
Inc(src, SrcStride);
|
|
|
|
|
inc(i);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
inc(n);
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
TempBitmap.EndUpdate;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FShowPopup and (FPopUpBitmap <> nil) then
|
|
|
|
|
begin
|
|
|
|
|
TempSrcRect := Rect(0, 0,
|
|
|
|
|
min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width),
|
|
|
|
|
min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height));
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect);
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FPanel.EndBufferDraw;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if (kind = PET_VIEW) then
|
|
|
|
|
begin
|
|
|
|
|
if TempForcedResize or FPendingResize then
|
|
|
|
|
PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0);
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FResizing := False;
|
|
|
|
|
FPendingResize := False;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FResizeCS.Release;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FPanel) then
|
|
|
|
|
begin
|
|
|
|
|
rect.x := 0;
|
|
|
|
|
rect.y := 0;
|
|
|
|
|
rect.width := DeviceToLogical(FPanel.Width, FScreenScale);
|
|
|
|
|
rect.height := DeviceToLogical(FPanel.Height, FScreenScale);
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
|
|
|
|
|
begin
|
|
|
|
|
screenX := LogicalToDevice(viewX, FScreenScale);
|
|
|
|
|
screenY := LogicalToDevice(viewY, FScreenScale);
|
|
|
|
|
Result := True;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean);
|
|
|
|
|
var
|
|
|
|
|
TempRect : TCEFRect;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FPanel) then
|
|
|
|
|
begin
|
|
|
|
|
TempRect.x := 0;
|
|
|
|
|
TempRect.y := 0;
|
|
|
|
|
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale);
|
|
|
|
|
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale);
|
|
|
|
|
|
|
|
|
|
screenInfo.device_scale_factor := FScreenScale;
|
|
|
|
|
screenInfo.depth := 0;
|
|
|
|
|
screenInfo.depth_per_component := 0;
|
|
|
|
|
screenInfo.is_monochrome := Ord(False);
|
|
|
|
|
screenInfo.rect := TempRect;
|
|
|
|
|
screenInfo.available_rect := TempRect;
|
|
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
|
|
|
|
|
begin
|
|
|
|
|
if show then
|
|
|
|
|
FShowPopUp := True
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
FShowPopUp := False;
|
|
|
|
|
FPopUpRect := rect(0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
if (FBrowser <> nil) then FBrowser.Invalidate(PET_VIEW);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnPopupSize(Sender: TObject; const browser: ICefBrowser; const rect: PCefRect);
|
|
|
|
|
begin
|
|
|
|
|
LogicalToDevice(rect^, FScreenScale);
|
|
|
|
|
|
|
|
|
|
FPopUpRect.Left := rect.x;
|
|
|
|
|
FPopUpRect.Top := rect.y;
|
|
|
|
|
FPopUpRect.Right := rect.x + rect.width - 1;
|
|
|
|
|
FPopUpRect.Bottom := rect.y + rect.height - 1;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnBeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; 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);
|
|
|
|
|
begin
|
|
|
|
|
// For simplicity, this demo blocks all popup windows and new tabs
|
|
|
|
|
Result := (targetDisposition in [WOD_NEW_FOREGROUND_TAB, WOD_NEW_BACKGROUND_TAB, WOD_NEW_POPUP, WOD_NEW_WINDOW]);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnBeforeClose(Sender: TObject; const browser: ICefBrowser);
|
|
|
|
|
begin
|
|
|
|
|
PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain and assigned(FBrowserInfoCS) then
|
2020-12-13 18:36:10 +01:00
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
|
|
|
|
|
|
|
|
|
FErrorCode := errorCode;
|
|
|
|
|
FErrorText := errorText;
|
|
|
|
|
FFailedUrl := failedUrl;
|
|
|
|
|
|
|
|
|
|
PostThreadMessage(ThreadID, CEF_WEBPAGE_ERROR_MSG, 0, 0);
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean);
|
|
|
|
|
begin
|
|
|
|
|
if not(FClosing) and not(Terminated) and not(isLoading) then
|
|
|
|
|
PostThreadMessage(ThreadID, CEF_WEBPAGE_LOADED_MSG, 0, 0);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Resize;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FResizeCS) and assigned(FPanel) then
|
|
|
|
|
try
|
|
|
|
|
FResizeCS.Acquire;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FResizing then
|
|
|
|
|
FPendingResize := True
|
2020-12-13 18:36:10 +01:00
|
|
|
|
else
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FPanel.BufferIsResized then
|
|
|
|
|
FBrowser.Invalidate(PET_VIEW)
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
FResizing := True;
|
|
|
|
|
FBrowser.WasResized;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FResizeCS.Release;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCEFBrowserThread.CreateBrowser : boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := (FBrowser <> nil) and FBrowser.CreateBrowser;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.LoadPendingURL;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if (length(FPendingURL) > 0) then
|
|
|
|
|
begin
|
|
|
|
|
FBrowser.LoadURL(FPendingURL);
|
|
|
|
|
FPendingURL := '';
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.WebpagePostProcessing;
|
|
|
|
|
begin
|
|
|
|
|
if FClosing or Terminated then
|
|
|
|
|
exit;
|
|
|
|
|
|
|
|
|
|
if (FDelayMs > 0) then
|
|
|
|
|
sleep(FDelayMs);
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if TakeSnapshot and assigned(FOnSnapshotAvailable) then
|
|
|
|
|
begin
|
|
|
|
|
if FSyncEvents then
|
|
|
|
|
Synchronize(DoOnSnapshotAvailable)
|
|
|
|
|
else
|
|
|
|
|
DoOnSnapshotAvailable;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
procedure TCEFBrowserThread.WebpageError;
|
|
|
|
|
begin
|
|
|
|
|
if not(FClosing) and not(Terminated) and assigned(FOnError) then
|
|
|
|
|
begin
|
|
|
|
|
if FSyncEvents then
|
|
|
|
|
Synchronize(DoOnError)
|
|
|
|
|
else
|
|
|
|
|
DoOnError;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
function TCEFBrowserThread.TakeSnapshot : boolean;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
Result := False;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if FClosing or Terminated or not(Initialized) then exit;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FBrowserInfoCS) and assigned(FPanel) and FPanel.BeginBufferDraw then
|
|
|
|
|
try
|
|
|
|
|
FBrowserInfoCS.Acquire;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
|
2020-12-14 13:27:19 +01:00
|
|
|
|
if assigned(FPanel.Buffer) and not(FPanel.Buffer.Empty) then
|
|
|
|
|
begin
|
|
|
|
|
if (FSnapshot = nil) then
|
|
|
|
|
begin
|
|
|
|
|
FSnapshot := TBitmap.Create;
|
|
|
|
|
FSnapshot.PixelFormat := pf32bit;
|
|
|
|
|
FSnapshot.HandleType := bmDIB;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
if (FSnapshot.Width <> FPanel.BufferWidth) then
|
|
|
|
|
FSnapshot.Width := FPanel.BufferWidth;
|
|
|
|
|
|
|
|
|
|
if (FSnapshot.Height <> FPanel.BufferHeight) then
|
|
|
|
|
FSnapshot.Height := FPanel.BufferHeight;
|
|
|
|
|
|
|
|
|
|
FSnapshot.Canvas.Draw(0, 0, FPanel.Buffer);
|
|
|
|
|
Result := True;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
FBrowserInfoCS.Release;
|
|
|
|
|
FPanel.EndBufferDraw;
|
|
|
|
|
end;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.CloseBrowser;
|
|
|
|
|
begin
|
|
|
|
|
if not(FClosing) and assigned(FBrowser) then
|
|
|
|
|
begin
|
|
|
|
|
FClosing := True;
|
|
|
|
|
FBrowser.CloseBrowser(True);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.DoOnError;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
FOnError(self);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
|
|
|
|
|
begin
|
|
|
|
|
FOnSnapshotAvailable(self);
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.InitError;
|
|
|
|
|
begin
|
2020-12-14 13:27:19 +01:00
|
|
|
|
ErrorText := 'There was an error initializing the CEF browser.';
|
|
|
|
|
|
|
|
|
|
if FSyncEvents then
|
|
|
|
|
Synchronize(DoOnError)
|
|
|
|
|
else
|
|
|
|
|
DoOnError;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCEFBrowserThread.Execute;
|
|
|
|
|
var
|
|
|
|
|
TempCont : boolean;
|
|
|
|
|
TempMsg : TMsg;
|
|
|
|
|
begin
|
|
|
|
|
if CreateBrowser then
|
|
|
|
|
begin
|
|
|
|
|
TempCont := True;
|
|
|
|
|
PeekMessage(TempMsg, 0, WM_USER, WM_USER, PM_NOREMOVE);
|
|
|
|
|
|
|
|
|
|
while TempCont and GetMessage(TempMsg, 0, 0, 0) and not(Terminated) do
|
|
|
|
|
begin
|
|
|
|
|
case TempMsg.Message of
|
|
|
|
|
CEF_PENDINGRESIZE : Resize;
|
|
|
|
|
CEF_CLOSE_BROWSER_MSG : CloseBrowser;
|
|
|
|
|
CEF_LOAD_PENDING_URL_MSG : LoadPendingURL;
|
|
|
|
|
CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing;
|
2020-12-14 13:27:19 +01:00
|
|
|
|
CEF_WEBPAGE_ERROR_MSG : WebpageError;
|
2020-12-13 18:36:10 +01:00
|
|
|
|
WM_QUIT : TempCont := False;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
DispatchMessage(TempMsg);
|
|
|
|
|
end;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
InitError;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end.
|