Bug 90268: Part 1, improve support for re-parenting native widgets. r=roc r=karlt

This commit is contained in:
Josh Aas 2011-11-21 15:15:38 -05:00
parent abda0e0ec9
commit a5615e40a2
5 changed files with 52 additions and 18 deletions

View File

@ -118,8 +118,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0x32966f95, 0x89e0, 0x447a, \
{ 0x91, 0x8d, 0x58, 0x53, 0xd6, 0x99, 0x4a, 0x72 } }
{ 0xEAAF1019, 0x0CD8, 0x4DD8, \
{ 0xBE, 0xB9, 0x8D, 0x8D, 0xEB, 0x52, 0xFC, 0xF6 } }
/*
* Window shadow styles
@ -356,6 +356,14 @@ class nsIWidget : public nsISupports {
nsWidgetInitData *aInitData = nsnull,
bool aForceUseIWidgetParent = false) = 0;
/**
* Set the event callback for a widget. If a device context is not
* provided then the existing device context will remain, it will
* not be nulled out.
*/
NS_IMETHOD SetEventCallback(EVENT_CALLBACK aEventFunction,
nsDeviceContext *aContext) = 0;
/**
* Attach to a top level widget.
*
@ -398,7 +406,7 @@ class nsIWidget : public nsISupports {
/**
* Reparent a widget
*
* Change the widgets parent
* Change the widget's parent. Null parents are allowed.
*
* @param aNewParent new parent
*/

View File

@ -705,24 +705,28 @@ nsChildView::SetParent(nsIWidget* aNewParent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG(aNewParent);
if (mOnDestroyCalled)
return NS_OK;
// make sure we stay alive
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
// remove us from our existing parent
if (mParentWidget)
if (mParentWidget) {
mParentWidget->RemoveChild(this);
}
nsresult rv = ReparentNativeWidget(aNewParent);
if (NS_SUCCEEDED(rv))
mParentWidget = aNewParent;
if (aNewParent) {
ReparentNativeWidget(aNewParent);
} else {
[mView removeFromSuperview];
mParentView = nil;
}
mParentWidget = aNewParent;
if (mParentWidget) {
mParentWidget->AddChild(this);
}
// add us to the new parent
mParentWidget->AddChild(this);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@ -744,7 +748,7 @@ nsChildView::ReparentNativeWidget(nsIWidget* aNewParent)
// we hold a ref to mView, so this is safe
[mView removeFromSuperview];
mParentView = newParentView;
mParentView = newParentView;
[mParentView addSubview:mView];
return NS_OK;

View File

@ -897,15 +897,17 @@ nsWindow::GetDPI()
NS_IMETHODIMP
nsWindow::SetParent(nsIWidget *aNewParent)
{
if (mContainer || !mGdkWindow || !mParent) {
NS_NOTREACHED("nsWindow::SetParent - reparenting a non-child window");
if (mContainer || !mGdkWindow) {
NS_NOTREACHED("nsWindow::SetParent called illegally");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_ASSERTION(!mTransientParent, "child widget with transient parent");
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
mParent->RemoveChild(this);
if (mParent) {
mParent->RemoveChild(this);
}
mParent = aNewParent;
@ -1002,6 +1004,10 @@ nsWindow::ReparentNativeWidgetInternal(nsIWidget* aNewParent,
NS_ABORT_IF_FALSE(!gdk_window_is_destroyed(aNewParentWindow),
"destroyed GdkWindow with widget");
SetWidgetForHierarchy(mGdkWindow, aOldContainer, aNewContainer);
if (aOldContainer == gInvisibleContainer) {
CheckDestroyInvisibleContainer();
}
}
if (!mIsTopLevel) {

View File

@ -250,6 +250,21 @@ nsBaseWidget::CreateChild(const nsIntRect &aRect,
return nsnull;
}
NS_IMETHODIMP
nsBaseWidget::SetEventCallback(EVENT_CALLBACK aEventFunction,
nsDeviceContext *aContext)
{
mEventCallback = aEventFunction;
if (aContext) {
NS_IF_RELEASE(mContext);
mContext = aContext;
NS_ADDREF(mContext);
}
return NS_OK;
}
// Attach a view to our widget which we'll send events to.
NS_IMETHODIMP
nsBaseWidget::AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,

View File

@ -165,6 +165,7 @@ public:
nsDeviceContext *aContext,
nsWidgetInitData *aInitData = nsnull,
bool aForceUseIWidgetParent = false);
NS_IMETHOD SetEventCallback(EVENT_CALLBACK aEventFunction, nsDeviceContext *aContext);
NS_IMETHOD AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction, nsDeviceContext *aContext);
virtual ViewWrapper* GetAttachedViewPtr();
NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper);