diff --git a/demos/Lazarus_any_OS/BrowserWindow/README.txt b/demos/Lazarus_any_OS/BrowserWindow/README.txt index 5f7d3918..99a23a57 100644 --- a/demos/Lazarus_any_OS/BrowserWindow/README.txt +++ b/demos/Lazarus_any_OS/BrowserWindow/README.txt @@ -28,13 +28,13 @@ Note: ** Mac 1) Go to "project options" and create the "App Bundle" -2) Download the CEF framework and place the content of the "Release" folder into ExternalPumpBrowser.app/Contents/Frameworks/Chromium Embedded Framework.framework +2) Download the CEF framework and place the content of the "Release" folder into BrowserWindow.app/Contents/Frameworks/Chromium Embedded Framework.framework You should have: Chromium Embedded Framework Libraries/* Resources/* 3) Open project "AppHelper", create App Bundle and compile the AppHelper. Run create_mac_helper.sh -4) Open project ExternalPumpBrowser, compile and run +4) Open project BrowserWindow, compile and run diff --git a/demos/Lazarus_any_OS/BrowserWindow/globalcefapplication.pas b/demos/Lazarus_any_OS/BrowserWindow/globalcefapplication.pas index 4e97ab04..64a101b3 100644 --- a/demos/Lazarus_any_OS/BrowserWindow/globalcefapplication.pas +++ b/demos/Lazarus_any_OS/BrowserWindow/globalcefapplication.pas @@ -51,7 +51,7 @@ unit GlobalCefApplication; interface uses - uCEFApplication, uCEFWorkScheduler, FileUtil; + uCEFApplication, uCEFWorkScheduler, uCEFLazApplication, FileUtil; procedure CreateGlobalCEFApp; @@ -75,7 +75,8 @@ begin GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil); {$ENDIF} - GlobalCEFApp := TCefApplication.Create; + GlobalCEFApp := TCefLazApplication.Create; + GlobalCEFApp.CheckCEFFiles := False; {$IFDEF USE_MULTI_THREAD_LOOP} // On Windows/Linux CEF can use threads for the message-loop GlobalCEFApp.MultiThreadedMessageLoop := True; diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/00-Delete.bat b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/00-Delete.bat new file mode 100644 index 00000000..0b5ba5c8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/00-Delete.bat @@ -0,0 +1,2 @@ +rmdir /S /Q lib +rmdir /S /Q backup diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.ico b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.ico new file mode 100644 index 00000000..25c186a5 Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.ico differ diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpi b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpi new file mode 100644 index 00000000..d948d88f --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpi @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="B:\laz_other\CEF4Delphi\demos\Lazarus Mac\SubProcess"/> + <CompressFinally Value="False"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="CEF4Delphi_Lazarus"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="2"> + <Unit0> + <Filename Value="AppHelper.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="..\uHelperProcessDom.pas"/> + <IsPartOfProject Value="True"/> + </Unit1> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="..\..\..\..\bin\AppHelper"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value=".."/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + </CodeGeneration> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> +</CONFIG> diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpr b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpr new file mode 100644 index 00000000..d0d2e185 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.lpr @@ -0,0 +1,73 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +program AppHelper; + +(* + * The compiled exe should be copied into + * SimpleBrowser.app/Content/Frameworks/SimpleBrowser2 Helper.app/Content/MacOS/SimpleBrowser2 Helper + * including app bundle in SimpleBrowser2.app/Content/Frameworks/SimpleBrowser2 Helper.app + *) + +{$mode objfpc}{$H+} + +{$I cef.inc} + +uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + Interfaces, // this includes the LCL widgetset + uHelperProcessDom, + uCEFApplication, uCEFTypes, uCEFConstants, LazFileUtils, sysutils; + +begin + GlobalCEFApp := TCefApplication.Create; + InitProcessMessagesHandler; + + // The main process and the subprocess *MUST* have the same GlobalCEFApp + // properties and events, specially FrameworkDirPath, ResourcesDirPath, + // LocalesDirPath, cache and UserDataPath paths. + {$IFDEF MACOSX} + GlobalCEFApp.InitLibLocationFromArgs; + {$ENDIF} + + GlobalCEFApp.StartSubProcess; + GlobalCEFApp.Free; + GlobalCEFApp := nil; +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.res b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.res new file mode 100644 index 00000000..bcdc0667 Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/AppHelper.res differ diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/cef.inc b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/cef.inc @@ -0,0 +1,468 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + // 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} + +// Delphi uses MACOS for the new MacOSX and DARWIN is not defined +// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7) +// We define MACOSX to avoid conflicts in both situations +{$IFDEF FPC} + {$IFDEF DARWIN} + {$DEFINE MACOSX} + {$ENDIF} +{$ELSE} + {$IFDEF MACOS} + {$DEFINE MACOSX} + {$ENDIF} +{$ENDIF} diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/create_mac_helper_apps.sh b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/create_mac_helper_apps.sh new file mode 100755 index 00000000..eb60983c --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/AppHelper/create_mac_helper_apps.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +BASEDIR=$(dirname "$0") +DEST=$1 +SRC=$2 + +if [ "$SRC" = "" ]; +then + SRC=$BASEDIR/../../../../bin/AppHelper.app +fi + +if [ "$1" = "" ] || [ ! -e "$DEST" ] || [ ! -e "$SRC" ]; +then + echo "Usage" + echo " $0 destpath/project.app" + echo " $0 destpath/project.app sourcedir/AppHelper.app" + echo + if [ ! -e "$DEST" ]; + then + echo "Error: Target app bundle not found. (Did you compile AND create the bundle?)" + fi + if [ ! -e "$SRC" ]; + then + echo "Error: Source (AppHelper) app bundle not found. (Did you compile AND create the bundle?)" + fi + exit; +fi + +SRCAPP=$(basename "$SRC") +SRCAPP="${SRCAPP%\.app}" +DESTAPP=$(basename "$DEST") +DESTAPP="${DESTAPP%\.app}" + +SUB="" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (GPU)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (Renderer)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (Plugin)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.ico b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.ico new file mode 100644 index 00000000..0341321b Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.ico differ diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpi b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpi new file mode 100644 index 00000000..3ec9b24d --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpi @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="12"/> + <General> + <Flags> + <CompatibilityMode Value="True"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <Title Value="BrowserWindowDom"/> + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="B:/laz_other/CEF4Delphi/demos/Lazarus_any_OS/BrowserWindowDom"/> + <CompressFinally Value="False"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages Count="3"> + <Item1> + <PackageName Value="LazDebuggerGdbmi"/> + </Item1> + <Item2> + <PackageName Value="CEF4Delphi_Lazarus"/> + </Item2> + <Item3> + <PackageName Value="LCL"/> + </Item3> + </RequiredPackages> + <Units Count="5"> + <Unit0> + <Filename Value="BrowserWindowDom.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="uBrowserWindowDom.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit1> + <Unit2> + <Filename Value="initsubprocess.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="InitSubProcess"/> + </Unit2> + <Unit3> + <Filename Value="globalcefapplication.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="GlobalCefApplication"/> + </Unit3> + <Unit4> + <Filename Value="uHelperProcessDom.pas"/> + <IsPartOfProject Value="True"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="../../../bin/BrowserWindowDom"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + </Linking> + <Other> + <CustomOptions Value="-dUseCthreads"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpr b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpr new file mode 100644 index 00000000..3e8fa958 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.lpr @@ -0,0 +1,84 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + + (* + * Include the following files + * BrowserWindow.app/Contents/Frameworks/ExternalPumpBrowser Helper.app/ + * files from the demos/Lazarus_Mac/AppHelper project + * use create_mac_helper.sh + * + * BrowserWindow.app/Contents/Frameworks/Chromium Embedded Framework.framework + * files from Release folder in cef download + * + *) + + +program BrowserWindowDom; + +{$mode objfpc}{$H+} +{$I cef.inc} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + {$IFDEF LINUX} + InitSubProcess, // On Linux this unit must be used *before* the "interfaces" unit. + {$ENDIF} + Interfaces, + Forms, + uBrowserWindowDom, GlobalCefApplication, + uHelperProcessDom // Used here, for any OS where the main exe server as AppHelper too. + { you can add units after this } + ; + +{$R *.res} + +{$IFDEF WIN32} + // CEF needs to set the LARGEADDRESSAWARE ($20) flag which allows 32-bit processes to use up to 3GB of RAM. + {$SetPEFlags $20} +{$ENDIF} + +begin + RequireDerivedFormResource:=True; + Application.Scaled := True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.res b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.res new file mode 100644 index 00000000..bec39b4a Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowDom/BrowserWindowDom.res differ diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/README.txt b/demos/Lazarus_any_OS/BrowserWindowDom/README.txt new file mode 100644 index 00000000..a2ae5a16 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/README.txt @@ -0,0 +1,40 @@ +BrowserWindow + +# ABOUT + +This example uses + TLazarusBrowserWindow + Examining DOM + +TCEFWorkScheduler feeds the CEF messageloop by calling DoMessageLoopWork(). On Mac this is currently the only way to run the CEF messageloop. + + +# SETUP + +** Windows +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +** Linux +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +Note: +- For your own Linux project you must modify the project source (lpr) and add "InitSubProcess" to the "uses" clause, so that it is in the list *before* the unit "Interfaces". +- The call to "DestroyGlobalCEFApp" must be in a unit *not* used by "unit InitSubProcess" (including not used in any nested way). + + +** Mac +1) Go to "project options" and create the "App Bundle" +2) Download the CEF framework and place the content of the "Release" folder into BrowserWindowDom.app/Contents/Frameworks/Chromium Embedded Framework.framework +You should have: + Chromium Embedded Framework + Libraries/* + Resources/* +3) Open project "AppHelper" (from the subfolder in this project's folder), create App Bundle and compile the AppHelper. + Run create_mac_helper.sh +4) Open project BrowserWindowDom, compile and run + + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/cef.inc b/demos/Lazarus_any_OS/BrowserWindowDom/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/cef.inc @@ -0,0 +1,468 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + // 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} + +// Delphi uses MACOS for the new MacOSX and DARWIN is not defined +// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7) +// We define MACOSX to avoid conflicts in both situations +{$IFDEF FPC} + {$IFDEF DARWIN} + {$DEFINE MACOSX} + {$ENDIF} +{$ELSE} + {$IFDEF MACOS} + {$DEFINE MACOSX} + {$ENDIF} +{$ENDIF} diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/create_mac_helper.sh b/demos/Lazarus_any_OS/BrowserWindowDom/create_mac_helper.sh new file mode 100755 index 00000000..49927781 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/create_mac_helper.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +CDIR=$(pwd) +cd "$(dirname "$0")" + +./AppHelper/create_mac_helper_apps.sh ../../../bin/BrowserWindowDom.app + +if [ "$(grep -i TCrCocoaApplication ../../../bin/BrowserWindowDom.app/Contents/Info.plist)" = "" ]; +then +sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/BrowserWindowDom.app/Contents/Info.plist +fi + +cd "$CDIR" diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/globalcefapplication.pas b/demos/Lazarus_any_OS/BrowserWindowDom/globalcefapplication.pas new file mode 100644 index 00000000..6302bb21 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/globalcefapplication.pas @@ -0,0 +1,118 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit GlobalCefApplication; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +{.$DEFINE USE_MULTI_THREAD_LOOP} // Only Windows/Linux +{.$DEFINE USE_APP_HELPER} // Optional on Windows/Linux + +{$IFDEF MACOSX} + {$UNDEF USE_MULTI_THREAD_LOOP} // Will fail on Mac + {$DEFINE USE_APP_HELPER} // Required on Mac +{$ENDIF} + +interface + +uses + uCEFApplication, uCEFWorkScheduler, uCEFLazApplication, FileUtil, + uHelperProcessDom; + +procedure CreateGlobalCEFApp; + +implementation + +procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); +begin + if (GlobalCEFWorkScheduler <> nil) then GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); +end; + +procedure CreateGlobalCEFApp; +begin + if GlobalCEFApp <> nil then + exit; + + {$IFnDEF USE_MULTI_THREAD_LOOP} + // TCEFWorkScheduler will call cef_do_message_loop_work when + // it's told in the GlobalCEFApp.OnScheduleMessagePumpWork event. + // GlobalCEFWorkScheduler needs to be created before the + // GlobalCEFApp.StartMainProcess call. + GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil); + {$ENDIF} + + GlobalCEFApp := TCefLazApplication.Create; + GlobalCEFApp.CheckCEFFiles := False; + {$IFDEF USE_MULTI_THREAD_LOOP} + // On Windows/Linux CEF can use threads for the message-loop + GlobalCEFApp.MultiThreadedMessageLoop := True; + {$ELSE} + // use External Pump for message-loop + GlobalCEFApp.ExternalMessagePump := True; + GlobalCEFApp.MultiThreadedMessageLoop := False; + GlobalCEFApp.OnScheduleMessagePumpWork := @GlobalCEFApp_OnScheduleMessagePumpWork; + {$ENDIF} + + {$IFnDEF MACOSX} + {$IFDEF USE_APP_HELPER} + (* Use AppHelper as subprocess, instead of the main exe *) + GlobalCEFApp.BrowserSubprocessPath := 'AppHelper' + GetExeExt; + {$ENDIF} + {$ENDIF} + + {$IFDEF MACOSX} + (* Enable the below to prevent being asked for permission to access "Chromium Safe Storage" + If set to true, Cookies will not be encrypted. + *) + GlobalCEFApp.UseMockKeyChain := True; + {$ENDIF} + {$IFDEF LINUX} + // This is a workaround for the 'GPU is not usable error' issue : + // https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef + GlobalCEFApp.DisableZygote := True; // this property adds the "--no-zygote" command line switch + {$ENDIF} + { + GlobalCEFApp.LogFile := 'cef.log'; + GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE; + } + + InitProcessMessagesHandler; // This is for the AppHelper process. +end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/initsubprocess.pas b/demos/Lazarus_any_OS/BrowserWindowDom/initsubprocess.pas new file mode 100644 index 00000000..512c43e8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/initsubprocess.pas @@ -0,0 +1,61 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit InitSubProcess; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, uCEFApplication, uCEFWorkScheduler; + +implementation + +initialization + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.lfm b/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.lfm new file mode 100644 index 00000000..09e1ab2d --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.lfm @@ -0,0 +1,73 @@ +object Form1: TForm1 + Left = 473 + Height = 589 + Top = 227 + Width = 967 + Caption = 'Initializing browser. Please wait...' + ClientHeight = 589 + ClientWidth = 967 + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + Position = poScreenCenter + LCLVersion = '2.1.0.0' + object AddressPnl: TPanel + Left = 0 + Height = 23 + Top = 0 + Width = 967 + Align = alTop + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 967 + TabOrder = 0 + object GoBtn: TButton + Left = 932 + Height = 23 + Top = 0 + Width = 35 + Align = alRight + Caption = 'Go' + OnClick = GoBtnClick + TabOrder = 0 + end + object AddressEdt: TComboBox + Left = 0 + Height = 23 + Top = 0 + Width = 932 + Align = alClient + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'https://www.google.com' + 'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' + 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_win_close' + 'https://www.w3schools.com/html/html5_video.asp' + 'http://www.adobe.com/software/flash/about/' + 'http://isflashinstalled.com/' + 'chrome://version/' + 'http://html5test.com/' + 'https://www.w3schools.com/' + 'http://webglsamples.org/' + 'https://get.webgl.org/' + 'https://www.youtube.com' + 'https://html5demos.com/drag/' + 'https://developers.google.com/maps/documentation/javascript/examples/streetview-embed?hl=fr' + 'https://www.w3schools.com/Tags/tryit.asp?filename=tryhtml_iframe_name' + 'https://www.browserleaks.com/webrtc' + 'https://frames-per-second.appspot.com/' + ) + TabOrder = 1 + Text = 'https://www.google.com' + end + end + object LazarusBrowserWindow1: TLazarusBrowserWindow + Left = 0 + Height = 566 + Top = 23 + Width = 967 + Align = alClient + TabOrder = 1 + OnBrowserClosed = LazarusBrowserWindow1BrowserClosed + end +end diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.pas b/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.pas new file mode 100644 index 00000000..8dd1e314 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/uBrowserWindowDom.pas @@ -0,0 +1,258 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uBrowserWindowDom; + +{$mode objfpc}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, + uCEFLazarusCocoa, // required for Cocoa + SysUtils, Messages, Forms, Controls, + Dialogs, ExtCtrls, StdCtrls, LMessages, Menus, + uCEFTypes, uCEFInterfaces, uHelperProcessDom, + uCEFWorkScheduler, uCEFLazarusBrowserWindow, uCEFProcessMessage, Classes; + +type + + { TForm1 } + + TForm1 = class(TForm) + AddressEdt: TComboBox; + GoBtn: TButton; + AddressPnl: TPanel; + LazarusBrowserWindow1: TLazarusBrowserWindow; + mDomHere: TMenuItem; + + 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 Chromium1OpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure FormCreate(Sender: TObject); + + procedure GoBtnClick(Sender: TObject); + procedure LazarusBrowserWindow1BrowserClosed(Sender: TObject); + private + FContextXY: TPoint; + + procedure DoBeforeContextMenu(Sender: TObject; const browser: ICefBrowser; + const frame: ICefFrame; const params: ICefContextMenuParams; + const model: ICefMenuModel); + procedure DoCaptureMenuXY; + procedure DoContextMenuCmd(Sender: TObject; const browser: ICefBrowser; + const frame: ICefFrame; const params: ICefContextMenuParams; + commandId: Integer; eventFlags: TCefEventFlags; out Result: Boolean); + procedure DoProcessMessageReceived(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; + sourceProcess: TCefProcessId; const message: ICefProcessMessage; out + Result: Boolean); + protected + {$IFDEF WINDOWS} + procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP; + procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP; + {$ENDIF} + + public + + end; + +var + Form1: TForm1; + + +implementation + +{$R *.lfm} + +// This is a demo with the simplest web browser you can build using CEF4Delphi and +// it doesn't show any sign of progress like other web browsers do. + +// Remember that it may take a few seconds to load if Windows update, your antivirus or +// any other windows service is using your hard drive. + +// Depending on your internet connection it may take longer than expected. + +// Please check that your firewall or antivirus are not blocking this application +// or the domain "google.com". If you don't live in the US, you'll be redirected to +// another domain which will take a little time too. + +// This demo uses a TChromium and a TCEFLinkedWindowParent + +// We need to use TCEFLinkedWindowParent in Linux to update the browser +// visibility and size automatically. + +// Destruction steps +// ================= +// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. +// 2. TChromium.OnClose sets aAction to cbaClose to destroy the browser, which triggers the TChromium.OnBeforeClose event. +// 3. TChromium.OnBeforeClose sets FCanClose := True and sends CEF_BEFORECLOSE to close the form. + +uses + uCEFApplication; + +{ TForm1 } + +procedure TForm1.GoBtnClick(Sender: TObject); +begin + LazarusBrowserWindow1.LoadURL(UTF8Decode(AddressEdt.Text)); +end; + +procedure TForm1.LazarusBrowserWindow1BrowserClosed(Sender: TObject); +begin + Close; +end; + +procedure TForm1.DoBeforeContextMenu(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; + const params: ICefContextMenuParams; const model: ICefMenuModel); +begin + model.Clear; + model.AddItem(1, 'Get DOM'); + TThread.Synchronize(nil, @DoCaptureMenuXY); +end; + +procedure TForm1.DoCaptureMenuXY; +begin + FContextXY := LazarusBrowserWindow1.ScreenToClient(Mouse.CursorPos); +end; + +procedure TForm1.DoContextMenuCmd(Sender: TObject; const browser: ICefBrowser; + const frame: ICefFrame; const params: ICefContextMenuParams; + commandId: Integer; eventFlags: TCefEventFlags; out Result: Boolean); +var + TempMsg : ICefProcessMessage; +begin + if commandId = 1 then + begin + TempMsg := TCefProcessMessageRef.New(MSG_REQUEST_DOM); // Same name than TCefCustomRenderProcessHandler.MessageName + TempMsg.ArgumentList.SetInt(0, FContextXY.X); + TempMsg.ArgumentList.SetInt(1, FContextXY.Y); + LazarusBrowserWindow1.Chromium.SendProcessMessage(PID_RENDERER, TempMsg); + end; +end; + +procedure TForm1.DoProcessMessageReceived(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; + sourceProcess: TCefProcessId; const message: ICefProcessMessage; out + Result: Boolean); +begin + Result := False; + case message.Name of + MSG_RESPONSE_DOM: begin + Caption := message.ArgumentList.GetString(0); + Result := True; + end; + end; +end; + +{$IFDEF WINDOWS} +procedure TForm1.WMEnterMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True; +end; + +procedure TForm1.WMExitMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False; +end; +{$ENDIF} + +procedure TForm1.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 + // 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 TForm1.Chromium1OpenUrlFromTab(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; + targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out + 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 TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + LazarusBrowserWindow1.CloseBrowser(True); + + CanClose := LazarusBrowserWindow1.IsClosed; +end; + +procedure TForm1.FormCreate(Sender: TObject); +begin + LazarusBrowserWindow1.Chromium.OnBeforeContextMenu := @DoBeforeContextMenu; + LazarusBrowserWindow1.Chromium.OnContextMenuCommand := @DoContextMenuCmd; + LazarusBrowserWindow1.Chromium.OnProcessMessageReceived := @DoProcessMessageReceived; + + LazarusBrowserWindow1.LoadURL(UTF8Decode(AddressEdt.Text)); +end; + +initialization + {$IFDEF DARWIN} // $IFDEF MACOSX + AddCrDelegate; + {$ENDIF} + if GlobalCEFApp = nil then begin + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + end; + +finalization + (* Destroy from this unit, which is used after "Interfaces". So this happens before the Application object is destroyed *) + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowDom/uHelperProcessDom.pas b/demos/Lazarus_any_OS/BrowserWindowDom/uHelperProcessDom.pas new file mode 100644 index 00000000..0583260c --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowDom/uHelperProcessDom.pas @@ -0,0 +1,161 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uHelperProcessDom; + +(* The code in this unit is executed in the renderer sub-process +*) + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, SysUtils, uCEFApplication, uCEFInterfaces, uCEFDomVisitor, uCEFTypes, + uCEFProcessMessage; + +const + MSG_REQUEST_DOM = 'MSG_REQUEST_DOM'; + MSG_RESPONSE_DOM = 'MSG_RESPONSE_DOM'; + +procedure InitProcessMessagesHandler; + +implementation + +type + + { TDomVisitorFindXY } + + TDomVisitorFindXY = class(TCefDomVisitorOwn) + protected + FFrame : ICefFrame; + FX, FY: Integer; + procedure visit(const document: ICefDomDocument); override; + public + constructor Create(AFrame: ICefFrame; X,Y: Integer); reintroduce; virtual; + end; + + +{ TDomVisitorFindXY } + +procedure TDomVisitorFindXY.visit(const document: ICefDomDocument); +var + node, foundNode: ICefDomNode; + nb: TCefRect; + TempMsg : ICefProcessMessage; +begin + node := document.GetBody; + foundNode := nil; + if node <> nil then + begin + nb := node.GetElementBounds; + if (FX >= nb.x) and (FX < nb.x + nb.width) and + (FY >= nb.y) and (FY < nb.y + nb.height) + then + begin + while node <> nil do + begin + foundNode := node; + if node.HasChildren then + begin + node := node.FirstChild; + while node <> nil do + begin + nb := node.GetElementBounds; + if (FX >= nb.x) and (FX < nb.x + nb.width) and + (FY >= nb.y) and (FY < nb.y + nb.height) + then + break // go outer loop + else + node := node.NextSibling; + end; + end + else + node := nil; + end; + end; + end; + + TempMsg := TCefProcessMessageRef.New(MSG_RESPONSE_DOM); // Same name than TCefCustomRenderProcessHandler.MessageName + if foundNode <> nil then + TempMsg.ArgumentList.SetString(0, foundNode.AsMarkup) + else + TempMsg.ArgumentList.SetString(0, 'Not Found'); + if (FFrame <> nil) and FFrame.IsValid then + FFrame.SendProcessMessage(PID_BROWSER, TempMsg); +end; + +constructor TDomVisitorFindXY.Create(AFrame: ICefFrame; X, Y: Integer); +begin + FFrame := AFrame; + FX := X; + FY := Y; + inherited Create; +end; + + +procedure DoProcessMessageReceived(const browser: ICefBrowser; + const frame: ICefFrame; sourceProcess: TCefProcessId; + const message: ICefProcessMessage; var aHandled: boolean); +var + TempVisitor : TDomVisitorFindXY; +begin + aHandled := False; + case message.Name of + MSG_REQUEST_DOM: begin + if (frame <> nil) and frame.IsValid then + begin + TempVisitor := TDomVisitorFindXY.Create( + frame, + message.ArgumentList.GetInt(0), + message.ArgumentList.GetInt(1) + ); + frame.VisitDom(TempVisitor); + end; + aHandled := True; + + end; + end; +end; + +procedure InitProcessMessagesHandler; +begin + GlobalCEFApp.OnProcessMessageReceived := @DoProcessMessageReceived; +end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.ico b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.ico new file mode 100644 index 00000000..0341321b Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.ico differ diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpi b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpi new file mode 100644 index 00000000..cbecfe3f --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpi @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="12"/> + <General> + <Flags> + <CompatibilityMode Value="True"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <Title Value="BrowserWindowEx"/> + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="B:/laz_other/CEF4Delphi/demos/Lazarus_any_OS/BrowserWindowEx"/> + <CompressFinally Value="False"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="CEF4Delphi_Lazarus"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="4"> + <Unit0> + <Filename Value="BrowserWindowEx.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="uBrowserWindowEx.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit1> + <Unit2> + <Filename Value="initsubprocess.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="InitSubProcess"/> + </Unit2> + <Unit3> + <Filename Value="globalcefapplication.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="GlobalCefApplication"/> + </Unit3> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="../../../bin/BrowserWindowEx"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CustomOptions Value="-dUseCthreads"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpr b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpr new file mode 100644 index 00000000..5d93ede8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.lpr @@ -0,0 +1,83 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + + (* + * Include the following files + * BrowserWindowEx.app/Contents/Frameworks/ExternalPumpBrowser Helper.app/ + * files from the demos/Lazarus_Mac/AppHelper project + * use create_mac_helper.sh + * + * BrowserWindowEx.app/Contents/Frameworks/Chromium Embedded Framework.framework + * files from Release folder in cef download + * + *) + + +program BrowserWindowEx; + +{$mode objfpc}{$H+} +{$I cef.inc} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + {$IFDEF LINUX} + InitSubProcess, // On Linux this unit must be used *before* the "interfaces" unit. + {$ENDIF} + Interfaces, + Forms, + uBrowserWindowEx, GlobalCefApplication + { you can add units after this } + ; + +{$R *.res} + +{$IFDEF WIN32} + // CEF needs to set the LARGEADDRESSAWARE ($20) flag which allows 32-bit processes to use up to 3GB of RAM. + {$SetPEFlags $20} +{$ENDIF} + +begin + RequireDerivedFormResource:=True; + Application.Scaled := True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.res b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.res new file mode 100644 index 00000000..bec39b4a Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowEx/BrowserWindowEx.res differ diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/README.txt b/demos/Lazarus_any_OS/BrowserWindowEx/README.txt new file mode 100644 index 00000000..86f182ca --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/README.txt @@ -0,0 +1,40 @@ +BrowserWindow + +# ABOUT + +This example uses + TLazarusBrowserWindow + TCEFWorkScheduler + +TCEFWorkScheduler feeds the CEF messageloop by calling DoMessageLoopWork(). On Mac this is currently the only way to run the CEF messageloop. + + +# SETUP + +** Windows +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +** Linux +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +Note: +- For your own Linux project you must modify the project source (lpr) and add "InitSubProcess" to the "uses" clause, so that it is in the list *before* the unit "Interfaces". +- The call to "DestroyGlobalCEFApp" must be in a unit *not* used by "unit InitSubProcess" (including not used in any nested way). + + +** Mac +1) Go to "project options" and create the "App Bundle" +2) Download the CEF framework and place the content of the "Release" folder into BrowserWindowEx.app/Contents/Frameworks/Chromium Embedded Framework.framework +You should have: + Chromium Embedded Framework + Libraries/* + Resources/* +3) Open project "AppHelper", create App Bundle and compile the AppHelper. + Run create_mac_helper.sh +4) Open project BrowserWindowEx, compile and run + + diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/cef.inc b/demos/Lazarus_any_OS/BrowserWindowEx/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/cef.inc @@ -0,0 +1,468 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + // 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} + +// Delphi uses MACOS for the new MacOSX and DARWIN is not defined +// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7) +// We define MACOSX to avoid conflicts in both situations +{$IFDEF FPC} + {$IFDEF DARWIN} + {$DEFINE MACOSX} + {$ENDIF} +{$ELSE} + {$IFDEF MACOS} + {$DEFINE MACOSX} + {$ENDIF} +{$ENDIF} diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/create_mac_helper.sh b/demos/Lazarus_any_OS/BrowserWindowEx/create_mac_helper.sh new file mode 100644 index 00000000..290132e0 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/create_mac_helper.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +CDIR=$(pwd) +cd "$(dirname "$0")" + +../AppHelper/create_mac_helper_apps.sh ../../../bin/BrowserWindowEx.app + +if [ "$(grep -i TCrCocoaApplication ../../../bin/BrowserWindowEx.app/Contents/Info.plist)" = "" ]; +then +sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/BrowserWindowEx.app/Contents/Info.plist +fi + +cd "$CDIR" diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/globalcefapplication.pas b/demos/Lazarus_any_OS/BrowserWindowEx/globalcefapplication.pas new file mode 100644 index 00000000..239db909 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/globalcefapplication.pas @@ -0,0 +1,116 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit GlobalCefApplication; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +{.$DEFINE USE_MULTI_THREAD_LOOP} // Only Windows/Linux +{.$DEFINE USE_APP_HELPER} // Optional on Windows/Linux + +{$IFDEF MACOSX} + {$UNDEF USE_MULTI_THREAD_LOOP} // Will fail on Mac + {$DEFINE USE_APP_HELPER} // Required on Mac +{$ENDIF} + +interface + +uses + uCEFApplication, uCEFWorkScheduler, FileUtil; + +procedure CreateGlobalCEFApp; + +implementation + +procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); +begin + if (GlobalCEFWorkScheduler <> nil) then GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); +end; + +procedure CreateGlobalCEFApp; +begin + if GlobalCEFApp <> nil then + exit; + + {$IFnDEF USE_MULTI_THREAD_LOOP} + // TCEFWorkScheduler will call cef_do_message_loop_work when + // it's told in the GlobalCEFApp.OnScheduleMessagePumpWork event. + // GlobalCEFWorkScheduler needs to be created before the + // GlobalCEFApp.StartMainProcess call. + GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil); + {$ENDIF} + + GlobalCEFApp := TCefApplication.Create; + {$IFDEF USE_MULTI_THREAD_LOOP} + // On Windows/Linux CEF can use threads for the message-loop + GlobalCEFApp.MultiThreadedMessageLoop := True; + {$ELSE} + // use External Pump for message-loop + GlobalCEFApp.ExternalMessagePump := True; + GlobalCEFApp.MultiThreadedMessageLoop := False; + GlobalCEFApp.OnScheduleMessagePumpWork := @GlobalCEFApp_OnScheduleMessagePumpWork; + {$ENDIF} + + GlobalCEFApp.CheckCEFFiles := false; + + {$IFnDEF MACOSX} + {$IFDEF USE_APP_HELPER} + (* Use AppHelper as subprocess, instead of the main exe *) + GlobalCEFApp.BrowserSubprocessPath := 'AppHelper' + GetExeExt; + {$ENDIF} + {$ENDIF} + + {$IFDEF MACOSX} + (* Enable the below to prevent being asked for permission to access "Chromium Safe Storage" + If set to true, Cookies will not be encrypted. + *) + GlobalCEFApp.UseMockKeyChain := True; + {$ENDIF} + {$IFDEF LINUX} + // This is a workaround for the 'GPU is not usable error' issue : + // https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef + GlobalCEFApp.DisableZygote := True; // this property adds the "--no-zygote" command line switch + {$ENDIF} + { + GlobalCEFApp.LogFile := 'cef.log'; + GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE; + } +end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/initsubprocess.pas b/demos/Lazarus_any_OS/BrowserWindowEx/initsubprocess.pas new file mode 100644 index 00000000..512c43e8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/initsubprocess.pas @@ -0,0 +1,61 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit InitSubProcess; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, uCEFApplication, uCEFWorkScheduler; + +implementation + +initialization + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.lfm b/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.lfm new file mode 100644 index 00000000..4ce25b65 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.lfm @@ -0,0 +1,245 @@ +object Form1: TForm1 + Left = 473 + Height = 589 + Top = 227 + Width = 967 + Caption = 'Initializing browser. Please wait...' + ClientHeight = 589 + ClientWidth = 967 + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + Position = poScreenCenter + LCLVersion = '2.1.0.0' + object PanelLeft: TPanel + Left = 0 + Height = 557 + Top = 32 + Width = 484 + Align = alLeft + ClientHeight = 557 + ClientWidth = 484 + TabOrder = 0 + object AddressPnlLeft: TPanel + Left = 1 + Height = 23 + Top = 1 + Width = 482 + Align = alTop + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 482 + Enabled = False + TabOrder = 0 + object GoBtnLeft: TButton + Left = 424 + Height = 23 + Top = 0 + Width = 35 + Align = alRight + Caption = 'Go' + OnClick = GoBtnLeftClick + TabOrder = 0 + end + object AddressEdtLeft: TComboBox + Left = 0 + Height = 23 + Top = 0 + Width = 424 + Align = alClient + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'https://www.google.com' + 'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' + 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_win_close' + 'https://www.w3schools.com/html/html5_video.asp' + 'http://www.adobe.com/software/flash/about/' + 'http://isflashinstalled.com/' + 'chrome://version/' + 'http://html5test.com/' + 'https://www.w3schools.com/' + 'http://webglsamples.org/' + 'https://get.webgl.org/' + 'https://www.youtube.com' + 'https://html5demos.com/drag/' + 'https://developers.google.com/maps/documentation/javascript/examples/streetview-embed?hl=fr' + 'https://www.w3schools.com/Tags/tryit.asp?filename=tryhtml_iframe_name' + 'https://www.browserleaks.com/webrtc' + 'https://frames-per-second.appspot.com/' + ) + TabOrder = 1 + Text = 'https://www.google.com' + end + object CloseBtnLeft: TSpeedButton + Left = 459 + Height = 23 + Top = 0 + Width = 23 + Align = alRight + Images = ImageList1 + ImageIndex = 0 + OnClick = CloseBtnLeftClick + end + end + object OpenBtnLeft: TSpeedButton + AnchorSideLeft.Control = PanelLeft + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = PanelLeft + AnchorSideTop.Side = asrCenter + Left = 182 + Height = 70 + Top = 243 + Width = 120 + Caption = 'Open Browser' + OnClick = OpenBtnLeftClick + end + end + object Splitter1: TSplitter + Left = 484 + Height = 557 + Top = 32 + Width = 5 + end + object PanelRight: TPanel + Left = 489 + Height = 557 + Top = 32 + Width = 478 + Align = alClient + ClientHeight = 557 + ClientWidth = 478 + TabOrder = 2 + object AddressPnlRight: TPanel + Left = 1 + Height = 23 + Top = 1 + Width = 476 + Align = alTop + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 476 + Enabled = False + TabOrder = 0 + object GoBtnRight: TButton + Left = 418 + Height = 23 + Top = 0 + Width = 35 + Align = alRight + Caption = 'Go' + OnClick = GoBtnRightClick + TabOrder = 0 + end + object AddressEdtRight: TComboBox + Left = 0 + Height = 23 + Top = 0 + Width = 418 + Align = alClient + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'https://www.google.com' + 'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' + 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_win_close' + 'https://www.w3schools.com/html/html5_video.asp' + 'http://www.adobe.com/software/flash/about/' + 'http://isflashinstalled.com/' + 'chrome://version/' + 'http://html5test.com/' + 'https://www.w3schools.com/' + 'http://webglsamples.org/' + 'https://get.webgl.org/' + 'https://www.youtube.com' + 'https://html5demos.com/drag/' + 'https://developers.google.com/maps/documentation/javascript/examples/streetview-embed?hl=fr' + 'https://www.w3schools.com/Tags/tryit.asp?filename=tryhtml_iframe_name' + 'https://www.browserleaks.com/webrtc' + 'https://frames-per-second.appspot.com/' + ) + TabOrder = 1 + Text = 'https://www.google.com' + end + object CloseBtnRight: TSpeedButton + Left = 453 + Height = 23 + Top = 0 + Width = 23 + Align = alRight + Images = ImageList1 + ImageIndex = 0 + OnClick = CloseBtnRightClick + end + end + object OpenBtnRight: TSpeedButton + AnchorSideLeft.Control = PanelRight + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = PanelRight + AnchorSideTop.Side = asrCenter + Left = 179 + Height = 70 + Top = 243 + Width = 120 + Caption = 'Open Browser' + OnClick = OpenBtnRightClick + end + end + object Panel1: TPanel + Left = 0 + Height = 32 + Top = 0 + Width = 967 + Align = alTop + AutoSize = True + ChildSizing.LeftRightSpacing = 5 + ChildSizing.TopBottomSpacing = 3 + ChildSizing.HorizontalSpacing = 10 + ChildSizing.VerticalSpacing = 3 + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 5 + ClientHeight = 32 + ClientWidth = 967 + TabOrder = 3 + object BtnCloseApp: TButton + Left = 5 + Height = 25 + Top = 3 + Width = 80 + Caption = 'Close App' + OnClick = BtnCloseAppClick + TabOrder = 0 + end + object BtnCloseForm: TButton + Left = 95 + Height = 25 + Top = 3 + Width = 86 + Caption = 'Close Form' + OnClick = BtnCloseFormClick + TabOrder = 1 + end + object BtnModal: TButton + Left = 191 + Height = 25 + Top = 3 + Width = 92 + Caption = 'Show Modal' + OnClick = BtnModalClick + TabOrder = 2 + end + end + object ImageList1: TImageList + left = 672 + top = 104 + Bitmap = { + 4C7A010000001000000010000000D70000000000000078DAE591CB0A82501445 + FD19C5C7F58DA2A0F8C2FFF2178BA0226C12A6A1627DC1E9EE410D1CA8E3BA70 + 270716FBEC7504E1775E92BCCA3C6FC8B2A66C3ECFB22B99665B2CF160E3F841 + 41D092A24C296661F82CD2B4E1B30B79DE9E9678E482759C9E5C77204D9BAA28 + 6AC9F7917D20513C966B1D900BD63447DE6320DB6E48D7CF244975B1D503726D + 7B20C67ABEC39D7719ABAD2CFA6267E48255D58EFFDBD7C79A7FB8425FEC8C5C + B09AD69061D424CB5DB6C4E346F00C579FBEC805CBD889CF778BFE715FDC68EE + 19B960B7F8FFB7F70660608313 + } + end +end diff --git a/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.pas b/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.pas new file mode 100644 index 00000000..c6007c1a --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowEx/uBrowserWindowEx.pas @@ -0,0 +1,395 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uBrowserWindowEx; + +{$mode objfpc}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, + uCEFLazarusCocoa, // required for Cocoa + SysUtils, Messages, Forms, Controls, + Dialogs, ExtCtrls, StdCtrls, LMessages, Buttons, + uCEFTypes, uCEFInterfaces, + uCEFWorkScheduler, uCEFLazarusBrowserWindow, Classes; + +type + + { TForm1 } + + TForm1 = class(TForm) + AddressEdtLeft: TComboBox; + AddressEdtRight: TComboBox; + AddressPnlRight: TPanel; + BtnCloseApp: TButton; + BtnCloseForm: TButton; + BtnModal: TButton; + GoBtnLeft: TButton; + AddressPnlLeft: TPanel; + GoBtnRight: TButton; + ImageList1: TImageList; + Panel1: TPanel; + PanelRight: TPanel; + PanelLeft: TPanel; + CloseBtnLeft: TSpeedButton; + CloseBtnRight: TSpeedButton; + OpenBtnLeft: TSpeedButton; + OpenBtnRight: TSpeedButton; + Splitter1: TSplitter; + + procedure BtnCloseAppClick(Sender: TObject); + procedure BtnCloseFormClick(Sender: TObject); + procedure BtnModalClick(Sender: TObject); + 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 Chromium1OpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure FormCreate(Sender: TObject); + + procedure OpenBtnLeftClick(Sender: TObject); + procedure LeftBrowserCreated(Sender: TObject); + procedure GoBtnLeftClick(Sender: TObject); + procedure CloseBtnLeftClick(Sender: TObject); + procedure LeftBrowserClosed(Sender: TObject); + + procedure OpenBtnRightClick(Sender: TObject); + procedure RightBrowserCreated(Sender: TObject); + procedure GoBtnRightClick(Sender: TObject); + procedure CloseBtnRightClick(Sender: TObject); + procedure RightBrowserClosed(Sender: TObject); + + procedure DoShowModal(Data: PtrInt); + procedure MaybeTerminateApp(Sender: TObject); + procedure MaybeCloseApp(Sender: TObject); + protected + FBrowserLeft, FBrowserRight: TLazarusBrowserWindow; + FClosingBrowsers: TList; + + {$IFDEF WINDOWS} + procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP; + procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP; + {$ENDIF} + + public + constructor Create(TheOwner: TComponent); override; + destructor Destroy; override; + + end; + +var + Form1: TForm1; + + +implementation + +{$R *.lfm} + +// This is a demo with the simplest web browser you can build using CEF4Delphi and +// it doesn't show any sign of progress like other web browsers do. + +// Remember that it may take a few seconds to load if Windows update, your antivirus or +// any other windows service is using your hard drive. + +// Depending on your internet connection it may take longer than expected. + +// Please check that your firewall or antivirus are not blocking this application +// or the domain "google.com". If you don't live in the US, you'll be redirected to +// another domain which will take a little time too. + +// This demo uses a TChromium and a TCEFLinkedWindowParent + +// We need to use TCEFLinkedWindowParent in Linux to update the browser +// visibility and size automatically. + +// Destruction steps +// ================= +// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. +// 2. TChromium.OnClose sets aAction to cbaClose to destroy the browser, which triggers the TChromium.OnBeforeClose event. +// 3. TChromium.OnBeforeClose sets FCanClose := True and sends CEF_BEFORECLOSE to close the form. + +uses + uCEFApplication; + +{ TForm1 } + +procedure TForm1.OpenBtnLeftClick(Sender: TObject); +begin + FBrowserLeft := TLazarusBrowserWindow.Create(Self); + FBrowserLeft.Chromium.OnBeforePopup := @Chromium1BeforePopup; + FBrowserLeft.Chromium.OnOpenUrlFromTab := @Chromium1OpenUrlFromTab; + FBrowserLeft.OnBrowserCreated := @LeftBrowserCreated; + FBrowserLeft.OnBrowserClosed := @LeftBrowserClosed; + FBrowserLeft.Align := alClient; + FBrowserLeft.Parent := PanelLeft; + + OpenBtnLeft.Enabled := False; + GoBtnLeftClick(nil); +end; + +procedure TForm1.LeftBrowserCreated(Sender: TObject); +begin + AddressPnlLeft.Enabled := True; +end; + +procedure TForm1.GoBtnLeftClick(Sender: TObject); +begin + FBrowserLeft.LoadURL(UTF8Decode(AddressEdtLeft.Text)); +end; + +procedure TForm1.CloseBtnLeftClick(Sender: TObject); +begin + AddressPnlLeft.Enabled := False; + FClosingBrowsers.Add(FBrowserLeft); + FBrowserLeft.CloseBrowser(True); + FBrowserLeft := nil; + //FreeAndNil(FBrowserLeft); + OpenBtnLeft.Enabled := True; +end; + +procedure TForm1.LeftBrowserClosed(Sender: TObject); +begin + FClosingBrowsers.Remove(Sender); + Sender.Free; +end; + + +procedure TForm1.OpenBtnRightClick(Sender: TObject); +begin + FBrowserRight := TLazarusBrowserWindow.Create(Self); + FBrowserRight.Chromium.OnBeforePopup := @Chromium1BeforePopup; + FBrowserRight.Chromium.OnOpenUrlFromTab := @Chromium1OpenUrlFromTab; + FBrowserRight.OnBrowserCreated := @RightBrowserCreated; + {$IFDEF MACOSX} + FBrowserRight.OnBrowserClosed := @RightBrowserClosed; + {$ENDIF} + FBrowserRight.Align := alClient; + FBrowserRight.Parent := PanelRight; + + OpenBtnRight.Enabled := False; + GoBtnRightClick(nil); +end; + +procedure TForm1.RightBrowserCreated(Sender: TObject); +begin + AddressPnlRight.Enabled := True; +end; + +procedure TForm1.GoBtnRightClick(Sender: TObject); +begin + FBrowserRight.LoadURL(UTF8Decode(AddressEdtRight.Text)); +end; + +procedure TForm1.CloseBtnRightClick(Sender: TObject); +begin + AddressPnlRight.Enabled := False; + {$IFDEF MACOSX} + FClosingBrowsers.Add(FBrowserRight); + FBrowserRight.CloseBrowser(True); + FBrowserRight := nil; + {$ELSE} + FreeAndNil(FBrowserRight); + {$ENDIF} + OpenBtnRight.Enabled := True; +end; + +procedure TForm1.RightBrowserClosed(Sender: TObject); +begin + FClosingBrowsers.Remove(Sender); + Sender.Free; +end; + +{$IFDEF WINDOWS} +procedure TForm1.WMEnterMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True; +end; + +procedure TForm1.WMExitMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False; +end; +{$ENDIF} + +constructor TForm1.Create(TheOwner: TComponent); +begin + FClosingBrowsers := TList.Create; + inherited Create(TheOwner); +end; + +destructor TForm1.Destroy; +begin + inherited Destroy; + FreeAndNil(FClosingBrowsers); +end; + +procedure TForm1.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 + // 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 TForm1.MaybeTerminateApp(Sender: TObject); +begin + Sender.Free; + FClosingBrowsers.Remove(Sender); + if FClosingBrowsers.Count = 0 then + Application.Terminate; +end; + +procedure TForm1.BtnCloseAppClick(Sender: TObject); +begin + // Does not call CloseQuery + Hide; + {$IFDEF MACOSX} + (* This demo takes no precaution against the App being closed by outher means + while waiting for all browsers to close + *) + if FBrowserLeft <> nil then begin + FBrowserLeft.OnBrowserClosed := @MaybeTerminateApp; + CloseBtnLeftClick(nil); + end; + if FBrowserRight <> nil then begin + FBrowserRight.OnBrowserClosed := @MaybeTerminateApp; + CloseBtnRightClick(nil); + end; + if FClosingBrowsers.Count = 0 then + Application.Terminate; + {$ELSE} + if FBrowserLeft <> nil then + FBrowserLeft.WaitForBrowserClosed; + if FBrowserRight <> nil then + FBrowserRight.WaitForBrowserClosed; + Application.Terminate; + {$ENDIF} +end; + +procedure TForm1.BtnCloseFormClick(Sender: TObject); +begin + Close; +end; + +procedure TForm1.BtnModalClick(Sender: TObject); +begin + {$IFDEF MACOSX} + Application.QueueAsyncCall(@DoShowModal, 0); + {$ELSE} + DoShowModal(0); + {$ENDIF} +end; + +procedure TForm1.DoShowModal(Data: PtrInt); +var + m: TForm1; +begin + m := TForm1.Create(Application); + m.BtnModal.Enabled := False; + m.Caption := 'MOD'; + m.BtnCloseApp.Visible := False; + m.ShowModal; + m.Free; +end; + +procedure TForm1.Chromium1OpenUrlFromTab(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; + targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out + 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 TForm1.MaybeCloseApp(Sender: TObject); +begin + Sender.Free; + FClosingBrowsers.Remove(Sender); + if FClosingBrowsers.Count = 0 then + Close; +end; + +procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + Hide; + if FBrowserLeft <> nil then begin + FBrowserLeft.OnBrowserClosed := @MaybeCloseApp; + CloseBtnLeftClick(nil); + end; + if FBrowserRight <> nil then begin + FBrowserRight.OnBrowserClosed := @MaybeCloseApp; + CloseBtnRightClick(nil); + end; + CanClose := FClosingBrowsers.Count = 0; +end; + +procedure TForm1.FormCreate(Sender: TObject); +begin + OpenBtnLeftClick(nil); +end; + +initialization + {$IFDEF DARWIN} // $IFDEF MACOSX + AddCrDelegate; + {$ENDIF} + if GlobalCEFApp = nil then begin + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + end; + +finalization + (* Destroy from this unit, which is used after "Interfaces". So this happens before the Application object is destroyed *) + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/00-Delete.bat b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/00-Delete.bat new file mode 100644 index 00000000..0b5ba5c8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/00-Delete.bat @@ -0,0 +1,2 @@ +rmdir /S /Q lib +rmdir /S /Q backup diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.ico b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.ico new file mode 100644 index 00000000..25c186a5 Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.ico differ diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpi b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpi new file mode 100644 index 00000000..d948d88f --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpi @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="12"/> + <PathDelim Value="\"/> + <General> + <Flags> + <MainUnitHasCreateFormStatements Value="False"/> + <MainUnitHasTitleStatement Value="False"/> + <MainUnitHasScaledStatement Value="False"/> + <CompatibilityMode Value="True"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <Title Value="AppHelper"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="B:\laz_other\CEF4Delphi\demos\Lazarus Mac\SubProcess"/> + <CompressFinally Value="False"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="CEF4Delphi_Lazarus"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="2"> + <Unit0> + <Filename Value="AppHelper.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="..\uHelperProcessDom.pas"/> + <IsPartOfProject Value="True"/> + </Unit1> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="..\..\..\..\bin\AppHelper"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value=".."/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + </CodeGeneration> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> +</CONFIG> diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpr b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpr new file mode 100644 index 00000000..d0d2e185 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.lpr @@ -0,0 +1,73 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +program AppHelper; + +(* + * The compiled exe should be copied into + * SimpleBrowser.app/Content/Frameworks/SimpleBrowser2 Helper.app/Content/MacOS/SimpleBrowser2 Helper + * including app bundle in SimpleBrowser2.app/Content/Frameworks/SimpleBrowser2 Helper.app + *) + +{$mode objfpc}{$H+} + +{$I cef.inc} + +uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + Interfaces, // this includes the LCL widgetset + uHelperProcessDom, + uCEFApplication, uCEFTypes, uCEFConstants, LazFileUtils, sysutils; + +begin + GlobalCEFApp := TCefApplication.Create; + InitProcessMessagesHandler; + + // The main process and the subprocess *MUST* have the same GlobalCEFApp + // properties and events, specially FrameworkDirPath, ResourcesDirPath, + // LocalesDirPath, cache and UserDataPath paths. + {$IFDEF MACOSX} + GlobalCEFApp.InitLibLocationFromArgs; + {$ENDIF} + + GlobalCEFApp.StartSubProcess; + GlobalCEFApp.Free; + GlobalCEFApp := nil; +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.res b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.res new file mode 100644 index 00000000..bcdc0667 Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/AppHelper.res differ diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/cef.inc b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/cef.inc @@ -0,0 +1,468 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + // 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} + +// Delphi uses MACOS for the new MacOSX and DARWIN is not defined +// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7) +// We define MACOSX to avoid conflicts in both situations +{$IFDEF FPC} + {$IFDEF DARWIN} + {$DEFINE MACOSX} + {$ENDIF} +{$ELSE} + {$IFDEF MACOS} + {$DEFINE MACOSX} + {$ENDIF} +{$ENDIF} diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/create_mac_helper_apps.sh b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/create_mac_helper_apps.sh new file mode 100755 index 00000000..eb60983c --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/AppHelper/create_mac_helper_apps.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +BASEDIR=$(dirname "$0") +DEST=$1 +SRC=$2 + +if [ "$SRC" = "" ]; +then + SRC=$BASEDIR/../../../../bin/AppHelper.app +fi + +if [ "$1" = "" ] || [ ! -e "$DEST" ] || [ ! -e "$SRC" ]; +then + echo "Usage" + echo " $0 destpath/project.app" + echo " $0 destpath/project.app sourcedir/AppHelper.app" + echo + if [ ! -e "$DEST" ]; + then + echo "Error: Target app bundle not found. (Did you compile AND create the bundle?)" + fi + if [ ! -e "$SRC" ]; + then + echo "Error: Source (AppHelper) app bundle not found. (Did you compile AND create the bundle?)" + fi + exit; +fi + +SRCAPP=$(basename "$SRC") +SRCAPP="${SRCAPP%\.app}" +DESTAPP=$(basename "$DEST") +DESTAPP="${DESTAPP%\.app}" + +SUB="" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (GPU)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (Renderer)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + +SUB=" (Plugin)" +rm -rf "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +cp -r "$SRC" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app" +mv "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$SRCAPP" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/MacOS/$DESTAPP Helper$SUB" +sed -i '' "s/$SRCAPP/$DESTAPP Helper$SUB/g" "$DEST/Contents/Frameworks/$DESTAPP Helper$SUB.app/Contents/Info.plist" + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.ico b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.ico new file mode 100644 index 00000000..0341321b Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.ico differ diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.lpi b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.lpi new file mode 100644 index 00000000..b7441b66 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.lpi @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="12"/> + <General> + <Flags> + <CompatibilityMode Value="True"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <Title Value="BrowserWindowOsrDom"/> + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="B:/laz_other/CEF4Delphi/demos/Lazarus_any_OS/BrowserWindowDom"/> + <CompressFinally Value="False"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages Count="3"> + <Item1> + <PackageName Value="LazDebuggerGdbmi"/> + </Item1> + <Item2> + <PackageName Value="CEF4Delphi_Lazarus"/> + </Item2> + <Item3> + <PackageName Value="LCL"/> + </Item3> + </RequiredPackages> + <Units Count="5"> + <Unit0> + <Filename Value="BrowserWindowOsrDom.pas"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="uBrowserWindowDom.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit1> + <Unit2> + <Filename Value="initsubprocess.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="InitSubProcess"/> + </Unit2> + <Unit3> + <Filename Value="globalcefapplication.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="GlobalCefApplication"/> + </Unit3> + <Unit4> + <Filename Value="uHelperProcessDom.pas"/> + <IsPartOfProject Value="True"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="../../../bin/BrowserWindowOsrDom"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + </Linking> + <Other> + <CustomOptions Value="-dUseCthreads"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.pas b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.pas new file mode 100644 index 00000000..83cde90b --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.pas @@ -0,0 +1,84 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + + (* + * Include the following files + * BrowserWindow.app/Contents/Frameworks/ExternalPumpBrowser Helper.app/ + * files from the demos/Lazarus_Mac/AppHelper project + * use create_mac_helper.sh + * + * BrowserWindow.app/Contents/Frameworks/Chromium Embedded Framework.framework + * files from Release folder in cef download + * + *) + + +program BrowserWindowOsrDom; + +{$mode objfpc}{$H+} +{$I cef.inc} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + {$IFDEF LINUX} + InitSubProcess, // On Linux this unit must be used *before* the "interfaces" unit. + {$ENDIF} + Interfaces, + Forms, + uBrowserWindowDom, GlobalCefApplication, + uHelperProcessDom // Used here, for any OS where the main exe server as AppHelper too. + { you can add units after this } + ; + +{$R *.res} + +{$IFDEF WIN32} + // CEF needs to set the LARGEADDRESSAWARE ($20) flag which allows 32-bit processes to use up to 3GB of RAM. + {$SetPEFlags $20} +{$ENDIF} + +begin + RequireDerivedFormResource:=True; + Application.Scaled := True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.res b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.res new file mode 100644 index 00000000..bec39b4a Binary files /dev/null and b/demos/Lazarus_any_OS/BrowserWindowOsrDom/BrowserWindowOsrDom.res differ diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/README.txt b/demos/Lazarus_any_OS/BrowserWindowOsrDom/README.txt new file mode 100644 index 00000000..38409acc --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/README.txt @@ -0,0 +1,40 @@ +BrowserWindow + +# ABOUT + +This example uses + TLazarusBrowserWindow + Examining DOM + +TCEFWorkScheduler feeds the CEF messageloop by calling DoMessageLoopWork(). On Mac this is currently the only way to run the CEF messageloop. + + +# SETUP + +** Windows +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +** Linux +1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe. + Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries. +2) Run the project + +Note: +- For your own Linux project you must modify the project source (lpr) and add "InitSubProcess" to the "uses" clause, so that it is in the list *before* the unit "Interfaces". +- The call to "DestroyGlobalCEFApp" must be in a unit *not* used by "unit InitSubProcess" (including not used in any nested way). + + +** Mac +1) Go to "project options" and create the "App Bundle" +2) Download the CEF framework and place the content of the "Release" folder into BrowserWindowOsrDom.app/Contents/Frameworks/Chromium Embedded Framework.framework +You should have: + Chromium Embedded Framework + Libraries/* + Resources/* +3) Open project "AppHelper" (from the subfolder in this project's folder), create App Bundle and compile the AppHelper. + Run create_mac_helper.sh +4) Open project BrowserWindowOsrDom, compile and run + + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/cef.inc b/demos/Lazarus_any_OS/BrowserWindowOsrDom/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/cef.inc @@ -0,0 +1,468 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + + // 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} + +// Delphi uses MACOS for the new MacOSX and DARWIN is not defined +// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7) +// We define MACOSX to avoid conflicts in both situations +{$IFDEF FPC} + {$IFDEF DARWIN} + {$DEFINE MACOSX} + {$ENDIF} +{$ELSE} + {$IFDEF MACOS} + {$DEFINE MACOSX} + {$ENDIF} +{$ENDIF} diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/create_mac_helper.sh b/demos/Lazarus_any_OS/BrowserWindowOsrDom/create_mac_helper.sh new file mode 100755 index 00000000..fc4e694f --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/create_mac_helper.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +CDIR=$(pwd) +cd "$(dirname "$0")" + +./AppHelper/create_mac_helper_apps.sh ../../../bin/BrowserWindowOsrDom.app + +if [ "$(grep -i TCrCocoaApplication ../../../bin/BrowserWindowOsrDom.app/Contents/Info.plist)" = "" ]; +then +sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/BrowserWindowOsrDom.app/Contents/Info.plist +fi + +cd "$CDIR" diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/globalcefapplication.pas b/demos/Lazarus_any_OS/BrowserWindowOsrDom/globalcefapplication.pas new file mode 100644 index 00000000..46db6401 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/globalcefapplication.pas @@ -0,0 +1,120 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit GlobalCefApplication; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +{.$DEFINE USE_MULTI_THREAD_LOOP} // Only Windows/Linux +{.$DEFINE USE_APP_HELPER} // Optional on Windows/Linux + +{$IFDEF MACOSX} + {$UNDEF USE_MULTI_THREAD_LOOP} // Will fail on Mac + {$DEFINE USE_APP_HELPER} // Required on Mac +{$ENDIF} + +interface + +uses + uCEFApplication, uCEFWorkScheduler, uCEFLazApplication, FileUtil, + uHelperProcessDom; + +procedure CreateGlobalCEFApp; + +implementation + +procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); +begin + if (GlobalCEFWorkScheduler <> nil) then GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); +end; + +procedure CreateGlobalCEFApp; +begin + if GlobalCEFApp <> nil then + exit; + + {$IFnDEF USE_MULTI_THREAD_LOOP} + // TCEFWorkScheduler will call cef_do_message_loop_work when + // it's told in the GlobalCEFApp.OnScheduleMessagePumpWork event. + // GlobalCEFWorkScheduler needs to be created before the + // GlobalCEFApp.StartMainProcess call. + GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil); + {$ENDIF} + + GlobalCEFApp := TCefLazApplication.Create; + GlobalCEFApp.CheckCEFFiles := False; + {$IFDEF USE_MULTI_THREAD_LOOP} + // On Windows/Linux CEF can use threads for the message-loop + GlobalCEFApp.MultiThreadedMessageLoop := True; + {$ELSE} + // use External Pump for message-loop + GlobalCEFApp.ExternalMessagePump := True; + GlobalCEFApp.MultiThreadedMessageLoop := False; + GlobalCEFApp.OnScheduleMessagePumpWork := @GlobalCEFApp_OnScheduleMessagePumpWork; + {$ENDIF} + + GlobalCEFApp.CheckCEFFiles := false; + + {$IFnDEF MACOSX} + {$IFDEF USE_APP_HELPER} + (* Use AppHelper as subprocess, instead of the main exe *) + GlobalCEFApp.BrowserSubprocessPath := 'AppHelper' + GetExeExt; + {$ENDIF} + {$ENDIF} + + {$IFDEF MACOSX} + (* Enable the below to prevent being asked for permission to access "Chromium Safe Storage" + If set to true, Cookies will not be encrypted. + *) + GlobalCEFApp.UseMockKeyChain := True; + {$ENDIF} + {$IFDEF LINUX} + // This is a workaround for the 'GPU is not usable error' issue : + // https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef + GlobalCEFApp.DisableZygote := True; // this property adds the "--no-zygote" command line switch + {$ENDIF} + { + GlobalCEFApp.LogFile := 'cef.log'; + GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE; + } + + InitProcessMessagesHandler; // This is for the AppHelper process. +end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/initsubprocess.pas b/demos/Lazarus_any_OS/BrowserWindowOsrDom/initsubprocess.pas new file mode 100644 index 00000000..512c43e8 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/initsubprocess.pas @@ -0,0 +1,61 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit InitSubProcess; + +{$mode ObjFPC}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, uCEFApplication, uCEFWorkScheduler; + +implementation + +initialization + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.lfm b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.lfm new file mode 100644 index 00000000..0dc868b3 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.lfm @@ -0,0 +1,82 @@ +object Form1: TForm1 + Left = 473 + Height = 589 + Top = 227 + Width = 967 + Caption = 'Initializing browser. Please wait...' + ClientHeight = 589 + ClientWidth = 967 + OnCloseQuery = FormCloseQuery + OnCreate = FormCreate + Position = poScreenCenter + LCLVersion = '2.1.0.0' + object AddressPnl: TPanel + Left = 0 + Height = 23 + Top = 0 + Width = 967 + Align = alTop + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 967 + TabOrder = 0 + object GoBtn: TButton + Left = 932 + Height = 23 + Top = 0 + Width = 35 + Align = alRight + Caption = 'Go' + OnClick = GoBtnClick + TabOrder = 0 + end + object AddressEdt: TComboBox + Left = 0 + Height = 23 + Top = 0 + Width = 932 + Align = alClient + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'https://www.google.com' + 'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' + 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_win_close' + 'https://www.w3schools.com/html/html5_video.asp' + 'http://www.adobe.com/software/flash/about/' + 'http://isflashinstalled.com/' + 'chrome://version/' + 'http://html5test.com/' + 'https://www.w3schools.com/' + 'http://webglsamples.org/' + 'https://get.webgl.org/' + 'https://www.youtube.com' + 'https://html5demos.com/drag/' + 'https://developers.google.com/maps/documentation/javascript/examples/streetview-embed?hl=fr' + 'https://www.w3schools.com/Tags/tryit.asp?filename=tryhtml_iframe_name' + 'https://www.browserleaks.com/webrtc' + 'https://frames-per-second.appspot.com/' + ) + TabOrder = 1 + Text = 'https://www.google.com' + end + end + object LazarusOsrBrowserWindow1: TLazarusOsrBrowserWindow + Left = 0 + Height = 566 + Top = 23 + Width = 967 + CopyOriginalBuffer = True + Align = alClient + TabOrder = 1 + OnMouseMove = LazarusOsrBrowserWindow1MouseMove + OnBrowserClosed = LazarusBrowserWindow1BrowserClosed + end + object PopupMenu1: TPopupMenu + left = 418 + top = 126 + object MenuItem1: TMenuItem + Caption = 'Nothing in this menu' + end + end +end diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.pas b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.pas new file mode 100644 index 00000000..7c4437da --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uBrowserWindowDom.pas @@ -0,0 +1,266 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uBrowserWindowDom; + +{$mode objfpc}{$H+} +{$I cef.inc} + +interface + +uses + GlobalCefApplication, + uCEFLazarusCocoa, // required for Cocoa + SysUtils, Messages, Forms, Controls, Dialogs, ExtCtrls, StdCtrls, LMessages, + Menus, Graphics, uCEFTypes, uCEFInterfaces, uHelperProcessDom, + uCEFWorkScheduler, uCEFLazarusBrowserWindow, uCEFProcessMessage, + uCEFLazarusOsrBrowserWindow, Classes; + +type + + { TForm1 } + + TForm1 = class(TForm) + AddressEdt: TComboBox; + GoBtn: TButton; + AddressPnl: TPanel; + LazarusOsrBrowserWindow1: TLazarusOsrBrowserWindow; + mDomHere: TMenuItem; + MenuItem1: TMenuItem; + PopupMenu1: TPopupMenu; + + 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 Chromium1OpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure FormCreate(Sender: TObject); + + procedure GoBtnClick(Sender: TObject); + procedure LazarusBrowserWindow1BrowserClosed(Sender: TObject); + procedure LazarusOsrBrowserWindow1MouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); + private + FCurRect: TRect; + procedure DoOnMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer; var AHandled: Boolean); + procedure DoOnMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer; var AHandled: Boolean); + procedure DoOnPaint(Sender: TObject); + procedure DoProcessMessageReceived(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; + sourceProcess: TCefProcessId; const message: ICefProcessMessage; out + Result: Boolean); + protected + {$IFDEF WINDOWS} + procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP; + procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP; + procedure WMDpiChanged(var Message: TMessage); message WM_DPICHANGED; + {$ENDIF} + + public + + end; + +var + Form1: TForm1; + + +implementation + +{$R *.lfm} + +uses + uCEFApplication; + +{ TForm1 } + +procedure TForm1.GoBtnClick(Sender: TObject); +begin + LazarusOsrBrowserWindow1.Chromium.LoadURL(UTF8Decode(AddressEdt.Text)); +end; + +procedure TForm1.LazarusBrowserWindow1BrowserClosed(Sender: TObject); +begin + Close; +end; + +procedure TForm1.LazarusOsrBrowserWindow1MouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); +var + TempMsg : ICefProcessMessage; +begin + TempMsg := TCefProcessMessageRef.New(MSG_REQUEST_DOM_R); // Same name than TCefCustomRenderProcessHandler.MessageName + TempMsg.ArgumentList.SetInt(0, X); + TempMsg.ArgumentList.SetInt(1, Y); + LazarusOsrBrowserWindow1.Chromium.SendProcessMessage(PID_RENDERER, TempMsg); +end; + +procedure TForm1.DoOnMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer; var AHandled: Boolean); +begin + AHandled := Button = mbRight; + + if Button = mbRight then begin + PopupMenu1.PopUp(X, Y); + end; +end; + +procedure TForm1.DoOnMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer; var AHandled: Boolean); +begin + AHandled := Button = mbRight; +end; + +procedure TForm1.DoOnPaint(Sender: TObject); +begin + if (FCurRect.Width > 0) and (FCurRect.Height > 0) then begin + LazarusOsrBrowserWindow1.Canvas.Brush.Style := bsClear; + LazarusOsrBrowserWindow1.Canvas.Pen.Style := psSolid; + LazarusOsrBrowserWindow1.Canvas.Pen.Color := clRed; + LazarusOsrBrowserWindow1.Canvas.Rectangle(FCurRect); + end; +end; + +procedure TForm1.DoProcessMessageReceived(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; + sourceProcess: TCefProcessId; const message: ICefProcessMessage; out + Result: Boolean); +begin + Result := False; + case message.Name of + MSG_RESPONSE_DOM_R: begin + FCurRect.Left := message.ArgumentList.GetInt(0); + FCurRect.Top := message.ArgumentList.GetInt(1); + FCurRect.Width := message.ArgumentList.GetInt(2); + FCurRect.Height := message.ArgumentList.GetInt(3); + Result := True; + LazarusOsrBrowserWindow1.Invalidate; + end; + end; +end; + +{$IFDEF WINDOWS} +procedure TForm1.WMEnterMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True; +end; + +procedure TForm1.WMExitMenuLoop(var aMessage: TMessage); +begin + inherited; + + if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False; +end; + +procedure TForm1.WMDpiChanged(var Message: TMessage); +begin + inherited; + + if (GlobalCEFApp <> nil) then + GlobalCEFApp.UpdateDeviceScaleFactor; + + if (LazarusOsrBrowserWindow1.Chromium <> nil) then + begin + LazarusOsrBrowserWindow1.Chromium.NotifyScreenInfoChanged; + LazarusOsrBrowserWindow1.Chromium.WasResized; + end; +end; + +{$ENDIF} + +procedure TForm1.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 + // 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 TForm1.Chromium1OpenUrlFromTab(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; + targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out + 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 TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + LazarusOsrBrowserWindow1.CloseBrowser(True); + + CanClose := LazarusOsrBrowserWindow1.IsClosed; +end; + +procedure TForm1.FormCreate(Sender: TObject); +begin + FCurRect.Width := 0; + LazarusOsrBrowserWindow1.Chromium.OnProcessMessageReceived := @DoProcessMessageReceived; + LazarusOsrBrowserWindow1.OnMouseDown := @DoOnMouseDown; + LazarusOsrBrowserWindow1.OnMouseUp := @DoOnMouseUp; + LazarusOsrBrowserWindow1.OnPaint := @DoOnPaint; + + LazarusOsrBrowserWindow1.Chromium.LoadURL(UTF8Decode(AddressEdt.Text)); +end; + +initialization + {$IFDEF DARWIN} // $IFDEF MACOSX + AddCrDelegate; + {$ENDIF} + if GlobalCEFApp = nil then begin + CreateGlobalCEFApp; + if not GlobalCEFApp.StartMainProcess then begin + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + halt(0); // exit the subprocess + end; + end; + +finalization + (* Destroy from this unit, which is used after "Interfaces". So this happens before the Application object is destroyed *) + if GlobalCEFWorkScheduler <> nil then + GlobalCEFWorkScheduler.StopScheduler; + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; + +end. + diff --git a/demos/Lazarus_any_OS/BrowserWindowOsrDom/uHelperProcessDom.pas b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uHelperProcessDom.pas new file mode 100644 index 00000000..d9604544 --- /dev/null +++ b/demos/Lazarus_any_OS/BrowserWindowOsrDom/uHelperProcessDom.pas @@ -0,0 +1,170 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uHelperProcessDom; + +(* The code in this unit is executed in the renderer sub-process +*) + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, SysUtils, uCEFApplication, uCEFInterfaces, uCEFDomVisitor, uCEFTypes, + uCEFProcessMessage; + +const + MSG_REQUEST_DOM_R = 'MSG_REQUEST_DOM_R'; + MSG_RESPONSE_DOM_R = 'MSG_RESPONSE_DOM_R'; + +procedure InitProcessMessagesHandler; + +implementation + +type + + { TDomVisitorFindXY } + + TDomVisitorFindXY = class(TCefDomVisitorOwn) + protected + FFrame : ICefFrame; + FX, FY: Integer; + procedure visit(const document: ICefDomDocument); override; + public + constructor Create(AFrame: ICefFrame; X,Y: Integer); reintroduce; virtual; + end; + + +{ TDomVisitorFindXY } + +procedure TDomVisitorFindXY.visit(const document: ICefDomDocument); +var + node, foundNode: ICefDomNode; + nb: TCefRect; + TempMsg : ICefProcessMessage; +begin + node := document.GetBody; + foundNode := nil; + if node <> nil then + begin + nb := node.GetElementBounds; + if (FX >= nb.x) and (FX < nb.x + nb.width) and + (FY >= nb.y) and (FY < nb.y + nb.height) + then + begin + while node <> nil do + begin + foundNode := node; + if node.HasChildren then + begin + node := node.FirstChild; + while node <> nil do + begin + nb := node.GetElementBounds; + if (FX >= nb.x) and (FX < nb.x + nb.width) and + (FY >= nb.y) and (FY < nb.y + nb.height) + then + break // go outer loop + else + node := node.NextSibling; + end; + end + else + node := nil; + end; + end; + end; + + TempMsg := TCefProcessMessageRef.New(MSG_RESPONSE_DOM_R); // Same name than TCefCustomRenderProcessHandler.MessageName + if foundNode <> nil then begin + nb := foundNode.GetElementBounds; + TempMsg.ArgumentList.SetInt(0, nb.X); + TempMsg.ArgumentList.SetInt(1, nb.y); + TempMsg.ArgumentList.SetInt(2, nb.width); + TempMsg.ArgumentList.SetInt(3, nb.height); + end + else begin + TempMsg.ArgumentList.SetInt(0, 0); + TempMsg.ArgumentList.SetInt(1, 0); + TempMsg.ArgumentList.SetInt(2, 0); + TempMsg.ArgumentList.SetInt(3, 0); + end; + if (FFrame <> nil) and FFrame.IsValid then + FFrame.SendProcessMessage(PID_BROWSER, TempMsg); +end; + +constructor TDomVisitorFindXY.Create(AFrame: ICefFrame; X, Y: Integer); +begin + FFrame := AFrame; + FX := X; + FY := Y; + inherited Create; +end; + + +procedure DoProcessMessageReceived(const browser: ICefBrowser; + const frame: ICefFrame; sourceProcess: TCefProcessId; + const message: ICefProcessMessage; var aHandled: boolean); +var + TempVisitor : TDomVisitorFindXY; +begin + aHandled := False; + case message.Name of + MSG_REQUEST_DOM_R: begin + if (frame <> nil) and frame.IsValid then + begin + TempVisitor := TDomVisitorFindXY.Create( + frame, + message.ArgumentList.GetInt(0), + message.ArgumentList.GetInt(1) + ); + frame.VisitDom(TempVisitor); + end; + aHandled := True; + + end; + end; +end; + +procedure InitProcessMessagesHandler; +begin + GlobalCEFApp.OnProcessMessageReceived := @DoProcessMessageReceived; +end; + +end. + diff --git a/packages/cef4delphi_lazarus.lpk b/packages/cef4delphi_lazarus.lpk index 37a1e18f..4f293e26 100644 --- a/packages/cef4delphi_lazarus.lpk +++ b/packages/cef4delphi_lazarus.lpk @@ -22,7 +22,7 @@ <Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/> <License Value="MPL 1.1"/> <Version Major="89" Release="6"/> - <Files Count="200"> + <Files Count="202"> <Item1> <Filename Value="..\source\uCEFAccessibilityHandler.pas"/> <UnitName Value="uCEFAccessibilityHandler"/> @@ -840,6 +840,15 @@ <HasRegisterProc Value="True"/> <UnitName Value="uceflazarusbrowserwindow"/> </Item200> + <Item201> + <Filename Value="..\source\uCEFLazApplication.pas"/> + <UnitName Value="uCEFLazApplication"/> + </Item201> + <Item202> + <Filename Value="..\source\uCEFLazarusOsrBrowserWindow.pas"/> + <HasRegisterProc Value="True"/> + <UnitName Value="uCEFLazarusOsrBrowserWindow"/> + </Item202> </Files> <RequiredPkgs Count="4"> <Item1> diff --git a/packages/cef4delphi_lazarus.pas b/packages/cef4delphi_lazarus.pas index 5ddb7c66..e5dcc2ac 100644 --- a/packages/cef4delphi_lazarus.pas +++ b/packages/cef4delphi_lazarus.pas @@ -65,8 +65,9 @@ uses uCEFMediaSinkDeviceInfoCallback, uCEFJson, uCEFBitmapBitBuffer, uCEFPrintDialogCallback, uCEFPrintHandler, uCEFPrintJobCallback, uCEFLinuxFunctions, uCEFLinuxTypes, uCEFLinuxConstants, - uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, uCEFLazarusCocoa, - uCEFLazarusBrowserWindow, LazarusPackageIntf; + uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, uCEFLazarusCocoa, + uCEFLazarusBrowserWindow, uCEFLazApplication, uCEFLazarusOsrBrowserWindow, + LazarusPackageIntf; implementation @@ -90,6 +91,8 @@ begin RegisterUnit('uCEFScrollViewComponent', @uCEFScrollViewComponent.Register); RegisterUnit('uCEFTextfieldComponent', @uCEFTextfieldComponent.Register); RegisterUnit('uCEFLazarusBrowserWindow', @uCEFLazarusBrowserWindow.Register); + RegisterUnit('uCEFLazarusOsrBrowserWindow', + @uCEFLazarusOsrBrowserWindow.Register); end; initialization diff --git a/source/uCEFApplicationCore.pas b/source/uCEFApplicationCore.pas index 551b7283..3e428eef 100644 --- a/source/uCEFApplicationCore.pas +++ b/source/uCEFApplicationCore.pas @@ -391,7 +391,7 @@ type // ICefLoadHandler and ICefPrintHandler should use them. procedure Internal_OnBeforeCommandLineProcessing(const processType: ustring; const commandLine: ICefCommandLine); procedure Internal_OnRegisterCustomSchemes(const registrar: TCefSchemeRegistrarRef); - procedure Internal_OnContextInitialized; + procedure Internal_OnContextInitialized; virtual; procedure Internal_OnBeforeChildProcessLaunch(const commandLine: ICefCommandLine); procedure Internal_OnScheduleMessagePumpWork(const delayMs: Int64); function Internal_GetLocalizedString(stringId: Integer; var stringVal: ustring) : boolean; diff --git a/source/uCEFBufferPanel.pas b/source/uCEFBufferPanel.pas index ced2cc3e..74c8eb59 100644 --- a/source/uCEFBufferPanel.pas +++ b/source/uCEFBufferPanel.pas @@ -133,6 +133,11 @@ type procedure WMIMEEndComp(var aMessage: TMessage); procedure WMIMESetContext(var aMessage: TMessage); procedure WMIMEComposition(var aMessage: TMessage); + + procedure DoOnIMECancelComposition; virtual; + procedure DoOnIMECommitText(const aText : ustring; const replacement_range : PCefRange; relative_cursor_pos : integer); virtual; + procedure DoOnIMESetComposition(const aText : ustring; const underlines : TCefCompositionUnderlineDynArray; const replacement_range, selection_range : TCefRange); virtual; + {$ENDIF} public @@ -636,6 +641,8 @@ begin Canvas.Brush.Style := bsSolid; Canvas.FillRect(rect(0, 0, Width, Height)); end; + + if Assigned(OnPaint) then OnPaint(Self); end; {$IFDEF MSWINDOWS} @@ -735,7 +742,7 @@ end; procedure TBufferPanel.WMIMEEndComp(var aMessage: TMessage); begin - if assigned(FOnIMECancelComposition) then FOnIMECancelComposition(self); + DoOnIMECancelComposition; if (FIMEHandler <> nil) then begin @@ -775,7 +782,7 @@ begin TempRange.from := high(Integer); TempRange.to_ := high(Integer); - FOnIMECommitText(self, TempText, @TempRange, 0); + DoOnIMECommitText(TempText, @TempRange, 0); end; FIMEHandler.ResetComposition; @@ -791,14 +798,14 @@ begin TempSelection.from := TempCompStart; TempSelection.to_ := TempCompStart + length(TempText); - FOnIMESetComposition(self, TempText, TempUnderlines, TempRange, TempSelection); + DoOnIMESetComposition(TempText, TempUnderlines, TempRange, TempSelection); end; FIMEHandler.UpdateCaretPosition(pred(TempCompStart)); end else begin - if assigned(FOnIMECancelComposition) then FOnIMECancelComposition(self); + DoOnIMECancelComposition; FIMEHandler.ResetComposition; FIMEHandler.DestroyImeWindow; @@ -812,6 +819,28 @@ begin end; end; end; + +procedure TBufferPanel.DoOnIMECancelComposition; +begin + if FOnIMECancelComposition <> nil then + FOnIMECancelComposition(Self); +end; + +procedure TBufferPanel.DoOnIMECommitText(const aText: ustring; + const replacement_range: PCefRange; relative_cursor_pos: integer); +begin + if FOnIMECommitText <> nil then + FOnIMECommitText(Self, aText, replacement_range, relative_cursor_pos); +end; + +procedure TBufferPanel.DoOnIMESetComposition(const aText: ustring; + const underlines: TCefCompositionUnderlineDynArray; const replacement_range, + selection_range: TCefRange); +begin + if FOnIMESetComposition <> nil then + FOnIMESetComposition(Self, aText, underlines, replacement_range, selection_range); +end; + {$ENDIF} function TBufferPanel.GetBufferBits : pointer; diff --git a/source/uCEFLazApplication.pas b/source/uCEFLazApplication.pas new file mode 100644 index 00000000..3298395d --- /dev/null +++ b/source/uCEFLazApplication.pas @@ -0,0 +1,80 @@ +unit uCEFLazApplication; + +{$IFDEF FPC} + {$MODE OBJFPC}{$H+} +{$ENDIF} + +{$I cef.inc} + +interface + +uses + {$IFDEF DELPHI16_UP} + {$ELSE} + Forms, LclProc, Classes, SysUtils, + {$ENDIF} + uCEFTypes, uCEFApplication; + +type + + { TCefLazApplication } + + TCefLazApplication = class(TCefApplication) + protected + FContextInitializedHandlers: TMethodList; + FContextInitializedDone: Boolean; + + procedure CallContextInitializedHandlers(Data: PtrInt); + public + constructor Create; + destructor Destroy; override; + procedure Internal_OnContextInitialized; override; // In UI thread + + Procedure AddContextInitializedHandler(AHandler: TNotifyEvent); + Procedure RemoveContextInitializedHandler(AHandler: TNotifyEvent); + end; + +implementation + +{ TCefLazApplication } + +procedure TCefLazApplication.Internal_OnContextInitialized; +begin + inherited Internal_OnContextInitialized; + Application.QueueAsyncCall(@CallContextInitializedHandlers, 0); + //TThread.Queue(@CallContextInitializedHandlers); +end; + +procedure TCefLazApplication.CallContextInitializedHandlers(Data: PtrInt); +begin + FContextInitializedHandlers.CallNotifyEvents(Self); + FContextInitializedDone := True; +end; + +constructor TCefLazApplication.Create; +begin + FContextInitializedHandlers := TMethodList.Create; + inherited Create; +end; + +destructor TCefLazApplication.Destroy; +begin + inherited Destroy; + FContextInitializedHandlers.Free; +end; + +procedure TCefLazApplication.AddContextInitializedHandler(AHandler: TNotifyEvent); +begin + FContextInitializedHandlers.Add(TMethod(AHandler)); + if FContextInitializedDone then + AHandler(Self); +end; + +procedure TCefLazApplication.RemoveContextInitializedHandler( + AHandler: TNotifyEvent); +begin + FContextInitializedHandlers.Remove(TMethod(AHandler)); +end; + +end. + diff --git a/source/uCEFLazarusOsrBrowserWindow.pas b/source/uCEFLazarusOsrBrowserWindow.pas new file mode 100644 index 00000000..bbe4ffc3 --- /dev/null +++ b/source/uCEFLazarusOsrBrowserWindow.pas @@ -0,0 +1,917 @@ +// ************************************************************************ +// ***************************** 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 <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. + * + *) + +unit uCEFLazarusOsrBrowserWindow; + +{$mode objfpc}{$H+} +{$i cef.inc} + +interface + +uses + {$IFDEF FPC} + LResources, + {$ENDIF} + uCEFApplication, uCEFChromiumWindow, uCEFTypes, uCEFInterfaces, uCEFChromium, + uCEFLinkedWinControlBase, uCEFLazApplication, uCEFBufferPanel, + uCEFLazarusBrowserWindow, uCEFBitmapBitBuffer, uCEFMiscFunctions, + uCEFConstants, Forms, ExtCtrls, LCLType, Graphics, Controls, syncobjs, + LazLogger, Classes, sysutils, math; + +type + + TBrowserMouseEvent = procedure(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer; + var AHandled: Boolean) of Object; + + + { TLazarusOsrBrowserWindow } + + TLazarusOsrBrowserWindow = class(TBufferPanel) + private + FPopUpBitmap : TBitmap; + FPopUpRect : TRect; + FShowPopUp : boolean; + FResizing : boolean; + FPendingResize : boolean; + FResizeCS : syncobjs.TCriticalSection; + + //FIMECS : TCriticalSection; + FDeviceBounds : TCefRectDynArray; + FSelectedRange : TCefRange; + + FLastKeyDown: Word; + + procedure AsyncInvalidate(Data: PtrInt); + procedure AsyncResize(Data: PtrInt); + procedure SyncIMERangeChanged; + + procedure DoGetChromiumBeforePopup(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 DoGetChromiumPopupShow(Sender: TObject; + const browser: ICefBrowser; AShow: Boolean); + procedure DoGetChromiumPopupSize(Sender: TObject; + const browser: ICefBrowser; const rect: PCefRect); + procedure DoGetChromiumTooltip(Sender: TObject; + const browser: ICefBrowser; var AText: ustring; out Result: Boolean); + procedure DoGetChromiumIMECompositionRangeChanged(Sender: TObject; + const browser: ICefBrowser; const selected_range: PCefRange; + character_boundsCount: NativeUInt; const character_bounds: PCefRect); + procedure DoGetChromiumCursorChange(Sender: TObject; + const browser: ICefBrowser; cursor_: TCefCursorHandle; + cursorType: TCefCursorType; const customCursorInfo: PCefCursorInfo; + var aResult: boolean); + procedure DoGetChromiumGetScreenInfo(Sender: TObject; + const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out + Result: Boolean); + procedure DoGetChromiumGetScreenPoint(Sender: TObject; + const browser: ICefBrowser; viewX, viewY: Integer; var screenX, + screenY: Integer; out Result: Boolean); + procedure DoGetChromiumViewRect(Sender: TObject; + const browser: ICefBrowser; var rect: TCefRect); + procedure DoChromiumPaint(Sender: TObject; const browser: ICefBrowser; + kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; + const dirtyRects: PCefRectArray; const ABuffer: Pointer; AWidth, + AHeight: Integer); + + private + FChromium : TLazChromium; + + FOnBrowserClosed : TNotifyEvent; + FOnBrowserCreated : TNotifyEvent; + FOnMouseDown: TBrowserMouseEvent; + FOnMouseUp: TBrowserMouseEvent; + + procedure DoCreateBrowserAfterContext(Sender: TObject); + + protected + function GetChromium: TLazChromium; + function getModifiers(Shift: TShiftState): TCefEventFlags; + function getKeyModifiers(Shift: TShiftState): TCefEventFlags; + function GetButton(Button: TMouseButton): TCefMouseButtonType; + procedure DestroyHandle; override; + procedure RealizeBounds; override; + + procedure DoEnter; override; + procedure DoExit; override; + procedure Click; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseEnter; override; + procedure MouseLeave; override; + function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override; + + (* Key input works only for windows. + *) + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override; + procedure KeyUp(var Key: Word; Shift: TShiftState); override; + {$IFDEF MSWINDOWS} + procedure DoOnIMECancelComposition; override; + procedure DoOnIMECommitText(const aText : ustring; const replacement_range : PCefRange; relative_cursor_pos : integer); override; + procedure DoOnIMESetComposition(const aText : ustring; const underlines : TCefCompositionUnderlineDynArray; const replacement_range, selection_range : TCefRange); override; + {$ENDIF} + procedure CaptureChanged; override; + + procedure DoOnCreated(Sender: TObject); + procedure DoOnClosed(Sender: TObject); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure CreateHandle; override; + + procedure CloseBrowser(aForceClose: boolean); + procedure WaitForBrowserClosed; + function IsClosed: boolean; + procedure LoadURL(aURL: ustring); + // + published + property Chromium : TLazChromium read GetChromium; + + property OnBrowserCreated : TNotifyEvent read FOnBrowserCreated write FOnBrowserCreated; + property OnBrowserClosed : TNotifyEvent read FOnBrowserClosed write FOnBrowserClosed; + + property OnMouseDown: TBrowserMouseEvent read FOnMouseDown write FOnMouseDown; + property OnMouseUp: TBrowserMouseEvent read FOnMouseUp write FOnMouseUp; + end; + +{$IFDEF FPC} +procedure Register; +{$ENDIF} + + +implementation + +{ TLazarusOsrBrowserWindow } + +procedure TLazarusOsrBrowserWindow.AsyncInvalidate(Data: PtrInt); +begin + Invalidate; +end; + +procedure TLazarusOsrBrowserWindow.AsyncResize(Data: PtrInt); +begin + try + FResizeCS.Acquire; + + if FResizing then + FPendingResize := True + else + if BufferIsResized then + Chromium.Invalidate(PET_VIEW) + else + begin + FResizing := True; + Chromium.WasResized; + end; + finally + FResizeCS.Release; + end; +end; + +procedure TLazarusOsrBrowserWindow.SyncIMERangeChanged; +begin + ChangeCompositionRange(FSelectedRange, FDeviceBounds); +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumBeforePopup(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 TLazarusOsrBrowserWindow.DoGetChromiumPopupShow(Sender: TObject; + const browser: ICefBrowser; AShow: Boolean); +begin + if aShow then + FShowPopUp := True + else + begin + FShowPopUp := False; + FPopUpRect := rect(0, 0, 0, 0); + + if (Chromium <> nil) then Chromium.Invalidate(PET_VIEW); + end; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumPopupSize(Sender: TObject; + const browser: ICefBrowser; const rect: PCefRect); +begin + LogicalToDevice(rect^, ScreenScale); + + FPopUpRect.Left := rect^.x; + FPopUpRect.Top := rect^.y; + FPopUpRect.Right := rect^.x + rect^.width - 1; + FPopUpRect.Bottom := rect^.y + rect^.height - 1; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumTooltip(Sender: TObject; + const browser: ICefBrowser; var AText: ustring; out Result: Boolean); +begin + hint := aText; + ShowHint := (length(aText) > 0); + Result := True; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumIMECompositionRangeChanged( + Sender: TObject; const browser: ICefBrowser; const selected_range: PCefRange; + character_boundsCount: NativeUInt; const character_bounds: PCefRect); +var + TempPRect : PCefRect; + i : NativeUInt; + TempScale : single; +begin + // TChromium.OnIMECompositionRangeChanged is triggered in a different thread + // and all functions using a IMM context need to be executed in the same + // thread, in this case the main thread. We need to save the parameters and + // send a message to the form to execute Panel1.ChangeCompositionRange in + // the main thread. + + if (FDeviceBounds <> nil) then + begin + Finalize(FDeviceBounds); + FDeviceBounds := nil; + end; + + FSelectedRange := selected_range^; + + if (character_boundsCount > 0) then + begin + SetLength(FDeviceBounds, character_boundsCount); + + i := 0; + TempPRect := character_bounds; + TempScale := ScreenScale; + + while (i < character_boundsCount) do + begin + FDeviceBounds[i] := TempPRect^; + LogicalToDevice(FDeviceBounds[i], TempScale); + + inc(TempPRect); + inc(i); + end; + end; + + TThread.Synchronize(nil, @SyncIMERangeChanged); +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumCursorChange(Sender: TObject; + const browser: ICefBrowser; cursor_: TCefCursorHandle; + cursorType: TCefCursorType; const customCursorInfo: PCefCursorInfo; + var aResult: boolean); +begin + Cursor := CefCursorToWindowsCursor(cursorType); + aResult := True; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumGetScreenInfo(Sender: TObject; + const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out + Result: Boolean); +var + TempRect : TCEFRect; + TempScale : single; +begin + TempScale := ScreenScale; + TempRect.x := 0; + TempRect.y := 0; + TempRect.width := DeviceToLogical(Width, TempScale); + TempRect.height := DeviceToLogical(Height, TempScale); + + screenInfo.device_scale_factor := TempScale; + screenInfo.depth := 0; + screenInfo.depth_per_component := 0; + screenInfo.is_monochrome := Ord(False); + screenInfo.rect := TempRect; + screenInfo.available_rect := TempRect; + + Result := True; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumGetScreenPoint(Sender: TObject; + const browser: ICefBrowser; viewX, viewY: Integer; var screenX, + screenY: Integer; out Result: Boolean); +var + TempScreenPt, TempViewPt : TPoint; + TempScale : single; +begin + TempScale := ScreenScale; + TempViewPt.x := LogicalToDevice(viewX, TempScale); + TempViewPt.y := LogicalToDevice(viewY, TempScale); + TempScreenPt := ClientToScreen(TempViewPt); + screenX := TempScreenPt.x; + screenY := TempScreenPt.y; + Result := True; +end; + +procedure TLazarusOsrBrowserWindow.DoGetChromiumViewRect(Sender: TObject; + const browser: ICefBrowser; var rect: TCefRect); +var + TempScale : single; +begin + TempScale := ScreenScale; + rect.x := 0; + rect.y := 0; + rect.width := DeviceToLogical(Width, TempScale); + rect.height := DeviceToLogical(Height, TempScale); +end; + +procedure TLazarusOsrBrowserWindow.DoChromiumPaint(Sender: TObject; + const browser: ICefBrowser; kind: TCefPaintElementType; + dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; + const ABuffer: 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; + {$IFDEF DARWIN} + s: PByte; + ls: integer; + {$ENDIF} +begin + try + FResizeCS.Acquire; + TempForcedResize := False; + + if 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 := UpdateBufferDimensions(aWidth, aHeight) or not(BufferIsResized(False)); + + TempBitmap := Buffer; + TempBitmap.BeginUpdate; + + TempWidth := BufferWidth; + TempHeight := BufferHeight; + end; + + SrcStride := aWidth * SizeOf(TRGBQuad); + n := 0; + + 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) {$IFnDEF DARWIN}* SizeOf(TRGBQuad){$ENDIF}; + + if (TempLineSize > 0) then + begin + TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad); + TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad)); + + src := @PByte(ABuffer)[TempSrcOffset]; + + i := 0; + j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y); + + while (i < j) do + begin + TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i]; + dst := @PByte(TempBufferBits)[TempDstOffset]; + + {$IFDEF DARWIN} + ls := TempLineSize; + s := src; + while ls > 0 do begin + PCardinal(dst)^ := (s[0] shl 24) or (s[1] shl 16) or (s[2] shl 8) or s[3]; + inc(dst, 4); + inc(s, 4); + dec(ls); + end; + {$ELSE} + Move(src^, dst^, TempLineSize); + {$ENDIF} + + + Inc(src, SrcStride); + inc(i); + end; + end; + end; + + inc(n); + end; + + TempBitmap.EndUpdate; + + 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)); + + BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect); + end; + + EndBufferDraw; + + if HandleAllocated then + //PostMessage(Handle, CEF_PENDINGINVALIDATE, 0, 0); + Application.QueueAsyncCall(@AsyncInvalidate, 0); + + if (kind = PET_VIEW) then + begin + if (TempForcedResize or FPendingResize) and + HandleAllocated then + Application.QueueAsyncCall(@AsyncResize, 0); + //PostMessage(Handle, CEF_PENDINGRESIZE, 0, 0); + + FResizing := False; + FPendingResize := False; + end; + end; + finally + FResizeCS.Release; + end; +end; + +function TLazarusOsrBrowserWindow.GetChromium: TLazChromium; +begin + Result := FChromium; +end; + +function TLazarusOsrBrowserWindow.getModifiers(Shift: TShiftState + ): TCefEventFlags; +begin + Result := EVENTFLAG_NONE; + + if (ssShift in Shift) then Result := Result or EVENTFLAG_SHIFT_DOWN; + if (ssAlt in Shift) then Result := Result or EVENTFLAG_ALT_DOWN; + if (ssCtrl in Shift) then Result := Result or EVENTFLAG_CONTROL_DOWN; + if (ssLeft in Shift) then Result := Result or EVENTFLAG_LEFT_MOUSE_BUTTON; + if (ssRight in Shift) then Result := Result or EVENTFLAG_RIGHT_MOUSE_BUTTON; + if (ssMiddle in Shift) then Result := Result or EVENTFLAG_MIDDLE_MOUSE_BUTTON; +end; + +function TLazarusOsrBrowserWindow.getKeyModifiers(Shift: TShiftState): TCefEventFlags; +begin + Result := EVENTFLAG_NONE; + + if (ssShift in Shift) then Result := Result or EVENTFLAG_SHIFT_DOWN; + if (ssAlt in Shift) then Result := Result or EVENTFLAG_ALT_DOWN; + if (ssCtrl in Shift) then Result := Result or EVENTFLAG_CONTROL_DOWN; + if (ssNum in Shift) then Result := Result or EVENTFLAG_NUM_LOCK_ON; + if (ssCaps in Shift) then Result := Result or EVENTFLAG_CAPS_LOCK_ON; +end; + +function TLazarusOsrBrowserWindow.GetButton(Button: TMouseButton + ): TCefMouseButtonType; +begin + case Button of + TMouseButton.mbRight : Result := MBT_RIGHT; + TMouseButton.mbMiddle : Result := MBT_MIDDLE; + else Result := MBT_LEFT; + end; +end; + +procedure TLazarusOsrBrowserWindow.DoCreateBrowserAfterContext(Sender: TObject); +begin + FChromium.CreateBrowser(nil); +end; + +procedure TLazarusOsrBrowserWindow.CreateHandle; +begin + inherited CreateHandle; + if not (csDesigning in ComponentState) then begin + if GlobalCEFApp is TCefLazApplication then + TCefLazApplication(GlobalCEFApp).AddContextInitializedHandler(@DoCreateBrowserAfterContext) + else + DoCreateBrowserAfterContext(nil); + end; +end; + +procedure TLazarusOsrBrowserWindow.DestroyHandle; +begin + if (GlobalCEFApp = nil) or + (not FChromium.HasBrowser) or + (csDesigning in ComponentState) + then begin + inherited DestroyHandle; + exit; + end; + + FChromium.CloseBrowser(True); + inherited DestroyHandle; +end; + +procedure TLazarusOsrBrowserWindow.RealizeBounds; +begin + inherited RealizeBounds; + Chromium.NotifyMoveOrResizeStarted; + AsyncResize(0); +end; + +procedure TLazarusOsrBrowserWindow.DoEnter; +begin + inherited DoEnter; + Chromium.SendFocusEvent(True); +end; + +procedure TLazarusOsrBrowserWindow.DoExit; +begin + inherited DoExit; + Chromium.SendFocusEvent(False); +end; + +procedure TLazarusOsrBrowserWindow.Click; +begin + inherited Click; + SetFocus; +end; + +procedure TLazarusOsrBrowserWindow.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + TempEvent : TCefMouseEvent; + LastClickCount: integer; + IsHandled: Boolean; +begin + inherited MouseDown(Button, Shift, X, Y); + IsHandled := False; + if FOnMouseDown <> nil then + FOnMouseDown(Self, Button, Shift, X, Y, IsHandled); + if IsHandled then + exit; + + SetFocus; + + LastClickCount := 1; + if ssDouble in Shift then LastClickCount := 2 + else if ssTriple in Shift then LastClickCount := 3 + else if ssQuad in Shift then LastClickCount := 4; + + TempEvent.x := X; + TempEvent.y := Y; + TempEvent.modifiers := getModifiers(Shift); + DeviceToLogical(TempEvent, ScreenScale); + Chromium.SendMouseClickEvent(@TempEvent, GetButton(Button), False, LastClickCount); +end; + +procedure TLazarusOsrBrowserWindow.MouseUp(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + TempEvent : TCefMouseEvent; + LastClickCount: integer; + IsHandled: Boolean; +begin + inherited MouseUp(Button, Shift, X, Y); + IsHandled := False; + if FOnMouseDown <> nil then + FOnMouseDown(Self, Button, Shift, X, Y, IsHandled); + if IsHandled then + exit; + + LastClickCount := 1; + if ssDouble in Shift then LastClickCount := 2 + else if ssTriple in Shift then LastClickCount := 3 + else if ssQuad in Shift then LastClickCount := 4; + + TempEvent.x := X; + TempEvent.y := Y; + TempEvent.modifiers := getModifiers(Shift); + DeviceToLogical(TempEvent, ScreenScale); + Chromium.SendMouseClickEvent(@TempEvent, GetButton(Button), True, LastClickCount); +end; + +procedure TLazarusOsrBrowserWindow.MouseMove(Shift: TShiftState; X, Y: Integer); +var + TempEvent : TCefMouseEvent; +begin + inherited MouseMove(Shift, X, Y); + + TempEvent.x := x; + TempEvent.y := y; + TempEvent.modifiers := getModifiers(Shift); + DeviceToLogical(TempEvent, ScreenScale); + Chromium.SendMouseMoveEvent(@TempEvent, False); +end; + +procedure TLazarusOsrBrowserWindow.MouseEnter; +var + TempEvent : TCefMouseEvent; + TempPoint : TPoint; +begin + inherited MouseEnter; + + TempPoint := ScreenToClient(mouse.CursorPos); + TempEvent.x := TempPoint.x; + TempEvent.y := TempPoint.y; + TempEvent.modifiers := EVENTFLAG_NONE; + DeviceToLogical(TempEvent, ScreenScale); + Chromium.SendMouseMoveEvent(@TempEvent, False); +end; + +procedure TLazarusOsrBrowserWindow.MouseLeave; +var + TempEvent : TCefMouseEvent; + TempPoint : TPoint; + TempTime : integer; +begin + inherited MouseLeave; + + TempPoint := ScreenToClient(mouse.CursorPos); + TempPoint := ScreenToclient(TempPoint); + TempEvent.x := TempPoint.x; + TempEvent.y := TempPoint.y; + {$IFDEF MSWINDOWS} + TempEvent.modifiers := GetCefMouseModifiers; + {$ELSE} + TempEvent.modifiers := EVENTFLAG_NONE; + {$ENDIF} + DeviceToLogical(TempEvent, ScreenScale); + Chromium.SendMouseMoveEvent(@TempEvent, True); +end; + +function TLazarusOsrBrowserWindow.DoMouseWheel(Shift: TShiftState; + WheelDelta: Integer; MousePos: TPoint): Boolean; +var + TempEvent : TCefMouseEvent; +begin + Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos); + + TempEvent.x := MousePos.x; + TempEvent.y := MousePos.y; + TempEvent.modifiers := getModifiers(Shift); + DeviceToLogical(TempEvent, ScreenScale); + {$IFDEF MSWINDOWS} + if CefIsKeyDown(VK_SHIFT) then + Chromium.SendMouseWheelEvent(@TempEvent, WheelDelta, 0) + else + {$ENDIF} + Chromium.SendMouseWheelEvent(@TempEvent, 0, WheelDelta); +end; + +procedure TLazarusOsrBrowserWindow.KeyDown(var Key: Word; Shift: TShiftState); +var + TempKeyEvent : TCefKeyEvent; +begin + FLastKeyDown := Key; + if (Key <> 0) and (Chromium <> nil) then + begin + TempKeyEvent.kind := KEYEVENT_RAWKEYDOWN; + TempKeyEvent.modifiers := getModifiers(Shift); + TempKeyEvent.windows_key_code := Key; + TempKeyEvent.native_key_code := 0; + TempKeyEvent.is_system_key := ord(False); + TempKeyEvent.character := #0; + TempKeyEvent.unmodified_character := #0; + TempKeyEvent.focus_on_editable_field := ord(False); + + Chromium.SendKeyEvent(@TempKeyEvent); + + if (Key in [VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_TAB]) then Key := 0; + end; + + inherited KeyDown(Key, Shift); +end; + +procedure TLazarusOsrBrowserWindow.UTF8KeyPress(var UTF8Key: TUTF8Char); +var + TempKeyEvent : TCefKeyEvent; + TempString : UnicodeString; +begin + if Focused then + begin + TempString := UTF8Decode(UTF8Key); + + if (length(TempString) > 0) then + begin + TempKeyEvent.kind := KEYEVENT_CHAR; + {$IFDEF MSWINDOWS} + TempKeyEvent.modifiers := GetCefKeyboardModifiers(WParam(TempString[1]), 0); + TempKeyEvent.windows_key_code := ord(TempString[1]); + {$ELSE} + TempKeyEvent.modifiers := getKeyModifiers(GetKeyShiftState); + TempKeyEvent.windows_key_code := FLastKeyDown; + {$ENDIF} + TempKeyEvent.native_key_code := 0; + TempKeyEvent.is_system_key := ord(False); + TempKeyEvent.character := TempString[1]; + TempKeyEvent.unmodified_character := TempString[1]; + TempKeyEvent.focus_on_editable_field := ord(False); + + Chromium.SendKeyEvent(@TempKeyEvent); + end; + end; + + inherited UTF8KeyPress(UTF8Key); +end; + +procedure TLazarusOsrBrowserWindow.KeyUp(var Key: Word; Shift: TShiftState); +var + TempKeyEvent : TCefKeyEvent; +begin + if (Key <> 0) and (Chromium <> nil) then + begin + TempKeyEvent.kind := KEYEVENT_KEYUP; + TempKeyEvent.modifiers := getModifiers(Shift); + TempKeyEvent.windows_key_code := Key; + TempKeyEvent.native_key_code := 0; + TempKeyEvent.is_system_key := ord(False); + TempKeyEvent.character := #0; + TempKeyEvent.unmodified_character := #0; + TempKeyEvent.focus_on_editable_field := ord(False); + + Chromium.SendKeyEvent(@TempKeyEvent); + end; + + inherited KeyUp(Key, Shift); +end; + +{$IFDEF MSWINDOWS} +procedure TLazarusOsrBrowserWindow.DoOnIMECancelComposition; +begin + inherited DoOnIMECancelComposition; + Chromium.IMECancelComposition; +end; + +procedure TLazarusOsrBrowserWindow.DoOnIMECommitText(const aText: ustring; + const replacement_range: PCefRange; relative_cursor_pos: integer); +begin + inherited DoOnIMECommitText(aText, replacement_range, relative_cursor_pos); + Chromium.IMECommitText(aText, replacement_range, relative_cursor_pos);; +end; + +procedure TLazarusOsrBrowserWindow.DoOnIMESetComposition(const aText: ustring; + const underlines: TCefCompositionUnderlineDynArray; const replacement_range, + selection_range: TCefRange); +begin + inherited DoOnIMESetComposition(aText, underlines, replacement_range, selection_range); + Chromium.IMESetComposition(aText, underlines, @replacement_range, @selection_range); +end; +{$ENDIF} + +procedure TLazarusOsrBrowserWindow.CaptureChanged; +begin + inherited CaptureChanged; + + if (Chromium <> nil) then Chromium.SendCaptureLostEvent; +end; + +procedure TLazarusOsrBrowserWindow.DoOnCreated(Sender: TObject); +begin + if Assigned(FOnBrowserCreated) then + FOnBrowserCreated(Self); +end; + +procedure TLazarusOsrBrowserWindow.DoOnClosed(Sender: TObject); +begin + if (not(csDestroying in ComponentState)) and + Assigned(FOnBrowserClosed) + then + FOnBrowserClosed(Self); +end; + +constructor TLazarusOsrBrowserWindow.Create(AOwner: TComponent); +begin + FResizeCS := TCriticalSection.Create; + + FDeviceBounds := nil; + FSelectedRange.from := 0; + FSelectedRange.to_ := 0; + + FChromium := TLazChromium.Create(Self); + FChromium.OnBrowserClosed := {$IFDEF FPC}@{$ENDIF}DoOnClosed; + FChromium.OnBrowserCreated := {$IFDEF FPC}@{$ENDIF}DoOnCreated; + + FChromium.OnPaint := {$IFDEF FPC}@{$ENDIF}DoChromiumPaint; + FChromium.OnGetViewRect := {$IFDEF FPC}@{$ENDIF}DoGetChromiumViewRect; + FChromium.OnCursorChange := {$IFDEF FPC}@{$ENDIF}DoGetChromiumCursorChange; + FChromium.OnGetScreenPoint := {$IFDEF FPC}@{$ENDIF}DoGetChromiumGetScreenPoint; + FChromium.OnGetScreenInfo := {$IFDEF FPC}@{$ENDIF}DoGetChromiumGetScreenInfo; + FChromium.OnPopupShow := {$IFDEF FPC}@{$ENDIF}DoGetChromiumPopupShow; + FChromium.OnPopupSize := {$IFDEF FPC}@{$ENDIF}DoGetChromiumPopupSize; + FChromium.OnTooltip := {$IFDEF FPC}@{$ENDIF}DoGetChromiumTooltip; + FChromium.OnBeforePopup := {$IFDEF FPC}@{$ENDIF}DoGetChromiumBeforePopup; + FChromium.OnIMECompositionRangeChanged := @DoGetChromiumIMECompositionRangeChanged; + + inherited Create(AOwner); + CopyOriginalBuffer := true; +end; + +destructor TLazarusOsrBrowserWindow.Destroy; +begin + inherited Destroy; + FreeAndNil(FResizeCS); + if (FDeviceBounds <> nil) then + begin + Finalize(FDeviceBounds); + FDeviceBounds := nil; + end; +end; + +procedure TLazarusOsrBrowserWindow.CloseBrowser(aForceClose: boolean); +begin + FChromium.CloseBrowser(aForceClose); +end; + +procedure TLazarusOsrBrowserWindow.WaitForBrowserClosed; +begin + if not FChromium.HasBrowser then + exit; + FChromium.CloseBrowser(True); + + while FChromium.HasBrowser do begin + Application.ProcessMessages; + if GlobalCEFApp.ExternalMessagePump then + GlobalCEFApp.DoMessageLoopWork; + sleep(5); + end; + + // TODO : sent closed? +end; + +function TLazarusOsrBrowserWindow.IsClosed: boolean; +begin + Result := not FChromium.HasBrowser; +end; + +procedure TLazarusOsrBrowserWindow.LoadURL(aURL: ustring); +begin + FChromium.LoadURL(aURL); +end; + + +{$IFDEF FPC} +procedure Register; +begin +// {$I res/tlazarusosrbrowserwindow.lrs} + RegisterComponents('Chromium', [TLazarusOsrBrowserWindow]); +end; +{$ENDIF} + +end. + diff --git a/source/uceflazarusbrowserwindow.pas b/source/uceflazarusbrowserwindow.pas index aa1b4c66..fa68d1ac 100644 --- a/source/uceflazarusbrowserwindow.pas +++ b/source/uceflazarusbrowserwindow.pas @@ -47,7 +47,8 @@ uses LResources, {$ENDIF} uCEFApplication, uCEFChromiumWindow, uCEFTypes, uCEFInterfaces, uCEFChromium, - uCEFLinkedWinControlBase, Forms, ExtCtrls, Classes, sysutils; + uCEFLinkedWinControlBase, uCEFLazApplication, uCEFBrowserViewComponent, Forms, + ExtCtrls, Controls, Classes, sysutils; type @@ -56,29 +57,80 @@ type only close once that event was finished. *) + { TLazChromium } + + TLazChromium = class(TChromium) + private type + TLazChromiumState = (csNoBrowser, csCreatingBrowser, csHasBrowser, csClosingBrowser, csCloseAfterCreate); + private + FState : TLazChromiumState; + FOnBrowserClosed : TNotifyEvent; + FOnBrowserCreated : TNotifyEvent; + + FLoadUrl, FFrameName : ustring; + function GetIsClosing: Boolean; + + protected + function GetHasBrowser : boolean; reintroduce; + + procedure doOnBeforeClose(const ABrowser: ICefBrowser); override; + procedure doOnAfterCreated(const ABrowser: ICefBrowser); override; + + procedure DoCreated(Data: PtrInt); + procedure DoOnClosed(Data: PtrInt); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + + function CreateBrowser(const aBrowserParent: TWinControl = nil; + const aWindowName: ustring = ''; const aContext: ICefRequestContext = + nil; const aExtraInfo: ICefDictionaryValue = nil): boolean; overload; override; + function CreateBrowser(aParentHandle: TCefWindowHandle; + aParentRect: TRect; const aWindowName: ustring = ''; + const aContext: ICefRequestContext = nil; + const aExtraInfo: ICefDictionaryValue = nil): boolean; overload; override; + procedure CreateBrowser(const aWindowName: ustring); overload; override; + function CreateBrowser(const aURL: ustring; + const aBrowserViewComp: TCEFBrowserViewComponent; + const aContext: ICefRequestContext = nil; + const aExtraInfo: ICefDictionaryValue = nil): boolean; overload; override; + + // CloseBrowser will work, even if the browser is still in creation, and Initialized is still false + procedure CloseBrowser(aForceClose: boolean); reintroduce; + + // LoadURL will work, even if the browser is still in creation, and Initialized is still false + procedure LoadURL(const aURL: ustring; const aFrameName: ustring = ''); overload; + + property HasBrowser: Boolean read GetHasBrowser; // Includes browser in creation + property IsClosing : Boolean read GetIsClosing; + + (* - Events to be called in main thread + - OnBrowserCreated: the parent event may be called when procedure Initialized is still false. + - OnBrowserCreated: may not be called, if the CloseBrowser has already been called + *) + property OnBrowserCreated : TNotifyEvent read FOnBrowserCreated write FOnBrowserCreated; + property OnBrowserClosed : TNotifyEvent read FOnBrowserClosed write FOnBrowserClosed; + end; + TLazarusBrowserWindow = class; { TChromiumWrapper } TChromiumWrapper = class protected type - TWrapperChromiumState = (csNoBrowser, csCreatingBrowser, csHasBrowser, csClosingBrowser, csCloseAfterCreate); TWrapperState = (wsNone, wsWaitingForClose, wsSentCloseEventAfterWait, wsDestroyAfterWait); protected - FChromium : TChromium; - FChromiumState : TWrapperChromiumState; + FChromium : TLazChromium; FWrapperState : TWrapperState; - FBrowserWindow : TLazarusBrowserWindow; - FLoadUrl : ustring; - procedure WebBrowser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); - procedure WebBrowser_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); reintroduce; - procedure WebBrowser_OnBeforeClose(Sender: TObject; const browser: ICefBrowser); reintroduce; + procedure DoOnAfterCreated(Sender: TObject); + procedure DoOnBeforeClose(Sender: TObject); + + procedure BrowserThread_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); {$IFDEF FPC} - procedure WebBrowser_OnGotFocus(Sender: TObject; const browser: ICefBrowser); + procedure BrowserThread_OnGotFocus(Sender: TObject; const browser: ICefBrowser); {$ENDIF} - procedure DoCreated(Data: PtrInt); procedure MaybeDestroy; public @@ -95,6 +147,8 @@ type It is the callers responsibility to take any necessary precaution. *) procedure WaitForBrowserClosed; + + property Chromium: TLazChromium read FChromium; end; { TLazarusBrowserWindow } @@ -112,6 +166,7 @@ type FTimer : TTimer; procedure DoCreateBrowser(Sender: TObject); + procedure DoCreateBrowserAfterContext(Sender: TObject); protected function GetChromium: TChromium; override; procedure DestroyHandle; override; @@ -148,11 +203,29 @@ procedure Register; implementation -{ TChromiumWrapper } +{ TLazChromium } -procedure TChromiumWrapper.WebBrowser_OnAfterCreated(Sender: TObject; - const browser: ICefBrowser); +function TLazChromium.GetIsClosing: Boolean; begin + Result := FState in [csCloseAfterCreate, csClosingBrowser]; +end; + +function TLazChromium.GetHasBrowser: boolean; +begin + Result := (FState <> csNoBrowser) or (inherited GetHasBrowser); +end; + +procedure TLazChromium.doOnBeforeClose(const ABrowser: ICefBrowser); +begin + inherited doOnBeforeClose(ABrowser); + + FState := csNoBrowser; + Application.QueueAsyncCall(@DoOnClosed, 0); +end; + +procedure TLazChromium.doOnAfterCreated(const ABrowser: ICefBrowser); +begin + inherited doOnAfterCreated(ABrowser); (* We may still be in Chromium.CreateBrowserSync In that case initialization will happen after this event, but before the call to CreateBrowser returns @@ -160,7 +233,127 @@ begin Application.QueueAsyncCall(@DoCreated, 0); end; -procedure TChromiumWrapper.WebBrowser_OnClose(Sender: TObject; +procedure TLazChromium.DoCreated(Data: PtrInt); +var + u, f: ustring; +begin + // Any other state, means this is a late async call + case FState of + csCreatingBrowser: begin + FState := csHasBrowser; + if FLoadUrl <> '' then begin + u := FLoadUrl; + f := FFrameName; + LoadURL(u, f); + end; + + if (FOnBrowserCreated <> nil) then + FOnBrowserCreated(Self); + end; + csCloseAfterCreate: begin + FState := csHasBrowser; + CloseBrowser(True); + end; + end; +end; + +procedure TLazChromium.DoOnClosed(Data: PtrInt); +begin + if (FOnBrowserClosed <> nil) then + FOnBrowserClosed(Self); +end; + +constructor TLazChromium.Create(AOwner: TComponent); +begin + FState := csNoBrowser; + inherited Create(AOwner); +end; + +destructor TLazChromium.Destroy; +begin + inherited Destroy; + Application.RemoveAsyncCalls(Self); +end; + +function TLazChromium.CreateBrowser(const aBrowserParent: TWinControl; + const aWindowName: ustring; const aContext: ICefRequestContext; + const aExtraInfo: ICefDictionaryValue): boolean; +begin + FState := csCreatingBrowser; + Result := inherited CreateBrowser(aBrowserParent, aWindowName, aContext, + aExtraInfo); + if Initialized then + DoCreated(0); +end; + +function TLazChromium.CreateBrowser(aParentHandle: TCefWindowHandle; + aParentRect: TRect; const aWindowName: ustring; + const aContext: ICefRequestContext; const aExtraInfo: ICefDictionaryValue): boolean; +begin + FState := csCreatingBrowser; + Result := inherited CreateBrowser(aParentHandle, aParentRect, aWindowName, + aContext, aExtraInfo); + if Initialized then + DoCreated(0); +end; + +procedure TLazChromium.CreateBrowser(const aWindowName: ustring); +begin + FState := csCreatingBrowser; + inherited CreateBrowser(aWindowName); + if Initialized then + DoCreated(0); +end; + +function TLazChromium.CreateBrowser(const aURL: ustring; + const aBrowserViewComp: TCEFBrowserViewComponent; + const aContext: ICefRequestContext; const aExtraInfo: ICefDictionaryValue + ): boolean; +begin + FState := csCreatingBrowser; + Result := inherited CreateBrowser(aURL, aBrowserViewComp, aContext, aExtraInfo); + if Initialized then + DoCreated(0); +end; + +procedure TLazChromium.CloseBrowser(aForceClose: boolean); +begin + if FState = csCreatingBrowser then begin + FState := csCloseAfterCreate; + exit; + end + else + if FState in [csHasBrowser] then + begin + FState := csClosingBrowser; + inherited CloseBrowser(aForceClose); + end; +end; + +procedure TLazChromium.LoadURL(const aURL: ustring; const aFrameName: ustring); +begin + FLoadUrl := ''; + FFrameName := ''; + if FState = csHasBrowser then + begin + inherited LoadURL(aURL, aFrameName); + end + else + begin + FLoadUrl := aURL; + FFrameName := aFrameName; + end; +end; + +{ TChromiumWrapper } + +procedure TChromiumWrapper.DoOnAfterCreated(Sender: TObject); +begin + if (FBrowserWindow <> nil) then + FBrowserWindow.DoOnCreated; +end; + +procedure TChromiumWrapper.BrowserThread_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction); begin (* FBrowserWindow should always be <> nil @@ -173,46 +366,23 @@ begin aAction := cbaClose; end; -procedure TChromiumWrapper.WebBrowser_OnBeforeClose(Sender: TObject; - const browser: ICefBrowser); +procedure TChromiumWrapper.DoOnBeforeClose(Sender: TObject); begin - FChromiumState := csNoBrowser; - if (FBrowserWindow <> nil) then begin if FWrapperState = wsWaitingForClose then FWrapperState := wsSentCloseEventAfterWait else - Application.QueueAsyncCall(@FBrowserWindow.DoOnClosed, 0); + FBrowserWindow.DoOnClosed(0); end; end; -procedure TChromiumWrapper.WebBrowser_OnGotFocus(Sender: TObject; +procedure TChromiumWrapper.BrowserThread_OnGotFocus(Sender: TObject; const browser: ICefBrowser); begin if (FBrowserWindow <> nil) then Application.QueueAsyncCall(@FBrowserWindow.DoOnFocus, 0); end; -procedure TChromiumWrapper.DoCreated(Data: PtrInt); -begin - - // Any other state, means this is a late async call - case FChromiumState of - csCreatingBrowser: begin - FChromiumState := csHasBrowser; - if FLoadUrl <> '' then - LoadURL(FLoadUrl); - - if (FBrowserWindow <> nil) then - FBrowserWindow.DoOnCreated; - end; - csCloseAfterCreate: begin - FChromiumState := csHasBrowser; - CloseBrowser(True); - end; - end; -end; - procedure TChromiumWrapper.MaybeDestroy; begin CloseBrowser(True); @@ -221,25 +391,24 @@ begin if FWrapperState in [wsWaitingForClose, wsSentCloseEventAfterWait] then FWrapperState := wsDestroyAfterWait; - if FChromiumState = csNoBrowser then + if not FChromium.HasBrowser then Destroy; end; constructor TChromiumWrapper.Create(AOwner: TLazarusBrowserWindow); begin FBrowserWindow := AOwner; - FChromiumState := csNoBrowser; FWrapperState := wsNone; if not(csDesigning in AOwner.ComponentState) then begin - FChromium := TChromium.Create(nil); - FChromium.OnClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnClose; - FChromium.OnBeforeClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnBeforeClose; - FChromium.OnAfterCreated := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnAfterCreated; + FChromium := TLazChromium.Create(nil); + FChromium.OnClose := {$IFDEF FPC}@{$ENDIF}BrowserThread_OnClose; + FChromium.OnBrowserClosed := {$IFDEF FPC}@{$ENDIF}DoOnBeforeClose; + FChromium.OnBrowserCreated := {$IFDEF FPC}@{$ENDIF}DoOnAfterCreated; {$IFDEF LINUX} // This is a workaround for the CEF issue #2026. Read below for more info. - FChromium.OnGotFocus := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnGotFocus; + FChromium.OnGotFocus := {$IFDEF FPC}@{$ENDIF}BrowserThread_OnGotFocus; {$ENDIF} end; @@ -248,8 +417,7 @@ end; destructor TChromiumWrapper.Destroy; begin - - if FChromiumState <> csNoBrowser then + if FChromium.HasBrowser then WaitForBrowserClosed; inherited Destroy; @@ -259,56 +427,35 @@ end; function TChromiumWrapper.CreateBrowser: boolean; begin - if FChromiumState <> csNoBrowser then + if FChromium.HasBrowser then exit(False); - FChromiumState := csCreatingBrowser; Result := FChromium.CreateBrowser(FBrowserWindow, ''); - if Result then begin - if FChromium.Initialized then - DoCreated(0); - end - else begin - FChromiumState := csNoBrowser; - end; end; procedure TChromiumWrapper.LoadURL(aURL: ustring); begin - FLoadUrl := ''; - if FChromiumState = csHasBrowser then - FChromium.LoadURL(aURL) - else - FLoadUrl := aURL; + FChromium.LoadURL(aURL); end; procedure TChromiumWrapper.CloseBrowser(aForceClose: boolean); begin - if FChromiumState = csCreatingBrowser then begin - FChromiumState := csCloseAfterCreate; - end - else - if FChromiumState in [csHasBrowser] then - begin - FChromiumState := csClosingBrowser; - FChromium.CloseBrowser(aForceClose); - end; + FChromium.CloseBrowser(aForceClose); end; function TChromiumWrapper.IsClosed: boolean; begin - Result := FChromiumState = csNoBrowser; + Result := not FChromium.HasBrowser; end; procedure TChromiumWrapper.WaitForBrowserClosed; begin - if FChromiumState = csNoBrowser then + if not FChromium.HasBrowser then exit; - if FChromiumState <> csClosingBrowser then - CloseBrowser(True); + FChromium.CloseBrowser(True); FWrapperState := wsWaitingForClose; - while FChromiumState <> csNoBrowser do begin + while FChromium.HasBrowser do begin Application.ProcessMessages; if GlobalCEFApp.ExternalMessagePump then GlobalCEFApp.DoMessageLoopWork; @@ -330,15 +477,15 @@ end; procedure TLazarusBrowserWindow.DoCreateBrowser(Sender: TObject); begin - FTimer.Enabled := False; + if FTimer <> nil then + FTimer.Enabled := False; - case FChromiumWrapper.FChromiumState of - csCreatingBrowser, csHasBrowser: begin + if FChromiumWrapper.Chromium.HasBrowser then begin + if not FChromiumWrapper.Chromium.IsClosing then begin FreeAndNil(FTimer); exit; - end; - csClosingBrowser, csCloseAfterCreate: begin - // need new wrapper // This could prevent an OnBrowserClosed event + end + else begin FChromiumWrapper.MaybeDestroy; FChromiumWrapper := TChromiumWrapper.Create(Self); end; @@ -351,11 +498,26 @@ begin if GlobalCEFApp.ExternalMessagePump then GlobalCEFApp.DoMessageLoopWork; + if FTimer = nil then + FTimer := TTimer.Create(Self); + FTimer.OnTimer := @DoCreateBrowser; FTimer.Interval := 100; FTimer.Enabled := True; end; end; +procedure TLazarusBrowserWindow.DoCreateBrowserAfterContext(Sender: TObject); +begin + {$IFnDEF WINDOWS} + FTimer := TTimer.Create(Self); + FTimer.Interval := 20; + FTimer.OnTimer := @DoCreateBrowser; + FTimer.Enabled := True; + {$ELSE} + DoCreateBrowser(nil); + {$ENDIF} +end; + function TLazarusBrowserWindow.GetChromium: TChromium; begin Result := FChromiumWrapper.FChromium; @@ -368,10 +530,11 @@ begin (* On Windows we can create the browser immediately. But at least on Linux, we need to wait *) - FTimer := TTimer.Create(Self); - FTimer.Interval := 20; - FTimer.OnTimer := @DoCreateBrowser; - FTimer.Enabled := True; + + if GlobalCEFApp is TCefLazApplication then + TCefLazApplication(GlobalCEFApp).AddContextInitializedHandler(@DoCreateBrowserAfterContext) + else + DoCreateBrowserAfterContext(nil); end; end; @@ -381,7 +544,7 @@ begin FreeAndNil(FTimer); if (GlobalCEFApp = nil) or - (FChromiumWrapper.FChromiumState = csNoBrowser) or + (not FChromiumWrapper.Chromium.HasBrowser) or (csDesigning in ComponentState) then begin inherited DestroyHandle;