1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is the Mozilla browser.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications, Inc.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
24 * Travis Bogard <travis@netscape.com>
25 * Adam Lock <adamlock@netscape.com>
26 * Mike Pinkerton <pinkerton@netscape.com>
27 * Dan Rosen <dr@netscape.com>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either the GNU General Public License Version 2 or later (the "GPL"), or
31 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
44 #include "nsDocShellTreeOwner.h"
45 #include "nsWebBrowser.h"
48 #include "nsIGenericFactory.h"
49 #include "nsStyleCoord.h"
51 #include "nsHTMLReflowState.h"
52 #include "nsIServiceManager.h"
53 #include "nsComponentManagerUtils.h"
54 #include "nsXPIDLString.h"
56 #include "nsReadableUtils.h"
57 #include "nsUnicharUtils.h"
58 #include "nsISimpleEnumerator.h"
60 // Interfaces needed to be included
61 #include "nsPresContext.h"
62 #include "nsIContextMenuListener.h"
63 #include "nsIContextMenuListener2.h"
64 #include "nsITooltipListener.h"
65 #include "nsIPrivateDOMEvent.h"
66 #include "nsIDOMNode.h"
67 #include "nsIDOMNodeList.h"
68 #include "nsIDOMDocument.h"
69 #include "nsIDOMDocumentType.h"
70 #include "nsIDOMElement.h"
71 #include "nsIDOMEvent.h"
72 #include "nsIDOMMouseEvent.h"
73 #include "nsIDOMNSUIEvent.h"
74 #include "nsIDOMEventTarget.h"
75 #include "nsIDOMNamedNodeMap.h"
76 #include "nsIDOMHTMLInputElement.h"
77 #include "nsIDOMHTMLTextAreaElement.h"
78 #include "nsIDOMHTMLHtmlElement.h"
79 #include "nsIDOMHTMLAppletElement.h"
80 #include "nsIDOMHTMLObjectElement.h"
81 #include "nsIDOMHTMLEmbedElement.h"
82 #include "nsIDOMHTMLDocument.h"
83 #include "nsIImageLoadingContent.h"
84 #include "nsIWebNavigation.h"
85 #include "nsIDOMHTMLElement.h"
86 #include "nsIPresShell.h"
87 #include "nsPIDOMWindow.h"
88 #include "nsIDOMWindowCollection.h"
89 #include "nsIFocusController.h"
90 #include "nsIWindowWatcher.h"
91 #include "nsPIWindowWatcher.h"
92 #include "nsIPrompt.h"
94 #include "nsIWebBrowserChromeFocus.h"
95 #include "nsIContent.h"
96 #include "imgIContainer.h"
97 #include "nsContextMenuInfo.h"
98 #include "nsPresContext.h"
99 #include "nsIViewManager.h"
101 #include "nsPIDOMEventTarget.h"
106 // A helper routine that navigates the tricky path from a |nsWebBrowser| to
107 // a |nsPIDOMEventTarget| via the window root and chrome event handler.
110 GetPIDOMEventTarget( nsWebBrowser
* inBrowser
, nsPIDOMEventTarget
** aTarget
)
112 nsCOMPtr
<nsIDOMWindow
> domWindow
;
113 inBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
114 NS_ENSURE_TRUE(domWindow
, NS_ERROR_FAILURE
);
116 nsCOMPtr
<nsPIDOMWindow
> domWindowPrivate
= do_QueryInterface(domWindow
);
117 NS_ENSURE_TRUE(domWindowPrivate
, NS_ERROR_FAILURE
);
118 nsPIDOMWindow
*rootWindow
= domWindowPrivate
->GetPrivateRoot();
119 NS_ENSURE_TRUE(rootWindow
, NS_ERROR_FAILURE
);
120 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
=
121 do_QueryInterface(rootWindow
->GetChromeEventHandler());
122 NS_ENSURE_TRUE(piTarget
, NS_ERROR_FAILURE
);
124 NS_IF_ADDREF(*aTarget
);
130 //*****************************************************************************
131 //*** nsDocShellTreeOwner: Object Management
132 //*****************************************************************************
134 nsDocShellTreeOwner::nsDocShellTreeOwner() :
137 mPrimaryContentShell(nsnull
),
138 mWebBrowserChrome(nsnull
),
140 mOwnerRequestor(nsnull
),
141 mChromeTooltipListener(nsnull
),
142 mChromeContextMenuListener(nsnull
)
146 nsDocShellTreeOwner::~nsDocShellTreeOwner()
148 RemoveChromeListeners();
151 //*****************************************************************************
152 // nsDocShellTreeOwner::nsISupports
153 //*****************************************************************************
155 NS_IMPL_ADDREF(nsDocShellTreeOwner
)
156 NS_IMPL_RELEASE(nsDocShellTreeOwner
)
158 NS_INTERFACE_MAP_BEGIN(nsDocShellTreeOwner
)
159 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDocShellTreeOwner
)
160 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner
)
161 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow
)
162 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
163 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener
)
164 NS_INTERFACE_MAP_ENTRY(nsICDocShellTreeOwner
)
165 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
168 //*****************************************************************************
169 // nsDocShellTreeOwner::nsIInterfaceRequestor
170 //*****************************************************************************
173 nsDocShellTreeOwner::GetInterface(const nsIID
& aIID
, void** aSink
)
175 NS_ENSURE_ARG_POINTER(aSink
);
177 if(NS_SUCCEEDED(QueryInterface(aIID
, aSink
)))
180 if (aIID
.Equals(NS_GET_IID(nsIWebBrowserChromeFocus
))) {
181 if (mWebBrowserChromeWeak
!= nsnull
)
182 return mWebBrowserChromeWeak
->QueryReferent(aIID
, aSink
);
183 return mOwnerWin
->QueryInterface(aIID
, aSink
);
186 if (aIID
.Equals(NS_GET_IID(nsIPrompt
))) {
195 return NS_NOINTERFACE
;
198 if (aIID
.Equals(NS_GET_IID(nsIAuthPrompt
))) {
199 nsIAuthPrompt
*prompt
;
200 EnsureAuthPrompter();
201 prompt
= mAuthPrompter
;
207 return NS_NOINTERFACE
;
210 nsCOMPtr
<nsIInterfaceRequestor
> req
= GetOwnerRequestor();
212 return req
->GetInterface(aIID
, aSink
);
214 return NS_NOINTERFACE
;
217 //*****************************************************************************
218 // nsDocShellTreeOwner::nsIDocShellTreeOwner
219 //*****************************************************************************
222 nsDocShellTreeOwner::FindItemWithName(const PRUnichar
* aName
,
223 nsIDocShellTreeItem
* aRequestor
,
224 nsIDocShellTreeItem
* aOriginalRequestor
,
225 nsIDocShellTreeItem
** aFoundItem
)
227 NS_ENSURE_ARG(aName
);
228 NS_ENSURE_ARG_POINTER(aFoundItem
);
229 *aFoundItem
= nsnull
; // if we don't find one, we return NS_OK and a null result
232 nsAutoString
name(aName
);
235 return NS_OK
; // stymied
240 if(name
.LowerCaseEqualsLiteral("_blank"))
242 // _main is an IE target which should be case-insensitive but isn't
243 // see bug 217886 for details
244 if(name
.LowerCaseEqualsLiteral("_content") || name
.EqualsLiteral("_main")) {
245 *aFoundItem
= mWebBrowser
->mDocShellAsItem
;
246 NS_IF_ADDREF(*aFoundItem
);
252 nsCOMPtr
<nsIDOMWindow
> domWindow
;
253 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
255 nsAutoString ourName
;
256 domWindow
->GetName(ourName
);
257 if (name
.Equals(ourName
, nsCaseInsensitiveStringComparator())) {
258 *aFoundItem
= mWebBrowser
->mDocShellAsItem
;
259 NS_IF_ADDREF(*aFoundItem
);
265 // next, check our children
266 rv
= FindChildWithName(aName
, PR_TRUE
, aRequestor
, aOriginalRequestor
,
268 if(NS_FAILED(rv
) || *aFoundItem
)
271 // next, if we have a parent and it isn't the requestor, ask it
272 nsCOMPtr
<nsIDocShellTreeOwner
> reqAsTreeOwner(do_QueryInterface(aRequestor
));
275 if (mTreeOwner
!= reqAsTreeOwner
)
276 return mTreeOwner
->FindItemWithName(aName
, mWebBrowser
->mDocShellAsItem
,
277 aOriginalRequestor
, aFoundItem
);
281 // finally, failing everything else, search all windows
282 return FindItemWithNameAcrossWindows(aName
, aRequestor
, aOriginalRequestor
,
287 nsDocShellTreeOwner::FindChildWithName(const PRUnichar
*aName
, PRBool aRecurse
,
288 nsIDocShellTreeItem
* aRequestor
,
289 nsIDocShellTreeItem
* aOriginalRequestor
,
290 nsIDocShellTreeItem
**aFoundItem
)
297 nsCOMPtr
<nsIDOMWindow
> domWindow
;
298 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
302 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
303 domWindow
->GetFrames(getter_AddRefs(frames
));
308 frames
->GetLength(&count
);
309 for (ctr
= 0; ctr
< count
; ctr
++) {
310 nsCOMPtr
<nsIDOMWindow
> frame
;
311 frames
->Item(ctr
, getter_AddRefs(frame
));
312 nsCOMPtr
<nsPIDOMWindow
> w(do_QueryInterface(frame
));
314 nsCOMPtr
<nsIDocShellTreeItem
> item
= do_QueryInterface(w
->GetDocShell());
315 if (item
&& item
!= aRequestor
) {
316 rv
= item
->FindItemWithName(aName
, mWebBrowser
->mDocShellAsItem
,
317 aOriginalRequestor
, aFoundItem
);
318 if (NS_FAILED(rv
) || *aFoundItem
)
328 nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar
* aName
,
329 nsIDocShellTreeItem
* aRequestor
,
330 nsIDocShellTreeItem
* aOriginalRequestor
,
331 nsIDocShellTreeItem
** aFoundItem
)
333 // search for the item across the list of top-level windows
334 nsCOMPtr
<nsPIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
338 return wwatch
->FindItemWithName(aName
, aRequestor
, aOriginalRequestor
,
343 nsDocShellTreeOwner::EnsurePrompter()
348 nsCOMPtr
<nsIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
349 if (wwatch
&& mWebBrowser
) {
350 nsCOMPtr
<nsIDOMWindow
> domWindow
;
351 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
353 wwatch
->GetNewPrompter(domWindow
, getter_AddRefs(mPrompter
));
358 nsDocShellTreeOwner::EnsureAuthPrompter()
363 nsCOMPtr
<nsIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
364 if (wwatch
&& mWebBrowser
) {
365 nsCOMPtr
<nsIDOMWindow
> domWindow
;
366 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
368 wwatch
->GetNewAuthPrompter(domWindow
, getter_AddRefs(mAuthPrompter
));
373 nsDocShellTreeOwner::AddToWatcher()
376 nsCOMPtr
<nsIDOMWindow
> domWindow
;
377 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
379 nsCOMPtr
<nsPIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
381 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= GetWebBrowserChrome();
382 if (webBrowserChrome
)
383 wwatch
->AddWindow(domWindow
, webBrowserChrome
);
390 nsDocShellTreeOwner::RemoveFromWatcher()
393 nsCOMPtr
<nsIDOMWindow
> domWindow
;
394 mWebBrowser
->GetContentDOMWindow(getter_AddRefs(domWindow
));
396 nsCOMPtr
<nsPIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
398 wwatch
->RemoveWindow(domWindow
);
405 nsDocShellTreeOwner::ContentShellAdded(nsIDocShellTreeItem
* aContentShell
,
406 PRBool aPrimary
, PRBool aTargetable
,
407 const nsAString
& aID
)
410 return mTreeOwner
->ContentShellAdded(aContentShell
, aPrimary
,
414 mPrimaryContentShell
= aContentShell
;
419 nsDocShellTreeOwner::ContentShellRemoved(nsIDocShellTreeItem
* aContentShell
)
422 return mTreeOwner
->ContentShellRemoved(aContentShell
);
424 if(mPrimaryContentShell
== aContentShell
)
425 mPrimaryContentShell
= nsnull
;
431 nsDocShellTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem
** aShell
)
433 NS_ENSURE_ARG_POINTER(aShell
);
436 return mTreeOwner
->GetPrimaryContentShell(aShell
);
438 *aShell
= (mPrimaryContentShell
? mPrimaryContentShell
: mWebBrowser
->mDocShellAsItem
.get());
439 NS_IF_ADDREF(*aShell
);
445 nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem
* aShellItem
,
446 PRInt32 aCX
, PRInt32 aCY
)
448 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= GetWebBrowserChrome();
450 NS_ENSURE_STATE(mTreeOwner
|| webBrowserChrome
);
453 return mTreeOwner
->SizeShellTo(aShellItem
, aCX
, aCY
);
455 if(aShellItem
== mWebBrowser
->mDocShellAsItem
)
456 return webBrowserChrome
->SizeBrowserTo(aCX
, aCY
);
458 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(aShellItem
));
459 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
461 nsCOMPtr
<nsIDOMDocument
> domDocument
;
462 webNav
->GetDocument(getter_AddRefs(domDocument
));
463 NS_ENSURE_TRUE(domDocument
, NS_ERROR_FAILURE
);
465 nsCOMPtr
<nsIDOMElement
> domElement
;
466 domDocument
->GetDocumentElement(getter_AddRefs(domElement
));
467 NS_ENSURE_TRUE(domElement
, NS_ERROR_FAILURE
);
469 // Set the preferred Size
471 NS_ERROR("Implement this");
473 Set the preferred size on the aShellItem.
476 nsCOMPtr
<nsPresContext
> presContext
;
477 mWebBrowser
->mDocShell
->GetPresContext(getter_AddRefs(presContext
));
478 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
480 nsIPresShell
*presShell
= presContext
->GetPresShell();
481 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
483 NS_ENSURE_SUCCESS(presShell
->ResizeReflow(NS_UNCONSTRAINEDSIZE
,
484 NS_UNCONSTRAINEDSIZE
), NS_ERROR_FAILURE
);
486 nsRect shellArea
= presContext
->GetVisibleArea();
488 PRInt32 browserCX
= presContext
->AppUnitsToDevPixels(shellArea
.width
);
489 PRInt32 browserCY
= presContext
->AppUnitsToDevPixels(shellArea
.height
);
491 return webBrowserChrome
->SizeBrowserTo(browserCX
, browserCY
);
495 nsDocShellTreeOwner::SetPersistence(PRBool aPersistPosition
,
497 PRBool aPersistSizeMode
)
499 return NS_ERROR_NOT_IMPLEMENTED
;
503 nsDocShellTreeOwner::GetPersistence(PRBool
* aPersistPosition
,
504 PRBool
* aPersistSize
,
505 PRBool
* aPersistSizeMode
)
507 return NS_ERROR_NOT_IMPLEMENTED
;
510 //*****************************************************************************
511 // nsDocShellTreeOwner::nsIBaseWindow
512 //*****************************************************************************
516 nsDocShellTreeOwner::InitWindow(nativeWindow aParentNativeWindow
,
517 nsIWidget
* aParentWidget
, PRInt32 aX
,
518 PRInt32 aY
, PRInt32 aCX
, PRInt32 aCY
)
520 return NS_ERROR_NULL_POINTER
;
524 nsDocShellTreeOwner::Create()
526 return NS_ERROR_NULL_POINTER
;
530 nsDocShellTreeOwner::Destroy()
532 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= GetWebBrowserChrome();
533 if (webBrowserChrome
)
535 return webBrowserChrome
->DestroyBrowserWindow();
538 return NS_ERROR_NULL_POINTER
;
542 nsDocShellTreeOwner::SetPosition(PRInt32 aX
, PRInt32 aY
)
544 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
547 return ownerWin
->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
,
550 return NS_ERROR_NULL_POINTER
;
554 nsDocShellTreeOwner::GetPosition(PRInt32
* aX
, PRInt32
* aY
)
556 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
559 return ownerWin
->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
,
560 aX
, aY
, nsnull
, nsnull
);
562 return NS_ERROR_NULL_POINTER
;
566 nsDocShellTreeOwner::SetSize(PRInt32 aCX
, PRInt32 aCY
, PRBool aRepaint
)
568 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
571 return ownerWin
->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
,
574 return NS_ERROR_NULL_POINTER
;
578 nsDocShellTreeOwner::GetSize(PRInt32
* aCX
, PRInt32
* aCY
)
580 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
583 return ownerWin
->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
,
584 nsnull
, nsnull
, aCX
, aCY
);
586 return NS_ERROR_NULL_POINTER
;
590 nsDocShellTreeOwner::SetPositionAndSize(PRInt32 aX
, PRInt32 aY
, PRInt32 aCX
,
591 PRInt32 aCY
, PRBool aRepaint
)
593 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
596 return ownerWin
->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
|
597 nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
,
600 return NS_ERROR_NULL_POINTER
;
604 nsDocShellTreeOwner::GetPositionAndSize(PRInt32
* aX
, PRInt32
* aY
, PRInt32
* aCX
,
607 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
610 return ownerWin
->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER
|
611 nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION
,
614 return NS_ERROR_NULL_POINTER
;
618 nsDocShellTreeOwner::Repaint(PRBool aForce
)
620 return NS_ERROR_NULL_POINTER
;
624 nsDocShellTreeOwner::GetParentWidget(nsIWidget
** aParentWidget
)
626 return NS_ERROR_NULL_POINTER
;
630 nsDocShellTreeOwner::SetParentWidget(nsIWidget
* aParentWidget
)
632 return NS_ERROR_NULL_POINTER
;
636 nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow
* aParentNativeWindow
)
638 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
641 return ownerWin
->GetSiteWindow(aParentNativeWindow
);
643 return NS_ERROR_NULL_POINTER
;
647 nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow
)
649 return NS_ERROR_NULL_POINTER
;
653 nsDocShellTreeOwner::GetVisibility(PRBool
* aVisibility
)
655 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
658 return ownerWin
->GetVisibility(aVisibility
);
660 return NS_ERROR_NULL_POINTER
;
664 nsDocShellTreeOwner::SetVisibility(PRBool aVisibility
)
666 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
669 return ownerWin
->SetVisibility(aVisibility
);
671 return NS_ERROR_NULL_POINTER
;
675 nsDocShellTreeOwner::GetEnabled(PRBool
*aEnabled
)
677 NS_ENSURE_ARG_POINTER(aEnabled
);
679 return NS_ERROR_NOT_IMPLEMENTED
;
683 nsDocShellTreeOwner::SetEnabled(PRBool aEnabled
)
685 return NS_ERROR_NOT_IMPLEMENTED
;
689 nsDocShellTreeOwner::GetBlurSuppression(PRBool
*aBlurSuppression
)
691 NS_ENSURE_ARG_POINTER(aBlurSuppression
);
692 *aBlurSuppression
= PR_FALSE
;
693 return NS_ERROR_NOT_IMPLEMENTED
;
697 nsDocShellTreeOwner::SetBlurSuppression(PRBool aBlurSuppression
)
699 return NS_ERROR_NOT_IMPLEMENTED
;
703 nsDocShellTreeOwner::GetMainWidget(nsIWidget
** aMainWidget
)
705 return NS_ERROR_NULL_POINTER
;
709 nsDocShellTreeOwner::SetFocus()
711 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
714 return ownerWin
->SetFocus();
716 return NS_ERROR_NULL_POINTER
;
720 nsDocShellTreeOwner::GetTitle(PRUnichar
** aTitle
)
722 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
725 return ownerWin
->GetTitle(aTitle
);
727 return NS_ERROR_NULL_POINTER
;
731 nsDocShellTreeOwner::SetTitle(const PRUnichar
* aTitle
)
733 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin
= GetOwnerWin();
736 return ownerWin
->SetTitle(aTitle
);
738 return NS_ERROR_NULL_POINTER
;
742 //*****************************************************************************
743 // nsDocShellTreeOwner::nsIWebProgressListener
744 //*****************************************************************************
748 nsDocShellTreeOwner::OnProgressChange(nsIWebProgress
* aProgress
,
749 nsIRequest
* aRequest
,
750 PRInt32 aCurSelfProgress
,
751 PRInt32 aMaxSelfProgress
,
752 PRInt32 aCurTotalProgress
,
753 PRInt32 aMaxTotalProgress
)
755 // In the absence of DOM document creation event, this method is the
756 // most convenient place to install the mouse listener on the
758 return AddChromeListeners();
762 nsDocShellTreeOwner::OnStateChange(nsIWebProgress
* aProgress
,
763 nsIRequest
* aRequest
,
764 PRUint32 aProgressStateFlags
,
771 nsDocShellTreeOwner::OnLocationChange(nsIWebProgress
* aWebProgress
,
772 nsIRequest
* aRequest
,
779 nsDocShellTreeOwner::OnStatusChange(nsIWebProgress
* aWebProgress
,
780 nsIRequest
* aRequest
,
782 const PRUnichar
* aMessage
)
788 nsDocShellTreeOwner::OnSecurityChange(nsIWebProgress
*aWebProgress
,
789 nsIRequest
*aRequest
,
796 //*****************************************************************************
797 // nsDocShellTreeOwner: Helpers
798 //*****************************************************************************
800 //*****************************************************************************
801 // nsDocShellTreeOwner: Accessors
802 //*****************************************************************************
805 nsDocShellTreeOwner::WebBrowser(nsWebBrowser
* aWebBrowser
)
808 RemoveChromeListeners();
809 if (aWebBrowser
!= mWebBrowser
) {
814 mWebBrowser
= aWebBrowser
;
818 nsDocShellTreeOwner::WebBrowser()
824 nsDocShellTreeOwner::SetTreeOwner(nsIDocShellTreeOwner
* aTreeOwner
)
827 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome(do_GetInterface(aTreeOwner
));
828 NS_ENSURE_TRUE(webBrowserChrome
, NS_ERROR_INVALID_ARG
);
829 NS_ENSURE_SUCCESS(SetWebBrowserChrome(webBrowserChrome
), NS_ERROR_INVALID_ARG
);
830 mTreeOwner
= aTreeOwner
;
834 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= GetWebBrowserChrome();
835 if (!webBrowserChrome
)
836 NS_ENSURE_SUCCESS(SetWebBrowserChrome(nsnull
), NS_ERROR_FAILURE
);
843 nsDocShellTreeOwner::SetWebBrowserChrome(nsIWebBrowserChrome
* aWebBrowserChrome
)
845 if(!aWebBrowserChrome
) {
846 mWebBrowserChrome
= nsnull
;
848 mOwnerRequestor
= nsnull
;
849 mWebBrowserChromeWeak
= 0;
851 nsCOMPtr
<nsISupportsWeakReference
> supportsweak
=
852 do_QueryInterface(aWebBrowserChrome
);
854 supportsweak
->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak
));
856 nsCOMPtr
<nsIEmbeddingSiteWindow
> ownerWin(do_QueryInterface(aWebBrowserChrome
));
857 nsCOMPtr
<nsIInterfaceRequestor
> requestor(do_QueryInterface(aWebBrowserChrome
));
859 // it's ok for ownerWin or requestor to be null.
860 mWebBrowserChrome
= aWebBrowserChrome
;
861 mOwnerWin
= ownerWin
;
862 mOwnerRequestor
= requestor
;
870 // AddChromeListeners
872 // Hook up things to the chrome like context menus and tooltips, if the chrome
873 // has implemented the right interfaces.
876 nsDocShellTreeOwner::AddChromeListeners()
880 nsCOMPtr
<nsIWebBrowserChrome
> webBrowserChrome
= GetWebBrowserChrome();
881 if (!webBrowserChrome
)
882 return NS_ERROR_FAILURE
;
885 if ( !mChromeTooltipListener
) {
886 nsCOMPtr
<nsITooltipListener
>
887 tooltipListener(do_QueryInterface(webBrowserChrome
));
888 if ( tooltipListener
) {
889 mChromeTooltipListener
= new ChromeTooltipListener(mWebBrowser
,
891 if ( mChromeTooltipListener
) {
892 NS_ADDREF(mChromeTooltipListener
);
893 rv
= mChromeTooltipListener
->AddChromeListeners();
896 rv
= NS_ERROR_OUT_OF_MEMORY
;
900 // install context menus
901 if ( !mChromeContextMenuListener
) {
902 nsCOMPtr
<nsIContextMenuListener2
>
903 contextListener2(do_QueryInterface(webBrowserChrome
));
904 nsCOMPtr
<nsIContextMenuListener
>
905 contextListener(do_QueryInterface(webBrowserChrome
));
906 if ( contextListener2
|| contextListener
) {
907 mChromeContextMenuListener
=
908 new ChromeContextMenuListener(mWebBrowser
, webBrowserChrome
);
909 if ( mChromeContextMenuListener
) {
910 NS_ADDREF(mChromeContextMenuListener
);
911 rv
= mChromeContextMenuListener
->AddChromeListeners();
914 rv
= NS_ERROR_OUT_OF_MEMORY
;
918 // install the external dragDrop handler
919 if ( !mChromeDragHandler
) {
920 mChromeDragHandler
= do_CreateInstance("@mozilla.org:/content/content-area-dragdrop;1", &rv
);
921 NS_ASSERTION(mChromeDragHandler
, "Couldn't create the chrome drag handler");
922 if ( mChromeDragHandler
) {
923 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
;
924 GetPIDOMEventTarget(mWebBrowser
, getter_AddRefs(piTarget
));
925 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(piTarget
));
926 mChromeDragHandler
->HookupTo(target
, static_cast<nsIWebNavigation
*>(mWebBrowser
));
932 } // AddChromeListeners
936 nsDocShellTreeOwner::RemoveChromeListeners()
938 if ( mChromeTooltipListener
) {
939 mChromeTooltipListener
->RemoveChromeListeners();
940 NS_RELEASE(mChromeTooltipListener
);
942 if ( mChromeContextMenuListener
) {
943 mChromeContextMenuListener
->RemoveChromeListeners();
944 NS_RELEASE(mChromeContextMenuListener
);
946 if ( mChromeDragHandler
)
947 mChromeDragHandler
->Detach();
952 already_AddRefed
<nsIWebBrowserChrome
>
953 nsDocShellTreeOwner::GetWebBrowserChrome()
955 nsIWebBrowserChrome
* chrome
= nsnull
;
956 if (mWebBrowserChromeWeak
!= nsnull
) {
957 mWebBrowserChromeWeak
->
958 QueryReferent(NS_GET_IID(nsIWebBrowserChrome
),
959 reinterpret_cast<void**>(&chrome
));
960 } else if (mWebBrowserChrome
) {
961 chrome
= mWebBrowserChrome
;
962 NS_ADDREF(mWebBrowserChrome
);
968 already_AddRefed
<nsIEmbeddingSiteWindow
>
969 nsDocShellTreeOwner::GetOwnerWin()
971 nsIEmbeddingSiteWindow
* win
= nsnull
;
972 if (mWebBrowserChromeWeak
!= nsnull
) {
973 mWebBrowserChromeWeak
->
974 QueryReferent(NS_GET_IID(nsIEmbeddingSiteWindow
),
975 reinterpret_cast<void**>(&win
));
976 } else if (mOwnerWin
) {
978 NS_ADDREF(mOwnerWin
);
984 already_AddRefed
<nsIInterfaceRequestor
>
985 nsDocShellTreeOwner::GetOwnerRequestor()
987 nsIInterfaceRequestor
* req
= nsnull
;
988 if (mWebBrowserChromeWeak
!= nsnull
) {
989 mWebBrowserChromeWeak
->
990 QueryReferent(NS_GET_IID(nsIInterfaceRequestor
),
991 reinterpret_cast<void**>(&req
));
992 } else if (mOwnerRequestor
) {
993 req
= mOwnerRequestor
;
994 NS_ADDREF(mOwnerRequestor
);
1006 ///////////////////////////////////////////////////////////////////////////////
1007 // DefaultTooltipTextProvider
1009 class DefaultTooltipTextProvider
: public nsITooltipTextProvider
1012 DefaultTooltipTextProvider();
1015 NS_DECL_NSITOOLTIPTEXTPROVIDER
1018 nsCOMPtr
<nsIAtom
> mTag_dialog
;
1019 nsCOMPtr
<nsIAtom
> mTag_dialogheader
;
1020 nsCOMPtr
<nsIAtom
> mTag_window
;
1023 NS_IMPL_THREADSAFE_ISUPPORTS1(DefaultTooltipTextProvider
, nsITooltipTextProvider
)
1025 DefaultTooltipTextProvider::DefaultTooltipTextProvider()
1027 // There are certain element types which we don't want to use
1028 // as tool tip text.
1029 mTag_dialog
= do_GetAtom("dialog");
1030 mTag_dialogheader
= do_GetAtom("dialogheader");
1031 mTag_window
= do_GetAtom("window");
1034 /* void getNodeText (in nsIDOMNode aNode, out wstring aText); */
1036 DefaultTooltipTextProvider::GetNodeText(nsIDOMNode
*aNode
, PRUnichar
**aText
,
1039 NS_ENSURE_ARG_POINTER(aNode
);
1040 NS_ENSURE_ARG_POINTER(aText
);
1044 PRBool found
= PR_FALSE
;
1045 nsCOMPtr
<nsIDOMNode
> current ( aNode
);
1046 while ( !found
&& current
) {
1047 nsCOMPtr
<nsIDOMElement
> currElement ( do_QueryInterface(current
) );
1048 if ( currElement
) {
1049 nsCOMPtr
<nsIContent
> content(do_QueryInterface(currElement
));
1051 nsIAtom
*tagAtom
= content
->Tag();
1052 if (tagAtom
!= mTag_dialog
&&
1053 tagAtom
!= mTag_dialogheader
&&
1054 tagAtom
!= mTag_window
) {
1055 // first try the normal title attribute...
1056 currElement
->GetAttribute(NS_LITERAL_STRING("title"), outText
);
1057 if ( outText
.Length() )
1060 // ...ok, that didn't work, try it in the XLink namespace
1061 currElement
->GetAttributeNS(NS_LITERAL_STRING("http://www.w3.org/1999/xlink"), NS_LITERAL_STRING("title"), outText
);
1062 if ( outText
.Length() )
1069 // not found here, walk up to the parent and keep trying
1071 nsCOMPtr
<nsIDOMNode
> temp ( current
);
1072 temp
->GetParentNode(getter_AddRefs(current
));
1074 } // while not found
1077 *aText
= (found
) ? ToNewUnicode(outText
) : nsnull
;
1082 ///////////////////////////////////////////////////////////////////////////////
1084 NS_IMPL_ADDREF(ChromeTooltipListener
)
1085 NS_IMPL_RELEASE(ChromeTooltipListener
)
1087 NS_INTERFACE_MAP_BEGIN(ChromeTooltipListener
)
1088 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMMouseListener
)
1089 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener
, nsIDOMMouseListener
)
1090 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener
)
1091 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener
)
1092 NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener
)
1093 NS_INTERFACE_MAP_END
1097 // ChromeTooltipListener ctor
1100 ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser
* inBrowser
,
1101 nsIWebBrowserChrome
* inChrome
)
1102 : mWebBrowser(inBrowser
), mWebBrowserChrome(inChrome
),
1103 mTooltipListenerInstalled(PR_FALSE
),
1104 mMouseClientX(0), mMouseClientY(0),
1105 mShowingTooltip(PR_FALSE
)
1107 mTooltipTextProvider
= do_GetService(NS_TOOLTIPTEXTPROVIDER_CONTRACTID
);
1108 if (!mTooltipTextProvider
) {
1109 nsISupports
*pProvider
= (nsISupports
*) new DefaultTooltipTextProvider
;
1110 mTooltipTextProvider
= do_QueryInterface(pProvider
);
1116 // ChromeTooltipListener dtor
1118 ChromeTooltipListener::~ChromeTooltipListener()
1125 // AddChromeListeners
1127 // Hook up things to the chrome like context menus and tooltips, if the chrome
1128 // has implemented the right interfaces.
1131 ChromeTooltipListener::AddChromeListeners()
1134 GetPIDOMEventTarget(mWebBrowser
, getter_AddRefs(mEventTarget
));
1136 // Register the appropriate events for tooltips, but only if
1137 // the embedding chrome cares.
1138 nsresult rv
= NS_OK
;
1139 nsCOMPtr
<nsITooltipListener
> tooltipListener ( do_QueryInterface(mWebBrowserChrome
) );
1140 if ( tooltipListener
&& !mTooltipListenerInstalled
) {
1141 rv
= AddTooltipListener();
1142 if ( NS_FAILED(rv
) )
1148 } // AddChromeListeners
1152 // AddTooltipListener
1154 // Subscribe to the events that will allow us to track tooltips. We need "mouse" for mouseExit,
1155 // "mouse motion" for mouseMove, and "key" for keyDown. As we add the listeners, keep track
1156 // of how many succeed so we can clean up correctly in Release().
1159 ChromeTooltipListener::AddTooltipListener()
1162 nsIDOMMouseListener
*pListener
= static_cast<nsIDOMMouseListener
*>(this);
1163 nsresult rv
= mEventTarget
->AddEventListenerByIID(pListener
, NS_GET_IID(nsIDOMMouseListener
));
1164 nsresult rv2
= mEventTarget
->AddEventListenerByIID(pListener
, NS_GET_IID(nsIDOMMouseMotionListener
));
1165 nsresult rv3
= mEventTarget
->AddEventListenerByIID(pListener
, NS_GET_IID(nsIDOMKeyListener
));
1167 // if all 3 succeed, we're a go!
1168 if (NS_SUCCEEDED(rv
) && NS_SUCCEEDED(rv2
) && NS_SUCCEEDED(rv3
))
1169 mTooltipListenerInstalled
= PR_TRUE
;
1177 // RemoveChromeListeners
1179 // Unsubscribe from the various things we've hooked up to the window root.
1182 ChromeTooltipListener::RemoveChromeListeners ( )
1186 if ( mTooltipListenerInstalled
)
1187 RemoveTooltipListener();
1189 mEventTarget
= nsnull
;
1191 // it really doesn't matter if these fail...
1194 } // RemoveChromeTooltipListeners
1199 // RemoveTooltipListener
1201 // Unsubscribe from all the various tooltip events that we were listening to
1204 ChromeTooltipListener::RemoveTooltipListener()
1207 nsIDOMMouseListener
*pListener
= static_cast<nsIDOMMouseListener
*>(this);
1208 nsresult rv
= mEventTarget
->RemoveEventListenerByIID(pListener
, NS_GET_IID(nsIDOMMouseListener
));
1209 nsresult rv2
= mEventTarget
->RemoveEventListenerByIID(pListener
, NS_GET_IID(nsIDOMMouseMotionListener
));
1210 nsresult rv3
= mEventTarget
->RemoveEventListenerByIID(pListener
, NS_GET_IID(nsIDOMKeyListener
));
1211 if (NS_SUCCEEDED(rv
) && NS_SUCCEEDED(rv2
) && NS_SUCCEEDED(rv3
))
1212 mTooltipListenerInstalled
= PR_FALSE
;
1222 // When the user starts typing, they generaly don't want to see any messy wax
1223 // builup. Hide the tooltip.
1226 ChromeTooltipListener::KeyDown(nsIDOMEvent
* aMouseEvent
)
1228 return HideTooltip();
1236 // We can ignore these as they are already handled by KeyDown
1239 ChromeTooltipListener::KeyUp(nsIDOMEvent
* aMouseEvent
)
1246 ChromeTooltipListener::KeyPress(nsIDOMEvent
* aMouseEvent
)
1256 // On a click, hide the tooltip
1259 ChromeTooltipListener::MouseDown(nsIDOMEvent
* aMouseEvent
)
1261 return HideTooltip();
1267 ChromeTooltipListener::MouseUp(nsIDOMEvent
* aMouseEvent
)
1273 ChromeTooltipListener::MouseClick(nsIDOMEvent
* aMouseEvent
)
1279 ChromeTooltipListener::MouseDblClick(nsIDOMEvent
* aMouseEvent
)
1285 ChromeTooltipListener::MouseOver(nsIDOMEvent
* aMouseEvent
)
1294 // If we're responding to tooltips, hide the tip whenever the mouse leaves
1295 // the area it was in.
1297 ChromeTooltipListener::MouseOut(nsIDOMEvent
* aMouseEvent
)
1299 return HideTooltip();
1306 // If we're a tooltip, fire off a timer to see if a tooltip should be shown. If the
1307 // timer fires, we cache the node in |mPossibleTooltipNode|.
1310 ChromeTooltipListener::MouseMove(nsIDOMEvent
* aMouseEvent
)
1312 nsCOMPtr
<nsIDOMMouseEvent
> mouseEvent ( do_QueryInterface(aMouseEvent
) );
1316 // stash the coordinates of the event so that we can still get back to it from within the
1317 // timer callback. On win32, we'll get a MouseMove event even when a popup goes away --
1318 // even when the mouse doesn't change position! To get around this, we make sure the
1319 // mouse has really moved before proceeding.
1320 PRInt32 newMouseX
, newMouseY
;
1321 mouseEvent
->GetClientX(&newMouseX
);
1322 mouseEvent
->GetClientY(&newMouseY
);
1323 if ( mMouseClientX
== newMouseX
&& mMouseClientY
== newMouseY
)
1325 mMouseClientX
= newMouseX
; mMouseClientY
= newMouseY
;
1326 mouseEvent
->GetScreenX(&mMouseScreenX
);
1327 mouseEvent
->GetScreenY(&mMouseScreenY
);
1329 // We want to close the tip if it is being displayed and the mouse moves. Recall
1330 // that |mShowingTooltip| is set when the popup is showing. Furthermore, as the mouse
1331 // moves, we want to make sure we reset the timer to show it, so that the delay
1332 // is from when the mouse stops moving, not when it enters the element.
1333 if ( mShowingTooltip
)
1334 return HideTooltip();
1335 if ( mTooltipTimer
)
1336 mTooltipTimer
->Cancel();
1338 mTooltipTimer
= do_CreateInstance("@mozilla.org/timer;1");
1339 if ( mTooltipTimer
) {
1340 nsCOMPtr
<nsIDOMEventTarget
> eventTarget
;
1341 aMouseEvent
->GetTarget(getter_AddRefs(eventTarget
));
1343 mPossibleTooltipNode
= do_QueryInterface(eventTarget
);
1344 if ( mPossibleTooltipNode
) {
1345 nsresult rv
= mTooltipTimer
->InitWithFuncCallback(sTooltipCallback
, this, kTooltipShowTime
,
1346 nsITimer::TYPE_ONE_SHOT
);
1348 mPossibleTooltipNode
= nsnull
;
1352 NS_WARNING ( "Could not create a timer for tooltip tracking" );
1362 // Tell the registered chrome that they should show the tooltip
1365 ChromeTooltipListener::ShowTooltip(PRInt32 inXCoords
, PRInt32 inYCoords
,
1366 const nsAString
& inTipText
)
1368 nsresult rv
= NS_OK
;
1370 // do the work to call the client
1371 nsCOMPtr
<nsITooltipListener
> tooltipListener ( do_QueryInterface(mWebBrowserChrome
) );
1372 if ( tooltipListener
) {
1373 rv
= tooltipListener
->OnShowTooltip ( inXCoords
, inYCoords
, PromiseFlatString(inTipText
).get() );
1374 if ( NS_SUCCEEDED(rv
) )
1375 mShowingTooltip
= PR_TRUE
;
1386 // Tell the registered chrome that they should rollup the tooltip
1387 // NOTE: This routine is safe to call even if the popup is already closed.
1390 ChromeTooltipListener::HideTooltip()
1392 nsresult rv
= NS_OK
;
1394 // shut down the relevant timers
1395 if ( mTooltipTimer
) {
1396 mTooltipTimer
->Cancel();
1397 mTooltipTimer
= nsnull
;
1398 // release tooltip target
1399 mPossibleTooltipNode
= nsnull
;
1401 if ( mAutoHideTimer
) {
1402 mAutoHideTimer
->Cancel();
1403 mAutoHideTimer
= nsnull
;
1406 // if we're showing the tip, tell the chrome to hide it
1407 if ( mShowingTooltip
) {
1408 nsCOMPtr
<nsITooltipListener
> tooltipListener ( do_QueryInterface(mWebBrowserChrome
) );
1409 if ( tooltipListener
) {
1410 rv
= tooltipListener
->OnHideTooltip ( );
1411 if ( NS_SUCCEEDED(rv
) )
1412 mShowingTooltip
= PR_FALSE
;
1424 // A timer callback, fired when the mouse has hovered inside of a frame for the
1425 // appropriate amount of time. Getting to this point means that we should show the
1426 // tooltip, but only after we determine there is an appropriate TITLE element.
1428 // This relies on certain things being cached into the |aChromeTooltipListener| object passed to
1430 // -- the x/y coordinates of the mouse (mMouseClientY, mMouseClientX)
1431 // -- the dom node the user hovered over (mPossibleTooltipNode)
1434 ChromeTooltipListener::sTooltipCallback(nsITimer
*aTimer
,
1435 void *aChromeTooltipListener
)
1437 ChromeTooltipListener
* self
= static_cast<ChromeTooltipListener
*>
1438 (aChromeTooltipListener
);
1439 if ( self
&& self
->mPossibleTooltipNode
){
1440 // The actual coordinates we want to put the tooltip at are relative to the
1441 // toplevel docshell of our mWebBrowser. We know what the screen
1442 // coordinates of the mouse event were, which means we just need the screen
1443 // coordinates of the docshell. Unfortunately, there is no good way to
1444 // find those short of groveling for the presentation in that docshell and
1445 // finding the screen coords of its toplevel widget...
1446 nsCOMPtr
<nsIDocShell
> docShell
=
1447 do_GetInterface(static_cast<nsIWebBrowser
*>(self
->mWebBrowser
));
1448 nsCOMPtr
<nsIPresShell
> shell
;
1450 docShell
->GetPresShell(getter_AddRefs(shell
));
1453 nsIWidget
* widget
= nsnull
;
1455 nsIViewManager
* vm
= shell
->GetViewManager();
1458 vm
->GetRootView(view
);
1461 widget
= view
->GetNearestWidget(&offset
);
1467 // release tooltip target if there is one, NO MATTER WHAT
1468 self
->mPossibleTooltipNode
= nsnull
;
1472 // if there is text associated with the node, show the tip and fire
1473 // off a timer to auto-hide it.
1475 nsXPIDLString tooltipText
;
1476 if (self
->mTooltipTextProvider
) {
1477 PRBool textFound
= PR_FALSE
;
1479 self
->mTooltipTextProvider
->GetNodeText(
1480 self
->mPossibleTooltipNode
, getter_Copies(tooltipText
), &textFound
);
1483 nsString
tipText(tooltipText
);
1484 self
->CreateAutoHideTimer();
1485 nsRect
widgetDot(0, 0, 1, 1);
1487 widget
->WidgetToScreen(widgetDot
, screenDot
);
1488 self
->ShowTooltip (self
->mMouseScreenX
- screenDot
.x
,
1489 self
->mMouseScreenY
- screenDot
.y
,
1494 // release tooltip target if there is one, NO MATTER WHAT
1495 self
->mPossibleTooltipNode
= nsnull
;
1496 } // if "self" data valid
1498 } // sTooltipCallback
1502 // CreateAutoHideTimer
1504 // Create a new timer to see if we should auto-hide. It's ok if this fails.
1507 ChromeTooltipListener::CreateAutoHideTimer()
1509 // just to be anal (er, safe)
1510 if ( mAutoHideTimer
) {
1511 mAutoHideTimer
->Cancel();
1512 mAutoHideTimer
= nsnull
;
1515 mAutoHideTimer
= do_CreateInstance("@mozilla.org/timer;1");
1516 if ( mAutoHideTimer
)
1517 mAutoHideTimer
->InitWithFuncCallback(sAutoHideCallback
, this, kTooltipAutoHideTime
,
1518 nsITimer::TYPE_ONE_SHOT
);
1520 } // CreateAutoHideTimer
1524 // sAutoHideCallback
1526 // This fires after a tooltip has been open for a certain length of time. Just tell
1527 // the listener to close the popup. We don't have to worry, because HideTooltip() can
1528 // be called multiple times, even if the tip has already been closed.
1531 ChromeTooltipListener::sAutoHideCallback(nsITimer
*aTimer
, void* aListener
)
1533 ChromeTooltipListener
* self
= static_cast<ChromeTooltipListener
*>(aListener
);
1535 self
->HideTooltip();
1537 // NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling ClosePopup();
1539 } // sAutoHideCallback
1548 NS_IMPL_ADDREF(ChromeContextMenuListener
)
1549 NS_IMPL_RELEASE(ChromeContextMenuListener
)
1551 NS_INTERFACE_MAP_BEGIN(ChromeContextMenuListener
)
1552 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMContextMenuListener
)
1553 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener
, nsIDOMContextMenuListener
)
1554 NS_INTERFACE_MAP_ENTRY(nsIDOMContextMenuListener
)
1555 NS_INTERFACE_MAP_END
1559 // ChromeTooltipListener ctor
1561 ChromeContextMenuListener::ChromeContextMenuListener(nsWebBrowser
* inBrowser
, nsIWebBrowserChrome
* inChrome
)
1562 : mContextMenuListenerInstalled(PR_FALSE
),
1563 mWebBrowser(inBrowser
),
1564 mWebBrowserChrome(inChrome
)
1570 // ChromeTooltipListener dtor
1572 ChromeContextMenuListener::~ChromeContextMenuListener()
1578 // AddContextMenuListener
1580 // Subscribe to the events that will allow us to track context menus. Bascially, this
1581 // is just the context-menu DOM event.
1584 ChromeContextMenuListener::AddContextMenuListener()
1587 nsIDOMContextMenuListener
*pListener
= static_cast<nsIDOMContextMenuListener
*>(this);
1588 nsresult rv
= mEventTarget
->AddEventListenerByIID(pListener
, NS_GET_IID(nsIDOMContextMenuListener
));
1589 if (NS_SUCCEEDED(rv
))
1590 mContextMenuListenerInstalled
= PR_TRUE
;
1598 // RemoveContextMenuListener
1600 // Unsubscribe from all the various context menu events that we were listening to.
1603 ChromeContextMenuListener::RemoveContextMenuListener()
1606 nsIDOMContextMenuListener
*pListener
= static_cast<nsIDOMContextMenuListener
*>(this);
1607 nsresult rv
= mEventTarget
->RemoveEventListenerByIID(pListener
, NS_GET_IID(nsIDOMContextMenuListener
));
1608 if (NS_SUCCEEDED(rv
))
1609 mContextMenuListenerInstalled
= PR_FALSE
;
1617 // AddChromeListeners
1619 // Hook up things to the chrome like context menus and tooltips, if the chrome
1620 // has implemented the right interfaces.
1623 ChromeContextMenuListener::AddChromeListeners()
1626 GetPIDOMEventTarget(mWebBrowser
, getter_AddRefs(mEventTarget
));
1628 // Register the appropriate events for context menus, but only if
1629 // the embedding chrome cares.
1630 nsresult rv
= NS_OK
;
1632 nsCOMPtr
<nsIContextMenuListener2
> contextListener2 ( do_QueryInterface(mWebBrowserChrome
) );
1633 nsCOMPtr
<nsIContextMenuListener
> contextListener ( do_QueryInterface(mWebBrowserChrome
) );
1634 if ( (contextListener
|| contextListener2
) && !mContextMenuListenerInstalled
)
1635 rv
= AddContextMenuListener();
1639 } // AddChromeListeners
1643 // RemoveChromeListeners
1645 // Unsubscribe from the various things we've hooked up to the window root.
1648 ChromeContextMenuListener::RemoveChromeListeners()
1650 if ( mContextMenuListenerInstalled
)
1651 RemoveContextMenuListener();
1653 mEventTarget
= nsnull
;
1655 // it really doesn't matter if these fail...
1658 } // RemoveChromeTooltipListeners
1665 // We're on call to show the context menu. Dig around in the DOM to
1666 // find the type of object we're dealing with and notify the front
1670 ChromeContextMenuListener::ContextMenu(nsIDOMEvent
* aMouseEvent
)
1672 nsCOMPtr
<nsIDOMNSUIEvent
> uievent(do_QueryInterface(aMouseEvent
));
1675 PRBool isDefaultPrevented
= PR_FALSE
;
1676 uievent
->GetPreventDefault(&isDefaultPrevented
);
1678 if (isDefaultPrevented
) {
1683 nsCOMPtr
<nsIDOMEventTarget
> targetNode
;
1684 nsresult res
= aMouseEvent
->GetTarget(getter_AddRefs(targetNode
));
1688 return NS_ERROR_NULL_POINTER
;
1690 nsCOMPtr
<nsIDOMNode
> targetDOMnode
;
1691 nsCOMPtr
<nsIDOMNode
> node
= do_QueryInterface(targetNode
);
1695 // Stop the context menu event going to other windows (bug 78396)
1696 aMouseEvent
->PreventDefault();
1698 // If the listener is a nsIContextMenuListener2, create the info object
1699 nsCOMPtr
<nsIContextMenuListener2
> menuListener2(do_QueryInterface(mWebBrowserChrome
));
1700 nsContextMenuInfo
*menuInfoImpl
= nsnull
;
1701 nsCOMPtr
<nsIContextMenuInfo
> menuInfo
;
1702 if (menuListener2
) {
1703 menuInfoImpl
= new nsContextMenuInfo
;
1705 return NS_ERROR_OUT_OF_MEMORY
;
1706 menuInfo
= menuInfoImpl
;
1709 PRUint32 flags
= nsIContextMenuListener::CONTEXT_NONE
;
1710 PRUint32 flags2
= nsIContextMenuListener2::CONTEXT_NONE
;
1712 // XXX test for selected text
1715 res
= node
->GetNodeType(&nodeType
);
1716 NS_ENSURE_SUCCESS(res
, res
);
1718 // First, checks for nodes that never have children.
1719 if (nodeType
== nsIDOMNode::ELEMENT_NODE
) {
1720 nsCOMPtr
<nsIImageLoadingContent
> content(do_QueryInterface(node
));
1722 nsCOMPtr
<nsIURI
> imgUri
;
1723 content
->GetCurrentURI(getter_AddRefs(imgUri
));
1725 flags
|= nsIContextMenuListener::CONTEXT_IMAGE
;
1726 flags2
|= nsIContextMenuListener2::CONTEXT_IMAGE
;
1727 targetDOMnode
= node
;
1731 nsCOMPtr
<nsIDOMHTMLInputElement
> inputElement(do_QueryInterface(node
));
1733 flags
|= nsIContextMenuListener::CONTEXT_INPUT
;
1734 flags2
|= nsIContextMenuListener2::CONTEXT_INPUT
;
1736 if (menuListener2
) {
1737 nsAutoString inputElemType
;
1738 inputElement
->GetType(inputElemType
);
1739 if (inputElemType
.LowerCaseEqualsLiteral("text") ||
1740 inputElemType
.LowerCaseEqualsLiteral("password"))
1741 flags2
|= nsIContextMenuListener2::CONTEXT_TEXT
;
1744 targetDOMnode
= node
;
1747 nsCOMPtr
<nsIDOMHTMLTextAreaElement
> textElement(do_QueryInterface(node
));
1749 flags
|= nsIContextMenuListener::CONTEXT_TEXT
;
1750 flags2
|= nsIContextMenuListener2::CONTEXT_TEXT
;
1751 targetDOMnode
= node
;
1754 // always consume events for plugins and Java who may throw their
1755 // own context menus but not for image objects. Document objects
1756 // will never be targets or ancestors of targets, so that's OK.
1757 nsCOMPtr
<nsIDOMHTMLObjectElement
> objectElement
;
1758 if (!(flags
& nsIContextMenuListener::CONTEXT_IMAGE
))
1759 objectElement
= do_QueryInterface(node
);
1760 nsCOMPtr
<nsIDOMHTMLEmbedElement
> embedElement(do_QueryInterface(node
));
1761 nsCOMPtr
<nsIDOMHTMLAppletElement
> appletElement(do_QueryInterface(node
));
1763 if (objectElement
|| embedElement
|| appletElement
)
1767 // Bubble out, looking for items of interest
1770 res
= node
->GetNodeType(&nodeType
);
1771 NS_ENSURE_SUCCESS(res
, res
);
1773 if (nodeType
== nsIDOMNode::ELEMENT_NODE
) {
1775 // Test if the element has an associated link
1776 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(node
));
1778 PRBool hasAttr
= PR_FALSE
;
1779 res
= element
->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr
);
1781 if (NS_SUCCEEDED(res
) && hasAttr
)
1783 flags
|= nsIContextMenuListener::CONTEXT_LINK
;
1784 flags2
|= nsIContextMenuListener2::CONTEXT_LINK
;
1786 targetDOMnode
= node
;
1788 menuInfoImpl
->SetAssociatedLink(node
);
1789 break; // exit do-while
1794 nsCOMPtr
<nsIDOMNode
> parentNode
;
1795 node
->GetParentNode(getter_AddRefs(parentNode
));
1799 if (!flags
&& !flags2
) {
1800 // We found nothing of interest so far, check if we
1801 // have at least an html document.
1802 nsCOMPtr
<nsIDOMDocument
> document
;
1803 node
= do_QueryInterface(targetNode
);
1804 node
->GetOwnerDocument(getter_AddRefs(document
));
1805 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDocument(do_QueryInterface(document
));
1807 flags
|= nsIContextMenuListener::CONTEXT_DOCUMENT
;
1808 flags2
|= nsIContextMenuListener2::CONTEXT_DOCUMENT
;
1809 targetDOMnode
= node
;
1810 if (!(flags
& nsIContextMenuListener::CONTEXT_IMAGE
)) {
1811 // check if this is a background image that the user was trying to click on
1812 // and if the listener is ready for that (only nsIContextMenuListener2 and up)
1813 if (menuInfoImpl
&& menuInfoImpl
->HasBackgroundImage(targetDOMnode
)) {
1814 flags2
|= nsIContextMenuListener2::CONTEXT_BACKGROUND_IMAGE
;
1815 // For the embedder to get the correct background image
1816 // targetDOMnode must point to the original node.
1817 targetDOMnode
= do_QueryInterface(targetNode
);
1823 // we need to cache the event target into the focus controller's popupNode
1824 // so we can get at it later from command code, etc.:
1826 // get the dom window
1827 nsCOMPtr
<nsIDOMWindow
> win
;
1828 res
= mWebBrowser
->GetContentDOMWindow(getter_AddRefs(win
));
1829 NS_ENSURE_SUCCESS(res
, res
);
1830 NS_ENSURE_TRUE(win
, NS_ERROR_FAILURE
);
1831 // get the private dom window
1832 nsCOMPtr
<nsPIDOMWindow
> privateWin(do_QueryInterface(win
, &res
));
1833 NS_ENSURE_SUCCESS(res
, res
);
1834 NS_ENSURE_TRUE(privateWin
, NS_ERROR_FAILURE
);
1835 // get the focus controller
1836 nsIFocusController
*focusController
= privateWin
->GetRootFocusController();
1837 NS_ENSURE_TRUE(focusController
, NS_ERROR_FAILURE
);
1838 // set the focus controller's popup node to the event target
1839 res
= focusController
->SetPopupNode(targetDOMnode
);
1840 NS_ENSURE_SUCCESS(res
, res
);
1842 // Tell the listener all about the event
1843 if ( menuListener2
) {
1844 menuInfoImpl
->SetMouseEvent(aMouseEvent
);
1845 menuInfoImpl
->SetDOMNode(targetDOMnode
);
1846 menuListener2
->OnShowContextMenu(flags2
, menuInfo
);
1849 nsCOMPtr
<nsIContextMenuListener
> menuListener(do_QueryInterface(mWebBrowserChrome
));
1851 menuListener
->OnShowContextMenu(flags
, aMouseEvent
, targetDOMnode
);