1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-04-07 06:50:04 +02:00

CrAppProtocol for cocoa / Add Cocoa CloseChildHandle

This commit is contained in:
martin 2021-02-25 15:10:58 +01:00
parent 08d8c3076f
commit 121a43e824
8 changed files with 225 additions and 7 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;
@ -194,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);
@ -267,6 +271,7 @@ begin
end;
initialization
AddCrDelegate;
if GlobalCEFApp = nil then begin
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin

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;
@ -291,6 +293,9 @@ end;
{$ENDIF}
initialization
{$IFDEF DARWIN} // $IFDEF MACOSX
AddCrDelegate;
{$ENDIF}
if GlobalCEFApp = nil then begin
CreateGlobalCEFApp;
if not GlobalCEFApp.StartMainProcess then begin

View File

@ -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="199">
<Item1>
<Filename Value="..\source\uCEFAccessibilityHandler.pas"/>
<UnitName Value="uCEFAccessibilityHandler"/>
@ -831,6 +831,10 @@
<Filename Value="..\source\uCEFLinkedWinControlBase.pas"/>
<UnitName Value="uCEFLinkedWinControlBase"/>
</Item198>
<Item199>
<Filename Value="..\source\uceflazaruscocoa.pas"/>
<UnitName Value="uceflazaruscocoa"/>
</Item199>
</Files>
<RequiredPkgs Count="4">
<Item1>

View File

@ -65,7 +65,8 @@ uses
uCEFMediaSinkDeviceInfoCallback, uCEFJson, uCEFBitmapBitBuffer,
uCEFPrintDialogCallback, uCEFPrintHandler, uCEFPrintJobCallback,
uCEFLinuxFunctions, uCEFLinuxTypes, uCEFLinuxConstants,
uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, LazarusPackageIntf;
uCEFWorkSchedulerQueueThread, uCEFLinkedWinControlBase, uCEFLazarusCocoa,
LazarusPackageIntf;
implementation

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;

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.