From eaf160c5861eed34410ea28b8725c4a0eb423cc1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Nov 2015 15:20:05 +0100 Subject: Add a manual test for cursors in multi-screen/High DPI setups. Change-Id: I4c0baeaf01f0b3d6162a16ef7fda822f5a4cb1db Task-number: QTBUG-49511 Reviewed-by: Joerg Bornemann --- tests/manual/qcursor/qcursor.pro | 2 +- tests/manual/qcursor/qcursorhighdpi/main.cpp | 321 +++++++++++++++++++++ .../qcursor/qcursorhighdpi/qcursorhighdpi.pro | 6 + 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 tests/manual/qcursor/qcursorhighdpi/main.cpp create mode 100644 tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro (limited to 'tests') diff --git a/tests/manual/qcursor/qcursor.pro b/tests/manual/qcursor/qcursor.pro index af082a4b82..0b5c2b1945 100644 --- a/tests/manual/qcursor/qcursor.pro +++ b/tests/manual/qcursor/qcursor.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = allcursors grab_override +SUBDIRS = allcursors grab_override qcursorhighdpi diff --git a/tests/manual/qcursor/qcursorhighdpi/main.cpp b/tests/manual/qcursor/qcursorhighdpi/main.cpp new file mode 100644 index 0000000000..fc45ae00d1 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/main.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if QT_VERSION > 0x050000 +# include +# include +# include +# include +#else +# define Q_NULLPTR 0 +# define Q_DECL_OVERRIDE +#endif + +#ifdef Q_OS_WIN +# include +#endif + +#include +#include + +// 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 << ""; + } +#else + QDesktopWidget *desktop = QApplication::desktop(); + int screenNumber = desktop->screenNumber(w); + str << "Screen #" <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 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(bitmap, mask); +} + +static QCursor bitmapCursor(int size) +{ + QPair 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 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(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 MainWindowPtr; +typedef QList 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" diff --git a/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro new file mode 100644 index 0000000000..3a8fc25b33 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro @@ -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 -- cgit v1.2.3