Cocoa: Fix popup window positioning.
Popup window positions where offset on retina MacBooks
with an connected external monitor.
Fix this by cleaning up the coordinate conversion
functions:
Remove the qt_mac_flipRect overload which tries
to position the window according screen size. This
functionality does not belong inside a coordinate/
type conversion function. Also, it was using the windows's
screen instead of the main screen which is incorrect.
"Y flipping": Use the height of the first screen in
[NSScreen screens], which is documented to always
be the screen that contains the coordinate system
origin. Remove the usages of QApplication::primaryScreen()
("Don't use Qt to implement Qt").
Task-number: QTBUG-36672
Change-Id: I2354d31361f5a4c2c80035cf4c7def939218406f
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
bb10
parent
66e5f8e9dc
commit
9d2d4ad483
|
|
@ -103,23 +103,13 @@ CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget);
|
|||
CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice);
|
||||
QString qt_mac_applicationName();
|
||||
|
||||
inline int qt_mac_flipYCoordinate(int y)
|
||||
{ return QGuiApplication::primaryScreen()->geometry().height() - y; }
|
||||
|
||||
inline qreal qt_mac_flipYCoordinate(qreal y)
|
||||
{ return QGuiApplication::primaryScreen()->geometry().height() - y; }
|
||||
|
||||
inline QPointF qt_mac_flipPoint(const NSPoint &p)
|
||||
{ return QPointF(p.x, qt_mac_flipYCoordinate(p.y)); }
|
||||
|
||||
inline NSPoint qt_mac_flipPoint(const QPoint &p)
|
||||
{ return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); }
|
||||
|
||||
inline NSPoint qt_mac_flipPoint(const QPointF &p)
|
||||
{ return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); }
|
||||
int qt_mac_flipYCoordinate(int y);
|
||||
qreal qt_mac_flipYCoordinate(qreal y);
|
||||
QPointF qt_mac_flipPoint(const NSPoint &p);
|
||||
NSPoint qt_mac_flipPoint(const QPoint &p);
|
||||
NSPoint qt_mac_flipPoint(const QPointF &p);
|
||||
|
||||
NSRect qt_mac_flipRect(const QRect &rect);
|
||||
NSRect qt_mac_flipRect(const QRect &rect, QWindow *window);
|
||||
|
||||
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
|
||||
|
||||
|
|
|
|||
|
|
@ -595,47 +595,45 @@ QString qt_mac_applicationName()
|
|||
return appName;
|
||||
}
|
||||
|
||||
int qt_mac_mainScreenHeight()
|
||||
{
|
||||
// The first screen in the screens array is documented
|
||||
// to have the (0,0) origin.
|
||||
NSRect screenFrame = [[[NSScreen screens] firstObject] frame];
|
||||
return screenFrame.size.height;
|
||||
}
|
||||
|
||||
int qt_mac_flipYCoordinate(int y)
|
||||
{
|
||||
return qt_mac_mainScreenHeight() - y;
|
||||
}
|
||||
|
||||
qreal qt_mac_flipYCoordinate(qreal y)
|
||||
{
|
||||
return qt_mac_mainScreenHeight() - y;
|
||||
}
|
||||
|
||||
QPointF qt_mac_flipPoint(const NSPoint &p)
|
||||
{
|
||||
return QPointF(p.x, qt_mac_flipYCoordinate(p.y));
|
||||
}
|
||||
|
||||
NSPoint qt_mac_flipPoint(const QPoint &p)
|
||||
{
|
||||
return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y()));
|
||||
}
|
||||
|
||||
NSPoint qt_mac_flipPoint(const QPointF &p)
|
||||
{
|
||||
return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y()));
|
||||
}
|
||||
|
||||
NSRect qt_mac_flipRect(const QRect &rect)
|
||||
{
|
||||
int flippedY = qt_mac_flipYCoordinate(rect.y() + rect.height());
|
||||
return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height());
|
||||
}
|
||||
|
||||
/*
|
||||
Mac window coordinates are in the first quadrant: 0, 0 is at the lower-left
|
||||
corner of the primary screen. This function converts the given rect to an
|
||||
NSRect for the window geometry, flipping from 4th quadrant to 1st quadrant
|
||||
and simultaneously ensuring that as much of the window as possible will be
|
||||
onscreen. If the rect is too tall for the screen, the OS will reduce the
|
||||
window's height anyway; but by moving the window upwards we can have more
|
||||
of it onscreen. But the application can still control the y coordinate
|
||||
in case it really wants the window to be positioned partially offscreen.
|
||||
*/
|
||||
NSRect qt_mac_flipRect(const QRect &rect, QWindow *window)
|
||||
{
|
||||
QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window);
|
||||
int flippedY = onScreen->geometry().height() - (rect.y() + rect.height());
|
||||
QList<QScreen *> screens = QGuiApplication::screens();
|
||||
if (screens.size() > 1) {
|
||||
int height = 0;
|
||||
foreach (QScreen *scr, screens)
|
||||
height = qMax(height, scr->size().height());
|
||||
int difference = height - onScreen->geometry().height();
|
||||
if (difference > 0)
|
||||
flippedY += difference;
|
||||
else
|
||||
flippedY -= difference;
|
||||
}
|
||||
// In case of automatic positioning, try to put as much of the window onscreen as possible.
|
||||
if (window->isTopLevel() && qt_window_private(const_cast<QWindow*>(window))->positionAutomatic && flippedY < 0)
|
||||
flippedY = onScreen->geometry().height() - onScreen->availableGeometry().height() - onScreen->availableGeometry().y();
|
||||
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
|
||||
qDebug() << Q_FUNC_INFO << rect << "flippedY" << flippedY <<
|
||||
"screen" << onScreen->geometry() << "available" << onScreen->availableGeometry();
|
||||
#endif
|
||||
return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height());
|
||||
}
|
||||
|
||||
OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
|
||||
{
|
||||
// Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev)
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
|
|||
QWindowSystemInterface::handleGeometryChange(window(), rect);
|
||||
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
||||
} else if (m_nsWindow) {
|
||||
NSRect bounds = qt_mac_flipRect(rect, window());
|
||||
NSRect bounds = qt_mac_flipRect(rect);
|
||||
[m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO];
|
||||
} else {
|
||||
[m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
|
||||
|
|
@ -418,7 +418,7 @@ void QCocoaWindow::clipWindow(const NSRect &clipRect)
|
|||
|
||||
NSRect clippedWindowRect = NSZeroRect;
|
||||
if (!NSIsEmptyRect(clipRect)) {
|
||||
NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size()), window());
|
||||
NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size()));
|
||||
clippedWindowRect = NSIntersectionRect(windowFrame, clipRect);
|
||||
// Clipping top/left offsets the content. Move it back.
|
||||
NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)),
|
||||
|
|
@ -1208,7 +1208,7 @@ NSWindow * QCocoaWindow::createNSWindow()
|
|||
QCocoaAutoReleasePool pool;
|
||||
|
||||
QRect rect = initialGeometry(window(), window()->geometry(), defaultWindowWidth, defaultWindowHeight);
|
||||
NSRect frame = qt_mac_flipRect(rect, window());
|
||||
NSRect frame = qt_mac_flipRect(rect);
|
||||
|
||||
Qt::WindowType type = window()->type();
|
||||
Qt::WindowFlags flags = window()->flags();
|
||||
|
|
|
|||
Loading…
Reference in New Issue