diff options
| author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2025-12-15 16:14:16 +0200 |
|---|---|---|
| committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2025-12-15 16:14:16 +0200 |
| commit | 2d66011e197f96cf17b170fe10b6a78354d3117c (patch) | |
| tree | e4737ff487171dc946ef33d9c355de128ab8d6d5 /src/plugins | |
| parent | 8216f5c5249db2c368434129fb6f4e35cb75edfc (diff) | |
| parent | f9e9e1f1a566511d663b32e422f7b054713e5112 (diff) | |
Merge tag 'v6.5.8-lts-lgpl' into 6.56.5
Qt 6.5.8-lts-lgpl release
Diffstat (limited to 'src/plugins')
25 files changed, 215 insertions, 159 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index faccf8b1173..337dd266fe8 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -22,17 +22,43 @@ QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceForma void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface) { - if (surface->surface()->surfaceClass() == QSurface::Window && - static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig())) { - QEGLPlatformContext::makeCurrent(surface); + if (surface->surface()->surfaceClass() != QSurface::Window) { + QEGLPlatformContext::swapBuffers(surface); + return; } + QAndroidPlatformOpenGLWindow *window = static_cast<QAndroidPlatformOpenGLWindow *>(surface); + // Since QEGLPlatformContext::makeCurrent() and QEGLPlatformContext::swapBuffers() + // will be using the eglSurface of the window, which wraps the Android Surface, we + // need to lock here to make sure we don't end up using a Surface already destroyed + // by Android + window->lockSurface(); + + if (window->checkNativeSurface(eglConfig())) { + // Call base class implementation directly since we are already locked + QEGLPlatformContext::makeCurrent(surface); + } QEGLPlatformContext::swapBuffers(surface); + + window->unlockSurface(); } bool QAndroidPlatformOpenGLContext::makeCurrent(QPlatformSurface *surface) { - return QEGLPlatformContext::makeCurrent(surface); + if (surface->surface()->surfaceClass() != QSurface::Window) + return QEGLPlatformContext::makeCurrent(surface); + + QAndroidPlatformOpenGLWindow *window = static_cast<QAndroidPlatformOpenGLWindow *>(surface); + window->lockSurface(); + // Has the Surface been destroyed? + if (window->eglSurface(eglConfig()) == EGL_NO_SURFACE) { + qWarning("makeCurrent(): no EGLSurface, likely Surface destroyed by Android."); + window->unlockSurface(); + return false; + } + const bool ok = QEGLPlatformContext::makeCurrent(surface); + window->unlockSurface(); + return ok; } EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 8ab95cf8be4..31ca205ace2 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -32,7 +32,7 @@ QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow() lockSurface(); if (m_nativeSurfaceId != -1) QtAndroid::destroySurface(m_nativeSurfaceId); - clearEgl(); + clearSurface(); unlockSurface(); } @@ -81,13 +81,13 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect) repaint(QRegion(rect)); } +// Called by QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(), +// surface is already locked when calling this EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) { if (QAndroidEventDispatcherStopper::stopped() || QGuiApplication::applicationState() == Qt::ApplicationSuspended) return m_eglSurface; - QMutexLocker lock(&m_surfaceMutex); - if (m_nativeSurfaceId == -1) { AndroidDeadlockProtector protector; if (!protector.acquire()) @@ -98,17 +98,16 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) m_surfaceWaitCondition.wait(&m_surfaceMutex); } - if (m_eglSurface == EGL_NO_SURFACE) { - m_surfaceMutex.unlock(); + if (m_eglSurface == EGL_NO_SURFACE) checkNativeSurface(config); - m_surfaceMutex.lock(); - } + return m_eglSurface; } bool QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config) { - QMutexLocker lock(&m_surfaceMutex); + // Either no surface created, or the m_eglSurface already wraps the active Surface + // -> makeCurrent is NOT needed. if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid()) return false; // makeCurrent is NOT needed. @@ -130,14 +129,14 @@ void QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState QtAndroid::destroySurface(m_nativeSurfaceId); m_nativeSurfaceId = -1; } - clearEgl(); + clearSurface(); unlockSurface(); } } void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) { - clearEgl(); + clearSurface(); QJniEnvironment env; m_nativeWindow = ANativeWindow_fromSurface(env.jniEnv(), m_androidSurfaceObject.object()); m_androidSurfaceObject = QJniObject(); @@ -158,7 +157,7 @@ QSurfaceFormat QAndroidPlatformOpenGLWindow::format() const return m_format; } -void QAndroidPlatformOpenGLWindow::clearEgl() +void QAndroidPlatformOpenGLWindow::clearSurface() { if (m_eglSurface != EGL_NO_SURFACE) { eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -168,7 +167,7 @@ void QAndroidPlatformOpenGLWindow::clearEgl() if (m_nativeWindow) { ANativeWindow_release(m_nativeWindow); - m_nativeWindow = 0; + m_nativeWindow = nullptr; } } @@ -180,11 +179,13 @@ void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surfac lockSurface(); m_androidSurfaceObject = surface; - if (surface) // wait until we have a valid surface to draw into + if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into m_surfaceWaitCondition.wakeOne(); + else + clearSurface(); unlockSurface(); - if (surface) { + if (m_androidSurfaceObject.isValid()) { // repaint the window, when we have a valid surface QRect availableGeometry = screen()->availableGeometry(); if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.h b/src/plugins/platforms/android/qandroidplatformopenglwindow.h index 8c31368b654..9a4247824e1 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.h +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.h @@ -35,7 +35,7 @@ public: protected: void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override; void createEgl(EGLConfig config); - void clearEgl(); + void clearSurface() override; private: EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.h b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h index 14d5b7fc0ef..4b750b7070b 100644 --- a/src/plugins/platforms/android/qandroidplatformvulkanwindow.h +++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h @@ -34,10 +34,10 @@ public: protected: void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override; + void clearSurface() override; private: void sendExpose(); - void clearSurface(); int m_nativeSurfaceId; ANativeWindow *m_nativeWindow; diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h index 6fccc2e7fea..2d92bfa0b04 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/qandroidplatformwindow.h @@ -57,6 +57,7 @@ public: protected: void setGeometry(const QRect &rect) override; + virtual void clearSurface() {} protected: Qt::WindowFlags m_windowFlags; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 7c2a942ca94..ad0dd3fd691 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -88,6 +88,13 @@ void QCALayerBackingStore::beginPaint(const QRegion ®ion) qCInfo(lcQpaBackingStore) << "Beginning paint of" << region << "into backingstore of" << m_requestedSize; + if (m_requestedSize.isEmpty()) { + // We can't create IOSurfaces with and empty size, so instead reset our back buffer + qCDebug(lcQpaBackingStore) << "Size is empty, throwing away back buffer"; + m_buffers.back().reset(nullptr); + return; + } + ensureBackBuffer(); // Find an unused back buffer, or reserve space for a new one const bool bufferWasRecreated = recreateBackBufferIfNeeded(); @@ -202,12 +209,19 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded() QPaintDevice *QCALayerBackingStore::paintDevice() { - Q_ASSERT(m_buffers.back()); - return m_buffers.back()->asImage(); + if (m_buffers.back()) { + return m_buffers.back()->asImage(); + } else { + static QImage fallbackDevice; + return &fallbackDevice; + } } void QCALayerBackingStore::endPaint() { + if (!m_buffers.back()) + return; + qCInfo(lcQpaBackingStore) << "Paint ended. Back buffer valid region is now" << m_buffers.back()->validRegion(); m_buffers.back()->unlock(); @@ -278,7 +292,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, Q_UNUSED(offset); if (!m_buffers.back()) { - qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first"; + qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring."; return; } @@ -405,7 +419,7 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo bool translucentBackground) { if (!m_buffers.back()) { - qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first"; + qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring."; return FlushFailed; } diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h index dedf8a7fd9c..30456a91bba 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.h +++ b/src/plugins/platforms/cocoa/qcocoadrag.h @@ -35,7 +35,8 @@ public: * to meet NSView dragImage:at guarantees, we need to record the original * event and view when handling an event in QNSView */ - void setLastMouseEvent(NSEvent *event, NSView *view); + void setLastInputEvent(NSEvent *event, NSView *view); + void viewDestroyed(NSView *view); void setAcceptedAction(Qt::DropAction act); void exitDragLoop(); diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index a8c0392f8ba..269ead2632e 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -31,13 +31,24 @@ QCocoaDrag::~QCocoaDrag() [m_lastEvent release]; } -void QCocoaDrag::setLastMouseEvent(NSEvent *event, NSView *view) +void QCocoaDrag::setLastInputEvent(NSEvent *event, NSView *view) { [m_lastEvent release]; m_lastEvent = [event copy]; m_lastView = view; } +void QCocoaDrag::viewDestroyed(NSView *view) +{ + if (view == m_lastView) { + if (m_lastEvent.window.contentView == view) { + [m_lastEvent release]; + m_lastEvent = nil; + } + m_lastView = nil; + } +} + QMimeData *QCocoaDrag::dragMimeData() { if (m_drag) @@ -95,9 +106,11 @@ Qt::DropAction QCocoaDrag::defaultAction(Qt::DropActions possibleActions, Qt::DropAction QCocoaDrag::drag(QDrag *o) { - m_drag = o; m_executed_drop_action = Qt::IgnoreAction; + if (!m_lastEvent) + return m_executed_drop_action; + m_drag = o; QMacPasteboard dragBoard(CFStringRef(NSPasteboardNameDrag), QUtiMimeConverter::HandlerScopeFlag::DnD); m_drag->mimeData()->setData("application/x-qt-mime-type-name"_L1, QByteArray("dummy")); dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest); diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 919f7c240bc..36546879ae4 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -29,6 +29,7 @@ public: void initialize() override; bool makeCurrent(QPlatformSurface *surface) override; + void beginFrame() override; void swapBuffers(QPlatformSurface *surface) override; void doneCurrent() override; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index a65311175ff..bfac716b633 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -332,6 +332,25 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) return true; } +void QCocoaGLContext::beginFrame() +{ + QMacAutoReleasePool pool; + + Q_ASSERT(context() && context()->surface()); + auto *surface = context()->surface()->surfaceHandle(); + Q_ASSERT(surface); + + qCDebug(lcQpaOpenGLContext) << "Beginning frame for" << this + << "in" << QThread::currentThread() << "for" << surface; + + Q_ASSERT(surface->surface()->supportsOpenGL()); + + if (surface->surface()->surfaceClass() == QSurface::Window) { + if (m_needsUpdate.fetchAndStoreRelaxed(false)) + update(); + } +} + /*! Sets the drawable object of the NSOpenGLContext, which is the frame buffer that is the target of OpenGL drawing operations. diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 42e3270afd1..91d614fa4e7 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -151,6 +151,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMouseMoveHelper); [[NSNotificationCenter defaultCenter] removeObserver:self]; [m_mouseMoveHelper release]; + // FIXME: Replace with __weak or someting equivalent + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + nativeDrag->viewDestroyed(self); + [super dealloc]; } diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 63b180111b4..34be561a230 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -117,7 +117,7 @@ static const QPointingDevice *pointingDeviceFor(qint64 deviceID) ulong timestamp = [theEvent timestamp] * 1000; QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - nativeDrag->setLastMouseEvent(theEvent, self); + nativeDrag->setLastInputEvent(theEvent, self); const auto modifiers = QAppleKeyMapper::fromCocoaModifiers(theEvent.modifierFlags); auto button = cocoaButton2QtButton(theEvent); diff --git a/src/plugins/platforms/cocoa/qnsview_tablet.mm b/src/plugins/platforms/cocoa/qnsview_tablet.mm index 4c6e351b3f4..09553aee5f6 100644 --- a/src/plugins/platforms/cocoa/qnsview_tablet.mm +++ b/src/plugins/platforms/cocoa/qnsview_tablet.mm @@ -28,6 +28,9 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceMap, devicesInProximity) ulong timestamp = [theEvent timestamp] * 1000; + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + nativeDrag->setLastInputEvent(theEvent, self); + QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint: &windowPoint andScreenPoint: &screenPoint]; diff --git a/src/plugins/platforms/cocoa/qnsview_touch.mm b/src/plugins/platforms/cocoa/qnsview_touch.mm index 6a147701fce..997edcbf36e 100644 --- a/src/plugins/platforms/cocoa/qnsview_touch.mm +++ b/src/plugins/platforms/cocoa/qnsview_touch.mm @@ -34,6 +34,10 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") return; const NSTimeInterval timestamp = [event timestamp]; + + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + nativeDrag->setLastInputEvent(event, self); + const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QInputDevice::DeviceType::TouchPad, [event deviceID]), points); @@ -45,6 +49,10 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") return; const NSTimeInterval timestamp = [event timestamp]; + + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + nativeDrag->setLastInputEvent(event, self); + const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QInputDevice::DeviceType::TouchPad, [event deviceID]), points); @@ -56,6 +64,10 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") return; const NSTimeInterval timestamp = [event timestamp]; + + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + nativeDrag->setLastInputEvent(event, self); + const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QInputDevice::DeviceType::TouchPad, [event deviceID]), points); diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index da6485a32dd..212c69938db 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -14,6 +14,8 @@ #include <qpa/qwindowsysteminterface.h> #include <qoperatingsystemversion.h> +#include <QtGui/private/qhighdpiscaling_p.h> + Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events"); static bool isMouseEvent(NSEvent *ev) @@ -225,7 +227,8 @@ static bool isMouseEvent(NSEvent *ev) // client geometry based on the QWindow's positionPolicy is a noop. // Now that we have a NSWindow to read the frame from we re-apply // the QWindow geometry, which will move the NSWindow if needed. - m_platformWindow->setGeometry(window->geometry()); + m_platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(window->geometry(), window)); + m_platformWindow->setVisible(window->isVisible()); } diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index b011bf0439d..bd9a960ed94 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -17,6 +17,8 @@ #include <QtCore/qsettings.h> #include <qpa/qwindowsysteminterface.h> +#include <QtGui/private/qguiapplication_p.h> + #include <commctrl.h> #include <shellapi.h> #include <shlobj.h> @@ -371,6 +373,10 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result) // since hi-res coordinates are delivered in this case (Windows issue). // Default to primary screen with check to prevent a crash. const QPoint globalPos = QPoint(GET_X_LPARAM(message.wParam), GET_Y_LPARAM(message.wParam)); + // QTBUG-130832: QMenu relies on lastCursorPosition being up to date. When this code + // is called it still holds the last known mouse position inside a Qt window. Do a + // forced update of this position. + QGuiApplicationPrivate::lastCursorPosition = QCursor::pos().toPointF(); const auto &screenManager = QWindowsContext::instance()->screenManager(); const QPlatformScreen *screen = screenManager.screenAtDp(globalPos); if (!screen) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index c78e41bd3e0..e8506b011c0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2671,8 +2671,24 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState) setFlag(WithinMaximize); if (newState & Qt::WindowFullScreen) setFlag(MaximizeToFullScreen); - ShowWindow(m_data.hwnd, - (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + if (m_data.flags & Qt::FramelessWindowHint) { + if (newState == Qt::WindowNoState) { + const QRect &rect = m_savedFrameGeometry; + MoveWindow(m_data.hwnd, rect.x(), rect.y(), rect.width(), rect.height(), true); + } else { + HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitor, &monitorInfo); + const RECT &rect = monitorInfo.rcWork; + m_savedFrameGeometry = geometry(); + MoveWindow(m_data.hwnd, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, true); + } + } else { + ShowWindow(m_data.hwnd, + (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + } clearFlag(WithinMaximize); clearFlag(MaximizeToFullScreen); } else if (visible && (oldState & newState & Qt::WindowMinimized)) { @@ -2832,15 +2848,16 @@ void QWindowsWindow::calculateFullFrameMargins() const auto systemMargins = testFlag(DisableNonClientScaling) ? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd) : frameMargins_sys(); + const QMargins actualMargins = systemMargins + customMargins(); const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); - const bool typicalFrame = (systemMargins.left() == systemMargins.right()) - && (systemMargins.right() == systemMargins.bottom()); + const bool typicalFrame = (actualMargins.left() == actualMargins.right()) + && (actualMargins.right() == actualMargins.bottom()); const QMargins adjustedMargins = typicalFrame ? - QMargins(systemMargins.left(), (yDiff - systemMargins.bottom()), - systemMargins.right(), systemMargins.bottom()) - : systemMargins + customMargins(); + QMargins(actualMargins.left(), (yDiff - actualMargins.bottom()), + actualMargins.right(), actualMargins.bottom()) + : actualMargins; setFullFrameMargins(adjustedMargins); } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 55c226d3e69..4f62a1880b8 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -682,96 +682,23 @@ static inline qreal fixed1616ToReal(xcb_input_fp1616_t val) return qreal(val) / 0x10000; } -//implementation is ported from https://codereview.qt-project.org/c/qt/qtbase/+/231552/12/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp#558 -namespace { - -/*! \internal - - Qt listens for XIAllDevices to avoid losing mouse events. This function - ensures that we don't process the same event twice: from a slave device and - then again from a master device. - - In a normal use case (e.g. mouse press and release inside a window), we will - drop events from master devices as duplicates. Other advantage of processing - events from slave devices is that they don't share button state. All buttons - on a master device share the state. - - Examples of special cases: - -\list - -\li During system move/resize, window manager (_NET_WM_MOVERESIZE) grabs the - master pointer, in this case we process the matching release from the slave - device. A master device event is not sent by the server, hence no duplicate - event to drop. If we listened for XIAllMasterDevices instead, we would never - see a release event in this case. - -\li If we dismiss a context menu by clicking somewhere outside a Qt application, - we will process the mouse press from the master pointer as that is the - device we are grabbing. We are not grabbing slave devices (grabbing on the - slave device is buggy according to 19d289ab1b5bde3e136765e5432b5c7d004df3a4). - And since the event occurs outside our window, the slave device event is - not sent to us by the server, hence no duplicate event to drop. - -\endlist -*/ -bool isDuplicateEvent(xcb_ge_event_t *event) -{ - Q_ASSERT(event); - - struct qXIEvent { - bool isValid = false; - uint16_t sourceid; - uint8_t evtype; - uint32_t detail; - int32_t root_x; - int32_t root_y; - }; - static qXIEvent lastSeenEvent; - - bool isDuplicate = false; - auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event); - if (lastSeenEvent.isValid) { - isDuplicate = lastSeenEvent.sourceid == xiDeviceEvent->sourceid && - lastSeenEvent.evtype == xiDeviceEvent->event_type && - lastSeenEvent.detail == xiDeviceEvent->detail && - lastSeenEvent.root_x == xiDeviceEvent->root_x && - lastSeenEvent.root_y == xiDeviceEvent->root_y; - } else { - lastSeenEvent.isValid = true; - } - lastSeenEvent.sourceid = xiDeviceEvent->sourceid; - lastSeenEvent.evtype = xiDeviceEvent->event_type; - lastSeenEvent.detail = xiDeviceEvent->detail; - lastSeenEvent.root_x = xiDeviceEvent->root_x; - lastSeenEvent.root_y = xiDeviceEvent->root_y; - - if (isDuplicate) { - qCDebug(lcQpaXInputEvents, "Duplicate XI2 event %d", event->event_type); - // This sanity check ensures that special cases like QTBUG-59277 keep working. - lastSeenEvent.isValid = false; // An event can be a duplicate only once. - } - - return isDuplicate; -} - -} // namespace - void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) { auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event); - if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) { - if (!(xiEvent->event_type == XCB_INPUT_BUTTON_PRESS - || xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE - || xiEvent->event_type == XCB_INPUT_MOTION)) { - if (!m_duringSystemMoveResize) - return; - if (xiEvent->event == XCB_NONE) - return; - - if (xiEvent->event_type == XCB_INPUT_TOUCH_END) - abortSystemMoveResize(xiEvent->event); + setTime(xiEvent->time); + if (m_xiSlavePointerIds.contains(xiEvent->deviceid) && xiEvent->event_type != XCB_INPUT_PROPERTY) { + if (!m_duringSystemMoveResize) + return; + if (xiEvent->event == XCB_NONE) + return; + if (xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE + && xiEvent->detail == XCB_BUTTON_INDEX_1 ) { + abortSystemMoveResize(xiEvent->event); + } else if (xiEvent->event_type == XCB_INPUT_TOUCH_END) { + abortSystemMoveResize(xiEvent->event); + return; + } else { return; } } @@ -783,27 +710,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) switch (xiEvent->event_type) { case XCB_INPUT_BUTTON_PRESS: case XCB_INPUT_BUTTON_RELEASE: - case XCB_INPUT_MOTION: { - if (isDuplicateEvent(event)) - return; - if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) { - if (m_duringSystemMoveResize) { - if (xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE - && xiEvent->detail == XCB_BUTTON_INDEX_1 ) { - abortSystemMoveResize(xiEvent->event); - } else { - return; - } - } - } - xiDeviceEvent = xiEvent; - eventListener = windowEventListenerFromId(xiDeviceEvent->event); - sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master - break; - } + case XCB_INPUT_MOTION: case XCB_INPUT_TOUCH_BEGIN: case XCB_INPUT_TOUCH_UPDATE: - case XCB_INPUT_TOUCH_END: { + case XCB_INPUT_TOUCH_END: + { xiDeviceEvent = xiEvent; eventListener = windowEventListenerFromId(xiDeviceEvent->event); sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 06f4b66edb2..9d1aa795e0a 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -657,12 +657,16 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp if (m_crtcs.size() == 1) { auto crtc = Q_XCB_REPLY(xcb_randr_get_crtc_info, xcb_connection(), m_crtcs[0], timestamp); - m_singlescreen = (monitorGeometry == (QRect(crtc->x, crtc->y, crtc->width, crtc->height))); - if (m_singlescreen) { - if (crtc->mode) { - updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); - if (mode() != crtc->mode) - updateRefreshRate(crtc->mode); + if (crtc == XCB_NONE) { + qCDebug(lcQpaScreen, "Didn't get crtc info when m_crtcs.size() == 1"); + } else { + m_singlescreen = (monitorGeometry == (QRect(crtc->x, crtc->y, crtc->width, crtc->height))); + if (m_singlescreen) { + if (crtc->mode) { + updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); + if (mode() != crtc->mode) + updateRefreshRate(crtc->mode); + } } } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 10181b58a4f..35f547cca99 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1960,8 +1960,10 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, return; } - if (connection()->buttonState() == Qt::NoButton) + if (connection()->buttonState() == Qt::NoButton) { connection()->setMousePressWindow(nullptr); + m_ignorePressedWindowOnMouseLeave = false; + } handleMouseEvent(timestamp, local, global, modifiers, type, source); } @@ -1981,11 +1983,6 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) return true; } -static bool windowContainsGlobalPoint(QXcbWindow *window, int x, int y) -{ - return window ? window->geometry().contains(window->mapFromGlobal(QPoint(x, y))) : false; -} - static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn) { return ((doCheckUnGrabAncestor(conn) @@ -2009,12 +2006,17 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in { connection()->setTime(timestamp); - if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow()) + if (ignoreEnterEvent(mode, detail, connection()) + || (connection()->mousePressWindow() && !m_ignorePressedWindowOnMouseLeave)) { return; + } // Updates scroll valuators, as user might have done some scrolling outside our X client. connection()->xi2UpdateScrollingDevices(); + if (mode == XCB_NOTIFY_MODE_UNGRAB && connection()->queryMouseButtons() != Qt::NoButton) + m_ignorePressedWindowOnMouseLeave = true; + const QPoint global = QPoint(root_x, root_y); const QPoint local(event_x, event_y); QWindowSystemInterface::handleEnterEvent(window(), local, global); @@ -2027,7 +2029,7 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, QXcbWindow *mousePressWindow = connection()->mousePressWindow(); if (ignoreLeaveEvent(mode, detail, connection()) - || (mousePressWindow && windowContainsGlobalPoint(mousePressWindow, root_x, root_y))) { + || (mousePressWindow && !m_ignorePressedWindowOnMouseLeave)) { return; } @@ -2047,7 +2049,7 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); } else { QWindowSystemInterface::handleLeaveEvent(window()); - if (!windowContainsGlobalPoint(this, root_x, root_y)) + if (m_ignorePressedWindowOnMouseLeave) connection()->setMousePressWindow(nullptr); } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 5d5d152e418..908e72722bd 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -230,6 +230,7 @@ protected: bool m_alertState = false; bool m_minimized = false; bool m_trayIconWindow = false; + bool m_ignorePressedWindowOnMouseLeave = false; xcb_window_t m_netWmUserTimeWindow = XCB_NONE; QSurfaceFormat m_format; diff --git a/src/plugins/printsupport/cups/CMakeLists.txt b/src/plugins/printsupport/cups/CMakeLists.txt index b6400d2d36b..6811fca10a2 100644 --- a/src/plugins/printsupport/cups/CMakeLists.txt +++ b/src/plugins/printsupport/cups/CMakeLists.txt @@ -1,7 +1,12 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -qt_find_package(Cups PROVIDED_TARGETS Cups::Cups) +if(NOT APPLE AND BUILD_SHARED_LIBS) + set(mark_cups_optional MARK_OPTIONAL) +else() + set(mark_cups_optional "") +endif() +qt_find_package(Cups PROVIDED_TARGETS Cups::Cups ${mark_cups_optional}) ##################################################################### ## QCupsPrinterSupportPlugin Plugin: diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index b69d36ab8c6..0eed9f73330 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -64,6 +64,12 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v break; case PPK_CupsOptions: d->cupsOptions = value.toStringList(); + if (d->cupsOptions.size() % 2 == 1) { + qWarning("%s: malformed value for key = PPK_CupsOptions " + "(odd number of elements in the string-list; " + "appending an empty entry)", Q_FUNC_INFO); + d->cupsOptions.emplace_back(); + } break; case PPK_QPageSize: d->setPageSize(qvariant_cast<QPageSize>(value)); @@ -199,6 +205,7 @@ void QCupsPrintEnginePrivate::closePrintDevice() options.append(QPair<QByteArray, QByteArray>("landscape", "")); QStringList::const_iterator it = cupsOptions.constBegin(); + Q_ASSERT(cupsOptions.size() % 2 == 0); while (it != cupsOptions.constEnd()) { options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit())); it += 2; diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf index 0ea483ac417..7e5b5ee9b56 100644 --- a/src/plugins/sqldrivers/.cmake.conf +++ b/src/plugins/sqldrivers/.cmake.conf @@ -1 +1 @@ -set(QT_REPO_MODULE_VERSION "6.5.7") +set(QT_REPO_MODULE_VERSION "6.5.8") diff --git a/src/plugins/tracing/qctflib.cpp b/src/plugins/tracing/qctflib.cpp index ced20754fab..f185dcf47ed 100644 --- a/src/plugins/tracing/qctflib.cpp +++ b/src/plugins/tracing/qctflib.cpp @@ -186,7 +186,12 @@ void QCtfLibImpl::writeCtfPacket(QCtfLibImpl::Channel &ch) /* Each packet contains header and context, which are defined in the metadata.txt */ QByteArray packet; packet << s_CtfHeaderMagic; - packet.append(QByteArrayView(s_TraceUuid.toBytes())); + /* Uuid is array of bytes hence implicitely big endian. */ + packet << qToBigEndian(s_TraceUuid.data1); + packet << qToBigEndian(s_TraceUuid.data2); + packet << qToBigEndian(s_TraceUuid.data3); + for (int i = 0; i < 8; i++) + packet << s_TraceUuid.data4[i]; packet << quint32(0); packet << ch.minTimestamp; |
