From c1ead32a84db96fd1b48e47d81511adf64cfe410 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 23 Apr 2018 11:39:56 +0200 Subject: [PATCH 01/19] Fix crash in QMacPanGestureRecognizer The reason it crashed was this: 1. Button was pressed => _panTimer started with the graphics view as destination. 2. Button was released => the graphicsview is destroyed 3. 300 ms later: Qt tries to deliver TimerEvent from _panTimer to the graphics view. Unfortunately, the graphics view is deleted, but Qt doesn't know that... (*crash*) We therefore chose to start the timer with a destination we are controlling the lifetime of: the QMacPanGestureRecognizer. Inside the timerEvent of that we can check if the actual target is already destroyed. Task-number: QTBUG-60404 Change-Id: Iff8f5b7217de42c4c5cf551ca507f0cff1c99a78 Reviewed-by: Frederik Gladhorn --- src/widgets/kernel/qmacgesturerecognizer.cpp | 15 +++++++++-- src/widgets/kernel/qmacgesturerecognizer_p.h | 4 +++ tests/auto/other/gestures/tst_gestures.cpp | 28 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp index 6dedd3c2d0..d39b93e320 100644 --- a/src/widgets/kernel/qmacgesturerecognizer.cpp +++ b/src/widgets/kernel/qmacgesturerecognizer.cpp @@ -43,6 +43,7 @@ #include "qevent.h" #include "qwidget.h" #include "qdebug.h" +#include #ifndef QT_NO_GESTURES @@ -181,6 +182,16 @@ QGesture *QMacPanGestureRecognizer::create(QObject *target) return 0; } +void QMacPanGestureRecognizer::timerEvent(QTimerEvent *ev) +{ + if (ev->timerId() == _panTimer.timerId()) { + if (_panTimer.isActive()) + _panTimer.stop(); + if (_target) + QCoreApplication::sendEvent(_target, ev); + } +} + QGestureRecognizer::Result QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *event) { @@ -195,7 +206,8 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * if (ev->touchPoints().size() == 1) { reset(gesture); _startPos = QCursor::pos(); - _panTimer.start(panBeginDelay, target); + _target = target; + _panTimer.start(panBeginDelay, this); _panCanceled = false; return QGestureRecognizer::MayBeGesture; } @@ -242,7 +254,6 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * case QEvent::Timer: { QTimerEvent *ev = static_cast(event); if (ev->timerId() == _panTimer.timerId()) { - _panTimer.stop(); if (_panCanceled) break; // Begin new pan session! diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h index be3f3266ac..e381a6cc2f 100644 --- a/src/widgets/kernel/qmacgesturerecognizer_p.h +++ b/src/widgets/kernel/qmacgesturerecognizer_p.h @@ -55,6 +55,7 @@ #include "qtimer.h" #include "qpoint.h" #include "qgesturerecognizer.h" +#include #ifndef QT_NO_GESTURES @@ -88,10 +89,13 @@ public: QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); void reset(QGesture *gesture); +protected: + void timerEvent(QTimerEvent *ev) override; private: QPointF _startPos; QBasicTimer _panTimer; bool _panCanceled; + QPointer _target; }; QT_END_NAMESPACE diff --git a/tests/auto/other/gestures/tst_gestures.cpp b/tests/auto/other/gestures/tst_gestures.cpp index 0767efb817..9abe9a77c0 100644 --- a/tests/auto/other/gestures/tst_gestures.cpp +++ b/tests/auto/other/gestures/tst_gestures.cpp @@ -331,6 +331,9 @@ private slots: void graphicsViewParentPropagation(); void panelPropagation(); void panelStacksBehindParent(); +#ifdef Q_OS_MACOS + void deleteMacPanGestureRecognizerTargetWidget(); +#endif void deleteGestureTargetWidget(); void deleteGestureTargetItem_data(); void deleteGestureTargetItem(); @@ -1807,6 +1810,31 @@ void tst_Gestures::panelStacksBehindParent() QCOMPARE(panel->gestureOverrideEventsReceived, 0); } +#ifdef Q_OS_MACOS +void tst_Gestures::deleteMacPanGestureRecognizerTargetWidget() +{ + QWidget window; + window.resize(400,400); + QGraphicsScene scene; + QGraphicsView *view = new QGraphicsView(&scene, &window); + view->resize(400, 400); + window.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTouchDevice *device = QTest::createTouchDevice(); + // QMacOSPenGestureRecognizer will start a timer on a touch press event + QTest::touchEvent(&window, device).press(1, QPoint(100, 100), &window); + delete view; + + // wait until after that the QMacOSPenGestureRecognizer timer (300ms) is triggered. + // This is needed so that the whole test does not finish before the timer triggers + // and to make sure it crashes while executing *this* function. (otherwise it might give the + // impression that some of the subsequent test function caused the crash...) + + QTest::qWait(400); // DO NOT CRASH while waiting +} +#endif + void tst_Gestures::deleteGestureTargetWidget() { } From 23b139038a1dc9a769a358ab112453abcdd39290 Mon Sep 17 00:00:00 2001 From: Mathieu Velten Date: Sat, 3 Mar 2018 12:23:51 +0100 Subject: [PATCH 02/19] xcb: round down the scale factor for values < 0.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This solves huge UI on some (most ?) HD 13 inches that have a calculated scale factor around 1.75. Task-number: QTBUG-53022 QTBUG-57211 Change-Id: I6cc22d3e47d38cb1d5a0daf5646a936256664e48 Reviewed-by: Mårten Nordheim Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/xcb/qxcbscreen.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index df458e85d7..e1bd8eb752 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -750,7 +750,12 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation) m_sizeMillimeters = sizeInMillimeters(geometry.size(), virtualDpi()); qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4); - m_pixelDensity = qMax(1, qRound(dpi/96)); + qreal rawFactor = dpi/96; + int roundedFactor = qFloor(rawFactor); + // Round up for .8 and higher. This favors "small UI" over "large UI". + if (rawFactor - roundedFactor >= 0.8) + roundedFactor = qCeil(rawFactor); + m_pixelDensity = qMax(1, roundedFactor); m_geometry = geometry; m_availableGeometry = geometry & m_virtualDesktop->workArea(); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); From 9b8fc8dd13dbf0e3bb446a23e82f24cfa7889f1c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Apr 2018 15:33:21 +0200 Subject: [PATCH 03/19] Examples: Fix Clang warning about hiding QGraphicsItem:::advance() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In file included from edge.cpp:52: ./node.h(76,10): warning: 'Node::advance' hides overloaded virtual function [-Woverloaded-virtual] bool advance(); Change-Id: I9d437059362c367e452b1b4f16077d4e0abd18de Reviewed-by: Topi Reiniö --- examples/widgets/graphicsview/elasticnodes/graphwidget.cpp | 2 +- examples/widgets/graphicsview/elasticnodes/node.cpp | 2 +- examples/widgets/graphicsview/elasticnodes/node.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp index 4259aab803..81928a4ee1 100644 --- a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp +++ b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp @@ -174,7 +174,7 @@ void GraphWidget::timerEvent(QTimerEvent *event) bool itemsMoved = false; foreach (Node *node, nodes) { - if (node->advance()) + if (node->advancePosition()) itemsMoved = true; } diff --git a/examples/widgets/graphicsview/elasticnodes/node.cpp b/examples/widgets/graphicsview/elasticnodes/node.cpp index 94df45524a..71737c984b 100644 --- a/examples/widgets/graphicsview/elasticnodes/node.cpp +++ b/examples/widgets/graphicsview/elasticnodes/node.cpp @@ -138,7 +138,7 @@ void Node::calculateForces() //! [6] //! [7] -bool Node::advance() +bool Node::advancePosition() { if (newPos == pos()) return false; diff --git a/examples/widgets/graphicsview/elasticnodes/node.h b/examples/widgets/graphicsview/elasticnodes/node.h index 487ae0d68e..43ea1fb24b 100644 --- a/examples/widgets/graphicsview/elasticnodes/node.h +++ b/examples/widgets/graphicsview/elasticnodes/node.h @@ -73,7 +73,7 @@ public: int type() const override { return Type; } void calculateForces(); - bool advance(); + bool advancePosition(); QRectF boundingRect() const override; QPainterPath shape() const override; From 7a1df3901092baae1a837feec9e92cdf3cdc2589 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Apr 2018 13:47:03 +0200 Subject: [PATCH 04/19] Tests: Fix clang warnings about unused variables and captures tst_qline.cpp(170,12): warning: unused variable 'baseB' [-Wunused-variable] ^ tst_qline.cpp(169,12): warning: unused variable 'baseA' [-Wunused-variable] tst_qheaderview.cpp(3329,14): warning: lambda capture 'this' is not used [-Wunused-lambda-capture] waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); qheaderview.cpp(3338,14): warning: lambda capture 'this' is not used [-Wunused-lambda-capture] waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); Change-Id: I0245a7b66d15b896e864b488f7a58e8513fbdc6c Reviewed-by: Thiago Macieira --- tests/auto/corelib/tools/qline/tst_qline.cpp | 3 --- tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp index 6e020ac35b..ae65d8f697 100644 --- a/tests/auto/corelib/tools/qline/tst_qline.cpp +++ b/tests/auto/corelib/tools/qline/tst_qline.cpp @@ -166,9 +166,6 @@ void tst_QLine::testIntersection_data() << 100.1599256468622 << 50.0; - QLineF baseA(0, -50, 0, 50); - QLineF baseB(-50, 0, 50, 0); - for (int i = 0; i < 1000; ++i) { QLineF a = QLineF::fromPolar(50, i); a.setP1(-a.p2()); diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index 74a2f7f2b6..08597d5eb1 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -3326,7 +3326,7 @@ void tst_QHeaderView::testMinMaxSectionSize(bool stretchLastSection) header.resizeSection(0, sectionSizeMax); QCOMPARE(header.sectionSize(0), sectionSizeMax); header.setMaximumSectionSize(defaultSectionSize); - waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); + waitFor([&header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); QCOMPARE(header.sectionSize(0), defaultSectionSize); // change section size on min change @@ -3335,7 +3335,7 @@ void tst_QHeaderView::testMinMaxSectionSize(bool stretchLastSection) header.resizeSection(0, sectionSizeMin); QCOMPARE(header.sectionSize(0), sectionSizeMin); header.setMinimumSectionSize(defaultSectionSize); - waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); + waitFor([&header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; }); QCOMPARE(header.sectionSize(0), defaultSectionSize); } From a058e56a86f58a73fd124b169ef57fcbdaab1ca3 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 11 Apr 2018 09:27:26 +0200 Subject: [PATCH 05/19] Docs: Mark vsp2SetLayerAlpha as preliminary Add the missing documentation. Change-Id: I5bc7fb191a7c073ed0d9e17e682d8ac808c10e96 Reviewed-by: Martin Smith Reviewed-by: Friedemann Kleint --- .../eglfsfunctions/qeglfsfunctions.qdoc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc b/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc index fc392ac369..0bee9190cf 100644 --- a/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc +++ b/src/platformheaders/eglfsfunctions/qeglfsfunctions.qdoc @@ -90,6 +90,12 @@ \preliminary */ +/*! + \fn bool QEglFSFunctions::vsp2SetLayerAlpha(const QScreen *screen, int id, qreal alpha) + \internal + \preliminary +*/ + /*! \fn void QEglFSFunctions::vsp2AddBlendListener(const QScreen *screen, void(*callback)()) \internal @@ -121,6 +127,11 @@ \internal */ +/*! + \typedef QEglFSFunctions::Vsp2SetLayerAlphaType + \internal +*/ + /*! \fn QByteArray QEglFSFunctions::vsp2AddBlendListenerTypeIdentifier() \internal */ @@ -140,3 +151,7 @@ /*! \fn QByteArray QEglFSFunctions::vsp2SetLayerPositionTypeIdentifier() \internal */ + +/*! \fn QByteArray QEglFSFunctions::vsp2SetLayerAlphaTypeIdentifier() + \internal + */ From ae618e069418621544a4c78984fbac61f2084195 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 23 Apr 2018 11:38:28 +0200 Subject: [PATCH 06/19] Manual touch test: Add handling for multiple touch screens - Add a display label showing the screen parameters. - Add a menu option to launch secondary windows and restructure the code accordingly Change-Id: I2bdb76da0b0a00e62db41e674aa93cef9598fe67 Reviewed-by: Andy Shaw --- tests/manual/touch/main.cpp | 96 ++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 17 deletions(-) diff --git a/tests/manual/touch/main.cpp b/tests/manual/touch/main.cpp index 9f2dcb3842..a244230a22 100644 --- a/tests/manual/touch/main.cpp +++ b/tests/manual/touch/main.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +52,8 @@ static bool optIgnoreTouch = false; static QVector optGestures; +static QWidgetList mainWindows; + static inline void drawEllipse(const QPointF ¢er, qreal hDiameter, qreal vDiameter, const QColor &color, QPainter &painter) { const QPen oldPen = painter.pen(); @@ -191,6 +195,7 @@ typedef QSharedPointer GesturePtr; typedef QVector GesturePtrs; typedef QVector EventTypeVector; +static EventTypeVector eventTypes; class EventFilter : public QObject { Q_OBJECT @@ -206,6 +211,8 @@ private: const EventTypeVector m_types; }; +static EventFilter *globalEventFilter = nullptr; + bool EventFilter::eventFilter(QObject *o, QEvent *e) { static int n = 0; @@ -406,29 +413,67 @@ void TouchTestWidget::paintEvent(QPaintEvent *) class MainWindow : public QMainWindow { Q_OBJECT -public: MainWindow(); +public: + static MainWindow *createMainWindow(); + QWidget *touchWidget() const { return m_touchWidget; } + void setVisible(bool visible) override; + public slots: void appendToLog(const QString &text) { m_logTextEdit->appendPlainText(text); } void dumpTouchDevices(); private: + void updateScreenLabel(); + void newWindow() { MainWindow::createMainWindow(); } + TouchTestWidget *m_touchWidget; QPlainTextEdit *m_logTextEdit; + QLabel *m_screenLabel; }; +MainWindow *MainWindow::createMainWindow() +{ + MainWindow *result = new MainWindow; + const QSize screenSize = QGuiApplication::primaryScreen()->availableGeometry().size(); + result->resize(screenSize / 2); + const QSize sizeDiff = screenSize - result->size(); + const QPoint pos = QPoint(sizeDiff.width() / 2, sizeDiff.height() / 2) + + mainWindows.size() * QPoint(30, 10); + result->move(pos); + result->show(); + + EventFilter *eventFilter = globalEventFilter; + if (!eventFilter) { + eventFilter = new EventFilter(eventTypes, result->touchWidget()); + result->touchWidget()->installEventFilter(eventFilter); + } + QObject::connect(eventFilter, &EventFilter::eventReceived, result, &MainWindow::appendToLog); + + mainWindows.append(result); + return result; +} + MainWindow::MainWindow() : m_touchWidget(new TouchTestWidget) , m_logTextEdit(new QPlainTextEdit) + , m_screenLabel(new QLabel) { - setWindowTitle(QStringLiteral("Touch Event Tester ") + QT_VERSION_STR); + QString title; + QTextStream(&title) << "Touch Event Tester " << QT_VERSION_STR << ' ' + << qApp->platformName() << " #" << (mainWindows.size() + 1); + setWindowTitle(title); setObjectName("MainWin"); QToolBar *toolBar = new QToolBar(this); addToolBar(Qt::TopToolBarArea, toolBar); QMenu *fileMenu = menuBar()->addMenu("File"); + QAction *newWindowAction = fileMenu->addAction(QStringLiteral("New Window"), this, &MainWindow::newWindow); + newWindowAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); + toolBar->addAction(newWindowAction); + fileMenu->addSeparator(); QAction *dumpDeviceAction = fileMenu->addAction(QStringLiteral("Dump devices")); dumpDeviceAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); connect(dumpDeviceAction, &QAction::triggered, this, &MainWindow::dumpTouchDevices); @@ -461,9 +506,32 @@ MainWindow::MainWindow() mainSplitter->addWidget(m_logTextEdit); setCentralWidget(mainSplitter); + statusBar()->addPermanentWidget(m_screenLabel); + dumpTouchDevices(); } +void MainWindow::setVisible(bool visible) +{ + QMainWindow::setVisible(visible); + connect(windowHandle(), &QWindow::screenChanged, this, &MainWindow::updateScreenLabel); + updateScreenLabel(); +} + +void MainWindow::updateScreenLabel() +{ + QString text; + QTextStream str(&text); + const QScreen *screen = windowHandle()->screen(); + const QRect geometry = screen->geometry(); + const qreal dpr = screen->devicePixelRatio(); + str << '"' << screen->name() << "\" " << geometry.width() << 'x' << geometry.height() + << forcesign << geometry.x() << geometry.y() << noforcesign; + if (!qFuzzyCompare(dpr, qreal(1))) + str << ", dpr=" << dpr; + m_screenLabel->setText(text); +} + void MainWindow::dumpTouchDevices() { QString message; @@ -522,14 +590,6 @@ int main(int argc, char *argv[]) if (parser.isSet(swipeGestureOption)) optGestures.append(Qt::SwipeGesture); - MainWindow w; - const QSize screenSize = QGuiApplication::primaryScreen()->availableGeometry().size(); - w.resize(screenSize / 2); - const QSize sizeDiff = screenSize - w.size(); - w.move(sizeDiff.width() / 2, sizeDiff.height() / 2); - w.show(); - - EventTypeVector eventTypes; if (!parser.isSet(noMouseLogOption)) eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick; if (parser.isSet(mouseMoveOption)) @@ -538,14 +598,16 @@ int main(int argc, char *argv[]) eventTypes << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd; if (!optGestures.isEmpty()) eventTypes << QEvent::Gesture << QEvent::GestureOverride; - QObject *filterTarget = parser.isSet(globalFilterOption) - ? static_cast(&a) - : static_cast(w.touchWidget()); - EventFilter *filter = new EventFilter(eventTypes, filterTarget); - filterTarget->installEventFilter(filter); - QObject::connect(filter, &EventFilter::eventReceived, &w, &MainWindow::appendToLog); + if (parser.isSet(globalFilterOption)) { + globalEventFilter = new EventFilter(eventTypes, &a); + a.installEventFilter(globalEventFilter); + } - return a.exec(); + MainWindow::createMainWindow(); + + const int exitCode = a.exec(); + qDeleteAll(mainWindows); + return exitCode; } #include "main.moc" From 2803cdf758dbae1006a0c50300af12dac9f71531 Mon Sep 17 00:00:00 2001 From: Karim Pinter Date: Fri, 6 Apr 2018 18:03:08 +0300 Subject: [PATCH 07/19] Fix for mouse with modifiers handling Modifier keys are saved in qinputdevicemanager such way that both evdev and libinput can use it the same way, it is also handling the repeating modifier key events. Evdev support is important for VxWorks support because it is using it. Task-number: QTBUG-60694 Change-Id: I49038cb7fe2ad5134b3a37167c19953867ea31c3 Reviewed-by: Andy Shaw Reviewed-by: Laszlo Agocs --- src/gui/kernel/qinputdevicemanager.cpp | 23 +----------------- src/gui/kernel/qinputdevicemanager_p.h | 2 +- .../evdevkeyboard/qevdevkeyboardhandler.cpp | 3 ++- .../input/evdevmouse/qevdevmousemanager.cpp | 5 ++-- .../input/libinput/qlibinputkeyboard.cpp | 24 ++++++++++++------- .../input/libinput/qlibinputkeyboard_p.h | 1 + .../input/libinput/qlibinputpointer.cpp | 2 +- 7 files changed, 23 insertions(+), 37 deletions(-) diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp index 37b1450d5a..6e4e5a9c93 100644 --- a/src/gui/kernel/qinputdevicemanager.cpp +++ b/src/gui/kernel/qinputdevicemanager.cpp @@ -109,30 +109,9 @@ Qt::KeyboardModifiers QInputDeviceManager::keyboardModifiers() const return d->keyboardModifiers; } -void QInputDeviceManager::setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key) +void QInputDeviceManager::setKeyboardModifiers(Qt::KeyboardModifiers mods) { Q_D(QInputDeviceManager); - Qt::KeyboardModifiers mods; - switch (key) { - case Qt::Key_Shift: - mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ShiftModifier); - break; - case Qt::Key_Control: - mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ControlModifier); - break; - case Qt::Key_Alt: - mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::AltModifier); - break; - case Qt::Key_Meta: - mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::MetaModifier); - break; - case Qt::Key_AltGr: - mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::GroupSwitchModifier); - break; - default: - mods = modsBeforeEvent; - break; - } d->keyboardModifiers = mods; } diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h index ddf1e6befa..d73c5526d0 100644 --- a/src/gui/kernel/qinputdevicemanager_p.h +++ b/src/gui/kernel/qinputdevicemanager_p.h @@ -79,7 +79,7 @@ public: void setCursorPos(const QPoint &pos); Qt::KeyboardModifiers keyboardModifiers() const; - void setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key); + void setKeyboardModifiers(Qt::KeyboardModifiers mods); signals: void deviceListChanged(QInputDeviceManager::DeviceType type); diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 47a65eded8..b21d5d9ef5 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -225,7 +225,8 @@ void QEvdevKeyboardHandler::readKeycode() void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtcode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat) { - QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(modifiers, qtcode); + if (!autoRepeat) + QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(QEvdevKeyboardHandler::toQtModifiers(m_modifiers)); QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease), qtcode, modifiers, nativecode + 8, 0, int(modifiers), diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 5264736dd6..ae81bca00f 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -148,14 +148,13 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButto QPoint pos(m_x + m_xoffset, m_y + m_yoffset); // Cannot track the keyboard modifiers ourselves here. Instead, report the // modifiers from the last key event that has been seen by QGuiApplication. - Qt::KeyboardModifiers mods = QGuiApplication::keyboardModifiers(); - QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, button, type, mods); + QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, button, type, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } void QEvdevMouseManager::handleWheelEvent(QPoint delta) { QPoint pos(m_x + m_xoffset, m_y + m_yoffset); - QWindowSystemInterface::handleWheelEvent(0, pos, pos, QPoint(), delta, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleWheelEvent(0, pos, pos, QPoint(), delta, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } void QEvdevMouseManager::addMouse(const QString &deviceNode) diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index ec01f95947..5152725468 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -135,7 +135,8 @@ QLibInputKeyboard::QLibInputKeyboard() #ifndef QT_NO_XKBCOMMON_EVDEV : m_ctx(0), m_keymap(0), - m_state(0) + m_state(0), + m_mods(Qt::NoModifier) #endif { #ifndef QT_NO_XKBCOMMON_EVDEV @@ -203,22 +204,27 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) Qt::KeyboardModifiers mods = Qt::NoModifier; const int qtkey = keysymToQtKey(sym, &mods, text); - xkb_state_component modtype = xkb_state_component(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); - if (xkb_state_mod_index_is_active(m_state, m_modindex[0], modtype) && (qtkey != Qt::Key_Control || !pressed)) + if (qtkey == Qt::Key_Control) mods |= Qt::ControlModifier; - if (xkb_state_mod_index_is_active(m_state, m_modindex[1], modtype) && (qtkey != Qt::Key_Alt || !pressed)) + if (qtkey == Qt::Key_Alt) mods |= Qt::AltModifier; - if (xkb_state_mod_index_is_active(m_state, m_modindex[2], modtype) && (qtkey != Qt::Key_Shift || !pressed)) + if (qtkey == Qt::Key_Shift) mods |= Qt::ShiftModifier; - if (xkb_state_mod_index_is_active(m_state, m_modindex[3], modtype) && (qtkey != Qt::Key_Meta || !pressed)) + if (qtkey == Qt::Key_Meta) mods |= Qt::MetaModifier; - xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); - QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(mods, qtkey); + if (mods != Qt::NoModifier) { + if (pressed) + m_mods |= mods; + else + m_mods &= ~mods; + + QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(m_mods); + } QWindowSystemInterface::handleExtendedKeyEvent(nullptr, pressed ? QEvent::KeyPress : QEvent::KeyRelease, - qtkey, mods, k, sym, mods, text); + qtkey, m_mods, k, sym, m_mods, text); if (pressed && xkb_keymap_key_repeats(m_keymap, k)) { m_repeatData.qtkey = qtkey; diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h index b7ee8a363f..9e09bccd79 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h +++ b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h @@ -93,6 +93,7 @@ private: QString unicodeText; int repeatCount; } m_repeatData; + Qt::KeyboardModifiers m_mods; #endif }; diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp index cb08ab53b2..c54b61fc66 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer.cpp +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -125,7 +125,7 @@ void QLibInputPointer::processAxis(libinput_event_pointer *e) #endif const int factor = 8; angleDelta *= -factor; - Qt::KeyboardModifiers mods = QGuiApplication::keyboardModifiers(); + Qt::KeyboardModifiers mods = QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers(); QWindowSystemInterface::handleWheelEvent(nullptr, m_pos, m_pos, QPoint(), angleDelta, mods); } From c9b46a130ec7f874a564bff1c9a70083705fc25b Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 18 Apr 2018 14:07:36 +0200 Subject: [PATCH 08/19] qtestlib: restore qWaitForWindowActive() its original semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes a bad hack for Unity issue described in QTBUG-67757. The workaround from 243a0660e10d13b8bd6eb4f90e5695aefab4611f caused even more problems, see QTBUG-63542. Besides causing more problems, the usage of this hack was inconsistent. The goal was to get stable geometry before continuing further in the test function. The same logic should have been used in qWaitForWindowExposed(). It was never documented that only qWaitForWindowActive() has this tweak. Also this hack was needed only for Unity, instead being unconditionally executed for all platforms. Task-number: QTBUG-67757 Change-Id: I7b7fb4b09151c4ab4807282006d7f956b18f60ad Reviewed-by: Qt CI Bot Reviewed-by: Kari Oikarinen Reviewed-by: Morten Johan Sørvig Reviewed-by: Ville Voutilainen --- src/testlib/qtestsystem.h | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h index 79fe68004e..daa0d7aea0 100644 --- a/src/testlib/qtestsystem.h +++ b/src/testlib/qtestsystem.h @@ -112,23 +112,7 @@ namespace QTest #ifdef QT_GUI_LIB Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000) { - bool becameActive = qWaitFor([&]() { return window->isActive(); }, timeout); - - // Try ensuring the platform window receives the real position. - // (i.e. that window->pos() reflects reality) - // isActive() ( == FocusIn in case of X) does not guarantee this. It seems some WMs randomly - // send the final ConfigureNotify (the one with the non-bogus 0,0 position) after the FocusIn. - // If we just let things go, every mapTo/FromGlobal call the tests perform directly after - // qWaitForWindowShown() will generate bogus results. - if (becameActive) { - int waitNo = 0; // 0, 0 might be a valid position after all, so do not wait for ever - while (window->position().isNull()) { - if (waitNo++ > timeout / 10) - break; - qWait(10); - } - } - return window->isActive(); + return qWaitFor([&]() { return window->isActive(); }, timeout); } Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000) From 6257ccd4b80d2e39d1eef51063b0e82d7119d6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 May 2018 13:58:08 +0200 Subject: [PATCH 09/19] macOS: Don't trigger deferred needsDisplay when using timer-based requestUpdate We've reverted to using the default timer-based request-update mechanism for now, so the code in [QNSView updateRegion:] needs to ensure it's only triggering a deferred needsDisplay if requestUpdate was done via the (now disabled) [QNSview requestUpdate], which uses setNeedsDisplay. Task-number: QTBUG-68048 Task-number: QTBUG-68047 Change-Id: I0421a32773908daa0f1be0075f4f2d25c90c8aea Reviewed-by: Simon Hausmann --- src/plugins/platforms/cocoa/qnsview.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a88cd5feda..c88ffc76d7 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -358,7 +358,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_platformWindow->handleExposeEvent(dirtyRegion); } - if (windowPrivate->updateRequestPending) { + if (m_updateRequested && windowPrivate->updateRequestPending) { // A call to QWindow::requestUpdate was issued during event delivery above, // but AppKit will reset the needsDisplay state of the view after completing // the current display cycle, so we need to defer the request to redisplay. From 8bcb8b069e9a35226c1465265d4d716c864dde54 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Mon, 5 Mar 2018 14:44:19 -0500 Subject: [PATCH 10/19] Flush the initial clear blit with SCREEN_WAIT_IDLE Without it, the clear runs asynchronously and screen may clear pixels _after_ Qt updates them. Change-Id: I0c0844676d8a4387439a2f818ee08942ccaf6b08 Reviewed-by: Dan Cape Reviewed-by: Janne Koskinen Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qqnxrasterwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index dc844189d1..0014ef8c6e 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -158,7 +158,7 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer() "Failed to clear window buffer"); } - Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), 0), + Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), SCREEN_WAIT_IDLE), "Failed to flush blits"); // Use the first available render buffer From 5ea238cda610f678655b2f5f02a9bba9654557e7 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Thu, 15 Mar 2018 10:36:48 -0400 Subject: [PATCH 11/19] Add screenContext native property Retrieving it via some other screen object can be painful especially when there isn't a readily available screen object to use. Change-Id: If13e808435ea6f2909d5b4c3c5c736950e00aa5a Reviewed-by: Dan Cape Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qqnxnativeinterface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 3eebb9c742..3bd6a86b59 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -91,6 +91,9 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resource) { + if (resource == "screenContext") + return m_integration->screenContext(); + return 0; } From 01c12a5c1a7524b76f68f28f65e8195799a4841a Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Mon, 26 Mar 2018 13:39:11 -0400 Subject: [PATCH 12/19] Feed external geometry changes to Qt So that Qt responds correctly when window managers make geometry changes. Note: Older versions of screen, such as the screen from the QNX 6.6.0 4036 patch, don't produce SIZE/POSITION property events. Change-Id: I7e1e5982a2cbd3f57d468b43869af8558c6d50e7 Reviewed-by: Dan Cape Reviewed-by: Rafael Roquetto --- .../platforms/qnx/qqnxscreeneventhandler.cpp | 26 +++++++++++++++++++ .../platforms/qnx/qqnxscreeneventhandler.h | 1 + 2 files changed, 27 insertions(+) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 5d230e2145..f211883e4f 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -591,6 +591,10 @@ void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event) case SCREEN_PROPERTY_FOCUS: handleKeyboardFocusPropertyEvent(window); break; + case SCREEN_PROPERTY_SIZE: + case SCREEN_PROPERTY_POSITION: + handleGeometryPropertyEvent(window); + break; default: // event ignored qScreenEventDebug() << "Ignore property event for property: " << property; @@ -617,6 +621,28 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi m_focusLostTimer = startTimer(50); } +void QQnxScreenEventHandler::handleGeometryPropertyEvent(screen_window_t window) +{ + int pos[2]; + if (screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) != 0) { + qFatal("QQnx: failed to query window property, errno=%d", errno); + } + + int size[2]; + if (screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) != 0) { + qFatal("QQnx: failed to query window property, errno=%d", errno); + } + + QRect rect(pos[0], pos[1], size[0], size[1]); + QWindow *qtWindow = QQnxIntegration::window(window); + if (qtWindow) { + qtWindow->setGeometry(rect); + QWindowSystemInterface::handleGeometryChange(qtWindow, rect); + } + + qScreenEventDebug() << qtWindow << "moved to" << rect; +} + void QQnxScreenEventHandler::timerEvent(QTimerEvent *event) { if (event->timerId() == m_focusLostTimer) { diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h index d872f9b9aa..40697b7a09 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h @@ -85,6 +85,7 @@ private: void handleDisplayEvent(screen_event_t event); void handlePropertyEvent(screen_event_t event); void handleKeyboardFocusPropertyEvent(screen_window_t window); + void handleGeometryPropertyEvent(screen_window_t window); private: enum { From 3e4b7223f102c40372bd11c50ecc684597f4bf32 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Apr 2018 15:29:08 +0200 Subject: [PATCH 13/19] Examples: Fix unused variable warnings by Clang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mainwindow.cpp(59,11): warning: unused variable 'ROWS' [-Wunused-const-variable] const int ROWS = 2; mainwindow.cpp(60,11): warning: unused variable 'COLUMNS' [-Wunused-const-variable] const int COLUMNS = 3; mainwindow.cpp(76,19): warning: unused variable 'message' [-Wunused-const-variable] Task-number: QTBUG-60635 Change-Id: I97c31462ffa826da9baa32c33c0ff0140bf46dfc Reviewed-by: Mårten Nordheim Reviewed-by: Richard Moe Gustavsen --- .../widgets/mainwindows/mainwindow/mainwindow.cpp | 12 ++++++++++++ examples/widgets/mainwindows/mainwindow/mainwindow.h | 2 ++ .../tutorials/modelview/6_treeview/mainwindow.cpp | 4 ---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp index b2c5ccc473..fe31207326 100644 --- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp +++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp @@ -187,6 +187,13 @@ void MainWindow::setupMenuBar() #endif dockWidgetMenu = menuBar()->addMenu(tr("&Dock Widgets")); + + QMenu *aboutMenu = menuBar()->addMenu(tr("About")); + QAction *aboutAct = aboutMenu->addAction(tr("&About"), this, &MainWindow::about); + aboutAct->setStatusTip(tr("Show the application's About box")); + + QAction *aboutQtAct = aboutMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); + aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); } void MainWindow::setDockOptions() @@ -476,3 +483,8 @@ void MainWindow::destroyDockWidget(QAction *action) if (destroyDockWidgetMenu->isEmpty()) destroyDockWidgetMenu->setEnabled(false); } + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About MainWindows"), message); +} diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.h b/examples/widgets/mainwindows/mainwindow/mainwindow.h index 9b1af6df80..a2c9d30ded 100644 --- a/examples/widgets/mainwindows/mainwindow/mainwindow.h +++ b/examples/widgets/mainwindows/mainwindow/mainwindow.h @@ -77,6 +77,8 @@ public slots: void createDockWidget(); void destroyDockWidget(QAction *action); + void about(); + private: void setupToolBar(); void setupMenuBar(); diff --git a/examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp b/examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp index f33155375c..1016afba07 100644 --- a/examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp +++ b/examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp @@ -55,10 +55,6 @@ #include #include "mainwindow.h" - -const int ROWS = 2; -const int COLUMNS = 3; - MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { From 3e001feb4d03d350ecea76f136c503675a2431ab Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 28 Nov 2017 15:41:30 +0100 Subject: [PATCH 14/19] If the page size is not valid on the new printer, set a custom size When the page size was not valid on the new printer, it would end up having the wrong page size name on the new printer. What should happen in this case is that it should set the originally set page size as a custom page size on the printer instead. Task-number: QTBUG-62221 Change-Id: Iaca34ae262f5d0685ca60e4ca4b38229a2283289 Reviewed-by: Albert Astals Cid --- .../platforms/cocoa/qprintengine_mac.mm | 14 +++++- .../printsupport/cups/qcupsprintengine.cpp | 5 ++- src/printsupport/kernel/qprintengine_win.cpp | 5 ++- .../kernel/qprinter/tst_qprinter.cpp | 45 +++++++++++++++++++ 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index b3d48c1ec3..eade407500 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -574,6 +574,11 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); break; case PPK_PrinterName: { + QVariant pageSize = QVariant::fromValue(d->m_pageLayout.pageSize()); + const bool isFullPage = d->m_pageLayout.mode() == QPageLayout::FullPageMode; + QVariant orientation = QVariant::fromValue(d->m_pageLayout.orientation()); + QVariant margins = QVariant::fromValue(QPair(d->m_pageLayout.margins(), + d->m_pageLayout.units())); QString id = value.toString(); if (id.isEmpty()) id = QCocoaPrinterSupport().defaultPrintDeviceId(); @@ -583,7 +588,14 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va PMPrinter printer = d->m_printDevice->macPrinter(); PMRetain(printer); PMSessionSetCurrentPMPrinter(d->session(), printer); - // TODO Do we need to check if the page size, etc, are valid on new printer? + // Ensure the settings are up to date and valid + if (d->m_printDevice->supportedPageSize(pageSize.value()).isValid()) + setProperty(PPK_QPageSize, pageSize); + else + setProperty(PPK_CustomPaperSize, pageSize.value().size(QPageSize::Point)); + setProperty(PPK_FullPage, QVariant(isFullPage)); + setProperty(PPK_Orientation, orientation); + setProperty(PPK_QPageMargins, margins); break; } case PPK_CustomPaperSize: diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index bd0d641e79..6c29a99705 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -276,7 +276,10 @@ void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter) grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; // Get the equivalent page size for this printer as supported names may be different - setPageSize(m_pageLayout.pageSize()); + if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid()) + setPageSize(m_pageLayout.pageSize()); + else + setPageSize(QPageSize(m_pageLayout.pageSize().size(QPageSize::Point), QPageSize::Point)); } void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index a943d24cb1..ca4d1d0bd6 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1234,7 +1234,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (printDevice.isValid()) { d->m_printDevice = printDevice; d->initialize(); - setProperty(PPK_QPageSize, pageSize); + if (d->m_printDevice.supportedPageSize(pageSize.value()).isValid()) + setProperty(PPK_QPageSize, pageSize); + else + setProperty(PPK_CustomPaperSize, pageSize.value().size(QPageSize::Point)); setProperty(PPK_FullPage, QVariant(isFullPage)); setProperty(PPK_Orientation, orientation); setProperty(PPK_QPageMargins, margins); diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index f68cf5c59c..4f86e74117 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -122,6 +122,7 @@ private slots: void testPageMetrics_data(); void testPageMetrics(); + void reusePageMetrics(); #endif private: QString testFileName(const QString &prefix, const QString &suffix); @@ -1955,6 +1956,50 @@ QString tst_QPrinter::testFileName(const QString &prefix, const QString &suffix) return result; } +void tst_QPrinter::reusePageMetrics() +{ + QList availablePrinters = QPrinterInfo::availablePrinters(); + if (availablePrinters.size() < 2) + QSKIP("Not enough printers to do this test with, need at least 2 setup"); + QPrinter defaultP; + QPrinterInfo info(defaultP); + QString otherPrinterName; + for (QPrinterInfo i : qAsConst(availablePrinters)) { + if (i.printerName() != defaultP.printerName()) { + otherPrinterName = i.printerName(); + break; + } + } + QPrinter otherP(QPrinterInfo::printerInfo(otherPrinterName)); + QList defaultPageSizes = info.supportedPageSizes(); + QList otherPageSizes = QPrinterInfo(otherP).supportedPageSizes(); + QPageSize unavailableSizeToSet; + for (QPageSize s : qAsConst(defaultPageSizes)) { + bool found = false; + for (QPageSize os : qAsConst(otherPageSizes)) { + if (os.isEquivalentTo(s)) { + found = true; + break; + } + } + const QPageSize tmpSize(s.size(QPageSize::Point), QPageSize::Point); + if (!tmpSize.name().startsWith("Custom")) + found = true; + if (!found) { + unavailableSizeToSet = s; + break; + } + } + if (!unavailableSizeToSet.isValid()) + QSKIP("Could not find a size that was not available on the non default printer. The test " + "requires this"); + defaultP.setPageSize(unavailableSizeToSet); + defaultP.setPrinterName(otherP.printerName()); + QVERIFY(defaultP.pageLayout().pageSize().isEquivalentTo(unavailableSizeToSet)); + QVERIFY(defaultP.pageLayout().pageSize().name() != unavailableSizeToSet.name()); + QCOMPARE(defaultP.pageLayout().pageSize().sizePoints(), unavailableSizeToSet.sizePoints()); +} + #endif // QT_CONFIG(printer) QTEST_MAIN(tst_QPrinter) From 6171d647b3a060e89b2a5f3f0218288ce0ccbcac Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 2 May 2018 16:14:29 +0200 Subject: [PATCH 15/19] tst_QUdpSocket: Fix Clang warning about unused expression tst_qudpsocket.cpp(965,9): warning: expression result unused [-Wunused-value] if (!socket2.bind(socket.localPort(), QUdpSocket::ReuseAddressHint), socket2.errorString().toLatin1().constData()) Task-number: QTBUG-63512 Change-Id: I51959432c6ff166c188842e34c3033ab1319c079 Reviewed-by: Thiago Macieira --- tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 8165ccbc58..8ebb27e58c 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -962,8 +962,10 @@ void tst_QUdpSocket::bindMode() // Depending on the user's privileges, this or will succeed or // fail. Admins are allowed to reuse the address, but nobody else. - if (!socket2.bind(socket.localPort(), QUdpSocket::ReuseAddressHint), socket2.errorString().toLatin1().constData()) - qWarning("Failed to bind with QUdpSocket::ReuseAddressHint, user isn't an administrator?"); + if (!socket2.bind(socket.localPort(), QUdpSocket::ReuseAddressHint)) { + qWarning("Failed to bind with QUdpSocket::ReuseAddressHint(%s), user isn't an administrator?", + qPrintable(socket2.errorString())); + } socket.close(); QVERIFY2(socket.bind(0, QUdpSocket::ShareAddress), socket.errorString().toLatin1().constData()); QVERIFY(!socket2.bind(socket.localPort())); From e5b5484598d97fa8fac22b8f4893d9ade370a153 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 16 Apr 2018 22:00:17 -0700 Subject: [PATCH 16/19] QProcess: set proper error state if we failed to create a pipe If the pipe creation fails, we need to properly close the pipes that were successfully created, emit the signal indicating failure and set the state back to NotRunning. The error string is reused from below, so there's no new translatable string. Task-number: QTBUG-67744 Change-Id: If90a92b041d3442fa0a4fffd1526207698f234a6 Reviewed-by: Friedemann Kleint Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess_win.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 3a62a67e3b..b1ec2c560c 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -499,8 +499,13 @@ void QProcessPrivate::startProcess() if (!openChannel(stdinChannel) || !openChannel(stdoutChannel) || - !openChannel(stderrChannel)) + !openChannel(stderrChannel)) { + QString errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string()); + cleanup(); + setErrorAndEmit(QProcess::FailedToStart, errorString); + q->setProcessState(QProcess::NotRunning); return; + } const QString args = qt_create_commandline(program, arguments, nativeArguments); QByteArray envlist; From cc812f516cb02eabea5d73a5479786b613972545 Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Thu, 8 Feb 2018 13:11:56 +0200 Subject: [PATCH 17/19] Configure window manager to support RCar D3 Initialize the device earlier and enable the screen as well. These changes are also compatible with the RCar H3. Change-Id: I4a83dedc0eed9df181c32e60ebf3666824d2a6c6 Reviewed-by: Kimmo Ollila Reviewed-by: Laszlo Agocs --- .../eglfs_rcar/qeglfsrcarintegration.cpp | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp index 98cf1d3bfb..212ebde05a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp @@ -52,12 +52,28 @@ QT_BEGIN_NAMESPACE void QEglFSRcarIntegration::platformInit() { + bool ok; + QEglFSDeviceIntegration::platformInit(); PVRGrfxServerInit(); mScreenSize = q_screenSizeFromFb(0); mNativeDisplay = (NativeDisplayType)EGL_DEFAULT_DISPLAY; + + mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); + if (!ok) + mNativeDisplayID = RCAR_DEFAULT_DISPLAY; + + r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); + wm_err = R_WM_ScreenBgColorSet(mNativeDisplayID, 0x20, 0x20, 0x20); // Grey + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to set screen background: %d", wm_err); + wm_err = R_WM_ScreenEnable(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to enable screen: %d", wm_err); } QSize QEglFSRcarIntegration::screenSize() const @@ -104,14 +120,6 @@ EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *w { bool ok; - mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); - if (!ok) - mNativeDisplayID = RCAR_DEFAULT_DISPLAY; - - r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); - if (wm_err != R_WM_ERR_OK) - qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); - mNativeWindow = (EGLNativeWindowTypeREL*)malloc(sizeof(EGLNativeWindowTypeREL)); memset(mNativeWindow, 0, sizeof(EGLNativeWindowTypeREL)); @@ -134,7 +142,7 @@ EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *w mNativeWindow->Surface.Type = R_WM_SURFACE_FB; mNativeWindow->Surface.BufMode = R_WM_WINBUF_ALLOC_INTERNAL; - wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); + r_wm_Error_t wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); if (wm_err != R_WM_ERR_OK) qFatal("Failed to create window layer: %d", wm_err); wm_err = R_WM_DevEventRegister(mNativeDisplayID, R_WM_EVENT_VBLANK, 0); From 2ef83cc12c8e507655a354feb5590cf444dc31d4 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 18 Apr 2018 13:12:24 +0200 Subject: [PATCH 18/19] tests: unblacklist tst_qwindow.cpp::modalWindowPosition() For details see QTBUG-67757. Change-Id: I82559cb667a8622f29f7e6a6f24bc2b1e59917d6 Reviewed-by: Kari Oikarinen --- tests/auto/gui/kernel/qwindow/BLACKLIST | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index cd1cb99c3c..70091121bc 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -3,8 +3,6 @@ linux osx-10.12 ci [positioning:fake] osx-10.12 ci -[modalWindowPosition] -ubuntu-16.04 [modalWithChildWindow] ubuntu-16.04 # QTBUG-66851 From da32360ffc3c7b677355c37ae54c89637c18047f Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 30 Apr 2018 10:03:19 +0200 Subject: [PATCH 19/19] macOS: ensure mouse events from the global monitor has the correct button set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global monitor will be used when popup windows are visible to catch all mouse events. But only certain kind of NSEvents has a buttonNumber set to something useful. So we need to check for this case before we create a QPA event. Task-number: QTBUG-60887 Change-Id: I5631c76ae82b8bfd232642036a08b5a8a29491c7 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoahelpers.mm | 10 ++++++++++ src/plugins/platforms/cocoa/qcocoawindow.mm | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index b729c7f4c0..e5954f277c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -265,6 +265,16 @@ QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) // ------------------------------------------------------------------------- +/*! + \fn Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) + + Returns the Qt::Button that corresponds to an NSEvent.buttonNumber. + + \note AppKit will use buttonNumber 0 to indicate both "left button" + and "no button". Only NSEvents that describes mouse press/release + events (e.g NSEventTypeOtherMouseDown) will contain a valid + button number. +*/ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum >= 0 && buttonNum <= 31) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 965a15a548..1e311ed388 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -404,10 +404,10 @@ void QCocoaWindow::setVisible(bool visible) removeMonitor(); monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) { QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]); - const auto eventType = e.type == NSMouseMoved ? QEvent::MouseMove : QEvent::MouseButtonPress; + const auto button = e.type == NSEventTypeMouseMoved ? Qt::NoButton : cocoaButton2QtButton([e buttonNumber]); + const auto eventType = e.type == NSEventTypeMouseMoved ? QEvent::MouseMove : QEvent::MouseButtonPress; QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint, - Qt::MouseButtons(uint(NSEvent.pressedMouseButtons & 0xFFFF)), - cocoaButton2QtButton(e.buttonNumber), eventType); + Qt::MouseButtons(uint(NSEvent.pressedMouseButtons & 0xFFFF)), button, eventType); }]; } }