Add a manual test for cursors in multi-screen/High DPI setups.
Change-Id: I4c0baeaf01f0b3d6162a16ef7fda822f5a4cb1db Task-number: QTBUG-49511 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
parent
3c56e33a27
commit
eaf160c586
@ -1,3 +1,3 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS = allcursors grab_override
|
SUBDIRS = allcursors grab_override qcursorhighdpi
|
||||||
|
321
tests/manual/qcursor/qcursorhighdpi/main.cpp
Normal file
321
tests/manual/qcursor/qcursorhighdpi/main.cpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
|
#include <QBitmap>
|
||||||
|
#include <QCursor>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
# include <QScreen>
|
||||||
|
# include <QWindow>
|
||||||
|
# include <private/qhighdpiscaling_p.h>
|
||||||
|
# include <qpa/qplatformwindow.h>
|
||||||
|
#else
|
||||||
|
# define Q_NULLPTR 0
|
||||||
|
# define Q_DECL_OVERRIDE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <qt_windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
// High DPI cursor test for testing cursor sizes in multi-screen setups.
|
||||||
|
// It creates one widget per screen with a grid of standard cursors,
|
||||||
|
// pixmap / bitmap cursors and pixmap / bitmap cursors with device pixel ratio 2.
|
||||||
|
// On the left, there is a ruler with 10 DIP marks.
|
||||||
|
// The code is meant to compile with Qt 4 also.
|
||||||
|
|
||||||
|
static QString screenInfo(const QWidget *w)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream str(&result);
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
QScreen *screen = Q_NULLPTR;
|
||||||
|
if (const QWindow *window = w->windowHandle())
|
||||||
|
screen = window->screen();
|
||||||
|
if (screen) {
|
||||||
|
str << '"' << screen->name() << "\" " << screen->size().width() << 'x'
|
||||||
|
<< screen->size().height() << ", DPR=" << screen->devicePixelRatio()
|
||||||
|
<< ", " << screen->logicalDotsPerInchX() << "DPI ";
|
||||||
|
if (QHighDpiScaling::isActive())
|
||||||
|
str << ", factor=" << QHighDpiScaling::factor(screen);
|
||||||
|
else
|
||||||
|
str << ", no scaling";
|
||||||
|
} else {
|
||||||
|
str << "<null>";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
QDesktopWidget *desktop = QApplication::desktop();
|
||||||
|
int screenNumber = desktop->screenNumber(w);
|
||||||
|
str << "Screen #" <<screenNumber << ' ' << desktop->screenGeometry(screenNumber).width()
|
||||||
|
<< 'x' << desktop->screenGeometry(screenNumber).height() << " PD: " << w->logicalDpiX() << "DPI";
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
str << ", SM_C_CURSOR: " << GetSystemMetrics(SM_CXCURSOR) << 'x' << GetSystemMetrics(SM_CYCURSOR);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for painting pixmaps and creating cursors
|
||||||
|
static QPixmap paintPixmap(int size, QColor c)
|
||||||
|
{
|
||||||
|
QPixmap result(size, size);
|
||||||
|
result.fill(c);
|
||||||
|
QPainter p(&result);
|
||||||
|
p.drawRect(QRect(QPoint(0, 0), result.size() - QSize(1, 1)));
|
||||||
|
p.drawLine(0, 0, size, size);
|
||||||
|
p.drawLine(0, size, size, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QCursor pixmapCursor(int size)
|
||||||
|
{
|
||||||
|
QCursor result(paintPixmap(size, Qt::red), size / 2, size / 2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPair<QBitmap, QBitmap> paintBitmaps(int size)
|
||||||
|
{
|
||||||
|
QBitmap bitmap(size, size);
|
||||||
|
bitmap.fill(Qt::color1);
|
||||||
|
QBitmap mask(size, size);
|
||||||
|
mask.fill(Qt::color1);
|
||||||
|
{
|
||||||
|
QPainter mp(&mask);
|
||||||
|
mp.fillRect(QRect(0, 0, size / 2, size / 2), Qt::color0);
|
||||||
|
}
|
||||||
|
return QPair<QBitmap, QBitmap>(bitmap, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QCursor bitmapCursor(int size)
|
||||||
|
{
|
||||||
|
QPair<QBitmap, QBitmap> bitmaps = paintBitmaps(size);
|
||||||
|
return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
static QCursor pixmapCursorDevicePixelRatio(int size, int dpr)
|
||||||
|
{
|
||||||
|
QPixmap pixmap = paintPixmap(dpr * size, Qt::yellow);
|
||||||
|
pixmap.setDevicePixelRatio(dpr);
|
||||||
|
return QCursor(pixmap, size / 2, size / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QCursor bitmapCursorDevicePixelRatio(int size, int dpr)
|
||||||
|
{
|
||||||
|
QPair<QBitmap, QBitmap> bitmaps = paintBitmaps(dpr * size);
|
||||||
|
bitmaps.first.setDevicePixelRatio(dpr);
|
||||||
|
bitmaps.second.setDevicePixelRatio(dpr);
|
||||||
|
return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2);
|
||||||
|
}
|
||||||
|
#endif // Qt 5
|
||||||
|
|
||||||
|
// Vertical ruler widget with 10 px marks
|
||||||
|
class VerticalRuler : public QWidget {
|
||||||
|
public:
|
||||||
|
VerticalRuler(QWidget *parent = Q_NULLPTR);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
VerticalRuler::VerticalRuler(QWidget *parent) : QWidget(parent)
|
||||||
|
{
|
||||||
|
const int screenWidth = QApplication::desktop()->screenGeometry(this).width();
|
||||||
|
setFixedWidth(screenWidth / 48); // 1920 pixel monitor ->40
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerticalRuler::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
const QSize sizeS(size());
|
||||||
|
const QPoint sizeP(sizeS.width(), sizeS.height());
|
||||||
|
const QPoint center = sizeP / 2;
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.fillRect(QRect(QPoint(0, 0), sizeS), Qt::white);
|
||||||
|
painter.drawLine(center.x(), 0, center.x(), sizeP.y());
|
||||||
|
for (int y = 0; y < sizeP.y(); y += 10)
|
||||||
|
painter.drawLine(center.x() - 5, y, center.x() + 5, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = Q_NULLPTR);
|
||||||
|
void updateScreenInfo() { m_screenInfoLabel->setText(screenInfo(this)); }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void screenChanged() { updateScreenInfo(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel *m_screenInfoLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
static QLabel *createCursorLabel(const QCursor &cursor, const QString &additionalText = QString())
|
||||||
|
{
|
||||||
|
QString labelText;
|
||||||
|
QDebug(&labelText).nospace() << cursor.shape();
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
labelText.remove(0, labelText.indexOf('(') + 1);
|
||||||
|
labelText.chop(1);
|
||||||
|
#endif // Qt 5
|
||||||
|
if (!additionalText.isEmpty())
|
||||||
|
labelText += ' ' + additionalText;
|
||||||
|
QLabel *result = new QLabel(labelText);
|
||||||
|
result->setFrameShape(QFrame::Box);
|
||||||
|
result->setCursor(cursor);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addToGrid(QWidget *w, QGridLayout *gridLayout, int columnCount, int &row, int &col)
|
||||||
|
{
|
||||||
|
gridLayout->addWidget(w, row, col);
|
||||||
|
if (col >= columnCount) {
|
||||||
|
col = 0;
|
||||||
|
row++;
|
||||||
|
} else {
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
, m_screenInfoLabel(new QLabel)
|
||||||
|
{
|
||||||
|
QString title = "Cursors ";
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
title += '(' + QGuiApplication::platformName() + ") ";
|
||||||
|
#endif
|
||||||
|
title += QT_VERSION_STR;
|
||||||
|
setWindowTitle(title);
|
||||||
|
|
||||||
|
QMenu *fileMenu = menuBar()->addMenu("File");
|
||||||
|
QAction *quitAction = fileMenu->addAction("Quit");
|
||||||
|
quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
|
||||||
|
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||||
|
|
||||||
|
QToolBar *fileToolBar = addToolBar("File");
|
||||||
|
fileToolBar->addAction(quitAction);
|
||||||
|
|
||||||
|
QWidget *cw = new QWidget;
|
||||||
|
QHBoxLayout *hLayout = new QHBoxLayout(cw);
|
||||||
|
hLayout->addWidget(new VerticalRuler(cw));
|
||||||
|
QGridLayout *gridLayout = new QGridLayout;
|
||||||
|
hLayout->addLayout(gridLayout);
|
||||||
|
|
||||||
|
const int columnCount = 5;
|
||||||
|
const int size = 32;
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
int col = 0;
|
||||||
|
for (int i = 0; i < Qt::BitmapCursor; ++i)
|
||||||
|
addToGrid(createCursorLabel(QCursor(static_cast<Qt::CursorShape>(i))), gridLayout, columnCount, row, col);
|
||||||
|
|
||||||
|
addToGrid(createCursorLabel(QCursor(pixmapCursor(size)),
|
||||||
|
QLatin1String("Plain PX ") + QString::number(size)),
|
||||||
|
gridLayout, columnCount, row, col);
|
||||||
|
|
||||||
|
addToGrid(createCursorLabel(bitmapCursor(size),
|
||||||
|
QLatin1String("Plain BM ") + QString::number(size)),
|
||||||
|
gridLayout, columnCount, row, col);
|
||||||
|
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
addToGrid(createCursorLabel(QCursor(pixmapCursorDevicePixelRatio(size, 2)),
|
||||||
|
"PX with DPR 2 " + QString::number(size)),
|
||||||
|
gridLayout, columnCount, row, col);
|
||||||
|
|
||||||
|
addToGrid(createCursorLabel(QCursor(bitmapCursorDevicePixelRatio(size, 2)),
|
||||||
|
"BM with DPR 2 " + QString::number(size)),
|
||||||
|
gridLayout, columnCount, row, col);
|
||||||
|
#endif // Qt 5
|
||||||
|
|
||||||
|
gridLayout->addWidget(m_screenInfoLabel, row + 1, 0, 1, columnCount);
|
||||||
|
|
||||||
|
setCentralWidget(cw);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef QSharedPointer<MainWindow> MainWindowPtr;
|
||||||
|
typedef QList<MainWindowPtr> MainWindowPtrList;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QStringList arguments;
|
||||||
|
std::copy(argv + 1, argv + argc, std::back_inserter(arguments));
|
||||||
|
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
if (arguments.contains("-s"))
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
else if (arguments.contains("-n"))
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
|
||||||
|
#endif // Qt 5
|
||||||
|
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
MainWindowPtrList windows;
|
||||||
|
|
||||||
|
QDesktopWidget *desktopWidget = app.desktop();
|
||||||
|
|
||||||
|
for (int s = desktopWidget->screenCount() - 1; s >= 0; --s) {
|
||||||
|
MainWindowPtr window(new MainWindow(desktopWidget->screen(s)));
|
||||||
|
const QPoint pos = desktopWidget->screenGeometry(s).center() - QPoint(200, 100);
|
||||||
|
window->move(pos);
|
||||||
|
windows.append(window);
|
||||||
|
window->show();
|
||||||
|
window->updateScreenInfo();
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
QObject::connect(window->windowHandle(), &QWindow::screenChanged,
|
||||||
|
window.data(), &MainWindow::updateScreenInfo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
#include "main.moc"
|
6
tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro
Normal file
6
tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
TEMPLATE = app
|
||||||
|
QT = core gui
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += gui-private core-private widgets
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
SOURCES += main.cpp
|
||||||
|
win32: LIBS += -lUser32
|
Loading…
x
Reference in New Issue
Block a user