diff --git a/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.lfm b/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.lfm index 0558d077..93f9602b 100644 --- a/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.lfm +++ b/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.lfm @@ -13,18 +13,18 @@ object Form1: TForm1 LCLVersion = '2.0.10.0' object AddressPnl: TPanel Left = 0 - Height = 21 + Height = 25 Top = 0 Width = 1013 Align = alTop BevelOuter = bvNone - ClientHeight = 21 + ClientHeight = 25 ClientWidth = 1013 Enabled = False TabOrder = 0 object AddressEdt: TEdit Left = 0 - Height = 21 + Height = 25 Top = 0 Width = 982 Align = alClient @@ -33,7 +33,7 @@ object Form1: TForm1 end object GoBtn: TButton Left = 982 - Height = 21 + Height = 25 Top = 0 Width = 31 Align = alRight @@ -44,10 +44,11 @@ object Form1: TForm1 end object ChromiumWindow1: TChromiumWindow Left = 0 - Height = 684 - Top = 21 + Height = 680 + Top = 25 Width = 1013 Align = alClient + TabStop = True TabOrder = 1 OnBeforeClose = ChromiumWindow1BeforeClose OnAfterCreated = ChromiumWindow1AfterCreated diff --git a/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.pas b/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.pas index 15b5a438..1a75e9d4 100644 --- a/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.pas +++ b/demos/Lazarus_Linux/SimpleBrowser/usimplebrowser.pas @@ -64,7 +64,7 @@ type procedure FormCreate(Sender: TObject); procedure ChromiumWindow1AfterCreated(Sender: TObject); - procedure ChromiumWindow1BeforeClose(Sender: TObject); + procedure ChromiumWindow1BeforeClose(Sender: TObject); private protected @@ -136,7 +136,7 @@ begin FClosing := False; // The browser will load the URL in AddressEdt initially. - ChromiumWindow1.ChromiumBrowser.DefaultURL := AddressEdt.Text; + ChromiumWindow1.ChromiumBrowser.DefaultURL := UTF8Decode(AddressEdt.Text); end; procedure TForm1.Chromium_OnBeforePopup(Sender: TObject; @@ -160,7 +160,7 @@ end; procedure TForm1.GoBtnClick(Sender: TObject); begin // This will load the URL in the edit box - ChromiumWindow1.LoadURL(AddressEdt.Text); + ChromiumWindow1.LoadURL(UTF8Decode(AddressEdt.Text)); end; procedure TForm1.FormActivate(Sender: TObject); diff --git a/demos/Lazarus_Linux/TinyBrowser2/TinyBrowser2.lpr b/demos/Lazarus_Linux/TinyBrowser2/TinyBrowser2.lpr index 5110ca93..f47a45a9 100644 --- a/demos/Lazarus_Linux/TinyBrowser2/TinyBrowser2.lpr +++ b/demos/Lazarus_Linux/TinyBrowser2/TinyBrowser2.lpr @@ -10,7 +10,7 @@ // For more information about CEF4Delphi visit : // https://www.briskbard.com/index.php?lang=en&pageid=cef // -// Copyright © 2018 Salvador Díaz Fau. All rights reserved. +// Copyright © 2021 Salvador Díaz Fau. All rights reserved. // // ************************************************************************ // ************ vvvv Original license and comments below vvvv ************* @@ -42,9 +42,7 @@ program TinyBrowser2; uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, - cmem, {$ENDIF}{$ENDIF} - Interfaces, uCEFApplication, uTinyBrowser2 in 'uTinyBrowser2.pas'; diff --git a/demos/Lazarus_Linux/TinyBrowser2/uTinyBrowser2.pas b/demos/Lazarus_Linux/TinyBrowser2/uTinyBrowser2.pas index 71b364f5..e3aeccef 100644 --- a/demos/Lazarus_Linux/TinyBrowser2/uTinyBrowser2.pas +++ b/demos/Lazarus_Linux/TinyBrowser2/uTinyBrowser2.pas @@ -50,7 +50,6 @@ type private FChromium : TChromiumCore; - procedure Chromium_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); procedure Chromium_OnBeforeClose(Sender: TObject; const browser: ICefBrowser); procedure Chromium_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 Chromium_OnOpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean); @@ -58,7 +57,6 @@ type public constructor Create; destructor Destroy; override; - procedure AfterConstruction; override; end; procedure CreateGlobalCEFApp; @@ -69,17 +67,19 @@ implementation // This demo is similar to the cefsimple demo in the official CEF project. // It doesn't use LCL to create forms from Lazarus code. -// It just uses CEF to create a browser window as if it was a popup browser window. +// It just uses CEF to create a browser window as if it was a popup browser +// window. -// This browser doesn't use multiple threads to handle the browser and it doesn't use an external message pump. -// For this reason we have to call GlobalCEFApp.RunMessageLoop to let CEF handle the message loop and +// This browser doesn't use multiple threads to handle the browser and it +// doesn't use an external message pump. For this reason we have to call +// GlobalCEFApp.RunMessageLoop to let CEF handle the message loop and // GlobalCEFApp.QuitMessageLoop when the browser has been destroyed. // The destruction steps are much simpler for that reason. -// In this demo it's only necessary to implement the TChromium.OnClose and TChromium.OnBeforeClose events. -// The TChromium.OnClose event only sets aAction to cbaClose to continue closing the browser. -// The TChromium.OnBeforeClose event calls GlobalCEFApp.QuitMessageLoop because the browser has been destroyed -// and it's necessary to close the message loop. +// In this demo it's only necessary to implement the TChromium.OnBeforeClose +// events. The TChromium.OnBeforeClose event calls GlobalCEFApp.QuitMessageLoop +// because the browser has been destroyed and it's necessary to close the +// message loop. uses uCEFApplication, uCEFConstants; @@ -117,47 +117,34 @@ constructor TTinyBrowser2.Create; begin inherited Create; - FChromium := nil; -end; - -destructor TTinyBrowser2.Destroy; -begin - if (FChromium <> nil) then - begin - FChromium.Free; - FChromium := nil; - end; - - inherited Destroy; -end; - -procedure TTinyBrowser2.AfterConstruction; -begin - inherited AfterConstruction; - FChromium := TChromiumCore.Create(nil); FChromium.DefaultURL := 'https://www.google.com'; - FChromium.OnClose := Chromium_OnClose; FChromium.OnBeforeClose := Chromium_OnBeforeClose; FChromium.OnBeforePopup := Chromium_OnBeforePopup; FChromium.OnOpenUrlFromTab := Chromium_OnOpenUrlFromTab; FChromium.CreateBrowser('Tiny Browser 2'); end; -procedure TTinyBrowser2.Chromium_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); +destructor TTinyBrowser2.Destroy; begin - aAction := cbaClose; + if (FChromium <> nil) then + FreeAndNil(FChromium); + + inherited Destroy; end; -procedure TTinyBrowser2.Chromium_OnBeforeClose(Sender: TObject; const browser: ICefBrowser); +procedure TTinyBrowser2.Chromium_OnBeforeClose(Sender: TObject; + const browser: ICefBrowser); begin GlobalCEFApp.QuitMessageLoop; end; -procedure TTinyBrowser2.Chromium_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; +procedure TTinyBrowser2.Chromium_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 diff --git a/source/uCEFChromiumWindow.pas b/source/uCEFChromiumWindow.pas index 72f69591..532d2041 100644 --- a/source/uCEFChromiumWindow.pas +++ b/source/uCEFChromiumWindow.pas @@ -74,10 +74,9 @@ type {$IFDEF FPC} procedure SetVisible(Value: Boolean); override; {$ENDIF} - function GetBrowserInitialized : boolean; + function GetBrowserInitialized : boolean; + function GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; override; {$IFDEF MSWINDOWS} - function GetChildWindowHandle : THandle; override; - procedure WndProc(var aMessage: TMessage); override; procedure OnCloseMsg(var aMessage : TMessage); message CEF_DOONCLOSE; @@ -86,11 +85,14 @@ type procedure WebBrowser_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); procedure WebBrowser_OnBeforeClose(Sender: TObject; const browser: ICefBrowser); procedure WebBrowser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); - {$IFDEF FPC} - procedure BrowserAfterCreated(Data: PtrInt); + procedure WebBrowser_OnGotFocus(Sender: TObject; const browser: ICefBrowser); + procedure BrowserSetFocusMsg(Data: PtrInt); + procedure BrowserAfterCreated(Data: PtrInt); procedure BrowserOnCLose(Data: PtrInt); {$ENDIF} + procedure DoEnter; override; + procedure DoExit; override; public constructor Create(AOwner: TComponent); override; @@ -176,11 +178,15 @@ begin FChromium.OnClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnClose; FChromium.OnBeforeClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnBeforeClose; FChromium.OnAfterCreated := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnAfterCreated; + {$IFDEF LINUX} + // This is a workaround for the CEF issue #2026. Read below for more info. + FChromium.OnGotFocus := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnGotFocus; + TabStop := True; + {$ENDIF} end; end; -{$IFDEF MSWINDOWS} -function TChromiumWindow.GetChildWindowHandle : THandle; +function TChromiumWindow.GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; begin Result := 0; @@ -189,6 +195,7 @@ begin if (Result = 0) then Result := inherited GetChildWindowHandle; end; +{$IFDEF MSWINDOWS} procedure TChromiumWindow.WndProc(var aMessage: TMessage); var TempHandle : THandle; @@ -274,6 +281,16 @@ end; {$ENDIF} {$IFDEF FPC} +procedure TChromiumWindow.WebBrowser_OnGotFocus(Sender: TObject; const browser: ICefBrowser); +begin + Application.QueueAsyncCall(@BrowserSetFocusMsg, 0); +end; + +procedure TChromiumWindow.BrowserSetFocusMsg(Data: PtrInt); +begin + SetFocus; +end; + procedure TChromiumWindow.BrowserAfterCreated(Data: PtrInt); begin UpdateSize; @@ -344,6 +361,34 @@ begin {$ENDIF} end; + +// This is a workaround for the CEF issue #2026 +// https://bitbucket.org/chromiumembedded/cef/issues/2026/multiple-major-keyboard-focus-issues-on +// We use ChromiumWindow1.OnEnter, ChromiumWindow1.OnExit and +// TChromium.OnGotFocus to avoid most of the focus issues. +// ChromiumWindow1.TabStop must be TRUE. +procedure TChromiumWindow.DoEnter; +begin + inherited DoEnter; + + {$IFDEF LINUX} + if not(csDesigning in ComponentState) and + FChromium.Initialized and + not(FChromium.FrameIsFocused) then + FChromium.SendFocusEvent(True); + {$ENDIF} +end; + +procedure TChromiumWindow.DoExit; +begin + inherited DoExit; + + {$IFDEF LINUX} + if not(csDesigning in ComponentState) then + FChromium.SendCaptureLostEvent; + {$ENDIF} +end; + {$IFDEF FPC} procedure Register; begin diff --git a/source/uCEFLinkedWindowParent.pas b/source/uCEFLinkedWindowParent.pas index 59c3bd2a..ac33cad4 100644 --- a/source/uCEFLinkedWindowParent.pas +++ b/source/uCEFLinkedWindowParent.pas @@ -73,7 +73,7 @@ type {$ENDIF} procedure SetChromium(aValue : TChromium); - function GetChildWindowHandle : THandle; override; + function GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; override; {$IFDEF MSWINDOWS} procedure WndProc(var aMessage: TMessage); override; {$ENDIF} @@ -105,7 +105,7 @@ begin FChromium := nil; end; -function TCEFLinkedWindowParent.GetChildWindowHandle : THandle; +function TCEFLinkedWindowParent.GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; begin Result := 0; diff --git a/source/uCEFWinControl.pas b/source/uCEFWinControl.pas index 8e4f29e6..509c6186 100644 --- a/source/uCEFWinControl.pas +++ b/source/uCEFWinControl.pas @@ -62,7 +62,7 @@ uses type TCEFWinControl = class(TWinControl) protected - function GetChildWindowHandle : THandle; virtual; + function GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; virtual; procedure Resize; override; public @@ -110,7 +110,7 @@ implementation uses uCEFMiscFunctions, uCEFClient, uCEFConstants; -function TCEFWinControl.GetChildWindowHandle : THandle; +function TCEFWinControl.GetChildWindowHandle : {$IFDEF FPC}LclType.{$ENDIF}THandle; begin {$IFDEF MSWINDOWS} if not(csDesigning in ComponentState) and HandleAllocated then diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json index fecd0511..161bfcc6 100644 --- a/update_CEF4Delphi.json +++ b/update_CEF4Delphi.json @@ -2,7 +2,7 @@ "UpdateLazPackages" : [ { "ForceNotify" : true, - "InternalVersion" : 260, + "InternalVersion" : 261, "Name" : "cef4delphi_lazarus.lpk", "Version" : "88.2.9.0" }