From 2e12bfdc1e537bb3cc027eed14500fe5724ab30f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 14 Dec 2018 10:48:43 +0100 Subject: [PATCH 01/27] eglfs: avoid breaking builds without EGL_EXT_platform_base Change-Id: I9183e17b42c00435f20c00a414e1f20aa3972351 Fixes: QTBUG-72559 Reviewed-by: Johan Helsing --- .../deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp | 1 - .../eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp index 1e4f4e72c8e..f1545206691 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -63,7 +63,6 @@ QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration() #ifndef EGL_EXT_platform_base typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); #endif #ifndef EGL_PLATFORM_GBM_KHR diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp index 65a7c4f38a5..a93762e5b4d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp @@ -45,6 +45,10 @@ QT_BEGIN_NAMESPACE +#ifndef EGL_EXT_platform_base +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +#endif + void QEglFSKmsGbmWindow::resetSurface() { QEglFSKmsGbmScreen *gbmScreen = static_cast(screen()); From 7faec58d5cccf7e7a5f92116f70cc504821711af Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 9 Jan 2019 15:01:16 +0100 Subject: [PATCH 02/27] Fix crash when using Qt Virtual Keyboard with QCalendarWidget For some reason, QCalendarWidget gets filtered press events that were intended for Qt Virtual Keyboard's input panel (QQuickView), so we have to make sure that the window is indeed a QWidget - no static_cast. Change-Id: Ibc9dce956918ac50d1fed8231a445b7338aef09c Fixes: QTBUG-72925 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qcalendarwidget.cpp | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 4946969360d..2ff383d9c70 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -3063,19 +3063,22 @@ bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event) { Q_D(QCalendarWidget); if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus()) { + // We can get filtered press events that were intended for Qt Virtual Keyboard's + // input panel (QQuickView), so we have to make sure that the window is indeed a QWidget - no static_cast. + // In addition, as we have a event filter on the whole application we first make sure that the top level widget + // of both this and the watched widget are the same to decide if we should finish the year edition. QWidget *tlw = window(); - QWidget *widget = static_cast(watched); - //as we have a event filter on the whole application we first make sure that the top level widget - //of both this and the watched widget are the same to decide if we should finish the year edition. - if (widget->window() == tlw) { - QPoint mousePos = widget->mapTo(tlw, static_cast(event)->pos()); - QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size()); - if (!geom.contains(mousePos)) { - event->accept(); - d->_q_yearEditingFinished(); - setFocus(); - return true; - } + QWidget *widget = qobject_cast(watched); + if (!widget || widget->window() != tlw) + return QWidget::eventFilter(watched, event); + + QPoint mousePos = widget->mapTo(tlw, static_cast(event)->pos()); + QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size()); + if (!geom.contains(mousePos)) { + event->accept(); + d->_q_yearEditingFinished(); + setFocus(); + return true; } } return QWidget::eventFilter(watched, event); From da55a1b04121abd44d9c72e0c7cba7d72f16d4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 1 Feb 2019 11:19:32 +0100 Subject: [PATCH 03/27] Widgets: Only set WA_WState_ExplicitShowHide via public API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling QWindow::setVisible doesn't have the same semantics, so we split off QWidget::setVisible into QWidgetPrivate::setVisible and call that instead from QWidgetWindow. Task-number QTBUG-67504 Change-Id: Ie50938d4a1d33ad4b59c742e75e3ca30f1b19399 Reviewed-by: Tor Arne Vestbø --- src/widgets/kernel/qwidget.cpp | 111 ++++++++++++++------------- src/widgets/kernel/qwidget_p.h | 1 + src/widgets/kernel/qwidgetwindow.cpp | 2 +- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 19599cc008c..332eee9c03e 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -8296,49 +8296,57 @@ void QWidgetPrivate::hide_sys() \endlist */ - void QWidget::setVisible(bool visible) { + if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible) + return; + + // Remember that setVisible was called explicitly + setAttribute(Qt::WA_WState_ExplicitShowHide); + + Q_D(QWidget); + d->setVisible(visible); +} + +// This method is called from QWidgetWindow in response to QWindow::setVisible, +// and should match the semantics of QWindow::setVisible. QWidget::setVisible on +// the other hand keeps track of WA_WState_ExplicitShowHide in addition. +void QWidgetPrivate::setVisible(bool visible) +{ + Q_Q(QWidget); if (visible) { // show - if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) - return; - - Q_D(QWidget); - // Designer uses a trick to make grabWidget work without showing - if (!isWindow() && parentWidget() && parentWidget()->isVisible() - && !parentWidget()->testAttribute(Qt::WA_WState_Created)) - parentWidget()->window()->d_func()->createRecursively(); + if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible() + && !q->parentWidget()->testAttribute(Qt::WA_WState_Created)) + q->parentWidget()->window()->d_func()->createRecursively(); //create toplevels but not children of non-visible parents - QWidget *pw = parentWidget(); - if (!testAttribute(Qt::WA_WState_Created) - && (isWindow() || pw->testAttribute(Qt::WA_WState_Created))) { - create(); + QWidget *pw = q->parentWidget(); + if (!q->testAttribute(Qt::WA_WState_Created) + && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) { + q->create(); } - bool wasResized = testAttribute(Qt::WA_Resized); - Qt::WindowStates initialWindowState = windowState(); + bool wasResized = q->testAttribute(Qt::WA_Resized); + Qt::WindowStates initialWindowState = q->windowState(); // polish if necessary - ensurePolished(); + q->ensurePolished(); - // remember that show was called explicitly - setAttribute(Qt::WA_WState_ExplicitShowHide); // whether we need to inform the parent widget immediately - bool needUpdateGeometry = !isWindow() && testAttribute(Qt::WA_WState_Hidden); + bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden); // we are no longer hidden - setAttribute(Qt::WA_WState_Hidden, false); + q->setAttribute(Qt::WA_WState_Hidden, false); if (needUpdateGeometry) - d->updateGeometry_helper(true); + updateGeometry_helper(true); // activate our layout before we and our children become visible - if (d->layout) - d->layout->activate(); + if (layout) + layout->activate(); - if (!isWindow()) { - QWidget *parent = parentWidget(); + if (!q->isWindow()) { + QWidget *parent = q->parentWidget(); while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) { parent->d_func()->layout->activate(); if (parent->isWindow()) @@ -8351,30 +8359,28 @@ void QWidget::setVisible(bool visible) // adjust size if necessary if (!wasResized - && (isWindow() || !parentWidget()->d_func()->layout)) { - if (isWindow()) { - adjustSize(); - if (windowState() != initialWindowState) - setWindowState(initialWindowState); + && (q->isWindow() || !q->parentWidget()->d_func()->layout)) { + if (q->isWindow()) { + q->adjustSize(); + if (q->windowState() != initialWindowState) + q->setWindowState(initialWindowState); } else { - adjustSize(); + q->adjustSize(); } - setAttribute(Qt::WA_Resized, false); + q->setAttribute(Qt::WA_Resized, false); } - setAttribute(Qt::WA_KeyboardFocusChange, false); + q->setAttribute(Qt::WA_KeyboardFocusChange, false); - if (isWindow() || parentWidget()->isVisible()) { - d->show_helper(); + if (q->isWindow() || q->parentWidget()->isVisible()) { + show_helper(); - qApp->d_func()->sendSyntheticEnterLeave(this); + qApp->d_func()->sendSyntheticEnterLeave(q); } QEvent showToParentEvent(QEvent::ShowToParent); - QApplication::sendEvent(this, &showToParentEvent); + QApplication::sendEvent(q, &showToParentEvent); } else { // hide - if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) - return; #if 0 // Used to be included in Qt4 for Q_WS_WIN // reset WS_DISABLED style in a Blocked window if(isWindow() && testAttribute(Qt::WA_WState_Created) @@ -8385,33 +8391,30 @@ void QWidget::setVisible(bool visible) SetWindowLong(winId(), GWL_STYLE, dwStyle); } #endif - if (QApplicationPrivate::hidden_focus_widget == this) + if (QApplicationPrivate::hidden_focus_widget == q) QApplicationPrivate::hidden_focus_widget = 0; - Q_D(QWidget); - // hw: The test on getOpaqueRegion() needs to be more intelligent // currently it doesn't work if the widget is hidden (the region will // be clipped). The real check should be testing the cached region // (and dirty flag) directly. - if (!isWindow() && parentWidget()) // && !d->getOpaqueRegion().isEmpty()) - parentWidget()->d_func()->setDirtyOpaqueRegion(); + if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty()) + q->parentWidget()->d_func()->setDirtyOpaqueRegion(); - setAttribute(Qt::WA_WState_Hidden); - setAttribute(Qt::WA_WState_ExplicitShowHide); - if (testAttribute(Qt::WA_WState_Created)) - d->hide_helper(); + q->setAttribute(Qt::WA_WState_Hidden); + if (q->testAttribute(Qt::WA_WState_Created)) + hide_helper(); // invalidate layout similar to updateGeometry() - if (!isWindow() && parentWidget()) { - if (parentWidget()->d_func()->layout) - parentWidget()->d_func()->layout->invalidate(); - else if (parentWidget()->isVisible()) - QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest)); + if (!q->isWindow() && q->parentWidget()) { + if (q->parentWidget()->d_func()->layout) + q->parentWidget()->d_func()->layout->invalidate(); + else if (q->parentWidget()->isVisible()) + QApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest)); } QEvent hideToParentEvent(QEvent::HideToParent); - QApplication::sendEvent(this, &hideToParentEvent); + QApplication::sendEvent(q, &hideToParentEvent); } } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 0d7e9e26ba1..7e4ea2cc0ca 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -483,6 +483,7 @@ public: void hide_sys(); void hide_helper(); void _q_showIfNotHidden(); + void setVisible(bool); void setEnabled_helper(bool); static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 991a05fa026..e9b749d7c2d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -73,7 +73,7 @@ public: { Q_Q(QWidgetWindow); if (QWidget *widget = q->widget()) - widget->setVisible(visible); + QWidgetPrivate::get(widget)->setVisible(visible); else QWindowPrivate::setVisible(visible); } From 37970d7b3e6fff92dca98db974ada865c1bfd730 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 12 Feb 2019 13:21:39 +0100 Subject: [PATCH 04/27] Fix determination of OpenGL include paths on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since include paths are fully resolved, we must remove the code that prepends the SDK path to the OpenGL include paths. Change-Id: I80d74629c7fc989a89c3f1d95d6de43b4c1de17a Fixes: QTBUG-73736 Reviewed-by: Tor Arne Vestbø --- mkspecs/common/mac.conf | 2 +- mkspecs/features/mac/sdk.prf | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/mkspecs/common/mac.conf b/mkspecs/common/mac.conf index b77494ec9b2..e000d1026bd 100644 --- a/mkspecs/common/mac.conf +++ b/mkspecs/common/mac.conf @@ -17,7 +17,7 @@ QMAKE_EXTENSION_SHLIB = dylib QMAKE_EXTENSIONS_AUX_SHLIB = tbd QMAKE_LIBDIR = -# sdk.prf will prefix the proper SDK sysroot +# The proper SDK sysroot will be automatically prepended QMAKE_INCDIR_OPENGL = \ /System/Library/Frameworks/OpenGL.framework/Headers \ /System/Library/Frameworks/AGL.framework/Headers/ diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf index 8360dd8b389..50a41657d83 100644 --- a/mkspecs/features/mac/sdk.prf +++ b/mkspecs/features/mac/sdk.prf @@ -33,10 +33,6 @@ QMAKE_MAC_SDK_PATH = $$xcodeSDKInfo(Path) QMAKE_MAC_SDK_PLATFORM_PATH = $$xcodeSDKInfo(PlatformPath) QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion) -sysrootified = -for(val, QMAKE_INCDIR_OPENGL): sysrootified += $${QMAKE_MAC_SDK_PATH}$$val -QMAKE_INCDIR_OPENGL = $$sysrootified - QMAKESPEC_NAME = $$basename(QMAKESPEC) # Resolve SDK version of various tools From aed1e2c49f0a9ad06732d39f70b513ad2fcfdaa3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 12 Feb 2019 14:21:03 +0100 Subject: [PATCH 05/27] Fix warning in tst_qopengl.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes warning: unused parameter ‘glFormat’ Change-Id: I4865300fb99ea5392b96f8e9f4f594f15f18625c Reviewed-by: Oliver Wolff --- tests/auto/gui/qopengl/tst_qopengl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index f1360b9efea..ede1e58a53c 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -642,6 +642,8 @@ static bool supportsInternalFboFormat(QOpenGLContext *ctx, int glFormat) return false; } } +#else + Q_UNUSED(glFormat); #endif return true; } From c4e9eabc309a275efc222f4127f31ba4677259b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 10 Feb 2019 22:53:02 +0100 Subject: [PATCH 06/27] Don't allow backingstore flush to non-raster surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I8e85706727a8c5f7585e34e3864c8a9f48481b92 Reviewed-by: Laszlo Agocs Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qbackingstore.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 8d71d1c3a97..0dfb52e7c33 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -192,6 +192,17 @@ void QBackingStore::endPaint() d_ptr->platformBackingStore->endPaint(); } +static bool isRasterSurface(QWindow *window) +{ + switch (window->surfaceType()) { + case QSurface::RasterSurface: + case QSurface::RasterGLSurface: + return true; + default: + return false; + }; +} + /*! Flushes the given \a region from the specified \a window onto the screen. @@ -220,6 +231,13 @@ void QBackingStore::flush(const QRegion ®ion, QWindow *window, const QPoint & return; } + if (!isRasterSurface(window)) { + qWarning() << "Attempted flush to non-raster surface" << window << "of type" << window->surfaceType() + << (window->inherits("QWidgetWindow") ? "(consider using Qt::WA_PaintOnScreen to exclude " + "from backingstore sync)" : ""); + return; + } + #ifdef QBACKINGSTORE_DEBUG if (window && window->isTopLevel() && !qt_window_private(window)->receivedExpose) { qWarning().nospace() << "QBackingStore::flush() called with non-exposed window " From 6b8610f4e8b72895bfa4228cca2230f31c259d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 13:55:52 +0100 Subject: [PATCH 07/27] macOS: Add explicit auto-release pool for requestActivateWindow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API is often called from main before entering the event loop, and the making the window first responder and key will autorelease both the window and view. Change-Id: Ie2a7dc14652015cbe802b57696e4a82d564e2dc0 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindow.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 724c9485bd6..ebdd51acb47 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1512,9 +1512,9 @@ void QCocoaWindow::deliverUpdateRequest() void QCocoaWindow::requestActivateWindow() { - NSWindow *window = [m_view window]; - [window makeFirstResponder:m_view]; - [window makeKeyWindow]; + QMacAutoReleasePool pool; + [m_view.window makeFirstResponder:m_view]; + [m_view.window makeKeyWindow]; } QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) From ae94ab264ba29a41beac81a61fb39c0d4f669270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 14:04:04 +0100 Subject: [PATCH 08/27] Add developer documentation on how to debug missing auto-release pools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie3942210ab5bafea22d65d6f7c9a099e40ee6b73 Reviewed-by: Morten Johan Sørvig --- src/corelib/kernel/qcore_mac_objc.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index bc23e821fd9..140c60a0800 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -129,6 +129,16 @@ QT_USE_NAMESPACE QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker); QT_BEGIN_NAMESPACE + +/* + Manages a scoped auto-release pool. + + To track autoreleases without any pools in place, such as in main() + before the runloop has started, export OBJC_DEBUG_MISSING_POOLS=YES + and break in objc_autoreleaseNoPool, e.g.: + + br set -n objc_autoreleaseNoPool -c "[((NSObject*)$r14) class] == [QNSWindow class]" +*/ QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { From 0ad651579fe9055e52d4a6754a95de35f7b9bf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 7 Feb 2019 17:27:18 +0100 Subject: [PATCH 09/27] macOS: Don't rely on QGuiApplication::instance() during CVDisplayLink callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The display-link callback comes in on a secondary thread, so there's a possible race in using QGuiApplication::instance() to check whether or not we're on the main thread. Change-Id: Ic26bca8f5f54847a1e1b11dc92e786693c86e9de Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoascreen.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index 36c11ba8af1..80dd7e40d35 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -269,15 +269,12 @@ struct DeferredDebugHelper void QCocoaScreen::deliverUpdateRequests() { - if (!QGuiApplication::instance()) - return; - // The CVDisplayLink callback is a notification that it's a good time to produce a new frame. // Since the callback is delivered on a separate thread we have to marshal it over to the // main thread, as Qt requires update requests to be delivered there. This needs to happen // asynchronously, as otherwise we may end up deadlocking if the main thread calls back // into any of the CVDisplayLink APIs. - if (QThread::currentThread() != QGuiApplication::instance()->thread()) { + if (!NSThread.isMainThread) { // We're explicitly not using the data of the GCD source to track the pending updates, // as the data isn't reset to 0 until after the event handler, and also doesn't update // during the event handler, both of which we need to track late frames. From 77389ad8ff9fd3dc56f5a398fab11a993e7a621c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 10 Feb 2019 17:39:06 +0100 Subject: [PATCH 10/27] macOS: Remove screen-update disable during resize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was needed as a workaround for the window border and window content becoming out of sync when we were drawing and flushing to the layer from another thread using OpenGL. Since we've disabled ThreadedOpenGL we can remove this workaround for now. The workaround also had other problems, as windowWillResize: did not turn out to be a reliable signal to know when a window was about to resize. Since we override windowWillUseStandardFrame:, we would not get the callback when zooming windows. Conversely, if we removed the windowWillUseStandardFrame: override, we would get a single callback for windowWillResize:, and then multiple callbacks that the window had resized. In addition, windowWillResize: is not only used as a callback, but also as a way to let the window delegate restrict the size, so it's called when e.g. AppKit determines the standard frame of the window -- an operation that doesn't involve an actual resize operation. If we re-introduce a workaround using screen-update disabling we need a better hook than windowWillResize:, and we need to track when we disable screen updates so that we can pair them up with corresponding screen update enables, otherwise we'll get log messages in the console about "SLSReenableUpdate: unbalanced enable/disable update". Change-Id: Ifca8892083c8666976391a4ada8f8d1471493943 Fixes: QTBUG-73726 Task-number: QTBUG-69321 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- .../platforms/cocoa/qnswindowdelegate.mm | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index 14f1ca0114b..087cb3651fd 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -102,40 +102,6 @@ static QCocoaWindow *toPlatformWindow(NSWindow *window) return QCocoaScreen::mapToNative(maximizedFrame); } -#pragma clang diagnostic push -// NSDisableScreenUpdates and NSEnableScreenUpdates are deprecated, but the -// NSAnimationContext API that replaces them doesn't handle the use-case of -// cross-thread screen update synchronization. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)frameSize -{ - Q_ASSERT(toPlatformWindow(window)); - - qCDebug(lcQpaWindow) << window << "will resize to" << QSizeF::fromCGSize(frameSize) - << "- disabling screen updates temporarily"; - - // There may be separate threads rendering to CA layers in this window, - // and if any of them do a swap while the resize is still in progress, - // the visual bounds of that layer will be updated before the visual - // bounds of the window frame, resulting in flickering while resizing. - - // To prevent this we disable screen updates for the whole process until - // the resize is complete, which makes the whole thing visually atomic. - NSDisableScreenUpdates(); - - return frameSize; -} - -- (void)windowDidResize:(NSNotification *)notification -{ - NSWindow *window = notification.object; - Q_ASSERT(toPlatformWindow(window)); - - qCDebug(lcQpaWindow) << window << "was resized - re-enabling screen updates"; - NSEnableScreenUpdates(); -} -#pragma clang diagnostic pop - - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu { Q_UNUSED(menu); From 80bcfa776f9243641484181a18090b34147e8e30 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 8 Feb 2019 22:33:15 +0100 Subject: [PATCH 11/27] Fix QSpinBox tests failing after change in the Windows QPA Some QSpinBox tests start failing after reverting to using legacy mouse messages to handle mouse input in the Windows QPA. It seems to be caused by a test that runs before it and moves the mouse cursor. Then when the QSpinBox tests run, they create widgets that appear below the mouse cursor, causing some mouse events to be generating and messing with the events synthesized by the test itself. With the pointer messages being used for mouse input, the legacy mouse messages that are generated under this condition were being ignored. But by reverting to the old implementation, the legacy messages are handled again, causing the test to fail. This change moves the mouse pointer to a safe position during the test initialization, so it does not depend on the state left by previous tests. This change needs to be integrated together or before the change in the windows QPA. Change-Id: I91f7e9376dc495ee61250e0a7d908c1c2b685bc8 Reviewed-by: Friedemann Kleint --- tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 37bb28dec95..1d106f94f3a 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -53,6 +53,8 @@ #include #include #include +#include + class SpinBox : public QSpinBox { @@ -343,6 +345,14 @@ tst_QSpinBox::tst_QSpinBox() void tst_QSpinBox::init() { QLocale::setDefault(QLocale(QLocale::C)); + +#if QT_CONFIG(cursor) + // Ensure mouse cursor was not left by previous tests where widgets + // will appear, as it could cause events and interfere with the tests. + const QScreen *screen = QGuiApplication::primaryScreen(); + const QRect availableGeometry = screen->availableGeometry(); + QCursor::setPos(availableGeometry.topLeft()); +#endif } void tst_QSpinBox::setValue_data() From 38504041148f2d1cffea6520ea448dd4171adb0b Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Mon, 4 Feb 2019 19:25:31 +0100 Subject: [PATCH 12/27] Windows QPA: Handle mouse input using legacy messages This change reverts to using legacy mouse messages when handling mouse and touchpad input, while using pointer messages to handle touchscreen and pen input. The use of pointer messages to handle everything, added in 5.12.0, caused issues in some particular cases, due mainly to differences in behavior or bugs in the pointer messages, which required workarounds in the Windows QPA, which didn't work well in all cases and led to additional issues. For instance, DoDragDrop() does not work when called by pointer (or touch/pen) handlers, but only after OS-synthesized legacy mouse messages are generated. Also, in some cases pointer messages for mouse movement are generated as non-client for client area events. Modal loops like the ones in window resize/move and menu handling caused some issues with pointer messages, as well. Also, we have to handle the OS-synthesized legacy mouse message generated for touch and pen. Ignoring them while letting the gui layer synthesize mouse events for touch/pen may break Drag and Drop by triggering DoDragDrop() before legacy messages, which can result in a hang inside the DoDragDrop() modal loop. This change should fix most regressions related to pointer messages, while keeping the enhancements in pen and touch input. Fixes: QTBUG-73389 Fixes: QTBUG-72624 Fixes: QTBUG-72801 Fixes: QTBUG-73290 Fixes: QTBUG-72458 Fixes: QTBUG-73358 Fixes: QTBUG-72992 Change-Id: I919f78930d3965270ef2094401e827ab87174979 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowscontext.cpp | 20 +- .../windows/qwindowspointerhandler.cpp | 487 ++++++------------ .../windows/qwindowspointerhandler.h | 6 +- 3 files changed, 167 insertions(+), 346 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2b96fb3a5ee..41655dbd57d 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -334,12 +334,8 @@ bool QWindowsContext::initTouch(unsigned integrationOptions) if (!touchDevice) return false; - if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) { - QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); - } else { - if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) - touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); - } + if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) + touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); QWindowSystemInterface::registerTouchDevice(touchDevice); @@ -376,7 +372,6 @@ bool QWindowsContext::initPointer(unsigned integrationOptions) if (!QWindowsContext::user32dll.supportsPointerApi()) return false; - QWindowsContext::user32dll.enableMouseInPointer(TRUE); d->m_systemInfo |= QWindowsContext::SI_SupportsPointer; return true; } @@ -1218,9 +1213,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: - if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) + if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) + return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); + else return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); - break; case QtWindows::NonClientPointerEvent: if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result); @@ -1246,10 +1242,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, window = window->parent(); if (!window) return false; - if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); - else + if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result); + else + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); } break; case QtWindows::TouchEvent: diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 203d803a1b6..f1960f15857 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -50,9 +50,6 @@ #include "qwindowswindow.h" #include "qwindowsintegration.h" #include "qwindowsscreen.h" -#if QT_CONFIG(draganddrop) -# include "qwindowsdrag.h" -#endif #include #include @@ -78,111 +75,9 @@ enum { QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD }; -struct PointerTouchEventInfo { - QPointer window; - QList points; - Qt::KeyboardModifiers modifiers; -}; - -struct PointerTabletEventInfo { - QPointer window; - QPointF local; - QPointF global; - int device; - int pointerType; - Qt::MouseButtons buttons; - qreal pressure; - int xTilt; - int yTilt; - qreal tangentialPressure; - qreal rotation; - int z; - qint64 uid; - Qt::KeyboardModifiers modifiers; -}; - -static QQueue touchEventQueue; -static QQueue tabletEventQueue; - -static void enqueueTouchEvent(QWindow *window, - const QList &points, - Qt::KeyboardModifiers modifiers) -{ - PointerTouchEventInfo eventInfo; - eventInfo.window = window; - eventInfo.points = points; - eventInfo.modifiers = modifiers; - touchEventQueue.enqueue(eventInfo); -} - -static void enqueueTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, - int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, - int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, - int z, qint64 uid, Qt::KeyboardModifiers modifiers) -{ - PointerTabletEventInfo eventInfo; - eventInfo.window = window; - eventInfo.local = local; - eventInfo.global = global; - eventInfo.device = device; - eventInfo.pointerType = pointerType; - eventInfo.buttons = buttons; - eventInfo.pressure = pressure; - eventInfo.xTilt = xTilt; - eventInfo.yTilt = yTilt; - eventInfo.tangentialPressure = tangentialPressure; - eventInfo.rotation = rotation; - eventInfo.z = z; - eventInfo.uid = uid; - eventInfo.modifiers = modifiers; - tabletEventQueue.enqueue(eventInfo); -} - -static void flushTouchEvents(QTouchDevice *touchDevice) -{ - while (!touchEventQueue.isEmpty()) { - PointerTouchEventInfo eventInfo = touchEventQueue.dequeue(); - if (eventInfo.window) { - QWindowSystemInterface::handleTouchEvent(eventInfo.window, - touchDevice, - eventInfo.points, - eventInfo.modifiers); - } - } -} - -static void flushTabletEvents() -{ - while (!tabletEventQueue.isEmpty()) { - PointerTabletEventInfo eventInfo = tabletEventQueue.dequeue(); - if (eventInfo.window) { - QWindowSystemInterface::handleTabletEvent(eventInfo.window, - eventInfo.local, - eventInfo.global, - eventInfo.device, - eventInfo.pointerType, - eventInfo.buttons, - eventInfo.pressure, - eventInfo.xTilt, - eventInfo.yTilt, - eventInfo.tangentialPressure, - eventInfo.rotation, - eventInfo.z, - eventInfo.uid, - eventInfo.modifiers); - } - } -} - bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) { *result = 0; - - // If we are inside the move/resize modal loop, let DefWindowProc() handle it (but process NC button release). - QWindowsWindow *platformWindow = static_cast(window->handle()); - if (msg.message != WM_NCPOINTERUP && platformWindow->testFlag(QWindowsWindow::ResizeMoveActive)) - return false; - const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam); POINTER_INPUT_TYPE pointerType; @@ -191,30 +86,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q return false; } - m_lastPointerType = pointerType; - - // Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow. - if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) { - POINTER_INFO pointerInfo; - if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) { - qWarning() << "GetPointerInfo() failed:" << qt_error_string(); - return false; - } - if (pointerInfo.pointerFlags & (POINTER_FLAG_UP | POINTER_FLAG_DOWN)) - return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo); - return false; - } - switch (pointerType) { case QT_PT_POINTER: case QT_PT_MOUSE: case QT_PT_TOUCHPAD: { - POINTER_INFO pointerInfo; - if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) { - qWarning() << "GetPointerInfo() failed:" << qt_error_string(); - return false; - } - return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo); + // Let Mouse/TouchPad be handled using legacy messages. + return false; } case QT_PT_TOUCH: { quint32 pointerCount = 0; @@ -290,76 +167,71 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q return false; } -static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeType, QEvent::Type *eventType, Qt::MouseButton *mouseButton) +namespace { +struct MouseEvent { + QEvent::Type type; + Qt::MouseButton button; +}; +} // namespace + +static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON... { - static const QHash buttonMapping { - {POINTER_CHANGE_FIRSTBUTTON_DOWN, Qt::LeftButton}, - {POINTER_CHANGE_FIRSTBUTTON_UP, Qt::LeftButton}, - {POINTER_CHANGE_SECONDBUTTON_DOWN, Qt::RightButton}, - {POINTER_CHANGE_SECONDBUTTON_UP, Qt::RightButton}, - {POINTER_CHANGE_THIRDBUTTON_DOWN, Qt::MiddleButton}, - {POINTER_CHANGE_THIRDBUTTON_UP, Qt::MiddleButton}, - {POINTER_CHANGE_FOURTHBUTTON_DOWN, Qt::XButton1}, - {POINTER_CHANGE_FOURTHBUTTON_UP, Qt::XButton1}, - {POINTER_CHANGE_FIFTHBUTTON_DOWN, Qt::XButton2}, - {POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2}, - }; - - static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = { - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - }; - - static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = { - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_UP, - }; - - if (!eventType || !mouseButton) - return; - - const bool nonClient = message == WM_NCPOINTERUPDATE || - message == WM_NCPOINTERDOWN || - message == WM_NCPOINTERUP; - - if (std::find(std::begin(downChanges), - std::end(downChanges), changeType) < std::end(downChanges)) { - *eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress : - QEvent::MouseButtonPress; - } else if (std::find(std::begin(upChanges), - std::end(upChanges), changeType) < std::end(upChanges)) { - *eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease : - QEvent::MouseButtonRelease; - } else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) { - *eventType = QEvent::Wheel; - } else { - *eventType = nonClient ? QEvent::NonClientAreaMouseMove : - QEvent::MouseMove; - } - - *mouseButton = buttonMapping.value(changeType, Qt::NoButton); + return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton; } -static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags) +static inline MouseEvent eventFromMsg(const MSG &msg) { - Qt::MouseButtons result = Qt::NoButton; - if (pointerFlags & POINTER_FLAG_FIRSTBUTTON) - result |= Qt::LeftButton; - if (pointerFlags & POINTER_FLAG_SECONDBUTTON) - result |= Qt::RightButton; - if (pointerFlags & POINTER_FLAG_THIRDBUTTON) - result |= Qt::MiddleButton; - if (pointerFlags & POINTER_FLAG_FOURTHBUTTON) - result |= Qt::XButton1; - if (pointerFlags & POINTER_FLAG_FIFTHBUTTON) - result |= Qt::XButton2; - return result; + switch (msg.message) { + case WM_MOUSEMOVE: + return {QEvent::MouseMove, Qt::NoButton}; + case WM_LBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::LeftButton}; + case WM_LBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::LeftButton}; + case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press + return {QEvent::MouseButtonPress, Qt::LeftButton}; + case WM_MBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::MidButton}; + case WM_MBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::MidButton}; + case WM_MBUTTONDBLCLK: + return {QEvent::MouseButtonPress, Qt::MidButton}; + case WM_RBUTTONDOWN: + return {QEvent::MouseButtonPress, Qt::RightButton}; + case WM_RBUTTONUP: + return {QEvent::MouseButtonRelease, Qt::RightButton}; + case WM_RBUTTONDBLCLK: + return {QEvent::MouseButtonPress, Qt::RightButton}; + case WM_XBUTTONDOWN: + return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; + case WM_XBUTTONUP: + return {QEvent::MouseButtonRelease, extraButton(msg.wParam)}; + case WM_XBUTTONDBLCLK: + return {QEvent::MouseButtonPress, extraButton(msg.wParam)}; + case WM_NCMOUSEMOVE: + return {QEvent::NonClientAreaMouseMove, Qt::NoButton}; + case WM_NCLBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; + case WM_NCLBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton}; + case WM_NCLBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; + case WM_NCMBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + case WM_NCMBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton}; + case WM_NCMBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + case WM_NCRBUTTONDOWN: + return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; + case WM_NCRBUTTONUP: + return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton}; + case WM_NCRBUTTONDBLCLK: + return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; + default: // WM_MOUSELEAVE + break; + } + return {QEvent::None, Qt::NoButton}; } static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState) @@ -419,15 +291,6 @@ static bool isValidWheelReceiver(QWindow *candidate) return false; } -static bool isMenuWindow(QWindow *window) -{ - if (window) - if (QObject *fo = window->focusObject()) - if (fo->inherits("QMenu")) - return true; - return false; -} - static QTouchDevice *createTouchDevice() { const int digitizers = GetSystemMetrics(SM_DIGITIZER); @@ -553,71 +416,6 @@ void QWindowsPointerHandler::handleEnterLeave(QWindow *window, m_previousCaptureWindow = hasCapture ? window : nullptr; } -bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd, - QtWindows::WindowsEventType et, - MSG msg, PVOID vPointerInfo) -{ - POINTER_INFO *pointerInfo = static_cast(vPointerInfo); - const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y); - const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); - const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags); - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); - - switch (msg.message) { - case WM_NCPOINTERDOWN: - case WM_NCPOINTERUP: - case WM_NCPOINTERUPDATE: - case WM_POINTERDOWN: - case WM_POINTERUP: - case WM_POINTERUPDATE: { - - QEvent::Type eventType; - Qt::MouseButton button; - getMouseEventInfo(msg.message, pointerInfo->ButtonChangeType, &eventType, &button); - - if (et & QtWindows::NonClientEventFlag) { - QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, - keyModifiers, Qt::MouseEventNotSynthesized); - return false; // To allow window dragging, etc. - } else { - - handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons); - handleEnterLeave(window, currentWindowUnderPointer, globalPos); - - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, - keyModifiers, Qt::MouseEventNotSynthesized); - - // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND - // has go to through DefWindowProc() for resizing to work, so we return false here, - // unless the click was on a menu, as it would mess with menu processing. - return msg.message != WM_POINTERDOWN || isMenuWindow(window); - } - } - case WM_POINTERHWHEEL: - case WM_POINTERWHEEL: { - - if (!isValidWheelReceiver(window)) - return true; - - int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); - - // Qt horizontal wheel rotation orientation is opposite to the one in WM_POINTERHWHEEL - if (msg.message == WM_POINTERHWHEEL) - delta = -delta; - - const QPoint angleDelta = (msg.message == WM_POINTERHWHEEL || (keyModifiers & Qt::AltModifier)) ? - QPoint(delta, 0) : QPoint(0, delta); - - QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); - return true; - } - case WM_POINTERLEAVE: - return true; - } - return false; -} - bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, quint32 count) @@ -653,15 +451,14 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, QList touchPoints; - bool primaryPointer = false; - bool pressRelease = false; - if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents).noquote().nospace() << showbase << __FUNCTION__ << " message=" << hex << msg.message << " count=" << dec << count; + Qt::TouchPointStates allStates = 0; + for (quint32 i = 0; i < count; ++i) { if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents).noquote().nospace() << showbase @@ -670,7 +467,13 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags; QWindowSystemInterface::TouchPoint touchPoint; - touchPoint.id = touchInfo[i].pointerInfo.pointerId; + const quint32 pointerId = touchInfo[i].pointerInfo.pointerId; + int id = m_touchInputIDToTouchPointID.value(pointerId, -1); + if (id == -1) { + id = m_touchInputIDToTouchPointID.size(); + m_touchInputIDToTouchPointID.insert(pointerId, id); + } + touchPoint.id = id; touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ? touchInfo[i].pressure / 1024.0 : 1.0; if (m_lastTouchPositions.contains(touchPoint.id)) @@ -691,32 +494,27 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) { touchPoint.state = Qt::TouchPointPressed; m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition); - pressRelease = true; } else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) { touchPoint.state = Qt::TouchPointReleased; m_lastTouchPositions.remove(touchPoint.id); - pressRelease = true; } else { touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved; m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition); } - if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) - primaryPointer = true; + allStates |= touchPoint.state; touchPoints.append(touchPoint); // Avoid getting repeated messages for this frame if there are multiple pointerIds QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId); } - if (primaryPointer && !pressRelease) { - // Postpone event delivery to avoid hanging inside DoDragDrop(). - // Only the primary pointer will generate mouse messages. - enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); - } else { - flushTouchEvents(m_touchDevice); - QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, - QWindowsKeyMapper::queryKeyboardModifiers()); - } + + // all touch points released, forget the ids we've seen. + if (allStates == Qt::TouchPointReleased) + m_touchInputIDToTouchPointID.clear(); + + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, + QWindowsKeyMapper::queryKeyboardModifiers()); return false; // Allow mouse messages to be generated. } @@ -807,10 +605,9 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - // Postpone event delivery to avoid hanging inside DoDragDrop(). - enqueueTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, - pressure, xTilt, yTilt, tangentialPressure, rotation, z, - pointerId, keyModifiers); + QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, + pressure, xTilt, yTilt, tangentialPressure, rotation, z, + pointerId, keyModifiers); return false; // Allow mouse messages to be generated. } } @@ -835,18 +632,46 @@ static inline bool isMouseEventSynthesizedFromPenOrTouch() return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE); } -// Process old-style mouse messages here. -bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) +bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window, + QWindow *currentWindowUnderPointer, + MSG msg, + QPoint globalPos, + Qt::KeyboardModifiers keyModifiers) { - // Generate enqueued events. - flushTouchEvents(m_touchDevice); - flushTabletEvents(); + QWindow *receiver = currentWindowUnderPointer; + if (!isValidWheelReceiver(receiver)) + receiver = window; + if (!isValidWheelReceiver(receiver)) + return true; + int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); + + // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL + if (msg.message == WM_MOUSEHWHEEL) + delta = -delta; + + const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ? + QPoint(delta, 0) : QPoint(0, delta); + + QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos); + + QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); + return true; +} + +// Process legacy mouse messages here. +bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, + HWND hwnd, + QtWindows::WindowsEventType et, + MSG msg, + LRESULT *result) +{ *result = 0; const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); QPoint localPos; QPoint globalPos; + if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) { globalPos = eventPos; localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos); @@ -857,46 +682,39 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); + QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); - // Handle "press and hold for right-clicking". - // We have to synthesize it here as it only comes from Windows as a fake RMB. - // MS docs say we could use bit 7 from extraInfo to distinguish pen from touch, - // but on the Surface it is set for both. So we use the last pointer type. - if (isMouseEventSynthesizedFromPenOrTouch()) { - if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP) - && (((m_lastPointerType == QT_PT_PEN) - && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)) - || ((m_lastPointerType == QT_PT_TOUCH) - && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) { - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton, - (msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress - : QEvent::MouseButtonRelease, - keyModifiers, Qt::MouseEventSynthesizedBySystem); - } - // Messages synthesized from touch/pen are only used for flushing queues and press&hold. - return false; + if (et == QtWindows::MouseWheelEvent) + return translateMouseWheelEvent(window, currentWindowUnderPointer, msg, globalPos, keyModifiers); + + // Windows sends a mouse move with no buttons pressed to signal "Enter" + // when a window is shown over the cursor. Discard the event and only use + // it for generating QEvent::Enter to be consistent with other platforms - + // X11 and macOS. + bool discardEvent = false; + if (msg.message == WM_MOUSEMOVE) { + static QPoint lastMouseMovePos; + if (msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos)) + discardEvent = true; + lastMouseMovePos = globalPos; } - if (et == QtWindows::MouseWheelEvent) { + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; + if (isMouseEventSynthesizedFromPenOrTouch()) { + if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) + return false; + source = Qt::MouseEventSynthesizedBySystem; + } - if (!isValidWheelReceiver(window)) - return true; + const MouseEvent mouseEvent = eventFromMsg(msg); - int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); - - // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL - if (msg.message == WM_MOUSEHWHEEL) - delta = -delta; - - const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ? - QPoint(delta, 0) : QPoint(0, delta); - - QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); - return true; + if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) { + QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, + mouseEvent.button, mouseEvent.type, keyModifiers, source); + return false; // Allow further event processing } if (msg.message == WM_MOUSELEAVE) { - if (window == m_currentWindow) { QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow; qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget; @@ -904,14 +722,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW m_windowUnderPointer = nullptr; m_currentWindow = nullptr; } - - } else if (msg.message == WM_MOUSEMOVE) { - - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); - handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons); - handleEnterLeave(window, currentWindowUnderPointer, globalPos); + return true; } - return false; + + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons); + handleEnterLeave(window, currentWindowUnderPointer, globalPos); + + if (!discardEvent && mouseEvent.type != QEvent::None) { + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, + mouseEvent.button, mouseEvent.type, keyModifiers, source); + } + + // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND + // is sent for unhandled WM_XBUTTONDOWN. + return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK) + || QWindowSystemInterface::flushWindowSystemEvents(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index ec3179e8218..aebef062bce 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -66,19 +66,19 @@ public: void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; } private: - bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo); bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); + bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers); void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons); void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos); QTouchDevice *m_touchDevice = nullptr; QHash m_lastTouchPositions; + QHash m_touchInputIDToTouchPointID; QPointer m_windowUnderPointer; QPointer m_currentWindow; QWindow *m_previousCaptureWindow = nullptr; bool m_needsEnterOnPointerUpdate = false; - DWORD m_lastPointerType = 0; }; QT_END_NAMESPACE From 81fd7f4c8af260d753a834480f790c82fb161889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 14:06:08 +0100 Subject: [PATCH 13/27] macOS: Add auto-release pool during QCocoaScreen::deliverUpdateRequests() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checking the application's keyWindow will autorelease the window, and there's no root pool in place when called from the display-link thread. Change-Id: Ic43164ad6397c92b858fb549f7a00e28b6110849 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoascreen.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index 80dd7e40d35..830a387fd16 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -269,6 +269,8 @@ struct DeferredDebugHelper void QCocoaScreen::deliverUpdateRequests() { + QMacAutoReleasePool pool; + // The CVDisplayLink callback is a notification that it's a good time to produce a new frame. // Since the callback is delivered on a separate thread we have to marshal it over to the // main thread, as Qt requires update requests to be delivered there. This needs to happen From d6c474b49b349dc6c30ea059040285221e712217 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 14 Dec 2018 12:36:22 +0100 Subject: [PATCH 14/27] QTextDocument: Do respect white-space:nowrap Prevent automatic insertion of line-breaks in blocks formatted with 'white-space:nowrap'. This follows the example of white-space:pre. Fixes: QTBUG-54787 Change-Id: If26f6a54106a02fe0e388947f6368ae4e86acf63 Reviewed-by: Shawn Rutledge Reviewed-by: Simon Hausmann --- src/gui/text/qtextdocumentfragment.cpp | 3 ++- .../tst_qtextdocumentfragment.cpp | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index e7eaa54a454..6b3604afb52 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -1139,7 +1139,8 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode() // #################### // block.setFloatPosition(node->cssFloat); - if (wsm == QTextHtmlParserNode::WhiteSpacePre) { + if (wsm == QTextHtmlParserNode::WhiteSpacePre + || wsm == QTextHtmlParserNode::WhiteSpaceNoWrap) { block.setNonBreakableLines(true); modifiedBlockFormat = true; } diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp index 3e354b7523b..d652bb066dd 100644 --- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp +++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp @@ -195,6 +195,8 @@ private slots: void css_linkPseudo(); void css_pageBreaks(); void css_cellPaddings(); + void css_whiteSpace_data(); + void css_whiteSpace(); void universalSelectors_data(); void universalSelectors(); void screenMedia(); @@ -1770,6 +1772,26 @@ void tst_QTextDocumentFragment::css_cellPaddings() QCOMPARE(cell.format().toTableCellFormat().bottomPadding(), qreal(15)); } +void tst_QTextDocumentFragment::css_whiteSpace_data() +{ + QTest::addColumn("htmlText"); + QTest::addColumn("nowrap"); + + QTest::newRow("default") << QString("

Normal Text

") << false; + QTest::newRow("white-space:nowrap") << QString("

Normal Text

") << true; + QTest::newRow("white-space:pre") << QString("

Normal Text

") << true; +} + +void tst_QTextDocumentFragment::css_whiteSpace() +{ + QFETCH(QString, htmlText); + QFETCH(bool, nowrap); + + doc->setHtml(htmlText); + QCOMPARE(doc->blockCount(), 1); + QCOMPARE(doc->begin().blockFormat().nonBreakableLines(), nowrap); +} + void tst_QTextDocumentFragment::html_blockLevelDiv() { const char html[] = "
Hello World"; From 6c18f86af7affc60a571c65f0b335d7ee8947100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 13:02:48 +0100 Subject: [PATCH 15/27] Track call sites of QMacAutoReleasePools for debugging pool usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Printing pools by calling [NSAutoreleasePool showPools] will now give a more detailed view of where the various pools in the stack were created, eg: AUTORELEASE POOLS for thread 0x1000be5c0 17 releases pending. [0x107802000] ................ PAGE (hot) (cold) [0x107802038] ################ POOL 0x107802038 [0x107802040] 0x107791c70 ^-- allocated in function: main [0x107802048] ################ POOL 0x107802048 [0x107802050] 0x1073b2e80 ^-- allocated in function: QCocoaWindow::initialize() [0x107802058] 0x107111ed0 NSCompositeAppearance [0x107802060] 0x107111ed0 NSCompositeAppearance [0x107802068] 0x107111ed0 NSCompositeAppearance [0x107802070] 0x1073bbe10 __NSCFString [0x107802078] 0x1073bbde0 _NSViewBackingLayer [0x107802080] 0x1073bc100 NSWeakObjectValue [0x107802088] 0x1073bbe40 QNSView [0x107802090] 0x1073bbe40 QNSView [0x107802098] 0x107111ed0 NSCompositeAppearance [0x1078020a0] 0x107111ed0 NSCompositeAppearance [0x1078020a8] 0x1073bbe40 QNSView [0x1078020b0] ################ POOL 0x1078020b0 [0x1078020b8] 0x1073bbe30 ^-- allocated in function: QCocoaWindow::recreateWindowIfNeeded() Change-Id: I97faf30db5835fea2f05320435b1b8c334a478d1 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcore_mac_objc.mm | 59 ++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 140c60a0800..4550891e2a4 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -48,6 +48,11 @@ #include #endif +#include +#include +#include +#include + #include QT_BEGIN_NAMESPACE @@ -127,22 +132,54 @@ QT_USE_NAMESPACE } @end QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker); + QT_BEGIN_NAMESPACE - -/* - Manages a scoped auto-release pool. - - To track autoreleases without any pools in place, such as in main() - before the runloop has started, export OBJC_DEBUG_MISSING_POOLS=YES - and break in objc_autoreleaseNoPool, e.g.: - - br set -n objc_autoreleaseNoPool -c "[((NSObject*)$r14) class] == [QNSWindow class]" -*/ QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { - [[[QMacAutoReleasePoolTracker alloc] initWithPool: + Class trackerClass = [QMacAutoReleasePoolTracker class]; + +#ifdef QT_DEBUG + void *poolFrame = nullptr; + if (__builtin_available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 5.0, *)) { + void *frame; + if (backtrace_from_fp(__builtin_frame_address(0), &frame, 1)) + poolFrame = frame; + } else { + static const int maxFrames = 3; + void *callstack[maxFrames]; + if (backtrace(callstack, maxFrames) == maxFrames) + poolFrame = callstack[maxFrames - 1]; + } + + if (poolFrame) { + Dl_info info; + if (dladdr(poolFrame, &info) && info.dli_sname) { + const char *symbolName = info.dli_sname; + if (symbolName[0] == '_') { + int status; + if (char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status)) + symbolName = demangled; + } + + char *className = nullptr; + asprintf(&className, " ^-- allocated in function: %s", symbolName); + + if (Class existingClass = objc_getClass(className)) + trackerClass = existingClass; + else + trackerClass = objc_duplicateClass(trackerClass, className, 0); + + free(className); + + if (symbolName != info.dli_sname) + free((char*)symbolName); + } + } +#endif + + [[[trackerClass alloc] initWithPool: reinterpret_cast(&pool)] autorelease]; } From 18f415e46d592f255495061618891ed18d356d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 22 Jan 2019 12:34:02 +0100 Subject: [PATCH 16/27] QBackingStore: Make QPlatformBackingStore creation lazy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some platform backing stores may require that the window has been created, so let's defer the platform backingstore creation until absolutely necessary. Change-Id: Ib93151c6473e3bbe77d994782d84289c2f63bcf2 Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qbackingstore.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 0dfb52e7c33..d935deb4d63 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -62,7 +62,7 @@ public: } QWindow *window; - QPlatformBackingStore *platformBackingStore; + QPlatformBackingStore *platformBackingStore = nullptr; QScopedPointer highDpiBackingstore; QRegion staticContents; QSize size; @@ -95,8 +95,6 @@ public: QBackingStore::QBackingStore(QWindow *window) : d_ptr(new QBackingStorePrivate(window)) { - d_ptr->platformBackingStore = QGuiApplicationPrivate::platformIntegration()->createPlatformBackingStore(window); - d_ptr->platformBackingStore->setBackingStore(this); } /*! @@ -131,7 +129,8 @@ void QBackingStore::beginPaint(const QRegion ®ion) d_ptr->highDpiBackingstore->devicePixelRatio() != d_ptr->window->devicePixelRatio()) resize(size()); - d_ptr->platformBackingStore->beginPaint(QHighDpi::toNativeLocalRegion(region, d_ptr->window)); + QPlatformBackingStore *platformBackingStore = handle(); + platformBackingStore->beginPaint(QHighDpi::toNativeLocalRegion(region, d_ptr->window)); // When QtGui is applying a high-dpi scale factor the backing store // creates a "large" backing store image. This image needs to be @@ -139,7 +138,7 @@ void QBackingStore::beginPaint(const QRegion ®ion) // devicePixelRatio. Do this on a separate image instance that shares // the image data to avoid having the new devicePixelRatio be propagated // back to the platform plugin. - QPaintDevice *device = d_ptr->platformBackingStore->paintDevice(); + QPaintDevice *device = platformBackingStore->paintDevice(); if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image) { QImage *source = static_cast(device); const bool needsNewImage = d_ptr->highDpiBackingstore.isNull() @@ -168,7 +167,7 @@ void QBackingStore::beginPaint(const QRegion ®ion) */ QPaintDevice *QBackingStore::paintDevice() { - QPaintDevice *device = d_ptr->platformBackingStore->paintDevice(); + QPaintDevice *device = handle()->paintDevice(); if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image) return d_ptr->highDpiBackingstore.data(); @@ -189,7 +188,7 @@ void QBackingStore::endPaint() if (paintDevice()->paintingActive()) qWarning() << "QBackingStore::endPaint() called with active painter on backingstore paint device"; - d_ptr->platformBackingStore->endPaint(); + handle()->endPaint(); } static bool isRasterSurface(QWindow *window) @@ -247,7 +246,7 @@ void QBackingStore::flush(const QRegion ®ion, QWindow *window, const QPoint & Q_ASSERT(window == topLevelWindow || topLevelWindow->isAncestorOf(window, QWindow::ExcludeTransients)); - d_ptr->platformBackingStore->flush(window, QHighDpi::toNativeLocalRegion(region, window), + handle()->flush(window, QHighDpi::toNativeLocalRegion(region, window), QHighDpi::toNativeLocalPosition(offset, window)); } @@ -259,7 +258,7 @@ void QBackingStore::flush(const QRegion ®ion, QWindow *window, const QPoint & void QBackingStore::resize(const QSize &size) { d_ptr->size = size; - d_ptr->platformBackingStore->resize(QHighDpi::toNativePixels(size, d_ptr->window), d_ptr->staticContents); + handle()->resize(QHighDpi::toNativePixels(size, d_ptr->window), d_ptr->staticContents); } /*! @@ -286,7 +285,7 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy) if (qFloor(nativeDx) != nativeDx || qFloor(nativeDy) != nativeDy) return false; - return d_ptr->platformBackingStore->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window), + return handle()->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window), nativeDx, nativeDy); } @@ -367,6 +366,10 @@ void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPo */ QPlatformBackingStore *QBackingStore::handle() const { + if (!d_ptr->platformBackingStore) { + d_ptr->platformBackingStore = QGuiApplicationPrivate::platformIntegration()->createPlatformBackingStore(d_ptr->window); + d_ptr->platformBackingStore->setBackingStore(const_cast(this)); + } return d_ptr->platformBackingStore; } From 2dcfaf7bee9e74546b96481554ba06d5dcb29cfa Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 30 Jan 2019 13:44:54 +0100 Subject: [PATCH 17/27] qmake/vcxproj generator: Fix bug in extra compiler initialization QMake ignored every extra compiler that sets variable_out and whose output does not have a builtin compiler (C++, C). What the code wants to achieve is to ignore extra compilers that put their output into variables that are handled "somewhere else already", e.g. are in the otherFilters list. Evidence for that is to be found in the addOnInput == true if branch. Task-number: QTBUG-71283 Change-Id: I8c1d76febccacb450cd14ad7a1f4b87726832312 Reviewed-by: Brett Stottlemyer Reviewed-by: Edward Welbourne Reviewed-by: Oliver Wolff --- qmake/generators/win32/msvc_vcproj.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 95c16661e7b..a81e540e1f1 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1541,14 +1541,14 @@ void VcprojGenerator::initExtraCompilerOutputs() extraCompile.Filter = ""; extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it); - // If the extra compiler has a variable_out set the output file - // is added to an other file list, and does not need its own.. bool addOnInput = hasBuiltinCompiler(firstExpandedOutputFileName(*it)); - const ProString &tmp_other_out = project->first(ProKey(*it + ".variable_out")); - if (!tmp_other_out.isEmpty() && !addOnInput) - continue; - if (!addOnInput) { + // If the extra compiler has a variable_out set that is already handled + // some other place, ignore it. + const ProString &outputVar = project->first(ProKey(*it + ".variable_out")); + if (!outputVar.isEmpty() && otherFilters.contains(outputVar)) + continue; + QString tmp_out = project->first(ProKey(*it + ".output")).toQString(); if (project->values(ProKey(*it + ".CONFIG")).indexOf("combine") != -1) { // Combined output, only one file result From 9f3cdf3d44cce757450f027684980538cb1263c5 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 1 Feb 2019 15:06:56 +0100 Subject: [PATCH 18/27] INSTALL: Remove outdated reference to Windows CE Change-Id: Ie4960ab6632642094b97d8eeae5bfe17b0aad633 Reviewed-by: Maurice Kalinowski --- INSTALL | 1 - 1 file changed, 1 deletion(-) diff --git a/INSTALL b/INSTALL index 7c14b301f87..d0976a92ae8 100644 --- a/INSTALL +++ b/INSTALL @@ -7,4 +7,3 @@ or follow one of these links: Mac OS X: http://doc.qt.io/qt-%SHORTVERSION%/osx-building.html Windows: http://doc.qt.io/qt-%SHORTVERSION%/windows-building.html X11 Platforms: http://doc.qt.io/qt-%SHORTVERSION%/linux-building.html -Windows CE: http://doc.qt.io/qt-%SHORTVERSION%/install-wince.html From 736cc1d564a204f66b2a3dd8e12a34b64a38d971 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 8 Feb 2019 12:43:26 +0100 Subject: [PATCH 19/27] Don't wrongly detect fonts as oblique We were interpreting bit #8 as the oblique bit, but this is the WWS-conformity bit. Bit #10 is the oblique bit. [ChangeLog][Windows] Fixed an issue where loading fonts from files or data would sometimes mistakenly classify them as oblique. Fixes: QTBUG-73660 Change-Id: Id9e5012d1b89d0bee0e966c5105657b38834e13a Reviewed-by: Lars Knoll Reviewed-by: Konstantin Ritt --- .../fontdatabases/windows/qwindowsfontdatabase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 40ac46df85e..bd4338feb83 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -1429,8 +1429,8 @@ QT_WARNING_POP reinterpret_cast(fontData.constData() + qFromBigEndian(os2TableEntry->offset)); - bool italic = qFromBigEndian(os2Table->selection) & 1; - bool oblique = qFromBigEndian(os2Table->selection) & 128; + bool italic = qFromBigEndian(os2Table->selection) & (1 << 0); + bool oblique = qFromBigEndian(os2Table->selection) & (1 << 9); if (italic) fontEngine->fontDef.style = QFont::StyleItalic; From 896b30767980f7033c34c2b90be99aac696d6432 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 12 Feb 2019 09:09:50 +0100 Subject: [PATCH 20/27] Add support for Visual Studio 2019 Change-Id: I963fc1c159edc644f081675c3dee248c25d7c9dc Reviewed-by: Joerg Bornemann Reviewed-by: Andre de la Rocha --- mkspecs/common/msvc-version.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf index de8ba56b7b8..06af6abf13b 100644 --- a/mkspecs/common/msvc-version.conf +++ b/mkspecs/common/msvc-version.conf @@ -113,4 +113,9 @@ greaterThan(QMAKE_MSC_VER, 1910) { COMPAT_MKSPEC = } +greaterThan(QMAKE_MSC_VER, 1919) { + # Visual Studio 2019 (16.0) / Visual C++ 19.20 and up + MSVC_VER = 16.0 +} + !isEmpty(COMPAT_MKSPEC):!$$COMPAT_MKSPEC: CONFIG += $$COMPAT_MKSPEC From 4aafe68e1ac12ab0f897828f9f8c2930a68fac95 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 12 Feb 2019 09:23:28 +0100 Subject: [PATCH 21/27] qmake vcxproj generator: Update platform toolset and solution header for VS 2019 Change-Id: Id01f28f2ef3e271fa48dddf5f8ccb6b057180aa0 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_objectmodel.cpp | 3 ++- qmake/generators/win32/msvc_objectmodel.h | 3 ++- qmake/generators/win32/msvc_vcproj.cpp | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 4f0cee65e1b..7335211f301 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -55,7 +55,8 @@ static DotNET vsVersionFromString(const char *versionString) { "11.0", NET2012 }, { "12.0", NET2013 }, { "14.0", NET2015 }, - { "15.0", NET2017 } + { "15.0", NET2017 }, + { "16.0", NET2019 } }; DotNET result = NETUnknown; for (const auto entry : mapping) { diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 9d1a1704899..41a6ffafa70 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -52,7 +52,8 @@ enum DotNET { NET2012 = 0xb0, NET2013 = 0xc0, NET2015 = 0xd0, - NET2017 = 0xe0 + NET2017 = 0xe0, + NET2019 }; DotNET vsVersionFromString(const ProString &versionString); diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index a81e540e1f1..669c8287fff 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -74,6 +74,8 @@ const char _slnHeader140[] = "Microsoft Visual Studio Solution File, Format "\n# Visual Studio 2015"; const char _slnHeader141[] = "Microsoft Visual Studio Solution File, Format Version 12.00" "\n# Visual Studio 2017"; +const char _slnHeader142[] = "Microsoft Visual Studio Solution File, Format Version 12.00" + "\n# Visual Studio Version 16"; // The following UUID _may_ change for later servicepacks... // If so we need to search through the registry at // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects @@ -301,6 +303,8 @@ QString VcprojGenerator::retrievePlatformToolSet() const return QStringLiteral("v140"); case NET2017: return QStringLiteral("v141"); + case NET2019: + return QStringLiteral("v142"); default: return QString(); } @@ -527,6 +531,9 @@ void VcprojGenerator::writeSubDirs(QTextStream &t) } switch (vcProject.Configuration.CompilerVersion) { + case NET2019: + t << _slnHeader142; + break; case NET2017: t << _slnHeader141; break; @@ -874,6 +881,9 @@ void VcprojGenerator::initProject() // Own elements ----------------------------- vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString(); switch (vcProject.Configuration.CompilerVersion) { + case NET2019: + vcProject.Version = "16.00"; + break; case NET2017: vcProject.Version = "15.00"; break; From 083c03e22b40cda682043df1044e01e15df2ce4b Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 12 Feb 2019 10:37:10 +0100 Subject: [PATCH 22/27] qmake vcxproj generator: Use correct version in solution header for 2017 Change-Id: I360202c88a8da84f3ecaf43304fcf6f5a992b953 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_vcproj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 669c8287fff..713a55d16bb 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -73,7 +73,7 @@ const char _slnHeader120[] = "Microsoft Visual Studio Solution File, Format const char _slnHeader140[] = "Microsoft Visual Studio Solution File, Format Version 12.00" "\n# Visual Studio 2015"; const char _slnHeader141[] = "Microsoft Visual Studio Solution File, Format Version 12.00" - "\n# Visual Studio 2017"; + "\n# Visual Studio 15"; const char _slnHeader142[] = "Microsoft Visual Studio Solution File, Format Version 12.00" "\n# Visual Studio Version 16"; // The following UUID _may_ change for later servicepacks... From a2c9f9433a772c03e6aaf820910487d794280c3a Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 6 Feb 2019 11:24:17 +0100 Subject: [PATCH 23/27] winrt: Handle WaitForWindowExposed As winrt does not have native windows, exposure check was just done by checking, whether the window is the active window. If a window is shown fullscreen though, winrtscreen will be resized. This resize triggers a resize of every maximized or fullscreen window that is shown. If we enter or leave full screen mode, we have to wait until the screen resize and the subsequent window resizes are done and only then we can consider the windows properly exposed. This patch reverts 54bcb9d42f5ceaafcca426dc2a5cc25d299d5a3d and thus unblacklists tst_QGraphicsItem::cursor on WinRT. Fixes: QTBUG-73545 Change-Id: If469fce319ed6b3a5d56b7bf3cbc11929b72bb11 Reviewed-by: Andre de la Rocha Reviewed-by: Qt CI Bot Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 18 +++++++++++++++++- src/plugins/platforms/winrt/qwinrtscreen.h | 3 +++ src/plugins/platforms/winrt/qwinrtwindow.cpp | 5 ++++- .../graphicsview/qgraphicsitem/BLACKLIST | 3 --- 4 files changed, 24 insertions(+), 5 deletions(-) delete mode 100644 tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 7f1854c601a..e611c7be240 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -511,6 +511,7 @@ public: QWindow *currentPressWindow = nullptr; QWindow *currentTargetWindow = nullptr; bool firstMouseMove = true; + bool resizePending = false; }; // To be called from the XAML thread @@ -1402,6 +1403,18 @@ void QWinRTScreen::emulateMouseMove(const QPointF &point, MousePositionTransitio Qt::NoModifier); } +void QWinRTScreen::setResizePending() +{ + Q_D(QWinRTScreen); + d->resizePending = true; +} + +bool QWinRTScreen::resizePending() const +{ + Q_D(const QWinRTScreen); + return d->resizePending; +} + HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args) { Q_D(QWinRTScreen); @@ -1507,7 +1520,7 @@ HRESULT QWinRTScreen::onRedirectReleased(ICorePointerRedirector *, IPointerEvent return onPointerUpdated(nullptr, args); } -HRESULT QWinRTScreen::onWindowSizeChanged(IApplicationView *, IInspectable *) +HRESULT QWinRTScreen::onWindowSizeChanged(IApplicationView *w, IInspectable *) { Q_D(QWinRTScreen); @@ -1527,6 +1540,9 @@ HRESULT QWinRTScreen::onWindowSizeChanged(IApplicationView *, IInspectable *) QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); + // If we "emulate" a resize, w will be nullptr.Checking w shows whether it's a real resize + if (w) + d->resizePending = false; return S_OK; } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index e28cfd8cc8a..63c254940df 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -136,6 +136,9 @@ public: void emulateMouseMove(const QPointF &point, MousePositionTransition transition); + void setResizePending(); + bool resizePending() const; + private: void handleExpose(); diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 83c3715bfdc..73816b65129 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -225,7 +225,8 @@ bool QWinRTWindow::isActive() const bool QWinRTWindow::isExposed() const { - const bool exposed = isActive(); + Q_D(const QWinRTWindow); + const bool exposed = isActive() && !d->screen->resizePending(); return exposed; } @@ -360,6 +361,7 @@ void QWinRTWindow::setWindowState(Qt::WindowStates state) qCDebug(lcQpaWindows) << "Failed to enter full screen mode."; return; } + d->screen->setResizePending(); d->state = state; return; } @@ -384,6 +386,7 @@ void QWinRTWindow::setWindowState(Qt::WindowStates state) qCDebug(lcQpaWindows) << "Failed to exit full screen mode."; return; } + d->screen->setResizePending(); } if (d->state & Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive) diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST deleted file mode 100644 index 071ccaaff45..00000000000 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -[cursor] -# QTBUG-73545 -winrt From 4b4a288f5f88077d647d47e9bdd911edf6cdca72 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 5 Feb 2019 10:45:38 +0100 Subject: [PATCH 24/27] Recognize UNC paths as absolute (i.e. not relative) IoUtils::isRelativePath() didn't attempt to consider UNC paths, due to a belief that qmake fails on them so badly that it wasn't worth the extra code. However, it turns out Qt Creator's copy of this code does need to take this into account, so start the change off in qmake's version so as to keep in sync. Task-number: QTCREATORBUG-21881 Change-Id: I3084b87c1d3ca6508255e94e04ac8db3ceaebb7e Reviewed-by: Joerg Bornemann --- qmake/library/ioutils.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 2b2c6d0078b..3e49a99cd5d 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -77,7 +77,12 @@ bool IoUtils::isRelativePath(const QString &path) && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) { return false; } - // (... unless, of course, they're UNC, which qmake fails on anyway) + // ... unless, of course, they're UNC: + if (path.length() >= 2 + && (path.at(0).unicode() == '\\' || path.at(0).unicode() == '/') + && path.at(1) == path.at(0)) { + return false; + } #else if (path.startsWith(QLatin1Char('/'))) return false; From 797f686ea4c7ba4953242fc7755bf30e531644d0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 11 Feb 2019 15:00:09 +0100 Subject: [PATCH 25/27] Turn bcm_host library into makeSpec source The bcm_host library couldn't be detected anymore. Let the makespec provide LIBDIR, INCDIR and LIBS for bcm_host to fix this. Change-Id: I4bc268504dc48edaf2884f1c14b745260fd9112c Fixes: QTBUG-73727 Reviewed-by: Kai Koehne --- mkspecs/devices/linux-rasp-pi-g++/qmake.conf | 4 ++++ mkspecs/devices/linux-rasp-pi2-g++/qmake.conf | 5 +++++ mkspecs/devices/linux-rasp-pi3-g++/qmake.conf | 4 ++++ src/gui/configure.json | 3 ++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf index b72091373d0..6ec7817efbd 100644 --- a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf @@ -20,6 +20,10 @@ QMAKE_INCDIR_OPENVG = $${QMAKE_INCDIR_EGL} QMAKE_LIBS_EGL = -lEGL -lGLESv2 QMAKE_LIBS_OPENVG = -lEGL -lOpenVG -lGLESv2 +QMAKE_INCDIR_BCM_HOST = $$[QT_SYSROOT]/opt/vc/include +QMAKE_LIBDIR_BCM_HOST = $$[QT_SYSROOT]/opt/vc/lib +QMAKE_LIBS_BCM_HOST = -lbcm_host + contains(DISTRO, squeeze) { #Debian Squeeze: Legacy everything QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 -lEGL diff --git a/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf index ffe8f5739a5..3b49f19a5b9 100644 --- a/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf @@ -16,6 +16,11 @@ QMAKE_INCDIR_OPENVG = $${QMAKE_INCDIR_EGL} QMAKE_LIBS_EGL = -lEGL -lGLESv2 QMAKE_LIBS_OPENVG = -lEGL -lOpenVG -lGLESv2 + +QMAKE_INCDIR_BCM_HOST = $$[QT_SYSROOT]/opt/vc/include +QMAKE_LIBDIR_BCM_HOST = $$[QT_SYSROOT]/opt/vc/lib +QMAKE_LIBS_BCM_HOST = -lbcm_host + QMAKE_CFLAGS += -march=armv7-a -marm -mthumb-interwork -mfpu=neon-vfpv4 -mtune=cortex-a7 -mabi=aapcs-linux QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/devices/linux-rasp-pi3-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi3-g++/qmake.conf index 2bb70ffb5aa..b215833486d 100644 --- a/mkspecs/devices/linux-rasp-pi3-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi3-g++/qmake.conf @@ -31,6 +31,10 @@ QMAKE_LIBS_OPENGL_ES2 = $${VC_LINK_LINE} -lGLESv2 # The official opt vc EGL references GLESv2 symbols: need to link it QMAKE_LIBS_EGL = $${VC_LINK_LINE} -lEGL -lGLESv2 +QMAKE_LIBDIR_BCM_HOST = $$VC_LIBRARY_PATH +QMAKE_INCDIR_BCM_HOST = $$VC_INCLUDE_PATH +QMAKE_LIBS_BCM_HOST = -lbcm_host + QMAKE_CFLAGS = -march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/src/gui/configure.json b/src/gui/configure.json index 70d08177915..44140bc7b67 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -59,8 +59,9 @@ }, "bcm_host": { "export": "", + "headers": ["bcm_host.h"], "sources": [ - "-lbcm_host" + { "type": "makeSpec", "spec": "BCM_HOST" } ] }, "dxguid": { From a34077ceac6a3e436328fcfb444e20111455a885 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 13 Feb 2019 15:42:11 +0100 Subject: [PATCH 26/27] Windows: Freetype: Load fonts from the user locations Since Windows 10 update 1809 it is possible to install fonts as a user so they are only available for use by the user and not on the system. So this location in the registry needs to be checked as well when looking for available fonts. Fixes: QTBUG-73241 Change-Id: I5d808e38b80dde8189fe8c549a6524bd559e30c7 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../windows/qwindowsfontdatabase_ft.cpp | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index f68ea54dcf4..db2186644bb 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -115,30 +115,33 @@ static FontKeys &fontKeys() { static FontKeys result; if (result.isEmpty()) { - const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), - QSettings::NativeFormat); - const QStringList allKeys = fontRegistry.allKeys(); - const QString trueType = QStringLiteral("(TrueType)"); + const QStringList keys = { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), + QStringLiteral("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") }; + for (const auto key : keys) { + const QSettings fontRegistry(key, QSettings::NativeFormat); + const QStringList allKeys = fontRegistry.allKeys(); + const QString trueType = QStringLiteral("(TrueType)"); #if QT_CONFIG(regularexpression) - const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); + const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); #else - const QRegExp sizeListMatch(QLatin1String("\\s(\\d+,)+\\d+")); + const QRegExp sizeListMatch(QLatin1String("\\s(\\d+,)+\\d+")); #endif - Q_ASSERT(sizeListMatch.isValid()); - const int size = allKeys.size(); - result.reserve(size); - for (int i = 0; i < size; ++i) { - FontKey fontKey; - const QString ®istryFontKey = allKeys.at(i); - fontKey.fileName = fontRegistry.value(registryFontKey).toString(); - QString realKey = registryFontKey; - realKey.remove(trueType); - realKey.remove(sizeListMatch); - const auto fontNames = QStringRef(&realKey).trimmed().split(QLatin1Char('&')); - fontKey.fontNames.reserve(fontNames.size()); - for (const QStringRef &fontName : fontNames) - fontKey.fontNames.append(fontName.trimmed().toString()); - result.append(fontKey); + Q_ASSERT(sizeListMatch.isValid()); + const int size = allKeys.size(); + result.reserve(result.size() + size); + for (int i = 0; i < size; ++i) { + FontKey fontKey; + const QString ®istryFontKey = allKeys.at(i); + fontKey.fileName = fontRegistry.value(registryFontKey).toString(); + QString realKey = registryFontKey; + realKey.remove(trueType); + realKey.remove(sizeListMatch); + const auto fontNames = QStringRef(&realKey).trimmed().split(QLatin1Char('&')); + fontKey.fontNames.reserve(fontNames.size()); + for (const QStringRef &fontName : fontNames) + fontKey.fontNames.append(fontName.trimmed().toString()); + result.append(fontKey); + } } } return result; From 501cca2c4b0851cea7133ba56c3a05d71c25ce6d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 27 Jan 2019 13:54:06 +0100 Subject: [PATCH 27/27] Add include to hurd-g++ mkspec Without this include, __REDIRECT does not get defined, and then open gets #defined to open64, leading to bogus MOC output. See https://bugs.debian.org/920613. Change-Id: I629d9dc6af05b9480c0c81a61d8890ab8bbefaae Reviewed-by: Joerg Bornemann --- mkspecs/hurd-g++/qplatformdefs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mkspecs/hurd-g++/qplatformdefs.h b/mkspecs/hurd-g++/qplatformdefs.h index 3c80cbdfade..b1887aae7f5 100644 --- a/mkspecs/hurd-g++/qplatformdefs.h +++ b/mkspecs/hurd-g++/qplatformdefs.h @@ -59,6 +59,7 @@ // We are hot - unistd.h should have turned on the specific APIs we requested +#include #include #include #include