mirror of
https://github.com/salvadordf/CEF4Delphi.git
synced 2025-05-13 21:46:53 +02:00
Improved keyboard and mouse support in FMXExternalPumpBrowser for MacOS
Added X11 error handling functions to FMXExternalPumpBrowser2 demo for Linux. Deleted FMXExternalPumpBrowser demo for Linux. Added uCEFMacOSConstants and uCEFMacOSFunctions units for MacOS. Replaced TThread.Queue for TThread.ForceQueue to avoid executing that method immediately in some cases.
This commit is contained in:
parent
a22e1a07b1
commit
44896524e8
@ -1,23 +0,0 @@
|
||||
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
|
@ -1,80 +0,0 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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.
|
||||
*
|
||||
*)
|
||||
|
||||
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.
|
File diff suppressed because it is too large
Load Diff
@ -1,468 +0,0 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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}
|
@ -1,100 +0,0 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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 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.
|
@ -1,141 +0,0 @@
|
||||
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
|
@ -1,915 +0,0 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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 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 := '<html><body bgcolor="white">' +
|
||||
'<h2>Failed to load URL ' + failedUrl +
|
||||
' with error ' + errorText +
|
||||
' (' + inttostr(errorCode) + ').</h2></body></html>';
|
||||
|
||||
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.
|
@ -43,7 +43,7 @@ program FMXExternalPumpBrowser2_sp;
|
||||
|
||||
uses
|
||||
System.IOUtils,
|
||||
uCEFApplicationCore;
|
||||
uCEFApplicationCore, uCEFConstants;
|
||||
|
||||
begin
|
||||
GlobalCEFApp := TCefApplicationCore.Create;
|
||||
@ -52,12 +52,19 @@ begin
|
||||
GlobalCEFApp.ExternalMessagePump := True;
|
||||
GlobalCEFApp.MultiThreadedMessageLoop := False;
|
||||
|
||||
// Use these settings if you already have the CEF binaries in a directory called "cef" inside your home directory.
|
||||
// You can also use the "Deployment" window but debugging might be slower.
|
||||
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';
|
||||
|
||||
{$IFDEF DEBUG}
|
||||
GlobalCEFApp.LogFile := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'debug.log';
|
||||
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
{$ENDIF}
|
||||
|
||||
// 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.
|
||||
|
@ -48,10 +48,21 @@ uses
|
||||
// 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;
|
||||
uCEFApplication, uCEFConstants, uCEFWorkScheduler, uCEFLinuxFunctions,
|
||||
uCEFLinuxTypes;
|
||||
|
||||
implementation
|
||||
|
||||
function CustomX11ErrorHandler(Display:PDisplay; ErrorEv:PXErrorEvent):longint;cdecl;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function CustomXIOErrorHandler(Display:PDisplay):longint;cdecl;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64);
|
||||
begin
|
||||
if (GlobalCEFWorkScheduler <> nil) then
|
||||
@ -76,6 +87,8 @@ begin
|
||||
GlobalCEFApp.DisableZygote := True;
|
||||
GlobalCEFApp.OnScheduleMessagePumpWork := GlobalCEFApp_OnScheduleMessagePumpWork;
|
||||
|
||||
// Use these settings if you already have the CEF binaries in a directory called "cef" inside your home directory.
|
||||
// You can also use the "Deployment" window but debugging might be slower.
|
||||
GlobalCEFApp.FrameworkDirPath := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'cef';
|
||||
GlobalCEFApp.ResourcesDirPath := GlobalCEFApp.FrameworkDirPath;
|
||||
GlobalCEFApp.LocalesDirPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'locales';
|
||||
@ -83,6 +96,11 @@ begin
|
||||
GlobalCEFApp.UserDataPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'User Data';
|
||||
GlobalCEFApp.BrowserSubprocessPath := GlobalCEFApp.FrameworkDirPath + TPath.DirectorySeparatorChar + 'FMXExternalPumpBrowser2_sp';
|
||||
|
||||
{$IFDEF DEBUG}
|
||||
GlobalCEFApp.LogFile := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'debug.log';
|
||||
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
{$ENDIF}
|
||||
|
||||
// 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.
|
||||
@ -90,6 +108,11 @@ begin
|
||||
|
||||
GlobalCEFApp.StartMainProcess;
|
||||
GlobalCEFWorkScheduler.CreateThread;
|
||||
|
||||
// Install xlib error handlers so that the application won't be terminated
|
||||
// on non-fatal errors. Must be done after initializing GTK.
|
||||
XSetErrorHandler(@CustomX11ErrorHandler);
|
||||
XSetIOErrorHandler(@CustomXIOErrorHandler);
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
@ -17,6 +17,7 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
DesignerMasterStyle = 0
|
||||
object AddressPnl: TPanel
|
||||
Align = Top
|
||||
Enabled = False
|
||||
Padding.Left = 5.000000000000000000
|
||||
Padding.Top = 5.000000000000000000
|
||||
Padding.Right = 5.000000000000000000
|
||||
@ -24,7 +25,8 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
Size.Width = 800.000000000000000000
|
||||
Size.Height = 33.000000000000000000
|
||||
Size.PlatformDefault = False
|
||||
TabOrder = 1
|
||||
TabOrder = 0
|
||||
TabStop = False
|
||||
object AddressEdt: TEdit
|
||||
Touch.InteractiveGestures = [LongTap, DoubleTap]
|
||||
Align = Client
|
||||
@ -43,7 +45,8 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
Size.Width = 81.000000000000000000
|
||||
Size.Height = 23.000000000000000000
|
||||
Size.PlatformDefault = False
|
||||
TabOrder = 2
|
||||
TabOrder = 1
|
||||
TabStop = False
|
||||
object GoBtn: TButton
|
||||
Align = Left
|
||||
Position.X = 5.000000000000000000
|
||||
@ -87,7 +90,7 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
end
|
||||
object Panel1: TFMXBufferPanel
|
||||
Align = Client
|
||||
TabOrder = 0
|
||||
TabOrder = 1
|
||||
CanFocus = True
|
||||
Size.Width = 800.000000000000000000
|
||||
Size.Height = 578.000000000000000000
|
||||
@ -101,8 +104,6 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
OnMouseUp = Panel1MouseUp
|
||||
OnMouseLeave = Panel1MouseLeave
|
||||
OnMouseWheel = Panel1MouseWheel
|
||||
OnKeyDown = Panel1KeyDown
|
||||
OnDialogKey = Panel1DialogKey
|
||||
end
|
||||
object StatusBar1: TStatusBar
|
||||
Position.Y = 611.000000000000000000
|
||||
|
@ -34,9 +34,7 @@
|
||||
* this source code without explicit permission.
|
||||
*
|
||||
*)
|
||||
|
||||
unit uFMXExternalPumpBrowser2;
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
interface
|
||||
@ -74,8 +72,6 @@ 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 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);
|
||||
@ -121,7 +117,6 @@ type
|
||||
function getModifiers(Shift: TShiftState): TCefEventFlags;
|
||||
function GetButton(Button: TMouseButton): TCefMouseButtonType;
|
||||
function GetMousePosition(var aPoint : TPointF) : boolean;
|
||||
|
||||
public
|
||||
procedure DoResize;
|
||||
procedure NotifyMoveOrResizeStarted;
|
||||
@ -136,11 +131,9 @@ var
|
||||
// ***************************
|
||||
// ********* WARNING *********
|
||||
// ***************************
|
||||
// This is a demo for LINUX and it's in BETA state.
|
||||
// This is a demo for LINUX and it's in ALPHA 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.
|
||||
|
||||
@ -187,9 +180,11 @@ begin
|
||||
TempCefEvent.kind := KEYEVENT_KEYUP;
|
||||
FMXExternalPumpBrowserFrm.SendCEFKeyEvent(TempCefEvent);
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
Result := True;
|
||||
end
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
procedure ConnectKeyPressReleaseEvents(const aWidget : PGtkWidget);
|
||||
@ -231,7 +226,8 @@ begin
|
||||
// opaque white background color
|
||||
chrmosr.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF);
|
||||
|
||||
if not(chrmosr.CreateBrowser) then Timer1.Enabled := True;
|
||||
if not(chrmosr.CreateBrowser) then
|
||||
Timer1.Enabled := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -302,7 +298,7 @@ end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.GoBtnEnter(Sender: TObject);
|
||||
begin
|
||||
chrmosr.SendFocusEvent(False);
|
||||
if (chrmosr <> nil) then chrmosr.SendFocusEvent(False);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1Click(Sender: TObject);
|
||||
@ -310,48 +306,14 @@ 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);
|
||||
if (chrmosr <> nil) then 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;
|
||||
if (chrmosr <> nil) then chrmosr.SendFocusEvent(False);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1MouseDown(Sender : TObject;
|
||||
@ -374,12 +336,14 @@ end;
|
||||
|
||||
function TFMXExternalPumpBrowserFrm.GetMousePosition(var aPoint : TPointF) : boolean;
|
||||
begin
|
||||
{$IFDEF DELPHI17_UP}
|
||||
if (FMouseWheelService <> nil) then
|
||||
begin
|
||||
aPoint := FMouseWheelService.GetMousePos;
|
||||
Result := True;
|
||||
end
|
||||
else
|
||||
{$ENDIF}
|
||||
begin
|
||||
aPoint.x := 0;
|
||||
aPoint.y := 0;
|
||||
@ -464,13 +428,14 @@ begin
|
||||
if FClosing then
|
||||
close
|
||||
else
|
||||
if not(chrmosr.CreateBrowser) and not(chrmosr.Initialized) then
|
||||
if not(chrmosr.CreateBrowser) then
|
||||
Timer1.Enabled := True;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.AddressEdtEnter(Sender: TObject);
|
||||
begin
|
||||
chrmosr.SendFocusEvent(False);
|
||||
if (chrmosr <> nil) then
|
||||
chrmosr.SendFocusEvent(False);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrAfterCreated(Sender: TObject; const browser: ICefBrowser);
|
||||
@ -478,14 +443,15 @@ begin
|
||||
// Now the browser is fully initialized we can enable the UI.
|
||||
Caption := 'FMX External Pump Browser 2';
|
||||
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;
|
||||
TThread.ForceQueue(nil, procedure
|
||||
begin
|
||||
close;
|
||||
end);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrBeforePopup( Sender : TObject;
|
||||
@ -569,13 +535,17 @@ begin
|
||||
rect.height := round(Panel1.Height);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrLoadError(Sender: TObject;
|
||||
const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer;
|
||||
const errorText, failedUrl: ustring);
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrLoadError( Sender : TObject;
|
||||
const browser : ICefBrowser;
|
||||
const frame : ICefFrame;
|
||||
errorCode : Integer;
|
||||
const errorText : ustring;
|
||||
const failedUrl : ustring);
|
||||
var
|
||||
TempString : ustring;
|
||||
begin
|
||||
if (errorCode = ERR_ABORTED) then exit;
|
||||
if (errorCode = ERR_ABORTED) then
|
||||
exit;
|
||||
|
||||
TempString := '<html><body bgcolor="white">' +
|
||||
'<h2>Failed to load URL ' + failedUrl +
|
||||
@ -585,8 +555,11 @@ begin
|
||||
chrmosr.LoadString(TempString, frame);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrLoadingStateChange(Sender: TObject;
|
||||
const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean);
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrLoadingStateChange( Sender : TObject;
|
||||
const browser : ICefBrowser;
|
||||
isLoading : Boolean;
|
||||
canGoBack : Boolean;
|
||||
canGoForward : Boolean);
|
||||
begin
|
||||
if isLoading then
|
||||
StatusLbl.Text := 'Loading...'
|
||||
@ -735,7 +708,7 @@ begin
|
||||
if (type_ = PET_VIEW) then
|
||||
begin
|
||||
if TempForcedResize or FPendingResize then
|
||||
TThread.Queue(nil, DoResize);
|
||||
TThread.ForceQueue(nil, DoResize);
|
||||
|
||||
FResizing := False;
|
||||
FPendingResize := False;
|
||||
@ -790,6 +763,9 @@ end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.DoResize;
|
||||
begin
|
||||
if (chrmosr = nil) or not(chrmosr.Initialized) then
|
||||
exit;
|
||||
|
||||
try
|
||||
if (FResizeCS <> nil) then
|
||||
begin
|
||||
|
@ -46,9 +46,9 @@ uses
|
||||
FMX.Forms,
|
||||
uCEFApplication,
|
||||
uCEFFMXWorkScheduler,
|
||||
uCEFMacOSFunctions,
|
||||
uFMXExternalPumpBrowser in 'uFMXExternalPumpBrowser.pas' {FMXExternalPumpBrowserFrm},
|
||||
uFMXApplicationService in 'uFMXApplicationService.pas',
|
||||
uFMXMiscFunctions in 'uFMXMiscFunctions.pas';
|
||||
uFMXApplicationService in 'uFMXApplicationService.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
@ -160,7 +160,6 @@
|
||||
<Form>FMXExternalPumpBrowserFrm</Form>
|
||||
</DCCReference>
|
||||
<DCCReference Include="uFMXApplicationService.pas"/>
|
||||
<DCCReference Include="uFMXMiscFunctions.pas"/>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
|
@ -93,7 +93,6 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
Size.Width = 800.000000000000000000
|
||||
Size.Height = 600.000000000000000000
|
||||
Size.PlatformDefault = False
|
||||
OnResized = Panel1Resize
|
||||
OnEnter = Panel1Enter
|
||||
OnExit = Panel1Exit
|
||||
OnResize = Panel1Resize
|
||||
@ -107,6 +106,58 @@ object FMXExternalPumpBrowserFrm: TFMXExternalPumpBrowserFrm
|
||||
OnKeyDown = Panel1KeyDown
|
||||
OnDialogKey = Panel1DialogKey
|
||||
end
|
||||
object MainMenu1: TMainMenu
|
||||
Left = 40
|
||||
Top = 273
|
||||
object EditMenu: TMenuItem
|
||||
Text = 'Edit'
|
||||
object UndoMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 4186
|
||||
Text = 'Undo'
|
||||
OnClick = UndoMenuItemClick
|
||||
end
|
||||
object RedoMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 12378
|
||||
Text = 'Redo'
|
||||
OnClick = RedoMenuItemClick
|
||||
end
|
||||
object SeparatorMenuItem: TMenuItem
|
||||
Locked = True
|
||||
Text = '-'
|
||||
end
|
||||
object CutMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 4184
|
||||
Text = 'Cut'
|
||||
OnClick = CutMenuItemClick
|
||||
end
|
||||
object CopyMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 4163
|
||||
Text = 'Copy'
|
||||
OnClick = CopyMenuItemClick
|
||||
end
|
||||
object PasteMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 4182
|
||||
Text = 'Paste'
|
||||
OnClick = PasteMenuItemClick
|
||||
end
|
||||
object DeleteMenuItem: TMenuItem
|
||||
Locked = True
|
||||
Text = 'Delete'
|
||||
OnClick = DeleteMenuItemClick
|
||||
end
|
||||
object SelectAllMenuItem: TMenuItem
|
||||
Locked = True
|
||||
ShortCut = 4161
|
||||
Text = 'Select all'
|
||||
OnClick = SelectAllMenuItemClick
|
||||
end
|
||||
end
|
||||
end
|
||||
object chrmosr: TFMXChromium
|
||||
OnTooltip = chrmosrTooltip
|
||||
OnCursorChange = chrmosrCursorChange
|
||||
|
@ -48,7 +48,7 @@ uses
|
||||
{$IFDEF DELPHI17_UP}FMX.Graphics,{$ENDIF}
|
||||
uCEFFMXChromium, uCEFFMXBufferPanel, uCEFFMXWorkScheduler,
|
||||
uCEFInterfaces, uCEFTypes, uCEFConstants, uCEFChromiumCore, FMX.Layouts,
|
||||
FMX.Memo.Types, FMX.ScrollBox, FMX.Memo;
|
||||
FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, FMX.Menus;
|
||||
|
||||
type
|
||||
tagRGBQUAD = record
|
||||
@ -69,6 +69,16 @@ type
|
||||
Layout1: TLayout;
|
||||
GoBtn: TButton;
|
||||
SnapshotBtn: TButton;
|
||||
MainMenu1: TMainMenu;
|
||||
EditMenu: TMenuItem;
|
||||
UndoMenuItem: TMenuItem;
|
||||
RedoMenuItem: TMenuItem;
|
||||
SeparatorMenuItem: TMenuItem;
|
||||
CutMenuItem: TMenuItem;
|
||||
CopyMenuItem: TMenuItem;
|
||||
PasteMenuItem: TMenuItem;
|
||||
DeleteMenuItem: TMenuItem;
|
||||
SelectAllMenuItem: TMenuItem;
|
||||
|
||||
procedure GoBtnClick(Sender: TObject);
|
||||
procedure GoBtnEnter(Sender: TObject);
|
||||
@ -110,6 +120,13 @@ type
|
||||
|
||||
procedure SnapshotBtnClick(Sender: TObject);
|
||||
procedure SnapshotBtnEnter(Sender: TObject);
|
||||
procedure CopyMenuItemClick(Sender: TObject);
|
||||
procedure CutMenuItemClick(Sender: TObject);
|
||||
procedure DeleteMenuItemClick(Sender: TObject);
|
||||
procedure PasteMenuItemClick(Sender: TObject);
|
||||
procedure RedoMenuItemClick(Sender: TObject);
|
||||
procedure SelectAllMenuItemClick(Sender: TObject);
|
||||
procedure UndoMenuItemClick(Sender: TObject);
|
||||
|
||||
protected
|
||||
FPopUpBitmap : TBitmap;
|
||||
@ -124,17 +141,10 @@ type
|
||||
FMouseWheelService : IFMXMouseService;
|
||||
{$ENDIF}
|
||||
|
||||
FLastClickCount : integer;
|
||||
FLastClickTime : integer;
|
||||
FLastClickPoint : TPointF;
|
||||
FLastClickButton : TMouseButton;
|
||||
|
||||
procedure LoadURL;
|
||||
function getModifiers(Shift: TShiftState): TCefEventFlags;
|
||||
function getModifiers(Shift: TShiftState; KeyCode: integer = 0): TCefEventFlags;
|
||||
function GetButton(Button: TMouseButton): TCefMouseButtonType;
|
||||
function GetMousePosition(var aPoint : TPointF) : boolean;
|
||||
procedure InitializeLastClick;
|
||||
function CancelPreviousClick(const x, y : single; var aCurrentTime : integer) : boolean;
|
||||
|
||||
public
|
||||
procedure DoResize;
|
||||
@ -152,10 +162,7 @@ var
|
||||
// This demo is in ALPHA state. It's incomplete and some features may not work!
|
||||
// ****************************************************************************
|
||||
// Known issues and missing features :
|
||||
// - 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.
|
||||
// - Right-click crashes the demo.
|
||||
|
||||
|
||||
@ -227,8 +234,10 @@ implementation
|
||||
{$R *.fmx}
|
||||
|
||||
uses
|
||||
System.SysUtils, System.Math, FMX.Platform, {$IFDEF MSWINDOWS}FMX.Platform.Win,{$ENDIF}
|
||||
uCEFMiscFunctions, uCEFApplication, uFMXApplicationService;
|
||||
System.SysUtils, System.Math, System.IOUtils,
|
||||
FMX.Platform,
|
||||
uCEFMiscFunctions, uCEFApplication, uFMXApplicationService,
|
||||
uCEFMacOSConstants, uCEFMacOSFunctions;
|
||||
|
||||
procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64);
|
||||
begin
|
||||
@ -252,13 +261,12 @@ begin
|
||||
GlobalCEFApp.ExternalMessagePump := True;
|
||||
GlobalCEFApp.MultiThreadedMessageLoop := False;
|
||||
GlobalCEFApp.UseMockKeyChain := True;
|
||||
//GlobalCEFApp.SingleProcess := True;
|
||||
GlobalCEFApp.OnScheduleMessagePumpWork := GlobalCEFApp_OnScheduleMessagePumpWork;
|
||||
//GlobalCEFApp.EnableGPU := True;
|
||||
|
||||
// Replace <username> with your username to create a log file in your home directory
|
||||
//GlobalCEFApp.LogFile := '/Users/<username>/debug.log';
|
||||
//GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
{$IFDEF DEBUG}
|
||||
GlobalCEFApp.LogFile := TPath.GetHomePath + TPath.DirectorySeparatorChar + 'debug.log';
|
||||
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.FormActivate(Sender: TObject);
|
||||
@ -268,7 +276,8 @@ begin
|
||||
// opaque white background color
|
||||
chrmosr.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF);
|
||||
|
||||
if not(chrmosr.CreateBrowser) then Timer1.Enabled := True;
|
||||
if not(chrmosr.CreateBrowser) then
|
||||
Timer1.Enabled := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -286,10 +295,6 @@ begin
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.FormCreate(Sender: TObject);
|
||||
{$IFDEF MSWINDOWS}
|
||||
var
|
||||
TempMajorVer, TempMinorVer : DWORD;
|
||||
{$ENDIF}
|
||||
begin
|
||||
TFMXApplicationService.AddPlatformService;
|
||||
|
||||
@ -304,8 +309,6 @@ begin
|
||||
|
||||
chrmosr.DefaultURL := AddressEdt.Text;
|
||||
|
||||
InitializeLastClick;
|
||||
|
||||
{$IFDEF DELPHI17_UP}
|
||||
if TPlatformServices.Current.SupportsPlatformService(IFMXMouseService) then
|
||||
FMouseWheelService := TPlatformServices.Current.GetPlatformService(IFMXMouseService) as IFMXMouseService;
|
||||
@ -358,8 +361,9 @@ begin
|
||||
Panel1.SetFocus;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1DialogKey(Sender: TObject;
|
||||
var Key: Word; Shift: TShiftState);
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1DialogKey( Sender : TObject;
|
||||
var Key : Word;
|
||||
Shift : TShiftState);
|
||||
begin
|
||||
if (Key = vkTab) then Key := 0;
|
||||
end;
|
||||
@ -374,29 +378,23 @@ begin
|
||||
chrmosr.SendFocusEvent(False);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1KeyUp(Sender: TObject; var Key: Word;
|
||||
var KeyChar: Char; Shift: TShiftState);
|
||||
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;
|
||||
if not(Panel1.IsFocused) or (KeyChar = #0) then
|
||||
exit;
|
||||
|
||||
TempKeyEvent.kind := KEYEVENT_KEYUP;
|
||||
TempKeyEvent.modifiers := getModifiers(Shift);
|
||||
TempKeyEvent.native_key_code := KeyToMacOSKeyCode(Key);
|
||||
TempKeyEvent.modifiers := getModifiers(Shift, TempKeyEvent.native_key_code);
|
||||
TempKeyEvent.windows_key_code := 0;
|
||||
TempKeyEvent.native_key_code := 0;
|
||||
TempKeyEvent.is_system_key := ord(False);
|
||||
TempKeyEvent.character := TempChar;
|
||||
TempKeyEvent.unmodified_character := TempChar;
|
||||
TempKeyEvent.character := KeyChar;
|
||||
TempKeyEvent.unmodified_character := KeyChar;
|
||||
TempKeyEvent.focus_on_editable_field := ord(False);
|
||||
|
||||
chrmosr.SendKeyEvent(@TempKeyEvent);
|
||||
@ -408,40 +406,27 @@ procedure TFMXExternalPumpBrowserFrm.Panel1KeyDown( Sender : TObject;
|
||||
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
|
||||
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.native_key_code := KeyToMacOSKeyCode(Key);
|
||||
TempKeyEvent.modifiers := getModifiers(Shift, TempKeyEvent.native_key_code);
|
||||
TempKeyEvent.windows_key_code := 0;
|
||||
TempKeyEvent.native_key_code := 0;
|
||||
TempKeyEvent.is_system_key := ord(False);
|
||||
TempKeyEvent.character := TempChar;
|
||||
TempKeyEvent.unmodified_character := TempChar;
|
||||
TempKeyEvent.character := KeyChar;
|
||||
TempKeyEvent.unmodified_character := KeyChar;
|
||||
TempKeyEvent.focus_on_editable_field := ord(False);
|
||||
|
||||
chrmosr.SendKeyEvent(@TempKeyEvent);
|
||||
|
||||
TempKeyEvent.kind := KEYEVENT_CHAR;
|
||||
|
||||
chrmosr.SendKeyEvent(@TempKeyEvent);
|
||||
if not(TempKeyEvent.native_key_code in CEF_MACOS_KEYPAD_KEYS +
|
||||
CEF_MACOS_ARROW_KEYS +
|
||||
CEF_MACOS_FUNCTION_KEYS) then
|
||||
begin
|
||||
TempKeyEvent.kind := KEYEVENT_CHAR;
|
||||
chrmosr.SendKeyEvent(@TempKeyEvent);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Panel1MouseDown(Sender : TObject;
|
||||
@ -450,28 +435,22 @@ procedure TFMXExternalPumpBrowserFrm.Panel1MouseDown(Sender : TObject;
|
||||
X, Y : Single);
|
||||
var
|
||||
TempEvent : TCefMouseEvent;
|
||||
TempTime : integer;
|
||||
TempCount : integer;
|
||||
begin
|
||||
if not(ssTouch in Shift) then
|
||||
begin
|
||||
Panel1.SetFocus;
|
||||
|
||||
if not(CancelPreviousClick(x, y, TempTime)) and (Button = FLastClickButton) then
|
||||
inc(FLastClickCount)
|
||||
else
|
||||
begin
|
||||
FLastClickPoint.x := x;
|
||||
FLastClickPoint.y := y;
|
||||
FLastClickCount := 1;
|
||||
end;
|
||||
|
||||
FLastClickTime := TempTime;
|
||||
FLastClickButton := Button;
|
||||
|
||||
TempEvent.x := round(X);
|
||||
TempEvent.y := round(Y);
|
||||
TempEvent.modifiers := getModifiers(Shift);
|
||||
chrmosr.SendMouseClickEvent(@TempEvent, GetButton(Button), False, FLastClickCount);
|
||||
|
||||
if (ssDouble in Shift) then
|
||||
TempCount := 2
|
||||
else
|
||||
TempCount := 1;
|
||||
|
||||
chrmosr.SendMouseClickEvent(@TempEvent, GetButton(Button), False, TempCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -499,21 +478,14 @@ procedure TFMXExternalPumpBrowserFrm.Panel1MouseLeave(Sender: TObject);
|
||||
var
|
||||
TempEvent : TCefMouseEvent;
|
||||
TempPoint : TPointF;
|
||||
TempTime : integer;
|
||||
begin
|
||||
if GetMousePosition(TempPoint) then
|
||||
begin
|
||||
TempPoint := Panel1.ScreenToClient(TempPoint);
|
||||
|
||||
if CancelPreviousClick(TempPoint.x, TempPoint.y, TempTime) then InitializeLastClick;
|
||||
|
||||
TempPoint := Panel1.ScreenToClient(TempPoint);
|
||||
TempEvent.x := round(TempPoint.x);
|
||||
TempEvent.y := round(TempPoint.y);
|
||||
{$IFDEF MSWINDOWS}
|
||||
TempEvent.modifiers := GetCefMouseModifiers;
|
||||
{$ELSE}
|
||||
TempEvent.modifiers := EVENTFLAG_NONE;
|
||||
{$ENDIF}
|
||||
|
||||
chrmosr.SendMouseMoveEvent(@TempEvent, True);
|
||||
end;
|
||||
end;
|
||||
@ -523,15 +495,13 @@ procedure TFMXExternalPumpBrowserFrm.Panel1MouseMove(Sender : TObject;
|
||||
X, Y : Single);
|
||||
var
|
||||
TempEvent : TCefMouseEvent;
|
||||
TempTime : integer;
|
||||
begin
|
||||
if not(ssTouch in Shift) then
|
||||
begin
|
||||
if CancelPreviousClick(x, y, TempTime) then InitializeLastClick;
|
||||
|
||||
TempEvent.x := round(x);
|
||||
TempEvent.y := round(y);
|
||||
TempEvent.modifiers := getModifiers(Shift);
|
||||
|
||||
chrmosr.SendMouseMoveEvent(@TempEvent, False);
|
||||
end;
|
||||
end;
|
||||
@ -542,13 +512,20 @@ procedure TFMXExternalPumpBrowserFrm.Panel1MouseUp(Sender : TObject;
|
||||
X, Y : Single);
|
||||
var
|
||||
TempEvent : TCefMouseEvent;
|
||||
TempCount : integer;
|
||||
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, FLastClickCount);
|
||||
|
||||
if (ssDouble in Shift) then
|
||||
TempCount := 2
|
||||
else
|
||||
TempCount := 1;
|
||||
|
||||
chrmosr.SendMouseClickEvent(@TempEvent, GetButton(Button), True, TempCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -566,6 +543,7 @@ begin
|
||||
TempEvent.x := round(TempPoint.x);
|
||||
TempEvent.y := round(TempPoint.y);
|
||||
TempEvent.modifiers := getModifiers(Shift);
|
||||
|
||||
chrmosr.SendMouseWheelEvent(@TempEvent, 0, WheelDelta);
|
||||
end;
|
||||
end;
|
||||
@ -575,6 +553,16 @@ begin
|
||||
DoResize;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.PasteMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardPaste;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.RedoMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardRedo;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.Timer1Timer(Sender: TObject);
|
||||
begin
|
||||
Timer1.Enabled := False;
|
||||
@ -583,6 +571,11 @@ begin
|
||||
Timer1.Enabled := True;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.UndoMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardUndo;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.AddressEdtEnter(Sender: TObject);
|
||||
begin
|
||||
chrmosr.SendFocusEvent(False);
|
||||
@ -600,10 +593,10 @@ procedure TFMXExternalPumpBrowserFrm.chrmosrBeforeClose(Sender: TObject; const b
|
||||
begin
|
||||
FCanClose := True;
|
||||
|
||||
TThread.Queue(nil, procedure
|
||||
begin
|
||||
close
|
||||
end);
|
||||
TThread.ForceQueue(nil, procedure
|
||||
begin
|
||||
close
|
||||
end);
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.chrmosrBeforePopup( Sender : TObject;
|
||||
@ -842,7 +835,7 @@ begin
|
||||
if (type_ = PET_VIEW) then
|
||||
begin
|
||||
if TempForcedResize or FPendingResize then
|
||||
TThread.Queue(nil, DoResize);
|
||||
TThread.ForceQueue(nil, DoResize);
|
||||
|
||||
FResizing := False;
|
||||
FPendingResize := False;
|
||||
@ -895,6 +888,21 @@ begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.CopyMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardCopy;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.CutMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardCut;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.DeleteMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.ClipboardDel;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.DoResize;
|
||||
begin
|
||||
try
|
||||
@ -934,21 +942,30 @@ begin
|
||||
if (chrmosr <> nil) then chrmosr.NotifyMoveOrResizeStarted;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.SelectAllMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
chrmosr.SelectAll;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.SendCaptureLostEvent;
|
||||
begin
|
||||
if (chrmosr <> nil) then chrmosr.SendCaptureLostEvent;
|
||||
end;
|
||||
|
||||
function TFMXExternalPumpBrowserFrm.getModifiers(Shift: TShiftState): TCefEventFlags;
|
||||
function TFMXExternalPumpBrowserFrm.getModifiers(Shift: TShiftState; KeyCode: integer): 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;
|
||||
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;
|
||||
if (ssCommand in Shift) then Result := Result or EVENTFLAG_COMMAND_DOWN;
|
||||
|
||||
if (KeyCode in CEF_MACOS_KEYPAD_KEYS) then
|
||||
Result := Result or EVENTFLAG_IS_KEY_PAD;
|
||||
end;
|
||||
|
||||
function TFMXExternalPumpBrowserFrm.GetButton(Button: TMouseButton): TCefMouseButtonType;
|
||||
@ -960,29 +977,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.InitializeLastClick;
|
||||
begin
|
||||
FLastClickCount := 1;
|
||||
FLastClickTime := 0;
|
||||
FLastClickPoint.x := 0;
|
||||
FLastClickPoint.y := 0;
|
||||
FLastClickButton := TMouseButton.mbLeft;
|
||||
end;
|
||||
|
||||
function TFMXExternalPumpBrowserFrm.CancelPreviousClick(const x, y : single; var aCurrentTime : integer) : boolean;
|
||||
begin
|
||||
{$IFDEF MSWINDOWS}
|
||||
aCurrentTime := GetMessageTime;
|
||||
|
||||
Result := (abs(FLastClickPoint.x - x) > (GetSystemMetrics(SM_CXDOUBLECLK) div 2)) or
|
||||
(abs(FLastClickPoint.y - y) > (GetSystemMetrics(SM_CYDOUBLECLK) div 2)) or
|
||||
(cardinal(aCurrentTime - FLastClickTime) > GetDoubleClickTime);
|
||||
{$ELSE}
|
||||
aCurrentTime := 0;
|
||||
Result := False;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TFMXExternalPumpBrowserFrm.SnapshotBtnClick(Sender: TObject);
|
||||
begin
|
||||
if SaveDialog1.Execute then Panel1.SaveToFile(SaveDialog1.FileName);
|
||||
|
@ -491,7 +491,7 @@ begin
|
||||
Result := HandleAllocated and PostMessage(Handle, CM_INVALIDATE, 0, 0);
|
||||
{$ELSE}
|
||||
Result := True;
|
||||
TThread.Queue(nil, @Invalidate);
|
||||
TThread.ForceQueue(nil, @Invalidate);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
|
@ -748,6 +748,7 @@ type
|
||||
procedure ClearDataForOrigin(const aOrigin : ustring; aStorageTypes : TCefClearDataStorageTypes = cdstAll);
|
||||
procedure ClearCache;
|
||||
|
||||
|
||||
function DeleteCookies(const url : ustring = ''; const cookieName : ustring = ''; aDeleteImmediately : boolean = False) : boolean;
|
||||
function VisitAllCookies(aID : integer = 0) : boolean;
|
||||
function VisitURLCookies(const url : ustring; includeHttpOnly : boolean = False; aID : integer = 0) : boolean;
|
||||
@ -2165,6 +2166,7 @@ begin
|
||||
Browser.Host.Print;
|
||||
end;
|
||||
|
||||
// The TChromiumCore.OnPdfPrintFinished event will be triggered when the PDF file is created.
|
||||
procedure TChromiumCore.PrintToPDF(const aFilePath, aTitle, aURL : ustring);
|
||||
var
|
||||
TempSettings : TCefPdfPrintSettings;
|
||||
@ -2512,7 +2514,7 @@ begin
|
||||
Browser.Host.StartDownload(aURL);
|
||||
end;
|
||||
|
||||
// Use the OnDownloadImageFinished event to receive the image
|
||||
// Use the TChromiumCore.OnDownloadImageFinished event to receive the image
|
||||
procedure TChromiumCore.DownloadImage(const imageUrl : ustring;
|
||||
isFavicon : boolean;
|
||||
maxImageSize : cardinal;
|
||||
@ -3634,6 +3636,7 @@ begin
|
||||
end;
|
||||
|
||||
// Leave aFrameName empty to get the HTML source from the main frame
|
||||
// The TChromiumCore.OnTextResultAvailable event will be triggered with the HTML contents
|
||||
procedure TChromiumCore.RetrieveHTML(const aFrameName : ustring);
|
||||
var
|
||||
TempFrame : ICefFrame;
|
||||
@ -3692,6 +3695,7 @@ begin
|
||||
end;
|
||||
|
||||
// Leave aFrameName empty to get the HTML source from the main frame
|
||||
// The TChromiumCore.OnTextResultAvailable event will be triggered with the text contents
|
||||
procedure TChromiumCore.RetrieveText(const aFrameName : ustring);
|
||||
var
|
||||
TempFrame : ICefFrame;
|
||||
@ -3749,6 +3753,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// The TChromiumCore.OnNavigationVisitorResultAvailable event will be triggered for each entry
|
||||
procedure TChromiumCore.GetNavigationEntries(currentOnly: Boolean);
|
||||
var
|
||||
TempVisitor : ICefNavigationEntryVisitor;
|
||||
@ -6616,6 +6621,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// This procedure will trigger OnMediaSinkDeviceInfo with the device info.
|
||||
procedure TChromiumCore.GetDeviceInfo(const aMediaSink: ICefMediaSink);
|
||||
var
|
||||
TempCallback : ICefMediaSinkDeviceInfoCallback;
|
||||
|
@ -276,10 +276,10 @@ begin
|
||||
if FUseQueueThread and (FQueueThread <> nil) and FQueueThread.Ready then
|
||||
FQueueThread.EnqueueValue(integer(delay_ms))
|
||||
else
|
||||
TThread.Queue(nil, procedure
|
||||
begin
|
||||
ScheduleWork(delay_ms);
|
||||
end);
|
||||
TThread.ForceQueue(nil, procedure
|
||||
begin
|
||||
ScheduleWork(delay_ms);
|
||||
end);
|
||||
end;
|
||||
|
||||
procedure TFMXWorkScheduler.StopScheduler;
|
||||
|
@ -65,6 +65,13 @@ function GdkEventToWindowsKeyCode(Event: PGdkEventKey) : integer;
|
||||
function GetWindowsKeyCodeWithoutLocation(key_code : integer) : integer;
|
||||
function GetControlCharacter(windows_key_code : integer; shift : boolean) : integer;
|
||||
{$IFDEF FMX}
|
||||
type
|
||||
TXErrorHandler = function (para1:PDisplay; para2:PXErrorEvent):longint; cdecl;
|
||||
TXIOErrorHandler = function (para1:PDisplay):longint; cdecl;
|
||||
|
||||
function XSetErrorHandler(para1:TXErrorHandler):TXErrorHandler; cdecl; external 'libX11.so';
|
||||
function XSetIOErrorHandler(para1:TXIOErrorHandler):TXIOErrorHandler; cdecl; external 'libX11.so';
|
||||
|
||||
function gdk_keyval_to_unicode(keyval: guint): guint32; cdecl; external 'libgdk-3.so';
|
||||
function g_signal_connect_data(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer; destroy_data: TGClosureNotify; connect_flags: TGConnectFlags): gulong; cdecl; external 'libgobject-2.0.so';
|
||||
function g_signal_connect(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer): gulong; overload;
|
||||
|
@ -80,6 +80,18 @@ type
|
||||
TGdkEventType = int32;
|
||||
PGdkEventKey = ^TGdkEventKey;
|
||||
PXDisplay = pointer;
|
||||
PDisplay = pointer;
|
||||
|
||||
PXErrorEvent = ^TXErrorEvent;
|
||||
TXErrorEvent = record
|
||||
_type : longint;
|
||||
display : PDisplay;
|
||||
resourceid : uint64;
|
||||
serial : uint64;
|
||||
error_code : uint8;
|
||||
request_code : uint8;
|
||||
minor_code : uint8;
|
||||
end;
|
||||
|
||||
PGTypeClass = ^TGTypeClass;
|
||||
TGTypeClass = record
|
||||
|
240
source/uCEFMacOSConstants.pas
Normal file
240
source/uCEFMacOSConstants.pas
Normal file
@ -0,0 +1,240 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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 uCEFMacOSConstants;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE OBJFPC}{$H+}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF}
|
||||
{$MINENUMSIZE 4}
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
interface
|
||||
|
||||
{$IFDEF MACOSX}
|
||||
const
|
||||
// Virtual Keycode constants defined in <HIToolbox/Events.h>
|
||||
// /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
|
||||
// /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
|
||||
|
||||
// These constants are the virtual keycodes defined originally in
|
||||
// Inside Mac Volume V, pg. V-191. They identify physical keys on a
|
||||
// keyboard. Those constants with "ANSI" in the name are labeled
|
||||
// according to the key position on an ANSI-standard US keyboard.
|
||||
// For example, kVK_ANSI_A indicates the virtual keycode for the key
|
||||
// with the letter 'A' in the US keyboard layout. Other keyboard
|
||||
// layouts may have the 'A' key label on a different physical key;
|
||||
// in this case, pressing 'A' will generate a different virtual
|
||||
// keycode.
|
||||
|
||||
kVK_ANSI_A = $00;
|
||||
kVK_ANSI_S = $01;
|
||||
kVK_ANSI_D = $02;
|
||||
kVK_ANSI_F = $03;
|
||||
kVK_ANSI_H = $04;
|
||||
kVK_ANSI_G = $05;
|
||||
kVK_ANSI_Z = $06;
|
||||
kVK_ANSI_X = $07;
|
||||
kVK_ANSI_C = $08;
|
||||
kVK_ANSI_V = $09;
|
||||
kVK_ANSI_B = $0B;
|
||||
kVK_ANSI_Q = $0C;
|
||||
kVK_ANSI_W = $0D;
|
||||
kVK_ANSI_E = $0E;
|
||||
kVK_ANSI_R = $0F;
|
||||
kVK_ANSI_Y = $10;
|
||||
kVK_ANSI_T = $11;
|
||||
kVK_ANSI_1 = $12;
|
||||
kVK_ANSI_2 = $13;
|
||||
kVK_ANSI_3 = $14;
|
||||
kVK_ANSI_4 = $15;
|
||||
kVK_ANSI_6 = $16;
|
||||
kVK_ANSI_5 = $17;
|
||||
kVK_ANSI_Equal = $18;
|
||||
kVK_ANSI_9 = $19;
|
||||
kVK_ANSI_7 = $1A;
|
||||
kVK_ANSI_Minus = $1B;
|
||||
kVK_ANSI_8 = $1C;
|
||||
kVK_ANSI_0 = $1D;
|
||||
kVK_ANSI_RightBracket = $1E;
|
||||
kVK_ANSI_O = $1F;
|
||||
kVK_ANSI_U = $20;
|
||||
kVK_ANSI_LeftBracket = $21;
|
||||
kVK_ANSI_I = $22;
|
||||
kVK_ANSI_P = $23;
|
||||
kVK_ANSI_L = $25;
|
||||
kVK_ANSI_J = $26;
|
||||
kVK_ANSI_Quote = $27;
|
||||
kVK_ANSI_K = $28;
|
||||
kVK_ANSI_Semicolon = $29;
|
||||
kVK_ANSI_Backslash = $2A;
|
||||
kVK_ANSI_Comma = $2B;
|
||||
kVK_ANSI_Slash = $2C;
|
||||
kVK_ANSI_N = $2D;
|
||||
kVK_ANSI_M = $2E;
|
||||
kVK_ANSI_Period = $2F;
|
||||
kVK_ANSI_Grave = $32;
|
||||
kVK_ANSI_KeypadDecimal = $41;
|
||||
kVK_ANSI_KeypadMultiply = $43;
|
||||
kVK_ANSI_KeypadPlus = $45;
|
||||
kVK_ANSI_KeypadClear = $47;
|
||||
kVK_ANSI_KeypadDivide = $4B;
|
||||
kVK_ANSI_KeypadEnter = $4C;
|
||||
kVK_ANSI_KeypadMinus = $4E;
|
||||
kVK_ANSI_KeypadEquals = $51;
|
||||
kVK_ANSI_Keypad0 = $52;
|
||||
kVK_ANSI_Keypad1 = $53;
|
||||
kVK_ANSI_Keypad2 = $54;
|
||||
kVK_ANSI_Keypad3 = $55;
|
||||
kVK_ANSI_Keypad4 = $56;
|
||||
kVK_ANSI_Keypad5 = $57;
|
||||
kVK_ANSI_Keypad6 = $58;
|
||||
kVK_ANSI_Keypad7 = $59;
|
||||
kVK_ANSI_Keypad8 = $5B;
|
||||
kVK_ANSI_Keypad9 = $5C;
|
||||
|
||||
// keycodes for keys that are independent of keyboard layout
|
||||
kVK_Return = $24;
|
||||
kVK_Tab = $30;
|
||||
kVK_Space = $31;
|
||||
kVK_Delete = $33;
|
||||
kVK_Escape = $35;
|
||||
kVK_Command = $37;
|
||||
kVK_Shift = $38;
|
||||
kVK_CapsLock = $39;
|
||||
kVK_Option = $3A;
|
||||
kVK_Control = $3B;
|
||||
kVK_RightShift = $3C;
|
||||
kVK_RightOption = $3D;
|
||||
kVK_RightControl = $3E;
|
||||
kVK_Function = $3F;
|
||||
kVK_F17 = $40;
|
||||
kVK_VolumeUp = $48;
|
||||
kVK_VolumeDown = $49;
|
||||
kVK_Mute = $4A;
|
||||
kVK_F18 = $4F;
|
||||
kVK_F19 = $50;
|
||||
kVK_F20 = $5A;
|
||||
kVK_F5 = $60;
|
||||
kVK_F6 = $61;
|
||||
kVK_F7 = $62;
|
||||
kVK_F3 = $63;
|
||||
kVK_F8 = $64;
|
||||
kVK_F9 = $65;
|
||||
kVK_F11 = $67;
|
||||
kVK_F13 = $69;
|
||||
kVK_F16 = $6A;
|
||||
kVK_F14 = $6B;
|
||||
kVK_F10 = $6D;
|
||||
kVK_F12 = $6F;
|
||||
kVK_F15 = $71;
|
||||
kVK_Help = $72;
|
||||
kVK_Home = $73;
|
||||
kVK_PageUp = $74;
|
||||
kVK_ForwardDelete = $75;
|
||||
kVK_F4 = $76;
|
||||
kVK_End = $77;
|
||||
kVK_F2 = $78;
|
||||
kVK_PageDown = $79;
|
||||
kVK_F1 = $7A;
|
||||
kVK_LeftArrow = $7B;
|
||||
kVK_RightArrow = $7C;
|
||||
kVK_DownArrow = $7D;
|
||||
kVK_UpArrow = $7E;
|
||||
|
||||
// ISO keyboards only
|
||||
kVK_ISO_Section = $0A;
|
||||
|
||||
// JIS keyboards only
|
||||
kVK_JIS_Yen = $5D;
|
||||
kVK_JIS_Underscore = $5E;
|
||||
kVK_JIS_KeypadComma = $5F;
|
||||
kVK_JIS_Eisu = $66;
|
||||
kVK_JIS_Kana = $68;
|
||||
|
||||
CEF_MACOS_KEYPAD_KEYS = [kVK_ANSI_KeypadDecimal,
|
||||
kVK_ANSI_KeypadMultiply,
|
||||
kVK_ANSI_KeypadPlus,
|
||||
kVK_ANSI_KeypadClear,
|
||||
kVK_ANSI_KeypadDivide,
|
||||
kVK_ANSI_KeypadEnter,
|
||||
kVK_ANSI_KeypadMinus,
|
||||
kVK_ANSI_KeypadEquals,
|
||||
kVK_ANSI_Keypad0,
|
||||
kVK_ANSI_Keypad1,
|
||||
kVK_ANSI_Keypad2,
|
||||
kVK_ANSI_Keypad3,
|
||||
kVK_ANSI_Keypad4,
|
||||
kVK_ANSI_Keypad5,
|
||||
kVK_ANSI_Keypad6,
|
||||
kVK_ANSI_Keypad7,
|
||||
kVK_ANSI_Keypad8,
|
||||
kVK_ANSI_Keypad9];
|
||||
|
||||
CEF_MACOS_ARROW_KEYS = [kVK_LeftArrow,
|
||||
kVK_RightArrow,
|
||||
kVK_DownArrow,
|
||||
kVK_UpArrow];
|
||||
|
||||
CEF_MACOS_FUNCTION_KEYS = [kVK_F1,
|
||||
kVK_F2,
|
||||
kVK_F3,
|
||||
kVK_F4,
|
||||
kVK_F5,
|
||||
kVK_F6,
|
||||
kVK_F7,
|
||||
kVK_F8,
|
||||
kVK_F9,
|
||||
kVK_F10,
|
||||
kVK_F11,
|
||||
kVK_F12,
|
||||
kVK_F13,
|
||||
kVK_F14,
|
||||
kVK_F15,
|
||||
kVK_F16,
|
||||
kVK_F17,
|
||||
kVK_F18,
|
||||
kVK_F19,
|
||||
kVK_F20];
|
||||
{$ENDIF}
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -35,17 +35,37 @@
|
||||
*
|
||||
*)
|
||||
|
||||
unit uFMXMiscFunctions;
|
||||
unit uCEFMacOSFunctions;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE OBJFPC}{$H+}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF}
|
||||
{$MINENUMSIZE 4}
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.UITypes,
|
||||
uCEFMacOSConstants;
|
||||
|
||||
{$IFDEF MACOSX}
|
||||
function KeyToMacOSKeyCode(aKey : Word): integer;
|
||||
{$IFDEF FMX}
|
||||
procedure CopyCEFFramework;
|
||||
procedure CopyCEFHelpers(const aProjectName : string);
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF MACOSX}
|
||||
{$IFDEF FMX}
|
||||
uses
|
||||
System.SysUtils, System.Types, System.IOUtils, Posix.Stdio,
|
||||
System.SysUtils, System.Types, System.IOUtils, Posix.Stdio, FMX.Types,
|
||||
uCEFMiscFunctions;
|
||||
|
||||
const
|
||||
@ -53,11 +73,144 @@ const
|
||||
PRJ_GPU_SUBFIX = '_helper_gpu';
|
||||
PRJ_PLUGIN_SUBFIX = '_helper_plugin';
|
||||
PRJ_RENDERER_SUBFIX = '_helper_renderer';
|
||||
HELPER_SUBFIX = ' Helper';
|
||||
GPU_SUBFIX = ' Helper (GPU)';
|
||||
PLUGIN_SUBFIX = ' Helper (Plugin)';
|
||||
RENDERER_SUBFIX = ' Helper (Renderer)';
|
||||
HELPER_SUBFIX = ' Helper';
|
||||
GPU_SUBFIX = ' Helper (GPU)';
|
||||
PLUGIN_SUBFIX = ' Helper (Plugin)';
|
||||
RENDERER_SUBFIX = ' Helper (Renderer)';
|
||||
{$ENDIF}
|
||||
|
||||
// Key Code translation following the information found in these documents :
|
||||
// https://developer.apple.com/library/archive/documentation/mac/pdf/MacintoshToolboxEssentials.pdf
|
||||
// https://eastmanreference.com/complete-list-of-applescript-key-codes
|
||||
|
||||
function KeyToMacOSKeyCode(aKey : Word): integer;
|
||||
begin
|
||||
case aKey of
|
||||
vkBack : Result := kVK_Delete;
|
||||
vkTab : Result := kVK_Tab;
|
||||
vkClear : Result := kVK_ANSI_KeypadClear;
|
||||
vkReturn : Result := kVK_Return;
|
||||
vkShift : Result := kVK_Shift;
|
||||
vkControl : Result := kVK_Control;
|
||||
vkMenu : Result := kVK_Option;
|
||||
vkPause : Result := kVK_F15;
|
||||
vkCapital : Result := kVK_CapsLock;
|
||||
vkEscape : Result := kVK_Escape;
|
||||
vkSpace : Result := kVK_Space;
|
||||
vkPrior : Result := kVK_PageUp;
|
||||
vkNext : Result := kVK_PageDown;
|
||||
vkEnd : Result := kVK_End;
|
||||
vkHome : Result := kVK_Home;
|
||||
vkLeft : Result := kVK_LeftArrow;
|
||||
vkUp : Result := kVK_UpArrow;
|
||||
vkRight : Result := kVK_RightArrow;
|
||||
vkDown : Result := kVK_DownArrow;
|
||||
vkSnapshot : Result := kVK_F13;
|
||||
vkHelp,
|
||||
vkInsert : Result := kVK_Help;
|
||||
vkDelete : Result := kVK_ForwardDelete;
|
||||
vk0 : Result := kVK_ANSI_0;
|
||||
vk1 : Result := kVK_ANSI_1;
|
||||
vk2 : Result := kVK_ANSI_2;
|
||||
vk3 : Result := kVK_ANSI_3;
|
||||
vk4 : Result := kVK_ANSI_4;
|
||||
vk5 : Result := kVK_ANSI_5;
|
||||
vk6 : Result := kVK_ANSI_6;
|
||||
vk7 : Result := kVK_ANSI_7;
|
||||
vk8 : Result := kVK_ANSI_8;
|
||||
vk9 : Result := kVK_ANSI_9;
|
||||
vkA : Result := kVK_ANSI_A;
|
||||
vkB : Result := kVK_ANSI_B;
|
||||
vkC : Result := kVK_ANSI_C;
|
||||
vkD : Result := kVK_ANSI_D;
|
||||
vkE : Result := kVK_ANSI_E;
|
||||
vkF : Result := kVK_ANSI_F;
|
||||
vkG : Result := kVK_ANSI_G;
|
||||
vkH : Result := kVK_ANSI_H;
|
||||
vkI : Result := kVK_ANSI_I;
|
||||
vkJ : Result := kVK_ANSI_J;
|
||||
vkK : Result := kVK_ANSI_K;
|
||||
vkL : Result := kVK_ANSI_L;
|
||||
vkM : Result := kVK_ANSI_M;
|
||||
vkN : Result := kVK_ANSI_N;
|
||||
vkO : Result := kVK_ANSI_O;
|
||||
vkP : Result := kVK_ANSI_P;
|
||||
vkQ : Result := kVK_ANSI_Q;
|
||||
vkR : Result := kVK_ANSI_R;
|
||||
vkS : Result := kVK_ANSI_S;
|
||||
vkT : Result := kVK_ANSI_T;
|
||||
vkU : Result := kVK_ANSI_U;
|
||||
vkV : Result := kVK_ANSI_V;
|
||||
vkW : Result := kVK_ANSI_W;
|
||||
vkX : Result := kVK_ANSI_X;
|
||||
vkY : Result := kVK_ANSI_Y;
|
||||
vkZ : Result := kVK_ANSI_Z;
|
||||
vkLWin : Result := kVK_Option;
|
||||
vkRWin : Result := kVK_RightOption;
|
||||
vkNumpad0 : Result := kVK_ANSI_Keypad0;
|
||||
vkNumpad1 : Result := kVK_ANSI_Keypad1;
|
||||
vkNumpad2 : Result := kVK_ANSI_Keypad2;
|
||||
vkNumpad3 : Result := kVK_ANSI_Keypad3;
|
||||
vkNumpad4 : Result := kVK_ANSI_Keypad4;
|
||||
vkNumpad5 : Result := kVK_ANSI_Keypad5;
|
||||
vkNumpad6 : Result := kVK_ANSI_Keypad6;
|
||||
vkNumpad7 : Result := kVK_ANSI_Keypad7;
|
||||
vkNumpad8 : Result := kVK_ANSI_Keypad8;
|
||||
vkNumpad9 : Result := kVK_ANSI_Keypad9;
|
||||
vkMultiply : Result := kVK_ANSI_KeypadMultiply;
|
||||
vkAdd : Result := kVK_ANSI_KeypadPlus;
|
||||
vkSubtract : Result := kVK_ANSI_KeypadMinus;
|
||||
vkDecimal : Result := kVK_ANSI_KeypadDecimal;
|
||||
vkDivide : Result := kVK_ANSI_KeypadDivide;
|
||||
vkF1 : Result := kVK_F1;
|
||||
vkF2 : Result := kVK_F2;
|
||||
vkF3 : Result := kVK_F3;
|
||||
vkF4 : Result := kVK_F4;
|
||||
vkF5 : Result := kVK_F5;
|
||||
vkF6 : Result := kVK_F6;
|
||||
vkF7 : Result := kVK_F7;
|
||||
vkF8 : Result := kVK_F8;
|
||||
vkF9 : Result := kVK_F9;
|
||||
vkF10 : Result := kVK_F10;
|
||||
vkF11 : Result := kVK_F11;
|
||||
vkF12 : Result := kVK_F12;
|
||||
vkF13 : Result := kVK_F13;
|
||||
vkF14 : Result := kVK_F14;
|
||||
vkF15 : Result := kVK_F15;
|
||||
vkF16 : Result := kVK_F16;
|
||||
vkF17 : Result := kVK_F17;
|
||||
vkF18 : Result := kVK_F18;
|
||||
vkF19 : Result := kVK_F19;
|
||||
vkF20 : Result := kVK_F20;
|
||||
vkNumLock : Result := kVK_ANSI_KeypadClear;
|
||||
vkScroll : Result := kVK_F14;
|
||||
vkLShift : Result := kVK_Shift;
|
||||
vkRShift : Result := kVK_RightShift;
|
||||
vkLControl : Result := kVK_Control;
|
||||
vkRControl : Result := kVK_RightControl;
|
||||
vkLMenu,
|
||||
vkRMenu : Result := kVK_Command;
|
||||
vkVolumeMute : Result := kVK_Mute;
|
||||
vkVolumeDown : Result := kVK_VolumeDown;
|
||||
vkVolumeUp : Result := kVK_VolumeUp;
|
||||
vkSemicolon : Result := kVK_ANSI_Semicolon;
|
||||
vkEqual : Result := kVK_ANSI_Equal;
|
||||
vkComma : Result := kVK_ANSI_Comma;
|
||||
vkMinus : Result := kVK_ANSI_Minus;
|
||||
vkPeriod : Result := kVK_ANSI_Period;
|
||||
vkSlash : Result := kVK_ANSI_Slash;
|
||||
vkTilde : Result := kVK_ANSI_Grave;
|
||||
vkLeftBracket : Result := kVK_ANSI_LeftBracket;
|
||||
vkBackslash : Result := kVK_ANSI_Backslash;
|
||||
vkRightBracket : Result := kVK_ANSI_RightBracket;
|
||||
vkQuote : Result := kVK_ANSI_Quote;
|
||||
vkOem102 : Result := kVK_ANSI_Backslash; // kVK_JIS_Yen in Japanese keyboards ?
|
||||
vkOemClear : Result := kVK_ANSI_KeypadClear;
|
||||
else Result := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF FMX}
|
||||
procedure CopyAllFiles(const aSrcPath, aDstPath: string);
|
||||
var
|
||||
TempDirectories, TempFiles : TStringDynArray;
|
||||
@ -88,7 +241,7 @@ begin
|
||||
end;
|
||||
except
|
||||
on e : exception do
|
||||
WriteLn('CopyAllFiles error : ' + e.Message);
|
||||
FMX.Types.Log.d('CopyAllFiles error : ' + e.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -114,7 +267,7 @@ begin
|
||||
end;
|
||||
except
|
||||
on e : exception do
|
||||
WriteLn('CopyCEFFramework error : ' + e.Message);
|
||||
FMX.Types.Log.d('CopyCEFFramework error : ' + e.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -171,8 +324,8 @@ begin
|
||||
RenameFile(aHelperPrjPath, appNewBundlePath);
|
||||
end;
|
||||
except
|
||||
on e: exception do
|
||||
WriteLn('RenameCEFHelper error : ' + e.Message);
|
||||
on e : exception do
|
||||
FMX.Types.Log.d('RenameCEFHelper error : ' + e.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -212,7 +365,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
@ -46,13 +46,6 @@ unit uCEFWorkScheduler;
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
// Define this conditional to use TCEFWorkSchedulerQueueThread instead of using
|
||||
// PostMessage, Application.QueueAsyncCall or TThread.Queue inside
|
||||
// TCEFWorkScheduler.ScheduleMessagePumpWork
|
||||
// TCEFWorkSchedulerQueueThread is just a new experimental way to handle the
|
||||
// external message pump events for all platforms.
|
||||
{.$DEFINE USEQUEUETHREAD}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
@ -66,7 +59,7 @@ uses
|
||||
Messages,
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
uCEFConstants, {$IFDEF USEQUEUETHREAD}uCEFWorkSchedulerQueueThread,{$ENDIF} uCEFWorkSchedulerThread;
|
||||
uCEFConstants, uCEFWorkSchedulerQueueThread, uCEFWorkSchedulerThread;
|
||||
|
||||
|
||||
type
|
||||
@ -74,13 +67,12 @@ type
|
||||
TCEFWorkScheduler = class(TComponent)
|
||||
protected
|
||||
FThread : TCEFWorkSchedulerThread;
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
FQueueThread : TCEFWorkSchedulerQueueThread;
|
||||
{$ENDIF}
|
||||
FDepleteWorkCycles : cardinal;
|
||||
FDepleteWorkDelay : cardinal;
|
||||
FDefaultInterval : integer;
|
||||
FStopped : boolean;
|
||||
FUseQueueThread : boolean;
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$WARN SYMBOL_PLATFORM OFF}
|
||||
FCompHandle : HWND;
|
||||
@ -88,11 +80,9 @@ type
|
||||
{$WARN SYMBOL_PLATFORM ON}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
procedure CreateQueueThread;
|
||||
procedure DestroyQueueThread;
|
||||
procedure QueueThread_OnPulse(Sender : TObject; aDelay : integer);
|
||||
{$ENDIF}
|
||||
|
||||
procedure DestroyThread;
|
||||
procedure DepleteWork;
|
||||
@ -136,6 +126,7 @@ type
|
||||
property DefaultInterval : integer read FDefaultInterval write SetDefaultInterval default CEF_TIMER_MAXDELAY;
|
||||
property DepleteWorkCycles : cardinal read FDepleteWorkCycles write FDepleteWorkCycles default CEF_TIMER_DEPLETEWORK_CYCLES;
|
||||
property DepleteWorkDelay : cardinal read FDepleteWorkDelay write FDepleteWorkDelay default CEF_TIMER_DEPLETEWORK_DELAY;
|
||||
property UseQueueThread : boolean read FUseQueueThread write FUseQueueThread default False;
|
||||
end;
|
||||
|
||||
var
|
||||
@ -199,9 +190,7 @@ end;
|
||||
destructor TCEFWorkScheduler.Destroy;
|
||||
begin
|
||||
DestroyThread;
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
DestroyQueueThread;
|
||||
{$ENDIF}
|
||||
{$IFDEF MSWINDOWS}
|
||||
DeallocateWindowHandle;
|
||||
{$ENDIF}
|
||||
@ -210,10 +199,9 @@ end;
|
||||
|
||||
procedure TCEFWorkScheduler.Initialize;
|
||||
begin
|
||||
FUseQueueThread := False;
|
||||
FThread := nil;
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
FQueueThread := nil;
|
||||
{$ENDIF}
|
||||
FStopped := False;
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$WARN SYMBOL_PLATFORM OFF}
|
||||
@ -246,12 +234,10 @@ begin
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
CreateQueueThread;
|
||||
{$ENDIF}
|
||||
end;
|
||||
if FUseQueueThread then
|
||||
CreateQueueThread;
|
||||
end;
|
||||
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
procedure TCEFWorkScheduler.CreateQueueThread;
|
||||
begin
|
||||
FQueueThread := TCEFWorkSchedulerQueueThread.Create;
|
||||
@ -287,7 +273,6 @@ procedure TCEFWorkScheduler.QueueThread_OnPulse(Sender : TObject; aDelay : integ
|
||||
begin
|
||||
ScheduleWork(aDelay);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure TCEFWorkScheduler.DestroyThread;
|
||||
begin
|
||||
@ -322,6 +307,14 @@ begin
|
||||
FCompHandle := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$WARN SYMBOL_PLATFORM OFF}
|
||||
procedure TCEFWorkScheduler.SetPriority(aValue : TThreadPriority);
|
||||
begin
|
||||
FPriority := aValue;
|
||||
if (FThread <> nil) then FThread.Priority := aValue;
|
||||
end;
|
||||
{$WARN SYMBOL_PLATFORM ON}
|
||||
{$ENDIF}
|
||||
|
||||
procedure TCEFWorkScheduler.DoMessageLoopWork;
|
||||
@ -335,16 +328,6 @@ begin
|
||||
if (FThread <> nil) then FThread.DefaultInterval := aValue;
|
||||
end;
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$WARN SYMBOL_PLATFORM OFF}
|
||||
procedure TCEFWorkScheduler.SetPriority(aValue : TThreadPriority);
|
||||
begin
|
||||
FPriority := aValue;
|
||||
if (FThread <> nil) then FThread.Priority := aValue;
|
||||
end;
|
||||
{$WARN SYMBOL_PLATFORM ON}
|
||||
{$ENDIF}
|
||||
|
||||
procedure TCEFWorkScheduler.DepleteWork;
|
||||
var
|
||||
i : cardinal;
|
||||
@ -363,27 +346,24 @@ procedure TCEFWorkScheduler.ScheduleMessagePumpWork(const delay_ms : int64);
|
||||
begin
|
||||
if FStopped then exit;
|
||||
|
||||
{$IFDEF USEQUEUETHREAD}
|
||||
if (FQueueThread <> nil) and FQueueThread.Ready then
|
||||
begin
|
||||
FQueueThread.EnqueueValue(integer(delay_ms));
|
||||
exit;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
if (FCompHandle <> 0) then
|
||||
PostMessage(FCompHandle, CEF_PUMPHAVEWORK, 0, LPARAM(delay_ms));
|
||||
{$ELSE}
|
||||
{$IFDEF FPC}
|
||||
Application.QueueAsyncCall(@ScheduleWorkAsync, integer(delay_ms));
|
||||
{$ELSE}
|
||||
TThread.Queue(nil, procedure
|
||||
begin
|
||||
ScheduleWork(delay_ms);
|
||||
end);
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
if FUseQueueThread and (FQueueThread <> nil) and FQueueThread.Ready then
|
||||
FQueueThread.EnqueueValue(integer(delay_ms))
|
||||
else
|
||||
begin
|
||||
{$IFDEF MSWINDOWS}
|
||||
if (FCompHandle <> 0) then
|
||||
PostMessage(FCompHandle, CEF_PUMPHAVEWORK, 0, LPARAM(delay_ms));
|
||||
{$ELSE}
|
||||
{$IFDEF FPC}
|
||||
Application.QueueAsyncCall(@ScheduleWorkAsync, integer(delay_ms));
|
||||
{$ELSE}
|
||||
TThread.ForceQueue(nil, procedure
|
||||
begin
|
||||
ScheduleWork(delay_ms);
|
||||
end);
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFNDEF MSWINDOWS}{$IFDEF FPC}
|
||||
|
@ -91,7 +91,7 @@ type
|
||||
procedure EnqueueValue(aValue : integer);
|
||||
|
||||
property Ready : boolean read FReady;
|
||||
property OnPulse : TOnPulseEvent read FOnPulse write FOnPulse;
|
||||
property OnPulse : TOnPulseEvent read FOnPulse write FOnPulse;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
@ -176,7 +176,9 @@ begin
|
||||
FPulsing := False;
|
||||
finally
|
||||
Unlock;
|
||||
if not(Terminated) then Synchronize({$IFDEF FPC}self, @{$ENDIF}DoOnPulseEvent);
|
||||
|
||||
if not(Terminated) then
|
||||
Synchronize({$IFDEF FPC}self, @{$ENDIF}DoOnPulseEvent);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
"UpdateLazPackages" : [
|
||||
{
|
||||
"ForceNotify" : true,
|
||||
"InternalVersion" : 296,
|
||||
"InternalVersion" : 297,
|
||||
"Name" : "cef4delphi_lazarus.lpk",
|
||||
"Version" : "90.6.6.0"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user