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 <msk@nullpointer.dk>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
Thorbjørn Lund Martsum 2018-12-04 13:31:39 +01:00
parent 7863be3115
commit 7fc427ba23
5 changed files with 34 additions and 19 deletions

View File

@ -41,6 +41,7 @@
#endif
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtWidgets/private/qlabel_p.h>
#include <qapplication.h>
#include <qdesktopwidget.h>
@ -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();

View File

@ -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

View File

@ -355,6 +355,8 @@ public:
void createRecursively();
void createWinId();
void setScreenForPoint(const QPoint &pos);
void createTLExtra();
void createExtra();
void deleteExtra();

View File

@ -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) {

View File

@ -456,7 +456,6 @@ public:
bool hasMouseMoved(const QPoint &globalPos);
void adjustMenuScreen(const QPoint &p);
void updateLayoutDirection();
QPointer<QPlatformMenu> platformMenu;