Bug 1562827 - [Linux] Merge nsWindow::ReparentNativeWidgetInternal() to nsWindow::SetParent() and use nsWindow::ReparentNativeWidget() for toplevel windows only, r=karlt

- Use former ReparentNativeWidgetInternal() code in nsWindow::SetParent().
  Also update mToplevelParentWindow for Wayland to hold default toplevel window.

- Make nsWindow::ReparentNativeWidget() to work on toplevel windows only and use only gtk_window_set_transient_for() to reparent
  a toplevel window. Also update mToplevelParentWindow for Wayland.

Differential Revision: https://phabricator.services.mozilla.com/D43600

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Martin Stransky 2019-08-28 23:48:44 +00:00
Родитель 52b58160a7
Коммит 1cf5fdd9b6
2 изменённых файлов: 43 добавлений и 65 удалений

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

@ -821,7 +821,6 @@ void nsWindow::SetParent(nsIWidget* aNewParent) {
if (mParent) {
mParent->RemoveChild(this);
}
mParent = aNewParent;
GtkWidget* oldContainer = GetMozContainerWidget();
@ -833,18 +832,47 @@ void nsWindow::SetParent(nsIWidget* aNewParent) {
return;
}
nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
GdkWindow* newParentWindow = nullptr;
GtkWidget* newContainer = nullptr;
if (aNewParent) {
aNewParent->AddChild(this);
ReparentNativeWidget(aNewParent);
newParentWindow = newParent->mGdkWindow;
newContainer = newParent->GetMozContainerWidget();
} else {
// aNewParent is nullptr, but reparent to a hidden window to avoid
// destroying the GdkWindow and its descendants.
// An invisible container widget is needed to hold descendant
// GtkWidgets.
GtkWidget* newContainer = EnsureInvisibleContainer();
GdkWindow* newParentWindow = gtk_widget_get_window(newContainer);
ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
oldContainer);
newContainer = EnsureInvisibleContainer();
newParentWindow = gtk_widget_get_window(newContainer);
}
if (!newContainer) {
// The new parent GdkWindow has been destroyed.
MOZ_ASSERT(!newParentWindow || gdk_window_is_destroyed(newParentWindow),
"live GdkWindow with no widget");
Destroy();
} else {
if (newContainer != oldContainer) {
MOZ_ASSERT(!gdk_window_is_destroyed(newParentWindow),
"destroyed GdkWindow with widget");
SetWidgetForHierarchy(mGdkWindow, oldContainer, newContainer);
if (oldContainer == gInvisibleContainer) {
CheckDestroyInvisibleContainer();
}
}
gdk_window_reparent(mGdkWindow, newParentWindow,
DevicePixelsToGdkCoordRoundDown(mBounds.x),
DevicePixelsToGdkCoordRoundDown(mBounds.y));
mToplevelParentWindow = GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
}
bool parentHasMappedToplevel = newParent && newParent->mHasMappedToplevel;
if (mHasMappedToplevel != parentHasMappedToplevel) {
SetHasMappedToplevel(parentHasMappedToplevel);
}
}
@ -852,66 +880,22 @@ bool nsWindow::WidgetTypeSupportsAcceleration() { return !IsSmallPopup(); }
void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
MOZ_ASSERT(aNewParent, "null widget");
NS_ASSERTION(!mIsDestroyed, "");
NS_ASSERTION(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
GtkWidget* oldContainer = GetMozContainerWidget();
if (!oldContainer) {
// The GdkWindows have been destroyed so there is nothing else to
// reparent.
MOZ_ASSERT(gdk_window_is_destroyed(mGdkWindow),
"live GdkWindow with no widget");
return;
}
MOZ_ASSERT(!mIsDestroyed, "");
MOZ_ASSERT(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
MOZ_ASSERT(!gdk_window_is_destroyed(mGdkWindow),
"destroyed GdkWindow with widget");
MOZ_ASSERT(
!mParent,
"nsWindow::ReparentNativeWidget() works on toplevel windows only.");
auto* newParent = static_cast<nsWindow*>(aNewParent);
GdkWindow* newParentWindow = newParent->mGdkWindow;
GtkWidget* newContainer = newParent->GetMozContainerWidget();
GtkWindow* newParentWidget = GTK_WINDOW(newParent->GetGtkWidget());
GtkWindow* shell = GTK_WINDOW(mShell);
if (shell && gtk_window_get_transient_for(shell)) {
GtkWindow* topLevelParent =
GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
gtk_window_set_transient_for(shell, topLevelParent);
}
ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
oldContainer);
}
void nsWindow::ReparentNativeWidgetInternal(nsIWidget* aNewParent,
GtkWidget* aNewContainer,
GdkWindow* aNewParentWindow,
GtkWidget* aOldContainer) {
if (!aNewContainer) {
// The new parent GdkWindow has been destroyed.
MOZ_ASSERT(!aNewParentWindow || gdk_window_is_destroyed(aNewParentWindow),
"live GdkWindow with no widget");
Destroy();
} else {
if (aNewContainer != aOldContainer) {
MOZ_ASSERT(!gdk_window_is_destroyed(aNewParentWindow),
"destroyed GdkWindow with widget");
SetWidgetForHierarchy(mGdkWindow, aOldContainer, aNewContainer);
if (aOldContainer == gInvisibleContainer) {
CheckDestroyInvisibleContainer();
}
}
if (!mIsTopLevel) {
gdk_window_reparent(mGdkWindow, aNewParentWindow,
DevicePixelsToGdkCoordRoundDown(mBounds.x),
DevicePixelsToGdkCoordRoundDown(mBounds.y));
}
}
auto* newParent = static_cast<nsWindow*>(aNewParent);
bool parentHasMappedToplevel = newParent && newParent->mHasMappedToplevel;
if (mHasMappedToplevel != parentHasMappedToplevel) {
SetHasMappedToplevel(parentHasMappedToplevel);
gtk_window_set_transient_for(shell, newParentWidget);
mToplevelParentWindow = newParentWidget;
}
}

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

@ -402,12 +402,6 @@ class nsWindow final : public nsBaseWidget {
void DispatchResized();
void MaybeDispatchResized();
// Helper for SetParent and ReparentNativeWidget.
void ReparentNativeWidgetInternal(nsIWidget* aNewParent,
GtkWidget* aNewContainer,
GdkWindow* aNewParentWindow,
GtkWidget* aOldContainer);
virtual void RegisterTouchWindow() override;
virtual bool CompositorInitiallyPaused() override {
#ifdef MOZ_WAYLAND