mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-11 02:10:17 +01:00
336 lines
13 KiB
C++
336 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** 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 mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Conrad Carlen <ccarlen@netscape.com>
|
|
*
|
|
* 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 ***** */
|
|
|
|
#include "CWindowCreator.h"
|
|
|
|
#include "nsIWindowWatcher.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsIWebBrowserSetup.h"
|
|
#include "nsIPrefBranch.h"
|
|
#include "nsIURI.h"
|
|
|
|
#include "CBrowserShell.h"
|
|
#include "CBrowserWindow.h"
|
|
#include "CPrintAttachment.h"
|
|
#include "ApplIDs.h"
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CWindowCreator
|
|
// ---------------------------------------------------------------------------
|
|
|
|
NS_IMPL_ISUPPORTS2(CWindowCreator, nsIWindowCreator, nsIWindowCreator2)
|
|
|
|
CWindowCreator::CWindowCreator()
|
|
{
|
|
}
|
|
|
|
CWindowCreator::~CWindowCreator()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP CWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
|
|
PRUint32 aChromeFlags,
|
|
nsIWebBrowserChrome **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = 0;
|
|
|
|
// we're ignoring aParent,
|
|
// but since windows on the Mac don't have parents anyway...
|
|
try {
|
|
LWindow *theWindow = CreateWindowInternal(aChromeFlags, PR_FALSE, -1, -1);
|
|
CBrowserShell *browser = dynamic_cast<CBrowserShell*>(theWindow->FindPaneByID(CBrowserShell::paneID_MainBrowser));
|
|
ThrowIfNil_(browser);
|
|
browser->GetWebBrowserChrome(_retval);
|
|
} catch(...) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP CWindowCreator::CreateChromeWindow2(nsIWebBrowserChrome *parent,
|
|
PRUint32 chromeFlags, PRUint32 contextFlags,
|
|
nsIURI *aURI, PRBool *aCancel,
|
|
nsIWebBrowserChrome **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCancel);
|
|
*aCancel = PR_FALSE;
|
|
if (contextFlags & nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) {
|
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
|
|
if (prefs) {
|
|
PRBool showBlocker = PR_TRUE;
|
|
prefs->GetBoolPref("browser.popups.showPopupBlocker", &showBlocker);
|
|
if (showBlocker) {
|
|
short itemHit;
|
|
AlertStdAlertParamRec pb;
|
|
|
|
LStr255 msgString(STRx_StdAlertStrings, str_OpeningPopupWindow);
|
|
LStr255 explainString(STRx_StdAlertStrings, str_OpeningPopupWindowExp);
|
|
LStr255 defaultButtonText(STRx_StdButtonTitles, str_DenyAll);
|
|
LStr255 cancelButtonText(STRx_StdButtonTitles, str_Allow);
|
|
|
|
pb.movable = false;
|
|
pb.helpButton = false;
|
|
pb.filterProc = nil;
|
|
pb.defaultText = defaultButtonText;
|
|
pb.cancelText = cancelButtonText;
|
|
pb.otherText = nil;
|
|
pb.defaultButton = kStdOkItemIndex;
|
|
pb.cancelButton = kStdCancelItemIndex;
|
|
pb.position = kWindowAlertPositionParentWindowScreen;
|
|
|
|
::StandardAlert(kAlertStopAlert, msgString, explainString, &pb, &itemHit);
|
|
// This a one-time (for the life of prefs.js) alert
|
|
prefs->SetBoolPref("browser.popups.showPopupBlocker", PR_FALSE);
|
|
if (itemHit == kAlertStdAlertOKButton) {
|
|
// Also, if these prefs are set, the DOM itself will prevent future
|
|
// popups from being opened and our window creator won't even get
|
|
// called. If you wanted to filter each request, don't set these
|
|
// prefs. For this purpose, it's what we want, though.
|
|
prefs->SetBoolPref("dom.disable_open_during_load", PR_TRUE);
|
|
prefs->SetIntPref("dom.disable_open_click_delay", 1000);
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return CreateChromeWindow(parent, chromeFlags, _retval);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
InitializeWindowCreator creates and hands off an object with a callback
|
|
to a window creation function. This will be used by Gecko C++ code
|
|
(never JS) to create new windows when no previous window is handy
|
|
to begin with. This is done in a few exceptional cases, like PSM code.
|
|
Failure to set this callback will only disable the ability to create
|
|
new windows under these circumstances.
|
|
*/
|
|
|
|
nsresult CWindowCreator::Initialize()
|
|
{
|
|
// Create a CWindowCreator and give it to the WindowWatcher service
|
|
// The WindowWatcher service will own it so we don't keep a ref.
|
|
CWindowCreator *windowCreator = new CWindowCreator;
|
|
if (!windowCreator) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
|
if (!wwatch) return NS_ERROR_FAILURE;
|
|
return wwatch->SetWindowCreator(windowCreator);
|
|
}
|
|
|
|
LWindow* CWindowCreator::CreateWindowInternal(PRUint32 inChromeFlags,
|
|
PRBool enablePrinting,
|
|
PRInt32 width, PRInt32 height)
|
|
{
|
|
const SInt16 kStatusBarHeight = 16;
|
|
const SDimension16 kMinimumWindowDimension = { 300, 150 };
|
|
const SInt16 kStdSizeVertMargin = 100;
|
|
|
|
LWindow *theWindow;
|
|
PRUint32 chromeFlags;
|
|
|
|
if (inChromeFlags == nsIWebBrowserChrome::CHROME_DEFAULT)
|
|
chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_RESIZE |
|
|
nsIWebBrowserChrome::CHROME_WINDOW_CLOSE |
|
|
nsIWebBrowserChrome::CHROME_TOOLBAR |
|
|
nsIWebBrowserChrome::CHROME_STATUSBAR;
|
|
else
|
|
chromeFlags = inChromeFlags;
|
|
|
|
// Bounds - Set to an arbitrary rect - we'll size it after all the subviews are in.
|
|
Rect globalBounds;
|
|
globalBounds.left = 4;
|
|
globalBounds.top = 42;
|
|
globalBounds.right = globalBounds.left + 600;
|
|
globalBounds.bottom = globalBounds.top + 400;
|
|
|
|
// ProcID and attributes
|
|
short windowDefProc;
|
|
UInt32 windowAttrs = (windAttr_Enabled | windAttr_Targetable);
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG)
|
|
{
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_TITLEBAR)
|
|
{
|
|
windowDefProc = kWindowMovableModalDialogProc;
|
|
windowAttrs |= windAttr_TitleBar;
|
|
}
|
|
else
|
|
windowDefProc = kWindowModalDialogProc;
|
|
}
|
|
else
|
|
{
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE)
|
|
{
|
|
windowDefProc = kWindowGrowDocumentProc;
|
|
windowAttrs |= windAttr_Resizable;
|
|
windowAttrs |= windAttr_Zoomable;
|
|
}
|
|
else
|
|
windowDefProc = kWindowDocumentProc;
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE)
|
|
windowAttrs |= windAttr_CloseBox;
|
|
}
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)
|
|
windowAttrs |= windAttr_Modal;
|
|
else
|
|
windowAttrs |= windAttr_Regular;
|
|
|
|
theWindow = new CBrowserWindow(LCommander::GetTopCommander(), globalBounds, "\p", windowDefProc, windowAttrs, window_InFront);
|
|
ThrowIfNil_(theWindow);
|
|
|
|
if (windowAttrs & windAttr_Resizable)
|
|
{
|
|
Rect stdBounds, minMaxBounds;
|
|
SDimension16 stdSize;
|
|
|
|
theWindow->CalcStandardBounds(stdBounds);
|
|
stdSize.width = stdBounds.right - stdBounds.left;
|
|
stdSize.height = stdBounds.bottom - stdBounds.top;
|
|
stdSize.width -= kStdSizeVertMargin; // Leave a vertical strip of desktop exposed
|
|
theWindow->SetStandardSize(stdSize);
|
|
minMaxBounds.left = kMinimumWindowDimension.width;
|
|
minMaxBounds.top = kMinimumWindowDimension.height;
|
|
|
|
Rect deskRect;
|
|
::GetRegionBounds(::GetGrayRgn(), &deskRect);
|
|
minMaxBounds.left = kMinimumWindowDimension.width;
|
|
minMaxBounds.top = kMinimumWindowDimension.height;
|
|
minMaxBounds.right = deskRect.right - deskRect.left;
|
|
minMaxBounds.bottom = deskRect.bottom - deskRect.top;
|
|
theWindow->SetMinMaxSize(minMaxBounds);
|
|
}
|
|
|
|
SDimension16 windowSize, toolBarSize;
|
|
theWindow->GetFrameSize(windowSize);
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR)
|
|
{
|
|
LView::SetDefaultView(theWindow);
|
|
LCommander::SetDefaultCommander(theWindow);
|
|
LAttachable::SetDefaultAttachable(nil);
|
|
|
|
LView *toolBarView = static_cast<LView*>(UReanimator::ReadObjects(ResType_PPob, 131));
|
|
ThrowIfNil_(toolBarView);
|
|
|
|
toolBarView->GetFrameSize(toolBarSize);
|
|
toolBarView->PlaceInSuperFrameAt(0, 0, false);
|
|
toolBarSize.width = windowSize.width;
|
|
toolBarView->ResizeFrameTo(toolBarSize.width, toolBarSize.height, false);
|
|
}
|
|
|
|
SPaneInfo aPaneInfo;
|
|
SViewInfo aViewInfo;
|
|
|
|
aPaneInfo.paneID = CBrowserShell::paneID_MainBrowser;
|
|
aPaneInfo.width = windowSize.width;
|
|
aPaneInfo.height = windowSize.height;
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR)
|
|
aPaneInfo.height -= toolBarSize.height;
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR)
|
|
aPaneInfo.height -= kStatusBarHeight - 1;
|
|
aPaneInfo.visible = true;
|
|
aPaneInfo.enabled = true;
|
|
aPaneInfo.bindings.left = true;
|
|
aPaneInfo.bindings.top = true;
|
|
aPaneInfo.bindings.right = true;
|
|
aPaneInfo.bindings.bottom = true;
|
|
aPaneInfo.left = 0;
|
|
aPaneInfo.top = (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR) ? toolBarSize.height : 0;
|
|
aPaneInfo.userCon = 0;
|
|
aPaneInfo.superView = theWindow;
|
|
|
|
aViewInfo.imageSize.width = 0;
|
|
aViewInfo.imageSize.height = 0;
|
|
aViewInfo.scrollPos.h = aViewInfo.scrollPos.v = 0;
|
|
aViewInfo.scrollUnit.h = aViewInfo.scrollUnit.v = 1;
|
|
aViewInfo.reconcileOverhang = 0;
|
|
|
|
CBrowserShell *aShell = new CBrowserShell(aPaneInfo, aViewInfo, chromeFlags, PR_TRUE);
|
|
ThrowIfNil_(aShell);
|
|
aShell->AddAttachments();
|
|
aShell->PutInside(theWindow, false);
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
|
|
{
|
|
nsCOMPtr<nsIWebBrowser> browser;
|
|
aShell->GetWebBrowser(getter_AddRefs(browser));
|
|
nsCOMPtr<nsIWebBrowserSetup> setup(do_QueryInterface(browser));
|
|
if (setup)
|
|
setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER, PR_TRUE);
|
|
}
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR)
|
|
{
|
|
LView::SetDefaultView(theWindow);
|
|
LCommander::SetDefaultCommander(theWindow);
|
|
LAttachable::SetDefaultAttachable(nil);
|
|
|
|
LView *statusView = static_cast<LView*>(UReanimator::ReadObjects(ResType_PPob, 130));
|
|
ThrowIfNil_(statusView);
|
|
|
|
statusView->PlaceInSuperFrameAt(0, windowSize.height - kStatusBarHeight + 1, false);
|
|
statusView->ResizeFrameTo(windowSize.width - 15, kStatusBarHeight, false);
|
|
}
|
|
|
|
if (enablePrinting)
|
|
{
|
|
CPrintAttachment *printAttachment = new CPrintAttachment(CBrowserShell::paneID_MainBrowser);
|
|
ThrowIfNil_(printAttachment);
|
|
theWindow->AddAttachment(printAttachment);
|
|
}
|
|
|
|
// Now the window is constructed...
|
|
theWindow->FinishCreate();
|
|
|
|
Rect theBounds;
|
|
theWindow->GetGlobalBounds(theBounds);
|
|
if (width == -1)
|
|
width = theBounds.right - theBounds.left;
|
|
if (height == -1)
|
|
height = theBounds.bottom - theBounds.top;
|
|
|
|
theWindow->ResizeWindowTo(width, height);
|
|
|
|
return theWindow;
|
|
}
|