зеркало из https://github.com/mozilla/gecko-dev.git
Making desperate attempt to reland with a couple crash-proofing changes. Bug
243724, r+sr=roc
This commit is contained in:
Родитель
59427ab6f1
Коммит
f8f45bc910
|
@ -1163,46 +1163,34 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
|
||||
if (!children) {
|
||||
return;
|
||||
}
|
||||
|
||||
children->First();
|
||||
do {
|
||||
nsCOMPtr<nsISupports> child;
|
||||
if (!NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> childWidget = do_QueryInterface(child);
|
||||
if (childWidget) {
|
||||
PRBool widgetVisible;
|
||||
childWidget->IsVisible(widgetVisible);
|
||||
if (widgetVisible) {
|
||||
nsView* view = nsView::GetViewFor(childWidget);
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kShow
|
||||
&& !view->GetFloating()) {
|
||||
nsRect bounds = view->GetBounds();
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
nsView* viewParent = view->GetParent();
|
||||
for (nsIWidget* childWidget = widget->GetFirstChild();
|
||||
childWidget;
|
||||
childWidget = childWidget->GetNextSibling()) {
|
||||
PRBool widgetVisible;
|
||||
childWidget->IsVisible(widgetVisible);
|
||||
if (widgetVisible) {
|
||||
nsView* view = nsView::GetViewFor(childWidget);
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kShow
|
||||
&& !view->GetFloating()) {
|
||||
nsRect bounds = view->GetBounds();
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
nsView* viewParent = view->GetParent();
|
||||
|
||||
while (viewParent && viewParent != aRootView) {
|
||||
viewParent->ConvertToParentCoords(&bounds.x, &bounds.y);
|
||||
viewParent = viewParent->GetParent();
|
||||
}
|
||||
while (viewParent && viewParent != aRootView) {
|
||||
viewParent->ConvertToParentCoords(&bounds.x, &bounds.y);
|
||||
viewParent = viewParent->GetParent();
|
||||
}
|
||||
|
||||
// maybe we couldn't get the view into the coordinate
|
||||
// system of aRootView (maybe it's not a descendant
|
||||
// view of aRootView?); if so, don't use it
|
||||
if (viewParent) {
|
||||
aRgn.Or(aRgn, bounds);
|
||||
}
|
||||
// maybe we couldn't get the view into the coordinate
|
||||
// system of aRootView (maybe it's not a descendant
|
||||
// view of aRootView?); if so, don't use it
|
||||
if (viewParent) {
|
||||
aRgn.Or(aRgn, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsViewManager::BuildRenderingDisplayList(nsIView* aRootView,
|
||||
|
@ -1628,32 +1616,24 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag
|
|||
}
|
||||
|
||||
PRBool childCovers = PR_FALSE;
|
||||
nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
|
||||
if (children) {
|
||||
children->First();
|
||||
do {
|
||||
nsCOMPtr<nsISupports> child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
|
||||
nsCOMPtr<nsIWidget> childWidget = do_QueryInterface(child);
|
||||
if (childWidget) {
|
||||
nsView* view = nsView::GetViewFor(childWidget);
|
||||
if (nsnull != view) {
|
||||
nsRect damage = bounds;
|
||||
nsView* vp = view;
|
||||
while (vp != aWidgetView && nsnull != vp) {
|
||||
vp->ConvertFromParentCoords(&damage.x, &damage.y);
|
||||
vp = vp->GetParent();
|
||||
}
|
||||
for (nsIWidget* childWidget = widget->GetFirstChild();
|
||||
childWidget;
|
||||
childWidget = childWidget->GetNextSibling()) {
|
||||
nsView* view = nsView::GetViewFor(childWidget);
|
||||
if (nsnull != view) {
|
||||
nsRect damage = bounds;
|
||||
nsView* vp = view;
|
||||
while (vp != aWidgetView && nsnull != vp) {
|
||||
vp->ConvertFromParentCoords(&damage.x, &damage.y);
|
||||
vp = vp->GetParent();
|
||||
}
|
||||
|
||||
if (nsnull != vp) { // vp == nsnull means it's in a different hierarchy so we ignore it
|
||||
if (UpdateWidgetArea(view, damage, aIgnoreWidgetView)) {
|
||||
childCovers = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nsnull != vp) { // vp == nsnull means it's in a different hierarchy so we ignore it
|
||||
if (UpdateWidgetArea(view, damage, aIgnoreWidgetView)) {
|
||||
childCovers = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!childCovers) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "prthread.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// forward declarations
|
||||
class nsIAppShell;
|
||||
|
@ -256,6 +257,12 @@ class nsIWidget : public nsISupports {
|
|||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
|
||||
|
||||
nsIWidget()
|
||||
: mLastChild(nsnull)
|
||||
, mPrevSibling(nsnull)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Create and initialize a widget.
|
||||
*
|
||||
|
@ -357,13 +364,48 @@ class nsIWidget : public nsISupports {
|
|||
virtual nsIWidget* GetParent(void) = 0;
|
||||
|
||||
/**
|
||||
* Return an nsEnumerator over the children of this widget.
|
||||
*
|
||||
* @return an enumerator over the list of children or nsnull if it does not
|
||||
* have any children
|
||||
*
|
||||
* Return the first child of this widget. Will return null if
|
||||
* there are no children.
|
||||
*/
|
||||
virtual nsIEnumerator* GetChildren(void) = 0;
|
||||
nsIWidget* GetFirstChild() const {
|
||||
return mFirstChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last child of this widget. Will return null if
|
||||
* there are no children.
|
||||
*/
|
||||
nsIWidget* GetLastChild() const {
|
||||
return mLastChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next sibling of this widget
|
||||
*/
|
||||
nsIWidget* GetNextSibling() const {
|
||||
return mNextSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the next sibling of this widget
|
||||
*/
|
||||
void SetNextSibling(nsIWidget* aSibling) {
|
||||
mNextSibling = aSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the previous sibling of this widget
|
||||
*/
|
||||
nsIWidget* GetPrevSibling() const {
|
||||
return mPrevSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the previous sibling of this widget
|
||||
*/
|
||||
void SetPrevSibling(nsIWidget* aSibling) {
|
||||
mPrevSibling = aSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide this widget
|
||||
|
@ -975,6 +1017,18 @@ class nsIWidget : public nsISupports {
|
|||
*/
|
||||
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
// keep the list of children. We also keep track of our siblings.
|
||||
// The ownership model is as follows: parent holds a strong ref to
|
||||
// the first element of the list, and each element holds a strong
|
||||
// ref to the next element in the list. The prevsibling and
|
||||
// lastchild pointers are weak, which is fine as long as they are
|
||||
// maintained properly.
|
||||
nsCOMPtr<nsIWidget> mFirstChild;
|
||||
nsIWidget* mLastChild;
|
||||
nsCOMPtr<nsIWidget> mNextSibling;
|
||||
nsIWidget* mPrevSibling;
|
||||
};
|
||||
|
||||
#endif // nsIWidget_h__
|
||||
|
|
|
@ -1543,24 +1543,15 @@ NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
|||
}
|
||||
|
||||
// Scroll the children (even if the widget is not visible)
|
||||
nsCOMPtr<nsIEnumerator> children(getter_AddRefs(GetChildren()));
|
||||
if ( children ) {
|
||||
children->First();
|
||||
do {
|
||||
nsCOMPtr<nsISupports> child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
|
||||
nsCOMPtr<nsIWidget> widget = do_QueryInterface(child);
|
||||
|
||||
// We use resize rather than move since it gives us control
|
||||
// over repainting. In the case of blitting, Quickdraw views
|
||||
// draw their child widgets on the blit, so we can scroll
|
||||
// like a bat out of hell by not wasting time invalidating
|
||||
// the widgets, since it's completely unnecessary to do so.
|
||||
nsRect bounds;
|
||||
widget->GetBounds(bounds);
|
||||
widget->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE);
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
// We use resize rather than move since it gives us control
|
||||
// over repainting. In the case of blitting, Quickdraw views
|
||||
// draw their child widgets on the blit, so we can scroll
|
||||
// like a bat out of hell by not wasting time invalidating
|
||||
// the widgets, since it's completely unnecessary to do so.
|
||||
nsRect bounds;
|
||||
kid->GetBounds(bounds);
|
||||
kid->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE);
|
||||
}
|
||||
|
||||
if (mVisible)
|
||||
|
|
|
@ -607,10 +607,8 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|||
gtk_widget_set_usize(mWidget, aWidth, aHeight);
|
||||
|
||||
ResetInternalVisibility();
|
||||
PRInt32 childCount = mChildren.Count();
|
||||
PRInt32 index;
|
||||
for (index = 0; index < childCount; index++) {
|
||||
NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility();
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2243,19 +2241,8 @@ void
|
|||
nsWidget::ThemeChanged()
|
||||
{
|
||||
// Dispatch a NS_THEMECHANGED event for each of our children, recursively
|
||||
nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) {
|
||||
|
||||
nsWidget* child = NS_REINTERPRET_CAST(nsWidget*, isupp.get());
|
||||
child->ThemeChanged();
|
||||
|
||||
if (NS_FAILED(children->Next())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
NS_STATIC_CAST(nsWidget*, kid)->ThemeChanged();
|
||||
}
|
||||
|
||||
DispatchStandardEvent(NS_THEMECHANGED);
|
||||
|
|
|
@ -894,26 +894,8 @@ NS_IMETHODIMP nsWindow::Update(void)
|
|||
// The view manager also expects us to force our
|
||||
// children to update too!
|
||||
|
||||
nsCOMPtr<nsIEnumerator> children;
|
||||
|
||||
children = dont_AddRef(GetChildren());
|
||||
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
|
||||
nsCOMPtr<nsIWidget> child;
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) {
|
||||
|
||||
child = do_QueryInterface(isupp);
|
||||
|
||||
if (child) {
|
||||
child->Update();
|
||||
}
|
||||
|
||||
if (NS_FAILED(children->Next())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
kid->Update();
|
||||
}
|
||||
|
||||
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
|
||||
|
@ -2225,26 +2207,14 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
|||
}
|
||||
|
||||
// Update bounds on our child windows
|
||||
nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
nsCOMPtr<nsIWidget> child;
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp)) && isupp)) {
|
||||
child = do_QueryInterface(isupp);
|
||||
|
||||
if (child) {
|
||||
nsRect bounds;
|
||||
child->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, child.get()));
|
||||
childWidget->SetBounds(bounds);
|
||||
childWidget->ResetInternalVisibility();
|
||||
}
|
||||
|
||||
if (NS_FAILED(children->Next()))
|
||||
break;
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
nsRect bounds;
|
||||
kid->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, kid);
|
||||
childWidget->SetBounds(bounds);
|
||||
childWidget->ResetInternalVisibility();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2724,10 +2694,8 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|||
mBounds.height = aHeight;
|
||||
|
||||
ResetInternalVisibility();
|
||||
PRInt32 childCount = mChildren.Count();
|
||||
PRInt32 index;
|
||||
for (index = 0; index < childCount; index++) {
|
||||
NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility();
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility();
|
||||
}
|
||||
|
||||
// code to keep the window from showing before it has been moved or resized
|
||||
|
|
|
@ -346,21 +346,13 @@ nsWindow::Destroy(void)
|
|||
|
||||
NativeShow(PR_FALSE);
|
||||
|
||||
// walk the list of children and call destroy on them.
|
||||
nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
nsCOMPtr<nsIWidget> child;
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))
|
||||
&& isupp)) {
|
||||
child = do_QueryInterface(isupp);
|
||||
if (child) {
|
||||
child->Destroy();
|
||||
}
|
||||
|
||||
if (NS_FAILED(children->Next()))
|
||||
break;
|
||||
}
|
||||
// walk the list of children and call destroy on them. Have to be
|
||||
// careful, though -- calling destroy on a kid may actually remove
|
||||
// it from our child list, losing its sibling links.
|
||||
for (nsIWidget* kid = mFirstChild; kid; ) {
|
||||
nsIWidget* next = kid->GetNextSibling();
|
||||
kid->Destroy();
|
||||
kid = next;
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
|
@ -835,25 +827,12 @@ nsWindow::Scroll(PRInt32 aDx,
|
|||
moz_drawingarea_scroll(mDrawingarea, aDx, aDy);
|
||||
|
||||
// Update bounds on our child windows
|
||||
nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
nsCOMPtr<nsIWidget> child;
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))
|
||||
&& isupp)) {
|
||||
child = do_QueryInterface(isupp);
|
||||
if (child) {
|
||||
nsRect bounds;
|
||||
child->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
NS_STATIC_CAST(nsBaseWidget*,
|
||||
(nsIWidget*)child)->SetBounds(bounds);
|
||||
}
|
||||
|
||||
if (NS_FAILED(children->Next()))
|
||||
break;
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
nsRect bounds;
|
||||
kid->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
NS_STATIC_CAST(nsBaseWidget*, kid)->SetBounds(bounds);
|
||||
}
|
||||
|
||||
// Process all updates so that everything is drawn.
|
||||
|
|
|
@ -97,36 +97,35 @@ void nsChildWindow::CalcWindowRegions()
|
|||
// clip the siblings out of the window region and visRegion
|
||||
if (mClipSiblings && mParent && !mIsTopWidgetWindow) {
|
||||
// need to walk the siblings backwards, to get clipping right.
|
||||
nsCOMPtr<nsIBidirectionalEnumerator> siblings = getter_AddRefs((nsIBidirectionalEnumerator*)mParent->GetChildren());
|
||||
if (siblings && NS_SUCCEEDED(siblings->Last())) {
|
||||
StRegionFromPool siblingRgn;
|
||||
if (siblingRgn == nsnull)
|
||||
return;
|
||||
do {
|
||||
// when we reach ourself, stop clipping.
|
||||
nsCOMPtr<nsISupports> item;
|
||||
if (NS_FAILED(siblings->CurrentItem(getter_AddRefs(item))) ||
|
||||
item == NS_STATIC_CAST(nsIWidget*, this))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIWidget> sibling(do_QueryInterface(item));
|
||||
PRBool visible;
|
||||
sibling->IsVisible(visible);
|
||||
if (visible) { // don't clip if not visible.
|
||||
// get sibling's bounds in parent's coordinate system.
|
||||
nsRect siblingRect;
|
||||
sibling->GetBounds(siblingRect);
|
||||
|
||||
// transform from parent's coordinate system to widget coordinates.
|
||||
siblingRect.MoveBy(-mBounds.x, -mBounds.y);
|
||||
nsIWidget* sibling = mParent->GetLastChild();
|
||||
if (!sibling)
|
||||
return;
|
||||
|
||||
Rect macRect;
|
||||
::SetRect(&macRect, siblingRect.x, siblingRect.y, siblingRect.XMost(), siblingRect.YMost());
|
||||
::RectRgn(siblingRgn, &macRect);
|
||||
::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion);
|
||||
::DiffRgn(mVisRegion, siblingRgn, mVisRegion);
|
||||
}
|
||||
} while (NS_SUCCEEDED(siblings->Prev()));
|
||||
}
|
||||
StRegionFromPool siblingRgn;
|
||||
if (siblingRgn == nsnull)
|
||||
return;
|
||||
|
||||
do {
|
||||
if (sibling == NS_STATIC_CAST(nsIWidget*, this))
|
||||
break;
|
||||
|
||||
PRBool visible;
|
||||
sibling->IsVisible(visible);
|
||||
if (visible) { // don't clip if not visible.
|
||||
// get sibling's bounds in parent's coordinate system.
|
||||
nsRect siblingRect;
|
||||
sibling->GetBounds(siblingRect);
|
||||
|
||||
// transform from parent's coordinate system to widget coordinates.
|
||||
siblingRect.MoveBy(-mBounds.x, -mBounds.y);
|
||||
|
||||
Rect macRect;
|
||||
::SetRect(&macRect, siblingRect.x, siblingRect.y, siblingRect.XMost(), siblingRect.YMost());
|
||||
::RectRgn(siblingRgn, &macRect);
|
||||
::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion);
|
||||
::DiffRgn(mVisRegion, siblingRgn, mVisRegion);
|
||||
}
|
||||
sibling = sibling->GetPrevSibling();
|
||||
} while (sibling);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,21 +298,9 @@ nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this), nsIKBStateContro
|
|||
nsWindow::~nsWindow()
|
||||
{
|
||||
// notify the children that we're gone
|
||||
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
|
||||
if (children)
|
||||
{
|
||||
children->First();
|
||||
do
|
||||
{
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||||
{
|
||||
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
|
||||
NS_RELEASE(child);
|
||||
|
||||
childWindow->mParent = nsnull;
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
|
||||
childWindow->mParent = nsnull;
|
||||
}
|
||||
|
||||
mDestructorCalled = PR_TRUE;
|
||||
|
@ -1737,36 +1725,27 @@ void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
|
|||
// and it does for the most part. However; certain cases, such as overlapping
|
||||
// areas that are handled by different view managers, don't properly clip siblings.
|
||||
#ifdef FRONT_TO_BACK
|
||||
# define FIRST_CHILD(children) (children->Last())
|
||||
# define NEXT_CHILD(children) (children->Prev())
|
||||
# define FIRST_CHILD() (mLastChild)
|
||||
# define NEXT_CHILD(child) ((child)->GetPrevSibling())
|
||||
#else
|
||||
# define FIRST_CHILD(children) (children->First())
|
||||
# define NEXT_CHILD(children) (children->Next())
|
||||
# define FIRST_CHILD() (mFirstChild)
|
||||
# define NEXT_CHILD(child) ((child)->GetNextSibling())
|
||||
#endif
|
||||
|
||||
// recursively draw the children
|
||||
nsCOMPtr<nsIBidirectionalEnumerator> children(getter_AddRefs((nsIBidirectionalEnumerator*)GetChildren()));
|
||||
if (children) {
|
||||
FIRST_CHILD(children);
|
||||
do {
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child))) {
|
||||
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
|
||||
for (nsIWidget* kid = FIRST_CHILD(); kid; kid = NEXT_CHILD(kid)) {
|
||||
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
|
||||
|
||||
nsRect childBounds;
|
||||
childWindow->GetBounds(childBounds);
|
||||
nsRect childBounds;
|
||||
childWindow->GetBounds(childBounds);
|
||||
|
||||
// redraw only the intersection of the child rect and the update rect
|
||||
nsRect intersection;
|
||||
if (intersection.IntersectRect(aRect, childBounds))
|
||||
{
|
||||
intersection.MoveBy(-childBounds.x, -childBounds.y);
|
||||
childWindow->UpdateWidget(intersection, aContext);
|
||||
}
|
||||
|
||||
NS_RELEASE(child);
|
||||
}
|
||||
} while (NS_SUCCEEDED(NEXT_CHILD(children)));
|
||||
// redraw only the intersection of the child rect and the update rect
|
||||
nsRect intersection;
|
||||
if (intersection.IntersectRect(aRect, childBounds))
|
||||
{
|
||||
intersection.MoveBy(-childBounds.x, -childBounds.y);
|
||||
childWindow->UpdateWidget(intersection, aContext);
|
||||
}
|
||||
}
|
||||
|
||||
#undef FIRST_CHILD
|
||||
|
@ -1956,25 +1935,14 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
|||
scrollChildren:
|
||||
//--------
|
||||
// Scroll the children
|
||||
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
|
||||
if (children)
|
||||
{
|
||||
children->First();
|
||||
do
|
||||
{
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||||
{
|
||||
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
|
||||
NS_RELEASE(child);
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
|
||||
|
||||
nsRect bounds;
|
||||
childWindow->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
childWindow->SetBounds(bounds);
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
nsRect bounds;
|
||||
childWindow->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
childWindow->SetBounds(bounds);
|
||||
}
|
||||
|
||||
// recalculate the window regions
|
||||
|
@ -2214,33 +2182,29 @@ void nsWindow::CalcWindowRegions()
|
|||
::CopyRgn(mWindowRegion, mVisRegion);
|
||||
|
||||
// clip the children out of the visRegion
|
||||
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
|
||||
if (children)
|
||||
if (mFirstChild)
|
||||
{
|
||||
StRegionFromPool childRgn;
|
||||
if (childRgn != nsnull) {
|
||||
children->First();
|
||||
nsIWidget* child = mFirstChild;
|
||||
do
|
||||
{
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||||
{
|
||||
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
|
||||
NS_RELEASE(child);
|
||||
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, child);
|
||||
|
||||
PRBool visible;
|
||||
childWindow->IsVisible(visible);
|
||||
if (visible) {
|
||||
nsRect childRect;
|
||||
childWindow->GetBounds(childRect);
|
||||
PRBool visible;
|
||||
childWindow->IsVisible(visible);
|
||||
if (visible) {
|
||||
nsRect childRect;
|
||||
childWindow->GetBounds(childRect);
|
||||
|
||||
Rect macRect;
|
||||
::SetRect(&macRect, childRect.x, childRect.y, childRect.XMost(), childRect.YMost());
|
||||
::RectRgn(childRgn, &macRect);
|
||||
::DiffRgn(mVisRegion, childRgn, mVisRegion);
|
||||
}
|
||||
Rect macRect;
|
||||
::SetRect(&macRect, childRect.x, childRect.y, childRect.XMost(), childRect.YMost());
|
||||
::RectRgn(childRgn, &macRect);
|
||||
::DiffRgn(mVisRegion, childRgn, mVisRegion);
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
|
||||
child = child->GetNextSibling();
|
||||
} while (child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2342,29 +2306,16 @@ nsWindow* nsWindow::FindWidgetHit(Point aThePoint)
|
|||
|
||||
nsWindow* widgetHit = this;
|
||||
|
||||
nsCOMPtr<nsIEnumerator> normalEnum ( getter_AddRefs(GetChildren()) );
|
||||
nsCOMPtr<nsIBidirectionalEnumerator> children ( do_QueryInterface(normalEnum) );
|
||||
if (children)
|
||||
{
|
||||
// traverse through all the nsWindows to find out who got hit, lowest level of course
|
||||
children->Last();
|
||||
do
|
||||
// traverse through all the nsWindows to find out who got hit, lowest level of course
|
||||
for (nsIWidget* kid = mLastChild; kid; kid = kid->GetPrevSibling()) {
|
||||
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
|
||||
|
||||
nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint);
|
||||
if (deeperHit)
|
||||
{
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||||
{
|
||||
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
|
||||
NS_RELEASE(child);
|
||||
|
||||
nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint);
|
||||
if (deeperHit)
|
||||
{
|
||||
widgetHit = deeperHit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
widgetHit = deeperHit;
|
||||
break;
|
||||
}
|
||||
while (NS_SUCCEEDED(children->Prev()));
|
||||
}
|
||||
|
||||
return widgetHit;
|
||||
|
|
|
@ -605,26 +605,8 @@ NS_IMETHODIMP nsWindow::Update(void)
|
|||
// The view manager also expects us to force our
|
||||
// children to update too!
|
||||
|
||||
nsCOMPtr<nsIEnumerator> children;
|
||||
|
||||
children = dont_AddRef(GetChildren());
|
||||
|
||||
if (children) {
|
||||
nsCOMPtr<nsISupports> isupp;
|
||||
|
||||
nsCOMPtr<nsIWidget> child;
|
||||
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) {
|
||||
|
||||
child = do_QueryInterface(isupp);
|
||||
|
||||
if (child) {
|
||||
child->Update();
|
||||
}
|
||||
|
||||
if (NS_FAILED(children->Next())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
kid->Update();
|
||||
}
|
||||
|
||||
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
|
||||
|
@ -695,25 +677,13 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
|||
|
||||
//--------
|
||||
// Scroll the children
|
||||
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
|
||||
if (children)
|
||||
{
|
||||
children->First();
|
||||
do
|
||||
{
|
||||
nsISupports* child;
|
||||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||||
{
|
||||
nsWindow *childWindow = NS_STATIC_CAST(nsWindow*, NS_STATIC_CAST(nsIWidget*, child));
|
||||
NS_RELEASE(child);
|
||||
|
||||
nsRect bounds;
|
||||
childWindow->GetRequestedBounds(bounds);
|
||||
childWindow->Move(bounds.x + aDx, bounds.y + aDy);
|
||||
Invalidate(bounds, PR_TRUE);
|
||||
}
|
||||
} while (NS_SUCCEEDED(children->Next()));
|
||||
}
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
childWindow = NS_STATIC_CAST(nsWindow*, kid);
|
||||
nsRect bounds;
|
||||
childWindow->GetRequestedBounds(bounds);
|
||||
childWindow->Move(bounds.x + aDx, bounds.y + aDy);
|
||||
Invalidate(bounds, PR_TRUE);
|
||||
}
|
||||
|
||||
// If we are obscurred by another window we have to update those areas
|
||||
// which were not copied with the XCopyArea function.
|
||||
|
|
|
@ -62,9 +62,6 @@ static PRInt32 gNumWidgets;
|
|||
// nsBaseWidget
|
||||
NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget)
|
||||
|
||||
// nsBaseWidget::Enumerator
|
||||
NS_IMPL_ISUPPORTS2(nsBaseWidget::Enumerator, nsIBidirectionalEnumerator, nsIEnumerator)
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -241,6 +238,9 @@ NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsBaseWidget::Destroy()
|
||||
{
|
||||
// Just in case our parent is the only ref to us
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
|
||||
// disconnect from the parent
|
||||
nsIWidget *parent = GetParent();
|
||||
if (parent) {
|
||||
|
@ -277,23 +277,6 @@ nsIWidget* nsBaseWidget::GetParent(void)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this nsBaseWidget's list of children
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsIEnumerator* nsBaseWidget::GetChildren()
|
||||
{
|
||||
nsIEnumerator* children = nsnull;
|
||||
|
||||
if (mChildren.Count()) {
|
||||
children = new Enumerator(*this);
|
||||
NS_IF_ADDREF(children);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Add a child to the list of children
|
||||
|
@ -301,7 +284,19 @@ nsIEnumerator* nsBaseWidget::GetChildren()
|
|||
//-------------------------------------------------------------------------
|
||||
void nsBaseWidget::AddChild(nsIWidget* aChild)
|
||||
{
|
||||
mChildren.AppendObject(aChild);
|
||||
NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
|
||||
"aChild not properly removed from its old child list");
|
||||
|
||||
if (!mFirstChild) {
|
||||
mFirstChild = mLastChild = aChild;
|
||||
} else {
|
||||
// append to the list
|
||||
NS_ASSERTION(mLastChild, "Bogus state");
|
||||
NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state");
|
||||
mLastChild->SetNextSibling(aChild);
|
||||
aChild->SetPrevSibling(mLastChild);
|
||||
mLastChild = aChild;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,7 +307,29 @@ void nsBaseWidget::AddChild(nsIWidget* aChild)
|
|||
//-------------------------------------------------------------------------
|
||||
void nsBaseWidget::RemoveChild(nsIWidget* aChild)
|
||||
{
|
||||
mChildren.RemoveObject(aChild);
|
||||
NS_ASSERTION(aChild->GetParent() == NS_STATIC_CAST(nsIWidget*, this),
|
||||
"Not one of our kids!");
|
||||
|
||||
if (mLastChild == aChild) {
|
||||
mLastChild = mLastChild->GetPrevSibling();
|
||||
}
|
||||
if (mFirstChild == aChild) {
|
||||
mFirstChild = mFirstChild->GetNextSibling();
|
||||
}
|
||||
|
||||
// Now remove from the list. Make sure that we pass ownership of the tail
|
||||
// of the list correctly before we have aChild let go of it.
|
||||
nsIWidget* prev = aChild->GetPrevSibling();
|
||||
nsIWidget* next = aChild->GetNextSibling();
|
||||
if (prev) {
|
||||
prev->SetNextSibling(next);
|
||||
}
|
||||
if (next) {
|
||||
next->SetPrevSibling(prev);
|
||||
}
|
||||
|
||||
aChild->SetNextSibling(nsnull);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
}
|
||||
|
||||
|
||||
|
@ -328,26 +345,36 @@ NS_IMETHODIMP nsBaseWidget::SetZIndex(PRInt32 aZIndex)
|
|||
// reorder this child in its parent's list.
|
||||
nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent());
|
||||
if (parent) {
|
||||
parent->mChildren.RemoveObject(this);
|
||||
PRInt32 childCount = parent->mChildren.Count();
|
||||
PRInt32 index;
|
||||
// XXXbz would a binary search for the right insertion point be
|
||||
// better? How long does this list get?
|
||||
for (index = 0; index < childCount; index++) {
|
||||
nsIWidget* childWidget = parent->mChildren[index];
|
||||
parent->RemoveChild(this);
|
||||
// Scope sib outside the for loop so we can check it afterward
|
||||
nsIWidget* sib = parent->GetFirstChild();
|
||||
for ( ; sib; sib = sib->GetNextSibling()) {
|
||||
PRInt32 childZIndex;
|
||||
if (NS_SUCCEEDED(childWidget->GetZIndex(&childZIndex))) {
|
||||
if (NS_SUCCEEDED(sib->GetZIndex(&childZIndex))) {
|
||||
if (aZIndex < childZIndex) {
|
||||
parent->mChildren.InsertObjectAt(this, index);
|
||||
PlaceBehind(eZPlacementBelow, childWidget, PR_FALSE);
|
||||
// Insert ourselves before sib
|
||||
nsIWidget* prev = sib->GetPrevSibling();
|
||||
mNextSibling = sib;
|
||||
mPrevSibling = prev;
|
||||
sib->SetPrevSibling(this);
|
||||
if (prev) {
|
||||
prev->SetNextSibling(this);
|
||||
} else {
|
||||
NS_ASSERTION(sib == parent->mFirstChild, "Broken child list");
|
||||
// We've taken ownership of sib, so it's safe to have parent let
|
||||
// go of it
|
||||
parent->mFirstChild = this;
|
||||
}
|
||||
PlaceBehind(eZPlacementBelow, sib, PR_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// were we added to the list?
|
||||
if (index == childCount) {
|
||||
parent->mChildren.AppendObject(this);
|
||||
if (!sib) {
|
||||
parent->AddChild(this);
|
||||
}
|
||||
|
||||
NS_RELEASE(parent);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1275,131 +1302,3 @@ nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut,
|
|||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
nsBaseWidget::Enumerator::Enumerator(nsBaseWidget & inParent)
|
||||
: mCurrentPosition(0), mParent(inParent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsBaseWidget::Enumerator::~Enumerator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//enumerator interfaces
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::Next()
|
||||
{
|
||||
if (mCurrentPosition < mParent.mChildren.Count() - 1 )
|
||||
mCurrentPosition ++;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::Prev()
|
||||
{
|
||||
if (mCurrentPosition > 0 )
|
||||
mCurrentPosition --;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ( mCurrentPosition < mParent.mChildren.Count() )
|
||||
NS_IF_ADDREF(*aItem = mParent.mChildren[mCurrentPosition]);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::First()
|
||||
{
|
||||
if ( mParent.mChildren.Count() ) {
|
||||
mCurrentPosition = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::Last()
|
||||
{
|
||||
PRInt32 itemCount = mParent.mChildren.Count();
|
||||
if ( itemCount ) {
|
||||
mCurrentPosition = itemCount - 1;
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::Enumerator::IsDone()
|
||||
{
|
||||
PRInt32 itemCount = mParent.mChildren.Count();
|
||||
|
||||
if ((mCurrentPosition == itemCount-1) || (itemCount == 0) ){ //empty lists always return done
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
return NS_ENUMERATOR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include "nsRect.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIMouseListener.h"
|
||||
#include "nsIEventListener.h"
|
||||
#include "nsIMenuListener.h"
|
||||
|
@ -47,7 +46,6 @@
|
|||
#include "nsIAppShell.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
|
@ -80,7 +78,6 @@ public:
|
|||
NS_IMETHOD Destroy();
|
||||
NS_IMETHOD SetParent(nsIWidget* aNewParent);
|
||||
virtual nsIWidget* GetParent(void);
|
||||
virtual nsIEnumerator* GetChildren();
|
||||
virtual void AddChild(nsIWidget* aChild);
|
||||
virtual void RemoveChild(nsIWidget* aChild);
|
||||
|
||||
|
@ -175,26 +172,7 @@ protected:
|
|||
nsRect* mOriginalBounds;
|
||||
PRInt32 mZIndex;
|
||||
nsSizeMode mSizeMode;
|
||||
|
||||
// keep the list of children
|
||||
nsCOMArray<nsIWidget> mChildren;
|
||||
|
||||
class Enumerator : public nsIBidirectionalEnumerator {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
Enumerator(nsBaseWidget & inParent);
|
||||
virtual ~Enumerator();
|
||||
|
||||
NS_DECL_NSIENUMERATOR
|
||||
NS_DECL_NSIBIDIRECTIONALENUMERATOR
|
||||
|
||||
private:
|
||||
PRInt32 mCurrentPosition;
|
||||
nsBaseWidget& mParent;
|
||||
};
|
||||
friend class Enumerator;
|
||||
|
||||
// Enumeration of the methods which are accessable on the "main GUI thread"
|
||||
// via the CallMethod(...) mechanism...
|
||||
// see nsSwitchToUIThread
|
||||
|
|
Загрузка…
Ссылка в новой задаче