Skip to content

Commit

Permalink
Bug 1689682 - Long tooltips open on wrong screen r=mac-reviewers,mstange
Browse files Browse the repository at this point in the history
Change ::Create(...LayoutDeviceIntRect...) to scale to desktop coordinates using the parent window scaling factor.

Change ::Create(...DesktopIntRect...) to treat the |aRect| argument as offsets when a child widget is being created per nsIWidget documentation.

Remove unnecessary logic from ::BackingScaleFactorChanged().

Change nsView to reset mDimBounds and mPosX, mPosY after destroying its widget.

Differential Revision: https://phabricator.services.mozilla.com/D106351
  • Loading branch information
hafta committed Mar 11, 2021
1 parent 341e6c4 commit fddd9b3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 25 deletions.
9 changes: 9 additions & 0 deletions view/nsView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ void nsView::DestroyWidget() {
}

mWindow = nullptr;
ZeroDimensions();
}
}

Expand Down Expand Up @@ -382,6 +383,12 @@ void nsView::SetDimensions(const nsRect& aRect, bool aPaint,
}
}

void nsView::ZeroDimensions() {
mPosX = 0;
mPosY = 0;
mDimBounds = {};
}

void nsView::NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible) {
if (!aEffectivelyVisible) {
DropMouseGrabbing();
Expand Down Expand Up @@ -698,6 +705,7 @@ nsresult nsView::DetachFromTopLevelWidget() {

mPreviousWindow = mWindow;
mWindow = nullptr;
ZeroDimensions();

mWidgetIsTopLevel = false;

Expand All @@ -722,6 +730,7 @@ void nsView::AssertNoWindow() {
mWindow->SetWidgetListener(nullptr);
mWindow->Destroy();
mWindow = nullptr;
ZeroDimensions();
}
}

Expand Down
6 changes: 6 additions & 0 deletions view/nsView.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ class nsView final : public nsIWidgetListener {
void SetDimensions(const nsRect& aRect, bool aPaint = true,
bool aResizeWidget = true);

/**
* Reset dimensions. To be used after destroying our widget to ensure stale
* dimensions will not be referenced after creating a new widget.
*/
void ZeroDimensions();

/**
* Called to indicate that the visibility of a view has been
* changed.
Expand Down
86 changes: 61 additions & 25 deletions widget/cocoa/nsCocoaWindow.mm
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,49 @@ static bool UseNativePopupWindows() {
#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */
}

DesktopToLayoutDeviceScale ParentBackingScaleFactor(nsIWidget* aParent, NSView* aParentView) {
if (aParent) {
return aParent->GetDesktopToDeviceScale();
}
NSWindow* parentWindow = [aParentView window];
if (parentWindow) {
return DesktopToLayoutDeviceScale([parentWindow backingScaleFactor]);
}
return DesktopToLayoutDeviceScale(1.0);
}

// Returns the screen rectangle for the given widget.
// Child widgets are positioned relative to this rectangle.
// Exactly one of the arguments must be non-null.
static DesktopRect GetWidgetScreenRectForChildren(nsIWidget* aWidget, NSView* aView) {
if (aWidget) {
mozilla::DesktopToLayoutDeviceScale scale = aWidget->GetDesktopToDeviceScale();
if (aWidget->WindowType() == eWindowType_child) {
return aWidget->GetScreenBounds() / scale;
}
return aWidget->GetClientBounds() / scale;
}

MOZ_RELEASE_ASSERT(aView);

// 1. Transform the view rect into window coords.
// The returned rect is in "origin bottom-left" coordinates.
NSRect rectInWindowCoordinatesOBL = [aView convertRect:[aView bounds] toView:nil];

// 2. Turn the window-coord rect into screen coords, still origin bottom-left.
NSRect rectInScreenCoordinatesOBL =
[[aView window] convertRectToScreen:rectInWindowCoordinatesOBL];

// 3. Convert the NSRect to a DesktopRect. This will convert to coordinates
// with the origin in the top left corner of the primary screen.
return DesktopRect(nsCocoaUtils::CocoaRectToGeckoRect(rectInScreenCoordinatesOBL));
}

// aRect here is specified in desktop pixels
//
// For child windows (where either aParent or aNativeParent is non-null),
// aRect.{x,y} are offsets from the origin of the parent window and not an
// absolute position.
nsresult nsCocoaWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
const DesktopIntRect& aRect, nsWidgetInitData* aInitData) {
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
Expand All @@ -273,9 +315,6 @@ static bool UseNativePopupWindows() {
// we have to provide an autorelease pool (see bug 559075).
nsAutoreleasePool localPool;

DesktopIntRect newBounds = aRect;
FitRectToVisibleAreaForScreen(newBounds, nullptr);

// Set defaults which can be overriden from aInitData in BaseCreate
mWindowType = eWindowType_toplevel;
mBorderStyle = eBorderStyle_default;
Expand All @@ -292,16 +331,29 @@ static bool UseNativePopupWindows() {
// Applications that use native popups don't want us to create popup windows.
if ((mWindowType == eWindowType_popup) && UseNativePopupWindows()) return NS_OK;

// If we have a parent widget, the new widget will be offset from the
// parent widget by aRect.{x,y}. Otherwise, we'll use aRect for the
// new widget coordinates.
DesktopIntPoint parentOrigin;

// Do we have a parent widget?
if (aParent || aNativeParent) {
DesktopRect parentDesktopRect = GetWidgetScreenRectForChildren(aParent, (NSView*)aNativeParent);
parentOrigin = gfx::RoundedToInt(parentDesktopRect.TopLeft());
}

DesktopIntRect widgetRect = aRect + parentOrigin;

nsresult rv =
CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(newBounds), mBorderStyle, false);
CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(widgetRect), mBorderStyle, false);
NS_ENSURE_SUCCESS(rv, rv);

if (mWindowType == eWindowType_popup) {
SetWindowMouseTransparent(aInitData->mMouseTransparent);

// now we can convert newBounds to device pixels for the window we created,
// now we can convert widgetRect to device pixels for the window we created,
// as the child view expects a rect expressed in the dev pix of its parent
LayoutDeviceIntRect devRect = RoundedToInt(newBounds * GetDesktopToDeviceScale());
LayoutDeviceIntRect devRect = RoundedToInt(widgetRect * GetDesktopToDeviceScale());
return CreatePopupContentView(devRect, aInitData);
}

Expand All @@ -314,7 +366,9 @@ static bool UseNativePopupWindows() {

nsresult nsCocoaWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData) {
DesktopIntRect desktopRect = RoundedToInt(aRect / GetDesktopToDeviceScale());
DesktopToLayoutDeviceScale desktopToDevScale =
ParentBackingScaleFactor(aParent, (NSView*)aNativeParent);
DesktopIntRect desktopRect = RoundedToInt(aRect / desktopToDevScale);
return Create(aParent, aNativeParent, desktopRect, aInitData);
}

Expand Down Expand Up @@ -1770,7 +1824,6 @@ static CGFloat GetBackingScaleFactor(NSWindow* aWindow) {
}

void nsCocoaWindow::BackingScaleFactorChanged() {
CGFloat oldScale = mBackingScaleFactor;
CGFloat newScale = GetBackingScaleFactor(mWindow);

// ignore notification if it hasn't really changed (or maybe we have
Expand Down Expand Up @@ -1804,23 +1857,6 @@ static CGFloat GetBackingScaleFactor(NSWindow* aWindow) {
presShell->BackingScaleFactorChanged();
}
mWidgetListener->UIResolutionChanged();

if ((mWindowType == eWindowType_popup) && (mBackingScaleFactor == 2.0)) {
// Recalculate the size and y-origin for the popup now that the backing
// scale factor has changed. After creating the popup window NSWindow,
// setting the frame when the menu is moved into the correct location
// causes the backing scale factor to change if the window is not on the
// menu bar display. Update the dimensions and y-origin here so that the
// frame is correct for the following ::Show(). Only do this when the
// scale factor changes from 1.0 to 2.0. When the scale factor changes
// from 2.0 to 1.0, the view will resize the widget before it is shown.
NSRect frame = [mWindow frame];
CGFloat previousYOrigin = frame.origin.y + frame.size.height;
frame.size.width = mBounds.Width() * (oldScale / newScale);
frame.size.height = mBounds.Height() * (oldScale / newScale);
frame.origin.y = previousYOrigin - frame.size.height;
[mWindow setFrame:frame display:NO animate:NO];
}
}

int32_t nsCocoaWindow::RoundsWidgetCoordinatesTo() {
Expand Down

0 comments on commit fddd9b3

Please sign in to comment.