reparent the view's descendant widgets when a view is re-inserted into a new view hierarchy position by paginated reflow. b=129034 r=roc+moz sr=kin

This commit is contained in:
kmcclusk%netscape.com 2002-09-12 03:59:15 +00:00
Родитель b61e862689
Коммит d6f51b19b1
7 изменённых файлов: 101 добавлений и 0 удалений

Просмотреть файл

@ -2164,6 +2164,64 @@ NS_IMETHODIMP nsViewManager::GetKeyEventGrabber(nsIView *&aView)
return NS_OK;
}
// Recursively reparent widgets if necessary
void nsViewManager::ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget)
{
PRBool hasWidget;
aView->HasWidget(&hasWidget);
if (hasWidget) {
// Check to see if the parent widget is the
// same as the new parent. If not then reparent
// the widget, otherwise there is nothing more
// to do for the view and its descendants
nsCOMPtr<nsIWidget> widget;
aView->GetWidget(*getter_AddRefs(widget));
nsCOMPtr<nsIWidget> parentWidget;
parentWidget = widget->GetParent();
if (parentWidget.get() != aNewWidget) {
widget->SetParent(aNewWidget);
}
return;
}
// Need to check each of the views children to see
// if they have a widget and reparent it.
nsView* view = NS_STATIC_CAST(nsView*, aView);
nsView *kid = view->GetFirstChild();
while (kid) {
ReparentChildWidgets(kid, aNewWidget);
kid = kid->GetNextSibling();
}
}
// Reparent a view and its descendant views widgets if necessary
void nsViewManager::ReparentWidgets(nsIView* aView, nsIView *aParent)
{
// Quickly determine whether the view has pre-existing children or a
// widget. In most cases the view will not have any pre-existing
// children when this is called. Only in the case
// where a view has been reparented by removing it from
// a reinserting it into a new location in the view hierarchy do we
// have to consider reparenting the existing widgets for the view and
// it's descendants.
nsView* view = NS_STATIC_CAST(nsView*, aView);
PRBool hasWidget;
aView->HasWidget(&hasWidget);
if (hasWidget || view->GetFirstChild()) {
nsCOMPtr<nsIWidget> parentWidget;
GetWidgetForView(aParent, getter_AddRefs(parentWidget));
if (parentWidget) {
ReparentChildWidgets(aView, parentWidget);
return;
}
NS_WARNING("Can not find a widget for the parent view");
}
}
NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIView *aSibling,
PRBool aAfter)
{
@ -2188,6 +2246,7 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV
// insert at end of document order, i.e., before first view
// this is the common case, by far
parent->InsertChild(child, nsnull);
ReparentWidgets(child, parent);
} else {
// insert at beginning of document order, i.e., after last view
nsView *kid = parent->GetFirstChild();
@ -2198,6 +2257,7 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV
}
// prev is last view or null if there are no children
parent->InsertChild(child, prev);
ReparentWidgets(child, parent);
}
} else {
nsView *kid = parent->GetFirstChild();
@ -2212,9 +2272,11 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV
if (aAfter) {
// insert after 'kid' in document order, i.e. before in view order
parent->InsertChild(child, prev);
ReparentWidgets(child, parent);
} else {
// insert before 'kid' in document order, i.e. after in view order
parent->InsertChild(child, kid);
ReparentWidgets(child, parent);
}
}
#else // don't keep consistent document order, but order things by z-index instead
@ -2233,6 +2295,7 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV
}
parent->InsertChild(child, prev);
ReparentWidgets(child, parent);
#endif
UpdateTransCnt(nsnull, child);

Просмотреть файл

@ -244,6 +244,8 @@ protected:
void ProcessPendingUpdates(nsView *aView);
private:
void ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget);
void ReparentWidgets(nsIView* aView, nsIView *aParent);
nsIRenderingContext *CreateRenderingContext(nsView &aView);
void AddRectToDirtyRegion(nsView* aView, const nsRect &aRect) const;
void UpdateTransCnt(nsView *oldview, nsView *newview);

Просмотреть файл

@ -320,6 +320,17 @@ class nsIWidget : public nsISupports {
NS_IMETHOD Destroy(void) = 0;
/**
* Reparent a widget
*
* Change the widgets parent
*
* @param aNewParent new parent
*/
NS_IMETHOD SetParent(nsIWidget* aNewParent) = 0;
/**
* Return the parent Widget of this Widget or nsnull if this is a
* top level window

Просмотреть файл

@ -1622,6 +1622,18 @@ NS_METHOD nsWindow::Destroy()
return NS_OK;
}
NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
{
if (aNewParent) {
HWND newParent = (HWND)aNewParent->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(newParent, "Parent widget has a null native window handle");
::SetParent(mWnd, newParent);
return NS_OK;
}
NS_WARNING("Null aNewParent passed to SetParent");
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//

Просмотреть файл

@ -295,6 +295,7 @@ public:
nsNativeWidget aNativeParent = nsnull);
NS_IMETHOD Destroy();
NS_IMETHOD SetParent(nsIWidget *aNewParent);
virtual nsIWidget* GetParent(void);
NS_IMETHOD Show(PRBool bState);
NS_IMETHOD IsVisible(PRBool & aState);

Просмотреть файл

@ -252,6 +252,17 @@ NS_METHOD nsBaseWidget::Destroy()
}
//-------------------------------------------------------------------------
//
// Set this nsBaseWidget's parent
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//-------------------------------------------------------------------------
//
// Get this nsBaseWidget parent

Просмотреть файл

@ -78,6 +78,7 @@ public:
NS_IMETHOD GetClientData(void*& aClientData);
NS_IMETHOD SetClientData(void* aClientData);
NS_IMETHOD Destroy();
NS_IMETHOD SetParent(nsIWidget* aNewParent);
virtual nsIWidget* GetParent(void);
virtual nsIEnumerator* GetChildren();
virtual void AddChild(nsIWidget* aChild);