зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
b61e862689
Коммит
d6f51b19b1
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче