mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 04:38:02 +00:00
Bug 1689682 - Long tooltips open on wrong screen r=mac-reviewers,mstange
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
This commit is contained in:
parent
bffb660313
commit
15dfd27d86
@ -148,6 +148,7 @@ void nsView::DestroyWidget() {
|
||||
}
|
||||
|
||||
mWindow = nullptr;
|
||||
ZeroDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
@ -698,6 +705,7 @@ nsresult nsView::DetachFromTopLevelWidget() {
|
||||
|
||||
mPreviousWindow = mWindow;
|
||||
mWindow = nullptr;
|
||||
ZeroDimensions();
|
||||
|
||||
mWidgetIsTopLevel = false;
|
||||
|
||||
@ -722,6 +730,7 @@ void nsView::AssertNoWindow() {
|
||||
mWindow->SetWidgetListener(nullptr);
|
||||
mWindow->Destroy();
|
||||
mWindow = nullptr;
|
||||
ZeroDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
@ -273,9 +315,6 @@ nsresult nsCocoaWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||
// 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;
|
||||
@ -292,16 +331,29 @@ nsresult nsCocoaWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -314,7 +366,9 @@ nsresult nsCocoaWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1770,7 +1824,6 @@ CGFloat nsCocoaWindow::BackingScaleFactor() {
|
||||
}
|
||||
|
||||
void nsCocoaWindow::BackingScaleFactorChanged() {
|
||||
CGFloat oldScale = mBackingScaleFactor;
|
||||
CGFloat newScale = GetBackingScaleFactor(mWindow);
|
||||
|
||||
// ignore notification if it hasn't really changed (or maybe we have
|
||||
@ -1804,23 +1857,6 @@ void nsCocoaWindow::BackingScaleFactorChanged() {
|
||||
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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user