Back to index

lightning-sunbird  0.9+nobinonly
nsXPBaseWindow.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 Communicator client 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) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsCOMPtr.h"
00038 #include "prmem.h"
00039 
00040 #include "nsXPBaseWindow.h"
00041 
00042 #include "nsCOMPtr.h"
00043 #include "nsIPrompt.h"
00044 #include "nsIAppShell.h"
00045 #include "nsIWidget.h"
00046 #include "nsIDOMDocument.h"
00047 #include "nsIURL.h"
00048 #include "nsIComponentManager.h"
00049 #include "nsIFactory.h"
00050 #include "nsCRT.h"
00051 #include "nsWidgetsCID.h"
00052 #include "nsViewerApp.h"
00053 
00054 #include "nsIDocument.h"
00055 #include "nsPresContext.h"
00056 #include "nsIDocumentViewer.h"
00057 #include "nsIContentViewer.h"
00058 #include "nsIPresShell.h"
00059 #include "nsIDocument.h"
00060 #include "nsIDocument.h"
00061 #include "nsIDOMEventReceiver.h"
00062 #include "nsIDOMElement.h"
00063 #include "nsIDOMHTMLDocument.h"
00064 #include "nsIWindowListener.h"
00065 #include "nsIBaseWindow.h"
00066 #include "nsIWebNavigation.h"
00067 #include "nsIViewManager.h"
00068 #include "nsGUIEvent.h"
00069 
00070 #include "nsIDocShell.h"
00071 #include "nsIDocShellTreeItem.h"
00072 #include "nsIDocShellTreeNode.h"
00073 #include "nsXPIDLString.h"
00074 #include "nsReadableUtils.h"
00075 
00076 #include <ctype.h> // tolower
00077 
00078 // XXX For font setting below
00079 #include "nsFont.h"
00080 //#include "nsUnitConversion.h"
00081 //#include "nsIDeviceContext.h"
00082 
00083 static NS_DEFINE_IID(kWindowCID, NS_WINDOW_CID);
00084 
00085 
00086 static NS_DEFINE_IID(kIXPBaseWindowIID, NS_IXPBASE_WINDOW_IID);
00087 static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
00088 static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
00089 static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
00090 static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
00091 
00092 static NS_DEFINE_IID(kIDOMMouseListenerIID,   NS_IDOMMOUSELISTENER_IID);
00093 static NS_DEFINE_IID(kIDOMEventReceiverIID,   NS_IDOMEVENTRECEIVER_IID);
00094 static NS_DEFINE_IID(kIDOMHTMLDocumentIID, NS_IDOMHTMLDOCUMENT_IID);
00095 
00096 //----------------------------------------------------------------------
00097 nsXPBaseWindow::nsXPBaseWindow() :
00098   mContentRoot(nsnull),
00099   mWindowListener(nsnull),
00100   mDocIsLoaded(PR_FALSE),
00101   mAppShell(nsnull)
00102 {
00103 }
00104 
00105 //----------------------------------------------------------------------
00106 nsXPBaseWindow::~nsXPBaseWindow()
00107 {
00108   NS_IF_RELEASE(mContentRoot);
00109   NS_IF_RELEASE(mAppShell);
00110 }
00111 
00112 //----------------------------------------------------------------------
00113 NS_IMPL_ADDREF(nsXPBaseWindow)
00114 NS_IMPL_RELEASE(nsXPBaseWindow)
00115 
00116 //----------------------------------------------------------------------
00117 nsresult nsXPBaseWindow::QueryInterface(const nsIID& aIID,
00118                                         void** aInstancePtrResult)
00119 {
00120   NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
00121   if (nsnull == aInstancePtrResult) {
00122     return NS_ERROR_NULL_POINTER;
00123   }
00124 
00125   *aInstancePtrResult = NULL;
00126 
00127   if (aIID.Equals(kIXPBaseWindowIID)) {
00128     *aInstancePtrResult = (void*) ((nsIXPBaseWindow*)this);
00129     NS_ADDREF_THIS();
00130     return NS_OK;
00131   }
00132   if (aIID.Equals(kIDOMMouseListenerIID)) {
00133     NS_ADDREF_THIS(); // Increase reference count for caller
00134     *aInstancePtrResult = (void *)((nsIDOMMouseListener*)this);
00135     return NS_OK;
00136   }
00137   
00138   if (aIID.Equals(kISupportsIID)) {
00139     NS_ADDREF_THIS();
00140     *aInstancePtrResult = (void*) ((nsISupports*)((nsIXPBaseWindow*)this));
00141     return NS_OK;
00142   }
00143 
00144   return NS_NOINTERFACE;
00145 }
00146 
00147 
00148 //----------------------------------------------------------------------
00149 static nsEventStatus PR_CALLBACK
00150 HandleXPDialogEvent(nsGUIEvent *aEvent)
00151 { 
00152   nsEventStatus result = nsEventStatus_eIgnore;
00153 
00154   nsXPBaseWindow* baseWin;
00155   aEvent->widget->GetClientData(((void*&)baseWin));
00156 
00157   if (nsnull != baseWin) {
00158     nsSizeEvent* sizeEvent;
00159     switch(aEvent->message) {
00160       case NS_SIZE:
00161         sizeEvent = (nsSizeEvent*)aEvent;  
00162         baseWin->Layout(sizeEvent->windowSize->width,
00163                         sizeEvent->windowSize->height);
00164         result = nsEventStatus_eConsumeNoDefault;
00165         break;
00166 
00167     case NS_DESTROY: {
00168         //nsViewerApp* app = baseWin->mApp;
00169         result = nsEventStatus_eConsumeDoDefault;
00170         baseWin->Close();
00171         NS_RELEASE(baseWin);
00172       }
00173       return result;
00174 
00175     default:
00176       break;
00177     }
00178     //NS_RELEASE(baseWin);
00179   }
00180   return result;
00181 }
00182 
00183 
00184 //----------------------------------------------------------------------
00185 nsresult nsXPBaseWindow::Init(nsXPBaseWindowType aType,
00186                               nsIAppShell*       aAppShell,
00187                               const nsString&    aDialogURL,
00188                               const nsString&    aTitle,
00189                               const nsRect&      aBounds,
00190                               PRUint32           aChromeMask,
00191                               PRBool             aAllowPlugins)
00192 {
00193   mAllowPlugins = aAllowPlugins;
00194   mWindowType   = aType;
00195   mAppShell     = aAppShell;
00196   NS_IF_ADDREF(mAppShell);
00197 
00198   // Create top level window
00199   nsresult rv;
00200   rv = CallCreateInstance(kWindowCID, &mWindow);
00201   if (NS_FAILED(rv)) {
00202     return rv;
00203   }
00204 
00205   mWindow->SetClientData(this);
00206 
00207   nsWidgetInitData initData;
00208   initData.mWindowType = eWindowType_toplevel;
00209   initData.mBorderStyle = eBorderStyle_default;
00210 
00211   nsRect r(0, 0, aBounds.width, aBounds.height);
00212   mWindow->Create((nsIWidget*)NULL, r, HandleXPDialogEvent,
00213                   nsnull, aAppShell, nsnull, &initData);
00214   mWindow->GetBounds(r);
00215 
00216   // Create web shell
00217   rv = CallCreateInstance("@mozilla.org/webshell;1", &mDocShell);
00218   if (NS_FAILED(rv)) {
00219     return rv;
00220   }
00221   r.x = r.y = 0;
00222   mDocShell->SetAllowPlugins(aAllowPlugins);
00223   nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
00224 
00225   rv = docShellWin->InitWindow(nsnull, mWindow, r.x, r.y, r.width, r.height);
00226   docShellWin->Create();
00227   docShellWin->SetVisibility(PR_TRUE);
00228 
00229   // Now lay it all out
00230   Layout(r.width, r.height);
00231 
00232   // Load URL to Load GUI
00233   mDialogURL = aDialogURL;
00234   LoadURL(mDialogURL);
00235 
00236   SetTitle(aTitle.get());
00237 
00238   return NS_OK;
00239 }
00240 
00241 //----------------------------------------------------------------------
00242 void nsXPBaseWindow::ForceRefresh()
00243 {
00244   nsIPresShell* shell;
00245   GetPresShell(shell);
00246   if (nsnull != shell) {
00247     nsIViewManager *vm = shell->GetViewManager();
00248     if (vm) {
00249       nsIView* root;
00250       vm->GetRootView(root);
00251       if (nsnull != root) {
00252         vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
00253       }
00254     }
00255     NS_RELEASE(shell);
00256   }
00257 }
00258 
00259 //----------------------------------------------------------------------
00260 void nsXPBaseWindow::Layout(PRInt32 aWidth, PRInt32 aHeight)
00261 {
00262   nsRect rr(0, 0, aWidth, aHeight);
00263   nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
00264   docShellWin->SetPositionAndSize(rr.x, rr.y, rr.width, rr.height, PR_FALSE);
00265 }
00266 
00267 //----------------------------------------------------------------------
00268 NS_IMETHODIMP nsXPBaseWindow::SetLocation(PRInt32 aX, PRInt32 aY)
00269 {
00270   NS_PRECONDITION(nsnull != mWindow, "null window");
00271   mWindow->Move(aX, aY);
00272   return NS_OK;
00273 }
00274 
00275 
00276 //----------------------------------------------------------------------
00277 NS_IMETHODIMP nsXPBaseWindow::SetDimensions(PRInt32 aWidth, PRInt32 aHeight)
00278 {
00279   NS_PRECONDITION(nsnull != mWindow, "null window");
00280 
00281   // XXX We want to do this in one shot
00282   mWindow->Resize(aWidth, aHeight, PR_FALSE);
00283   Layout(aWidth, aHeight);
00284 
00285   return NS_OK;
00286 }
00287 
00288 //----------------------------------------------------------------------
00289 NS_IMETHODIMP nsXPBaseWindow::GetBounds(nsRect& aBounds)
00290 {
00291   mWindow->GetBounds(aBounds);
00292   return NS_OK;
00293 }
00294 
00295 //----------------------------------------------------------------------
00296 NS_IMETHODIMP
00297 nsXPBaseWindow::GetWindowBounds(nsRect& aBounds)
00298 {
00299   //XXX This needs to be non-client bounds when it exists.
00300   mWindow->GetBounds(aBounds);
00301   return NS_OK;
00302 }
00303 
00304 //----------------------------------------------------------------------
00305 NS_IMETHODIMP nsXPBaseWindow::SetVisible(PRBool aIsVisible)
00306 {
00307   NS_PRECONDITION(nsnull != mWindow, "null window");
00308   mWindow->Show(aIsVisible);
00309   return NS_OK;
00310 }
00311 
00312 //----------------------------------------------------------------------
00313 NS_IMETHODIMP nsXPBaseWindow::Close()
00314 {
00315   if (nsnull != mWindowListener) {
00316     mWindowListener->Destroy(this);
00317   }
00318 
00319   if (mDocShell) {
00320     nsCOMPtr<nsIBaseWindow> webShellWin(do_QueryInterface(mDocShell));
00321     webShellWin->Destroy();
00322     NS_RELEASE(mDocShell);
00323   }
00324 
00325   if (nsnull != mWindow) {
00326     nsIWidget* w = mWindow;
00327     NS_RELEASE(w);
00328   }
00329 
00330   return NS_OK;
00331 }
00332 
00333 
00334 //----------------------------------------------------------------------
00335 NS_IMETHODIMP nsXPBaseWindow::GetDocShell(nsIDocShell*& aResult)
00336 {
00337   NS_IF_ADDREF(aResult = mDocShell);
00338   return NS_OK;
00339 }
00340 
00341 //---------------------------------------------------------------
00342 NS_IMETHODIMP nsXPBaseWindow::SetTitle(const PRUnichar* aTitle)
00343 {
00344   NS_PRECONDITION(nsnull != mWindow, "null window");
00345   mTitle = aTitle;
00346   nsAutoString newTitle(aTitle);
00347   mWindow->SetTitle(newTitle);
00348   return NS_OK;
00349 }
00350 
00351 //---------------------------------------------------------------
00352 NS_IMETHODIMP nsXPBaseWindow::GetTitle(const PRUnichar** aResult)
00353 {
00354   *aResult = ToNewUnicode(mTitle);
00355   return NS_OK;
00356 }
00357 
00358 //---------------------------------------------------------------
00359 NS_IMETHODIMP nsXPBaseWindow::LoadURL(const nsString& aURL)
00360 {
00361    nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
00362    webNav->LoadURI(aURL.get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull);
00363    return NS_OK;
00364 }
00365 
00366 //-----------------------------------------------------------------
00367 NS_IMETHODIMP nsXPBaseWindow::AddEventListener(nsIDOMNode * aNode)
00368 {
00369   nsIDOMEventReceiver * receiver;
00370 
00371   NS_PRECONDITION(nsnull != aNode, "adding event listener to null node");
00372 
00373   if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) {
00374     receiver->AddEventListenerByIID((nsIDOMMouseListener*)this, kIDOMMouseListenerIID);
00375     NS_RELEASE(receiver);
00376     return NS_OK;
00377   }
00378   return NS_ERROR_FAILURE;
00379 }
00380 
00381 //-----------------------------------------------------------------
00382 NS_IMETHODIMP nsXPBaseWindow::RemoveEventListener(nsIDOMNode * aNode)
00383 {
00384   nsIDOMEventReceiver * receiver;
00385 
00386   NS_PRECONDITION(nsnull != aNode, "removing event listener from null node");
00387 
00388   if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) {
00389     receiver->RemoveEventListenerByIID(this, kIDOMMouseListenerIID);
00390     NS_RELEASE(receiver);
00391     return NS_OK;
00392   }
00393   return NS_ERROR_FAILURE;
00394 }
00395 
00396 //-----------------------------------------------------------------
00397 NS_IMETHODIMP nsXPBaseWindow::AddWindowListener(nsIWindowListener * aWindowListener)
00398 {
00399   if (nsnull != mWindowListener) {
00400     return NS_ERROR_FAILURE;
00401   }
00402 
00403   mWindowListener = aWindowListener;
00404   if (mDocIsLoaded && nsnull != mWindowListener) {
00405     mWindowListener->Initialize(this);
00406   }
00407   return NS_OK;
00408 }
00409 
00410 //-----------------------------------------------------
00411 // Get the HTML Document
00412 NS_IMETHODIMP nsXPBaseWindow::GetDocument(nsIDOMHTMLDocument *& aDocument)
00413 {
00414   nsIDOMHTMLDocument *htmlDoc = nsnull;
00415   nsIPresShell *shell = nsnull;
00416   GetPresShell(shell);
00417   if (nsnull != shell) {
00418     nsIDocument *doc = shell->GetDocument();
00419     if (doc) {
00420       doc->QueryInterface(kIDOMHTMLDocumentIID,(void **)&htmlDoc);
00421     }
00422     NS_RELEASE(shell);
00423   }
00424 
00425   aDocument = htmlDoc;
00426   return NS_OK;
00427 }
00428 
00429 
00430 //----------------------------------------------------------------------
00431 NS_IMETHODIMP nsXPBaseWindow::GetPresShell(nsIPresShell*& aPresShell)
00432 {
00433   aPresShell = nsnull;
00434 
00435   if (mDocShell) {
00436     nsIContentViewer* cv = nsnull;
00437     mDocShell->GetContentViewer(&cv);
00438     if (nsnull != cv) {
00439       nsIDocumentViewer* docv = nsnull;
00440       cv->QueryInterface(kIDocumentViewerIID, (void**) &docv);
00441       if (nsnull != docv) {
00442         nsCOMPtr<nsPresContext> cx;
00443         docv->GetPresContext(getter_AddRefs(cx));
00444         if (nsnull != cx) {
00445           NS_IF_ADDREF(aPresShell = cx->GetPresShell());
00446         }
00447         NS_RELEASE(docv);
00448       }
00449       NS_RELEASE(cv);
00450     }
00451   }
00452   return NS_OK;
00453 }
00454 
00455 //-----------------------------------------------------------------
00456 //-- nsIDOMMouseListener
00457 //-----------------------------------------------------------------
00458 
00459 //-----------------------------------------------------------------
00460 nsresult nsXPBaseWindow::HandleEvent(nsIDOMEvent* aEvent)
00461 {
00462   return NS_OK;
00463 }
00464 
00465 //-----------------------------------------------------------------
00466 nsresult nsXPBaseWindow::MouseUp(nsIDOMEvent* aMouseEvent)
00467 {
00468   return NS_OK;
00469 }
00470 
00471 //-----------------------------------------------------------------
00472 nsresult nsXPBaseWindow::MouseDown(nsIDOMEvent* aMouseEvent)
00473 {
00474   return NS_OK;
00475 }
00476 
00477 //-----------------------------------------------------------------
00478 nsresult nsXPBaseWindow::MouseClick(nsIDOMEvent* aMouseEvent)
00479 {
00480   if (nsnull != mWindowListener) {
00481     PRBool status;
00482     mWindowListener->MouseClick(aMouseEvent, this, status);
00483   }
00484   return NS_OK;
00485 }
00486 
00487 //-----------------------------------------------------------------
00488 nsresult nsXPBaseWindow::MouseDblClick(nsIDOMEvent* aMouseEvent)
00489 {
00490   return NS_OK;
00491 }
00492 
00493 //-----------------------------------------------------------------
00494 nsresult nsXPBaseWindow::MouseOver(nsIDOMEvent* aMouseEvent)
00495 {
00496   return NS_OK;
00497 }
00498 
00499 //-----------------------------------------------------------------
00500 nsresult nsXPBaseWindow::MouseOut(nsIDOMEvent* aMouseEvent)
00501 {
00502   return NS_OK;
00503 }
00504 
00505 //----------------------------------------------------------------------
00506 // Factory code for creating nsXPBaseWindow's
00507 //----------------------------------------------------------------------
00508 class nsXPBaseWindowFactory : public nsIFactory
00509 {
00510 public:
00511   NS_DECL_ISUPPORTS
00512   NS_DECL_NSIFACTORY
00513 
00514   nsXPBaseWindowFactory();
00515   virtual ~nsXPBaseWindowFactory();
00516 };
00517 
00518 //----------------------------------------------------------------------
00519 nsXPBaseWindowFactory::nsXPBaseWindowFactory()
00520 {
00521 }
00522 
00523 //----------------------------------------------------------------------
00524 nsXPBaseWindowFactory::~nsXPBaseWindowFactory()
00525 {
00526 }
00527 
00528 //----------------------------------------------------------------------
00529 nsresult
00530 nsXPBaseWindowFactory::QueryInterface(const nsIID &aIID, void **aResult)
00531 {
00532   if (aResult == NULL) {
00533     return NS_ERROR_NULL_POINTER;
00534   }
00535 
00536   // Always NULL result, in case of failure
00537   *aResult = NULL;
00538 
00539   if (aIID.Equals(kISupportsIID)) {
00540     *aResult = (void *)(nsISupports*)this;
00541   } else if (aIID.Equals(kIFactoryIID)) {
00542     *aResult = (void *)(nsIFactory*)this;
00543   }
00544 
00545   if (*aResult == NULL) {
00546     return NS_NOINTERFACE;
00547   }
00548 
00549   NS_ADDREF_THIS(); // Increase reference count for caller
00550   return NS_OK;
00551 }
00552 
00553 NS_IMPL_ADDREF(nsXPBaseWindowFactory)
00554 NS_IMPL_RELEASE(nsXPBaseWindowFactory)
00555 
00556 //----------------------------------------------------------------------
00557 nsresult
00558 nsXPBaseWindowFactory::CreateInstance(nsISupports *aOuter,
00559                                        const nsIID &aIID,
00560                                        void **aResult)
00561 {
00562   nsresult rv;
00563   nsXPBaseWindow *inst;
00564 
00565   if (aResult == NULL) {
00566     return NS_ERROR_NULL_POINTER;
00567   }
00568   *aResult = NULL;
00569   if (nsnull != aOuter) {
00570     rv = NS_ERROR_NO_AGGREGATION;
00571     goto done;
00572   }
00573 
00574   NS_NEWXPCOM(inst, nsXPBaseWindow);
00575   if (inst == NULL) {
00576     rv = NS_ERROR_OUT_OF_MEMORY;
00577     goto done;
00578   }
00579 
00580   NS_ADDREF(inst);
00581   rv = inst->QueryInterface(aIID, aResult);
00582   NS_RELEASE(inst);
00583 
00584 done:
00585   return rv;
00586 }
00587 
00588 //----------------------------------------------------------------------
00589 nsresult
00590 nsXPBaseWindowFactory::LockFactory(PRBool aLock)
00591 {
00592   // Not implemented in simplest case.
00593   return NS_OK;
00594 }
00595 
00596 //----------------------------------------------------------------------
00597 nsresult
00598 NS_NewXPBaseWindowFactory(nsIFactory** aFactory)
00599 {
00600   nsresult rv = NS_OK;
00601   nsXPBaseWindowFactory* inst;
00602   NS_NEWXPCOM(inst, nsXPBaseWindowFactory);
00603   if (nsnull == inst) {
00604     rv = NS_ERROR_OUT_OF_MEMORY;
00605   }
00606   else {
00607     NS_ADDREF(inst);
00608   }
00609   *aFactory = inst;
00610   return rv;
00611 }