Back to index

lightning-sunbird  0.9+nobinonly
CWindowCreator.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Conrad Carlen <ccarlen@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "CWindowCreator.h"
00040 
00041 #include "nsIWindowWatcher.h"
00042 #include "nsServiceManagerUtils.h"
00043 #include "nsIWebBrowserSetup.h"
00044 #include "nsIPrefBranch.h"
00045 #include "nsIURI.h"
00046 
00047 #include "CBrowserShell.h"
00048 #include "CBrowserWindow.h"
00049 #include "CPrintAttachment.h"
00050 #include "ApplIDs.h"
00051 
00052 // ---------------------------------------------------------------------------
00053 //  CWindowCreator
00054 // ---------------------------------------------------------------------------
00055 
00056 NS_IMPL_ISUPPORTS2(CWindowCreator, nsIWindowCreator, nsIWindowCreator2)
00057 
00058 CWindowCreator::CWindowCreator()
00059 {
00060 }
00061 
00062 CWindowCreator::~CWindowCreator()
00063 {
00064 }
00065 
00066 NS_IMETHODIMP CWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
00067                                                  PRUint32 aChromeFlags,
00068                                                  nsIWebBrowserChrome **_retval)
00069 {
00070     NS_ENSURE_ARG_POINTER(_retval);
00071     *_retval = 0;
00072 
00073     // we're ignoring aParent,
00074     // but since windows on the Mac don't have parents anyway...
00075     try {
00076         LWindow *theWindow = CreateWindowInternal(aChromeFlags, PR_FALSE, -1, -1);
00077         CBrowserShell *browser = dynamic_cast<CBrowserShell*>(theWindow->FindPaneByID(CBrowserShell::paneID_MainBrowser));
00078         ThrowIfNil_(browser);
00079         browser->GetWebBrowserChrome(_retval);
00080     } catch(...) {
00081         return NS_ERROR_FAILURE;
00082     }
00083 
00084     return NS_OK;
00085 }
00086 
00087 NS_IMETHODIMP CWindowCreator::CreateChromeWindow2(nsIWebBrowserChrome *parent,
00088                                                   PRUint32 chromeFlags, PRUint32 contextFlags,
00089                                                   nsIURI *aURI, PRBool *aCancel,
00090                                                   nsIWebBrowserChrome **_retval)
00091 {
00092     NS_ENSURE_ARG_POINTER(aCancel);
00093     *aCancel = PR_FALSE;
00094     if (contextFlags & nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) {
00095         nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
00096         if (prefs) {
00097             PRBool showBlocker = PR_TRUE;
00098             prefs->GetBoolPref("browser.popups.showPopupBlocker", &showBlocker);
00099             if (showBlocker) {
00100                 short itemHit;
00101                 AlertStdAlertParamRec pb;
00102 
00103                 LStr255 msgString(STRx_StdAlertStrings, str_OpeningPopupWindow);
00104                 LStr255 explainString(STRx_StdAlertStrings, str_OpeningPopupWindowExp);
00105                 LStr255 defaultButtonText(STRx_StdButtonTitles, str_DenyAll);
00106                 LStr255 cancelButtonText(STRx_StdButtonTitles, str_Allow);
00107                 
00108                 pb.movable = false;
00109                 pb.helpButton = false;
00110                 pb.filterProc = nil;
00111                 pb.defaultText = defaultButtonText;
00112                 pb.cancelText = cancelButtonText;
00113                 pb.otherText = nil;
00114                 pb.defaultButton = kStdOkItemIndex;
00115                 pb.cancelButton = kStdCancelItemIndex;
00116                 pb.position = kWindowAlertPositionParentWindowScreen;
00117 
00118                 ::StandardAlert(kAlertStopAlert, msgString, explainString, &pb, &itemHit);
00119                 // This a one-time (for the life of prefs.js) alert
00120                 prefs->SetBoolPref("browser.popups.showPopupBlocker", PR_FALSE);
00121                 if (itemHit == kAlertStdAlertOKButton) {
00122                     // Also, if these prefs are set, the DOM itself will prevent future
00123                     // popups from being opened and our window creator won't even get
00124                     // called. If you wanted to filter each request, don't set these
00125                     // prefs. For this purpose, it's what we want, though.
00126                     prefs->SetBoolPref("dom.disable_open_during_load", PR_TRUE);
00127                     prefs->SetIntPref("dom.disable_open_click_delay", 1000);
00128                     return NS_ERROR_FAILURE;
00129                 }
00130             }
00131         }
00132     }
00133     return CreateChromeWindow(parent, chromeFlags, _retval);
00134 }
00135 
00136 
00137 
00138 /*
00139    InitializeWindowCreator creates and hands off an object with a callback
00140    to a window creation function. This will be used by Gecko C++ code
00141    (never JS) to create new windows when no previous window is handy
00142    to begin with. This is done in a few exceptional cases, like PSM code.
00143    Failure to set this callback will only disable the ability to create
00144    new windows under these circumstances.
00145 */
00146 
00147 nsresult CWindowCreator::Initialize()
00148 {
00149     // Create a CWindowCreator and give it to the WindowWatcher service
00150     // The WindowWatcher service will own it so we don't keep a ref.
00151     CWindowCreator *windowCreator = new CWindowCreator;
00152     if (!windowCreator) return NS_ERROR_FAILURE;
00153     
00154     nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
00155     if (!wwatch) return NS_ERROR_FAILURE;
00156     return wwatch->SetWindowCreator(windowCreator);
00157 }
00158 
00159 LWindow* CWindowCreator::CreateWindowInternal(PRUint32 inChromeFlags,
00160                                               PRBool enablePrinting,
00161                                               PRInt32 width, PRInt32 height)
00162 {
00163     const SInt16 kStatusBarHeight = 16;
00164     const SDimension16 kMinimumWindowDimension = { 300, 150 };
00165     const SInt16 kStdSizeVertMargin = 100;
00166     
00167     LWindow         *theWindow;
00168     PRUint32        chromeFlags;
00169     
00170     if (inChromeFlags == nsIWebBrowserChrome::CHROME_DEFAULT)
00171         chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_RESIZE |
00172                       nsIWebBrowserChrome::CHROME_WINDOW_CLOSE |
00173                       nsIWebBrowserChrome::CHROME_TOOLBAR |
00174                       nsIWebBrowserChrome::CHROME_STATUSBAR;
00175     else
00176         chromeFlags = inChromeFlags;
00177     
00178     // Bounds - Set to an arbitrary rect - we'll size it after all the subviews are in.
00179     Rect globalBounds;
00180     globalBounds.left = 4;
00181     globalBounds.top = 42;
00182     globalBounds.right = globalBounds.left + 600;
00183     globalBounds.bottom = globalBounds.top + 400;
00184     
00185     // ProcID and attributes
00186     short windowDefProc;
00187     UInt32 windowAttrs = (windAttr_Enabled | windAttr_Targetable);
00188     if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG)
00189     {
00190         if (chromeFlags & nsIWebBrowserChrome::CHROME_TITLEBAR)
00191         {
00192             windowDefProc = kWindowMovableModalDialogProc;
00193             windowAttrs |= windAttr_TitleBar;
00194         }
00195         else
00196             windowDefProc = kWindowModalDialogProc;            
00197     }
00198     else
00199     {
00200         if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE)
00201         {
00202             windowDefProc = kWindowGrowDocumentProc;
00203             windowAttrs |= windAttr_Resizable;
00204             windowAttrs |= windAttr_Zoomable;
00205         }
00206         else
00207             windowDefProc = kWindowDocumentProc;            
00208         
00209         if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE)
00210             windowAttrs |= windAttr_CloseBox;
00211     }
00212 
00213     if (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)
00214         windowAttrs |= windAttr_Modal;
00215     else
00216         windowAttrs |= windAttr_Regular;    
00217     
00218     theWindow = new CBrowserWindow(LCommander::GetTopCommander(), globalBounds, "\p", windowDefProc, windowAttrs, window_InFront);
00219     ThrowIfNil_(theWindow);
00220     
00221     if (windowAttrs & windAttr_Resizable)
00222     {
00223         Rect stdBounds, minMaxBounds;
00224         SDimension16 stdSize;
00225         
00226         theWindow->CalcStandardBounds(stdBounds);
00227         stdSize.width = stdBounds.right - stdBounds.left;
00228         stdSize.height = stdBounds.bottom - stdBounds.top;
00229         stdSize.width -= kStdSizeVertMargin; // Leave a vertical strip of desktop exposed
00230         theWindow->SetStandardSize(stdSize);
00231         minMaxBounds.left = kMinimumWindowDimension.width;
00232         minMaxBounds.top = kMinimumWindowDimension.height;
00233         
00234         Rect  deskRect;
00235         ::GetRegionBounds(::GetGrayRgn(), &deskRect);
00236         minMaxBounds.left = kMinimumWindowDimension.width;
00237         minMaxBounds.top = kMinimumWindowDimension.height;
00238         minMaxBounds.right = deskRect.right - deskRect.left;
00239         minMaxBounds.bottom = deskRect.bottom - deskRect.top;
00240         theWindow->SetMinMaxSize(minMaxBounds);
00241     }
00242 
00243     SDimension16 windowSize, toolBarSize;
00244     theWindow->GetFrameSize(windowSize);
00245 
00246     if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR)
00247     {
00248         LView::SetDefaultView(theWindow);
00249         LCommander::SetDefaultCommander(theWindow);
00250         LAttachable::SetDefaultAttachable(nil);
00251 
00252         LView *toolBarView = static_cast<LView*>(UReanimator::ReadObjects(ResType_PPob, 131));
00253         ThrowIfNil_(toolBarView);
00254                     
00255         toolBarView->GetFrameSize(toolBarSize);
00256         toolBarView->PlaceInSuperFrameAt(0, 0, false);
00257         toolBarSize.width = windowSize.width;
00258         toolBarView->ResizeFrameTo(toolBarSize.width, toolBarSize.height, false);
00259     }
00260 
00261     SPaneInfo aPaneInfo;
00262     SViewInfo aViewInfo;
00263     
00264     aPaneInfo.paneID = CBrowserShell::paneID_MainBrowser;
00265     aPaneInfo.width = windowSize.width;
00266     aPaneInfo.height = windowSize.height;
00267     if (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR)
00268         aPaneInfo.height -= toolBarSize.height;
00269     if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR)
00270         aPaneInfo.height -= kStatusBarHeight - 1;
00271     aPaneInfo.visible = true;
00272     aPaneInfo.enabled = true;
00273     aPaneInfo.bindings.left = true;
00274     aPaneInfo.bindings.top = true;
00275     aPaneInfo.bindings.right = true;
00276     aPaneInfo.bindings.bottom = true;
00277     aPaneInfo.left = 0;
00278     aPaneInfo.top = (chromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR) ? toolBarSize.height : 0;
00279     aPaneInfo.userCon = 0;
00280     aPaneInfo.superView = theWindow;
00281     
00282     aViewInfo.imageSize.width = 0;
00283     aViewInfo.imageSize.height = 0;
00284     aViewInfo.scrollPos.h = aViewInfo.scrollPos.v = 0;
00285     aViewInfo.scrollUnit.h = aViewInfo.scrollUnit.v = 1;
00286     aViewInfo.reconcileOverhang = 0;
00287     
00288     CBrowserShell *aShell = new CBrowserShell(aPaneInfo, aViewInfo, chromeFlags, PR_TRUE);
00289     ThrowIfNil_(aShell);
00290     aShell->AddAttachments();
00291     aShell->PutInside(theWindow, false);
00292     
00293     if (chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
00294     {
00295         nsCOMPtr<nsIWebBrowser> browser;
00296         aShell->GetWebBrowser(getter_AddRefs(browser));
00297         nsCOMPtr<nsIWebBrowserSetup> setup(do_QueryInterface(browser));
00298         if (setup)
00299           setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER, PR_TRUE);
00300     }
00301        
00302     if (chromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR)
00303     {
00304         LView::SetDefaultView(theWindow);
00305         LCommander::SetDefaultCommander(theWindow);
00306         LAttachable::SetDefaultAttachable(nil);
00307 
00308         LView *statusView = static_cast<LView*>(UReanimator::ReadObjects(ResType_PPob, 130));
00309         ThrowIfNil_(statusView);
00310         
00311         statusView->PlaceInSuperFrameAt(0, windowSize.height - kStatusBarHeight + 1, false);
00312         statusView->ResizeFrameTo(windowSize.width - 15, kStatusBarHeight, false);
00313     }        
00314 
00315     if (enablePrinting)
00316     {
00317         CPrintAttachment *printAttachment = new CPrintAttachment(CBrowserShell::paneID_MainBrowser);
00318         ThrowIfNil_(printAttachment);
00319         theWindow->AddAttachment(printAttachment);
00320     }
00321         
00322     // Now the window is constructed...
00323     theWindow->FinishCreate();        
00324 
00325     Rect    theBounds;
00326     theWindow->GetGlobalBounds(theBounds);
00327     if (width == -1)
00328         width = theBounds.right - theBounds.left;
00329     if (height == -1)
00330         height = theBounds.bottom - theBounds.top;
00331         
00332     theWindow->ResizeWindowTo(width, height);
00333 
00334     return theWindow;
00335 }