From 8957cb2682d874403c3ee08c98bfd544a60c6da4 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Wed, 3 Apr 2019 14:18:20 +0200 Subject: [PATCH 01/19] Windows QPA: Fix mouse button reported in non-client events The current mouse buttons state was being retrieved from WPARAM for all mouse messages. However, for non-client messages this parameter contains unrelated information, which resulted in non-client events reporting incorrect button state. Changing it to retrieve state using GetAsyncKeyState() for non-client messages, like in the legacy mouse handler implementation. Fixes: QTBUG-74649 Change-Id: Ia246164208707072e584dd521697e9d31d3e65ad Reviewed-by: Friedemann Kleint --- .../windows/qwindowspointerhandler.cpp | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index f1960f1585..2673c04c48 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -250,6 +250,23 @@ static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState) return result; } +static Qt::MouseButtons queryMouseButtons() +{ + Qt::MouseButtons result = Qt::NoButton; + const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON); + if (GetAsyncKeyState(VK_LBUTTON) < 0) + result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton; + if (GetAsyncKeyState(VK_RBUTTON) < 0) + result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton; + if (GetAsyncKeyState(VK_MBUTTON) < 0) + result |= Qt::MidButton; + if (GetAsyncKeyState(VK_XBUTTON1) < 0) + result |= Qt::XButton1; + if (GetAsyncKeyState(VK_XBUTTON2) < 0) + result |= Qt::XButton2; + return result; +} + static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos) { QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); @@ -681,7 +698,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); if (et == QtWindows::MouseWheelEvent) @@ -709,7 +725,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, const MouseEvent mouseEvent = eventFromMsg(msg); if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) { - QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, + const Qt::MouseButtons nonclientButtons = queryMouseButtons(); + QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, nonclientButtons, mouseEvent.button, mouseEvent.type, keyModifiers, source); return false; // Allow further event processing } @@ -725,6 +742,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, return true; } + const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons); handleEnterLeave(window, currentWindowUnderPointer, globalPos); From 4451c86dfd134f35795383bf632f161629a720e4 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 27 Mar 2019 19:30:58 +0000 Subject: [PATCH 02/19] Doc-fixes in QRandomGenerator::bounded(int...) They return int, not quint32. Change-Id: I9879b58cccf9ea324ea1fc0c567a9d30b82fa44d Reviewed-by: Thiago Macieira (cherry picked from commit 6ed2ea86db63c72a38a60543da5a95d3543d39b1) --- src/corelib/global/qrandom.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 6195c324e7..90df8653a7 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -930,7 +930,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn quint32 QRandomGenerator::bounded(int highest) + \fn int QRandomGenerator::bounded(int highest) \overload Generates one random 32-bit quantity in the range between 0 (inclusive) and @@ -957,7 +957,6 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel \snippet code/src_corelib_global_qrandom.cpp 14 - Note that this function cannot be used to obtain values in the full 32-bit range of quint32. Instead, use generate(). @@ -965,7 +964,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn quint32 QRandomGenerator::bounded(int lowest, int highest) + \fn int QRandomGenerator::bounded(int lowest, int highest) \overload Generates one random 32-bit quantity in the range between \a lowest From f5da03ae78d1ae5f6cbd997c69711b9b7f13aab1 Mon Sep 17 00:00:00 2001 From: Antti Kokko Date: Mon, 1 Apr 2019 13:35:31 +0300 Subject: [PATCH 03/19] Add changes file for Qt 5.12.3 Edited-By: Thiago Macieira Change-Id: I26354551e7d3a6573bad0aa3851055f482a9a242 Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- dist/changes-5.12.3 | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 dist/changes-5.12.3 diff --git a/dist/changes-5.12.3 b/dist/changes-5.12.3 new file mode 100644 index 0000000000..e6636fc153 --- /dev/null +++ b/dist/changes-5.12.3 @@ -0,0 +1,82 @@ +Qt 5.12.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.2. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Third-Party Code * +**************************************************************************** + + - Changed classification of the wintab license from Public Domain to + Custom. + +**************************************************************************** +* QtCore * +**************************************************************************** + + - Event system: + * [QTBUG-72438] Fixed a possible race condition on Windows that would + cause an interrupted event loop to be stuck until more events were + posted. + + - Logging system: + * [QTBUG-74359] Fixed the compilation of qCDebug("", ...) when debug + output was disabled. + + - QCollator: + * [QTBUG-74209] Fixed a bug that caused QCompare to incorrect return a + sorting order on Windows if the Win32 API failed. + + - QDateTime / QTimeZone: + * [QTBUG-74614] Fixed handling of timezones that contain no DST + transitions. + + - QProcess: + * [QTBUG-73778] Fixed a crash when calling closeWriteChannel() on Windows. + +**************************************************************************** +* QtSql * +**************************************************************************** + + - When cross-compiling pg_config, mysql_config are not looked up in PATH + anymore. Pass -psql_config path/to/pg_config or -mysql_config + path/to/mysql_config to explicitly enable PSQL or MySQL in this setup. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + + - Android: + * Text fields with ImhNoPredictiveText set are no longer working around + keyboards that disregard this setting. To enforce the workaround, the + environment variable + QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT should be set. + + * [QTBUG-74029] Added entries in the AndroidManifest.xml for specific + portrait and landscape splash screens. If one is present for the current + orientation, it will be preferred over the generic one. + + - Linux: + * [QTBUG-74526] Changed the way we use the statx() system call to use a + fallback mechanism provided by the GNU C library. This should allow Qt + applications that are compiled with glibc >= 2.28 to run even on kernels + older than 4.11. + + - Windows: + * [QTBUG-74062] Fixed QToolTip pop-ups and QComboBox animation pop-ups + being off by a few pixels on Windows 10. + From 534df5a33bd6a3d0d00194212cf868a9ef57bd53 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Thu, 28 Mar 2019 18:33:44 +0300 Subject: [PATCH 04/19] Fix QTabletEvent::uniqueId() when Qt uses WinInk A new 'pointerId' is assigned to the stylus every time it enters tablet's proximity. But applications expect this ID be constant, at least during one application run. Therefore, it needs to use 'sourceDevice' instead. Basically, WinInk doesn't have an ability to distinguich two different styluses connected to the same tablet. We cannot do anything about it, it is supported only in WinTab. Task-number: QTBUG-74700 Change-Id: I8328f1e5102b037b370082e69e965ab68b487882 Reviewed-by: Andre de la Rocha --- .../platforms/windows/qwindowspointerhandler.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 2673c04c48..9a8b5d5121 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -548,7 +548,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect)) return false; - const quint32 pointerId = penInfo->pointerInfo.pointerId; + const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice; const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y); const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left) @@ -564,7 +564,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents).noquote().nospace() << showbase - << __FUNCTION__ << " pointerId=" << pointerId + << __FUNCTION__ << " sourceDevice=" << sourceDevice << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos << " message=" << hex << msg.message << " flags=" << hex << penInfo->pointerInfo.pointerFlags; @@ -587,7 +587,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin switch (msg.message) { case WM_POINTERENTER: { - QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, pointerId); + QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, sourceDevice); m_windowUnderPointer = window; // The local coordinates may fall outside the window. // Wait until the next update to send the enter event. @@ -600,12 +600,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin m_windowUnderPointer = nullptr; m_currentWindow = nullptr; } - QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, pointerId); + QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, sourceDevice); break; case WM_POINTERDOWN: case WM_POINTERUP: case WM_POINTERUPDATE: { - QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(pointerId).target; // Pass to window that grabbed it. + QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it. if (!target && m_windowUnderPointer) target = m_windowUnderPointer; if (!target) @@ -624,7 +624,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, - pointerId, keyModifiers); + sourceDevice, keyModifiers); return false; // Allow mouse messages to be generated. } } From 7c6b969383a403474a63715fd7a12caddd826611 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 15 Apr 2019 15:50:15 +0200 Subject: [PATCH 05/19] eglfs: Call destroy() from dtors of concrete windows Calling destroy from the QEglFSWindow dtor() triggers the virtual invalidateSurface() to be called on a partly destroyed object. As the child windows deregister themselves from their screens on invalidateSurface() this is dangerous: It leaves a dangling pointer in the screen. Fixes: QTBUG-75075 Change-Id: Idd3fea18562d41973f364340df875a50dbd5691e Reviewed-by: Laszlo Agocs --- src/plugins/platforms/eglfs/api/qeglfswindow.cpp | 3 +++ .../eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h | 3 +++ .../eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp | 2 ++ .../eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp | 3 +++ 4 files changed, 11 insertions(+) diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index 98e9ee4728..c1d5af47aa 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -167,6 +167,9 @@ void QEglFSWindow::create() void QEglFSWindow::destroy() { + if (!m_flags.testFlag(Created)) + return; // already destroyed + #ifndef QT_NO_OPENGL QOpenGLCompositor::instance()->removeWindow(this); #endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h index a19cf7e8bc..ee4b7978f1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h @@ -55,6 +55,9 @@ public: : QEglFSWindow(w), m_integration(integration) { } + + ~QEglFSKmsGbmWindow() { destroy(); } + void resetSurface() override; void invalidateSurface() override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index ecdfb352ab..3e78196227 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -116,6 +116,8 @@ public: , m_egl_stream(EGL_NO_STREAM_KHR) { } + ~QEglFSKmsEglDeviceWindow() { destroy(); } + void invalidateSurface() override; void resetSurface() override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp index 0d9b6b6290..d1250ec9bf 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp @@ -205,6 +205,9 @@ public: : QEglFSWindow(w) , m_integration(integration) {} + + ~QEglFSKmsVsp2Window() { destroy(); } + void resetSurface() override; void invalidateSurface() override; const QEglFSKmsVsp2Integration *m_integration; From 0bd27f80e0fff56e5450bb10aa7da8ba1ac00406 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 16 Apr 2019 10:19:27 +0200 Subject: [PATCH 06/19] ANGLE: clean up displays on dll unload If the displays are not cleaned up on dll unloading, profilers might report memory leaks. Change-Id: I04cbc3c2448bfb450f7d840e216827f86856e963 Reviewed-by: Friedemann Kleint Reviewed-by: Andre de la Rocha Reviewed-by: Andy Shaw --- src/3rdparty/angle/src/libANGLE/Display.cpp | 17 ++++ src/3rdparty/angle/src/libANGLE/Display.h | 1 + .../angle/src/libGLESv2/global_state.cpp | 2 + ...NGLE-clean-up-displays-on-dll-unload.patch | 78 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp index 735b472787..0bb0bb05b1 100644 --- a/src/3rdparty/angle/src/libANGLE/Display.cpp +++ b/src/3rdparty/angle/src/libANGLE/Display.cpp @@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri return display; } +//static +void Display::CleanupDisplays() +{ + // ~Display takes care of removing the entry from the according map + { + ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); + while (!displays->empty()) + delete displays->begin()->second; + } + + { + DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap(); + while (!displays->empty()) + delete displays->begin()->second; + } +} + Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice) : mImplementation(nullptr), mDisplayId(displayId), diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h index aa1d1c3b37..2a1c386d75 100644 --- a/src/3rdparty/angle/src/libANGLE/Display.h +++ b/src/3rdparty/angle/src/libANGLE/Display.h @@ -65,6 +65,7 @@ class Display final : angle::NonCopyable static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap); static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay, const AttributeMap &attribMap); + static void CleanupDisplays(); static const ClientExtensions &GetClientExtensions(); static const std::string &GetClientExtensionString(); diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp index c5f3dfe4e1..26045bf5b2 100644 --- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp +++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp @@ -13,6 +13,7 @@ #include "common/tls.h" #include "libANGLE/Thread.h" +#include "libANGLE/Display.h" namespace gl { @@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) return static_cast(egl::DeallocateCurrentThread()); case DLL_PROCESS_DETACH: + egl::Display::CleanupDisplays(); return static_cast(egl::TerminateProcess()); } diff --git a/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch new file mode 100644 index 0000000000..fce3fd76b2 --- /dev/null +++ b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch @@ -0,0 +1,78 @@ +From d8ca4f6d0d8fffd8319f340685e03751049678ae Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Tue, 16 Apr 2019 10:19:27 +0200 +Subject: [PATCH] ANGLE: clean up displays on dll unload + +If the displays are not cleaned up on dll unloading, profilers might +report memory leaks. + +Change-Id: I04cbc3c2448bfb450f7d840e216827f86856e963 +--- + src/3rdparty/angle/src/libANGLE/Display.cpp | 17 +++++++++++++++++ + src/3rdparty/angle/src/libANGLE/Display.h | 1 + + .../angle/src/libGLESv2/global_state.cpp | 2 ++ + 3 files changed, 20 insertions(+) + +diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp +index 735b472787..0bb0bb05b1 100644 +--- a/src/3rdparty/angle/src/libANGLE/Display.cpp ++++ b/src/3rdparty/angle/src/libANGLE/Display.cpp +@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri + return display; + } + ++//static ++void Display::CleanupDisplays() ++{ ++ // ~Display takes care of removing the entry from the according map ++ { ++ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); ++ while (!displays->empty()) ++ delete displays->begin()->second; ++ } ++ ++ { ++ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap(); ++ while (!displays->empty()) ++ delete displays->begin()->second; ++ } ++} ++ + Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice) + : mImplementation(nullptr), + mDisplayId(displayId), +diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h +index aa1d1c3b37..2a1c386d75 100644 +--- a/src/3rdparty/angle/src/libANGLE/Display.h ++++ b/src/3rdparty/angle/src/libANGLE/Display.h +@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable + static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap); + static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay, + const AttributeMap &attribMap); ++ static void CleanupDisplays(); + + static const ClientExtensions &GetClientExtensions(); + static const std::string &GetClientExtensionString(); +diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp +index c5f3dfe4e1..26045bf5b2 100644 +--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp +@@ -13,6 +13,7 @@ + #include "common/tls.h" + + #include "libANGLE/Thread.h" ++#include "libANGLE/Display.h" + + namespace gl + { +@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) + return static_cast(egl::DeallocateCurrentThread()); + + case DLL_PROCESS_DETACH: ++ egl::Display::CleanupDisplays(); + return static_cast(egl::TerminateProcess()); + } + +-- +2.20.1.windows.1 + From 7ee449a18695f7ec17bed18b59956003fabfe53e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 16 Apr 2019 12:23:26 +0200 Subject: [PATCH 07/19] Fix threaded QOpenGL when robustness is requested If the shared context had robustness set then all child contexts must as well, otherwise we will fallback to a non-shared context breaking threaded rendering. Change-Id: Ie5526e632ad21289b6164c1ca06e54ec714187c7 Reviewed-by: Laszlo Agocs --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 476de6d1e5..4adf662152 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -270,7 +270,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) // ES does not support any format option m_format.setOptions(QSurfaceFormat::FormatOptions()); } - + // Robustness must match that of the shared context. + if (share && share->format().testOption(QSurfaceFormat::ResetNotification)) + m_format.setOption(QSurfaceFormat::ResetNotification); Q_ASSERT(glVersions.count() > 0); for (int i = 0; !m_context && i < glVersions.count(); i++) { From e4d2c74aad2a04208981355ee1698dcf08b8cd95 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 12 Apr 2019 17:06:25 +0200 Subject: [PATCH 08/19] Fix setting Qt::WA_ShowWithoutActivating on eglfs window WebEngine HTML based popups depends on setting Qt::WA_ShowWithoutActivating, to keep forwarding events to chromium event handling. This works well with xcb, windows or coca windows backends, however was not respected on eglfs. Add check before activating the window. Task-number: QTBUG-69533 Change-Id: I66b249ec497af890c8a2228eee3bac3c806e77ed Reviewed-by: Laszlo Agocs --- src/plugins/platforms/eglfs/api/qeglfsintegration.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 48469b0f8c..c8a1ddf9b9 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -199,6 +199,10 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const QEglFSWindow *w = qt_egl_device_integration()->createWindow(window); w->create(); + const auto showWithoutActivating = window->property("_q_showWithoutActivating"); + if (showWithoutActivating.isValid() && showWithoutActivating.toBool()) + return w; + // Activate only the window for the primary screen to make input work if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen()) w->requestActivateWindow(); From 4298658bef89fb79974530bfa3723a48a6bf7efc Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 11 Apr 2019 14:37:44 +0200 Subject: [PATCH 09/19] Fix corner case in openglcompositor for eglfs Add 'source' window offset. This covers the cases where platform window is created besides one full screen window (like for popups), where content has qquickwidget / qopenglwidgtet. In that case fbos/textures from those widgets have offset according to 'source' window. Note backingstore texture has geometry of 'source' window. Task-number: QTBUG-69533 Change-Id: I2514b36fd3a6b9b86f51999df1c2b3e9565aafde Reviewed-by: Laszlo Agocs --- .../platformcompositor/qopenglcompositor.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 0f4946f81a..635bf0107f 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -188,14 +188,15 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) topLeftRect.width(), topLeftRect.height()); } -static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, +static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &sourceWindowRect, + const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix) { const QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) return; - const QRect rectInWindow = textures->geometry(idx); + const QRect rectInWindow = textures->geometry(idx).translated(sourceWindowRect.topLeft()); const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); @@ -218,7 +219,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window) const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size()); float currentOpacity = 1.0f; BlendStateBinder blend; - + const QRect sourceWindowRect = window->sourceWindow()->geometry(); for (int i = 0; i < textures->count(); ++i) { uint textureId = textures->textureId(i); const float opacity = window->sourceWindow()->opacity(); @@ -243,16 +244,16 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window) target = m_rotationMatrix * target; m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { - // Texture from an FBO belonging to a QOpenGLWidget + // Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget blend.set(false); - clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); + clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); } } for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { blend.set(true); - clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); + clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); } } From c096d97097e37b36281f8ad25852a2397f20a32f Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Mon, 15 Apr 2019 16:37:11 +0200 Subject: [PATCH 10/19] Windows QPA: Fix custom drop formats being ignored Changes QWindowsDropDataObject to only ignore non-CF_HDROP formats when the drop contains only "text/uri-list" mime data, and the URIs are for local files, to avoid messing with custom formats set by the developer, while still fixing the case reported in QTBUG-62662. Fixes: QTBUG-74232 Change-Id: I946ced222377716876d0aea54b3eb05d40e7fa44 Reviewed-by: Friedemann Kleint --- .../windows/qwindowsdropdataobject.cpp | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp index 229ff92894..e1a41c0ede 100644 --- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -41,6 +41,7 @@ #include #include +#include "qwindowsmime.h" QT_BEGIN_NAMESPACE @@ -48,8 +49,9 @@ QT_BEGIN_NAMESPACE \class QWindowsDropDataObject \brief QWindowsOleDataObject subclass specialized for handling Drag&Drop. - Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped - files to be attached to Office applications (instead of adding an URL link). + Prevents "text/uri-list" data for local files from being exported as text + or URLs, to allow dropped files to be attached to Office applications + (instead of creating local hyperlinks). \internal \ingroup qt-lighthouse-win @@ -80,14 +82,22 @@ QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc) return QWindowsOleDataObject::QueryGetData(pformatetc); } -// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP. +// If the data is "text/uri-list" only, and all URIs are for local files, +// we prevent it from being exported as text or URLs, to make target applications +// like MS Office attach or open the files instead of creating local hyperlinks. bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const { QMimeData *dropData = mimeData(); - if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) { - QList urls = dropData->urls(); - return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); + if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) { + QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat); + if (pformatetc->cfFormat == CF_UNICODETEXT + || pformatetc->cfFormat == CF_TEXT + || formatName == QStringLiteral("UniformResourceLocator") + || formatName == QStringLiteral("UniformResourceLocatorW")) { + QList urls = dropData->urls(); + return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); + } } return false; From c381df060f16a522e6edd3541b09af06c0aa3024 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 17 Apr 2019 15:03:58 +0200 Subject: [PATCH 11/19] Doc: Document QMAKE_[L|C[XX]]FLAGS_RELEASE_WITH_DEBUGINFO Fixes: QTBUG-17463 Change-Id: Ic2f0870da14db21b1da053716b6d63ba0ed679c9 Reviewed-by: Leena Miettinen --- qmake/doc/src/qmake-manual.qdoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 1e1b365141..a4c314b709 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -1580,6 +1580,14 @@ The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \target QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO + \section1 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO + + Specifies the C compiler flags for release builds where + \c{force_debug_info} is set in \c{CONFIG}. + The value of this variable is typically handled by + qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \target QMAKE_CFLAGS_SHLIB \section1 QMAKE_CFLAGS_SHLIB @@ -1648,6 +1656,14 @@ The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \target QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO + \section1 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO + + Specifies the C++ compiler flags for release builds where + \c{force_debug_info} is set in \c{CONFIG}. + The value of this variable is typically handled by + qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \target QMAKE_CXXFLAGS_SHLIB \section1 QMAKE_CXXFLAGS_SHLIB @@ -2028,6 +2044,12 @@ The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \section1 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO + + Specifies the linker flags for release builds where \c{force_debug_info} is + set in \c{CONFIG}. The value of this variable is typically handled by + qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \section1 QMAKE_LFLAGS_APP Specifies the linker flags for building applications. From b556890a9f7dd45550f0d4e9da981e2f779a943b Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Wed, 17 Apr 2019 17:19:03 +0200 Subject: [PATCH 12/19] Windows QPA: fix media keys losing autorepeat/keycode information For WM_APPCOMMAND messages that also trigger WM_KEYDOWN/WM_KEYUP, let the latter messages be handled, instead of stripping them and synthesizing a press/release from the command code, in order to get the correct scan codes and autorepeat info. Fixes: QTBUG-73879 Change-Id: I936cd76be87a76dc6b6223eeb246e4e7aee3a4ac Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowskeymapper.cpp | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index c050369801..c5af4d8042 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -879,21 +879,16 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con #if defined(WM_APPCOMMAND) const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam); // QTBUG-57198, do not send mouse-synthesized commands as key events in addition + bool skipPressRelease = false; switch (GET_DEVICE_LPARAM(msg.lParam)) { case FAPPCOMMAND_MOUSE: return false; case FAPPCOMMAND_KEY: - // QTBUG-62838, swallow WM_KEYDOWN, WM_KEYUP for commands that are - // reflected in VK(s) like VK_MEDIA_NEXT_TRACK. Don't do that for - // APPCOMMAND_BROWSER_HOME as that one does not trigger two events - if (cmd != APPCOMMAND_BROWSER_HOME) { - MSG peekedMsg; - if (PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_NOREMOVE) - && peekedMsg.message == WM_KEYDOWN) { - PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE); - PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE); - } - } + // QTBUG-62838, use WM_KEYDOWN/WM_KEYUP for commands that are reflected + // in VK(s) like VK_MEDIA_NEXT_TRACK, to get correct codes and autorepeat. + // Don't do that for APPCOMMAND_BROWSER_HOME as that one does not trigger two events. + if (cmd != APPCOMMAND_BROWSER_HOME) + skipPressRelease = true; break; } @@ -908,7 +903,8 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con return false; const int qtKey = int(CmdTbl[cmd]); - sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0); + if (!skipPressRelease) + sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0); // QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise, // the keys are not passed to the active media player. # if QT_CONFIG(shortcut) From 585150e3d947d0ee30489f275e7fc39bce4fe059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 22 Mar 2019 15:13:25 +0100 Subject: [PATCH 13/19] macOS: Clean up and deduplicate QMacCGContext We now use QCFType to track the CGContextRef, instead of manually maintaining the lifetime of the context. A bunch of unused methods were removed, including completely broken ones like isNull(). Change-Id: Ib5a05aadbf8f228192e74c9a4c8919580b831497 Reviewed-by: Timur Pocheptsov --- src/gui/painting/qcoregraphics.mm | 162 ++++++++++++++++------------- src/gui/painting/qcoregraphics_p.h | 36 ++----- 2 files changed, 95 insertions(+), 103 deletions(-) diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index 53066687d3..e2497eaadb 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -366,40 +366,35 @@ void qt_mac_scale_region(QRegion *region, qreal scaleFactor) // ---------------------- QMacCGContext ---------------------- -QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) : context(0) +QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) { - // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood. - QImage *image = 0; - if (paintDevice->devType() == QInternal::Image) { - image = static_cast(paintDevice); - } else if (paintDevice->devType() == QInternal::Pixmap) { - - const QPixmap *pm = static_cast(paintDevice); - QPlatformPixmap *data = const_cast(pm)->data_ptr().data(); - if (data && data->classId() == QPlatformPixmap::RasterClass) { - image = data->buffer(); - } else { - qDebug("QMacCGContext: Unsupported pixmap class"); - } - } else if (paintDevice->devType() == QInternal::Widget) { - // TODO test: image = static_cast(static_cast(paintDevice)->backingStore()->paintDevice()); - qDebug("QMacCGContext: not implemented: Widget class"); - } - - if (!image) - return; // Context type not supported. - - QCFType colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - context = CGBitmapContextCreate(image->bits(), image->width(), image->height(), 8, - image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image)); - - CGContextTranslateCTM(context, 0, image->height()); - const qreal devicePixelRatio = paintDevice->devicePixelRatioF(); - CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); - CGContextScaleCTM(context, 1, -1); + initialize(paintDevice); } -QMacCGContext::QMacCGContext(QPainter *painter) : context(0) +void QMacCGContext::initialize(QPaintDevice *paintDevice) +{ + // Find the underlying QImage of the paint device + switch (int deviceType = paintDevice->devType()) { + case QInternal::Pixmap: { + auto *platformPixmap = static_cast(paintDevice)->handle(); + if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass) + initialize(platformPixmap->buffer()); + else + qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId(); + break; + } + case QInternal::Image: + initialize(static_cast(paintDevice)); + break; + case QInternal::Widget: + qWarning() << "QMacCGContext: not implemented: Widget class"; + break; + default: + qWarning() << "QMacCGContext:: Unsupported paint device type" << deviceType; + } +} + +QMacCGContext::QMacCGContext(QPainter *painter) { QPaintEngine *paintEngine = painter->paintEngine(); @@ -414,51 +409,68 @@ QMacCGContext::QMacCGContext(QPainter *painter) : context(0) return; } - int devType = painter->device()->devType(); - if (paintEngine->type() == QPaintEngine::Raster - && (devType == QInternal::Widget || - devType == QInternal::Pixmap || - devType == QInternal::Image)) { - - const QImage *image = static_cast(paintEngine->paintDevice()); - QCFType colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8, - image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image)); - - // Invert y axis - CGContextTranslateCTM(context, 0, image->height()); - CGContextScaleCTM(context, 1, -1); - - const qreal devicePixelRatio = image->devicePixelRatio(); - - if (devType == QInternal::Widget) { - // Set the clip rect which is an intersection of the system clip - // and the painter clip. To make matters more interesting these - // are in device pixels and device-independent pixels, respectively. - QRegion clip = painter->paintEngine()->systemClip(); // get system clip in device pixels - QTransform native = painter->deviceTransform(); // get device transform. dx/dy is in device pixels - - if (painter->hasClipping()) { - QRegion r = painter->clipRegion(); // get painter clip, which is in device-independent pixels - qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels - r.translate(native.dx(), native.dy()); - if (clip.isEmpty()) - clip = r; - else - clip &= r; - } - qt_mac_clip_cg(context, clip, 0); // clip in device pixels - - // Scale the context so that painting happens in device-independent pixels - CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); - CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio); - } else { - // Scale to paint in device-independent pixels - CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); - } - } else { - qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType; + if (paintEngine->type() != QPaintEngine::Raster) { + qWarning() << "QMacCGContext:: Unsupported paint engine type" << paintEngine->type(); + return; } + + // The raster paint engine always operates on a QImage + Q_ASSERT(paintEngine->paintDevice()->devType() == QInternal::Image); + + // On behalf of one of these supported painter devices + switch (int painterDeviceType = painter->device()->devType()) { + case QInternal::Pixmap: + case QInternal::Image: + case QInternal::Widget: + break; + default: + qWarning() << "QMacCGContext:: Unsupported paint device type" << painterDeviceType; + return; + } + + // Applying the clip is so entangled with the rest of the context setup + // that for simplicity we just pass in the painter. + initialize(static_cast(paintEngine->paintDevice()), painter); +} + +void QMacCGContext::initialize(const QImage *image, QPainter *painter) +{ + QCFType colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8, + image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image)); + + // Invert y axis + CGContextTranslateCTM(context, 0, image->height()); + CGContextScaleCTM(context, 1, -1); + + const qreal devicePixelRatio = image->devicePixelRatio(); + + if (painter && painter->device()->devType() == QInternal::Widget) { + // Set the clip rect which is an intersection of the system clip and the painter clip + QRegion clip = painter->paintEngine()->systemClip(); + QTransform deviceTransform = painter->deviceTransform(); + + if (painter->hasClipping()) { + // To make matters more interesting the painter clip is in device-independent pixels, + // so we need to scale it to match the device-pixels of the system clip. + QRegion painterClip = painter->clipRegion(); + qt_mac_scale_region(&painterClip, devicePixelRatio); + + painterClip.translate(deviceTransform.dx(), deviceTransform.dy()); + + if (clip.isEmpty()) + clip = painterClip; + else + clip &= painterClip; + } + + qt_mac_clip_cg(context, clip, 0); + + CGContextTranslateCTM(context, deviceTransform.dx(), deviceTransform.dy()); + } + + // Scale the context so that painting happens in device-independent pixels + CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); } QT_END_NAMESPACE diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h index 868c2b08b5..ba2cde8325 100644 --- a/src/gui/painting/qcoregraphics_p.h +++ b/src/gui/painting/qcoregraphics_p.h @@ -51,6 +51,8 @@ // We mean it. // +#include + #include #include #include @@ -89,38 +91,16 @@ Q_GUI_EXPORT QBrush qt_mac_toQBrush(CGColorRef color); class Q_GUI_EXPORT QMacCGContext { public: - inline QMacCGContext() { context = 0; } + QMacCGContext() = default; QMacCGContext(QPaintDevice *pdev); QMacCGContext(QPainter *p); - inline QMacCGContext(CGContextRef cg, bool takeOwnership = false) { - context = cg; - if (!takeOwnership) - CGContextRetain(context); - } - inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } - inline ~QMacCGContext() { - if (context) - CGContextRelease(context); - } - inline bool isNull() const { return context; } - inline operator CGContextRef() { return context; } - inline QMacCGContext &operator=(const QMacCGContext ©) { - if (context) - CGContextRelease(context); - context = copy.context; - CGContextRetain(context); - return *this; - } - inline QMacCGContext &operator=(CGContextRef cg) { - if (context) - CGContextRelease(context); - context = cg; - CGContextRetain(context); //we do not take ownership - return *this; - } + + operator CGContextRef() { return context; } private: - CGContextRef context; + void initialize(QPaintDevice *paintDevice); + void initialize(const QImage *, QPainter *painter = nullptr); + QCFType context; }; QT_END_NAMESPACE From 2b2133f85362325dbb7c0a8e73b8a4697128b5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 21 Mar 2019 15:26:45 +0100 Subject: [PATCH 14/19] macOS: Gracefully handle devicePixelRatio mismatch in QCALayerBackingStore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the client of the backingstore fails to pick up dpr changes, and tries to flush the backingstore without a repaint, we will end up flushing a back-buffer with a stale dpr. Detect when this happens, warn the user, and smooth out the situation by adjusting the layer accordingly. Change-Id: If4596a8976a3902252c81d8e28c7aeb9fdd908bf Reviewed-by: Laszlo Agocs Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qcocoabackingstore.h | 1 + .../platforms/cocoa/qcocoabackingstore.mm | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 508f24d578..6f24598250 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -93,6 +93,7 @@ private: QRegion dirtyRegion; // In unscaled coordinates QImage *asImage(); + qreal devicePixelRatio() const { return m_devicePixelRatio; } private: qreal m_devicePixelRatio; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 8e4e928bc5..d42a723b47 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -460,12 +460,29 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, NSView *backingStoreView = static_cast(window()->handle())->view(); NSView *flushedView = static_cast(flushedWindow->handle())->view(); + // If the backingstore is just flushed, without being painted to first, then we may + // end in a situation where the backingstore is flushed to a layer with a different + // scale factor than the one it was created for in beginPaint. This is the client's + // fault in not picking up the change in scale factor of the window and re-painting + // the backingstore accordingly. To smoothing things out, we warn about this situation, + // and change the layer's contentsScale to match the scale of the back buffer, so that + // we at least cover the whole layer. This is necessary since we set the view's + // contents placement policy to NSViewLayerContentsPlacementTopLeft, which means + // AppKit will not do any scaling on our behalf. + if (m_buffers.back()->devicePixelRatio() != flushedView.layer.contentsScale) { + qCWarning(lcQpaBackingStore) << "Back buffer dpr of" << m_buffers.back()->devicePixelRatio() + << "doesn't match" << flushedView.layer << "contents scale of" << flushedView.layer.contentsScale + << "- updating layer to match."; + flushedView.layer.contentsScale = m_buffers.back()->devicePixelRatio(); + } + id backBufferSurface = (__bridge id)m_buffers.back()->surface(); if (flushedView.layer.contents == backBufferSurface) { // We've managed to paint to the back buffer again before Core Animation had time - // to flush the transaction and persist the layer changes to the window server. - // The layer already knows about the back buffer, and we don't need to re-apply - // it to pick up the surface changes, so bail out early. + // to flush the transaction and persist the layer changes to the window server, or + // we've been asked to flush without painting anything. The layer already knows about + // the back buffer, and we don't need to re-apply it to pick up any possible surface + // changes, so bail out early. qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView << ", layer already reflects back buffer"; return; From 6a21dc9d734fbde681dc4bf01d41561766a4359c Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 23 Apr 2019 10:10:08 +0200 Subject: [PATCH 15/19] Fix typo in QHostAddress::SpecialAddress description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia4269b74eb85d5055ca0e893277be92df012c000 Fixes: QTBUG-75332 Reviewed-by: Akihito Izawa Reviewed-by: Mårten Nordheim --- src/network/kernel/qhostaddress.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index fba91c62c8..5d0ef150f3 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -385,8 +385,8 @@ QHostAddress QNetmask::address(QAbstractSocket::NetworkLayerProtocol protocol) c \value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1"). \value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1"). \value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255"). - \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces. - \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interaces. + \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces. + \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces. \value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces. */ From c2917243a96d19c9cd49c827e63d40b7c0110d7d Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 15 Apr 2019 12:41:52 +0200 Subject: [PATCH 16/19] syncqt: Fix resolution of injected headers for external modules Injected headers were made relative to MODULE_BASE_OUTDIR by syncqt and made absolute by resolving against REAL_MODULE_BASE_OUTDIR. This breaks for modules that reside outside the original Qt source tree (if the directory depth doesn't coincidentally match). Now, we resolve injected headers against build_basedir, which is REAL_MODULE_BASE_OUTDIR. To emphasize the equivalence of REAL_MODULE_BASE_OUTDIR and syncqt's build_basedir, use the former for syncqt's -output argument. This commit amends 2aa779e8. Fixes: QTBUG-70587 Change-Id: I2935d87d7ee681fa4aa795a270b94ab7a43abe59 Reviewed-by: Dominik Holland Reviewed-by: Oliver Wolff --- bin/syncqt.pl | 2 +- mkspecs/features/qt_module_headers.prf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 972717efcf..7793811c9f 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -1111,7 +1111,7 @@ foreach my $lib (@modules_to_sync) { elsif (!$shadow) { $pri_install_pfiles.= "$pri_install_iheader ";; } - $pri_injections .= fixPaths($iheader, $out_basedir) + $pri_injections .= fixPaths($iheader, $build_basedir) .":".($no_stamp ? "^" : "").fixPaths($oheader, "$out_basedir/include/$lib") .$injection." " if ($shadow); } diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 6b4b9143fa..37b69e31c8 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -23,7 +23,7 @@ load(qt_build_paths) QMAKE_SYNCQT += -module $$mod QMAKE_SYNCQT += \ -version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) \ - -builddir $$system_quote($$shadowed($$MODULE_BASE_INDIR)) $$MODULE_SYNCQT_DIR + -builddir $$system_quote($$REAL_MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR !silent: message($$QMAKE_SYNCQT) system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT") From f36a306563b4e77e4c64884382da22f3412708a0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 17 Apr 2019 14:16:36 +0200 Subject: [PATCH 17/19] configure: Support the = prefix for -I and -L For gcc's -I and -L arguments a = prefix is replaced by the sysroot. Since we're resolving include paths and library paths, we have to support this feature. For example, the linux-rasp-pi3-g++ makes use of this and is broken without this patch. Change-Id: Ie39e63322bd35e2a93aa8e55d52260164b8c6a6b Reviewed-by: Kai Koehne --- mkspecs/features/qt_configure.prf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 62ad972796..aa4348235e 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -515,6 +515,17 @@ defineTest(qtConfSetupLibraries) { } } +defineReplace(qtGccSysrootifiedPath) { + return($$replace(1, ^=, $$[QT_SYSROOT])) +} + +defineReplace(qtGccSysrootifiedPaths) { + sysrootified = + for (path, 1): \ + sysrootified += $$qtGccSysrootifiedPath($$path) + return($$sysrootified) +} + # libs-var, libs, in-paths, out-paths-var defineTest(qtConfResolveLibs) { ret = true @@ -531,6 +542,7 @@ defineTest(qtConfResolveLibs) { out += $$l } else: contains(l, "^-L.*") { lp = $$replace(l, "^-L", ) + gcc: lp = $$qtGccSysrootifiedPath($$lp) !exists($$lp/.) { qtLog("Library path $$val_escape(lp) is invalid.") ret = false @@ -604,6 +616,7 @@ defineTest(qtConfResolveAllLibs) { # libs-var, in-paths, libs defineTest(qtConfResolvePathLibs) { ret = true + gcc: 2 = $$qtGccSysrootifiedPaths($$2) for (libdir, 2) { !exists($$libdir/.) { qtLog("Library path $$val_escape(libdir) is invalid.") @@ -654,6 +667,7 @@ defineReplace(qtConfGetTestIncludes) { # includes-var, in-paths, test-object-var defineTest(qtConfResolvePathIncs) { ret = true + gcc: 2 = $$qtGccSysrootifiedPaths($$2) for (incdir, 2) { !exists($$incdir/.) { qtLog("Include path $$val_escape(incdir) is invalid.") From de854aa37f49de6d8f6ee12c0e9d247c5143c2da Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 23 Apr 2019 09:54:46 +0200 Subject: [PATCH 18/19] Teach qmake MSVC's compiler options /std:c++[14|17|latest] This fixes the "could not parse compiler option" warning when generating VS project files. Fixes: QTBUG-75275 Change-Id: Idd98ae5fdb8ebf5a4e311cbb6cd3ed1daba74ca4 Reviewed-by: Kai Koehne --- qmake/generators/win32/msbuild_objectmodel.cpp | 2 ++ qmake/generators/win32/msvc_objectmodel.cpp | 8 ++++++++ qmake/generators/win32/msvc_objectmodel.h | 1 + 3 files changed, 11 insertions(+) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index ad2976aa01..87cd560552 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -143,6 +143,7 @@ const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName"; const char _IntermediateDirectory[] = "IntermediateDirectory"; const char _KeyContainer[] = "KeyContainer"; const char _KeyFile[] = "KeyFile"; +const char _LanguageStandard[] = "LanguageStandard"; const char _LargeAddressAware[] = "LargeAddressAware"; const char _LinkDLL[] = "LinkDLL"; const char _LinkErrorReporting[] = "LinkErrorReporting"; @@ -1492,6 +1493,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) << attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions) << attrTagT(_MinimalRebuild, tool.MinimalRebuild) << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation) + << attrTagS(_LanguageStandard, tool.LanguageStandard) << attrTagS(_ObjectFileName, tool.ObjectFile) << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName) << attrTagT(_OmitFramePointers, tool.OmitFramePointers) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 7335211f30..f08554d0f5 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -1146,6 +1146,14 @@ bool VCCLCompilerTool::parseOption(const char* option) ShowIncludes = _True; break; } + if (strlen(option) > 8 && second == 't' && third == 'd') { + const QString version = option + 8; + static const QStringList knownVersions = { "14", "17", "latest" }; + if (knownVersions.contains(version)) { + LanguageStandard = "stdcpp" + version; + break; + } + } found = false; break; case 'u': if (!second) diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 41a6ffafa7..f6d1fc8023 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -526,6 +526,7 @@ public: triState ImproveFloatingPointConsistency; inlineExpansionOption InlineFunctionExpansion; triState KeepComments; + QString LanguageStandard; triState MinimalRebuild; QString ObjectFile; triState OmitDefaultLibName; From 2947435d8737f9b97a80532864ec2302f6719355 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Mon, 4 Feb 2019 18:42:35 +0300 Subject: [PATCH 19/19] QSystemTrayIcon/X11: Create tray icon window when system tray appears ... and destroy it otherwise. Fixes: QTBUG-61898 Fixes: QTBUG-73459 Done-with: Gatis Paeglis Change-Id: I6bd8f397f7ccdb123f6a60d4fa466f7b0d760dfc Reviewed-by: Gatis Paeglis --- src/widgets/util/qsystemtrayicon_p.h | 4 ++ src/widgets/util/qsystemtrayicon_x11.cpp | 75 +++++++++++++++++------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h index 5bdf020a47..e31532ea19 100644 --- a/src/widgets/util/qsystemtrayicon_p.h +++ b/src/widgets/util/qsystemtrayicon_p.h @@ -69,6 +69,7 @@ QT_BEGIN_NAMESPACE class QSystemTrayIconSys; +class QSystemTrayWatcher; class QPlatformSystemTrayIcon; class QToolButton; class QLabel; @@ -90,6 +91,8 @@ public: void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs); + void destroyIcon(); + static bool isSystemTrayAvailable_sys(); static bool supportsMessages_sys(); @@ -101,6 +104,7 @@ public: QSystemTrayIconSys *sys; QPlatformSystemTrayIcon *qpa_sys; bool visible; + QSystemTrayWatcher *trayWatcher; private: void install_sys_qpa(); diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index 86532456c7..70e5f3678e 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -92,9 +92,6 @@ protected: virtual void resizeEvent(QResizeEvent *) override; virtual void moveEvent(QMoveEvent *) override; -private slots: - void systemTrayWindowChanged(QScreen *screen); - private: QSystemTrayIcon *q; }; @@ -116,15 +113,6 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn) setMouseTracking(true); } -void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *) -{ - if (!locateSystemTray()) { - QBalloonTip::hideBalloon(); - hide(); // still no luck - destroy(); - } -} - QRect QSystemTrayIconSys::globalGeometry() const { return QRect(mapToGlobal(QPoint(0, 0)), size()); @@ -199,10 +187,41 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *event) } //////////////////////////////////////////////////////////////////////////// +class QSystemTrayWatcher: public QObject +{ + Q_OBJECT +public: + QSystemTrayWatcher(QSystemTrayIcon *trayIcon) + : QObject(trayIcon) + , mTrayIcon(trayIcon) + { + // This code uses string-based syntax because we want to connect to a signal + // which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged(). + connect(qGuiApp->platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)), + this, SLOT(systemTrayWindowChanged(QScreen*))); + } + +private slots: + void systemTrayWindowChanged(QScreen *) + { + auto icon = static_cast(QObjectPrivate::get(mTrayIcon)); + icon->destroyIcon(); + if (icon->visible && locateSystemTray()) { + icon->sys = new QSystemTrayIconSys(mTrayIcon); + icon->sys->show(); + } + } + +private: + QSystemTrayIcon *mTrayIcon = nullptr; +}; +//////////////////////////////////////////////////////////////////////////// + QSystemTrayIconPrivate::QSystemTrayIconPrivate() : sys(0), qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()), - visible(false) + visible(false), + trayWatcher(nullptr) { } @@ -213,16 +232,21 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate() void QSystemTrayIconPrivate::install_sys() { + Q_Q(QSystemTrayIcon); + if (qpa_sys) { install_sys_qpa(); return; } - Q_Q(QSystemTrayIcon); - if (!sys && locateSystemTray()) { - sys = new QSystemTrayIconSys(q); - QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)), - sys, SLOT(systemTrayWindowChanged(QScreen*))); - sys->show(); + + if (!sys) { + if (!trayWatcher) + trayWatcher = new QSystemTrayWatcher(q); + + if (locateSystemTray()) { + sys = new QSystemTrayIconSys(q); + sys->show(); + } } } @@ -241,14 +265,21 @@ void QSystemTrayIconPrivate::remove_sys() remove_sys_qpa(); return; } + + destroyIcon(); +} + +void QSystemTrayIconPrivate::destroyIcon() +{ if (!sys) return; QBalloonTip::hideBalloon(); - sys->hide(); // this should do the trick, but... - delete sys; // wm may resize system tray only for DestroyEvents - sys = 0; + sys->hide(); + delete sys; + sys = nullptr; } + void QSystemTrayIconPrivate::updateIcon_sys() { if (qpa_sys) {