Skip to content

Commit d159f11

Browse files
committedDec 16, 2024
Bug 1936164 - Don't reparent widgets when moving views around. r=tnikkel,layout-reviewers
This wasn't done consistently (otherwise bug 1936194 wouldn't have worked). Now that we recreate the popups when needed, we can rely on that instead of reparenting the widget. Popups are the only type of widget we should ever reparent, as other widgets are created at the top level which can't be moved around. Differential Revision: https://phabricator.services.mozilla.com/D232202
1 parent 8b5448f commit d159f11

13 files changed

+21
-116
lines changed
 

‎view/nsViewManager.cpp

-51
Original file line numberDiff line numberDiff line change
@@ -616,53 +616,6 @@ void nsViewManager::DispatchEvent(WidgetGUIEvent* aEvent, nsView* aView,
616616
*aStatus = nsEventStatus_eIgnore;
617617
}
618618

619-
// Recursively reparent widgets if necessary
620-
621-
void nsViewManager::ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget) {
622-
MOZ_ASSERT(aNewWidget, "null widget");
623-
624-
if (nsIWidget* widget = aView->GetWidget()) {
625-
// Check to see if the parent widget is the
626-
// same as the new parent. If not then reparent
627-
// the widget, otherwise there is nothing more
628-
// to do for the view and its descendants
629-
if (widget->GetParent() != aNewWidget) {
630-
widget->SetParent(aNewWidget);
631-
}
632-
return;
633-
}
634-
635-
// Need to check each of the views children to see
636-
// if they have a widget and reparent it.
637-
638-
for (nsView* kid = aView->GetFirstChild(); kid; kid = kid->GetNextSibling()) {
639-
ReparentChildWidgets(kid, aNewWidget);
640-
}
641-
}
642-
643-
// Reparent a view and its descendant views widgets if necessary
644-
645-
void nsViewManager::ReparentWidgets(nsView* aView, nsView* aParent) {
646-
MOZ_ASSERT(aParent, "Must have a parent");
647-
MOZ_ASSERT(aView, "Must have a view");
648-
649-
// Quickly determine whether the view has pre-existing children or a
650-
// widget. In most cases the view will not have any pre-existing
651-
// children when this is called. Only in the case
652-
// where a view has been reparented by removing it from
653-
// a reinserting it into a new location in the view hierarchy do we
654-
// have to consider reparenting the existing widgets for the view and
655-
// it's descendants.
656-
if (aView->HasWidget() || aView->GetFirstChild()) {
657-
nsIWidget* parentWidget = aParent->GetNearestWidget(nullptr);
658-
if (parentWidget) {
659-
ReparentChildWidgets(aView, parentWidget);
660-
return;
661-
}
662-
NS_WARNING("Can not find a widget for the parent view");
663-
}
664-
}
665-
666619
void nsViewManager::InsertChild(nsView* aParent, nsView* aChild,
667620
nsView* aSibling, bool aAfter) {
668621
MOZ_ASSERT(nullptr != aParent, "null ptr");
@@ -682,7 +635,6 @@ void nsViewManager::InsertChild(nsView* aParent, nsView* aChild,
682635
// insert at end of document order, i.e., before first view
683636
// this is the common case, by far
684637
aParent->InsertChild(aChild, nullptr);
685-
ReparentWidgets(aChild, aParent);
686638
} else {
687639
// insert at beginning of document order, i.e., after last view
688640
nsView* kid = aParent->GetFirstChild();
@@ -693,7 +645,6 @@ void nsViewManager::InsertChild(nsView* aParent, nsView* aChild,
693645
}
694646
// prev is last view or null if there are no children
695647
aParent->InsertChild(aChild, prev);
696-
ReparentWidgets(aChild, aParent);
697648
}
698649
} else {
699650
nsView* kid = aParent->GetFirstChild();
@@ -707,11 +658,9 @@ void nsViewManager::InsertChild(nsView* aParent, nsView* aChild,
707658
if (aAfter) {
708659
// insert after 'kid' in document order, i.e. before in view order
709660
aParent->InsertChild(aChild, prev);
710-
ReparentWidgets(aChild, aParent);
711661
} else {
712662
// insert before 'kid' in document order, i.e. after in view order
713663
aParent->InsertChild(aChild, kid);
714-
ReparentWidgets(aChild, aParent);
715664
}
716665
}
717666
}

‎view/nsViewManager.h

-2
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,6 @@ class nsViewManager final {
309309
static void CollectVMsForWillPaint(nsView* aView, nsViewManager* aParentVM,
310310
nsTArray<RefPtr<nsViewManager>>& aVMs);
311311

312-
void ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget);
313-
void ReparentWidgets(nsView* aView, nsView* aParent);
314312
void InvalidateWidgetArea(nsView* aWidgetView,
315313
const nsRegion& aDamagedRegion);
316314

‎widget/android/nsWindow.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2306,7 +2306,7 @@ void nsWindow::OnGeckoViewReady() {
23062306
acc->OnReady();
23072307
}
23082308

2309-
void nsWindow::DidChangeParent(nsIWidget*) {
2309+
void nsWindow::DidClearParent(nsIWidget*) {
23102310
// if we are now in the toplevel window's hierarchy, schedule a redraw
23112311
if (FindTopLevel() == nsWindow::TopWindow()) {
23122312
RedrawAll();

‎widget/android/nsWindow.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class nsWindow final : public nsBaseWidget {
158158
const LayoutDeviceIntRect& aRect,
159159
InitData* aInitData) override;
160160
void Destroy() override;
161-
void DidChangeParent(nsIWidget* aNewParent) override;
161+
void DidClearParent(nsIWidget*) override;
162162
float GetDPI() override;
163163
double GetDefaultScaleInternal() override;
164164
void Show(bool aState) override;

‎widget/cocoa/nsChildView.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class nsChildView final : public nsBaseWidget {
469469

470470
nsCocoaWindow* GetAppWindowWidget() const;
471471

472-
void DidChangeParent(nsIWidget*) override;
472+
void DidClearParent(nsIWidget*) override;
473473

474474
mozilla::widget::TextInputHandler* GetTextInputHandler() {
475475
return mTextInputHandler;

‎widget/cocoa/nsChildView.mm

+2-10
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ static inline void FlipCocoaScreenCoordinate(NSPoint& inPoint) {
249249
// mGeckoChild are used throughout the ChildView class to tell if it's safe
250250
// to use a ChildView object.
251251
[mView widgetDestroyed]; // Safe if mView is nil.
252-
SetParent(nullptr);
252+
ClearParent();
253253
TearDownView(); // Safe if called twice.
254254
}
255255

@@ -524,23 +524,15 @@ static void ManipulateViewWithoutNeedingDisplay(NSView* aView,
524524
}
525525

526526
// Change the parent of this widget
527-
void nsChildView::DidChangeParent(nsIWidget*) {
527+
void nsChildView::DidClearParent(nsIWidget*) {
528528
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
529529

530530
if (mOnDestroyCalled) {
531531
return;
532532
}
533533

534-
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
535-
536534
// we hold a ref to mView, so this is safe
537535
[mView removeFromSuperview];
538-
mParentView = mParent
539-
? (NSView<mozView>*)mParent->GetNativeData(NS_NATIVE_WIDGET)
540-
: nullptr;
541-
if (mParentView) {
542-
[mParentView addSubview:mView];
543-
}
544536

545537
NS_OBJC_END_TRY_IGNORE_BLOCK;
546538
}

‎widget/gtk/nsWindow.cpp

-23
Original file line numberDiff line numberDiff line change
@@ -715,29 +715,6 @@ bool nsWindow::WidgetTypeSupportsAcceleration() {
715715
return true;
716716
}
717717

718-
void nsWindow::DidChangeParent(nsIWidget* aOldParent) {
719-
LOG("nsWindow::DidChangeParent new parent %p -> %p\n", aOldParent, mParent);
720-
if (!mParent) {
721-
return;
722-
}
723-
724-
auto* newParent = static_cast<nsWindow*>(mParent);
725-
if (mIsDestroyed || newParent->IsDestroyed()) {
726-
return;
727-
}
728-
729-
if (!IsTopLevelWidget()) {
730-
GdkWindow* window = GetToplevelGdkWindow();
731-
GdkWindow* parentWindow = newParent->GetToplevelGdkWindow();
732-
gdk_window_reparent(window, parentWindow, 0, 0);
733-
SetHasMappedToplevel(newParent->mHasMappedToplevel);
734-
return;
735-
}
736-
737-
GtkWindow* newParentWidget = GTK_WINDOW(newParent->GetGtkWidget());
738-
GtkWindowSetTransientFor(GTK_WINDOW(mShell), newParentWidget);
739-
}
740-
741718
static void InitPenEvent(WidgetMouseEvent& aGeckoEvent, GdkEvent* aEvent) {
742719
// Find the source of the event
743720
GdkDevice* device = gdk_event_get_source_device(aEvent);

‎widget/gtk/nsWindow.h

-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ class nsWindow final : public nsBaseWidget {
338338
void SetTransparencyMode(TransparencyMode aMode) override;
339339
TransparencyMode GetTransparencyMode() override;
340340
void SetInputRegion(const InputRegion&) override;
341-
void DidChangeParent(nsIWidget* aOldParent) override;
342341

343342
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
344343
NativeMouseMessage aNativeMessage,

‎widget/nsBaseWidget.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -426,22 +426,20 @@ void nsBaseWidget::BaseCreate(nsIWidget* aParent, widget::InitData* aInitData) {
426426
}
427427
}
428428

429-
void nsIWidget::SetParent(nsIWidget* aNewParent) {
429+
void nsIWidget::ClearParent() {
430+
if (!mParent) {
431+
return;
432+
}
430433
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
431434
nsCOMPtr<nsIWidget> oldParent = mParent;
432-
if (mParent) {
433-
mParent->RemoveFromChildList(this);
434-
}
435-
mParent = aNewParent;
436-
if (mParent) {
437-
mParent->AddToChildList(this);
438-
}
439-
DidChangeParent(oldParent);
435+
oldParent->RemoveFromChildList(this);
436+
mParent = nullptr;
437+
DidClearParent(oldParent);
440438
}
441439

442440
void nsIWidget::RemoveAllChildren() {
443441
while (nsCOMPtr<nsIWidget> kid = mLastChild) {
444-
kid->SetParent(nullptr);
442+
kid->ClearParent();
445443
MOZ_ASSERT(kid != mLastChild);
446444
}
447445
}

‎widget/nsIWidget.h

+4-10
Original file line numberDiff line numberDiff line change
@@ -513,14 +513,8 @@ class nsIWidget : public nsISupports {
513513
*/
514514
bool Destroyed() const { return mOnDestroyCalled; }
515515

516-
/**
517-
* Reparent a widget
518-
*
519-
* Change the widget's parent. Null parents are allowed.
520-
*
521-
* @param aNewParent new parent
522-
*/
523-
void SetParent(nsIWidget* aNewParent);
516+
/** Clear the widget's parent. */
517+
void ClearParent();
524518

525519
/**
526520
* Return the parent Widget of this Widget or nullptr if this is a
@@ -531,8 +525,8 @@ class nsIWidget : public nsISupports {
531525
*/
532526
nsIWidget* GetParent() const { return mParent; }
533527

534-
/** Gets called when mParent changes after creation. */
535-
virtual void DidChangeParent(nsIWidget* aOldParent) {}
528+
/** Gets called when mParent is cleared. */
529+
virtual void DidClearParent(nsIWidget* aOldParent) {}
536530

537531
/**
538532
* Return the top level Widget of this Widget

‎widget/uikit/nsWindow.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ - (UIAccessibilityContainerType)accessibilityContainerType {
760760
void nsWindow::Destroy() {
761761
for (uint32_t i = 0; i < mChildren.Length(); ++i) {
762762
// why do we still have children?
763-
mChildren[i]->SetParent(nullptr);
763+
mChildren[i]->ClearParent();
764764
}
765765

766766
if (mParent) mParent->mChildren.RemoveElement(this);

‎widget/windows/nsWindow.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1441,13 +1441,11 @@ void nsWindow::DissociateFromNativeWindow() {
14411441
mPrevWndProc.reset();
14421442
}
14431443

1444-
void nsWindow::DidChangeParent(nsIWidget*) {
1444+
void nsWindow::DidClearParent(nsIWidget*) {
14451445
if (mWindowType == WindowType::Popup || !mWnd) {
14461446
return;
14471447
}
1448-
HWND newParent =
1449-
mParent ? (HWND)mParent->GetNativeData(NS_NATIVE_WINDOW) : nullptr;
1450-
::SetParent(mWnd, newParent);
1448+
::SetParent(mWnd, nullptr);
14511449
RecreateDirectManipulationIfNeeded();
14521450
}
14531451

‎widget/windows/nsWindow.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class nsWindow final : public nsBaseWidget {
195195
void Destroy() override;
196196
float GetDPI() override;
197197
double GetDefaultScaleInternal() override;
198-
void DidChangeParent(nsIWidget* aOldParent) override;
198+
void DidClearParent(nsIWidget* aOldParent) override;
199199
int32_t LogToPhys(double aValue);
200200
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override {
201201
if (mozilla::widget::WinUtils::IsPerMonitorDPIAware()) {

0 commit comments

Comments
 (0)
Failed to load comments.