diff --git a/demos/Lazarus_Linux/PopupBrowser2/00-Delete.bat b/demos/Lazarus_Linux/PopupBrowser2/00-Delete.bat
new file mode 100644
index 00000000..0b5ba5c8
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/00-Delete.bat
@@ -0,0 +1,2 @@
+rmdir /S /Q lib
+rmdir /S /Q backup
diff --git a/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpi b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpi
new file mode 100644
index 00000000..afee6fe1
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpi
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpr b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpr
new file mode 100644
index 00000000..7ef05c2b
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lpr
@@ -0,0 +1,73 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 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 © 2018 Salvador DÃaz 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.
+ *
+ *)
+
+program PopupBrowser2;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}{$ENDIF}
+ // "Interfaces" is a custom unit used to initialize the LCL WidgetSet
+ // We keep the same name to avoid a Lazarus warning.
+ Interfaces, // this includes the LCL widgetset
+ Forms,
+ uCEFApplication,
+ uMainForm in 'uMainForm.pas' {MainForm},
+ uChildForm in 'uChildForm.pas' {ChildForm};
+
+//{$R *.res}
+
+begin
+ CreateGlobalCEFApp;
+
+ if GlobalCEFApp.StartMainProcess then
+ begin
+ // The LCL Widgetset must be initialized after the CEF initialization and
+ // only in the browser process.
+ CustomWidgetSetInitialization;
+ RequireDerivedFormResource:=True;
+ Application.Scaled:=True;
+ Application.Initialize;
+ Application.CreateForm(TMainForm, MainForm);
+ Application.Run;
+ CustomWidgetSetFinalization;
+ end;
+
+ DestroyGlobalCEFApp;
+end.
diff --git a/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lps b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lps
new file mode 100644
index 00000000..e15d2cfe
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/PopupBrowser2.lps
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/Lazarus_Linux/PopupBrowser2/cef.inc b/demos/Lazarus_Linux/PopupBrowser2/cef.inc
new file mode 100644
index 00000000..a4c8d038
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/cef.inc
@@ -0,0 +1,456 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 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 © 2017 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.
+ *
+ *)
+
+ // The complete list of compiler versions is here :
+ // http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
+
+{$DEFINE DELPHI_VERSION_UNKNOW}
+
+// Delphi 5
+{$IFDEF VER130}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+{$ENDIF}
+
+// Delphi 6
+{$IFDEF VER140}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+{$ENDIF}
+
+// Delphi 7
+{$IFDEF VER150}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+{$ENDIF}
+
+// Delphi 8
+{$IFDEF VER160}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+{$ENDIF}
+
+// Delphi 2005
+{$IFDEF VER170}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+{$ENDIF}
+
+{$IFDEF VER180}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ // Delphi 2007
+ {$IFDEF VER185}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ // Delphi 2006
+ {$ELSE}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$ENDIF}
+{$ENDIF}
+
+// Delphi 2009
+{$IFDEF VER200}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+{$ENDIF}
+
+//Delphi 2010
+{$IFDEF VER210}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+{$ENDIF}
+
+// Delphi XE
+{$IFDEF VER220}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+{$ENDIF}
+
+// Delphi XE2 (First FireMonkey and 64bit compiler)
+{$IFDEF VER230}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+{$ENDIF}
+
+// Delphi XE3
+{$IFDEF VER240}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+{$ENDIF}
+
+// Delphi XE4
+{$IFDEF VER250}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+{$ENDIF}
+
+// Delphi XE5
+{$IFDEF VER260}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+{$ENDIF}
+
+// Delphi XE6
+{$IFDEF VER270}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+{$ENDIF}
+
+// Delphi XE7
+{$IFDEF VER280}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+{$ENDIF}
+
+// Delphi XE8
+{$IFDEF VER290}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+{$ENDIF VER290}
+
+// Rad Studio 10 - Delphi Seattle
+{$IFDEF VER300}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+{$ENDIF}
+
+// Rad Studio 10.1 - Delphi Berlin
+{$IFDEF VER310}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+{$ENDIF}
+
+// Rad Studio 10.2 - Delphi Tokyo
+{$IFDEF VER320}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+{$ENDIF}
+
+// Rad Studio 10.3 - Delphi Rio
+{$IFDEF VER330}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+ {$DEFINE DELPHI26_UP}
+{$ENDIF}
+
+// Rad Studio 10.4 - Delphi Sydney
+{$IFDEF VER340}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+ {$DEFINE DELPHI26_UP}
+ {$DEFINE DELPHI27_UP}
+{$ENDIF}
+
+{$IFDEF FPC}
+ {$DEFINE SUPPORTS_INLINE}
+ {$IF DEFINED(FPC_FULLVERSION) AND (FPC_FULLVERSION >= 30200)}
+ {$DEFINE FPC_VER_320}
+ {$IFEND}
+{$ELSE}
+ {$IFDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+ {$DEFINE DELPHI26_UP}
+ {$DEFINE DELPHI27_UP}
+ {$ENDIF}
+{$ENDIF}
+
+{$IFDEF DELPHI9_UP}
+ {$DEFINE SUPPORTS_INLINE}
+{$ENDIF}
+
+{$IF DEFINED(CPUX32) OR
+ DEFINED(CPU386) OR
+ DEFINED(CPUi386) OR
+ DEFINED(CPUPOWERPC32) OR
+ DEFINED(CPUSPARC32) OR
+ DEFINED(CPU32BITS) OR
+ DEFINED(CPUARM32) OR
+ DEFINED(WIN32) OR
+ DEFINED(IOS32) OR
+ DEFINED(MACOS32) OR
+ DEFINED(LINUX32) OR
+ DEFINED(POSIX32) OR
+ DEFINED(ANDROID32)}
+ {$DEFINE TARGET_32BITS}
+{$IFEND}
+
diff --git a/demos/Lazarus_Linux/PopupBrowser2/interfaces.pas b/demos/Lazarus_Linux/PopupBrowser2/interfaces.pas
new file mode 100644
index 00000000..60c7250f
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/interfaces.pas
@@ -0,0 +1,30 @@
+unit Interfaces;
+
+{$mode objfpc}{$H+}
+
+interface
+
+{$IFDEF UNIX}{$IFNDEF DisableCWString}uses cwstring;{$ENDIF}{$ENDIF}
+
+procedure CustomWidgetSetInitialization;
+procedure CustomWidgetSetFinalization;
+
+implementation
+
+uses
+ {$IFNDEF EnableLibOverlay}
+ gtk2DisableLibOverlay,
+ {$ENDIF}
+ Gtk2Int, Forms;
+
+procedure CustomWidgetSetInitialization;
+begin
+ CreateWidgetset(TGtk2WidgetSet);
+end;
+
+procedure CustomWidgetSetFinalization;
+begin
+ FreeWidgetSet;
+end;
+
+end.
diff --git a/demos/Lazarus_Linux/PopupBrowser2/uChildForm.dfm b/demos/Lazarus_Linux/PopupBrowser2/uChildForm.dfm
new file mode 100644
index 00000000..f3186455
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/uChildForm.dfm
@@ -0,0 +1,41 @@
+object ChildForm: TChildForm
+ Left = 543
+ Height = 256
+ Top = 145
+ Width = 352
+ Caption = 'Popup'
+ ClientHeight = 256
+ ClientWidth = 352
+ Color = clBtnFace
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ OnClose = FormClose
+ OnCloseQuery = FormCloseQuery
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnShow = FormShow
+ Position = poDefault
+ LCLVersion = '2.0.10.0'
+ object CEFLinkedWindowParent1: TCEFLinkedWindowParent
+ Left = 0
+ Height = 256
+ Top = 0
+ Width = 352
+ Align = alClient
+ TabStop = True
+ TabOrder = 0
+ OnEnter = CEFLinkedWindowParent1Enter
+ OnExit = CEFLinkedWindowParent1Exit
+ Chromium = Chromium1
+ end
+ object Chromium1: TChromium
+ OnGotFocus = Chromium1GotFocus
+ OnTitleChange = Chromium1TitleChange
+ OnBeforePopup = Chromium1BeforePopup
+ OnBeforeClose = Chromium1BeforeClose
+ OnClose = Chromium1Close
+ Left = 24
+ Top = 56
+ end
+end
diff --git a/demos/Lazarus_Linux/PopupBrowser2/uChildForm.pas b/demos/Lazarus_Linux/PopupBrowser2/uChildForm.pas
new file mode 100644
index 00000000..a180d0a4
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/uChildForm.pas
@@ -0,0 +1,282 @@
+// ************************************************************************
+// ***************************** 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 uChildForm;
+
+{$mode objfpc}{$H+}
+
+{$I cef.inc}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
+ LMessages, SyncObjs,
+ uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFWindowParent,
+ uCEFWinControl, uCEFLinkedWindowParent, uCEFChromiumEvents;
+
+const
+ CEF_CLOSECHILD = $A52;
+
+type
+
+ { TChildForm }
+
+ TChildForm = class(TForm)
+ CEFLinkedWindowParent1: TCEFLinkedWindowParent;
+ Chromium1: TChromium;
+
+ procedure CEFLinkedWindowParent1Enter(Sender: TObject);
+ procedure CEFLinkedWindowParent1Exit(Sender: TObject);
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+ procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+
+ procedure Chromium1BeforePopup(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 Chromium1TitleChange(Sender: TObject; const browser: ICefBrowser; const title: ustring);
+ procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction);
+ procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+ procedure Chromium1GotFocus(Sender: TObject; const browser: ICefBrowser);
+ procedure FormShow(Sender: TObject);
+
+ protected
+ FCanClose : boolean;
+ FClosing : boolean;
+ FClientInitialized : boolean;
+ FPopupFeatures : TCefPopupFeatures;
+
+ procedure WMMove(var aMessage: TLMMove); message LM_MOVE;
+ procedure WMSize(var aMessage: TLMSize); message LM_SIZE;
+ procedure WMWindowPosChanged(var aMessage: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED;
+
+ procedure BrowserCloseFormMsg(Data: PtrInt);
+
+ public
+ procedure AfterConstruction; override;
+ function CreateClientHandler(var windowInfo : TCefWindowInfo; var client : ICefClient; const targetFrameName : string; const popupFeatures : TCefPopupFeatures) : boolean;
+ procedure ApplyPopupFeatures;
+ procedure SendCompMessage(aMsg : cardinal; aData : PtrInt = 0);
+
+ property ClientInitialized : boolean read FClientInitialized;
+ property Closing : boolean read FClosing;
+ end;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ Math,
+ uCEFMiscFunctions, uCEFApplication, uMainForm;
+
+// Destruction steps
+// =================
+// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event.
+// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event.
+// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form.
+
+procedure TChildForm.AfterConstruction;
+begin
+ inherited AfterConstruction;
+
+ CreateHandle;
+
+ CEFLinkedWindowParent1.CreateHandle;
+end;
+
+function TChildForm.CreateClientHandler(var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ const targetFrameName : string;
+ const popupFeatures : TCefPopupFeatures) : boolean;
+var
+ TempRect : TRect;
+begin
+ if Chromium1.CreateClientHandler(client, False) then
+ begin
+ Result := True;
+ FClientInitialized := True;
+ FPopupFeatures := popupFeatures;
+ TempRect := CEFLinkedWindowParent1.BoundsRect;
+
+ if (FPopupFeatures.widthset <> 0) then TempRect.Right := max(FPopupFeatures.width, 100);
+ if (FPopupFeatures.heightset <> 0) then TempRect.Bottom := max(FPopupFeatures.height, 100);
+
+ WindowInfoAsChild(windowInfo, CEFLinkedWindowParent1.Handle, TempRect, '');
+ end
+ else
+ Result := False;
+end;
+
+procedure TChildForm.ApplyPopupFeatures;
+begin
+ if (FPopupFeatures.xset <> 0) then Chromium1.SetFormLeftTo(FPopupFeatures.x);
+ if (FPopupFeatures.yset <> 0) then Chromium1.SetFormTopTo(FPopupFeatures.y);
+ if (FPopupFeatures.widthset <> 0) then Chromium1.ResizeFormWidthTo(FPopupFeatures.width);
+ if (FPopupFeatures.heightset <> 0) then Chromium1.ResizeFormHeightTo(FPopupFeatures.height);
+end;
+
+procedure TChildForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+begin
+ // We must wait until all browsers trigger the TChromium.OnBeforeClose event
+ // in order to close the application safely or we will have shutdown issues.
+ FCanClose := True;
+ SendCompMessage(CEF_BEFORECLOSE);
+end;
+
+procedure TChildForm.Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction);
+begin
+ // continue closing the browser
+ aAction := cbaClose;
+end;
+
+procedure TChildForm.Chromium1TitleChange(Sender: TObject; const browser: ICefBrowser; const title: ustring);
+begin
+ Caption := title;
+end;
+
+procedure TChildForm.WMMove(var aMessage : TLMMove);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TChildForm.WMSize(var aMessage: TLMSize);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TChildForm.WMWindowPosChanged(var aMessage: TLMWindowPosChanged);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TChildForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+ CloseAction := caFree;
+end;
+
+procedure TChildForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+ CanClose := FCanClose;
+
+ if not(FClosing) then
+ begin
+ FClosing := True;
+ Visible := False;
+ Chromium1.CloseBrowser(True);
+ end;
+end;
+
+procedure TChildForm.Chromium1BeforePopup(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
+ case targetDisposition of
+ WOD_NEW_FOREGROUND_TAB,
+ WOD_NEW_BACKGROUND_TAB,
+ WOD_NEW_WINDOW : Result := True; // For simplicity, this demo blocks new tabs and new windows.
+
+ WOD_NEW_POPUP : Result := not(TMainForm(Owner).CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures));
+
+ else Result := False;
+ end;
+end;
+
+procedure TChildForm.FormCreate(Sender: TObject);
+begin
+ FCanClose := False;
+ FClosing := False;
+ FClientInitialized := False;
+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 CEFLinkedWindowParent1.OnEnter, CEFLinkedWindowParent1.OnExit and
+// TChromium.OnGotFocus to avoid most of the focus issues.
+// CEFLinkedWindowParent1.TabStop must be TRUE.
+procedure TChildForm.CEFLinkedWindowParent1Enter(Sender: TObject);
+begin
+ if not(csDesigning in ComponentState) and
+ Chromium1.Initialized and
+ not(Chromium1.FrameIsFocused) then
+ Chromium1.SendFocusEvent(True);
+end;
+
+procedure TChildForm.CEFLinkedWindowParent1Exit(Sender: TObject);
+begin
+ if not(csDesigning in ComponentState) then
+ Chromium1.SendCaptureLostEvent;
+end;
+
+procedure TChildForm.Chromium1GotFocus(Sender: TObject;
+ const browser: ICefBrowser);
+begin
+ CEFLinkedWindowParent1.SetFocus;
+end;
+
+procedure TChildForm.FormShow(Sender: TObject);
+begin
+
+end;
+
+procedure TChildForm.FormDestroy(Sender: TObject);
+begin
+ if FClientInitialized then
+ TMainForm(Owner).SendCompMessage(CEF_CHILDDESTROYED);
+end;
+
+procedure TChildForm.BrowserCloseFormMsg(Data: PtrInt);
+begin
+ Close;
+end;
+
+procedure TChildForm.SendCompMessage(aMsg : cardinal; aData : PtrInt);
+begin
+ case aMsg of
+ CEF_BEFORECLOSE : Application.QueueAsyncCall(@BrowserCloseFormMsg, aData);
+ end;
+end;
+
+end.
diff --git a/demos/Lazarus_Linux/PopupBrowser2/uMainForm.lfm b/demos/Lazarus_Linux/PopupBrowser2/uMainForm.lfm
new file mode 100644
index 00000000..262b59c5
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/uMainForm.lfm
@@ -0,0 +1,71 @@
+object MainForm: TMainForm
+ Left = 364
+ Height = 624
+ Top = 213
+ Width = 1038
+ Caption = 'Initializing browser. Please wait...'
+ ClientHeight = 624
+ ClientWidth = 1038
+ Color = clBtnFace
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ OnActivate = FormActivate
+ OnCloseQuery = FormCloseQuery
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ Position = poScreenCenter
+ LCLVersion = '2.0.10.0'
+ object AddressPnl: TPanel
+ Left = 0
+ Height = 21
+ Top = 0
+ Width = 1038
+ Align = alTop
+ BevelOuter = bvNone
+ ClientHeight = 21
+ ClientWidth = 1038
+ Enabled = False
+ TabOrder = 0
+ object AddressEdt: TEdit
+ Left = 0
+ Height = 21
+ Top = 0
+ Width = 1007
+ Align = alClient
+ TabOrder = 0
+ Text = 'file:///PopupBrowser.html'
+ end
+ object GoBtn: TButton
+ Left = 1007
+ Height = 21
+ Top = 0
+ Width = 31
+ Align = alRight
+ Caption = 'Go'
+ OnClick = GoBtnClick
+ TabOrder = 1
+ end
+ end
+ object CEFLinkedWindowParent1: TCEFLinkedWindowParent
+ Left = 0
+ Height = 603
+ Top = 21
+ Width = 1038
+ Align = alClient
+ TabStop = True
+ TabOrder = 1
+ OnEnter = CEFLinkedWindowParent1Enter
+ OnExit = CEFLinkedWindowParent1Exit
+ Chromium = Chromium1
+ end
+ object Chromium1: TChromium
+ OnGotFocus = Chromium1GotFocus
+ OnBeforePopup = Chromium1BeforePopup
+ OnAfterCreated = Chromium1AfterCreated
+ OnBeforeClose = Chromium1BeforeClose
+ OnClose = Chromium1Close
+ Left = 56
+ Top = 152
+ end
+end
diff --git a/demos/Lazarus_Linux/PopupBrowser2/uMainForm.pas b/demos/Lazarus_Linux/PopupBrowser2/uMainForm.pas
new file mode 100644
index 00000000..77b77117
--- /dev/null
+++ b/demos/Lazarus_Linux/PopupBrowser2/uMainForm.pas
@@ -0,0 +1,443 @@
+// ************************************************************************
+// ***************************** 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 uMainForm;
+
+{$mode objfpc}{$H+}
+
+{$I cef.inc}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
+ LMessages, SyncObjs,
+ uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes,
+ uChildForm, uCEFWinControl, uCEFChromiumEvents, uCEFLinkedWindowParent;
+
+const
+ CEF_CREATENEXTCHILD = $A50;
+ CEF_CHILDDESTROYED = $A51;
+ CEF_INITIALIZED = $A52;
+
+type
+
+ { TMainForm }
+
+ TMainForm = class(TForm)
+ AddressPnl: TPanel;
+ AddressEdt: TEdit;
+ CEFLinkedWindowParent1: TCEFLinkedWindowParent;
+ GoBtn: TButton;
+ Chromium1: TChromium;
+
+ procedure CEFLinkedWindowParent1Enter(Sender: TObject);
+ procedure CEFLinkedWindowParent1Exit(Sender: TObject);
+
+ procedure GoBtnClick(Sender: TObject);
+
+ procedure FormActivate(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+
+ procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
+ procedure Chromium1BeforePopup(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 Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+ procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
+ procedure Chromium1GotFocus(Sender: TObject; const browser: ICefBrowser);
+
+ protected
+ FChildForm : TChildForm;
+ FCriticalSection : TCriticalSection;
+ FCanClose : boolean; // Set to True in TChromium.OnBeforeClose
+ FClosingMainForm : boolean; // Set to True in the CloseQuery event.
+ FClosingChildren : boolean; // Set to True in the CloseQuery event.
+
+ function GetPopupChildCount : integer;
+
+ procedure ClosePopupChildren;
+ procedure CreateHiddenChildForm;
+
+ procedure WMMove(var aMessage: TLMMove); message LM_MOVE;
+ procedure WMSize(var aMessage: TLMSize); message LM_SIZE;
+ procedure WMWindowPosChanged(var aMessage: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED;
+
+ procedure BrowserCreatedMsg(Data: PtrInt);
+ procedure BrowserInitializedMsg(Data: PtrInt);
+ procedure BrowserCreateNextChildMsg(Data: PtrInt);
+ procedure BrowserChildDestroyedMsg(Data: PtrInt);
+ procedure BrowserCloseFormMsg(Data: PtrInt);
+
+ property PopupChildCount : integer read GetPopupChildCount;
+
+ public
+ function CreateClientHandler(var windowInfo : TCefWindowInfo; var client : ICefClient; const targetFrameName : string; const popupFeatures : TCefPopupFeatures) : boolean;
+ procedure SendCompMessage(aMsg : cardinal; aData : PtrInt = 0);
+ end;
+
+var
+ MainForm: TMainForm;
+
+procedure CreateGlobalCEFApp;
+
+implementation
+
+{$R *.lfm}
+
+uses
+ LCLIntf,
+ uCEFApplication, uCEFMiscFunctions;
+
+// This is demo shows how to create popup windows in CEF.
+
+// You need to understand the SimpleBrowser2 demo completely before trying to understand this demo.
+
+// When TChromium needs to show a new popup window it executes TChromium.OnBeforePopup.
+
+// LCL components *MUST* be created and destroyed in the main thread but CEF executes the
+// TChromium.OnBeforePopup in a different thread.
+
+// For this reason this demo creates a hidden popup form (TChildForm) in case CEF needs to show a popup window.
+// TChromium.OnBeforePopup calls TChildForm.CreateClientHandler to initialize some parameters and create the new ICefClient.
+// After that, it sends a CEF_CREATENEXTCHILD message to show the popup form and create a new one.
+
+// All the child forms must be correctly destroyed before closing the main form. Read the code comments in uChildForm.pas
+// to know how the popup windows are destroyed.
+
+// The main form close all active popup forms and waits until all of them have sent a CEF_CHILDDESTROYED message.
+
+// Destruction steps
+// =================
+// 1. FormCloseQuery sets CanClose to FALSE and it closes all child forms.
+// 2. When all the child forms are closed then FormCloseQuery is triggered again, sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event.
+// 3. TChromium.OnClose sets aAction to cbaClose which triggers the TChromium.OnBeforeClose event.
+// 4. TChromium.OnBeforeClose sets FCanClose := True and sends a CEF_BEFORECLOSE message to close the form in the main thread.
+
+
+// Many other demos use a timer to create the browser but this demo sends a
+// CEF_INITIALIZED message in the GlobalCEFApp.OnContextInitialized and
+// TForm.OnActivate events
+procedure GlobalCEFApp_OnContextInitialized;
+begin
+ if (MainForm <> nil) and MainForm.Showing and MainForm.Focused then
+ MainForm.SendCompMessage(CEF_INITIALIZED);
+end;
+
+procedure CreateGlobalCEFApp;
+begin
+ GlobalCEFApp := TCefApplication.Create;
+ GlobalCEFApp.OnContextInitialized := @GlobalCEFApp_OnContextInitialized;
+end;
+
+procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+ FClosingChildren := True;
+ Visible := False;
+
+ if (PopupChildCount > 0) then
+ begin
+ ClosePopupChildren;
+ CanClose := False;
+ end
+ else
+ begin
+ CanClose := FCanClose;
+
+ if not(FClosingMainForm) then
+ begin
+ FClosingMainForm := True;
+ Chromium1.CloseBrowser(True);
+ end;
+ end;
+end;
+
+procedure TMainForm.FormCreate(Sender: TObject);
+begin
+ FClosingChildren := False;
+ FClosingMainForm := False;
+ FCanClose := False;
+ FCriticalSection := TCriticalSection.Create;
+
+ // CEF can't find the HTML if we load file:///filename.html in Linux so we
+ // add the full path manually.
+ // The "Click me to open a file" button in PopupBrowser.html will not work
+ // because of this limitation.
+ AddressEdt.Text := 'file://' + IncludeTrailingPathDelimiter(ExtractFileDir(ParamStr(0))) + 'PopupBrowser.html';
+
+ Chromium1.DefaultURL := UTF8Decode(AddressEdt.Text);
+ Chromium1.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF);
+
+ CreateHiddenChildForm;
+end;
+
+procedure TMainForm.FormDestroy(Sender: TObject);
+begin
+ FreeAndNil(FCriticalSection);
+end;
+
+procedure TMainForm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
+begin
+ // Now the browser is fully initialized we can send a message to the main form
+ // to enable the user interface.
+ SendCompMessage(CEF_AFTERCREATED);
+end;
+
+procedure TMainForm.Chromium1BeforePopup(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
+ case targetDisposition of
+ WOD_NEW_FOREGROUND_TAB,
+ WOD_NEW_BACKGROUND_TAB,
+ WOD_NEW_WINDOW : Result := True; // For simplicity, this demo blocks new tabs and new windows.
+
+ WOD_NEW_POPUP : Result := not(CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures));
+
+ else Result := False;
+ end;
+end;
+
+function TMainForm.CreateClientHandler(var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ const targetFrameName : string;
+ const popupFeatures : TCefPopupFeatures) : boolean;
+begin
+ try
+ FCriticalSection.Acquire;
+
+ if (FChildForm <> nil) and
+ FChildForm.CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures) then
+ begin
+ SendCompMessage(CEF_CREATENEXTCHILD);
+ Result := True;
+ end;
+ finally
+ FCriticalSection.Release;
+ end;
+end;
+
+function TMainForm.GetPopupChildCount : integer;
+var
+ i : integer;
+ TempForm : TCustomForm;
+begin
+ Result := 0;
+ i := pred(screen.CustomFormCount);
+
+ while (i >= 0) do
+ begin
+ TempForm := screen.CustomForms[i];
+
+ // Only count the fully initialized child forms and not the one waiting to be used.
+
+ if (TempForm is TChildForm) and
+ TChildForm(TempForm).ClientInitialized then
+ inc(Result);
+
+ dec(i);
+ end;
+end;
+
+procedure TMainForm.ClosePopupChildren;
+var
+ i : integer;
+ TempForm : TCustomForm;
+begin
+ i := pred(screen.CustomFormCount);
+
+ while (i >= 0) do
+ begin
+ TempForm := screen.CustomForms[i];
+
+ // Only send WM_CLOSE to fully initialized child forms.
+
+ if (TempForm is TChildForm) and
+ TChildForm(TempForm).ClientInitialized and
+ not(TChildForm(TempForm).Closing) then
+ TempForm.Close;
+
+ dec(i);
+ end;
+end;
+
+procedure TMainForm.GoBtnClick(Sender: TObject);
+begin
+ // This will load the URL in the edit box
+ Chromium1.LoadURL(UTF8Decode(AddressEdt.Text));
+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 CEFLinkedWindowParent1.OnEnter, CEFLinkedWindowParent1.OnExit and
+// TChromium.OnGotFocus to avoid most of the focus issues.
+// CEFLinkedWindowParent1.TabStop must be TRUE.
+procedure TMainForm.CEFLinkedWindowParent1Enter(Sender: TObject);
+begin
+ if not(csDesigning in ComponentState) and
+ Chromium1.Initialized and
+ not(Chromium1.FrameIsFocused) then
+ Chromium1.SendFocusEvent(True);
+end;
+
+procedure TMainForm.CEFLinkedWindowParent1Exit(Sender: TObject);
+begin
+ if not(csDesigning in ComponentState) then
+ Chromium1.SendCaptureLostEvent;
+end;
+
+procedure TMainForm.Chromium1GotFocus(Sender: TObject;
+ const browser: ICefBrowser);
+begin
+ CEFLinkedWindowParent1.SetFocus;
+end;
+
+procedure TMainForm.FormActivate(Sender: TObject);
+begin
+ // Linux needs a fully formed window to add a Chromium browser so we use this
+ // event to send a CEF_INITIALIZED message that will create the browser.
+ SendCompMessage(CEF_INITIALIZED);
+end;
+
+procedure TMainForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+begin
+ // We must wait until all browsers trigger the TChromium.OnBeforeClose event
+ // in order to close the application safely or we will have shutdown issues.
+ FCanClose := True;
+ SendCompMessage(CEF_BEFORECLOSE);
+end;
+
+procedure TMainForm.Chromium1Close(Sender: TObject; const browser: ICefBrowser;
+ var aAction: TCefCloseBrowserAction);
+begin
+ // continue closing the browser
+ aAction := cbaClose;
+end;
+
+procedure TMainForm.WMMove(var aMessage : TLMMove);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainForm.WMSize(var aMessage: TLMSize);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainForm.WMWindowPosChanged(var aMessage: TLMWindowPosChanged);
+begin
+ inherited;
+ Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainForm.CreateHiddenChildForm;
+begin
+ // Linux requires a fully formed window in order to add a Chromium browser so
+ // we show the next popup window outside the visible screen space and then we
+ // hide it.
+ FChildForm := TChildForm.Create(self);
+ FChildForm.Top := -1000;
+ FChildForm.Left := -1000;
+ FChildForm.Show;
+ FChildForm.Hide;
+ // Center the child form on the screen by default
+ FChildForm.Top := (screen.Height - FChildForm.Height) div 2;
+ FChildForm.Left := (screen.Width - FChildForm.Width) div 2;
+end;
+
+procedure TMainForm.BrowserCreatedMsg(Data: PtrInt);
+begin
+ Caption := 'Popup Browser';
+ cursor := crDefault;
+ AddressPnl.Enabled := True;
+end;
+
+procedure TMainForm.BrowserInitializedMsg(Data: PtrInt);
+begin
+ if not(Chromium1.Initialized) then
+ Chromium1.CreateBrowser(CEFLinkedWindowParent1.Handle, CEFLinkedWindowParent1.BoundsRect);
+end;
+
+procedure TMainForm.BrowserChildDestroyedMsg(Data: PtrInt);
+begin
+ if FClosingChildren and (PopupChildCount = 0) then Close;
+end;
+
+procedure TMainForm.BrowserCreateNextChildMsg(Data: PtrInt);
+begin
+ try
+ FCriticalSection.Acquire;
+
+ if (FChildForm <> nil) then
+ begin
+ FChildForm.ApplyPopupFeatures;
+ FChildForm.Show;
+ // SetActiveWindow should bring the child form to the front...
+ SetActiveWindow(FChildForm.Handle);
+ end;
+
+ CreateHiddenChildForm;
+ finally
+ FCriticalSection.Release;
+ end;
+end;
+
+procedure TMainForm.BrowserCloseFormMsg(Data: PtrInt);
+begin
+ Close;
+end;
+
+procedure TMainForm.SendCompMessage(aMsg : cardinal; aData : PtrInt);
+begin
+ case aMsg of
+ CEF_INITIALIZED : Application.QueueAsyncCall(@BrowserInitializedMsg, aData);
+ CEF_AFTERCREATED : Application.QueueAsyncCall(@BrowserCreatedMsg, aData);
+ CEF_CREATENEXTCHILD : Application.QueueAsyncCall(@BrowserCreateNextChildMsg, aData);
+ CEF_CHILDDESTROYED : Application.QueueAsyncCall(@BrowserChildDestroyedMsg, aData);
+ CEF_BEFORECLOSE : Application.QueueAsyncCall(@BrowserCloseFormMsg, aData);
+ end;
+end;
+
+end.
diff --git a/demos/Lazarus_Linux/SimpleOSRBrowser/SimpleOSRBrowser.lps b/demos/Lazarus_Linux/SimpleOSRBrowser/SimpleOSRBrowser.lps
index b2d702f0..2857f6b6 100644
--- a/demos/Lazarus_Linux/SimpleOSRBrowser/SimpleOSRBrowser.lps
+++ b/demos/Lazarus_Linux/SimpleOSRBrowser/SimpleOSRBrowser.lps
@@ -3,15 +3,14 @@
-
+
-
-
+
+
-
-
+
@@ -20,9 +19,10 @@
-
-
-
+
+
+
+
@@ -34,11 +34,9 @@
-
-
+
-
-
+
@@ -128,12 +126,12 @@
-
-
-
+
+
+
-
-
+
+
@@ -202,9 +200,9 @@
-
-
-
+
+
+
@@ -707,8 +705,8 @@
-
-
+
+
@@ -755,143 +753,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
diff --git a/demos/Lazarus_Linux/TabbedBrowser2/TabbedBrowser2.lps b/demos/Lazarus_Linux/TabbedBrowser2/TabbedBrowser2.lps
index 22d2f435..e0c3a64b 100644
--- a/demos/Lazarus_Linux/TabbedBrowser2/TabbedBrowser2.lps
+++ b/demos/Lazarus_Linux/TabbedBrowser2/TabbedBrowser2.lps
@@ -39,13 +39,13 @@
-
-
+
+
-
-
-
+
+
+
@@ -125,123 +125,127 @@
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
+
+
+
+
+
diff --git a/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.lfm b/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.lfm
index f2a64ec1..0af54084 100644
--- a/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.lfm
+++ b/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.lfm
@@ -198,6 +198,7 @@ object BrowserFrame: TBrowserFrame
Top = 28
Width = 932
Align = alClient
+ TabStop = True
TabOrder = 2
OnEnter = CEFLinkedWindowParent1Enter
OnExit = CEFLinkedWindowParent1Exit
diff --git a/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.pas b/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.pas
index bd9782d4..3cbbcd35 100644
--- a/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.pas
+++ b/demos/Lazarus_Linux/TabbedBrowser2/uBrowserFrame.pas
@@ -309,18 +309,29 @@ begin
SendCompMessage(CEF_AFTERCREATED);
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 CEFLinkedWindowParent1.OnEnter, CEFLinkedWindowParent1.OnExit and
+// TChromium.OnGotFocus to avoid most of the focus issues.
+// CEFLinkedWindowParent1.TabStop must be TRUE.
+procedure TBrowserFrame.CEFLinkedWindowParent1Exit(Sender: TObject);
+begin
+ if not(csDesigning in ComponentState) then
+ Chromium1.SendCaptureLostEvent;
+end;
+
procedure TBrowserFrame.CEFLinkedWindowParent1Enter(Sender: TObject);
begin
if not(csDesigning in ComponentState) and
Chromium1.Initialized and
not(Chromium1.FrameIsFocused) then
Chromium1.SendFocusEvent(True);
-end;
+end;
-procedure TBrowserFrame.CEFLinkedWindowParent1Exit(Sender: TObject);
+procedure TBrowserFrame.Chromium1GotFocus(Sender: TObject;
+ const browser: ICefBrowser);
begin
- if not(csDesigning in ComponentState) then
- Chromium1.SendCaptureLostEvent;
+ CEFLinkedWindowParent1.SetFocus;
end;
procedure TBrowserFrame.BackBtnClick(Sender: TObject);
@@ -360,12 +371,6 @@ begin
aAction := cbaClose;
end;
-procedure TBrowserFrame.Chromium1GotFocus(Sender: TObject;
- const browser: ICefBrowser);
-begin
- CEFLinkedWindowParent1.SetFocus;
-end;
-
procedure TBrowserFrame.Chromium1LoadError(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer;
const errorText, failedUrl: ustring);
@@ -431,7 +436,8 @@ var
begin
TempURL := BrowserAddress;
- if (URLCbx.Items.IndexOf(TempURL) < 0) then URLCbx.Items.Add(TempURL);
+ if (URLCbx.Items.IndexOf(TempURL) < 0) then
+ URLCbx.Items.Add(TempURL);
URLCbx.Text := TempURL;
end;
diff --git a/source/uCEFLinkedWindowParent.pas b/source/uCEFLinkedWindowParent.pas
index 6fd8aead..399a464c 100644
--- a/source/uCEFLinkedWindowParent.pas
+++ b/source/uCEFLinkedWindowParent.pas
@@ -70,7 +70,6 @@ type
{$IFDEF FPC}{$IFDEF LINUX}
procedure SetVisible(Value: Boolean); override;
- procedure UpdateSize; override;
{$ENDIF}{$ENDIF}
procedure SetChromium(aValue : TChromium);
@@ -82,6 +81,9 @@ type
public
constructor Create(AOwner : TComponent); override;
+ {$IFDEF FPC}{$IFDEF LINUX}
+ procedure UpdateSize; override;
+ {$ENDIF}{$ENDIF}
published
property Chromium : TChromium read FChromium write SetChromium;
diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json
index c511fdec..6943debd 100644
--- a/update_CEF4Delphi.json
+++ b/update_CEF4Delphi.json
@@ -2,7 +2,7 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
- "InternalVersion" : 221,
+ "InternalVersion" : 222,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "87.1.12.0"
}