Back to index

lightning-sunbird  0.9+nobinonly
EmbedWindow.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  *  Zack Rusin <zack@kde.org>.
00020  * Portions created by the Initial Developer are Copyright (C) 2004
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Lars Knoll <knoll@kde.org>
00025  *   Zack Rusin <zack@kde.org>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 #include "EmbedWindow.h"
00041 
00042 #include "qgeckoembed.h"
00043 
00044 #include <nsCWebBrowser.h>
00045 #include <nsIComponentManager.h>
00046 #include <nsIDocShellTreeItem.h>
00047 #include "nsIWidget.h"
00048 #include "nsIWebNavigation.h"
00049 #include "nsReadableUtils.h"
00050 #include "nsIDOMNode.h"
00051 #include "nsIDOMElement.h"
00052 #include "nsIDOMEvent.h"
00053 
00054 #include <qapplication.h>
00055 #include <qeventloop.h>
00056 #include <qvbox.h>
00057 #include <qwidget.h>
00058 #include <qtooltip.h>
00059 #include <qcursor.h>
00060 #include <qlabel.h>
00061 
00062 class MozTipLabel : public QLabel
00063 {
00064 public:
00065     MozTipLabel( QWidget* parent)
00066         : QLabel( parent, "toolTipTip",
00067                   Qt::WStyle_StaysOnTop | Qt::WStyle_Customize | Qt::WStyle_NoBorder
00068                   | Qt::WStyle_Tool | Qt::WX11BypassWM )
00069     {
00070         setMargin(1);
00071         setAutoMask( FALSE );
00072         setFrameStyle( QFrame::Plain | QFrame::Box );
00073         setLineWidth( 1 );
00074         setAlignment( AlignAuto | AlignTop );
00075         setIndent(0);
00076         polish();
00077         adjustSize();
00078         setFont(QToolTip::font());
00079         setPalette(QToolTip::palette());
00080     }
00081 };
00082 
00083 
00084 EmbedWindow::EmbedWindow()
00085     : mOwner(nsnull),
00086       mVisibility(PR_FALSE),
00087       mIsModal(PR_FALSE),
00088       tooltip(0)
00089 {
00090 }
00091 
00092 EmbedWindow::~EmbedWindow(void)
00093 {
00094     ExitModalEventLoop(PR_FALSE);
00095     if (tooltip)
00096         delete tooltip;
00097 }
00098 
00099 void
00100 EmbedWindow::Init(QGeckoEmbed *aOwner)
00101 {
00102     // save our owner for later
00103     mOwner = aOwner;
00104 
00105     // create our nsIWebBrowser object and set up some basic defaults.
00106     mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
00107     if (!mWebBrowser) {
00108         //log an error
00109         return;
00110     }
00111 
00112     mWebBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *, this));
00113 
00114     nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(mWebBrowser);
00115     item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
00116 
00117 }
00118 
00119 nsresult
00120 EmbedWindow::CreateWindow(void)
00121 {
00122     nsresult rv;
00123 
00124     // Get the base window interface for the web browser object and
00125     // create the window.
00126     mBaseWindow = do_QueryInterface(mWebBrowser);
00127     rv = mBaseWindow->InitWindow(mOwner,
00128                                  nsnull,
00129                                  0, 0,
00130                                  mOwner->width(),
00131                                  mOwner->height());
00132     if (NS_FAILED(rv))
00133         return rv;
00134 
00135     rv = mBaseWindow->Create();
00136     if (NS_FAILED(rv))
00137         return rv;
00138 
00139     return NS_OK;
00140 }
00141 
00142 void
00143 EmbedWindow::ReleaseChildren(void)
00144 {
00145     ExitModalEventLoop(PR_FALSE);
00146 
00147     mBaseWindow->Destroy();
00148     mBaseWindow = 0;
00149     mWebBrowser = 0;
00150 }
00151 
00152 // nsISupports
00153 
00154 NS_IMPL_ADDREF(EmbedWindow)
00155     NS_IMPL_RELEASE(EmbedWindow)
00156 
00157     NS_INTERFACE_MAP_BEGIN(EmbedWindow)
00158     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
00159     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
00160     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
00161     NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
00162     NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
00163     NS_INTERFACE_MAP_ENTRY(nsIContextMenuListener)
00164     NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
00165     NS_INTERFACE_MAP_END
00166 
00167 // nsIWebBrowserChrome
00168 
00169 NS_IMETHODIMP
00170 EmbedWindow::SetStatus(PRUint32 aStatusType, const PRUnichar *aStatus)
00171 {
00172     switch (aStatusType) {
00173     case STATUS_SCRIPT:
00174     {
00175         mOwner->emitScriptStatus(QString::fromUcs2(aStatus));
00176     }
00177     break;
00178     case STATUS_SCRIPT_DEFAULT:
00179         // Gee, that's nice.
00180         break;
00181     case STATUS_LINK:
00182     {
00183         mLinkMessage = aStatus;
00184         mOwner->emitLinkStatus(QString::fromUcs2(aStatus));
00185     }
00186     break;
00187     }
00188     return NS_OK;
00189 }
00190 
00191 NS_IMETHODIMP
00192 EmbedWindow::GetWebBrowser(nsIWebBrowser **aWebBrowser)
00193 {
00194     *aWebBrowser = mWebBrowser;
00195     NS_IF_ADDREF(*aWebBrowser);
00196     return NS_OK;
00197 }
00198 
00199 NS_IMETHODIMP
00200 EmbedWindow::SetWebBrowser(nsIWebBrowser *aWebBrowser)
00201 {
00202     mWebBrowser = aWebBrowser;
00203     return NS_OK;
00204 }
00205 
00206 NS_IMETHODIMP
00207 EmbedWindow::GetChromeFlags(PRUint32 *aChromeFlags)
00208 {
00209     *aChromeFlags = mOwner->chromeMask();
00210     return NS_OK;
00211 }
00212 
00213 NS_IMETHODIMP
00214 EmbedWindow::SetChromeFlags(PRUint32 aChromeFlags)
00215 {
00216     mOwner->setChromeMask(aChromeFlags);
00217     return NS_OK;
00218 }
00219 
00220 NS_IMETHODIMP
00221 EmbedWindow::DestroyBrowserWindow(void)
00222 {
00223     emit mOwner->destroyBrowser();
00224 
00225     return NS_OK;
00226 }
00227 
00228 NS_IMETHODIMP
00229 EmbedWindow::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
00230 {
00231     emit mOwner->sizeTo(aCX, aCY);
00232     return NS_OK;
00233 }
00234 
00235 NS_IMETHODIMP
00236 EmbedWindow::ShowAsModal(void)
00237 {
00238     qDebug("setting modal");
00239     mIsModal = PR_TRUE;
00240     qApp->eventLoop()->enterLoop();
00241     return NS_OK;
00242 }
00243 
00244 NS_IMETHODIMP
00245 EmbedWindow::IsWindowModal(PRBool *_retval)
00246 {
00247     *_retval = mIsModal;
00248     return NS_OK;
00249 }
00250 
00251 NS_IMETHODIMP
00252 EmbedWindow::ExitModalEventLoop(nsresult aStatus)
00253 {
00254     qDebug("exiting modal");
00255     qApp->eventLoop()->exitLoop();
00256     return NS_OK;
00257 }
00258 
00259 // nsIWebBrowserChromeFocus
00260 
00261 NS_IMETHODIMP
00262 EmbedWindow::FocusNextElement()
00263 {
00264     //FIXME:
00265     //i think gecko handles that internally
00266     //mOwner->focusNextPrevChild(TRUE);
00267     return NS_OK;
00268 }
00269 
00270 NS_IMETHODIMP
00271 EmbedWindow::FocusPrevElement()
00272 {
00273     //FIXME: same story as above
00274     //mOwner->focusNextPrevChild(FALSE);
00275     return NS_OK;
00276 }
00277 
00278 // nsIEmbeddingSiteWindow
00279 
00280 NS_IMETHODIMP
00281 EmbedWindow::SetDimensions(PRUint32 aFlags, PRInt32 aX, PRInt32 aY,
00282                            PRInt32 aCX, PRInt32 aCY)
00283 {
00284     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
00285         (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
00286                    nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
00287         return mBaseWindow->SetPositionAndSize(aX, aY, aCX, aCY, PR_TRUE);
00288     }
00289     else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
00290         return mBaseWindow->SetPosition(aX, aY);
00291     }
00292     else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
00293                        nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
00294         return mBaseWindow->SetSize(aCX, aCY, PR_TRUE);
00295     }
00296     return NS_ERROR_INVALID_ARG;
00297 }
00298 
00299 NS_IMETHODIMP
00300 EmbedWindow::GetDimensions(PRUint32 aFlags, PRInt32 *aX,
00301                            PRInt32 *aY, PRInt32 *aCX, PRInt32 *aCY)
00302 {
00303     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
00304         (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
00305                    nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
00306         return mBaseWindow->GetPositionAndSize(aX, aY, aCX, aCY);
00307     }
00308     else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
00309         return mBaseWindow->GetPosition(aX, aY);
00310     }
00311     else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
00312                        nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
00313         return mBaseWindow->GetSize(aCX, aCY);
00314     }
00315     return NS_ERROR_INVALID_ARG;
00316 }
00317 
00318 NS_IMETHODIMP
00319 EmbedWindow::SetFocus(void)
00320 {
00321     // XXX might have to do more here.
00322     return mBaseWindow->SetFocus();
00323 }
00324 
00325 NS_IMETHODIMP
00326 EmbedWindow::GetTitle(PRUnichar **aTitle)
00327 {
00328     *aTitle = ToNewUnicode(mTitle);
00329     return NS_OK;
00330 }
00331 
00332 NS_IMETHODIMP
00333 EmbedWindow::SetTitle(const PRUnichar *aTitle)
00334 {
00335     mTitle = aTitle;
00336     emit mOwner->windowTitleChanged(QString::fromUcs2(aTitle));
00337     return NS_OK;
00338 }
00339 
00340 NS_IMETHODIMP
00341 EmbedWindow::GetSiteWindow(void **aSiteWindow)
00342 {
00343     *aSiteWindow = NS_STATIC_CAST(void *, mOwner);
00344     return NS_OK;
00345 }
00346 
00347 NS_IMETHODIMP
00348 EmbedWindow::GetVisibility(PRBool *aVisibility)
00349 {
00350     *aVisibility = mVisibility;
00351     return NS_OK;
00352 }
00353 
00354 NS_IMETHODIMP
00355 EmbedWindow::SetVisibility(PRBool aVisibility)
00356 {
00357     // We always set the visibility so that if it's chrome and we finish
00358     // the load we know that we have to show the window.
00359     mVisibility = aVisibility;
00360 
00361     // if this is a chrome window and the chrome hasn't finished loading
00362     // yet then don't show the window yet.
00363     if (mOwner->isChrome() && !mOwner->chromeLoaded())
00364         return NS_OK;
00365 
00366     emit mOwner->visibilityChanged(aVisibility);
00367 
00368     return NS_OK;
00369 }
00370 
00371 // nsITooltipListener
00372 
00373 NS_IMETHODIMP
00374 EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText)
00375 {
00376     QString tipText = QString::fromUcs2(aTipText);
00377 
00378     // get the root origin for this content window
00379     nsCOMPtr<nsIWidget> mainWidget;
00380     mBaseWindow->GetMainWidget(getter_AddRefs(mainWidget));
00381     QWidget *window;
00382     window = NS_STATIC_CAST(QWidget*, mainWidget->GetNativeData(NS_NATIVE_WINDOW));
00383 
00384     if (!window) {
00385         NS_ERROR("no qt window in hierarchy!\n");
00386         return NS_ERROR_FAILURE;
00387     }
00388 
00389     int screen = qApp->desktop()->screenNumber(window);
00390     if (!tooltip || qApp->desktop()->screenNumber(tooltip) != screen) {
00391         delete tooltip;
00392         QWidget *s = QApplication::desktop()->screen(screen);
00393         tooltip = new MozTipLabel(s);
00394     }
00395 
00396     tooltip->setText(tipText);
00397     tooltip->resize(tooltip->sizeHint());
00398     QPoint pos(aXCoords, aYCoords+24);
00399     pos = window->mapToGlobal(pos);
00400     tooltip->move(pos);
00401     tooltip->show();
00402 
00403     return NS_OK;
00404 }
00405 
00406 NS_IMETHODIMP
00407 EmbedWindow::OnHideTooltip(void)
00408 {
00409     if (tooltip)
00410         tooltip->hide();
00411     return NS_OK;
00412 }
00413 
00414 
00415 NS_IMETHODIMP
00416 EmbedWindow::OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
00417 {
00418 //     if (!aEvent->type == NS_CONTEXTMENU)
00419 //         return NS_OK;
00420     qDebug("EmbedWindow::OnShowContextMenu");
00421 
00422     QString url = mOwner->url();
00423 
00424     PRUint16 nodeType;
00425     aNode->GetNodeType(&nodeType);
00426     if (nodeType == nsIDOMNode::ELEMENT_NODE) {
00427         nsIDOMElement *element = static_cast<nsIDOMElement *>(aNode);
00428         nsString tagname;
00429         element->GetTagName(tagname);
00430         nsCString ctagname;
00431         LossyCopyUTF16toASCII(tagname, ctagname);
00432         if (!strcasecmp(ctagname.get(), "a")) {
00433             nsString href;
00434             nsString attr;
00435             attr.AssignLiteral("href");
00436             element->GetAttribute(attr, href);
00437             url = mOwner->resolvedUrl(QString::fromUcs2(href.get()));
00438         } else if (!strcasecmp(ctagname.get(), "img")) {
00439             nsString href;
00440             nsString attr;
00441             attr.AssignLiteral("src");
00442             element->GetAttribute(attr, href);
00443             url = mOwner->resolvedUrl(QString::fromUcs2(href.get()));
00444         }
00445     }
00446 
00447     emit mOwner->showContextMenu(QCursor::pos(), url);
00448     return NS_OK;
00449 }
00450 
00451 // nsIInterfaceRequestor
00452 
00453 NS_IMETHODIMP
00454 EmbedWindow::GetInterface(const nsIID &aIID, void** aInstancePtr)
00455 {
00456     nsresult rv;
00457 
00458     rv = QueryInterface(aIID, aInstancePtr);
00459 
00460     // pass it up to the web browser object
00461     if (NS_FAILED(rv) || !*aInstancePtr) {
00462         nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(mWebBrowser);
00463         return ir->GetInterface(aIID, aInstancePtr);
00464     }
00465 
00466     return rv;
00467 }