1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 #include "nsIWidget.h"
40 #include "nsViewManager.h"
41 #include "nsGUIEvent.h"
42 #include "nsIDeviceContext.h"
43 #include "nsIComponentManager.h"
44 #include "nsIScrollableView.h"
45 #include "nsGfxCIID.h"
46 #include "nsIRegion.h"
47 #include "nsIInterfaceRequestor.h"
52 static nsEventStatus PR_CALLBACK
HandleEvent(nsGUIEvent
*aEvent
);
55 //#define SHOW_VIEW_BORDERS
56 //#define HIDE_ALL_WIDGETS
58 // {34297A07-A8FD-d811-87C6-000244212BCB}
59 #define VIEW_WRAPPER_IID \
60 { 0x34297a07, 0xa8fd, 0xd811, { 0x87, 0xc6, 0x0, 0x2, 0x44, 0x21, 0x2b, 0xcb } }
64 * nsISupports-derived helper class that allows to store and get a view
66 class ViewWrapper
: public nsIInterfaceRequestor
69 NS_DECLARE_STATIC_IID_ACCESSOR(VIEW_WRAPPER_IID
)
71 NS_DECL_NSIINTERFACEREQUESTOR
73 ViewWrapper(nsView
* aView
) : mView(aView
) {}
75 nsView
* GetView() { return mView
; }
80 NS_DEFINE_STATIC_IID_ACCESSOR(ViewWrapper
, VIEW_WRAPPER_IID
)
82 NS_IMPL_ADDREF(ViewWrapper
)
83 NS_IMPL_RELEASE(ViewWrapper
)
85 NS_IMPL_QUERY_INTERFACE2(ViewWrapper
, ViewWrapper
, nsIInterfaceRequestor
)
88 NS_IMETHODIMP
ViewWrapper::QueryInterface(REFNSIID aIID
, void** aInstancePtr
)
90 NS_ENSURE_ARG_POINTER(aInstancePtr
);
92 NS_ASSERTION(!aIID
.Equals(NS_GET_IID(nsIView
)) &&
93 !aIID
.Equals(NS_GET_IID(nsIScrollableView
)),
94 "Someone expects a viewwrapper to be a view!");
96 *aInstancePtr
= nsnull
;
98 if (aIID
.Equals(NS_GET_IID(nsISupports
))) {
99 *aInstancePtr
= static_cast<nsISupports
*>(this);
101 else if (aIID
.Equals(NS_GET_IID(ViewWrapper
))) {
102 *aInstancePtr
= this;
104 else if (aIID
.Equals(NS_GET_IID(nsIInterfaceRequestor
))) {
105 *aInstancePtr
= this;
114 return NS_NOINTERFACE
;
118 NS_IMETHODIMP
ViewWrapper::GetInterface(REFNSIID aIID
, void** aInstancePtr
)
120 if (aIID
.Equals(NS_GET_IID(nsIScrollableView
))) {
121 *aInstancePtr
= mView
->ToScrollableView();
124 if (aIID
.Equals(NS_GET_IID(nsIView
))) {
125 *aInstancePtr
= mView
;
128 return QueryInterface(aIID
, aInstancePtr
);
132 * Given a widget, returns the stored ViewWrapper on it, or NULL if no
133 * ViewWrapper is there.
135 static ViewWrapper
* GetWrapperFor(nsIWidget
* aWidget
)
137 // The widget's client data points back to the owning view
140 aWidget
->GetClientData(clientData
);
141 nsISupports
* data
= (nsISupports
*)clientData
;
144 ViewWrapper
* wrapper
;
145 CallQueryInterface(data
, &wrapper
);
146 // Give a weak reference to the caller. There will still be at least one
147 // reference left, since the wrapper was addrefed when set on the widget.
157 // Main events handler
159 nsEventStatus PR_CALLBACK
HandleEvent(nsGUIEvent
*aEvent
)
161 //printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->widgetSupports,
162 // aEvent->message, aEvent->point.x, aEvent->point.y);
163 nsEventStatus result
= nsEventStatus_eIgnore
;
164 nsView
*view
= nsView::GetViewFor(aEvent
->widget
);
168 view
->GetViewManager()->DispatchEvent(aEvent
, &result
);
174 nsView::nsView(nsViewManager
* aViewManager
, nsViewVisibility aVisibility
)
176 MOZ_COUNT_CTOR(nsView
);
179 // Views should be transparent by default. Not being transparent is
180 // a promise that the view will paint all its pixels opaquely. Views
181 // should make this promise explicitly by calling
182 // SetViewContentTransparency.
184 mViewManager
= aViewManager
;
185 mDirtyRegion
= nsnull
;
186 mDeletionObserver
= nsnull
;
189 void nsView::DropMouseGrabbing() {
190 // check to see if we are grabbing events
191 if (mViewManager
->GetMouseEventGrabber() == this) {
192 // we are grabbing events. Move the grab to the parent if we can.
193 PRBool boolResult
; //not used
194 // if GetParent() returns null, then we release the grab, which is the best we can do
195 mViewManager
->GrabMouseEvents(GetParent(), boolResult
);
201 MOZ_COUNT_DTOR(nsView
);
203 if (this == nsViewManager::GetViewFocusedBeforeSuppression()) {
204 #ifdef DEBUG_FOCUS_SUPPRESSION
205 if (GetViewManager()->IsFocusSuppressed()) {
206 printf("*** 0 INFO TODO [CPEARCE] destroying view focused before suppression, while suppressed\n");
209 nsViewManager::SetViewFocusedBeforeSuppression(nsnull
);
211 if (this == nsViewManager::GetCurrentlyFocusedView()) {
212 #ifdef DEBUG_FOCUS_SUPPRESSION
213 if (GetViewManager()->IsFocusSuppressed()) {
214 printf("*** 0 INFO TODO [CPEARCE] destroying view currently focused, while suppressed\n");
217 nsViewManager::SetCurrentlyFocusedView(nsnull
);
220 while (GetFirstChild())
222 nsView
* child
= GetFirstChild();
223 if (child
->GetViewManager() == mViewManager
) {
226 // just unhook it. Someone else will want to destroy this.
235 nsView
*rootView
= mViewManager
->GetRootView();
239 // Root views can have parents!
242 mViewManager
->RemoveChild(this);
245 if (rootView
== this)
247 // Inform the view manager that the root view has gone away...
248 mViewManager
->SetRootView(nsnull
);
253 mParent
->RemoveChild(this);
256 mViewManager
= nsnull
;
260 mParent
->RemoveChild(this);
263 // Destroy and release the widget
266 // Release memory for the view wrapper
267 ViewWrapper
* wrapper
= GetWrapperFor(mWindow
);
268 NS_IF_RELEASE(wrapper
);
270 mWindow
->SetClientData(nsnull
);
271 if (!(mVFlags
& NS_VIEW_DISOWNS_WIDGET
)) {
278 if (mDeletionObserver
) {
279 mDeletionObserver
->Clear();
283 nsresult
nsView::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
285 if (nsnull
== aInstancePtr
) {
286 return NS_ERROR_NULL_POINTER
;
289 NS_ASSERTION(!aIID
.Equals(NS_GET_IID(nsISupports
)),
290 "Someone expects views to be ISupports-derived!");
292 *aInstancePtr
= nsnull
;
294 if (aIID
.Equals(NS_GET_IID(nsIView
))) {
295 *aInstancePtr
= (void*)(nsIView
*)this;
299 return NS_NOINTERFACE
;
302 nsIView
* nsIView::GetViewFor(nsIWidget
* aWidget
)
304 NS_PRECONDITION(nsnull
!= aWidget
, "null widget ptr");
306 ViewWrapper
* wrapper
= GetWrapperFor(aWidget
);
308 return wrapper
->GetView();
312 void nsIView::Destroy()
317 void nsView::SetPosition(nscoord aX
, nscoord aY
)
319 mDimBounds
.x
+= aX
- mPosX
;
320 mDimBounds
.y
+= aY
- mPosY
;
324 NS_ASSERTION(GetParent() || (aX
== 0 && aY
== 0),
325 "Don't try to move the root widget to something non-zero");
327 ResetWidgetBounds(PR_TRUE
, PR_TRUE
, PR_FALSE
);
330 void nsView::SetPositionIgnoringChildWidgets(nscoord aX
, nscoord aY
)
332 mDimBounds
.x
+= aX
- mPosX
;
333 mDimBounds
.y
+= aY
- mPosY
;
337 ResetWidgetBounds(PR_FALSE
, PR_TRUE
, PR_FALSE
);
340 void nsView::ResetWidgetBounds(PRBool aRecurse
, PRBool aMoveOnly
,
341 PRBool aInvalidateChangedSize
) {
343 // If our view manager has refresh disabled, then do nothing; the view
344 // manager will set our position when refresh is reenabled. Just let it
345 // know that it has pending updates.
346 if (!mViewManager
->IsRefreshEnabled()) {
347 mViewManager
->PostPendingUpdate();
351 DoResetWidgetBounds(aMoveOnly
, aInvalidateChangedSize
);
352 } else if (aRecurse
) {
353 // reposition any widgets under this view
354 for (nsView
* v
= GetFirstChild(); v
; v
= v
->GetNextSibling()) {
355 v
->ResetWidgetBounds(PR_TRUE
, aMoveOnly
, aInvalidateChangedSize
);
360 nsRect
nsView::CalcWidgetBounds(nsWindowType aType
)
362 nsCOMPtr
<nsIDeviceContext
> dx
;
363 mViewManager
->GetDeviceContext(*getter_AddRefs(dx
));
364 NS_ASSERTION(dx
, "View manager can't be created without a device context");
365 PRInt32 p2a
= dx
->AppUnitsPerDevPixel();
367 nsRect
viewBounds(mDimBounds
);
370 // put offset into screen coordinates
372 nsIWidget
* parentWidget
= GetParent()->GetNearestWidget(&offset
);
373 viewBounds
+= offset
;
375 if (parentWidget
&& aType
== eWindowType_popup
&&
376 mVis
== nsViewVisibility_kShow
) {
377 nsRect
screenRect(0,0,1,1);
378 parentWidget
->WidgetToScreen(screenRect
, screenRect
);
379 viewBounds
+= nsPoint(NSIntPixelsToAppUnits(screenRect
.x
, p2a
),
380 NSIntPixelsToAppUnits(screenRect
.y
, p2a
));
384 nsRect
newBounds(viewBounds
);
385 newBounds
.ScaleRoundPreservingCentersInverse(p2a
);
387 nsPoint
roundedOffset(NSIntPixelsToAppUnits(newBounds
.x
, p2a
),
388 NSIntPixelsToAppUnits(newBounds
.y
, p2a
));
389 mViewToWidgetOffset
= viewBounds
.TopLeft() - roundedOffset
;
394 void nsView::DoResetWidgetBounds(PRBool aMoveOnly
,
395 PRBool aInvalidateChangedSize
) {
396 // The geometry of a root view's widget is controlled externally,
397 // NOT by sizing or positioning the view
398 if (mViewManager
->GetRootView() == this) {
403 mWindow
->GetBounds(curBounds
);
405 mWindow
->GetWindowType(type
);
407 if (curBounds
.IsEmpty() && mDimBounds
.IsEmpty() && type
== eWindowType_popup
) {
408 // Don't manipulate empty popup widgets. For example there's no point
409 // moving hidden comboboxes around, or doing X server roundtrips
410 // to compute their true screen position. This could mean that WidgetToScreen
411 // operations on these widgets don't return up-to-date values, but popup
412 // positions aren't reliable anyway because of correction to be on or off-screen.
416 NS_PRECONDITION(mWindow
, "Why was this called??");
418 nsRect newBounds
= CalcWidgetBounds(type
);
420 PRBool changedPos
= curBounds
.TopLeft() != newBounds
.TopLeft();
421 PRBool changedSize
= curBounds
.Size() != newBounds
.Size();
424 if (changedSize
&& !aMoveOnly
) {
425 mWindow
->Resize(newBounds
.x
, newBounds
.y
, newBounds
.width
, newBounds
.height
,
426 aInvalidateChangedSize
);
428 mWindow
->Move(newBounds
.x
, newBounds
.y
);
431 if (changedSize
&& !aMoveOnly
) {
432 mWindow
->Resize(newBounds
.width
, newBounds
.height
, aInvalidateChangedSize
);
433 } // else do nothing!
437 void nsView::SetDimensions(const nsRect
& aRect
, PRBool aPaint
, PRBool aResizeWidget
)
440 dims
.MoveBy(mPosX
, mPosY
);
442 // Don't use nsRect's operator== here, since it returns true when
443 // both rects are empty even if they have different widths and we
444 // have cases where that sort of thing matters to us.
445 if (mDimBounds
.TopLeft() == dims
.TopLeft() &&
446 mDimBounds
.Size() == dims
.Size()) {
453 ResetWidgetBounds(PR_FALSE
, PR_FALSE
, aPaint
);
457 NS_IMETHODIMP
nsView::SetVisibility(nsViewVisibility aVisibility
)
462 if (aVisibility
== nsViewVisibility_kHide
)
467 if (nsnull
!= mWindow
)
469 #ifndef HIDE_ALL_WIDGETS
470 if (mVis
== nsViewVisibility_kShow
)
472 DoResetWidgetBounds(PR_FALSE
, PR_TRUE
);
473 mWindow
->Show(PR_TRUE
);
477 mWindow
->Show(PR_FALSE
);
483 NS_IMETHODIMP
nsView::SetFloating(PRBool aFloatingView
)
486 mVFlags
|= NS_VIEW_FLAG_FLOATING
;
488 mVFlags
&= ~NS_VIEW_FLAG_FLOATING
;
491 // recursively make all sub-views "floating" grr.
492 for (nsView
* child
= mFirstChild
; chlid
; child
= child
->GetNextSibling()) {
493 child
->SetFloating(aFloatingView
);
500 void nsView::InvalidateHierarchy(nsViewManager
*aViewManagerParent
)
502 if (aViewManagerParent
) {
503 // We're removed from the view hierarchy of aRemovalPoint, so make sure
504 // we're not still grabbing mouse events.
505 if (aViewManagerParent
->GetMouseEventGrabber() == this) {
507 aViewManagerParent
->GrabMouseEvents(nsnull
, res
);
511 if (mViewManager
->GetRootView() == this)
512 mViewManager
->InvalidateHierarchy();
514 for (nsView
*child
= mFirstChild
; child
; child
= child
->GetNextSibling())
515 child
->InvalidateHierarchy(aViewManagerParent
);
518 void nsView::InsertChild(nsView
*aChild
, nsView
*aSibling
)
520 NS_PRECONDITION(nsnull
!= aChild
, "null ptr");
522 if (nsnull
!= aChild
)
524 if (nsnull
!= aSibling
)
527 NS_ASSERTION(aSibling
->GetParent() == this, "tried to insert view with invalid sibling");
529 //insert after sibling
530 aChild
->SetNextSibling(aSibling
->GetNextSibling());
531 aSibling
->SetNextSibling(aChild
);
535 aChild
->SetNextSibling(mFirstChild
);
536 mFirstChild
= aChild
;
538 aChild
->SetParent(this);
540 // If we just inserted a root view, then update the RootViewManager
541 // on all view managers in the new subtree.
543 nsViewManager
*vm
= aChild
->GetViewManager();
544 if (vm
->GetRootView() == aChild
)
546 aChild
->InvalidateHierarchy(nsnull
); // don't care about releasing grabs
551 void nsView::RemoveChild(nsView
*child
)
553 NS_PRECONDITION(nsnull
!= child
, "null ptr");
557 nsView
* prevKid
= nsnull
;
558 nsView
* kid
= mFirstChild
;
559 PRBool found
= PR_FALSE
;
560 while (nsnull
!= kid
) {
562 if (nsnull
!= prevKid
) {
563 prevKid
->SetNextSibling(kid
->GetNextSibling());
565 mFirstChild
= kid
->GetNextSibling();
567 child
->SetParent(nsnull
);
572 kid
= kid
->GetNextSibling();
574 NS_ASSERTION(found
, "tried to remove non child");
576 // If we just removed a root view, then update the RootViewManager
577 // on all view managers in the removed subtree.
579 nsViewManager
*vm
= child
->GetViewManager();
580 if (vm
->GetRootView() == child
)
582 child
->InvalidateHierarchy(GetViewManager());
587 // Native widgets ultimately just can't deal with the awesome power of
588 // CSS2 z-index. However, we set the z-index on the widget anyway
589 // because in many simple common cases the widgets do end up in the
590 // right order. We set each widget's z-index to the z-index of the
591 // nearest ancestor that has non-auto z-index.
592 static void UpdateNativeWidgetZIndexes(nsView
* aView
, PRInt32 aZIndex
)
594 if (aView
->HasWidget()) {
595 nsIWidget
* widget
= aView
->GetWidget();
597 widget
->GetZIndex(&curZ
);
598 if (curZ
!= aZIndex
) {
599 widget
->SetZIndex(aZIndex
);
602 for (nsView
* v
= aView
->GetFirstChild(); v
; v
= v
->GetNextSibling()) {
603 if (v
->GetZIndexIsAuto()) {
604 UpdateNativeWidgetZIndexes(v
, aZIndex
);
610 static PRInt32
FindNonAutoZIndex(nsView
* aView
)
613 if (!aView
->GetZIndexIsAuto()) {
614 return aView
->GetZIndex();
616 aView
= aView
->GetParent();
621 nsresult
nsIView::CreateWidget(const nsIID
&aWindowIID
,
622 nsWidgetInitData
*aWidgetInitData
,
623 nsNativeWidget aNative
,
624 PRBool aEnableDragDrop
,
625 PRBool aResetVisibility
,
626 nsContentType aContentType
,
627 nsIWidget
* aParentWidget
)
629 if (NS_UNLIKELY(mWindow
)) {
630 NS_ERROR("We already have a window for this view? BAD");
631 ViewWrapper
* wrapper
= GetWrapperFor(mWindow
);
632 NS_IF_RELEASE(wrapper
);
633 mWindow
->SetClientData(nsnull
);
638 nsView
* v
= static_cast<nsView
*>(this);
640 nsRect trect
= v
->CalcWidgetBounds(aWidgetInitData
641 ? aWidgetInitData
->mWindowType
642 : eWindowType_child
);
644 if (NS_OK
== v
->LoadWidget(aWindowIID
))
647 nsCOMPtr
<nsIDeviceContext
> dx
;
648 mViewManager
->GetDeviceContext(*getter_AddRefs(dx
));
649 dx
->SupportsNativeWidgets(usewidgets
);
651 if (PR_TRUE
== usewidgets
)
653 PRBool initDataPassedIn
= PR_TRUE
;
654 nsWidgetInitData initData
;
655 if (!aWidgetInitData
) {
656 // No initData, we're a child window
657 // Create initData to pass in params
658 initDataPassedIn
= PR_FALSE
;
659 initData
.clipChildren
= PR_TRUE
; // Clip child window's children
660 initData
.clipSiblings
= PR_TRUE
; // Clip child window's siblings
661 aWidgetInitData
= &initData
;
663 aWidgetInitData
->mContentType
= aContentType
;
665 if (aNative
&& aWidgetInitData
->mWindowType
!= eWindowType_popup
)
666 mWindow
->Create(aNative
, trect
, ::HandleEvent
, dx
, nsnull
, nsnull
, aWidgetInitData
);
669 if (!initDataPassedIn
&& GetParent() &&
670 GetParent()->GetViewManager() != mViewManager
)
671 initData
.mListenForResizes
= PR_TRUE
;
673 NS_ASSERTION(aWidgetInitData
->mWindowType
== eWindowType_popup
,
674 "popup widget type expected");
675 mWindow
->Create(aParentWidget
, trect
,
676 ::HandleEvent
, dx
, nsnull
, nsnull
, aWidgetInitData
);
679 nsIWidget
* parentWidget
= GetParent() ? GetParent()->GetNearestWidget(nsnull
)
681 if (aWidgetInitData
->mWindowType
== eWindowType_popup
) {
682 // Without a parent, we can't make a popup. This can happen
685 return NS_ERROR_FAILURE
;
686 mWindow
->Create(parentWidget
->GetNativeData(NS_NATIVE_WIDGET
), trect
,
687 ::HandleEvent
, dx
, nsnull
, nsnull
, aWidgetInitData
);
689 mWindow
->Create(parentWidget
, trect
,
690 ::HandleEvent
, dx
, nsnull
, nsnull
, aWidgetInitData
);
694 if (aEnableDragDrop
) {
695 mWindow
->EnableDragDrop(PR_TRUE
);
698 // propagate the z-index to the widget.
699 UpdateNativeWidgetZIndexes(v
, FindNonAutoZIndex(v
));
701 // We should tell the widget its size even if we don't create a
702 // native widget. (At the moment, this doesn't really matter,
703 // but we might want it to work at some point.)
704 mWindow
->Resize(trect
.x
, trect
.y
, trect
.width
, trect
.height
,
709 //make sure visibility state is accurate
711 if (aResetVisibility
) {
712 v
->SetVisibility(GetVisibility());
718 void nsView::SetZIndex(PRBool aAuto
, PRInt32 aZIndex
, PRBool aTopMost
)
720 PRBool oldIsAuto
= GetZIndexIsAuto();
721 mVFlags
= (mVFlags
& ~NS_VIEW_FLAG_AUTO_ZINDEX
) | (aAuto
? NS_VIEW_FLAG_AUTO_ZINDEX
: 0);
723 SetTopMost(aTopMost
);
725 if (HasWidget() || !oldIsAuto
|| !aAuto
) {
726 UpdateNativeWidgetZIndexes(this, FindNonAutoZIndex(this));
731 // internal window creation functions
733 nsresult
nsView::LoadWidget(const nsCID
&aClassIID
)
735 ViewWrapper
* wrapper
= new ViewWrapper(this);
737 return NS_ERROR_OUT_OF_MEMORY
;
738 NS_ADDREF(wrapper
); // Will be released in ~nsView
740 nsresult rv
= CallCreateInstance(aClassIID
, &mWindow
);
742 if (NS_SUCCEEDED(rv
)) {
743 // Set the widget's client data
744 mWindow
->SetClientData(wrapper
);
753 void nsIView::List(FILE* out
, PRInt32 aIndent
) const
756 for (i
= aIndent
; --i
>= 0; ) fputs(" ", out
);
757 fprintf(out
, "%p ", (void*)this);
758 if (nsnull
!= mWindow
) {
760 nsRect nonclientBounds
;
762 nsIDeviceContext
*dx
;
763 mViewManager
->GetDeviceContext(dx
);
764 p2t
= (float) dx
->AppUnitsPerDevPixel();
766 mWindow
->GetClientBounds(windowBounds
);
768 mWindow
->GetBounds(nonclientBounds
);
769 nonclientBounds
*= p2t
;
770 nsrefcnt widgetRefCnt
= mWindow
->AddRef() - 1;
773 mWindow
->GetZIndex(&Z
);
774 fprintf(out
, "(widget=%p[%d] z=%d pos={%d,%d,%d,%d}) ",
775 (void*)mWindow
, widgetRefCnt
, Z
,
776 nonclientBounds
.x
, nonclientBounds
.y
,
777 windowBounds
.width
, windowBounds
.height
);
779 nsRect brect
= GetBounds();
780 fprintf(out
, "{%d,%d,%d,%d}",
781 brect
.x
, brect
.y
, brect
.width
, brect
.height
);
782 fprintf(out
, " z=%d vis=%d clientData=%p <\n",
783 mZIndex
, mVis
, mClientData
);
784 for (nsView
* kid
= mFirstChild
; kid
; kid
= kid
->GetNextSibling()) {
785 NS_ASSERTION(kid
->GetParent() == this, "incorrect parent");
786 kid
->List(out
, aIndent
+ 1);
788 for (i
= aIndent
; --i
>= 0; ) fputs(" ", out
);
793 nsPoint
nsIView::GetOffsetTo(const nsIView
* aOther
) const
795 nsPoint
offset(0, 0);
797 for (v
= this; v
!= aOther
&& v
; v
= v
->GetParent()) {
798 offset
+= v
->GetPosition();
802 // Looks like aOther wasn't an ancestor of |this|. So now we have
803 // the root-VM-relative position of |this| in |offset|. Convert back
804 // to the coordinates of aOther
806 offset
-= aOther
->GetPosition();
807 aOther
= aOther
->GetParent();
814 nsIntPoint
nsIView::GetScreenPosition() const
816 nsIntRect
screenRect(0,0,0,0);
817 nsPoint
toWidgetOffset(0,0);
818 nsIWidget
* widget
= GetNearestWidget(&toWidgetOffset
);
820 nsCOMPtr
<nsIDeviceContext
> dx
;
821 mViewManager
->GetDeviceContext(*getter_AddRefs(dx
));
822 PRInt32 p2a
= dx
->AppUnitsPerDevPixel();
823 nsIntRect
ourRect(NSAppUnitsToIntPixels(toWidgetOffset
.x
, p2a
),
824 NSAppUnitsToIntPixels(toWidgetOffset
.y
, p2a
),
827 widget
->WidgetToScreen(ourRect
, screenRect
);
830 return nsIntPoint(screenRect
.x
, screenRect
.y
);
833 nsIWidget
* nsIView::GetNearestWidget(nsPoint
* aOffset
) const
837 for (v
= static_cast<const nsView
*>(this);
838 v
&& !v
->HasWidget(); v
= v
->GetParent()) {
839 pt
+= v
->GetPosition();
845 return static_cast<const nsView
*>(this)->GetViewManager()->GetWidget();
848 // pt is now the offset from v's origin to this's origin
849 // The widget's origin is the top left corner of v's bounds, which may
850 // not coincide with v's origin
852 nsRect vBounds
= v
->GetBounds();
853 *aOffset
= pt
+ v
->GetPosition() - nsPoint(vBounds
.x
, vBounds
.y
) +
854 v
->ViewToWidgetOffset();
856 return v
->GetWidget();
859 PRBool
nsIView::IsRoot() const
861 NS_ASSERTION(mViewManager
!= nsnull
," View manager is null in nsView::IsRoot()");
862 return mViewManager
->GetRootView() == this;
865 PRBool
nsIView::ExternalIsRoot() const
867 return nsIView::IsRoot();
871 nsIView::SetDeletionObserver(nsWeakView
* aDeletionObserver
)
873 if (mDeletionObserver
&& aDeletionObserver
) {
874 aDeletionObserver
->SetPrevious(mDeletionObserver
);
876 mDeletionObserver
= aDeletionObserver
;