From 7fc427ba23a624a433d93e1c604d870656835305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lund=20Martsum?= Date: Tue, 4 Dec 2018 13:31:39 +0100 Subject: [PATCH] QToolTip - set correct screen before resize In order to get a correctly not truncated size we need the hint to be calculated based on the screen it is about to be shown on. This patch places some code in QWidgetPrivate that is used by QMenu and QToolTip + can be used to solve similar problems in the future. Task-number: QTBUG-72306 Change-Id: I58c058761f71b4a7675b6a078be62aa813ead752 Reviewed-by: Morten Kristensen Reviewed-by: Oliver Wolff --- src/widgets/kernel/qtooltip.cpp | 9 +++++++++ src/widgets/kernel/qwidget.cpp | 21 +++++++++++++++++++++ src/widgets/kernel/qwidget_p.h | 2 ++ src/widgets/widgets/qmenu.cpp | 20 ++------------------ src/widgets/widgets/qmenu_p.h | 1 - 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 2e6575c163..9d8b0062f5 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -41,6 +41,7 @@ #endif #include +#include #include #include @@ -127,6 +128,7 @@ public: ~QTipLabel(); static QTipLabel *instance; + void adjustTooltipScreen(const QPoint &pos); void updateSize(const QPoint &pos); bool eventFilter(QObject *, QEvent *) override; @@ -222,6 +224,12 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint void QTipLabel::updateSize(const QPoint &pos) { +#ifndef Q_OS_WINRT + // ### The code below does not always work well on WinRT + // (e.g COIN fails an auto test - tst_QToolTip::qtbug64550_stylesheet - QTBUG-72652) + d_func()->setScreenForPoint(pos); +#endif + // Ensure that we get correct sizeHints by placing this window on the right screen. QFontMetrics fm(font()); QSize extra(1, 0); // Make it look good with the default ToolTip font on Mac, which has a small descent. @@ -229,6 +237,7 @@ void QTipLabel::updateSize(const QPoint &pos) ++extra.rheight(); QSize sh = sizeHint(); if (wordWrap()) { + // ### When the above WinRT code is fixed, windowhandle should be used to find the screen. QScreen *screen = QGuiApplication::screenAt(pos); if (!screen) screen = QGuiApplication::primaryScreen(); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index bcfae46155..2a94b25ec9 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -2571,6 +2571,27 @@ void QWidgetPrivate::createWinId() } } +/*! +\internal +Ensures that the widget is set on the screen point is on. This is handy getting a correct +size hint before a resize in e.g QMenu and QToolTip +*/ + +void QWidgetPrivate::setScreenForPoint(const QPoint &pos) +{ + Q_Q(QWidget); + if (!q->isWindow()) + return; + // Find the screen for pos and make the widget undertand it is on that screen. + const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr; + QScreen *actualScreen = QGuiApplication::screenAt(pos); + if (actualScreen && currentScreen != actualScreen) { + if (!windowHandle()) // Try to create a window handle if not created. + createWinId(); + if (windowHandle()) + windowHandle()->setScreen(actualScreen); + } +} /*! \internal diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index be45c4c868..6f1ce67c4c 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -355,6 +355,8 @@ public: void createRecursively(); void createWinId(); + void setScreenForPoint(const QPoint &pos); + void createTLExtra(); void createExtra(); void deleteExtra(); diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index c79e88f094..e3c29ff6ee 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -896,23 +896,6 @@ void QMenuPrivate::_q_overrideMenuActionDestroyed() menuAction=defaultMenuAction; } -void QMenuPrivate::adjustMenuScreen(const QPoint &p) -{ - Q_Q(QMenu); - // The windowHandle must point to the screen where the menu will be shown. - // The (item) size calculations depend on the menu screen, - // so a wrong screen would often cause wrong sizes (on high DPI) - const QScreen *currentScreen = q->windowHandle() ? q->windowHandle()->screen() : nullptr; - QScreen *actualScreen = QGuiApplication::screenAt(p); - if (actualScreen && currentScreen != actualScreen) { - if (!q->windowHandle()) // Try to create a window handle if not created. - createWinId(); - if (q->windowHandle()) - q->windowHandle()->setScreen(actualScreen); - itemsDirty = true; - } -} - void QMenuPrivate::updateLayoutDirection() { Q_Q(QMenu); @@ -2375,7 +2358,8 @@ void QMenu::popup(const QPoint &p, QAction *atAction) d->motions = 0; d->doChildEffects = true; d->updateLayoutDirection(); - d->adjustMenuScreen(p); + // Ensure that we get correct sizeHints by placing this window on the right screen. + d->setScreenForPoint(p); const bool contextMenu = d->isContextMenu(); if (d->lastContextMenu != contextMenu) { diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 721a35bf90..f740919dc7 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -456,7 +456,6 @@ public: bool hasMouseMoved(const QPoint &globalPos); - void adjustMenuScreen(const QPoint &p); void updateLayoutDirection(); QPointer platformMenu;