diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/00-DeleteDCUs.bat b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/00-DeleteDCUs.bat new file mode 100644 index 00000000..160b94f1 --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/00-DeleteDCUs.bat @@ -0,0 +1,23 @@ +del /s /q *. +del /s /q *.o +del /s /q *.dcu +del /s /q *.exe +del /s /q *.res +del /s /q *.rsm +del /s /q *.log +del /s /q *.dsk +del /s /q *.identcache +del /s /q *.stat +del /s /q *.local +del /s /q *.~* +rmdir Win32\Debug +rmdir Win32\Release +rmdir Win32 +rmdir Win64\Debug +rmdir Win64\Release +rmdir Win64 +rmdir Linux64\Debug +rmdir Linux64\Release +rmdir Linux64 +rmdir __history +rmdir __recovery diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dpr b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dpr new file mode 100644 index 00000000..1ce1a79c --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dpr @@ -0,0 +1,80 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2018 Salvador Díaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +program FMXExternalPumpBrowser; + +uses + // FMX initializes GTK in the initialization section of some of its units and + // that means that GTK is already initialized when the code in the DPR is + // executed. + // Chromium has to be initialized in a process with only one thread but GTK + // creates several threads during its initialization. To avoid this problem + // we have to initialize CEF before GTK. + // uCEFLoader *MUST* be the first unit in the DPR file to make sure Chromium + // is initialized before GTK. + // uCEFLoader *MUST NOT* make any reference to any FMX unit to keep the right + // initalization order. + // Read the answer to this question for more more information : + // https://stackoverflow.com/questions/52103407/changing-the-initialization-order-of-the-unit-in-delphi + uCEFLoader in 'uCEFLoader.pas', + System.StartUpCopy, + FMX.Forms, + uCEFApplication, + uCEFWorkScheduler, + uFMXExternalPumpBrowser in 'uFMXExternalPumpBrowser.pas' {FMXExternalPumpBrowserFrm}; + +{$R *.res} + +begin + CreateGlobalCEFApp; + + if GlobalCEFApp.StartMainProcess then + begin + {$IFDEF LINUX}InitializeGTK;{$ENDIF} + Application.Initialize; + Application.CreateForm(TFMXExternalPumpBrowserFrm, FMXExternalPumpBrowserFrm); + Application.Run; + + // The form needs to be destroyed *BEFORE* stopping the work scheduler. + FMXExternalPumpBrowserFrm.Free; + + GlobalCEFWorkScheduler.StopScheduler; + end; + + DestroyGlobalCEFApp; + DestroyGlobalCEFWorkScheduler; +end. diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dproj b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dproj new file mode 100644 index 00000000..371cdd00 --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/FMXExternalPumpBrowser.dproj @@ -0,0 +1,1317 @@ + + + {BE24D13B-2634-4064-8746-AB331419C5FA} + 19.2 + FMX + FMXExternalPumpBrowser.dpr + True + Debug + Linux64 + 131 + Application + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + ..\..\..\bin + false + false + false + false + false + RESTComponents;emsclientfiredac;FireDAC;FireDACSqliteDriver;soaprtl;FireDACIBDriver;soapmidas;FireDACCommon;emsclient;RESTBackendComponents;soapserver;FireDACCommonDriver;CloudService;inet;$(DCC_UsePackage) + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\delphi_PROJECTICNS.icns + FMXExternalPumpBrowser + 3082 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + $(FrameworkType);$(DCC_Define) + + + $(fmxlinux)\Lib\$(ProductVersion)\$(Config);$(DCC_UnitSearchPath) + + + DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;vclFireDAC;FireDACDb2Driver;DataSnapFireDAC;svnui;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;Componentes_UI;vcldb;bindcompfmx;svn;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;CEF4Delphi;DbxCommonDriver;IndyProtocols240;IndySystem240;fmx;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;IndyCore240;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;bindcompvcl;DataSnapConnectors;VCLRESTComponents;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;DataSnapClient;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + 1033 + $(BDS)\bin\default_app.manifest + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;vclFireDAC;FireDACDb2Driver;DataSnapFireDAC;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;DbxCommonDriver;IndyProtocols240;IndySystem240;fmx;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;IndyCore240;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;bindcompvcl;DataSnapConnectors;VCLRESTComponents;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;DataSnapClient;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + 1033 + $(BDS)\bin\default_app.manifest + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + 1033 + PerMonitor + true + + + true + PerMonitorV2 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + PerMonitor + true + 1033 + + + true + PerMonitorV2 + + + + MainSource + + + +
FMXExternalPumpBrowserFrm
+
+ + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Application + + + + FMXExternalPumpBrowser.dpr + + + IP Abstraction Indy Implementation Design Time + DBExpress Enterprise Data Explorer Integration + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + FMXExternalPumpBrowser.exe + true + + + + + .\ + FMXExternalPumpBrowser + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + 1 + + + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen + 64 + + + ..\$(PROJECTNAME).launchscreen + 64 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + Contents + 1 + + + Contents + 1 + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + True + True + + + 12 + + + + +
diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/cef.inc b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/cef.inc new file mode 100644 index 00000000..c8ce967e --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/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 + * 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/Delphi_FMX_Linux/FMXExternalPumpBrowser/uCEFLoader.pas b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uCEFLoader.pas new file mode 100644 index 00000000..4970a380 --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uCEFLoader.pas @@ -0,0 +1,100 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2021 Salvador Diaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +unit uCEFLoader; + +interface + +{$IFDEF LINUX} +uses + FMUX.Config; + +procedure InitializeGTK; +{$ENDIF} + +implementation + +{$IFDEF LINUX} +uses + System.SysUtils, System.IOUtils; + +function GetLibDirName: string; +begin + {$IFNDEF FMXLINUX_EXTERNAL_RUNTIME} + Result := TPath.Combine(TPath.GetHomePath, '.fmxlinux'); + {$ELSE} + Result := ExtractFilePath(ParamStr(0)); + {$ENDIF} +end; + +function GetLibFileName: string; +const + LibName = 'libfmux'; + LibVer = '1.60'; +begin + {$IFDEF FMXLINUX_EXTERNAL_RUNTIME} + Result := TPath.Combine(GetLibDirName, LibName + '.so'); + {$ELSE} + {$IFDEF TRIAL} + Result := TPath.Combine(GetLibDirName, LibName + '-Trial-' + LibVer + '.so'); + {$ELSEIF GETIT} + Result := TPath.Combine(GetLibDirName, LibName + '-Getit' + LibVer + '.so'); + {$ELSE} + Result := TPath.Combine(GetLibDirName, LibName + '-' + LibVer + '.so'); + {$ENDIF} + {$ENDIF} +end; + +procedure InitializeGTK; +var + FmuxInit: procedure (Flags: Integer); cdecl; + TempHandle : NativeInt; +begin + TempHandle := LoadLibrary(PChar(GetLibFileName)); + + if (TempHandle <> 0) then + begin + FmuxInit := GetProcAddress(TempHandle, 'FmuxInit'); + FmuxInit(0); + end; +end; + +initialization + DoNotCallFmuxInit := True; +{$ENDIF} + +end. diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx new file mode 100644 index 00000000..465c3fde --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx @@ -0,0 +1,141 @@ +object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm + Left = 0 + Top = 0 + Caption = 'Initializing browser. Please wait...' + ClientHeight = 633 + ClientWidth = 800 + Position = ScreenCenter + FormFactor.Width = 320 + FormFactor.Height = 480 + FormFactor.Devices = [Desktop] + OnActivate = FormActivate + OnCreate = FormCreate + OnCloseQuery = FormCloseQuery + OnDestroy = FormDestroy + OnShow = FormShow + OnHide = FormHide + DesignerMasterStyle = 0 + object AddressPnl: TPanel + Align = Top + Padding.Left = 5.000000000000000000 + Padding.Top = 5.000000000000000000 + Padding.Right = 5.000000000000000000 + Padding.Bottom = 5.000000000000000000 + Size.Width = 800.000000000000000000 + Size.Height = 33.000000000000000000 + Size.PlatformDefault = False + TabOrder = 1 + object AddressEdt: TEdit + Touch.InteractiveGestures = [LongTap, DoubleTap] + Align = Client + TabOrder = 0 + Text = 'https://www.google.com' + Size.Width = 709.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + OnEnter = AddressEdtEnter + end + object Layout1: TLayout + Align = Right + Padding.Left = 5.000000000000000000 + Position.X = 714.000000000000000000 + Position.Y = 5.000000000000000000 + Size.Width = 81.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + TabOrder = 2 + object GoBtn: TButton + Align = Left + Position.X = 5.000000000000000000 + Size.Width = 36.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + TabOrder = 0 + Text = 'Go' + OnClick = GoBtnClick + OnEnter = GoBtnEnter + end + object SnapshotBtn: TButton + Align = Right + StyledSettings = [Style, FontColor] + Position.X = 45.000000000000000000 + Size.Width = 36.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + TabOrder = 1 + Text = #181 + TextSettings.Font.Family = 'Webdings' + TextSettings.Font.Size = 32.000000000000000000 + OnClick = SnapshotBtnClick + OnEnter = SnapshotBtnEnter + end + end + end + object Timer1: TTimer + Enabled = False + Interval = 300 + OnTimer = Timer1Timer + Left = 40 + Top = 137 + end + object SaveDialog1: TSaveDialog + DefaultExt = 'bmp' + Filter = 'Bitmap files (*.bmp)|*.BMP' + Title = 'Save snapshot' + Left = 40 + Top = 201 + end + object Panel1: TFMXBufferPanel + Align = Client + TabOrder = 0 + CanFocus = True + Size.Width = 800.000000000000000000 + Size.Height = 578.000000000000000000 + Size.PlatformDefault = False + OnEnter = Panel1Enter + OnExit = Panel1Exit + OnResize = Panel1Resize + OnClick = Panel1Click + OnMouseDown = Panel1MouseDown + OnMouseMove = Panel1MouseMove + OnMouseUp = Panel1MouseUp + OnMouseLeave = Panel1MouseLeave + OnMouseWheel = Panel1MouseWheel + OnKeyDown = Panel1KeyDown + OnDialogKey = Panel1DialogKey + end + object StatusBar1: TStatusBar + Position.Y = 611.000000000000000000 + ShowSizeGrip = True + Size.Width = 800.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + TabOrder = 5 + object StatusLbl: TLabel + Align = Client + Margins.Left = 5.000000000000000000 + Margins.Right = 50.000000000000000000 + Size.Width = 745.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + TabOrder = 0 + end + end + object chrmosr: TFMXChromium + OnLoadError = chrmosrLoadError + OnLoadingStateChange = chrmosrLoadingStateChange + OnTooltip = chrmosrTooltip + OnCursorChange = chrmosrCursorChange + OnBeforePopup = chrmosrBeforePopup + OnAfterCreated = chrmosrAfterCreated + OnBeforeClose = chrmosrBeforeClose + OnGetViewRect = chrmosrGetViewRect + OnGetScreenPoint = chrmosrGetScreenPoint + OnGetScreenInfo = chrmosrGetScreenInfo + OnPopupShow = chrmosrPopupShow + OnPopupSize = chrmosrPopupSize + OnPaint = chrmosrPaint + Left = 40 + Top = 73 + end +end diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas new file mode 100644 index 00000000..f7f6d9ad --- /dev/null +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas @@ -0,0 +1,915 @@ +// ************************************************************************ +// ***************************** CEF4Delphi ******************************* +// ************************************************************************ +// +// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based +// browser in Delphi applications. +// +// The original license of DCEF3 still applies to CEF4Delphi. +// +// For more information about CEF4Delphi visit : +// https://www.briskbard.com/index.php?lang=en&pageid=cef +// +// Copyright © 2021 Salvador Diaz Fau. All rights reserved. +// +// ************************************************************************ +// ************ vvvv Original license and comments below vvvv ************* +// ************************************************************************ +(* + * Delphi Chromium Embedded 3 + * + * Usage allowed under the restrictions of the Lesser GNU General Public License + * or alternatively the restrictions of the Mozilla Public License 1.1 + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * + * Unit owner : Henri Gourvest + * Web site : http://www.progdigy.com + * Repository : http://code.google.com/p/delphichromiumembedded/ + * Group : http://groups.google.com/group/delphichromiumembedded + * + * Embarcadero Technologies, Inc is not permitted to use or redistribute + * this source code without explicit permission. + * + *) + +unit uFMXExternalPumpBrowser; + +{$I cef.inc} + +interface + +uses + {$IFDEF MSWINDOWS}WinApi.Windows,{$ENDIF} + System.Types, System.UITypes, System.Classes, System.SyncObjs, + FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Edit, FMX.StdCtrls, + FMX.Controls.Presentation, FMX.Graphics, FMX.Layouts, FMX.DialogService, + uCEFFMXChromium, uCEFFMXBufferPanel, uCEFFMXWorkScheduler, + uCEFInterfaces, uCEFTypes, uCEFConstants, uCEFChromiumCore; + +type + TFMXExternalPumpBrowserFrm = class(TForm) + AddressPnl: TPanel; + AddressEdt: TEdit; + chrmosr: TFMXChromium; + Timer1: TTimer; + SaveDialog1: TSaveDialog; + Panel1: TFMXBufferPanel; + Layout1: TLayout; + GoBtn: TButton; + SnapshotBtn: TButton; + StatusBar1: TStatusBar; + StatusLbl: TLabel; + + procedure GoBtnClick(Sender: TObject); + procedure GoBtnEnter(Sender: TObject); + + procedure Panel1Enter(Sender: TObject); + procedure Panel1Exit(Sender: TObject); + procedure Panel1Resize(Sender: TObject); + procedure Panel1Click(Sender: TObject); + procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); + procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); + procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); + procedure Panel1MouseLeave(Sender: TObject); + procedure Panel1MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); + procedure Panel1KeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); + procedure Panel1DialogKey(Sender: TObject; var Key: Word; Shift: TShiftState); + + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormActivate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormHide(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + + procedure chrmosrPaint(Sender: TObject; const browser: ICefBrowser; type_: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer); + procedure chrmosrGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); + procedure chrmosrGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); + procedure chrmosrGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean); + procedure chrmosrPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean); + procedure chrmosrPopupSize(Sender: TObject; const browser: ICefBrowser; const rect: PCefRect); + procedure chrmosrBeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure chrmosrTooltip(Sender: TObject; const browser: ICefBrowser; var text: ustring; out Result: Boolean); + procedure chrmosrBeforePopup(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 chrmosrAfterCreated(Sender: TObject; const browser: ICefBrowser); + procedure chrmosrCursorChange(Sender: TObject; const browser: ICefBrowser; cursor_: TCefCursorHandle; cursorType: TCefCursorType; const customCursorInfo: PCefCursorInfo; var aResult: Boolean); + procedure chrmosrLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean); + procedure chrmosrLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); + + procedure Timer1Timer(Sender: TObject); + procedure AddressEdtEnter(Sender: TObject); + + procedure SnapshotBtnClick(Sender: TObject); + procedure SnapshotBtnEnter(Sender: TObject); + + protected + FPopUpBitmap : TBitmap; + FPopUpRect : TRect; + FShowPopUp : boolean; + FResizing : boolean; + FPendingResize : boolean; + FCanClose : boolean; + FClosing : boolean; + FResizeCS : TCriticalSection; + {$IFDEF DELPHI17_UP} + FMouseWheelService : IFMXMouseService; + {$ENDIF} + + procedure LoadURL; + function getModifiers(Shift: TShiftState): TCefEventFlags; + function GetButton(Button: TMouseButton): TCefMouseButtonType; + function GetMousePosition(var aPoint : TPointF) : boolean; + + public + procedure DoResize; + procedure NotifyMoveOrResizeStarted; + procedure SendCaptureLostEvent; + procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override; + procedure SendCEFKeyEvent(const aCefEvent : TCefKeyEvent); + end; + +var + FMXExternalPumpBrowserFrm : TFMXExternalPumpBrowserFrm; + +procedure CreateGlobalCEFApp; + +// *************************** +// ********* WARNING ********* +// *************************** +// This is a demo for LINUX and it's in BETA state. +// It still has several features unimplemented!!! + + + +// This is a simple browser using FireMonkey components in OSR mode (off-screen rendering) +// and a external message pump. + +// All FMX applications using CEF4Delphi should add the $(FrameworkType) conditional define +// in the project options to avoid duplicated resources. +// This demo has that define in the menu option : +// Project -> Options -> Building -> Delphi compiler -> Conditional defines (All configurations) + +// This is the destruction sequence in OSR mode : +// 1- FormCloseQuery sets CanClose to the initial FCanClose value (False) and +// calls chrmosr.CloseBrowser(True). +// 2- chrmosr.CloseBrowser(True) will trigger chrmosr.OnClose and the default +// implementation will destroy the internal browser immediately, which will +// trigger the chrmosr.OnBeforeClose event. +// 3- chrmosr.OnBeforeClose sets FCanClose to True and enables the timer to +// close the form after a few milliseconds. + +implementation + +{$R *.fmx} + +uses + System.SysUtils, System.Math, System.IOUtils, + FMX.Platform, {$IFDEF LINUX}FMX.Platform.Linux,{$ENDIF} + uCEFApplication, uCEFWorkScheduler, uCEFMiscFunctions, uCEFLinuxTypes, + uCEFLinuxConstants, uCEFLinuxFunctions; + +{$IFDEF LINUX} +function GTKKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer) : GBoolean; cdecl; +var + TempCefEvent : TCefKeyEvent; +begin + if FMXExternalPumpBrowserFrm.Panel1.IsFocused then + begin + GdkEventKeyToCEFKeyEvent(Event, TempCefEvent); + + if (Event^._type = GDK_KEY_PRESS) then + begin + TempCefEvent.kind := KEYEVENT_RAWKEYDOWN; + FMXExternalPumpBrowserFrm.SendCEFKeyEvent(TempCefEvent); + TempCefEvent.kind := KEYEVENT_CHAR; + FMXExternalPumpBrowserFrm.SendCEFKeyEvent(TempCefEvent); + end + else + begin + TempCefEvent.kind := KEYEVENT_KEYUP; + FMXExternalPumpBrowserFrm.SendCEFKeyEvent(TempCefEvent); + end; + end; + + Result := True; +end; + +procedure ConnectKeyPressReleaseEvents(const aWidget : PGtkWidget); +begin + g_signal_connect(aWidget, 'key-press-event', TGCallback(@GTKKeyPress), nil); + g_signal_connect(aWidget, 'key-release-event', TGCallback(@GTKKeyPress), nil); +end; +{$ENDIF} + +procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); +begin + if (GlobalCEFWorkScheduler <> nil) then + GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); +end; + +procedure CreateGlobalCEFApp; +begin + // 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. + // We use CreateDelayed in order to have a single thread in the process while + // CEF is initialized. + GlobalCEFWorkScheduler := TCEFWorkScheduler.CreateDelayed; + + GlobalCEFApp := TCefApplication.Create; + GlobalCEFApp.WindowlessRenderingEnabled := True; + GlobalCEFApp.EnableHighDPISupport := True; + GlobalCEFApp.ExternalMessagePump := True; + GlobalCEFApp.MultiThreadedMessageLoop := False; + GlobalCEFApp.DisableZygote := True; + GlobalCEFApp.OnScheduleMessagePumpWork := GlobalCEFApp_OnScheduleMessagePumpWork; + + // You can deploy the CEF binaries with the executable or you can set these + // properties to use the CEF binaries in your home directory + GlobalCEFApp.FrameworkDirPath := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'cef'; + GlobalCEFApp.ResourcesDirPath := GlobalCEFApp.FrameworkDirPath; + GlobalCEFApp.LocalesDirPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'locales'; + + // This is a workaround to fix a Chromium initialization crash. + // The current FMX solution to initialize CEF with a loader unit + // creates a race condition with the media key controller in Chromium. + GlobalCEFApp.DisableFeatures := 'HardwareMediaKeyHandling'; +end; + +procedure TFMXExternalPumpBrowserFrm.FormActivate(Sender: TObject); +var + TempError : string; +begin + if not(FCanClose) and ((GlobalCEFApp = nil) or not(GlobalCEFApp.LibLoaded)) then + begin + FCanClose := True; + FClosing := True; + TempError := 'CEF binaries missing!'; + + if (GlobalCEFApp = nil) then + TempError := TempError + CRLF + CRLF + 'GlobalCEFApp was not created!' + else + if (length(GlobalCEFApp.MissingLibFiles) > 0) then + TempError := TempError + CRLF + CRLF + + 'The missing files are :' + CRLF + + trim(GlobalCEFApp.MissingLibFiles); + + TDialogService.MessageDialog(TempError, TMsgDlgType.mtError, + [TMsgDlgBtn.mbOK], TMsgDlgBtn.mbOK, 0, + procedure(const AResult: TModalResult) + begin + Timer1.Enabled := True; + end); + end + else + if not(chrmosr.Initialized) then + begin + {$IFDEF LINUX} + ConnectKeyPressReleaseEvents(TLinuxWindowHandle(Handle).NativeHandle); + {$ENDIF} + + // opaque white background color + chrmosr.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF); + + if not(chrmosr.CreateBrowser) then Timer1.Enabled := True; + end; +end; + +procedure TFMXExternalPumpBrowserFrm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + CanClose := FCanClose; + + if not(FClosing) then + begin + FClosing := True; + Visible := False; + AddressPnl.Enabled := False; + chrmosr.CloseBrowser(True); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.FormCreate(Sender: TObject); +begin + FPopUpBitmap := nil; + FPopUpRect := rect(0, 0, 0, 0); + FShowPopUp := False; + FResizing := False; + FPendingResize := False; + FCanClose := False; + FClosing := False; + FResizeCS := TCriticalSection.Create; + + chrmosr.DefaultURL := AddressEdt.Text; + + {$IFDEF DELPHI17_UP} + if TPlatformServices.Current.SupportsPlatformService(IFMXMouseService) then + FMouseWheelService := TPlatformServices.Current.GetPlatformService(IFMXMouseService) as IFMXMouseService; + {$ENDIF} +end; + +procedure TFMXExternalPumpBrowserFrm.FormDestroy(Sender: TObject); +begin + FResizeCS.Free; + if (FPopUpBitmap <> nil) then FreeAndNil(FPopUpBitmap); +end; + +procedure TFMXExternalPumpBrowserFrm.FormHide(Sender: TObject); +begin + chrmosr.SendFocusEvent(False); + chrmosr.WasHidden(True); +end; + +procedure TFMXExternalPumpBrowserFrm.FormShow(Sender: TObject); +begin + chrmosr.WasHidden(False); + chrmosr.SendFocusEvent(True); +end; + +procedure TFMXExternalPumpBrowserFrm.GoBtnClick(Sender: TObject); +begin + LoadURL; +end; + +procedure TFMXExternalPumpBrowserFrm.LoadURL; +begin + FResizeCS.Acquire; + FResizing := False; + FPendingResize := False; + FResizeCS.Release; + + chrmosr.LoadURL(AddressEdt.Text); +end; + +procedure TFMXExternalPumpBrowserFrm.GoBtnEnter(Sender: TObject); +begin + chrmosr.SendFocusEvent(False); +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1Click(Sender: TObject); +begin + Panel1.SetFocus; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1DialogKey(Sender: TObject; + var Key: Word; Shift: TShiftState); +begin + if (Key = vkTab) then Key := 0; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1Enter(Sender: TObject); +begin + chrmosr.SendFocusEvent(True); +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1Exit(Sender: TObject); +begin + chrmosr.SendFocusEvent(False); +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1KeyDown( Sender : TObject; + var Key : Word; + var KeyChar : Char; + Shift : TShiftState); +var + TempKeyEvent : TCefKeyEvent; +begin + if not(Panel1.IsFocused) then exit; + + if (Key = 0) and (KeyChar <> #0) then + begin + TempKeyEvent.kind := KEYEVENT_CHAR; + TempKeyEvent.modifiers := getModifiers(Shift); + TempKeyEvent.windows_key_code := ord(KeyChar); + 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); + + chrmosr.SendKeyEvent(@TempKeyEvent); + end + else + if (Key <> 0) and (KeyChar = #0) and + (Key in [vkLeft, vkRight, vkUp, vkDown]) then + Key := 0; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1MouseDown(Sender : TObject; + Button : TMouseButton; + Shift : TShiftState; + X, Y : Single); +var + TempEvent : TCefMouseEvent; +begin + if not(ssTouch in Shift) then + begin + Panel1.SetFocus; + + TempEvent.x := round(X); + TempEvent.y := round(Y); + TempEvent.modifiers := getModifiers(Shift); + chrmosr.SendMouseClickEvent(@TempEvent, GetButton(Button), False, 1); + end; +end; + +function TFMXExternalPumpBrowserFrm.GetMousePosition(var aPoint : TPointF) : boolean; +begin + if (FMouseWheelService <> nil) then + begin + aPoint := FMouseWheelService.GetMousePos; + Result := True; + end + else + begin + aPoint.x := 0; + aPoint.y := 0; + Result := False; + end; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1MouseLeave(Sender: TObject); +var + TempEvent : TCefMouseEvent; + TempPoint : TPointF; +begin + if GetMousePosition(TempPoint) then + begin + TempPoint := Panel1.ScreenToClient(TempPoint); + + TempEvent.x := round(TempPoint.x); + TempEvent.y := round(TempPoint.y); + TempEvent.modifiers := EVENTFLAG_NONE; + chrmosr.SendMouseMoveEvent(@TempEvent, True); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1MouseMove(Sender : TObject; + Shift : TShiftState; + X, Y : Single); +var + TempEvent : TCefMouseEvent; +begin + if not(ssTouch in Shift) then + begin + TempEvent.x := round(x); + TempEvent.y := round(y); + TempEvent.modifiers := getModifiers(Shift); + chrmosr.SendMouseMoveEvent(@TempEvent, False); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1MouseUp(Sender : TObject; + Button : TMouseButton; + Shift : TShiftState; + X, Y : Single); +var + TempEvent : TCefMouseEvent; +begin + if not(ssTouch in Shift) then + begin + TempEvent.x := round(X); + TempEvent.y := round(Y); + TempEvent.modifiers := getModifiers(Shift); + chrmosr.SendMouseClickEvent(@TempEvent, GetButton(Button), True, 1); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1MouseWheel( Sender : TObject; + Shift : TShiftState; + WheelDelta : Integer; + var Handled : Boolean); +var + TempEvent : TCefMouseEvent; + TempPoint : TPointF; +begin + if Panel1.IsFocused and GetMousePosition(TempPoint) then + begin + TempPoint := Panel1.ScreenToClient(TempPoint); + TempEvent.x := round(TempPoint.x); + TempEvent.y := round(TempPoint.y); + TempEvent.modifiers := getModifiers(Shift); + chrmosr.SendMouseWheelEvent(@TempEvent, 0, WheelDelta); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.Panel1Resize(Sender: TObject); +begin + DoResize; +end; + +procedure TFMXExternalPumpBrowserFrm.Timer1Timer(Sender: TObject); +begin + Timer1.Enabled := False; + + if FClosing then + close + else + if not(chrmosr.CreateBrowser) and not(chrmosr.Initialized) then + Timer1.Enabled := True; +end; + +procedure TFMXExternalPumpBrowserFrm.AddressEdtEnter(Sender: TObject); +begin + chrmosr.SendFocusEvent(False); +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrAfterCreated(Sender: TObject; const browser: ICefBrowser); +begin + // Now the browser is fully initialized we can enable the UI. + Caption := 'FMX External Pump Browser'; + AddressPnl.Enabled := True; + Panel1.SetFocus; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrBeforeClose(Sender: TObject; const browser: ICefBrowser); +begin + FCanClose := True; + // We need to close the form outside this event so we use the timer + Timer1.Enabled := True; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrBeforePopup( Sender : TObject; + const browser : ICefBrowser; + const frame : ICefFrame; + const targetUrl : ustring; + const 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 TFMXExternalPumpBrowserFrm.chrmosrCursorChange( Sender : TObject; + const browser : ICefBrowser; + cursor_ : TCefCursorHandle; + cursorType : TCefCursorType; + const customCursorInfo : PCefCursorInfo; + var aResult : Boolean); +begin + Panel1.Cursor := CefCursorToWindowsCursor(cursorType); + aResult := True; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrGetScreenInfo( Sender : TObject; + const browser : ICefBrowser; + var screenInfo : TCefScreenInfo; + out Result : Boolean); +var + TempRect : TCEFRect; +begin + TempRect.x := 0; + TempRect.y := 0; + TempRect.width := round(Panel1.Width); + TempRect.height := round(Panel1.Height); + + screenInfo.device_scale_factor := Panel1.ScreenScale; + screenInfo.depth := 0; + screenInfo.depth_per_component := 0; + screenInfo.is_monochrome := Ord(False); + screenInfo.rect := TempRect; + screenInfo.available_rect := TempRect; + + Result := True; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrGetScreenPoint( Sender : TObject; + const browser : ICefBrowser; + viewX : Integer; + viewY : Integer; + var screenX : Integer; + var screenY : Integer; + out Result : Boolean); +var + TempScreenPt, TempViewPt : TPoint; +begin + // TFMXBufferPanel.ClientToScreen applies the scale factor. No need to call LogicalToDevice to set TempViewPt. + TempViewPt.x := viewX; + TempViewPt.y := viewY; + TempScreenPt := Panel1.ClientToScreen(TempViewPt); + screenX := TempScreenPt.x; + screenY := TempScreenPt.y; + Result := True; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrGetViewRect( Sender : TObject; + const browser : ICefBrowser; + var rect : TCefRect); +begin + rect.x := 0; + rect.y := 0; + rect.width := round(Panel1.Width); + rect.height := round(Panel1.Height); +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrLoadError(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; + const errorText, failedUrl: ustring); +var + TempString : ustring; +begin + if (errorCode = ERR_ABORTED) then exit; + + TempString := '' + + '

Failed to load URL ' + failedUrl + + ' with error ' + errorText + + ' (' + inttostr(errorCode) + ').

'; + + chrmosr.LoadString(TempString, frame); +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrLoadingStateChange(Sender: TObject; + const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean); +begin + if isLoading then + StatusLbl.Text := 'Loading...' + else + StatusLbl.Text := ''; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrPaint( Sender : TObject; + const browser : ICefBrowser; + type_ : TCefPaintElementType; + dirtyRectsCount : NativeUInt; + const dirtyRects : PCefRectArray; + const buffer : Pointer; + width : Integer; + height : Integer); +var + src, dst: PByte; + i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, TempWidth, TempHeight : Integer; + n : NativeUInt; + {$IFNDEF DELPHI17_UP} + TempScanlineSize, DstStride : integer; + {$ENDIF} + TempBufferBits : Pointer; + TempForcedResize : boolean; + TempBitmapData : TBitmapData; + TempBitmap : TBitmap; + TempSrcRect, TempDstRect : TRectF; +begin + try + FResizeCS.Acquire; + TempForcedResize := False; + + if Panel1.BeginBufferDraw then + try + if (type_ = PET_POPUP) then + begin + if (FPopUpBitmap = nil) or + (width <> FPopUpBitmap.Width) or + (height <> FPopUpBitmap.Height) then + begin + if (FPopUpBitmap <> nil) then FPopUpBitmap.Free; + + FPopUpBitmap := TBitmap.Create(width, height); + {$IFDEF DELPHI17_UP} + FPopUpBitmap.BitmapScale := Panel1.ScreenScale; + {$ENDIF} + end; + + TempWidth := FPopUpBitmap.Width; + TempHeight := FPopUpBitmap.Height; + {$IFNDEF DELPHI17_UP} + TempScanlineSize := FPopUpBitmap.BytesPerLine; + {$ENDIF} + TempBitmap := FPopUpBitmap; + end + else + begin + TempForcedResize := Panel1.UpdateBufferDimensions(Width, Height) or not(Panel1.BufferIsResized(False)); + TempWidth := Panel1.BufferWidth; + TempHeight := Panel1.BufferHeight; + {$IFNDEF DELPHI17_UP} + TempScanlineSize := Panel1.ScanlineSize; + {$ENDIF} + TempBitmap := Panel1.Buffer; + end; + + + if (TempBitmap <> nil) {$IFDEF DELPHI17_UP}and TempBitmap.Map(TMapAccess.ReadWrite, TempBitmapData){$ENDIF} then + begin + try + {$IFNDEF DELPHI17_UP} + TempBufferBits := TempBitmapData.StartLine; + DstStride := TempScanlineSize; + {$ENDIF} + SrcStride := Width * 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) * SizeOf(TRGBQuad); + + if (TempLineSize > 0) then + begin + TempSrcOffset := ((dirtyRects[n].y * Width) + dirtyRects[n].x) * SizeOf(TRGBQuad); + + {$IFDEF DELPHI17_UP} + TempDstOffset := (dirtyRects[n].x * SizeOf(TRGBQuad)); + {$ELSE} + TempDstOffset := (dirtyRects[n].y * TempScanlineSize) + (dirtyRects[n].x * SizeOf(TRGBQuad)); + {$ENDIF} + + src := @PByte(buffer)[TempSrcOffset]; + {$IFNDEF DELPHI17_UP} + dst := @PByte(TempBufferBits)[TempDstOffset]; + {$ENDIF} + + i := 0; + j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y); + + while (i < j) do + begin + {$IFDEF DELPHI17_UP} + TempBufferBits := TempBitmapData.GetScanline(dirtyRects[n].y + i); + dst := @PByte(TempBufferBits)[TempDstOffset]; + {$ENDIF} + + Move(src^, dst^, TempLineSize); + + {$IFNDEF DELPHI17_UP} + inc(dst, DstStride); + {$ENDIF} + inc(src, SrcStride); + inc(i); + end; + end; + end; + + inc(n); + end; + + Panel1.InvalidatePanel; + finally + {$IFDEF DELPHI17_UP} + TempBitmap.Unmap(TempBitmapData); + {$ENDIF} + end; + + if FShowPopup and (FPopUpBitmap <> nil) then + begin + TempSrcRect := RectF(0, 0, + min(FPopUpRect.Width, FPopUpBitmap.Width), + min(FPopUpRect.Height, FPopUpBitmap.Height)); + + TempDstRect.Left := FPopUpRect.Left / GlobalCEFApp.DeviceScaleFactor; + TempDstRect.Top := FPopUpRect.Top / GlobalCEFApp.DeviceScaleFactor; + TempDstRect.Right := TempDstRect.Left + (TempSrcRect.Width / GlobalCEFApp.DeviceScaleFactor); + TempDstRect.Bottom := TempDstRect.Top + (TempSrcRect.Height / GlobalCEFApp.DeviceScaleFactor); + + Panel1.BufferDraw(FPopUpBitmap, TempSrcRect, TempDstRect); + end; + end; + + if (type_ = PET_VIEW) then + begin + if TempForcedResize or FPendingResize then + TThread.Queue(nil, DoResize); + + FResizing := False; + FPendingResize := False; + end; + finally + Panel1.EndBufferDraw; + end; + finally + FResizeCS.Release; + end; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrPopupShow( Sender : TObject; + const browser : ICefBrowser; + show : Boolean); +begin + if show then + FShowPopUp := True + else + begin + FShowPopUp := False; + FPopUpRect := rect(0, 0, 0, 0); + + chrmosr.Invalidate(PET_VIEW); + end; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrPopupSize( Sender : TObject; + const browser : ICefBrowser; + const rect : PCefRect); +begin + if (GlobalCEFApp <> nil) then + begin + LogicalToDevice(rect^, GlobalCEFApp.DeviceScaleFactor); + + FPopUpRect.Left := rect.x; + FPopUpRect.Top := rect.y; + FPopUpRect.Right := rect.x + rect.width - 1; + FPopUpRect.Bottom := rect.y + rect.height - 1; + end; +end; + +procedure TFMXExternalPumpBrowserFrm.chrmosrTooltip( Sender : TObject; + const browser : ICefBrowser; + var text : ustring; + out Result : Boolean); +begin + Panel1.Hint := text; + Panel1.ShowHint := (length(text) > 0); + Result := True; +end; + +procedure TFMXExternalPumpBrowserFrm.DoResize; +begin + try + if (FResizeCS <> nil) then + begin + FResizeCS.Acquire; + + if FResizing then + FPendingResize := True + else + if Panel1.BufferIsResized then + chrmosr.Invalidate(PET_VIEW) + else + begin + FResizing := True; + chrmosr.WasResized; + end; + end; + finally + if (FResizeCS <> nil) then FResizeCS.Release; + end; +end; + +procedure TFMXExternalPumpBrowserFrm.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); +var + PositionChanged: Boolean; +begin + PositionChanged := (ALeft <> Left) or (ATop <> Top); + + inherited SetBounds(ALeft, ATop, AWidth, AHeight); + + if PositionChanged then NotifyMoveOrResizeStarted; +end; + +procedure TFMXExternalPumpBrowserFrm.SendCEFKeyEvent(const aCefEvent : TCefKeyEvent); +begin + chrmosr.SendKeyEvent(@aCefEvent); +end; + +procedure TFMXExternalPumpBrowserFrm.NotifyMoveOrResizeStarted; +begin + if (chrmosr <> nil) then chrmosr.NotifyMoveOrResizeStarted; +end; + +procedure TFMXExternalPumpBrowserFrm.SendCaptureLostEvent; +begin + if (chrmosr <> nil) then chrmosr.SendCaptureLostEvent; +end; + +function TFMXExternalPumpBrowserFrm.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 TFMXExternalPumpBrowserFrm.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 TFMXExternalPumpBrowserFrm.SnapshotBtnClick(Sender: TObject); +begin + if SaveDialog1.Execute then Panel1.SaveToFile(SaveDialog1.FileName); +end; + +procedure TFMXExternalPumpBrowserFrm.SnapshotBtnEnter(Sender: TObject); +begin + chrmosr.SendFocusEvent(False); +end; + +end. diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2.dproj b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2.dproj index b58de607..4a969926 100644 --- a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2.dproj +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2.dproj @@ -1,7 +1,7 @@  {BE24D13B-2634-4064-8746-AB331419C5FA} - 19.1 + 19.2 FMX FMXExternalPumpBrowser2.dpr True @@ -356,6 +356,16 @@ 1 + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + res\drawable-ldpi diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dpr b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dpr index b5c85fd2..d55969a1 100644 --- a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dpr +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dpr @@ -42,6 +42,7 @@ program FMXExternalPumpBrowser2_sp; {$R *.res} uses + System.IOUtils, uCEFApplicationCore; begin @@ -51,6 +52,12 @@ begin GlobalCEFApp.ExternalMessagePump := True; GlobalCEFApp.MultiThreadedMessageLoop := False; + GlobalCEFApp.FrameworkDirPath := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'cef'; + GlobalCEFApp.ResourcesDirPath := GlobalCEFApp.FrameworkDirPath; + GlobalCEFApp.LocalesDirPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'locales'; + GlobalCEFApp.cache := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'cache'; + GlobalCEFApp.UserDataPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'User Data'; + // This is a workaround to fix a Chromium initialization crash. // The current FMX solution to initialize CEF with a loader unit // creates a race condition with the media key controller in Chromium. diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dproj b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dproj index 841a1818..32593d7d 100644 --- a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dproj +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/FMXExternalPumpBrowser2_sp.dproj @@ -1,7 +1,7 @@  {2E3F5B05-DDFA-4E9D-98F7-DAD46B88C4C6} - 19.1 + 19.2 None FMXExternalPumpBrowser2_sp.dpr True @@ -64,6 +64,7 @@ RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACADSDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;inetdb;emsedge;fmx;FireDACIBDriver;dbexpress;IndyCore;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;soapserver;bindengine;CloudService;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndySystem;FireDACDb2Driver;FireDACInfxDriver;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;rtl;emsserverresource;DbxClientDriver;CustomIPTransport;bindcomp;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;IndyProtocols;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + $(fmxlinux)\Lib\$(ProductVersion)\$(Config);$(DCC_UnitSearchPath) DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;bindcompvclsmp;emsclientfiredac;tethering;svnui;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;inetdb;emsedge;fmx;FireDACIBDriver;fmxdae;vcledge;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) @@ -300,6 +301,16 @@ 1 + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + res\drawable-ldpi diff --git a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/uCEFLoader.pas b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/uCEFLoader.pas index 69b7b629..a3e30f06 100644 --- a/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/uCEFLoader.pas +++ b/demos/Delphi_FMX_Linux/FMXExternalPumpBrowser2/uCEFLoader.pas @@ -47,6 +47,7 @@ uses // project. // Read the answer to this question for more more information : // https://stackoverflow.com/questions/52103407/changing-the-initialization-order-of-the-unit-in-delphi + System.IOUtils, uCEFApplication, uCEFConstants, uCEFWorkScheduler; implementation @@ -74,7 +75,13 @@ begin GlobalCEFApp.MultiThreadedMessageLoop := False; GlobalCEFApp.DisableZygote := True; GlobalCEFApp.OnScheduleMessagePumpWork := GlobalCEFApp_OnScheduleMessagePumpWork; - GlobalCEFApp.BrowserSubprocessPath := 'FMXExternalPumpBrowser2_sp'; + + GlobalCEFApp.FrameworkDirPath := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'cef'; + GlobalCEFApp.ResourcesDirPath := GlobalCEFApp.FrameworkDirPath; + GlobalCEFApp.LocalesDirPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'locales'; + GlobalCEFApp.cache := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'cache'; + GlobalCEFApp.UserDataPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'User Data'; + GlobalCEFApp.BrowserSubprocessPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'FMXExternalPumpBrowser2_sp'; // This is a workaround to fix a Chromium initialization crash. // The current FMX solution to initialize CEF with a loader unit diff --git a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXApplicationService.pas b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXApplicationService.pas index 609c5f48..ae082bae 100644 --- a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXApplicationService.pas +++ b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXApplicationService.pas @@ -86,7 +86,6 @@ type private FNewDelegate : ICrAppControlProtocol; FOldDelegate : NSApplicationDelegate; - FLastMacOsKeyDownCode : integer; protected class var OldFMXApplicationService: IFMXApplicationService; @@ -122,7 +121,6 @@ type function applicationDockMenu(sender: NSApplication): NSMenu; class procedure AddPlatformService; - class function LastMacOsKeyDownCode: integer; property DefaultTitle : string read GetDefaultTitle; property Title : string read GetTitle write SetTitle; @@ -201,7 +199,6 @@ begin FNewDelegate := nil; FOldDelegate := nil; - FLastMacOsKeyDownCode := 0; end; procedure TFMXApplicationService.AfterConstruction; @@ -274,14 +271,6 @@ begin end; end; -class function TFMXApplicationService.LastMacOsKeyDownCode: integer; -begin - if assigned(NewFMXApplicationService) then - Result := TFMXApplicationService(NewFMXApplicationService).FLastMacOsKeyDownCode - else - Result := 0; -end; - function TFMXApplicationService.GetDefaultTitle: string; begin Result := OldFMXApplicationService.GetDefaultTitle; @@ -377,22 +366,8 @@ begin Result := nil; end; -function TFMXApplicationService.HandleMessage: Boolean; { -const - WaitTimeout = 0.001; -var - TempEvent : NSEvent; - TempNSApp : NSApplication; - TempTimeout : NSDate; } -begin { - TempNSApp := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication); - TempTimeout := TNSDate.Wrap(TNSDate.OCClass.dateWithTimeIntervalSinceNow(WaitTimeout)); - TempEvent := TempNSApp.nextEventMatchingMask(NSAnyEventMask, TempTimeout, NSDefaultRunLoopMode, False); - - if (TempEvent <> nil) and (TempEvent.&type = NSKeyDown) then - FLastMacOsKeyDownCode := TempEvent.keyCode; - } - +function TFMXApplicationService.HandleMessage: Boolean; +begin Result := OldFMXApplicationService.HandleMessage; end; diff --git a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx index eb799638..9da61602 100644 --- a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx +++ b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.fmx @@ -103,6 +103,7 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm OnMouseUp = Panel1MouseUp OnMouseLeave = Panel1MouseLeave OnMouseWheel = Panel1MouseWheel + OnKeyUp = Panel1KeyUp OnKeyDown = Panel1KeyDown OnDialogKey = Panel1DialogKey end diff --git a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas index 76259813..29783f5f 100644 --- a/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas +++ b/demos/Delphi_FMX_Mac/FMXExternalPumpBrowser/uFMXExternalPumpBrowser.pas @@ -42,15 +42,10 @@ unit uFMXExternalPumpBrowser; interface uses - {$IFDEF MSWINDOWS} - Winapi.Messages, Winapi.Windows, - {$ENDIF} System.Types, System.UITypes, System.Classes, System.SyncObjs, - FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, + Macapi.AppKit, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Edit, FMX.StdCtrls, FMX.Controls.Presentation, - {$IFDEF DELPHI17_UP} - FMX.Graphics, - {$ENDIF} + {$IFDEF DELPHI17_UP}FMX.Graphics,{$ENDIF} uCEFFMXChromium, uCEFFMXBufferPanel, uCEFFMXWorkScheduler, uCEFInterfaces, uCEFTypes, uCEFConstants, uCEFChromiumCore, FMX.Layouts, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo; @@ -87,6 +82,7 @@ type procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); procedure Panel1MouseLeave(Sender: TObject); procedure Panel1MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); + procedure Panel1KeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); procedure Panel1KeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); procedure Panel1DialogKey(Sender: TObject; var Key: Word; Shift: TShiftState); @@ -139,27 +135,12 @@ type function GetMousePosition(var aPoint : TPointF) : boolean; procedure InitializeLastClick; function CancelPreviousClick(const x, y : single; var aCurrentTime : integer) : boolean; - {$IFDEF MSWINDOWS} - function SendCompMessage(aMsg : cardinal; aWParam : WPARAM = 0; aLParam : LPARAM = 0) : boolean; - function ArePointerEventsSupported : boolean; - function HandlePenEvent(const aID : uint32; aMsg : cardinal) : boolean; - function HandleTouchEvent(const aID : uint32; aMsg : cardinal) : boolean; overload; - function HandlePointerEvent(const aMessage : TMsg) : boolean; - {$ENDIF} public procedure DoResize; procedure NotifyMoveOrResizeStarted; procedure SendCaptureLostEvent; procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override; - {$IFDEF MSWINDOWS} - procedure HandleSYSCHAR(const aMessage : TMsg); - procedure HandleSYSKEYDOWN(const aMessage : TMsg); - procedure HandleSYSKEYUP(const aMessage : TMsg); - procedure HandleKEYDOWN(const aMessage : TMsg); - procedure HandleKEYUP(const aMessage : TMsg); - function HandlePOINTER(const aMessage : TMsg) : boolean; - {$ENDIF} end; var @@ -171,7 +152,7 @@ var // This demo is in ALPHA state. It's incomplete and some features may not work! // **************************************************************************** // Known issues and missing features : -// - Keyboard support not implemented yet. +// - Keyboard support is incomplete. // - Full screen event is not handled correctly. // - The CrAppProtocol implementation in uFMXApplicationService needs to be tested. // - All Windows code in this demo must be removed. @@ -393,33 +374,74 @@ begin chrmosr.SendFocusEvent(False); end; +procedure TFMXExternalPumpBrowserFrm.Panel1KeyUp(Sender: TObject; var Key: Word; + var KeyChar: Char; Shift: TShiftState); +var + TempKeyEvent : TCefKeyEvent; + TempChar : char; +begin + if not(Panel1.IsFocused) then exit; + + if (KeyChar <> #0) then + TempChar := KeyChar + else + if (Key <> 0) then + TempChar := chr(Key) + else + TempChar := #0; + + TempKeyEvent.kind := KEYEVENT_KEYUP; + TempKeyEvent.modifiers := getModifiers(Shift); + TempKeyEvent.windows_key_code := 0; + TempKeyEvent.native_key_code := 0; + TempKeyEvent.is_system_key := ord(False); + TempKeyEvent.character := TempChar; + TempKeyEvent.unmodified_character := TempChar; + TempKeyEvent.focus_on_editable_field := ord(False); + + chrmosr.SendKeyEvent(@TempKeyEvent); +end; + procedure TFMXExternalPumpBrowserFrm.Panel1KeyDown( Sender : TObject; var Key : Word; var KeyChar : Char; Shift : TShiftState); var TempKeyEvent : TCefKeyEvent; + TempChar : char; begin if not(Panel1.IsFocused) then exit; - if (Key = 0) and (KeyChar <> #0) then - begin - TempKeyEvent.kind := KEYEVENT_CHAR; - TempKeyEvent.modifiers := getModifiers(Shift); - TempKeyEvent.windows_key_code := ord(KeyChar); - // TempKeyEvent.native_key_code := TFMXApplicationService.LastMacOsKeyDownCode; - 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); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end + if (KeyChar <> #0) then + TempChar := KeyChar else - if (Key <> 0) and (KeyChar = #0) and - (Key in [vkLeft, vkRight, vkUp, vkDown]) then - Key := 0; + if (Key <> 0) then + begin + TempChar := chr(Key); + + if (Key in [vkLeft, vkRight, vkUp, vkDown]) then + begin + Key := 0; + exit; + end; + end + else + TempChar := #0; + + TempKeyEvent.kind := KEYEVENT_KEYDOWN; + TempKeyEvent.modifiers := getModifiers(Shift); + TempKeyEvent.windows_key_code := 0; + TempKeyEvent.native_key_code := 0; + TempKeyEvent.is_system_key := ord(False); + TempKeyEvent.character := TempChar; + TempKeyEvent.unmodified_character := TempChar; + TempKeyEvent.focus_on_editable_field := ord(False); + + chrmosr.SendKeyEvent(@TempKeyEvent); + + TempKeyEvent.kind := KEYEVENT_CHAR; + + chrmosr.SendKeyEvent(@TempKeyEvent); end; procedure TFMXExternalPumpBrowserFrm.Panel1MouseDown(Sender : TObject; @@ -578,14 +600,10 @@ procedure TFMXExternalPumpBrowserFrm.chrmosrBeforeClose(Sender: TObject; const b begin FCanClose := True; - {$IFDEF MSWINDOWS} - SendCompMessage(WM_CLOSE); - {$ELSE} TThread.Queue(nil, procedure begin close end); - {$ENDIF} end; procedure TFMXExternalPumpBrowserFrm.chrmosrBeforePopup( Sender : TObject; @@ -824,13 +842,7 @@ begin if (type_ = PET_VIEW) then begin if TempForcedResize or FPendingResize then - begin - {$IFDEF MSWINDOWS} - SendCompMessage(CEF_PENDINGRESIZE); - {$ELSE} - TThread.Queue(nil, DoResize); - {$ENDIF} - end; + TThread.Queue(nil, DoResize); FResizing := False; FPendingResize := False; @@ -981,263 +993,4 @@ begin chrmosr.SendFocusEvent(False); end; -{$IFDEF MSWINDOWS} -procedure TFMXExternalPumpBrowserFrm.HandleSYSCHAR(const aMessage : TMsg); -var - TempKeyEvent : TCefKeyEvent; -begin - if Panel1.IsFocused and (aMessage.wParam in [VK_BACK..VK_HELP]) then - begin - TempKeyEvent.kind := KEYEVENT_CHAR; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(True); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; -end; - -procedure TFMXExternalPumpBrowserFrm.HandleSYSKEYDOWN(const aMessage : TMsg); -var - TempKeyEvent : TCefKeyEvent; -begin - if Panel1.IsFocused and (aMessage.wParam in [VK_BACK..VK_HELP]) then - begin - TempKeyEvent.kind := KEYEVENT_RAWKEYDOWN; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(True); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; -end; - -procedure TFMXExternalPumpBrowserFrm.HandleSYSKEYUP(const aMessage : TMsg); -var - TempKeyEvent : TCefKeyEvent; -begin - if Panel1.IsFocused and (aMessage.wParam in [VK_BACK..VK_HELP]) then - begin - TempKeyEvent.kind := KEYEVENT_KEYUP; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(True); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; -end; - -procedure TFMXExternalPumpBrowserFrm.HandleKEYDOWN(const aMessage : TMsg); -var - TempKeyEvent : TCefKeyEvent; -begin - if Panel1.IsFocused then - begin - TempKeyEvent.kind := KEYEVENT_RAWKEYDOWN; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(False); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; -end; - -procedure TFMXExternalPumpBrowserFrm.HandleKEYUP(const aMessage : TMsg); -var - TempKeyEvent : TCefKeyEvent; -begin - if Panel1.IsFocused then - begin - if (aMessage.wParam = vkReturn) then - begin - TempKeyEvent.kind := KEYEVENT_CHAR; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(False); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; - - TempKeyEvent.kind := KEYEVENT_KEYUP; - TempKeyEvent.modifiers := GetCefKeyboardModifiers(aMessage.wParam, aMessage.lParam); - TempKeyEvent.windows_key_code := integer(aMessage.wParam); - TempKeyEvent.native_key_code := integer(aMessage.lParam); - TempKeyEvent.is_system_key := ord(False); - TempKeyEvent.character := #0; - TempKeyEvent.unmodified_character := #0; - TempKeyEvent.focus_on_editable_field := ord(False); - - chrmosr.SendKeyEvent(@TempKeyEvent); - end; -end; - -function TFMXExternalPumpBrowserFrm.HandlePOINTER(const aMessage : TMsg) : boolean; -begin - Result := Panel1.IsFocused and - (GlobalCEFApp <> nil) and - ArePointerEventsSupported and - HandlePointerEvent(aMessage); -end; - -function TFMXExternalPumpBrowserFrm.SendCompMessage(aMsg : cardinal; aWParam : WPARAM; aLParam : LPARAM) : boolean; -var - TempHandle : TWinWindowHandle; -begin - TempHandle := WindowHandleToPlatform(Handle); - Result := WinApi.Windows.PostMessage(TempHandle.Wnd, aMsg, aWParam, aLParam); -end; - -function TFMXExternalPumpBrowserFrm.ArePointerEventsSupported : boolean; -begin - Result := FAtLeastWin8 and - (@GetPointerType <> nil) and - (@GetPointerTouchInfo <> nil) and - (@GetPointerPenInfo <> nil); -end; - -function TFMXExternalPumpBrowserFrm.HandlePointerEvent(const aMessage : TMsg) : boolean; -const - PT_TOUCH = 2; - PT_PEN = 3; -var - TempID : uint32; - TempType : POINTER_INPUT_TYPE; -begin - Result := False; - TempID := LoWord(aMessage.wParam); - - if GetPointerType(TempID, @TempType) then - case TempType of - PT_PEN : Result := HandlePenEvent(TempID, aMessage.message); - PT_TOUCH : Result := HandleTouchEvent(TempID, aMessage.message); - end; -end; - -function TFMXExternalPumpBrowserFrm.HandlePenEvent(const aID : uint32; aMsg : cardinal) : boolean; -var - TempPenInfo : POINTER_PEN_INFO; - TempTouchEvent : TCefTouchEvent; - TempPoint : TPoint; -begin - Result := False; - if not(GetPointerPenInfo(aID, @TempPenInfo)) then exit; - - TempTouchEvent.id := aID; - TempTouchEvent.x := 0; - TempTouchEvent.y := 0; - TempTouchEvent.radius_x := 0; - TempTouchEvent.radius_y := 0; - TempTouchEvent.type_ := CEF_TET_RELEASED; - TempTouchEvent.modifiers := EVENTFLAG_NONE; - - if ((TempPenInfo.penFlags and PEN_FLAG_ERASER) <> 0) then - TempTouchEvent.pointer_type := CEF_POINTER_TYPE_ERASER - else - TempTouchEvent.pointer_type := CEF_POINTER_TYPE_PEN; - - if ((TempPenInfo.penMask and PEN_MASK_PRESSURE) <> 0) then - TempTouchEvent.pressure := TempPenInfo.pressure / 1024 - else - TempTouchEvent.pressure := 0; - - if ((TempPenInfo.penMask and PEN_MASK_ROTATION) <> 0) then - TempTouchEvent.rotation_angle := TempPenInfo.rotation / 180 * Pi - else - TempTouchEvent.rotation_angle := 0; - - Result := True; - - case aMsg of - WM_POINTERDOWN : - TempTouchEvent.type_ := CEF_TET_PRESSED; - - WM_POINTERUPDATE : - if ((TempPenInfo.pointerInfo.pointerFlags and POINTER_FLAG_INCONTACT) <> 0) then - TempTouchEvent.type_ := CEF_TET_MOVED - else - exit; // Ignore hover events. - - WM_POINTERUP : - TempTouchEvent.type_ := CEF_TET_RELEASED; - end; - - if ((TempPenInfo.pointerInfo.pointerFlags and POINTER_FLAG_CANCELED) <> 0) then - TempTouchEvent.type_ := CEF_TET_CANCELLED; - - TempPoint := Panel1.ScreenToClient(TempPenInfo.pointerInfo.ptPixelLocation); - // TFMXBufferPanel.ScreenToClient applies the scale factor. No need to call DeviceToLogical to set TempTouchEvent. - TempTouchEvent.x := TempPoint.x; - TempTouchEvent.y := TempPoint.y; - - chrmosr.SendTouchEvent(@TempTouchEvent); -end; - -function TFMXExternalPumpBrowserFrm.HandleTouchEvent(const aID : uint32; aMsg : cardinal) : boolean; -var - TempTouchInfo : POINTER_TOUCH_INFO; - TempTouchEvent : TCefTouchEvent; - TempPoint : TPoint; -begin - Result := False; - if not(GetPointerTouchInfo(aID, @TempTouchInfo)) then exit; - - TempTouchEvent.id := aID; - TempTouchEvent.x := 0; - TempTouchEvent.y := 0; - TempTouchEvent.radius_x := 0; - TempTouchEvent.radius_y := 0; - TempTouchEvent.rotation_angle := 0; - TempTouchEvent.pressure := 0; - TempTouchEvent.type_ := CEF_TET_RELEASED; - TempTouchEvent.modifiers := EVENTFLAG_NONE; - TempTouchEvent.pointer_type := CEF_POINTER_TYPE_TOUCH; - - Result := True; - - case aMsg of - WM_POINTERDOWN : - TempTouchEvent.type_ := CEF_TET_PRESSED; - - WM_POINTERUPDATE : - if ((TempTouchInfo.pointerInfo.pointerFlags and POINTER_FLAG_INCONTACT) <> 0) then - TempTouchEvent.type_ := CEF_TET_MOVED - else - exit; // Ignore hover events. - - WM_POINTERUP : - TempTouchEvent.type_ := CEF_TET_RELEASED; - end; - - if ((TempTouchInfo.pointerInfo.pointerFlags and POINTER_FLAG_CANCELED) <> 0) then - TempTouchEvent.type_ := CEF_TET_CANCELLED; - - TempPoint := Panel1.ScreenToClient(TempTouchInfo.pointerInfo.ptPixelLocation); - // TFMXBufferPanel.ScreenToClient applies the scale factor. No need to call DeviceToLogical to set TempTouchEvent. - TempTouchEvent.x := TempPoint.x; - TempTouchEvent.y := TempPoint.y; - - chrmosr.SendTouchEvent(@TempTouchEvent); -end; -{$ENDIF} - end. diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json index 0dd79e1a..ccef7748 100644 --- a/update_CEF4Delphi.json +++ b/update_CEF4Delphi.json @@ -2,7 +2,7 @@ "UpdateLazPackages" : [ { "ForceNotify" : true, - "InternalVersion" : 295, + "InternalVersion" : 296, "Name" : "cef4delphi_lazarus.lpk", "Version" : "90.6.6.0" }