You've already forked lazarus-ccr
Fixed some DOM events. Added new OnCloseWindow event. Added possibility to disable JavaScript. The interface is not fixed and some events could change shortly. Tested with XULRuuner from 1.9.0.16 to 1.9.1.11. XULRunner 1.9.2.x does not work due JavaScript problems, quite sure located in the XULRunner. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1231 8e941d3f-bd1b-0410-a28a-d453659cc2b4
520 lines
15 KiB
ObjectPascal
Executable File
520 lines
15 KiB
ObjectPascal
Executable File
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* 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.
|
|
*
|
|
* The Original Code is GeckoComponents for Delphi.
|
|
*
|
|
* The Initial Developer of the Original Code is Takanori Ito.
|
|
* Portions created by the Initial Developer are Copyright (C) 2003
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
unit GeckoChromeWindow;
|
|
|
|
{$IFDEF LCLCocoa}
|
|
{$MODESWITCH ObjectiveC1}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LResources, {$ENDIF}
|
|
SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
|
Dialogs, CallbackInterfaces, nsXPCOM, nsTypes, nsXPCOM_std19
|
|
{$IFDEF LCLCarbon}, CarbonPrivate {$ENDIF}
|
|
{$IFDEF LCLCocoa}, CocoaAll, CocoaUtils, CocoaPrivate {$ENDIF};
|
|
|
|
type
|
|
TGeckoChromeForm = class(TForm,
|
|
IGeckoCreateWindowTarget,
|
|
nsIWebBrowserChrome,
|
|
nsIEmbeddingSiteWindow,
|
|
nsIWebProgressListener,
|
|
nsIInterfaceRequestor_std19,
|
|
nsIWeakReference,
|
|
nsISupportsWeakReference)
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormResize(Sender: TObject);
|
|
private
|
|
{ Private 錾 }
|
|
FWebBrowser: nsIWebBrowser;
|
|
FChromeFlags: Longword;
|
|
|
|
// nsIWebBrowserChrome
|
|
procedure SetStatus(statusType: PRUint32; const status: PWideChar); safecall;
|
|
function GetWebBrowser(): nsIWebBrowser; safecall;
|
|
procedure SetWebBrowser(aWebBrowser: nsIWebBrowser); safecall;
|
|
function GetChromeFlags: PRUint32; safecall;
|
|
procedure SetChromeFlags(aChromeFlags: PRUint32); safecall;
|
|
procedure DestroyBrowserWindow(); safecall;
|
|
procedure SizeBrowserTo(aCX: PRInt32; aCY: PRInt32); safecall;
|
|
procedure ShowAsModal(); safecall;
|
|
function IsWindowModal(): PRBool; safecall;
|
|
procedure ExitModalEventLoop(aStatus: nsresult); safecall;
|
|
// nsIEmbeddingSiteWindow
|
|
procedure SetDimensions(flags: PRUint32; x, y, cx, cy: PRInt32); safecall;
|
|
procedure GetDimensions(flags: Longword; out x, y, cx, cy: PRInt32); safecall;
|
|
procedure SetFocus; reintroduce; safecall;
|
|
function GetVisibility(): PRBool; safecall;
|
|
procedure SetVisibility(Value: PRBool); safecall;
|
|
function GetTitle(): PWideChar; safecall;
|
|
procedure SetTitle(const Value: PWideChar); safecall;
|
|
function GetSiteWindow: Pointer; safecall;
|
|
// nsIWebProgressListener
|
|
procedure OnStateChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aStateFlags: PRUint32; aStatus: nsresult); safecall;
|
|
procedure OnProgressChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aCurSelfProgress: PRInt32; aMaxSelfProgress: PRInt32; aCurTotalProgress: PRInt32; aMaxTotalProgress: PRInt32); safecall;
|
|
procedure OnLocationChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; location: nsIURI); safecall;
|
|
procedure OnStatusChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aStatus: nsresult; const aMessage: PWideChar); safecall;
|
|
procedure OnSecurityChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; state: PRUint32); safecall;
|
|
// nsIInterfaceRequestor
|
|
function NS_GetInterface(const uuid: TGUID; out Intf): nsresult; stdcall;
|
|
function nsIInterfaceRequestor_std19.GetInterface = NS_GetInterface;
|
|
// for nsIWeakReference
|
|
procedure QueryReferent(const IID: TGUID; out Obj); safecall;
|
|
// for nsISupportsWeakReference
|
|
function GetWeakReference(): nsIWeakReference; safecall;
|
|
|
|
function GetNativeWindow : THANDLE; //FPC port: added this.
|
|
procedure InitWebBrowser;
|
|
procedure UpdateChrome;
|
|
procedure ContentFinishedLoading;
|
|
public
|
|
{ Public 錾 }
|
|
function SafeCallException(Obj: TObject; Addr: Pointer): HResult; override;
|
|
|
|
constructor CreateWithChromeFlags(AOwner: TComponent; aChromeFlags: Longword);
|
|
|
|
// IGeckoCreateWindowTarget
|
|
function DoCreateChromeWindow(chromeFlags: Longword): nsIWebBrowserChrome;
|
|
function GetWebBrowserChrome: nsIWebBrowserChrome;
|
|
property WebBrowser : nsIWebBrowser read FWebBrowser; //FPC port: added this.
|
|
end;
|
|
|
|
var
|
|
GeckoChromeForm: TGeckoChromeForm;
|
|
|
|
implementation
|
|
|
|
{$IFNDEF LCL}
|
|
{$R *.dfm}
|
|
{$ENDIF}
|
|
|
|
uses
|
|
nsXPCOMGlue, nsError, BrowserSupports;
|
|
|
|
{$PUSH}
|
|
{$HINTS OFF}
|
|
procedure UseParameter(var X);
|
|
begin
|
|
end;
|
|
{$POP}
|
|
|
|
constructor TGeckoChromeForm.CreateWithChromeFlags(AOwner: TComponent; AChromeFlags: Longword);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FChromeFlags := aChromeFlags;
|
|
UpdateChrome;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.FormClose(Sender: TObject;
|
|
var Action: TCloseAction);
|
|
begin
|
|
Action := caFree;
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetNativeWindow : THANDLE;
|
|
{$IFDEF LCLCocoa}
|
|
var
|
|
ARect : NSRect;
|
|
AView : NSView;
|
|
{$ENDIF}
|
|
begin
|
|
{$IFDEF MSWINDOWS}Result := Handle;{$ENDIF}
|
|
|
|
{$IFDEF LCLCarbon}Result := TCarbonWindow(Handle).Window;{$ENDIF}
|
|
//Carbon doesn't work but leave in so package compiles in Carbon IDE.
|
|
|
|
// {$IFDEF LCLCocoa}Result := Pointer(TCocoaForm(Handle).MainWindowView.superview);{$ENDIF}
|
|
//Old PasCocoa-based widgetset.
|
|
|
|
//Does adding a view work better than using window's view (below)? No, it doesn't.
|
|
{$IFDEF LCLCocoa}
|
|
ARect := NSView(TCocoaWindow(Handle).contentView).visibleRect;
|
|
ARect.size.width := ARect.size.width - 30;
|
|
ARect.size.height := ARect.size. height - 30;
|
|
ARect.origin.x := 15;
|
|
ARect.origin.y := 15;
|
|
AView := NSView.alloc.initWithFrame(ARect);
|
|
NSView(TCocoaWindow(Handle).contentView).addSubView(AView);
|
|
Result := HANDLE(AView);
|
|
{$ENDIF}
|
|
|
|
//NSLog(NSStringUtf8(FloatToStr(NSView(TCocoaWindow(Handle).contentView).frame.size.width)));
|
|
// {$IFDEF LCLCocoa}Result := Pointer(TCocoaWindow(Handle).contentView);{$ENDIF}
|
|
//New ObjC-based Cocoa widgetset.
|
|
|
|
{$IFDEF LCLGtk}Result := Handle;{$ENDIF} //Is Handle same as GTK Window?
|
|
|
|
{$IFDEF LCLGtk2}Result := Handle;{$ENDIF} //Is Handle same as GTK Window?
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.InitWebBrowser;
|
|
var
|
|
base: nsIBaseWindow;
|
|
begin
|
|
NS_CreateInstance(NS_WEBBROWSER_CID, nsIWebBrowser, FWebBrowser);
|
|
|
|
FWebBrowser.ContainerWindow := Self;
|
|
|
|
base := FWebBrowser as nsIBaseWindow;
|
|
base.InitWindow(GetNativeWindow, nil, 0, 0, ClientWidth, ClientHeight);
|
|
base.Create;
|
|
FWebBrowser.AddWebBrowserListener(Self, nsIWebProgressListener);
|
|
base.SetVisibility(True);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.UpdateChrome;
|
|
begin
|
|
{if (FChromeFlags and CHROME_WINDOW_BORDERS)<>0 then
|
|
if (FChromeFlags and CHROME_WINDOW_RESIZE)<>0 then
|
|
BorderStyle := bsSizeable
|
|
else
|
|
if (FChromeFlags and CHROME_OPENAS_DIALOG)<>0 then
|
|
BorderStyle := bsDialog
|
|
else
|
|
BorderStyle := bsSingle
|
|
else
|
|
BorderStyle := bsNone;}
|
|
BorderStyle := bsSizeable;
|
|
|
|
{
|
|
if (FChromeFlags and CHROME_WINDOW_CLOSE)<>0 then
|
|
BorderIcons := BorderIcons + [biClose]
|
|
else
|
|
BorderIcons := BorderIcons - [biClose];
|
|
}
|
|
|
|
if (FChromeFlags and CHROME_SCROLLBARS)<>0 then
|
|
AutoScroll := True
|
|
else
|
|
AutoScroll := False;
|
|
|
|
{
|
|
if (FChromeFlags and CHROME_TITLEBAR)<>0 then
|
|
BorderIcons := BorderIcons + [biSystemMenu]
|
|
else
|
|
BorderIcons := BorderIcons - [biSystemMenu];
|
|
}
|
|
|
|
end;
|
|
|
|
function TGeckoChromeForm.DoCreateChromeWindow(chromeFlags: Longword): nsIWebBrowserChrome;
|
|
begin
|
|
UseParameter(chromeFlags);
|
|
Result := nil;
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetWebBrowserChrome: nsIWebBrowserChrome;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetStatus(statusType: Longword; const status: PWideChar);
|
|
begin
|
|
UseParameter(statusType);
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetWebBrowser: nsIWebBrowser;
|
|
begin
|
|
Result := FWebBrowser as nsIWebBrowser;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetWebBrowser(aWebBrowser: nsIWebBrowser);
|
|
begin
|
|
UseParameter(aWebBrowser);
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetChromeFlags: PRUint32;
|
|
begin
|
|
Result := FChromeFlags;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetChromeFlags(aChromeFlags: Longword);
|
|
begin
|
|
FChromeFlags := aChromeFlags;
|
|
UpdateChrome;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.DestroyBrowserWindow;
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SizeBrowserTo(aCX, aCY: Integer);
|
|
var
|
|
dx, dy: Integer;
|
|
begin
|
|
dx := Width - ClientWidth;
|
|
dy := Height - ClientHeight;
|
|
SetBounds(Left, Top, aCX+dx, aCY+dy);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.ShowAsModal;
|
|
begin
|
|
Visible := False;
|
|
ShowModal;
|
|
end;
|
|
|
|
function TGeckoChromeForm.IsWindowModal: PRBool;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.ExitModalEventLoop(aStatus: nsresult); safecall;
|
|
begin
|
|
UseParameter(aStatus);
|
|
ModalResult := 1;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetDimensions(flags: Longword; x, y, cx, cy: Longint);
|
|
const
|
|
FLAGS_POSITION = NS_IEMBEDDINGSITEWINDOW_DIM_FLAGS_POSITION;
|
|
FLAGS_SIZE_INNER = ns_IEmbeddingSiteWindow_DIM_FLAGS_SIZE_INNER;
|
|
FLAGS_SIZE_OUTER = ns_IEmbeddingSiteWindow_DIM_FLAGS_SIZE_OUTER;
|
|
var
|
|
dx, dy: Integer;
|
|
begin
|
|
dx := Width - ClientWidth;
|
|
dy := Height - ClientHeight;
|
|
|
|
if (flags and FLAGS_POSITION)<>0 then
|
|
begin
|
|
if (flags and FLAGS_SIZE_INNER)<>0 then
|
|
begin
|
|
Bounds(x, y, cx+dx, cy+dy);
|
|
end else
|
|
if (flags and FLAGS_SIZE_OUTER)<>0 then
|
|
begin
|
|
Bounds(x, y, cx, cy);
|
|
end else
|
|
begin
|
|
Bounds(x, y, Width, Height);
|
|
end;
|
|
end else
|
|
if (flags and FLAGS_SIZE_INNER)<>0 then
|
|
begin
|
|
Bounds(Left, Top, cx+dx, cy+dy);
|
|
end else
|
|
if (flags and FLAGS_SIZE_OUTER)<>0 then
|
|
begin
|
|
Bounds(Left, Top, cx, cy);
|
|
end;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.GetDimensions(flags: Longword; out x, y, cx, cy: Longint);
|
|
const
|
|
FLAGS_POSITION = ns_IEmbeddingSiteWindow_DIM_FLAGS_POSITION;
|
|
FLAGS_SIZE_INNER = ns_IEmbeddingSiteWindow_DIM_FLAGS_SIZE_INNER;
|
|
FLAGS_SIZE_OUTER = ns_IEmbeddingSiteWindow_DIM_FLAGS_SIZE_OUTER;
|
|
begin
|
|
if (flags and FLAGS_POSITION)<>0 then
|
|
begin
|
|
x := Left;
|
|
y := Top;
|
|
end;
|
|
|
|
if (flags and FLAGS_SIZE_INNER)<>0 then
|
|
begin
|
|
cx := ClientWidth;
|
|
cy := ClientHeight;
|
|
end else
|
|
if (flags and FLAGS_SIZE_OUTER)<>0 then
|
|
begin
|
|
cx := Width;
|
|
cy := Height;
|
|
end;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetFocus();
|
|
begin
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetVisibility: PRBool;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetVisibility(Value: LongBool);
|
|
begin
|
|
UseParameter(Value);
|
|
//Visible := Value;
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetTitle: PWideChar;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.SetTitle(const Value: PWideChar);
|
|
begin
|
|
Caption := WideString(Value);
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetSiteWindow: Pointer;
|
|
begin
|
|
//Known "not safe" conversion.
|
|
{$PUSH}
|
|
{$HINTS OFF}
|
|
Result := Pointer(GetNativeWindow);
|
|
{$POP}
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.OnStateChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aStateFlags: PRUint32; aStatus: nsresult);
|
|
begin
|
|
UseParameter(aWebProgress);
|
|
UseParameter(aRequest);
|
|
UseParameter(aStatus);
|
|
if ((aStateFlags and NS_IWEBPROGRESSLISTENER_STATE_STOP)<>0) and
|
|
((aStateFlags and NS_IWEBPROGRESSLISTENER_STATE_IS_DOCUMENT)<>0) then
|
|
begin
|
|
ContentFinishedLoading();
|
|
end;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.OnProgressChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aCurSelfProgress: PRInt32; aMaxSelfProgress: PRInt32; aCurTotalProgress: PRInt32; aMaxTotalProgress: PRInt32);
|
|
begin
|
|
UseParameter(aWebProgress);
|
|
UseParameter(aRequest);
|
|
UseParameter(aCurSelfProgress);
|
|
UseParameter(aMaxSelfProgress);
|
|
UseParameter(aCurTotalProgress);
|
|
UseParameter(aMaxTotalProgress);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.OnLocationChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; location: nsIURI);
|
|
begin
|
|
UseParameter(aWebProgress);
|
|
UseParameter(aRequest);
|
|
UseParameter(location);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.OnStatusChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; aStatus: nsresult; const aMessage: PWideChar);
|
|
begin
|
|
UseParameter(aWebProgress);
|
|
UseParameter(aRequest);
|
|
UseParameter(aStatus);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.OnSecurityChange(aWebProgress: nsIWebProgress; aRequest: nsIRequest; state: PRUint32);
|
|
begin
|
|
UseParameter(aWebProgress);
|
|
UseParameter(aRequest);
|
|
UseParameter(state);
|
|
end;
|
|
|
|
function TGeckoChromeForm.NS_GetInterface(const uuid: TGUID; out Intf): nsresult;
|
|
var
|
|
domwin: nsIDOMWindow;
|
|
begin
|
|
if IsEqualGUID(uuid, nsIDOMWindow) then
|
|
begin
|
|
if Assigned(FWebBrowser) then
|
|
begin
|
|
domwin := FWebBrowser.ContentDOMWindow;
|
|
Result := domwin.QueryInterface(uuid, Intf);
|
|
end else
|
|
Result := NS_ERROR_NOT_INITIALIZED;
|
|
end else
|
|
begin
|
|
// FPC port: Result is PRUInt32, but QueryInterface returns Longint,
|
|
// so cast to nsresult to prevent range check error.
|
|
Result := nsresult(QueryInterface(uuid, Intf));
|
|
end;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.QueryReferent(const IID: TGUID; out Obj);
|
|
var
|
|
rv: nsresult;
|
|
begin
|
|
rv := QueryInterface(IID, Obj);
|
|
if NS_FAILED(rv) then
|
|
raise EIntfCastError.Create('QueryReferent');
|
|
end;
|
|
|
|
function TGeckoChromeForm.GetWeakReference: nsIWeakReference;
|
|
begin
|
|
Result := Self as nsIWeakReference;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.FormCreate(Sender: TObject);
|
|
begin
|
|
InitWebBrowser;
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.FormResize(Sender: TObject);
|
|
var
|
|
baseWin: nsIBaseWindow;
|
|
begin
|
|
//
|
|
baseWin:=FWebBrowser as nsIBaseWindow;
|
|
baseWin.SetPositionAndSize(0, 0, ClientWidth, ClientHeight, True);
|
|
baseWin.SetVisibility(True);
|
|
end;
|
|
|
|
procedure TGeckoChromeForm.ContentFinishedLoading;
|
|
var
|
|
contentWin: nsIDOMWindow;
|
|
begin
|
|
try
|
|
contentWin := FWebBrowser.ContentDOMWindow;
|
|
contentWin.SizeToContent;
|
|
Visible := True;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF LCL}
|
|
const
|
|
E_FAIL = HRESULT($80004005);
|
|
{$ENDIF}
|
|
|
|
function TGeckoChromeForm.SafeCallException(Obj: TObject; Addr: Pointer): HResult;
|
|
begin
|
|
UseParameter(Addr);
|
|
if Obj is EIntfCastError then
|
|
Result := E_NOINTERFACE
|
|
else
|
|
Result := E_FAIL;
|
|
end;
|
|
|
|
initialization
|
|
{$IFDEF LCL}
|
|
{$I GeckoChromeWindow.lrs}
|
|
{$ENDIF}
|
|
|
|
end.
|