1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-02-02 10:25:26 +02:00

Merge pull request #348 from User4martin/fpc-work-mac-1

Thank you very much!
This commit is contained in:
Salvador Díaz Fau 2021-03-01 08:42:09 +01:00 committed by GitHub
commit 811140603e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1939 additions and 50 deletions

View File

@ -5,4 +5,9 @@ cd "$(dirname "$0")"
../../Lazarus_any_OS/AppHelper/create_mac_helper_apps.sh ../../../bin/ExternalPumpBrowser.app
if [ "$(grep -i TCrCocoaApplication ../../../bin/ExternalPumpBrowser.app/Contents/Info.plist)" = "" ];
then
sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/ExternalPumpBrowser.app/Contents/Info.plist
fi
cd "$CDIR"

View File

@ -43,7 +43,9 @@ unit uExternalPumpBrowser;
interface
uses
GlobalCefApplication, Classes, SysUtils, Messages, Forms, Controls, Graphics,
GlobalCefApplication,
uCEFLazarusCocoa, // required for Cocoa
Classes, SysUtils, Messages, Forms, Controls, Graphics,
Dialogs, ExtCtrls, StdCtrls, LMessages, uCEFChromium, uCEFWindowParent,
uCEFConstants, uCEFTypes, uCEFInterfaces, uCEFChromiumEvents,
uCEFLinkedWindowParent, uCEFWorkScheduler;
@ -88,10 +90,9 @@ type
procedure WMSize(var Message: TLMSize); message LM_SIZE;
procedure WMWindowPosChanged(var Message: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED;
procedure SendCompMessage(aMsg : cardinal);
procedure BrowserCreatedMsg(Data: PtrInt);
procedure BrowserCloseFormMsg(Data: PtrInt);
procedure BrowserFocusMsg(Data: PtrInt);
procedure BrowserBeforeCloseMsg(Data: PtrInt);
public
end;
@ -195,7 +196,9 @@ end;
procedure TForm1.Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
begin
aAction := cbaClose;
// continue closing the browser
CEFLinkedWindowParent1.DestroyChildWindow;
aAction := cbaDelay;
end;
procedure TForm1.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
@ -203,13 +206,13 @@ begin
// We must wait until all browsers trigger the TChromium.OnBeforeClose event
// in order to close the application safely or we will have shutdown issues.
FCanClose := True;
SendCompMessage(CEF_BEFORECLOSE);
Application.QueueAsyncCall(@BrowserBeforeCloseMsg, 0);
end;
procedure TForm1.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
// Now the browser is fully initialized we can initialize the UI.
SendCompMessage(CEF_AFTERCREATED);
Application.QueueAsyncCall(@BrowserCreatedMsg, 0);
end;
procedure TForm1.CEFLinkedWindowParent1Enter(Sender: TObject);
@ -234,22 +237,19 @@ begin
AddressPnl.Enabled := True;
end;
procedure TForm1.BrowserCloseFormMsg(Data: PtrInt);
procedure TForm1.BrowserFocusMsg(Data: PtrInt);
begin
CEFLinkedWindowParent1.SetFocus;
end;
procedure TForm1.BrowserBeforeCloseMsg(Data: PtrInt);
begin
Close;
end;
procedure TForm1.SendCompMessage(aMsg : cardinal);
begin
case aMsg of
CEF_AFTERCREATED : Application.QueueAsyncCall(@BrowserCreatedMsg, 0);
CEF_BEFORECLOSE : Application.QueueAsyncCall(@BrowserCloseFormMsg, 0);
end;
end;
procedure TForm1.Chromium1GotFocus(Sender: TObject; const browser: ICefBrowser);
begin
CEFLinkedWindowParent1.SetFocus;
Application.QueueAsyncCall(@BrowserFocusMsg, 0);
end;
procedure TForm1.WMMove(var Message: TLMMove);
@ -271,10 +271,12 @@ begin
end;
initialization
AddCrDelegate;
if GlobalCEFApp = nil then begin
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin
DestroyGlobalCEFApp;
DestroyGlobalCEFWorkScheduler;
halt(0); // exit the subprocess
end;
end;

View File

@ -8,6 +8,7 @@
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<CompatibilityMode Value="True"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="AppHelper"/>
@ -18,8 +19,8 @@
</XPManifest>
<Icon Value="0"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
@ -30,19 +31,19 @@
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="CEF4Delphi_Lazarus"/>
</Item>
<Item>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item>
</Item2>
</RequiredPackages>
<Units>
<Unit>
<Units Count="1">
<Unit0>
<Filename Value="AppHelper.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
</Unit0>
</Units>
</ProjectOptions>
<CompilerOptions>

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<CompatibilityMode Value="True"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="BrowserWindow"/>
<Scaled Value="True"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<XPManifest>
<DpiAware Value="True"/>
</XPManifest>
<Icon Value="0"/>
</General>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<DestinationDirectory Value="B:/laz_other/CEF4Delphi/demos/Lazarus_any_OS/BrowserWindow"/>
<CompressFinally Value="False"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="CEF4Delphi_Lazarus"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="4">
<Unit0>
<Filename Value="BrowserWindow.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="uBrowserWindow.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit1>
<Unit2>
<Filename Value="initsubprocess.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="InitSubProcess"/>
</Unit2>
<Unit3>
<Filename Value="globalcefapplication.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="GlobalCefApplication"/>
</Unit3>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="../../../bin/BrowserWindow"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CustomOptions Value="-dUseCthreads"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,83 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
(*
* Include the following files
* BrowserWindow.app/Contents/Frameworks/ExternalPumpBrowser Helper.app/
* files from the demos/Lazarus_Mac/AppHelper project
* use create_mac_helper.sh
*
* BrowserWindow.app/Contents/Frameworks/Chromium Embedded Framework.framework
* files from Release folder in cef download
*
*)
program BrowserWindow;
{$mode objfpc}{$H+}
{$I cef.inc}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
{$IFDEF LINUX}
InitSubProcess, // On Linux this unit must be used *before* the "interfaces" unit.
{$ENDIF}
Interfaces,
Forms,
uBrowserWindow, GlobalCefApplication
{ you can add units after this }
;
{$R *.res}
{$IFDEF WIN32}
// CEF needs to set the LARGEADDRESSAWARE ($20) flag which allows 32-bit processes to use up to 3GB of RAM.
{$SetPEFlags $20}
{$ENDIF}
begin
RequireDerivedFormResource:=True;
Application.Scaled := True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Binary file not shown.

View File

@ -0,0 +1,40 @@
BrowserWindow
# ABOUT
This example uses
TLazarusBrowserWindow
TCEFWorkScheduler
TCEFWorkScheduler feeds the CEF messageloop by calling DoMessageLoopWork(). On Mac this is currently the only way to run the CEF messageloop.
# SETUP
** Windows
1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe.
Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries.
2) Run the project
** Linux
1) Download the CEF framework and place the content of the "Release" folder into the same folder as your exe.
Alternatively you can point "GlobalCEFApp.FrameworkDirPath" to the location with the libraries.
2) Run the project
Note:
- For your own Linux project you must modify the project source (lpr) and add "InitSubProcess" to the "uses" clause, so that it is in the list *before* the unit "Interfaces".
- The call to "DestroyGlobalCEFApp" must be in a unit *not* used by "unit InitSubProcess" (including not used in any nested way).
** Mac
1) Go to "project options" and create the "App Bundle"
2) Download the CEF framework and place the content of the "Release" folder into ExternalPumpBrowser.app/Contents/Frameworks/Chromium Embedded Framework.framework
You should have:
Chromium Embedded Framework
Libraries/*
Resources/*
3) Open project "AppHelper", create App Bundle and compile the AppHelper.
Run create_mac_helper.sh
4) Open project ExternalPumpBrowser, compile and run

View File

@ -0,0 +1,468 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2017 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
// The complete list of compiler versions is here :
// http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
{$DEFINE DELPHI_VERSION_UNKNOW}
// Delphi 5
{$IFDEF VER130}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$ENDIF}
// Delphi 6
{$IFDEF VER140}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$ENDIF}
// Delphi 7
{$IFDEF VER150}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$ENDIF}
// Delphi 8
{$IFDEF VER160}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$ENDIF}
// Delphi 2005
{$IFDEF VER170}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$ENDIF}
{$IFDEF VER180}
{$UNDEF DELPHI_VERSION_UNKNOW}
// Delphi 2007
{$IFDEF VER185}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
// Delphi 2006
{$ELSE}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$ENDIF}
{$ENDIF}
// Delphi 2009
{$IFDEF VER200}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$ENDIF}
//Delphi 2010
{$IFDEF VER210}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$ENDIF}
// Delphi XE
{$IFDEF VER220}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$ENDIF}
// Delphi XE2 (First FireMonkey and 64bit compiler)
{$IFDEF VER230}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$ENDIF}
// Delphi XE3
{$IFDEF VER240}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$ENDIF}
// Delphi XE4
{$IFDEF VER250}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$ENDIF}
// Delphi XE5
{$IFDEF VER260}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$ENDIF}
// Delphi XE6
{$IFDEF VER270}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$ENDIF}
// Delphi XE7
{$IFDEF VER280}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$ENDIF}
// Delphi XE8
{$IFDEF VER290}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$ENDIF VER290}
// Rad Studio 10 - Delphi Seattle
{$IFDEF VER300}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$ENDIF}
// Rad Studio 10.1 - Delphi Berlin
{$IFDEF VER310}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$ENDIF}
// Rad Studio 10.2 - Delphi Tokyo
{$IFDEF VER320}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$ENDIF}
// Rad Studio 10.3 - Delphi Rio
{$IFDEF VER330}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$ENDIF}
// Rad Studio 10.4 - Delphi Sydney
{$IFDEF VER340}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$DEFINE DELPHI27_UP}
{$ENDIF}
{$IFDEF FPC}
{$DEFINE SUPPORTS_INLINE}
{$IF DEFINED(FPC_FULLVERSION) AND (FPC_FULLVERSION >= 30200)}
{$DEFINE FPC_VER_320}
{$IFEND}
{$ELSE}
{$IFDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$DEFINE DELPHI27_UP}
{$ENDIF}
{$ENDIF}
{$IFDEF DELPHI9_UP}
{$DEFINE SUPPORTS_INLINE}
{$ENDIF}
{$IF DEFINED(CPUX32) OR
DEFINED(CPU386) OR
DEFINED(CPUi386) OR
DEFINED(CPUPOWERPC32) OR
DEFINED(CPUSPARC32) OR
DEFINED(CPU32BITS) OR
DEFINED(CPUARM32) OR
DEFINED(WIN32) OR
DEFINED(IOS32) OR
DEFINED(MACOS32) OR
DEFINED(LINUX32) OR
DEFINED(POSIX32) OR
DEFINED(ANDROID32)}
{$DEFINE TARGET_32BITS}
{$IFEND}
// Delphi uses MACOS for the new MacOSX and DARWIN is not defined
// FPC uses DARWIN for the new MacOSX and MACOS is defined for the classic Macintosh OS (System 7)
// We define MACOSX to avoid conflicts in both situations
{$IFDEF FPC}
{$IFDEF DARWIN}
{$DEFINE MACOSX}
{$ENDIF}
{$ELSE}
{$IFDEF MACOS}
{$DEFINE MACOSX}
{$ENDIF}
{$ENDIF}

View File

@ -0,0 +1,13 @@
#!/bin/sh
CDIR=$(pwd)
cd "$(dirname "$0")"
../AppHelper/create_mac_helper_apps.sh ../../../bin/BrowserWindow.app
if [ "$(grep -i TCrCocoaApplication ../../../bin/BrowserWindow.app/Contents/Info.plist)" = "" ];
then
sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/BrowserWindow.app/Contents/Info.plist
fi
cd "$CDIR"

View File

@ -0,0 +1,114 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2021 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit GlobalCefApplication;
{$mode ObjFPC}{$H+}
{$I cef.inc}
{.$DEFINE USE_MULTI_THREAD_LOOP} // Only Windows/Linux
{.$DEFINE USE_APP_HELPER} // Optional on Windows/Linux
{$IFDEF MACOSX}
{$UNDEF USE_MULTI_THREAD_LOOP} // Will fail on Mac
{$DEFINE USE_APP_HELPER} // Required on Mac
{$ENDIF}
interface
uses
uCEFApplication, uCEFWorkScheduler, FileUtil;
procedure CreateGlobalCEFApp;
implementation
procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64);
begin
if (GlobalCEFWorkScheduler <> nil) then GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS);
end;
procedure CreateGlobalCEFApp;
begin
if GlobalCEFApp <> nil then
exit;
{$IFnDEF USE_MULTI_THREAD_LOOP}
// TCEFWorkScheduler will call cef_do_message_loop_work when
// it's told in the GlobalCEFApp.OnScheduleMessagePumpWork event.
// GlobalCEFWorkScheduler needs to be created before the
// GlobalCEFApp.StartMainProcess call.
GlobalCEFWorkScheduler := TCEFWorkScheduler.Create(nil);
{$ENDIF}
GlobalCEFApp := TCefApplication.Create;
{$IFDEF USE_MULTI_THREAD_LOOP}
// On Windows/Linux CEF can use threads for the message-loop
GlobalCEFApp.MultiThreadedMessageLoop := True;
{$ELSE}
// use External Pump for message-loop
GlobalCEFApp.ExternalMessagePump := True;
GlobalCEFApp.MultiThreadedMessageLoop := False;
GlobalCEFApp.OnScheduleMessagePumpWork := @GlobalCEFApp_OnScheduleMessagePumpWork;
{$ENDIF}
{$IFnDEF MACOSX}
{$IFDEF USE_APP_HELPER}
(* Use AppHelper as subprocess, instead of the main exe *)
GlobalCEFApp.BrowserSubprocessPath := 'AppHelper' + GetExeExt;
{$ENDIF}
{$ENDIF}
{$IFDEF MACOSX}
(* Enable the below to prevent being asked for permission to access "Chromium Safe Storage"
If set to true, Cookies will not be encrypted.
*)
//GlobalCEFApp.UseMockKeyChain := True;
{$ENDIF}
{$IFDEF LINUX}
// This is a workaround for the 'GPU is not usable error' issue :
// https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef
GlobalCEFApp.DisableZygote := True; // this property adds the "--no-zygote" command line switch
{$ENDIF}
{
GlobalCEFApp.LogFile := 'cef.log';
GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE;
}
end;
end.

View File

@ -0,0 +1,61 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2021 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit InitSubProcess;
{$mode ObjFPC}{$H+}
{$I cef.inc}
interface
uses
GlobalCefApplication, uCEFApplication, uCEFWorkScheduler;
implementation
initialization
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin
if GlobalCEFWorkScheduler <> nil then
GlobalCEFWorkScheduler.StopScheduler;
DestroyGlobalCEFApp;
DestroyGlobalCEFWorkScheduler;
halt(0); // exit the subprocess
end;
end.

View File

@ -0,0 +1,74 @@
object Form1: TForm1
Left = 473
Height = 589
Top = 227
Width = 967
Caption = 'Initializing browser. Please wait...'
ClientHeight = 589
ClientWidth = 967
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
Position = poScreenCenter
LCLVersion = '2.1.0.0'
object AddressPnl: TPanel
Left = 0
Height = 23
Top = 0
Width = 967
Align = alTop
BevelOuter = bvNone
ClientHeight = 23
ClientWidth = 967
TabOrder = 0
object GoBtn: TButton
Left = 932
Height = 23
Top = 0
Width = 35
Align = alRight
Caption = 'Go'
OnClick = GoBtnClick
TabOrder = 0
end
object AddressEdt: TComboBox
Left = 0
Height = 23
Top = 0
Width = 932
Align = alClient
ItemHeight = 15
ItemIndex = 0
Items.Strings = (
'https://www.google.com'
'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending'
'https://www.w3schools.com/js/tryit.asp?filename=tryjs_win_close'
'https://www.w3schools.com/html/html5_video.asp'
'http://www.adobe.com/software/flash/about/'
'http://isflashinstalled.com/'
'chrome://version/'
'http://html5test.com/'
'https://www.w3schools.com/'
'http://webglsamples.org/'
'https://get.webgl.org/'
'https://www.youtube.com'
'https://html5demos.com/drag/'
'https://developers.google.com/maps/documentation/javascript/examples/streetview-embed?hl=fr'
'https://www.w3schools.com/Tags/tryit.asp?filename=tryhtml_iframe_name'
'https://www.browserleaks.com/webrtc'
'https://frames-per-second.appspot.com/'
)
TabOrder = 1
Text = 'https://www.google.com'
end
end
object LazarusBrowserWindow1: TLazarusBrowserWindow
Left = 0
Height = 566
Top = 23
Width = 967
Align = alClient
TabOrder = 1
OnBrowserCreated = LazarusBrowserWindow1BrowserCreated
OnBrowserClosed = LazarusBrowserWindow1BrowserClosed
end
end

View File

@ -0,0 +1,203 @@
// ************************************************************************
// ***************************** 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 uBrowserWindow;
{$mode objfpc}{$H+}
{$I cef.inc}
interface
uses
GlobalCefApplication,
uCEFLazarusCocoa, // required for Cocoa
SysUtils, Messages, Forms, Controls,
Dialogs, ExtCtrls, StdCtrls, LMessages,
uCEFTypes, uCEFInterfaces,
uCEFWorkScheduler, uCEFLazarusBrowserWindow, Classes;
type
{ TForm1 }
TForm1 = class(TForm)
AddressEdt: TComboBox;
GoBtn: TButton;
AddressPnl: TPanel;
LazarusBrowserWindow1: TLazarusBrowserWindow;
procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean);
procedure Chromium1OpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormCreate(Sender: TObject);
procedure GoBtnClick(Sender: TObject);
procedure LazarusBrowserWindow1BrowserClosed(Sender: TObject);
procedure LazarusBrowserWindow1BrowserCreated(Sender: TObject);
protected
{$IFDEF WINDOWS}
procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP;
procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP;
{$ENDIF}
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
// This is a demo with the simplest web browser you can build using CEF4Delphi and
// it doesn't show any sign of progress like other web browsers do.
// Remember that it may take a few seconds to load if Windows update, your antivirus or
// any other windows service is using your hard drive.
// Depending on your internet connection it may take longer than expected.
// Please check that your firewall or antivirus are not blocking this application
// or the domain "google.com". If you don't live in the US, you'll be redirected to
// another domain which will take a little time too.
// This demo uses a TChromium and a TCEFLinkedWindowParent
// We need to use TCEFLinkedWindowParent in Linux to update the browser
// visibility and size automatically.
// Destruction steps
// =================
// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event.
// 2. TChromium.OnClose sets aAction to cbaClose to destroy the browser, which triggers the TChromium.OnBeforeClose event.
// 3. TChromium.OnBeforeClose sets FCanClose := True and sends CEF_BEFORECLOSE to close the form.
uses
uCEFApplication;
{ TForm1 }
procedure TForm1.GoBtnClick(Sender: TObject);
begin
LazarusBrowserWindow1.LoadURL(UTF8Decode(AddressEdt.Text));
end;
procedure TForm1.LazarusBrowserWindow1BrowserClosed(Sender: TObject);
begin
Close;
end;
procedure TForm1.LazarusBrowserWindow1BrowserCreated(Sender: TObject);
begin
Caption := 'BrowserWindow';
end;
{$IFDEF WINDOWS}
procedure TForm1.WMEnterMenuLoop(var aMessage: TMessage);
begin
inherited;
if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True;
end;
procedure TForm1.WMExitMenuLoop(var aMessage: TMessage);
begin
inherited;
if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False;
end;
{$ENDIF}
procedure TForm1.Chromium1BeforePopup(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; const targetUrl,
targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition;
userGesture: Boolean; const popupFeatures: TCefPopupFeatures;
var windowInfo: TCefWindowInfo; var client: ICefClient;
var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue;
var noJavascriptAccess: Boolean; var Result: Boolean);
begin
// For simplicity, this demo blocks all popup windows and new tabs
Result := (targetDisposition in [WOD_NEW_FOREGROUND_TAB, WOD_NEW_BACKGROUND_TAB, WOD_NEW_POPUP, WOD_NEW_WINDOW]);
end;
procedure TForm1.Chromium1OpenUrlFromTab(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring;
targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out
Result: Boolean);
begin
// For simplicity, this demo blocks all popup windows and new tabs
Result := (targetDisposition in [WOD_NEW_FOREGROUND_TAB, WOD_NEW_BACKGROUND_TAB, WOD_NEW_POPUP, WOD_NEW_WINDOW]);
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
LazarusBrowserWindow1.CloseBrowser(True);
CanClose := LazarusBrowserWindow1.IsClosed;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LazarusBrowserWindow1.LoadURL(UTF8Decode(AddressEdt.Text));
end;
initialization
{$IFDEF DARWIN} // $IFDEF MACOSX
AddCrDelegate;
{$ENDIF}
if GlobalCEFApp = nil then begin
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin
DestroyGlobalCEFApp;
DestroyGlobalCEFWorkScheduler;
halt(0); // exit the subprocess
end;
end;
finalization
(* Destroy from this unit, which is used after "Interfaces". So this happens before the Application object is destroyed *)
if GlobalCEFWorkScheduler <> nil then
GlobalCEFWorkScheduler.StopScheduler;
DestroyGlobalCEFApp;
DestroyGlobalCEFWorkScheduler;
end.

View File

@ -5,4 +5,9 @@ cd "$(dirname "$0")"
../AppHelper/create_mac_helper_apps.sh ../../../bin/ExternalPumpBrowser.app
if [ "$(grep -i TCrCocoaApplication ../../../bin/ExternalPumpBrowser.app/Contents/Info.plist)" = "" ];
then
sed -i '' "1,4s/<dict>/<dict>\n <key>NSPrincipalClass<\/key>\n <string>TCrCocoaApplication<\/string>/" ../../../bin/ExternalPumpBrowser.app/Contents/Info.plist
fi
cd "$CDIR"

View File

@ -43,7 +43,9 @@ unit uExternalPumpBrowser;
interface
uses
GlobalCefApplication, Classes, SysUtils, Messages, Forms, Controls, Graphics,
GlobalCefApplication,
uCEFLazarusCocoa, // required for Cocoa
Classes, SysUtils, Messages, Forms, Controls, Graphics,
Dialogs, ExtCtrls, StdCtrls, LMessages, uCEFChromium, uCEFWindowParent,
uCEFConstants, uCEFTypes, uCEFInterfaces, uCEFChromiumEvents,
uCEFLinkedWindowParent, uCEFWorkScheduler;
@ -92,10 +94,9 @@ type
procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP;
{$ENDIF}
procedure SendCompMessage(aMsg : cardinal);
procedure BrowserCreatedMsg(Data: PtrInt);
procedure BrowserCloseFormMsg(Data: PtrInt);
procedure BrowserFocusMsg(Data: PtrInt);
procedure BrowserBeforeCloseMsg(Data: PtrInt);
public
end;
@ -211,13 +212,13 @@ begin
// We must wait until all browsers trigger the TChromium.OnBeforeClose event
// in order to close the application safely or we will have shutdown issues.
FCanClose := True;
SendCompMessage(CEF_BEFORECLOSE);
Application.QueueAsyncCall(@BrowserBeforeCloseMsg, 0);
end;
procedure TForm1.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
// Now the browser is fully initialized we can initialize the UI.
SendCompMessage(CEF_AFTERCREATED);
Application.QueueAsyncCall(@BrowserCreatedMsg, 0);
end;
procedure TForm1.CEFLinkedWindowParent1Enter(Sender: TObject);
@ -242,22 +243,19 @@ begin
AddressPnl.Enabled := True;
end;
procedure TForm1.BrowserCloseFormMsg(Data: PtrInt);
procedure TForm1.BrowserFocusMsg(Data: PtrInt);
begin
CEFLinkedWindowParent1.SetFocus;
end;
procedure TForm1.BrowserBeforeCloseMsg(Data: PtrInt);
begin
Close;
end;
procedure TForm1.SendCompMessage(aMsg : cardinal);
begin
case aMsg of
CEF_AFTERCREATED : Application.QueueAsyncCall(@BrowserCreatedMsg, 0);
CEF_BEFORECLOSE : Application.QueueAsyncCall(@BrowserCloseFormMsg, 0);
end;
end;
procedure TForm1.Chromium1GotFocus(Sender: TObject; const browser: ICefBrowser);
begin
CEFLinkedWindowParent1.SetFocus;
Application.QueueAsyncCall(@BrowserFocusMsg, 0);
end;
procedure TForm1.WMMove(var Message: TLMMove);
@ -295,10 +293,14 @@ end;
{$ENDIF}
initialization
{$IFDEF DARWIN} // $IFDEF MACOSX
AddCrDelegate;
{$ENDIF}
if GlobalCEFApp = nil then begin
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin
DestroyGlobalCEFApp;
DestroyGlobalCEFWorkScheduler;
halt(0); // exit the subprocess
end;
end;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="4">
<Package Version="5">
<PathDelim Value="\"/>
<Name Value="CEF4Delphi_Lazarus"/>
<Type Value="RunAndDesignTime"/>
@ -22,7 +22,7 @@
<Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/>
<License Value="MPL 1.1"/>
<Version Major="88" Minor="2" Release="9"/>
<Files Count="198">
<Files Count="200">
<Item1>
<Filename Value="..\source\uCEFAccessibilityHandler.pas"/>
<UnitName Value="uCEFAccessibilityHandler"/>
@ -831,7 +831,17 @@
<Filename Value="..\source\uCEFLinkedWinControlBase.pas"/>
<UnitName Value="uCEFLinkedWinControlBase"/>
</Item198>
<Item199>
<Filename Value="..\source\uceflazaruscocoa.pas"/>
<UnitName Value="uceflazaruscocoa"/>
</Item199>
<Item200>
<Filename Value="..\source\uceflazarusbrowserwindow.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="uceflazarusbrowserwindow"/>
</Item200>
</Files>
<CompatibilityMode Value="True"/>
<RequiredPkgs Count="4">
<Item1>
<PackageName Value="dcpcrypt"/>

View File

@ -65,7 +65,8 @@ uses
uCEFMediaSinkDeviceInfoCallback, uCEFJson, uCEFBitmapBitBuffer,
uCEFPrintDialogCallback, uCEFPrintHandler, uCEFPrintJobCallback,
uCEFLinuxFunctions, uCEFLinuxTypes, uCEFLinuxConstants,
uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, LazarusPackageIntf;
uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, uCEFLazarusCocoa,
uCEFLazarusBrowserWindow, LazarusPackageIntf;
implementation
@ -88,6 +89,7 @@ begin
RegisterUnit('uCEFPanelComponent', @uCEFPanelComponent.Register);
RegisterUnit('uCEFScrollViewComponent', @uCEFScrollViewComponent.Register);
RegisterUnit('uCEFTextfieldComponent', @uCEFTextfieldComponent.Register);
RegisterUnit('uCEFLazarusBrowserWindow', @uCEFLazarusBrowserWindow.Register);
end;
initialization

View File

@ -0,0 +1,38 @@
LazarusResources.Add('tlazarusbrowserwindow','PNG',[
#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#2#0#0#0'o'#21#170#175
+#0#0#0#9'pHYs'#0#0#13#215#0#0#13#215#1'B('#155'x'#0#0#0#7'tIME'#7#226#5#11#10
+#31#18#187#205#226'X'#0#0#3#10'IDAT8'#203#173#149'Ml'#27'U'#16#199'g'#158'7'
+#222#197'Qk'#183'IIBl#'#156'JM'#12'V'#137#168#16'E *8Qn'#17' '#142#168#226
+#200#181#189'p'#228#128#212'['#213#3'\'#171#194#165'= TQ'#129'P'#131#26#138
+'d'#167#20'PE'#212'H'#9'_'#18'i'#226#218#241'G'#214'~'#187#222'}3'#195'a#w'
+#243'Q)'#144#206'i5o'#222'_3'#191#153'y'#139'"'#2#143#195','#215'u'#23#23#23
+#247#169'R,'#22#161'\.'#19#145#236#195#136#168'\.+"RJ'#237''''#29#165#20#17
+#237'I'#162'g'#246#192#232'Q'#7'k.\-'#223#191#241#253'M'#1#4#128#4#192#169
+#215'_}'#231#197#241#177#131#143#22'b'#230'm'#222'Oo5'#191#190'v'#205'NZ'#153
+'L'#26#5#1#128#133'ggg'#175'_'#15#222#255#224#204#187#147#187'4Z'#1#128#136
+'p'#204'.'#220'l^'#186#252#133#149't'#208'Jv'#180#239'j'#175#165#187#237#142
+'6'#146#224'D'#242#147#243#23#206']Y'#142#199'G'#3#180#153'Q'#127#154'j'#30
+#206#207#223'N$'#157#182#246#200#176#31#154#227#133#209#3#169#228'j'#203#183
+#5#6#149#12#165#7#239#222#254'a'#253#244'3'#135#156#205'+'#136#184')'#20'e'
+#20'y'#231#254#30'('#30'+'#212'j'#235'n'#167'{4w'#248#243#143#222'^m'#19#139
+'d3'#214#221#127#186':'#228#148'm'#245#180'k'#148'b'#14#251']'#3#0'+R!'#162
+#200'['#249'y!?>'#246#236'sS_~'#245#237#220#197'3'#31'_Y'#178#7#20'"z~xvfb'
+#249#129#7#28#218#142#179#244#231#253'L'#225'p'#31#144#136#168#168#180'X'#193
+'@l'#242#217#209#247'N'#191#242#203#239#27#141#166#214':'#208#186#215'r{'#183
+'~'#171#167#146#9'f'#16#129'-P'#153'w)'#141'X'#136#152#133#166'&'''#218#186
+'Wk{'#134#24#17'Z:'#232#6#6#128#1#0#1#12#131'!V'#24'+'#173#159'Q$'#20#132#20
+#24#177'mY'#217#8'_'#155#28'Zu'#189#7']'#31#1#12'K'#169#144#209#1'#'#2#3#244
+#136'@'#152#5#250#211'cE*}F'''#166#167#23#238'-'#140#28'9d)u'#227#158#251#217
+#135'/|sgMD'#222'x~'#196'0'#136#0' 4'#154#237'\6K'#180#209#135#205#204#219#25
+#189'<'#214#233't}'#207'7'#134#184#222#9#175#222'i'#13#13#165#237#212#224#210
+#154'oH'#16' 4'#208#236#132#25#232'lc'#180'} '#135#147#193'K'''#166'W'#170'u'
+#207#15'{'#129#17#162#229#170'n'#235#224#216'S'#131'!'#177#14#229#143#149'Zv'
+'|'#212#134'`'#247#129#140'o'#201'['#185#134#147'(}'#247#227#175#169''''#236
+'t'#250'`h'#248#228#241#225#182'G'#213'zk'#221#13#158#206#231'rV3'#190'T'#15
+#187#22'g'#20#217#169#145'F'#241#205#137#185'j'#166'2'#255#211#147#233#129
+#191'V'#209#13'h'#234'h'#225#228#145#214#1#171#190'5v'#171#208#206#189#29#182
+'{3'#249#234'L>'#23#243'U'#1'`G <d'#244'x'#222#236' '#8#148'R'#142#227#252'o'
+#9'D'#212'Zc'#163#209#168'T*'#158#231#25'c'#254#235#31#5#17#17#209'q'#156'R'
+#169#132#241#203';I'#237#229#193#142'>'#254#5'Ixq'#26'FW'#221'b'#0#0#0#0'IEN'
+'D'#174'B`'#130
]);

View File

@ -5184,9 +5184,11 @@ end;
function TChromiumCore.doOnClose(const browser: ICefBrowser): Boolean;
var
TempAction : TCefCloseBrowserAction;
id: Integer;
begin
Result := False;
TempAction := cbaClose;
id := browser.Identifier;
// TempAction values
// -----------------
@ -5205,11 +5207,11 @@ begin
cbaDelay :
begin
Result := True;
SetBrowserIsClosing(browser.Identifier);
SetBrowserIsClosing(id);
end;
else
SetBrowserIsClosing(browser.Identifier);
SetBrowserIsClosing(id);
end;
end;

View File

@ -37,15 +37,18 @@
unit uCEFWinControl;
{$I cef.inc}
{$IFDEF FPC}
{$MODE OBJFPC}{$H+}
{$IFDEF MACOSX}
{$ModeSwitch objectivec1}
{$ENDIF}
{$ENDIF}
{$IFNDEF CPUX64}{$ALIGN ON}{$ENDIF}
{$MINENUMSIZE 4}
{$I cef.inc}
interface
uses
@ -57,6 +60,9 @@ uses
LCLProc, LCLType, LCLIntf, LResources, InterfaceBase,
{$ENDIF}
{$ENDIF}
{$IFDEF FPC}{$IFDEF MACOSX}
CocoaAll,
{$ENDIF}{$ENDIF}
uCEFTypes, uCEFInterfaces;
type
@ -186,12 +192,25 @@ function TCEFWinControl.DestroyChildWindow : boolean;
var
TempHWND : HWND;
{$ENDIF}
{$IFDEF FPC}{$IFDEF MACOSX}
var
ViewObj: NSObject;
{$ENDIF}{$ENDIF}
begin
{$IFDEF MSWINDOWS}
TempHWND := ChildWindowHandle;
Result := (TempHWND <> 0) and DestroyWindow(TempHWND);
{$ELSE}
Result := False;
{$IFDEF FPC}{$IFDEF MACOSX}
ViewObj := NSObject(ChildWindowHandle);
if ViewObj <> nil then begin
if ViewObj.isKindOfClass_(nsview) then begin
NSView(ViewObj).removeFromSuperview;
Result := True;
end;
end;
{$ENDIF}{$ENDIF}
{$ENDIF}
end;

View File

@ -0,0 +1,487 @@
// ************************************************************************
// ***************************** 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 uCEFLazarusBrowserWindow;
{$mode objfpc}{$H+}
{$i cef.inc}
interface
uses
{$IFDEF FPC}
LResources,
{$ENDIF}
uCEFApplication, uCEFChromiumWindow, uCEFTypes, uCEFInterfaces, uCEFChromium,
uCEFLinkedWinControlBase, Forms, ExtCtrls, Classes, sysutils;
type
(* On cocoa closing a browser does not work, while the application is in any other event.
I.e. if the App is in a button-press event, then the browser will
only close once that event was finished.
*)
TLazarusBrowserWindow = class;
{ TChromiumWrapper }
TChromiumWrapper = class
protected type
TWrapperChromiumState = (csNoBrowser, csCreatingBrowser, csHasBrowser, csClosingBrowser, csCloseAfterCreate);
TWrapperState = (wsNone, wsWaitingForClose, wsSentCloseEventAfterWait, wsDestroyAfterWait);
protected
FChromium : TChromium;
FChromiumState : TWrapperChromiumState;
FWrapperState : TWrapperState;
FBrowserWindow : TLazarusBrowserWindow;
FLoadUrl : ustring;
procedure WebBrowser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure WebBrowser_OnClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); reintroduce;
procedure WebBrowser_OnBeforeClose(Sender: TObject; const browser: ICefBrowser); reintroduce;
{$IFDEF FPC}
procedure WebBrowser_OnGotFocus(Sender: TObject; const browser: ICefBrowser);
{$ENDIF}
procedure DoCreated(Data: PtrInt);
procedure MaybeDestroy;
public
constructor Create(AOwner: TLazarusBrowserWindow); reintroduce;
destructor Destroy; override;
function CreateBrowser: boolean;
procedure LoadURL(aURL: ustring);
procedure CloseBrowser(aForceClose: boolean);
function IsClosed: boolean;
(* WaitForBrowserClosed calls ProcessMessages.
It therefore is possible that the TLazarusBrowserWindow will be destroyed
when this method returns.
It is the callers responsibility to take any necessary precaution.
*)
procedure WaitForBrowserClosed;
end;
{ TLazarusBrowserWindow }
(* On MacOs TLazarusBrowserWindow must wait for OnBrowserClosed before it can
be destroyed or before its handle can be closed
*)
TLazarusBrowserWindow = class(TCEFLinkedWinControlBase)
private
FChromiumWrapper : TChromiumWrapper;
FOnBrowserClosed : TNotifyEvent;
FOnBrowserCreated : TNotifyEvent;
FTimer : TTimer;
procedure DoCreateBrowser(Sender: TObject);
protected
function GetChromium: TChromium; override;
procedure DestroyHandle; override;
procedure RealizeBounds; override;
procedure DoEnter; override;
procedure DoExit; override;
procedure DoOnCreated;
procedure DoOnClosed(Data: PtrInt);
procedure DoOnFocus(Data: PtrInt);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CreateHandle; override;
procedure CloseBrowser(aForceClose: boolean);
procedure WaitForBrowserClosed;
function IsClosed: boolean;
procedure LoadURL(aURL: ustring);
published
property Chromium; // : TChromium read GetChromium;
property OnBrowserCreated : TNotifyEvent read FOnBrowserCreated write FOnBrowserCreated;
(* OnBrowserClosed will not be called, if the TLazarusBrowserWindow is
destroyed/destroying before the browser is closed.
*)
property OnBrowserClosed : TNotifyEvent read FOnBrowserClosed write FOnBrowserClosed;
end;
{$IFDEF FPC}
procedure Register;
{$ENDIF}
implementation
{ TChromiumWrapper }
procedure TChromiumWrapper.WebBrowser_OnAfterCreated(Sender: TObject;
const browser: ICefBrowser);
begin
(* We may still be in Chromium.CreateBrowserSync
In that case initialization will happen after this event,
but before the call to CreateBrowser returns
*)
Application.QueueAsyncCall(@DoCreated, 0);
end;
procedure TChromiumWrapper.WebBrowser_OnClose(Sender: TObject;
const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
begin
(* FBrowserWindow should always be <> nil
If FBrowserWindow is nil (MacOS) then the FBrowserWindow.Handle is destroyed too,
and CEF should call BeforeClose, without calling DoClose
*)
if (FBrowserWindow <> nil) and FBrowserWindow.DestroyChildWindow then
aAction := cbaDelay
else
aAction := cbaClose;
end;
procedure TChromiumWrapper.WebBrowser_OnBeforeClose(Sender: TObject;
const browser: ICefBrowser);
begin
FChromiumState := csNoBrowser;
if (FBrowserWindow <> nil) then begin
if FWrapperState = wsWaitingForClose then
FWrapperState := wsSentCloseEventAfterWait
else
Application.QueueAsyncCall(@FBrowserWindow.DoOnClosed, 0);
end;
end;
procedure TChromiumWrapper.WebBrowser_OnGotFocus(Sender: TObject;
const browser: ICefBrowser);
begin
if (FBrowserWindow <> nil) then
Application.QueueAsyncCall(@FBrowserWindow.DoOnFocus, 0);
end;
procedure TChromiumWrapper.DoCreated(Data: PtrInt);
begin
// Any other state, means this is a late async call
case FChromiumState of
csCreatingBrowser: begin
FChromiumState := csHasBrowser;
if FLoadUrl <> '' then
LoadURL(FLoadUrl);
if (FBrowserWindow <> nil) then
FBrowserWindow.DoOnCreated;
end;
csCloseAfterCreate: begin
FChromiumState := csHasBrowser;
CloseBrowser(True);
end;
end;
end;
procedure TChromiumWrapper.MaybeDestroy;
begin
CloseBrowser(True);
FBrowserWindow := nil;
if FWrapperState in [wsWaitingForClose, wsSentCloseEventAfterWait] then
FWrapperState := wsDestroyAfterWait;
if FChromiumState = csNoBrowser then
Destroy;
end;
constructor TChromiumWrapper.Create(AOwner: TLazarusBrowserWindow);
begin
FBrowserWindow := AOwner;
FChromiumState := csNoBrowser;
FWrapperState := wsNone;
if not(csDesigning in AOwner.ComponentState) then
begin
FChromium := TChromium.Create(nil);
FChromium.OnClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnClose;
FChromium.OnBeforeClose := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnBeforeClose;
FChromium.OnAfterCreated := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnAfterCreated;
{$IFDEF LINUX}
// This is a workaround for the CEF issue #2026. Read below for more info.
FChromium.OnGotFocus := {$IFDEF FPC}@{$ENDIF}WebBrowser_OnGotFocus;
{$ENDIF}
end;
inherited Create;
end;
destructor TChromiumWrapper.Destroy;
begin
if FChromiumState <> csNoBrowser then
WaitForBrowserClosed;
inherited Destroy;
FChromium.Destroy;
Application.RemoveAsyncCalls(Self);
end;
function TChromiumWrapper.CreateBrowser: boolean;
begin
if FChromiumState <> csNoBrowser then
exit(False);
FChromiumState := csCreatingBrowser;
Result := FChromium.CreateBrowser(FBrowserWindow, '');
if Result then begin
if FChromium.Initialized then
DoCreated(0);
end
else begin
FChromiumState := csNoBrowser;
end;
end;
procedure TChromiumWrapper.LoadURL(aURL: ustring);
begin
FLoadUrl := '';
if FChromiumState = csHasBrowser then
FChromium.LoadURL(aURL)
else
FLoadUrl := aURL;
end;
procedure TChromiumWrapper.CloseBrowser(aForceClose: boolean);
begin
if FChromiumState = csCreatingBrowser then begin
FChromiumState := csCloseAfterCreate;
end
else
if FChromiumState in [csHasBrowser] then
begin
FChromiumState := csClosingBrowser;
FChromium.CloseBrowser(aForceClose);
end;
end;
function TChromiumWrapper.IsClosed: boolean;
begin
Result := FChromiumState = csNoBrowser;
end;
procedure TChromiumWrapper.WaitForBrowserClosed;
begin
if FChromiumState = csNoBrowser then
exit;
if FChromiumState <> csClosingBrowser then
CloseBrowser(True);
FWrapperState := wsWaitingForClose;
while FChromiumState <> csNoBrowser do begin
Application.ProcessMessages;
if GlobalCEFApp.ExternalMessagePump then
GlobalCEFApp.DoMessageLoopWork;
sleep(5);
end;
if (FBrowserWindow <> nil) and
(FWrapperState = wsSentCloseEventAfterWait)
then
Application.QueueAsyncCall(@FBrowserWindow.DoOnClosed, 0);
if FWrapperState = wsDestroyAfterWait then
Destroy
else
FWrapperState := wsNone;
end;
{ TLazarusBrowserWindow }
procedure TLazarusBrowserWindow.DoCreateBrowser(Sender: TObject);
begin
FTimer.Enabled := False;
case FChromiumWrapper.FChromiumState of
csCreatingBrowser, csHasBrowser: begin
FreeAndNil(FTimer);
exit;
end;
csClosingBrowser, csCloseAfterCreate: begin
// need new wrapper // This could prevent an OnBrowserClosed event
FChromiumWrapper.MaybeDestroy;
FChromiumWrapper := TChromiumWrapper.Create(Self);
end;
end;
if FChromiumWrapper.CreateBrowser then begin
FreeAndNil(FTimer);
end
else begin
if GlobalCEFApp.ExternalMessagePump then
GlobalCEFApp.DoMessageLoopWork;
FTimer.Interval := 100;
FTimer.Enabled := True;
end;
end;
function TLazarusBrowserWindow.GetChromium: TChromium;
begin
Result := FChromiumWrapper.FChromium;
end;
procedure TLazarusBrowserWindow.CreateHandle;
begin
inherited CreateHandle;
if not (csDesigning in ComponentState) then begin
(* On Windows we can create the browser immediately.
But at least on Linux, we need to wait
*)
FTimer := TTimer.Create(Self);
FTimer.Interval := 20;
FTimer.OnTimer := @DoCreateBrowser;
FTimer.Enabled := True;
end;
end;
procedure TLazarusBrowserWindow.DestroyHandle;
begin
if FTimer <> nil then
FreeAndNil(FTimer);
if (GlobalCEFApp = nil) or
(FChromiumWrapper.FChromiumState = csNoBrowser) or
(csDesigning in ComponentState)
then begin
inherited DestroyHandle;
exit;
end;
{$IFDEF MACOSX}
inherited DestroyHandle;
FChromiumWrapper.CloseBrowser(True);
{$ELSE}
FChromiumWrapper.WaitForBrowserClosed;
inherited DestroyHandle;
{$ENDIF}
end;
procedure TLazarusBrowserWindow.RealizeBounds;
begin
inherited RealizeBounds;
if not (csDesigning in ComponentState) and HandleAllocated then
Chromium.NotifyMoveOrResizeStarted;
end;
procedure TLazarusBrowserWindow.DoEnter;
begin
inherited DoEnter;
If not(csDesigning in ComponentState) then Chromium.SetFocus(True);
end;
procedure TLazarusBrowserWindow.DoExit;
begin
inherited DoExit;
if not(csDesigning in ComponentState) then
Chromium.SendCaptureLostEvent;
end;
procedure TLazarusBrowserWindow.DoOnCreated;
begin
{$IFDEF FPC}{$IFDEF LINUX}
Chromium.UpdateXWindowVisibility(Visible);
Chromium.UpdateBrowserSize(Left, Top, Width, Height);
{$ENDIF}{$ENDIF}
if Assigned(FOnBrowserCreated) then
FOnBrowserCreated(Self);
end;
procedure TLazarusBrowserWindow.DoOnClosed(Data: PtrInt);
begin
if (not(csDestroying in ComponentState)) and
Assigned(FOnBrowserClosed)
then
FOnBrowserClosed(Self);
end;
procedure TLazarusBrowserWindow.DoOnFocus(Data: PtrInt);
begin
SetFocus;
end;
constructor TLazarusBrowserWindow.Create(AOwner: TComponent);
begin
FChromiumWrapper := TChromiumWrapper.Create(Self);
inherited Create(AOwner);
end;
destructor TLazarusBrowserWindow.Destroy;
begin
inherited Destroy;
FChromiumWrapper.MaybeDestroy;
Application.RemoveAsyncCalls(Self);
end;
procedure TLazarusBrowserWindow.CloseBrowser(aForceClose: boolean);
begin
FChromiumWrapper.CloseBrowser(aForceClose);
end;
procedure TLazarusBrowserWindow.WaitForBrowserClosed;
begin
FChromiumWrapper.WaitForBrowserClosed;
end;
function TLazarusBrowserWindow.IsClosed: boolean;
begin
Result := FChromiumWrapper.IsClosed;
end;
procedure TLazarusBrowserWindow.LoadURL(aURL: ustring);
begin
FChromiumWrapper.LoadURL(aURL);
end;
{$IFDEF FPC}
procedure Register;
begin
{$I res/tlazarusbrowserwindow.lrs}
RegisterComponents('Chromium', [TLazarusBrowserWindow]);
end;
{$ENDIF}
end.

174
source/uceflazaruscocoa.pas Normal file
View File

@ -0,0 +1,174 @@
// ************************************************************************
// ***************************** 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.
//
// Unit Author: Jonas Maebe
//
unit uCEFLazarusCocoa;
{$mode objfpc}{$H+}
{$I cef.inc}
{$IFDEF DARWIN} // $IFDEF MACOSX
{$ModeSwitch objectivec2}
{$ENDIF}
interface
uses
{$IFDEF DARWIN} // $IFDEF MACOSX
CocoaAll, CocoaInt, Cocoa_Extra,
{$ENDIF}
Classes, SysUtils;
{$IFDEF DARWIN} // $IFDEF MACOSX
type
CrAppProtocol = objcprotocol
function isHandlingSendEvent: objcbool; message 'isHandlingSendEvent';
end;
CrAppControlProtocol = objcprotocol(CrAppProtocol)
procedure setHandlingSendEvent(handlingSendEvent: objcbool); message 'setHandlingSendEvent:';
end;
TCrCocoaApplication = objcclass(TCocoaApplication, CrAppControlProtocol)
public
function isHandlingSendEvent: LCLObjCBoolean;
procedure setHandlingSendEvent(handlingSendEvent: LCLObjCBoolean);
procedure sendEvent(theEvent: NSEvent); override;
procedure terminate(sender: id); override;
private
fHandlingSendEvent: LCLObjCBoolean;
end;
procedure AddCrDelegate;
{$ENDIF}
implementation
{$IFDEF DARWIN} // $IFDEF MACOSX
uses
Forms;
type
TChromeAppDelegateIntercept = objcclass(NSProxy)
procedure tryToTerminateApplication(app: NSApplication); message 'tryToTerminateApplication:';
function initWithDelegate(delegate: id): id; message 'initWithDelegate:';
procedure dealloc; override;
function respondsToSelector(aSelector: SEL): LCLObjCBoolean; override;
procedure forwardInvocation (invocation: NSInvocation); override;
function methodSignatureForSelector (sel_: SEL): NSMethodSignature; override;
private
fLCLDelegate: id;
end;
procedure TChromeAppDelegateIntercept.tryToTerminateApplication(app: NSApplication);
begin
Application.MainForm.Close;
end;
function TChromeAppDelegateIntercept.initWithDelegate(delegate: id): id;
begin
fLCLDelegate:=delegate;
fLCLDelegate.retain;
result:=self;
end;
procedure TChromeAppDelegateIntercept.dealloc;
begin
fLCLDelegate.release;
fLCLDelegate:=nil;
inherited dealloc;
end;
function TChromeAppDelegateIntercept.respondsToSelector(aSelector: SEL): LCLObjCBoolean;
begin
if aSelector = objcselector('tryToTerminateApplication:') then
result:=true
else if assigned(fLCLDelegate) then
result:=fLCLDelegate.respondsToSelector(aSelector)
else
result:=false;
end;
procedure TChromeAppDelegateIntercept.forwardInvocation(invocation: NSInvocation);
begin
{ this only gets called in case we can't handle the invocation }
if assigned(fLCLDelegate) then
begin
invocation.setTarget(fLCLDelegate);
invocation.invoke;
end;
end;
function TChromeAppDelegateIntercept.methodSignatureForSelector(sel_: SEL): NSMethodSignature;
begin
{ if the original delegate can handle it, send it there. Otherwise we try to handle it }
if assigned(fLCLDelegate) then
result:=fLCLDelegate.methodSignatureForSelector(sel_);
if not assigned(result) then
result:=inherited;
end;
procedure AddCrDelegate;
var
delegate: id;
begin
delegate := TChromeAppDelegateIntercept.alloc.initWithDelegate(NSApp.delegate);
NSApp.setDelegate(delegate);
end;
function TCrCocoaApplication.isHandlingSendEvent: LCLObjCBoolean;
begin
result:=fHandlingSendEvent;
end;
procedure TCrCocoaApplication.setHandlingSendEvent(handlingSendEvent: LCLObjCBoolean);
begin
fHandlingSendEvent:=handlingSendEvent;
end;
procedure TCrCocoaApplication.sendEvent(theEvent: NSEvent);
var
CurrentHandling: LCLObjCBoolean;
begin
CurrentHandling:=isHandlingSendEvent;
setHandlingSendEvent(true);
inherited;
setHandlingSendEvent(CurrentHandling);
end;
procedure TCrCocoaApplication.terminate(sender: id);
var
AppDelegate: TChromeAppDelegateIntercept;
begin
AppDelegate:=TChromeAppDelegateIntercept(NSApp.delegate);
AppDelegate.tryToTerminateApplication(CocoaWidgetSet.NSApp);
end;
{$ENDIF}
end.