Skip to content

Commit a98c455

Browse files
committedOct 22, 2024
Bug 1924240 - Devirtualize parent handling. r=mac-reviewers,win-reviewers,geckoview-reviewers,bradwerth,m_kato,rkraesig
Move mParent to nsIWidget.h along with kids and so on. Instead of ReparentNativeWidget add a more general DidChangeParent method. Make mParent weak to prevent cycles. These are broken on Destroy() but it feels kinda silly, and we were inconsistent before I started this effort so pretty sure it can be done. Differential Revision: https://phabricator.services.mozilla.com/D225796
1 parent 7e27cb0 commit a98c455

18 files changed

+133
-428
lines changed
 

‎view/nsViewManager.cpp

+3-11
Original file line numberDiff line numberDiff line change
@@ -662,21 +662,13 @@ void nsViewManager::DispatchEvent(WidgetGUIEvent* aEvent, nsView* aView,
662662
void nsViewManager::ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget) {
663663
MOZ_ASSERT(aNewWidget, "null widget");
664664

665-
if (aView->HasWidget()) {
665+
if (nsIWidget* widget = aView->GetWidget()) {
666666
// Check to see if the parent widget is the
667667
// same as the new parent. If not then reparent
668668
// the widget, otherwise there is nothing more
669669
// to do for the view and its descendants
670-
nsIWidget* widget = aView->GetWidget();
671-
nsIWidget* parentWidget = widget->GetParent();
672-
if (parentWidget) {
673-
// Child widget
674-
if (parentWidget != aNewWidget) {
675-
widget->SetParent(aNewWidget);
676-
}
677-
} else {
678-
// Toplevel widget (popup, dialog, etc)
679-
widget->ReparentNativeWidget(aNewWidget);
670+
if (widget->GetParent() != aNewWidget) {
671+
widget->SetParent(aNewWidget);
680672
}
681673
return;
682674
}

‎widget/PuppetWidget.cpp

+2-39
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,15 @@ PuppetWidget::~PuppetWidget() { Destroy(); }
9696
void PuppetWidget::InfallibleCreate(nsIWidget* aParent,
9797
const LayoutDeviceIntRect& aRect,
9898
widget::InitData* aInitData) {
99-
// FIXME(emilio): Why aParent = nullptr? Can we even get here with non-null
100-
// aParent?
101-
BaseCreate(/* aParent = */ nullptr, aInitData);
99+
BaseCreate(aParent, aInitData);
102100

103101
mBounds = aRect;
104102
mEnabled = true;
105103
mVisible = true;
106104

107-
mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
108-
IntSize(1, 1), SurfaceFormat::B8G8R8A8);
109-
110105
mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
111106

112-
PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
113-
if (parent) {
114-
parent->SetChild(this);
115-
mWindowRenderer = parent->GetWindowRenderer();
116-
} else {
117-
Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
118-
}
107+
Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
119108
mMemoryPressureObserver = MemoryPressureObserver::Create(this);
120109
}
121110

@@ -148,7 +137,6 @@ void PuppetWidget::Destroy() {
148137
mMemoryPressureObserver->Unregister();
149138
mMemoryPressureObserver = nullptr;
150139
}
151-
mChild = nullptr;
152140
if (mWindowRenderer) {
153141
mWindowRenderer->Destroy();
154142
}
@@ -163,10 +151,6 @@ void PuppetWidget::Show(bool aState) {
163151
bool wasVisible = mVisible;
164152
mVisible = aState;
165153

166-
if (mChild) {
167-
mChild->mVisible = aState;
168-
}
169-
170154
if (!wasVisible && mVisible) {
171155
// The previously attached widget listener is handy if
172156
// we're transitioning from page to page without dropping
@@ -187,11 +171,6 @@ void PuppetWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
187171
mBounds.SizeTo(
188172
LayoutDeviceIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
189173

190-
if (mChild) {
191-
mChild->Resize(aWidth, aHeight, aRepaint);
192-
return;
193-
}
194-
195174
// XXX: roc says that |aRepaint| dictates whether or not to
196175
// invalidate the expanded area
197176
if (oldBounds.Size() < mBounds.Size() && aRepaint) {
@@ -225,11 +204,6 @@ void PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect) {
225204
debug_DumpInvalidate(stderr, this, &aRect, "PuppetWidget", 0);
226205
#endif
227206

228-
if (mChild) {
229-
mChild->Invalidate(aRect);
230-
return;
231-
}
232-
233207
if (mBrowserChild && !aRect.IsEmpty() && !mWidgetPaintTask.IsPending()) {
234208
mWidgetPaintTask = new WidgetPaintTask(this);
235209
nsCOMPtr<nsIRunnable> event(mWidgetPaintTask.get());
@@ -262,9 +236,6 @@ nsresult PuppetWidget::DispatchEvent(WidgetGUIEvent* aEvent,
262236
debug_DumpEvent(stdout, aEvent->mWidget, aEvent, "PuppetWidget", 0);
263237
#endif
264238

265-
MOZ_ASSERT(!mChild || mChild->mWindowType == WindowType::Popup,
266-
"Unexpected event dispatch!");
267-
268239
MOZ_ASSERT(!aEvent->AsKeyboardEvent() ||
269240
aEvent->mFlags.mIsSynthesizedForTests ||
270241
aEvent->AsKeyboardEvent()->AreAllEditCommandsInitialized(),
@@ -937,14 +908,6 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
937908
mUpdateCursor = false;
938909
}
939910

940-
void PuppetWidget::SetChild(PuppetWidget* aChild) {
941-
MOZ_ASSERT(this != aChild, "can't parent a widget to itself");
942-
MOZ_ASSERT(!aChild->mChild,
943-
"fake widget 'hierarchy' only expected to have one level");
944-
945-
mChild = aChild;
946-
}
947-
948911
NS_IMETHODIMP
949912
PuppetWidget::WidgetPaintTask::Run() {
950913
if (mWidget) {

‎widget/PuppetWidget.h

-8
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,6 @@ class PuppetWidget final : public nsBaseWidget,
303303
private:
304304
void Paint();
305305

306-
void SetChild(PuppetWidget* aChild);
307-
308306
nsresult RequestIMEToCommitComposition(bool aCancel);
309307
nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification);
310308
nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
@@ -347,14 +345,8 @@ class PuppetWidget final : public nsBaseWidget,
347345
// it's possible for BrowserChild to outlive the PuppetWidget, we clear
348346
// this weak reference in Destroy()
349347
BrowserChild* mBrowserChild;
350-
// The "widget" to which we delegate events if we don't have an
351-
// event handler.
352-
RefPtr<PuppetWidget> mChild;
353348
nsRevocableEventPtr<WidgetPaintTask> mWidgetPaintTask;
354349
RefPtr<layers::MemoryPressureObserver> mMemoryPressureObserver;
355-
// XXX/cjones: keeping this around until we teach LayerManager to do
356-
// retained-content-only transactions
357-
RefPtr<DrawTarget> mDrawTarget;
358350
// IME
359351
IMENotificationRequests mIMENotificationRequestsOfParent;
360352
InputContext mInputContext;

‎widget/android/nsWindow.cpp

+17-41
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,7 @@ void nsWindow::LogWindow(nsWindow* win, int index, int indent) {
21692169
char spaces[] = " ";
21702170
spaces[indent < 20 ? indent : 20] = 0;
21712171
ALOG("%s [% 2d] 0x%p [parent 0x%p] [% 3d,% 3dx% 3d,% 3d] vis %d type %d",
2172-
spaces, index, win, win->mParent.get(), win->mBounds.x, win->mBounds.y,
2172+
spaces, index, win, win->mParent, win->mBounds.x, win->mBounds.y,
21732173
win->mBounds.width, win->mBounds.height, win->mIsVisible,
21742174
int(win->mWindowType));
21752175
int i = 0;
@@ -2226,7 +2226,6 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
22262226
aInitData->mWindowType != WindowType::Invisible);
22272227

22282228
BaseCreate(aParent, aInitData);
2229-
mParent = static_cast<nsWindow*>(aParent);
22302229
MOZ_ASSERT_IF(!IsTopLevel(), aParent);
22312230

22322231
if (IsTopLevel()) {
@@ -2251,23 +2250,17 @@ void nsWindow::Destroy() {
22512250
// Stuff below may release the last ref to this
22522251
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
22532252

2254-
while (RefPtr<nsWindow> kid = static_cast<nsWindow*>(mLastChild)) {
2255-
// why do we still have children?
2256-
ALOG("### Warning: Destroying window %p and reparenting child %p to null!",
2257-
this, kid.get());
2258-
RemoveChild(kid);
2259-
kid->mParent = nullptr;
2260-
}
2253+
RemoveAllChildren();
22612254

22622255
// Ensure the compositor has been shutdown before this nsWindow is potentially
22632256
// deleted
22642257
nsBaseWidget::DestroyCompositor();
22652258

22662259
nsBaseWidget::Destroy();
22672260

2268-
if (IsTopLevel()) gTopLevelWindows.RemoveElement(this);
2269-
2270-
SetParent(nullptr);
2261+
if (IsTopLevel()) {
2262+
gTopLevelWindows.RemoveElement(this);
2263+
}
22712264

22722265
nsBaseWidget::OnDestroy();
22732266

@@ -2311,27 +2304,13 @@ void nsWindow::OnGeckoViewReady() {
23112304
acc->OnReady();
23122305
}
23132306

2314-
void nsWindow::SetParent(nsIWidget* aNewParent) {
2315-
if (mParent == aNewParent) {
2316-
return;
2317-
}
2318-
2319-
if (mParent) {
2320-
mParent->RemoveChild(this);
2321-
}
2322-
2323-
mParent = static_cast<nsWindow*>(aNewParent);
2324-
2325-
if (mParent) {
2326-
mParent->AddChild(this);
2327-
}
2328-
2307+
void nsWindow::DidChangeParent(nsIWidget*) {
23292308
// if we are now in the toplevel window's hierarchy, schedule a redraw
2330-
if (FindTopLevel() == nsWindow::TopWindow()) RedrawAll();
2309+
if (FindTopLevel() == nsWindow::TopWindow()) {
2310+
RedrawAll();
2311+
}
23312312
}
23322313

2333-
nsIWidget* nsWindow::GetParent() { return mParent; }
2334-
23352314
RefPtr<MozPromise<bool, bool, false>> nsWindow::OnLoadRequest(
23362315
nsIURI* aUri, int32_t aWindowType, int32_t aFlags,
23372316
nsIPrincipal* aTriggeringPrincipal, bool aHasUserGesture,
@@ -2523,9 +2502,10 @@ void nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) {}
25232502
nsWindow* nsWindow::FindTopLevel() {
25242503
nsWindow* toplevel = this;
25252504
while (toplevel) {
2526-
if (toplevel->IsTopLevel()) return toplevel;
2527-
2528-
toplevel = toplevel->mParent;
2505+
if (toplevel->IsTopLevel()) {
2506+
return toplevel;
2507+
}
2508+
toplevel = static_cast<nsWindow*>(toplevel->mParent);
25292509
}
25302510

25312511
ALOG(
@@ -2586,10 +2566,8 @@ LayoutDeviceIntRect nsWindow::GetScreenBounds() {
25862566
LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() {
25872567
LayoutDeviceIntPoint p(0, 0);
25882568

2589-
for (nsWindow* w = this; !!w; w = w->mParent) {
2590-
p.x += w->mBounds.x;
2591-
p.y += w->mBounds.y;
2592-
2569+
for (nsWindow* w = this; !!w; w = static_cast<nsWindow*>(w->mParent)) {
2570+
p += w->mBounds.TopLeft();
25932571
if (w->IsTopLevel()) {
25942572
break;
25952573
}
@@ -3080,8 +3058,7 @@ nsresult nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
30803058

30813059
const auto& npzc = npzcSup->GetJavaNPZC();
30823060
const auto& bounds = FindTopLevel()->mBounds;
3083-
aPoint.x -= bounds.x;
3084-
aPoint.y -= bounds.y;
3061+
aPoint -= bounds.TopLeft();
30853062

30863063
DispatchToUiThread(
30873064
"nsWindow::SynthesizeNativeTouchPoint",
@@ -3106,8 +3083,7 @@ nsresult nsWindow::SynthesizeNativeMouseEvent(
31063083

31073084
const auto& npzc = npzcSup->GetJavaNPZC();
31083085
const auto& bounds = FindTopLevel()->mBounds;
3109-
aPoint.x -= bounds.x;
3110-
aPoint.y -= bounds.y;
3086+
aPoint -= bounds.TopLeft();
31113087

31123088
int32_t nativeMessage;
31133089
switch (aNativeMessage) {

‎widget/android/nsWindow.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ class nsWindow final : public nsBaseWidget {
7171
bool aIsTopLevel);
7272

7373
private:
74-
RefPtr<nsWindow> mParent;
7574
nsCOMPtr<nsIUserIdleServiceInternal> mIdleService;
7675
mozilla::ScreenIntCoord mDynamicToolbarMaxHeight{0};
7776
mozilla::ScreenIntMargin mSafeAreaInsets;
@@ -159,8 +158,7 @@ class nsWindow final : public nsBaseWidget {
159158
const LayoutDeviceIntRect& aRect,
160159
InitData* aInitData) override;
161160
void Destroy() override;
162-
void SetParent(nsIWidget* aNewParent) override;
163-
nsIWidget* GetParent(void) override;
161+
void DidChangeParent(nsIWidget* aNewParent) override;
164162
float GetDPI() override;
165163
double GetDefaultScaleInternal() override;
166164
void Show(bool aState) override;

‎widget/cocoa/nsChildView.h

+1-6
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,6 @@ class nsChildView final : public nsBaseWidget {
304304
void Show(bool aState) override;
305305
bool IsVisible() const override;
306306

307-
void SetParent(nsIWidget* aNewParent) override;
308-
nsIWidget* GetParent() override;
309307
float GetDPI() override;
310308

311309
void Move(double aX, double aY) override;
@@ -463,8 +461,6 @@ class nsChildView final : public nsBaseWidget {
463461
const bool aIsVertical,
464462
const LayoutDeviceIntPoint& aPoint) override;
465463

466-
void ResetParent();
467-
468464
static bool DoHasPendingInputEvent();
469465
static uint32_t GetCurrentInputEventCount();
470466
static void UpdateCurrentInputEventCount();
@@ -473,7 +469,7 @@ class nsChildView final : public nsBaseWidget {
473469

474470
nsCocoaWindow* GetAppWindowWidget() const;
475471

476-
void ReparentNativeWidget(nsIWidget* aNewParent) override;
472+
void DidChangeParent(nsIWidget*) override;
477473

478474
mozilla::widget::TextInputHandler* GetTextInputHandler() {
479475
return mTextInputHandler;
@@ -562,7 +558,6 @@ class nsChildView final : public nsBaseWidget {
562558
InputContext mInputContext;
563559

564560
NSView* mParentView;
565-
nsCOMPtr<nsIWidget> mParentWidget;
566561

567562
#ifdef ACCESSIBILITY
568563
// weak ref to this childview's associated mozAccessible for speed reasons

0 commit comments

Comments
 (0)
Failed to load comments.