pjs/embedding/browser/powerplant/source/CWindowCreator.cpp

336 строки
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 "nsIServiceManagerUtils.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;
}