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
This commit is contained in:
@@ -662,21 +662,13 @@ void nsViewManager::DispatchEvent(WidgetGUIEvent* aEvent, nsView* aView,
|
||||
void nsViewManager::ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget) {
|
||||
MOZ_ASSERT(aNewWidget, "null widget");
|
||||
|
||||
if (aView->HasWidget()) {
|
||||
if (nsIWidget* widget = aView->GetWidget()) {
|
||||
// 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
|
||||
nsIWidget* widget = aView->GetWidget();
|
||||
nsIWidget* parentWidget = widget->GetParent();
|
||||
if (parentWidget) {
|
||||
// Child widget
|
||||
if (parentWidget != aNewWidget) {
|
||||
widget->SetParent(aNewWidget);
|
||||
}
|
||||
} else {
|
||||
// Toplevel widget (popup, dialog, etc)
|
||||
widget->ReparentNativeWidget(aNewWidget);
|
||||
if (widget->GetParent() != aNewWidget) {
|
||||
widget->SetParent(aNewWidget);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,26 +96,15 @@ PuppetWidget::~PuppetWidget() { Destroy(); }
|
||||
void PuppetWidget::InfallibleCreate(nsIWidget* aParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
widget::InitData* aInitData) {
|
||||
// FIXME(emilio): Why aParent = nullptr? Can we even get here with non-null
|
||||
// aParent?
|
||||
BaseCreate(/* aParent = */ nullptr, aInitData);
|
||||
BaseCreate(aParent, aInitData);
|
||||
|
||||
mBounds = aRect;
|
||||
mEnabled = true;
|
||||
mVisible = true;
|
||||
|
||||
mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
||||
IntSize(1, 1), SurfaceFormat::B8G8R8A8);
|
||||
|
||||
mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
|
||||
|
||||
PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
|
||||
if (parent) {
|
||||
parent->SetChild(this);
|
||||
mWindowRenderer = parent->GetWindowRenderer();
|
||||
} else {
|
||||
Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
|
||||
}
|
||||
Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
|
||||
mMemoryPressureObserver = MemoryPressureObserver::Create(this);
|
||||
}
|
||||
|
||||
@@ -148,7 +137,6 @@ void PuppetWidget::Destroy() {
|
||||
mMemoryPressureObserver->Unregister();
|
||||
mMemoryPressureObserver = nullptr;
|
||||
}
|
||||
mChild = nullptr;
|
||||
if (mWindowRenderer) {
|
||||
mWindowRenderer->Destroy();
|
||||
}
|
||||
@@ -163,10 +151,6 @@ void PuppetWidget::Show(bool aState) {
|
||||
bool wasVisible = mVisible;
|
||||
mVisible = aState;
|
||||
|
||||
if (mChild) {
|
||||
mChild->mVisible = aState;
|
||||
}
|
||||
|
||||
if (!wasVisible && mVisible) {
|
||||
// The previously attached widget listener is handy if
|
||||
// we're transitioning from page to page without dropping
|
||||
@@ -187,11 +171,6 @@ void PuppetWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
|
||||
mBounds.SizeTo(
|
||||
LayoutDeviceIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
|
||||
|
||||
if (mChild) {
|
||||
mChild->Resize(aWidth, aHeight, aRepaint);
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: roc says that |aRepaint| dictates whether or not to
|
||||
// invalidate the expanded area
|
||||
if (oldBounds.Size() < mBounds.Size() && aRepaint) {
|
||||
@@ -225,11 +204,6 @@ void PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect) {
|
||||
debug_DumpInvalidate(stderr, this, &aRect, "PuppetWidget", 0);
|
||||
#endif
|
||||
|
||||
if (mChild) {
|
||||
mChild->Invalidate(aRect);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBrowserChild && !aRect.IsEmpty() && !mWidgetPaintTask.IsPending()) {
|
||||
mWidgetPaintTask = new WidgetPaintTask(this);
|
||||
nsCOMPtr<nsIRunnable> event(mWidgetPaintTask.get());
|
||||
@@ -262,9 +236,6 @@ nsresult PuppetWidget::DispatchEvent(WidgetGUIEvent* aEvent,
|
||||
debug_DumpEvent(stdout, aEvent->mWidget, aEvent, "PuppetWidget", 0);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(!mChild || mChild->mWindowType == WindowType::Popup,
|
||||
"Unexpected event dispatch!");
|
||||
|
||||
MOZ_ASSERT(!aEvent->AsKeyboardEvent() ||
|
||||
aEvent->mFlags.mIsSynthesizedForTests ||
|
||||
aEvent->AsKeyboardEvent()->AreAllEditCommandsInitialized(),
|
||||
@@ -937,14 +908,6 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
|
||||
mUpdateCursor = false;
|
||||
}
|
||||
|
||||
void PuppetWidget::SetChild(PuppetWidget* aChild) {
|
||||
MOZ_ASSERT(this != aChild, "can't parent a widget to itself");
|
||||
MOZ_ASSERT(!aChild->mChild,
|
||||
"fake widget 'hierarchy' only expected to have one level");
|
||||
|
||||
mChild = aChild;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PuppetWidget::WidgetPaintTask::Run() {
|
||||
if (mWidget) {
|
||||
|
||||
@@ -303,8 +303,6 @@ class PuppetWidget final : public nsBaseWidget,
|
||||
private:
|
||||
void Paint();
|
||||
|
||||
void SetChild(PuppetWidget* aChild);
|
||||
|
||||
nsresult RequestIMEToCommitComposition(bool aCancel);
|
||||
nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
|
||||
@@ -347,14 +345,8 @@ class PuppetWidget final : public nsBaseWidget,
|
||||
// it's possible for BrowserChild to outlive the PuppetWidget, we clear
|
||||
// this weak reference in Destroy()
|
||||
BrowserChild* mBrowserChild;
|
||||
// The "widget" to which we delegate events if we don't have an
|
||||
// event handler.
|
||||
RefPtr<PuppetWidget> mChild;
|
||||
nsRevocableEventPtr<WidgetPaintTask> mWidgetPaintTask;
|
||||
RefPtr<layers::MemoryPressureObserver> mMemoryPressureObserver;
|
||||
// XXX/cjones: keeping this around until we teach LayerManager to do
|
||||
// retained-content-only transactions
|
||||
RefPtr<DrawTarget> mDrawTarget;
|
||||
// IME
|
||||
IMENotificationRequests mIMENotificationRequestsOfParent;
|
||||
InputContext mInputContext;
|
||||
|
||||
@@ -2169,7 +2169,7 @@ void nsWindow::LogWindow(nsWindow* win, int index, int indent) {
|
||||
char spaces[] = " ";
|
||||
spaces[indent < 20 ? indent : 20] = 0;
|
||||
ALOG("%s [% 2d] 0x%p [parent 0x%p] [% 3d,% 3dx% 3d,% 3d] vis %d type %d",
|
||||
spaces, index, win, win->mParent.get(), win->mBounds.x, win->mBounds.y,
|
||||
spaces, index, win, win->mParent, win->mBounds.x, win->mBounds.y,
|
||||
win->mBounds.width, win->mBounds.height, win->mIsVisible,
|
||||
int(win->mWindowType));
|
||||
int i = 0;
|
||||
@@ -2226,7 +2226,6 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
|
||||
aInitData->mWindowType != WindowType::Invisible);
|
||||
|
||||
BaseCreate(aParent, aInitData);
|
||||
mParent = static_cast<nsWindow*>(aParent);
|
||||
MOZ_ASSERT_IF(!IsTopLevel(), aParent);
|
||||
|
||||
if (IsTopLevel()) {
|
||||
@@ -2251,13 +2250,7 @@ void nsWindow::Destroy() {
|
||||
// Stuff below may release the last ref to this
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
|
||||
while (RefPtr<nsWindow> kid = static_cast<nsWindow*>(mLastChild)) {
|
||||
// why do we still have children?
|
||||
ALOG("### Warning: Destroying window %p and reparenting child %p to null!",
|
||||
this, kid.get());
|
||||
RemoveChild(kid);
|
||||
kid->mParent = nullptr;
|
||||
}
|
||||
RemoveAllChildren();
|
||||
|
||||
// Ensure the compositor has been shutdown before this nsWindow is potentially
|
||||
// deleted
|
||||
@@ -2265,9 +2258,9 @@ void nsWindow::Destroy() {
|
||||
|
||||
nsBaseWidget::Destroy();
|
||||
|
||||
if (IsTopLevel()) gTopLevelWindows.RemoveElement(this);
|
||||
|
||||
SetParent(nullptr);
|
||||
if (IsTopLevel()) {
|
||||
gTopLevelWindows.RemoveElement(this);
|
||||
}
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
|
||||
@@ -2311,27 +2304,13 @@ void nsWindow::OnGeckoViewReady() {
|
||||
acc->OnReady();
|
||||
}
|
||||
|
||||
void nsWindow::SetParent(nsIWidget* aNewParent) {
|
||||
if (mParent == aNewParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mParent) {
|
||||
mParent->RemoveChild(this);
|
||||
}
|
||||
|
||||
mParent = static_cast<nsWindow*>(aNewParent);
|
||||
|
||||
if (mParent) {
|
||||
mParent->AddChild(this);
|
||||
}
|
||||
|
||||
void nsWindow::DidChangeParent(nsIWidget*) {
|
||||
// if we are now in the toplevel window's hierarchy, schedule a redraw
|
||||
if (FindTopLevel() == nsWindow::TopWindow()) RedrawAll();
|
||||
if (FindTopLevel() == nsWindow::TopWindow()) {
|
||||
RedrawAll();
|
||||
}
|
||||
}
|
||||
|
||||
nsIWidget* nsWindow::GetParent() { return mParent; }
|
||||
|
||||
RefPtr<MozPromise<bool, bool, false>> nsWindow::OnLoadRequest(
|
||||
nsIURI* aUri, int32_t aWindowType, int32_t aFlags,
|
||||
nsIPrincipal* aTriggeringPrincipal, bool aHasUserGesture,
|
||||
@@ -2523,9 +2502,10 @@ void nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) {}
|
||||
nsWindow* nsWindow::FindTopLevel() {
|
||||
nsWindow* toplevel = this;
|
||||
while (toplevel) {
|
||||
if (toplevel->IsTopLevel()) return toplevel;
|
||||
|
||||
toplevel = toplevel->mParent;
|
||||
if (toplevel->IsTopLevel()) {
|
||||
return toplevel;
|
||||
}
|
||||
toplevel = static_cast<nsWindow*>(toplevel->mParent);
|
||||
}
|
||||
|
||||
ALOG(
|
||||
@@ -2586,10 +2566,8 @@ LayoutDeviceIntRect nsWindow::GetScreenBounds() {
|
||||
LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() {
|
||||
LayoutDeviceIntPoint p(0, 0);
|
||||
|
||||
for (nsWindow* w = this; !!w; w = w->mParent) {
|
||||
p.x += w->mBounds.x;
|
||||
p.y += w->mBounds.y;
|
||||
|
||||
for (nsWindow* w = this; !!w; w = static_cast<nsWindow*>(w->mParent)) {
|
||||
p += w->mBounds.TopLeft();
|
||||
if (w->IsTopLevel()) {
|
||||
break;
|
||||
}
|
||||
@@ -3080,8 +3058,7 @@ nsresult nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||
|
||||
const auto& npzc = npzcSup->GetJavaNPZC();
|
||||
const auto& bounds = FindTopLevel()->mBounds;
|
||||
aPoint.x -= bounds.x;
|
||||
aPoint.y -= bounds.y;
|
||||
aPoint -= bounds.TopLeft();
|
||||
|
||||
DispatchToUiThread(
|
||||
"nsWindow::SynthesizeNativeTouchPoint",
|
||||
@@ -3106,8 +3083,7 @@ nsresult nsWindow::SynthesizeNativeMouseEvent(
|
||||
|
||||
const auto& npzc = npzcSup->GetJavaNPZC();
|
||||
const auto& bounds = FindTopLevel()->mBounds;
|
||||
aPoint.x -= bounds.x;
|
||||
aPoint.y -= bounds.y;
|
||||
aPoint -= bounds.TopLeft();
|
||||
|
||||
int32_t nativeMessage;
|
||||
switch (aNativeMessage) {
|
||||
|
||||
@@ -71,7 +71,6 @@ class nsWindow final : public nsBaseWidget {
|
||||
bool aIsTopLevel);
|
||||
|
||||
private:
|
||||
RefPtr<nsWindow> mParent;
|
||||
nsCOMPtr<nsIUserIdleServiceInternal> mIdleService;
|
||||
mozilla::ScreenIntCoord mDynamicToolbarMaxHeight{0};
|
||||
mozilla::ScreenIntMargin mSafeAreaInsets;
|
||||
@@ -159,8 +158,7 @@ class nsWindow final : public nsBaseWidget {
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
InitData* aInitData) override;
|
||||
void Destroy() override;
|
||||
void SetParent(nsIWidget* aNewParent) override;
|
||||
nsIWidget* GetParent(void) override;
|
||||
void DidChangeParent(nsIWidget* aNewParent) override;
|
||||
float GetDPI() override;
|
||||
double GetDefaultScaleInternal() override;
|
||||
void Show(bool aState) override;
|
||||
|
||||
@@ -304,8 +304,6 @@ class nsChildView final : public nsBaseWidget {
|
||||
void Show(bool aState) override;
|
||||
bool IsVisible() const override;
|
||||
|
||||
void SetParent(nsIWidget* aNewParent) override;
|
||||
nsIWidget* GetParent() override;
|
||||
float GetDPI() override;
|
||||
|
||||
void Move(double aX, double aY) override;
|
||||
@@ -463,8 +461,6 @@ class nsChildView final : public nsBaseWidget {
|
||||
const bool aIsVertical,
|
||||
const LayoutDeviceIntPoint& aPoint) override;
|
||||
|
||||
void ResetParent();
|
||||
|
||||
static bool DoHasPendingInputEvent();
|
||||
static uint32_t GetCurrentInputEventCount();
|
||||
static void UpdateCurrentInputEventCount();
|
||||
@@ -473,7 +469,7 @@ class nsChildView final : public nsBaseWidget {
|
||||
|
||||
nsCocoaWindow* GetAppWindowWidget() const;
|
||||
|
||||
void ReparentNativeWidget(nsIWidget* aNewParent) override;
|
||||
void DidChangeParent(nsIWidget*) override;
|
||||
|
||||
mozilla::widget::TextInputHandler* GetTextInputHandler() {
|
||||
return mTextInputHandler;
|
||||
@@ -562,7 +558,6 @@ class nsChildView final : public nsBaseWidget {
|
||||
InputContext mInputContext;
|
||||
|
||||
NSView* mParentView;
|
||||
nsCOMPtr<nsIWidget> mParentWidget;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
// weak ref to this childview's associated mozAccessible for speed reasons
|
||||
|
||||
@@ -228,22 +228,7 @@ nsChildView::nsChildView()
|
||||
mIsDispatchPaint(false) {}
|
||||
|
||||
nsChildView::~nsChildView() {
|
||||
// Notify the children that we're gone. childView->ResetParent() can change
|
||||
// our list of children while it's being iterated, so the way we iterate the
|
||||
// list must allow for this.
|
||||
for (nsIWidget* kid = mLastChild; kid;) {
|
||||
const WindowType kidType = kid->GetWindowType();
|
||||
if (kidType == WindowType::Child) {
|
||||
RefPtr<nsChildView> childView = static_cast<nsChildView*>(kid);
|
||||
kid = kid->GetPrevSibling();
|
||||
childView->ResetParent();
|
||||
} else {
|
||||
RefPtr<nsCocoaWindow> childWindow = static_cast<nsCocoaWindow*>(kid);
|
||||
kid = kid->GetPrevSibling();
|
||||
RemoveChild(childWindow);
|
||||
childWindow->mParent = nullptr;
|
||||
}
|
||||
}
|
||||
RemoveAllChildren();
|
||||
|
||||
NS_WARNING_ASSERTION(
|
||||
mOnDestroyCalled,
|
||||
@@ -263,7 +248,7 @@ nsChildView::~nsChildView() {
|
||||
// mGeckoChild are used throughout the ChildView class to tell if it's safe
|
||||
// to use a ChildView object.
|
||||
[mView widgetDestroyed]; // Safe if mView is nil.
|
||||
mParentWidget = nil;
|
||||
SetParent(nullptr);
|
||||
TearDownView(); // Safe if called twice.
|
||||
}
|
||||
|
||||
@@ -284,14 +269,8 @@ nsresult nsChildView::Create(nsIWidget* aParent,
|
||||
|
||||
BaseCreate(aParent, aInitData);
|
||||
|
||||
mParentWidget = nil;
|
||||
mParentView = nil;
|
||||
if (aParent) {
|
||||
// This is the popup window case. aParent is the nsCocoaWindow for the
|
||||
// popup window, and mParentView will be its content view.
|
||||
mParentWidget = aParent;
|
||||
mParentView = (NSView*)aParent->GetNativeData(NS_NATIVE_WIDGET);
|
||||
}
|
||||
mParentView =
|
||||
mParent ? (NSView*)mParent->GetNativeData(NS_NATIVE_WIDGET) : nullptr;
|
||||
|
||||
// create our parallel NSView and hook it up to our parent. Recall
|
||||
// that NS_NATIVE_WIDGET is the NSView.
|
||||
@@ -305,10 +284,11 @@ nsresult nsChildView::Create(nsIWidget* aParent,
|
||||
// If this view was created in a Gecko view hierarchy, the initial state
|
||||
// is hidden. If the view is attached only to a native NSView but has
|
||||
// no Gecko parent (as in embedding), the initial state is visible.
|
||||
if (mParentWidget)
|
||||
if (mParent) {
|
||||
[mView setHidden:YES];
|
||||
else
|
||||
} else {
|
||||
mVisible = true;
|
||||
}
|
||||
|
||||
// Hook it up in the NSView hierarchy.
|
||||
if (mParentView) {
|
||||
@@ -317,8 +297,9 @@ nsresult nsChildView::Create(nsIWidget* aParent,
|
||||
|
||||
// if this is a ChildView, make sure that our per-window data
|
||||
// is set up
|
||||
if ([mView isKindOfClass:[ChildView class]])
|
||||
if ([mView isKindOfClass:[ChildView class]]) {
|
||||
[[WindowDataMap sharedWindowDataMap] ensureDataForWindow:[mView window]];
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mTextInputHandler, "mTextInputHandler has already existed");
|
||||
mTextInputHandler = new TextInputHandler(this, mView);
|
||||
@@ -394,7 +375,6 @@ void nsChildView::Destroy() {
|
||||
nsBaseWidget::Destroy();
|
||||
|
||||
NotifyWindowDestroyed();
|
||||
mParentWidget = nil;
|
||||
|
||||
TearDownView();
|
||||
|
||||
@@ -543,62 +523,27 @@ void nsChildView::Show(bool aState) {
|
||||
}
|
||||
|
||||
// Change the parent of this widget
|
||||
void nsChildView::SetParent(nsIWidget* aNewParent) {
|
||||
void nsChildView::DidChangeParent(nsIWidget*) {
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
if (mOnDestroyCalled) return;
|
||||
if (mOnDestroyCalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
|
||||
if (mParentWidget) {
|
||||
mParentWidget->RemoveChild(this);
|
||||
}
|
||||
|
||||
if (aNewParent) {
|
||||
ReparentNativeWidget(aNewParent);
|
||||
} else {
|
||||
[mView removeFromSuperview];
|
||||
mParentView = nil;
|
||||
}
|
||||
|
||||
mParentWidget = aNewParent;
|
||||
|
||||
if (mParentWidget) {
|
||||
mParentWidget->AddChild(this);
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
}
|
||||
|
||||
void nsChildView::ReparentNativeWidget(nsIWidget* aNewParent) {
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
MOZ_ASSERT(aNewParent, "null widget");
|
||||
|
||||
if (mOnDestroyCalled) return;
|
||||
|
||||
NSView<mozView>* newParentView =
|
||||
(NSView<mozView>*)aNewParent->GetNativeData(NS_NATIVE_WIDGET);
|
||||
NS_ENSURE_TRUE_VOID(newParentView);
|
||||
|
||||
// we hold a ref to mView, so this is safe
|
||||
[mView removeFromSuperview];
|
||||
mParentView = newParentView;
|
||||
[mParentView addSubview:mView];
|
||||
mParentView = mParent
|
||||
? (NSView<mozView>*)mParent->GetNativeData(NS_NATIVE_WIDGET)
|
||||
: nullptr;
|
||||
if (mParentView) {
|
||||
[mParentView addSubview:mView];
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
}
|
||||
|
||||
void nsChildView::ResetParent() {
|
||||
if (!mOnDestroyCalled) {
|
||||
if (mParentWidget) mParentWidget->RemoveChild(this);
|
||||
if (mView) [mView removeFromSuperview];
|
||||
}
|
||||
mParentWidget = nullptr;
|
||||
}
|
||||
|
||||
nsIWidget* nsChildView::GetParent() { return mParentWidget; }
|
||||
|
||||
float nsChildView::GetDPI() {
|
||||
float dpi = 96.0;
|
||||
nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
|
||||
@@ -653,7 +598,7 @@ LayoutDeviceIntRect nsChildView::GetBounds() {
|
||||
|
||||
LayoutDeviceIntRect nsChildView::GetClientBounds() {
|
||||
LayoutDeviceIntRect rect = GetBounds();
|
||||
if (!mParentWidget) {
|
||||
if (!mParent) {
|
||||
// For top level widgets we want the position on screen, not the position
|
||||
// of this view inside the window.
|
||||
rect.MoveTo(WidgetToScreenOffset());
|
||||
@@ -1293,7 +1238,7 @@ nsresult nsChildView::DispatchEvent(WidgetGUIEvent* event,
|
||||
// If the listener is NULL, check if the parent is a popup. If it is, then
|
||||
// this child is the popup content view attached to a popup. Get the
|
||||
// listener from the parent popup instead.
|
||||
nsCOMPtr<nsIWidget> parentWidget = mParentWidget;
|
||||
nsCOMPtr<nsIWidget> parentWidget = mParent;
|
||||
if (!listener && parentWidget) {
|
||||
if (parentWidget->GetWindowType() == WindowType::Popup) {
|
||||
// Check just in case event->mWidget isn't this widget
|
||||
@@ -1314,11 +1259,10 @@ nsresult nsChildView::DispatchEvent(WidgetGUIEvent* event,
|
||||
|
||||
nsIWidget* nsChildView::GetWidgetForListenerEvents() {
|
||||
// If there is no listener, use the parent popup's listener if that exists.
|
||||
if (!mWidgetListener && mParentWidget &&
|
||||
mParentWidget->GetWindowType() == WindowType::Popup) {
|
||||
return mParentWidget;
|
||||
if (!mWidgetListener && mParent &&
|
||||
mParent->GetWindowType() == WindowType::Popup) {
|
||||
return mParent;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -323,9 +323,6 @@ class nsCocoaWindow final : public nsBaseWidget {
|
||||
|
||||
void SetPopupWindowLevel();
|
||||
|
||||
nsIWidget* GetParent() override { return mParent; }
|
||||
void SetParent(nsIWidget*) override;
|
||||
|
||||
bool InFullScreenMode() const { return mInFullScreenMode; }
|
||||
|
||||
void PauseOrResumeCompositor(bool aPause) override;
|
||||
@@ -381,7 +378,6 @@ class nsCocoaWindow final : public nsBaseWidget {
|
||||
return nsIWidget::CreateTopLevelWindow();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> mParent;
|
||||
BaseWindow* mWindow; // our cocoa window [STRONG]
|
||||
WindowDelegate*
|
||||
mDelegate; // our delegate for processing window msgs [STRONG]
|
||||
|
||||
@@ -120,8 +120,7 @@ static void RollUpPopups(nsIRollupListener::AllowAnimations aAllowAnimations =
|
||||
}
|
||||
|
||||
nsCocoaWindow::nsCocoaWindow()
|
||||
: mParent(nullptr),
|
||||
mWindow(nil),
|
||||
: mWindow(nil),
|
||||
mDelegate(nil),
|
||||
mPopupContentView(nil),
|
||||
mFullscreenTransitionAnimation(nil),
|
||||
@@ -188,25 +187,7 @@ void nsCocoaWindow::DestroyNativeWindow() {
|
||||
nsCocoaWindow::~nsCocoaWindow() {
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
// Notify the children that we're gone. Popup windows (e.g. tooltips) can
|
||||
// have nsChildView children. 'kid' is an nsChildView object if and only if
|
||||
// its 'type' is 'WindowType::Child'.
|
||||
// childView->ResetParent() can change our list of children while it's
|
||||
// being iterated, so the way we iterate the list must allow for this.
|
||||
for (nsIWidget* kid = mLastChild; kid;) {
|
||||
const WindowType kidType = kid->GetWindowType();
|
||||
if (kidType == WindowType::Child) {
|
||||
RefPtr<nsChildView> childView = static_cast<nsChildView*>(kid);
|
||||
kid = kid->GetPrevSibling();
|
||||
childView->ResetParent();
|
||||
} else {
|
||||
RefPtr<nsCocoaWindow> childWindow = static_cast<nsCocoaWindow*>(kid);
|
||||
kid = kid->GetPrevSibling();
|
||||
RemoveChild(childWindow);
|
||||
childWindow->mParent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveAllChildren();
|
||||
if (mWindow && mWindowMadeHere) {
|
||||
CancelAllTransitions();
|
||||
DestroyNativeWindow();
|
||||
@@ -275,7 +256,6 @@ nsresult nsCocoaWindow::Create(nsIWidget* aParent, const DesktopIntRect& aRect,
|
||||
|
||||
Inherited::BaseCreate(aParent, aInitData);
|
||||
|
||||
mParent = aParent;
|
||||
mAlwaysOnTop = aInitData->mAlwaysOnTop;
|
||||
mIsAlert = aInitData->mIsAlert;
|
||||
|
||||
@@ -590,7 +570,6 @@ void nsCocoaWindow::Destroy() {
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
nsBaseWidget::Destroy();
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
void* nsCocoaWindow::GetNativeData(uint32_t aDataType) {
|
||||
@@ -686,7 +665,7 @@ void nsCocoaWindow::SetModal(bool aModal) {
|
||||
// incompatible with the modal event loop in AppWindow::ShowModal() (each of
|
||||
// these event loops is "exclusive", and can't run at the same time as other
|
||||
// (similar) event loops).
|
||||
for (auto* ancestorWidget = mParent.get(); ancestorWidget;
|
||||
for (auto* ancestorWidget = mParent; ancestorWidget;
|
||||
ancestorWidget = ancestorWidget->GetParent()) {
|
||||
if (ancestorWidget->GetWindowType() == WindowType::Child) {
|
||||
continue;
|
||||
@@ -879,20 +858,6 @@ bool nsCocoaWindow::NeedsRecreateToReshow() {
|
||||
NSScreen.screens.count > 1;
|
||||
}
|
||||
|
||||
void nsCocoaWindow::SetParent(nsIWidget* aNewParent) {
|
||||
// TODO(emilio): Do we need to reparent the native widget? We never did...
|
||||
|
||||
if (mParent) {
|
||||
mParent->RemoveChild(this);
|
||||
}
|
||||
|
||||
mParent = aNewParent;
|
||||
|
||||
if (mParent) {
|
||||
mParent->AddChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
WindowRenderer* nsCocoaWindow::GetWindowRenderer() {
|
||||
if (mPopupContentView) {
|
||||
return mPopupContentView->GetWindowRenderer();
|
||||
|
||||
@@ -560,7 +560,8 @@ void nsWindow::OnDestroy(void) {
|
||||
|
||||
// Remove association between this object and its parent and siblings.
|
||||
nsBaseWidget::Destroy();
|
||||
mParent = nullptr;
|
||||
|
||||
RemoveAllChildren();
|
||||
|
||||
NotifyWindowDestroyed();
|
||||
}
|
||||
@@ -667,8 +668,6 @@ void nsWindow::Destroy() {
|
||||
OnDestroy();
|
||||
}
|
||||
|
||||
nsIWidget* nsWindow::GetParent() { return mParent; }
|
||||
|
||||
float nsWindow::GetDPI() {
|
||||
float dpi = 96.0f;
|
||||
nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
|
||||
@@ -719,41 +718,6 @@ DesktopToLayoutDeviceScale nsWindow::GetDesktopToDeviceScaleByScreen() {
|
||||
return nsBaseWidget::GetDesktopToDeviceScale();
|
||||
}
|
||||
|
||||
// Reparent a child window to a new parent.
|
||||
void nsWindow::SetParent(nsIWidget* aNewParent) {
|
||||
LOG("nsWindow::SetParent() new parent %p", aNewParent);
|
||||
if (!mIsChildWindow) {
|
||||
NS_WARNING("Used by child widgets only");
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
||||
if (mParent) {
|
||||
mParent->RemoveChild(this);
|
||||
}
|
||||
mParent = aNewParent;
|
||||
|
||||
// We're already deleted, quit.
|
||||
if (!mGdkWindow || mIsDestroyed || !aNewParent) {
|
||||
return;
|
||||
}
|
||||
aNewParent->AddChild(this);
|
||||
|
||||
auto* newParent = static_cast<nsWindow*>(aNewParent);
|
||||
|
||||
// New parent is deleted, quit.
|
||||
if (newParent->mIsDestroyed) {
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
GdkWindow* window = GetToplevelGdkWindow();
|
||||
GdkWindow* parentWindow = newParent->GetToplevelGdkWindow();
|
||||
LOG(" child GdkWindow %p set parent GdkWindow %p", window, parentWindow);
|
||||
gdk_window_reparent(window, parentWindow, 0, 0);
|
||||
SetHasMappedToplevel(newParent && newParent->mHasMappedToplevel);
|
||||
}
|
||||
|
||||
bool nsWindow::WidgetTypeSupportsAcceleration() {
|
||||
if (IsSmallPopup()) {
|
||||
return false;
|
||||
@@ -764,18 +728,26 @@ bool nsWindow::WidgetTypeSupportsAcceleration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
|
||||
MOZ_ASSERT(aNewParent, "null widget");
|
||||
MOZ_ASSERT(!mIsDestroyed, "");
|
||||
MOZ_ASSERT(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
|
||||
MOZ_ASSERT(
|
||||
!mParent,
|
||||
"nsWindow::ReparentNativeWidget() works on toplevel windows only.");
|
||||
void nsWindow::DidChangeParent(nsIWidget* aOldParent) {
|
||||
LOG("nsWindow::DidChangeParent new parent %p -> %p\n", aOldParent, mParent);
|
||||
if (!mParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* newParent = static_cast<nsWindow*>(mParent);
|
||||
if (mIsDestroyed || newParent->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsTopLevelWindowType()) {
|
||||
GdkWindow* window = GetToplevelGdkWindow();
|
||||
GdkWindow* parentWindow = newParent->GetToplevelGdkWindow();
|
||||
gdk_window_reparent(window, parentWindow, 0, 0);
|
||||
SetHasMappedToplevel(newParent->mHasMappedToplevel);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* newParent = static_cast<nsWindow*>(aNewParent);
|
||||
GtkWindow* newParentWidget = GTK_WINDOW(newParent->GetGtkWidget());
|
||||
|
||||
LOG("nsWindow::ReparentNativeWidget new parent %p\n", newParent);
|
||||
GtkWindowSetTransientFor(GTK_WINDOW(mShell), newParentWidget);
|
||||
}
|
||||
|
||||
@@ -5875,8 +5847,6 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
|
||||
// initialize all the common bits of this class
|
||||
BaseCreate(aParent, aInitData);
|
||||
|
||||
// and do our common creation
|
||||
mParent = aParent;
|
||||
// save our bounds
|
||||
mBounds = aRect;
|
||||
LOG(" mBounds: x:%d y:%d w:%d h:%d\n", mBounds.x, mBounds.y, mBounds.width,
|
||||
|
||||
@@ -162,13 +162,11 @@ class nsWindow final : public nsBaseWidget {
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
InitData* aInitData) override;
|
||||
void Destroy() override;
|
||||
nsIWidget* GetParent() override;
|
||||
float GetDPI() override;
|
||||
double GetDefaultScaleInternal() override;
|
||||
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override;
|
||||
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen()
|
||||
override;
|
||||
void SetParent(nsIWidget* aNewParent) override;
|
||||
void SetModal(bool aModal) override;
|
||||
bool IsVisible() const override;
|
||||
bool IsMapped() const override;
|
||||
@@ -334,7 +332,7 @@ class nsWindow final : public nsBaseWidget {
|
||||
void SetTransparencyMode(TransparencyMode aMode) override;
|
||||
TransparencyMode GetTransparencyMode() override;
|
||||
void SetInputRegion(const InputRegion&) override;
|
||||
void ReparentNativeWidget(nsIWidget* aNewParent) override;
|
||||
void DidChangeParent(nsIWidget* aOldParent) override;
|
||||
|
||||
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
|
||||
NativeMouseMessage aNativeMessage,
|
||||
@@ -492,7 +490,6 @@ class nsWindow final : public nsBaseWidget {
|
||||
|
||||
void RegisterTouchWindow() override;
|
||||
|
||||
nsCOMPtr<nsIWidget> mParent;
|
||||
mozilla::Atomic<int, mozilla::Relaxed> mCeiledScaleFactor{1};
|
||||
double mFractionalScaleFactor = 0.0;
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ HeadlessWidget::HeadlessWidget()
|
||||
mVisible(false),
|
||||
mDestroyed(false),
|
||||
mAlwaysOnTop(false),
|
||||
mTopLevel(nullptr),
|
||||
mCompositorWidget(nullptr),
|
||||
mSizeMode(nsSizeMode_Normal),
|
||||
mLastSizeMode(nsSizeMode_Normal),
|
||||
@@ -120,21 +119,13 @@ void HeadlessWidget::Destroy() {
|
||||
nsresult HeadlessWidget::Create(nsIWidget* aParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
widget::InitData* aInitData) {
|
||||
// FIXME(emilio): Why aParent = nullptr? Should just pass in aParent, most
|
||||
// likely?
|
||||
BaseCreate(/* aParent = */ nullptr, aInitData);
|
||||
BaseCreate(aParent, aInitData);
|
||||
|
||||
mBounds = aRect;
|
||||
mRestoreBounds = aRect;
|
||||
|
||||
mAlwaysOnTop = aInitData && aInitData->mAlwaysOnTop;
|
||||
|
||||
if (aParent) {
|
||||
mTopLevel = aParent->GetTopLevelWidget();
|
||||
} else {
|
||||
mTopLevel = this;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -144,8 +135,6 @@ void HeadlessWidget::GetCompositorWidgetInitData(
|
||||
mozilla::widget::HeadlessCompositorWidgetInitData(GetClientSize());
|
||||
}
|
||||
|
||||
nsIWidget* HeadlessWidget::GetTopLevelWidget() { return mTopLevel; }
|
||||
|
||||
void HeadlessWidget::RaiseWindow() {
|
||||
MOZ_ASSERT(
|
||||
mWindowType == WindowType::TopLevel || mWindowType == WindowType::Dialog,
|
||||
@@ -202,7 +191,9 @@ void HeadlessWidget::SetFocus(Raise aRaise,
|
||||
|
||||
// The toplevel only becomes active if it's currently visible; otherwise, it
|
||||
// will be activated anyway when it's shown.
|
||||
if (topLevel->IsVisible()) topLevel->RaiseWindow();
|
||||
if (topLevel->IsVisible()) {
|
||||
topLevel->RaiseWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +230,7 @@ void HeadlessWidget::MoveInternal(int32_t aX, int32_t aY) {
|
||||
}
|
||||
|
||||
LayoutDeviceIntPoint HeadlessWidget::WidgetToScreenOffset() {
|
||||
return mTopLevel->GetBounds().TopLeft();
|
||||
return GetTopLevelWidget()->GetBounds().TopLeft();
|
||||
}
|
||||
|
||||
WindowRenderer* HeadlessWidget::GetWindowRenderer() {
|
||||
|
||||
@@ -54,8 +54,6 @@ class HeadlessWidget : public nsBaseWidget {
|
||||
widget::InitData* aInitData = nullptr) override;
|
||||
using nsBaseWidget::Create; // for Create signature not overridden here
|
||||
|
||||
nsIWidget* GetTopLevelWidget() override;
|
||||
|
||||
void GetCompositorWidgetInitData(
|
||||
mozilla::widget::CompositorWidgetInitData* aInitData) override;
|
||||
|
||||
@@ -144,7 +142,6 @@ class HeadlessWidget : public nsBaseWidget {
|
||||
bool mVisible;
|
||||
bool mDestroyed;
|
||||
bool mAlwaysOnTop;
|
||||
nsIWidget* mTopLevel;
|
||||
HeadlessCompositorWidget* mCompositorWidget;
|
||||
nsSizeMode mSizeMode;
|
||||
// The size mode before entering fullscreen mode.
|
||||
|
||||
@@ -420,8 +420,29 @@ void nsBaseWidget::BaseCreate(nsIWidget* aParent, widget::InitData* aInitData) {
|
||||
mIsPIPWindow = aInitData->mPIPWindow;
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
aParent->AddChild(this);
|
||||
mParent = aParent;
|
||||
if (mParent) {
|
||||
mParent->AddToChildList(this);
|
||||
}
|
||||
}
|
||||
|
||||
void nsIWidget::SetParent(nsIWidget* aNewParent) {
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
||||
nsCOMPtr<nsIWidget> oldParent = mParent;
|
||||
if (mParent) {
|
||||
mParent->RemoveFromChildList(this);
|
||||
}
|
||||
mParent = aNewParent;
|
||||
if (mParent) {
|
||||
mParent->AddToChildList(this);
|
||||
}
|
||||
DidChangeParent(oldParent);
|
||||
}
|
||||
|
||||
void nsIWidget::RemoveAllChildren() {
|
||||
while (nsCOMPtr<nsIWidget> kid = mLastChild) {
|
||||
kid->SetParent(nullptr);
|
||||
MOZ_ASSERT(kid != mLastChild);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,40 +538,20 @@ void nsBaseWidget::Destroy() {
|
||||
// Just in case our parent is the only ref to us
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
// disconnect from the parent
|
||||
nsIWidget* parent = GetParent();
|
||||
if (parent) {
|
||||
parent->RemoveChild(this);
|
||||
if (mParent) {
|
||||
mParent->RemoveFromChildList(this);
|
||||
}
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this nsBaseWidget parent
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget* nsBaseWidget::GetParent(void) { return nullptr; }
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this nsBaseWidget top level widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget* nsBaseWidget::GetTopLevelWidget() {
|
||||
nsIWidget *topLevelWidget = nullptr, *widget = this;
|
||||
while (widget) {
|
||||
topLevelWidget = widget;
|
||||
widget = widget->GetParent();
|
||||
nsIWidget* nsIWidget::GetTopLevelWidget() {
|
||||
auto* cur = this;
|
||||
while (nsIWidget* parent = cur->GetParent()) {
|
||||
cur = parent;
|
||||
}
|
||||
return topLevelWidget;
|
||||
return cur;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget* nsBaseWidget::GetSheetWindowParent(void) { return nullptr; }
|
||||
|
||||
float nsBaseWidget::GetDPI() { return 96.0f; }
|
||||
|
||||
void nsBaseWidget::NotifyAPZOfDPIChange() {
|
||||
@@ -597,7 +598,7 @@ RefPtr<mozilla::VsyncDispatcher> nsIWidget::GetVsyncDispatcher() {
|
||||
// Add a child to the list of children
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsBaseWidget::AddChild(nsIWidget* aChild) {
|
||||
void nsIWidget::AddToChildList(nsIWidget* aChild) {
|
||||
MOZ_ASSERT(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
|
||||
"aChild not properly removed from its old child list");
|
||||
|
||||
@@ -618,7 +619,7 @@ void nsBaseWidget::AddChild(nsIWidget* aChild) {
|
||||
// Remove a child from the list of children
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsBaseWidget::RemoveChild(nsIWidget* aChild) {
|
||||
void nsIWidget::RemoveFromChildList(nsIWidget* aChild) {
|
||||
MOZ_ASSERT(aChild->GetParent() == this, "Not one of our kids!");
|
||||
|
||||
if (mLastChild == aChild) {
|
||||
|
||||
@@ -168,13 +168,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
nsIWidgetListener* GetWidgetListener() const override;
|
||||
void SetWidgetListener(nsIWidgetListener* alistener) override;
|
||||
void Destroy() override;
|
||||
void SetParent(nsIWidget* aNewParent) override {};
|
||||
nsIWidget* GetParent() override;
|
||||
nsIWidget* GetTopLevelWidget() override;
|
||||
nsIWidget* GetSheetWindowParent(void) override;
|
||||
float GetDPI() override;
|
||||
void AddChild(nsIWidget* aChild) override;
|
||||
void RemoveChild(nsIWidget* aChild) override;
|
||||
|
||||
void GetWorkspaceID(nsAString& workspaceID) override;
|
||||
void MoveToWorkspace(const nsAString& workspaceID) override;
|
||||
@@ -363,8 +357,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
|
||||
PopupLevel GetPopupLevel() { return mPopupLevel; }
|
||||
|
||||
void ReparentNativeWidget(nsIWidget* aNewParent) override {}
|
||||
|
||||
const SizeConstraints GetSizeConstraints() override;
|
||||
void SetSizeConstraints(const SizeConstraints& aConstraints) override;
|
||||
|
||||
|
||||
@@ -333,6 +333,7 @@ struct AutoObserverNotifier {
|
||||
*/
|
||||
class nsIWidget : public nsISupports {
|
||||
protected:
|
||||
friend class nsBaseWidget;
|
||||
typedef mozilla::dom::BrowserChild BrowserChild;
|
||||
|
||||
public:
|
||||
@@ -398,13 +399,7 @@ class nsIWidget : public nsISupports {
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
|
||||
|
||||
nsIWidget()
|
||||
: mLastChild(nullptr),
|
||||
mPrevSibling(nullptr),
|
||||
mOnDestroyCalled(false),
|
||||
mWindowType(WindowType::Child) {
|
||||
ClearNativeTouchSequence(nullptr);
|
||||
}
|
||||
nsIWidget() = default;
|
||||
|
||||
/**
|
||||
* Create and initialize a widget.
|
||||
@@ -529,7 +524,7 @@ class nsIWidget : public nsISupports {
|
||||
*
|
||||
* @param aNewParent new parent
|
||||
*/
|
||||
virtual void SetParent(nsIWidget* aNewParent) = 0;
|
||||
void SetParent(nsIWidget* aNewParent);
|
||||
|
||||
/**
|
||||
* Return the parent Widget of this Widget or nullptr if this is a
|
||||
@@ -538,24 +533,17 @@ class nsIWidget : public nsISupports {
|
||||
* @return the parent widget or nullptr if it does not have a parent
|
||||
*
|
||||
*/
|
||||
virtual nsIWidget* GetParent(void) = 0;
|
||||
nsIWidget* GetParent() const { return mParent; }
|
||||
|
||||
/** Gets called when mParent changes after creation. */
|
||||
virtual void DidChangeParent(nsIWidget* aOldParent) {}
|
||||
|
||||
/**
|
||||
* Return the top level Widget of this Widget
|
||||
*
|
||||
* @return the top level widget
|
||||
*/
|
||||
virtual nsIWidget* GetTopLevelWidget() = 0;
|
||||
|
||||
/**
|
||||
* Return the top (non-sheet) parent of this Widget if it's a sheet,
|
||||
* or nullptr if this isn't a sheet (or some other error occurred).
|
||||
* Sheets are only supported on some platforms (currently only macOS).
|
||||
*
|
||||
* @return the top (non-sheet) parent widget or nullptr
|
||||
*
|
||||
*/
|
||||
virtual nsIWidget* GetSheetWindowParent(void) = 0;
|
||||
nsIWidget* GetTopLevelWidget();
|
||||
|
||||
/**
|
||||
* Return the physical DPI of the screen containing the window ...
|
||||
@@ -1209,15 +1197,15 @@ class nsIWidget : public nsISupports {
|
||||
/**
|
||||
* Internal methods
|
||||
*/
|
||||
|
||||
//@{
|
||||
virtual void AddChild(nsIWidget* aChild) = 0;
|
||||
virtual void RemoveChild(nsIWidget* aChild) = 0;
|
||||
virtual void* GetNativeData(uint32_t aDataType) = 0;
|
||||
virtual void FreeNativeData(void* data, uint32_t aDataType) = 0; //~~~
|
||||
|
||||
//@}
|
||||
protected:
|
||||
void AddToChildList(nsIWidget* aChild);
|
||||
void RemoveFromChildList(nsIWidget* aChild);
|
||||
void RemoveAllChildren();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Set the widget's title.
|
||||
* Must be called after Create.
|
||||
@@ -1850,13 +1838,6 @@ class nsIWidget : public nsISupports {
|
||||
|
||||
static already_AddRefed<nsIWidget> CreateHeadlessWidget();
|
||||
|
||||
/**
|
||||
* Reparent this widget's native widget.
|
||||
* @param aNewParent the native widget of aNewParent is the new native
|
||||
* parent widget
|
||||
*/
|
||||
virtual void ReparentNativeWidget(nsIWidget* aNewParent) = 0;
|
||||
|
||||
/**
|
||||
* Return true if widget has it's own GL context
|
||||
*/
|
||||
@@ -2090,12 +2071,14 @@ class nsIWidget : public nsISupports {
|
||||
// lastchild pointers are weak, which is fine as long as they are
|
||||
// maintained properly.
|
||||
nsCOMPtr<nsIWidget> mFirstChild;
|
||||
nsIWidget* MOZ_NON_OWNING_REF mLastChild;
|
||||
nsIWidget* MOZ_NON_OWNING_REF mLastChild = nullptr;
|
||||
nsCOMPtr<nsIWidget> mNextSibling;
|
||||
nsIWidget* MOZ_NON_OWNING_REF mPrevSibling;
|
||||
nsIWidget* MOZ_NON_OWNING_REF mPrevSibling = nullptr;
|
||||
// Keeps us alive.
|
||||
nsIWidget* MOZ_NON_OWNING_REF mParent = nullptr;
|
||||
// When Destroy() is called, the sub class should set this true.
|
||||
bool mOnDestroyCalled;
|
||||
WindowType mWindowType;
|
||||
bool mOnDestroyCalled = false;
|
||||
WindowType mWindowType = WindowType::Child;
|
||||
WidgetType mWidgetType = WidgetType::Native;
|
||||
};
|
||||
|
||||
|
||||
@@ -880,7 +880,6 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
|
||||
nsToolkit::GetToolkit();
|
||||
|
||||
BaseCreate(aParent, aInitData);
|
||||
mParent = aParent;
|
||||
|
||||
HWND parent =
|
||||
aParent ? (HWND)aParent->GetNativeData(NS_NATIVE_WINDOW) : nullptr;
|
||||
@@ -1448,54 +1447,16 @@ void nsWindow::DissociateFromNativeWindow() {
|
||||
mPrevWndProc.reset();
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* SECTION: nsIWidget::SetParent, nsIWidget::GetParent
|
||||
*
|
||||
* Set or clear the parent widgets using window properties, and
|
||||
* handles calculating native parent handles.
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Get and set parent widgets
|
||||
void nsWindow::SetParent(nsIWidget* aNewParent) {
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
nsIWidget* parent = GetParent();
|
||||
if (parent) {
|
||||
parent->RemoveChild(this);
|
||||
}
|
||||
|
||||
mParent = aNewParent;
|
||||
|
||||
if (aNewParent) {
|
||||
ReparentNativeWidget(aNewParent);
|
||||
aNewParent->AddChild(this);
|
||||
void nsWindow::DidChangeParent(nsIWidget*) {
|
||||
if (mWindowType == WindowType::Popup || !mWnd) {
|
||||
return;
|
||||
}
|
||||
if (mWnd) {
|
||||
// If we have no parent, SetParent should return the desktop.
|
||||
VERIFY(::SetParent(mWnd, nullptr));
|
||||
RecreateDirectManipulationIfNeeded();
|
||||
}
|
||||
HWND newParent =
|
||||
mParent ? (HWND)mParent->GetNativeData(NS_NATIVE_WINDOW) : nullptr;
|
||||
::SetParent(mWnd, newParent);
|
||||
RecreateDirectManipulationIfNeeded();
|
||||
}
|
||||
|
||||
void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
|
||||
MOZ_ASSERT(aNewParent, "null widget");
|
||||
|
||||
mParent = aNewParent;
|
||||
if (mWindowType == WindowType::Popup) {
|
||||
return;
|
||||
}
|
||||
HWND newParent = (HWND)aNewParent->GetNativeData(NS_NATIVE_WINDOW);
|
||||
NS_ASSERTION(newParent, "Parent widget has a null native window handle");
|
||||
if (newParent && mWnd) {
|
||||
::SetParent(mWnd, newParent);
|
||||
RecreateDirectManipulationIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
nsIWidget* nsWindow::GetParent() { return mParent; }
|
||||
|
||||
static int32_t RoundDown(double aDouble) {
|
||||
return aDouble > 0 ? static_cast<int32_t>(floor(aDouble))
|
||||
: static_cast<int32_t>(ceil(aDouble));
|
||||
@@ -6896,7 +6857,6 @@ void nsWindow::OnDestroy() {
|
||||
|
||||
// Disconnects us from our parent, will call our GetParent().
|
||||
nsBaseWidget::Destroy();
|
||||
mParent = nullptr;
|
||||
|
||||
// Release references to children, device context, toolkit, and app shell.
|
||||
nsBaseWidget::OnDestroy();
|
||||
|
||||
@@ -198,10 +198,9 @@ class nsWindow final : public nsBaseWidget {
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
InitData* aInitData = nullptr) override;
|
||||
void Destroy() override;
|
||||
void SetParent(nsIWidget* aNewParent) override;
|
||||
nsIWidget* GetParent(void) override;
|
||||
float GetDPI() override;
|
||||
double GetDefaultScaleInternal() override;
|
||||
void DidChangeParent(nsIWidget* aOldParent) override;
|
||||
int32_t LogToPhys(double aValue);
|
||||
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override {
|
||||
if (mozilla::widget::WinUtils::IsPerMonitorDPIAware()) {
|
||||
@@ -385,8 +384,6 @@ class nsWindow final : public nsBaseWidget {
|
||||
mTaskbarPreview = do_GetWeakReference(preview);
|
||||
}
|
||||
|
||||
void ReparentNativeWidget(nsIWidget* aNewParent) override;
|
||||
|
||||
// Open file picker tracking
|
||||
void PickerOpen();
|
||||
void PickerClosed();
|
||||
@@ -762,7 +759,6 @@ class nsWindow final : public nsBaseWidget {
|
||||
|
||||
InputContext mInputContext;
|
||||
|
||||
nsCOMPtr<nsIWidget> mParent;
|
||||
nsIntSize mLastSize = nsIntSize(0, 0);
|
||||
nsIntPoint mLastPoint;
|
||||
HWND mWnd = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user