diff options
Diffstat (limited to 'src/plugins/platforms')
44 files changed, 267 insertions, 143 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index b57deacb57..3d9dfd8359 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -47,6 +47,8 @@ #include <QScopedPointer> #include "qiosurfacegraphicsbuffer.h" +#include <unordered_map> + QT_BEGIN_NAMESPACE class QCocoaBackingStore : public QRasterBackingStore @@ -71,8 +73,9 @@ private: void redrawRoundedBottomCorners(CGRect) const; }; -class QCALayerBackingStore : public QCocoaBackingStore +class QCALayerBackingStore : public QObject, public QCocoaBackingStore { + Q_OBJECT public: QCALayerBackingStore(QWindow *window); ~QCALayerBackingStore(); @@ -119,6 +122,11 @@ private: QMacNotificationObserver m_backingPropertiesObserver; std::list<std::unique_ptr<GraphicsBuffer>> m_buffers; + + void flushSubWindow(QWindow *window); + std::unordered_map<QWindow*, std::unique_ptr<QCALayerBackingStore>> m_subWindowBackingstores; + void windowDestroyed(QObject *object); + bool m_clearSurfaceOnPaint = true; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 2947c8c885..102f00a25d 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -381,7 +381,7 @@ void QCALayerBackingStore::beginPaint(const QRegion ®ion) // Although undocumented, QBackingStore::beginPaint expects the painted region // to be cleared before use if the window has a surface format with an alpha. // Fresh IOSurfaces are already cleared, so we don't need to clear those. - if (!bufferWasRecreated && window()->format().hasAlpha()) { + if (m_clearSurfaceOnPaint && !bufferWasRecreated && window()->format().hasAlpha()) { qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use"; QPainter painter(m_buffers.back()->asImage()); painter.setCompositionMode(QPainter::CompositionMode_Source); @@ -510,9 +510,13 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, if (!prepareForFlush()) return; + if (flushedWindow != window()) { + flushSubWindow(flushedWindow); + return; + } + QMacAutoReleasePool pool; - NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view(); NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view(); // If the backingstore is just flushed, without being painted to first, then we may @@ -547,7 +551,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, // are committed as part of a display-cycle instead of on the next runloop pass. This // means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush // with other pending view and layer updates. - backingStoreView.window.viewsNeedDisplay = YES; + flushedView.window.viewsNeedDisplay = YES; if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) { // The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable, @@ -555,28 +559,10 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, flushedView.layer.contents = nil; } - if (flushedView == backingStoreView) { - qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface - << "to" << flushedView.layer << "of" << flushedView; - flushedView.layer.contents = backBufferSurface; - } else { - auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView]; - auto scale = flushedView.layer.contentsScale; - subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale)); - - // We make a copy of the image data up front, which means we don't - // need to mark the IOSurface as being in use. FIXME: Investigate - // if there's a cheaper way to get sub-image data to a layer. - m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess); - QImage subImage = m_buffers.back()->asImage()->copy(QRectF::fromCGRect(subviewRect).toRect()); - m_buffers.back()->unlock(); + qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface + << "to" << flushedView.layer << "of" << flushedView; - qCInfo(lcQpaBackingStore) << "Flushing" << subImage - << "to" << flushedView.layer << "of subview" << flushedView; - QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace( - QCFType<CGImageRef>(subImage.toCGImage()), colorSpace()); - flushedView.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage); - } + flushedView.layer.contents = backBufferSurface; // Since we may receive multiple flushes before a new frame is started, we do not // swap any buffers just yet. Instead we check in the next beginPaint if the layer's @@ -588,6 +574,53 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, // the window server. } +void QCALayerBackingStore::flushSubWindow(QWindow *subWindow) +{ + qCInfo(lcQpaBackingStore) << "Flushing sub-window" << subWindow + << "via its own backingstore"; + + auto &subWindowBackingStore = m_subWindowBackingstores[subWindow]; + if (!subWindowBackingStore) { + subWindowBackingStore.reset(new QCALayerBackingStore(subWindow)); + QObject::connect(subWindow, &QObject::destroyed, this, &QCALayerBackingStore::windowDestroyed); + subWindowBackingStore->m_clearSurfaceOnPaint = false; + } + + auto subWindowSize = subWindow->size(); + static const auto kNoStaticContents = QRegion(); + subWindowBackingStore->resize(subWindowSize, kNoStaticContents); + + auto subWindowLocalRect = QRect(QPoint(), subWindowSize); + subWindowBackingStore->beginPaint(subWindowLocalRect); + + QPainter painter(subWindowBackingStore->m_buffers.back()->asImage()); + painter.setCompositionMode(QPainter::CompositionMode_Source); + + NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view(); + NSView *flushedView = static_cast<QCocoaWindow *>(subWindow->handle())->view(); + auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView]; + auto scale = flushedView.layer.contentsScale; + subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale)); + + m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess); + const QImage *backingStoreImage = m_buffers.back()->asImage(); + painter.drawImage(subWindowLocalRect, *backingStoreImage, QRectF::fromCGRect(subviewRect)); + m_buffers.back()->unlock(); + + painter.end(); + subWindowBackingStore->endPaint(); + subWindowBackingStore->flush(subWindow, subWindowLocalRect, QPoint()); + + qCInfo(lcQpaBackingStore) << "Done flushing sub-window" << subWindow; +} + +void QCALayerBackingStore::windowDestroyed(QObject *object) +{ + auto *window = static_cast<QWindow*>(object); + qCInfo(lcQpaBackingStore) << "Removing backingstore for sub-window" << window; + m_subWindowBackingstores.erase(window); +} + #ifndef QT_NO_OPENGL void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground) @@ -721,4 +754,6 @@ QImage *QCALayerBackingStore::GraphicsBuffer::asImage() return &m_image; } +#include "moc_qcocoabackingstore.cpp" + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index cbe86e7e48..1a718975d1 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -45,7 +45,7 @@ // ------------- // // This file is not part of the Qt API. It provides helper functions -// for the Cocoa lighthouse plugin. This header file may +// for the Cocoa plugin. This header file may // change from version to version without notice, or even be removed. // // We mean it. diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index d0baea5b36..000bcd708b 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -74,8 +74,6 @@ QT_BEGIN_NAMESPACE Input method support in Cocoa uses NSTextInput protorol. Therefore almost all functionality is implemented in QNSView. - - \ingroup qt-lighthouse-cocoa */ diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 9689d6a89b..95b30ec447 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE \class QWindowsDirect2DBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p) diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index a4cfaa85a8..2eb04a501b 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -327,11 +327,12 @@ QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::Su } break; case SC_TitleBarNormalButton: - if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) + if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) { offset += delta; - else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) + } else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) { ret.adjust(0, 0, -delta*2, 0); offset += (delta +delta); + } break; case SC_TitleBarSysMenu: if (tb.flags & Qt::WindowSystemMenuHint) { diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp index fbf700518e..c122335a57 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp @@ -62,6 +62,16 @@ QWasmOpenGLContext::~QWasmOpenGLContext() } } +bool QWasmOpenGLContext::isOpenGLVersionSupported(QSurfaceFormat format) +{ + // Version check: support WebGL 1 and 2: + // (ES) 2.0 -> WebGL 1.0 + // (ES) 3.0 -> WebGL 2.0 + // [we don't expect that new WebGL versions will be created] + return ((format.majorVersion() == 2 && format.minorVersion() == 0) || + (format.majorVersion() == 3 && format.minorVersion() == 0)); +} + bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface) { // Native emscripten/WebGL contexts are tied to a single screen/canvas. The first @@ -92,10 +102,8 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons attributes.failIfMajorPerformanceCaveat = false; attributes.antialias = true; attributes.enableExtensionsByDefault = true; - - if (format.majorVersion() == 3) { - attributes.majorVersion = 2; - } + attributes.majorVersion = format.majorVersion() - 1; + attributes.minorVersion = format.minorVersion(); // WebGL doesn't allow separate attach buffers to STENCIL_ATTACHMENT and DEPTH_ATTACHMENT // we need both or none @@ -149,6 +157,9 @@ bool QWasmOpenGLContext::isSharing() const bool QWasmOpenGLContext::isValid() const { + if (!(isOpenGLVersionSupported(m_requestedFormat))) + return false; + // Note: we get isValid() calls before we see the surface and can // create a native context, so no context is also a valid state. return !m_context || !emscripten_is_webgl_context_lost(m_context); diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h index d27007e8ea..cf84379c36 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.h +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h @@ -51,6 +51,7 @@ public: QFunctionPointer getProcAddress(const char *procName) override; private: + static bool isOpenGLVersionSupported(QSurfaceFormat format); bool maybeCreateEmscriptenContext(QPlatformSurface *surface); static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format); diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index 1929f800a4..94d8470ab1 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -46,10 +46,9 @@ QT_BEGIN_NAMESPACE /*! - \group qt-lighthouse-win - \title Qt Lighthouse plugin for Windows + \title Qt platform plugin for Windows - \brief Class documentation of the Qt Lighthouse plugin for Windows. + \brief Class documentation of the Qt platform plugin for Windows. \section1 Supported Parameters @@ -78,7 +77,6 @@ QT_BEGIN_NAMESPACE \class QWindowsIntegrationPlugin \brief Plugin. \internal - \ingroup qt-lighthouse-win */ /*! @@ -86,7 +84,6 @@ QT_BEGIN_NAMESPACE \brief Namespace for enumerations, etc. \internal - \ingroup qt-lighthouse-win */ /*! @@ -97,7 +94,6 @@ QT_BEGIN_NAMESPACE With flags that should help to structure the code. \internal - \ingroup qt-lighthouse-win */ class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index bd7bdc55d1..e3939ca2d7 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE \class QWindowsBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index efcb0b6e6e..b23904e978 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE \note The OLE-functions used in this class require OleInitialize(). \internal - \ingroup qt-lighthouse-win */ #ifndef QT_NO_DEBUG_STREAM @@ -110,7 +109,6 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) \sa QWindowsInternalMimeDataBase, QWindowsClipboard \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index b8b54d9b86..c7b85187a3 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -186,7 +186,6 @@ static bool enableNonClientDpiScaling(HWND hwnd) \sa QWindowsShell32DLL \internal - \ingroup qt-lighthouse-win */ void QWindowsUser32DLL::init() @@ -252,7 +251,6 @@ QWindowsContext *QWindowsContext::m_instance = nullptr; Holds state information formerly stored in \c qapplication_win.cpp. \internal - \ingroup qt-lighthouse-win */ typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash; @@ -1007,6 +1005,13 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr) return result; } +void QWindowsContext::forceNcCalcSize(HWND hwnd) +{ + // Force WM_NCCALCSIZE to adjust margin + SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); +} + bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi) { @@ -1667,7 +1672,6 @@ static inline bool isTopLevel(HWND hwnd) There is another one for timers, sockets, etc in QEventDispatcherWin32. - \ingroup qt-lighthouse-win */ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 1831ac6ec0..c89b8b91f4 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -249,6 +249,8 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + static void forceNcCalcSize(HWND hwnd); + static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0); static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out, const QPlatformScreen *screen = nullptr); diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 19de3d5939..338bb9ff8f 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -73,7 +73,6 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \brief Cache key for storing values in a QHash with a QCursor as key. \internal - \ingroup qt-lighthouse-win */ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) @@ -97,7 +96,6 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) as do the Window manager frames (resize/move handles). \internal - \ingroup qt-lighthouse-win \sa QWindowsWindowCursor */ @@ -816,7 +814,6 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const cursor handle resource. \internal - \ingroup qt-lighthouse-win \sa QWindowsCursor */ diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index ccc809413e..dbd7d557db 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -130,7 +130,6 @@ namespace QWindowsDialogs remove all those messages (usually 1) and post the last one with a reset button state. - \ingroup qt-lighthouse-win */ void eatMouseMove() @@ -173,7 +172,6 @@ void eatMouseMove() \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeDialogBase : public QObject @@ -213,7 +211,6 @@ private: \sa QWindowsDialogThread, QWindowsNativeDialogBase \internal - \ingroup qt-lighthouse-win */ template <class BaseClass> @@ -267,7 +264,6 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsDialogThread : public QThread @@ -408,7 +404,6 @@ void QWindowsDialogHelperBase<BaseClass>::exec() does not reliably work. Provides thread-safe setters (for the non-modal case). \internal - \ingroup qt-lighthouse-win \sa QFileDialogOptions */ @@ -502,7 +497,6 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile \sa QWindowsNativeFileDialogBase, QWindowsFileDialogHelper \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeFileDialogBase; @@ -548,7 +542,6 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi \sa QWindowsNativeFileDialogBase \internal - \ingroup qt-lighthouse-win */ class QWindowsShellItem { @@ -791,7 +784,6 @@ QDebug operator<<(QDebug d, IShellItem *i) \sa QWindowsNativeFileDialogEventHandler, QWindowsFileDialogHelper \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase @@ -1304,7 +1296,6 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *) Implements single-selection methods. \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase @@ -1381,7 +1372,6 @@ QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const Implements multi-selection methods. \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase @@ -1554,7 +1544,6 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp but only on QQuickWindows, which do not have a fallback. \internal - \ingroup qt-lighthouse-win */ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper> @@ -1690,7 +1679,6 @@ QString QWindowsFileDialogHelper::selectedNameFilter() const \internal \sa QWindowsXpFileDialogHelper - \ingroup qt-lighthouse-win */ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase @@ -1938,7 +1926,6 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF \sa QWindowsXpNativeFileDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper> @@ -2015,7 +2002,6 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const \sa QWindowsColorDialogHelper \sa #define USE_NATIVE_COLOR_DIALOG \internal - \ingroup qt-lighthouse-win */ using SharedPointerColor = QSharedPointer<QColor>; @@ -2095,7 +2081,6 @@ void QWindowsNativeColorDialog::doExec(HWND owner) \sa #define USE_NATIVE_COLOR_DIALOG \sa QWindowsNativeColorDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsColorDialogHelper : public QWindowsDialogHelperBase<QPlatformColorDialogHelper> diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 3e4c93d47a..bb1e1345dc 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -75,7 +75,6 @@ QT_BEGIN_NAMESPACE \sa QWindowsOleDropSource \internal - \ingroup qt-lighthouse-win */ class QWindowsDragCursorWindow : public QRasterWindow @@ -135,7 +134,6 @@ void QWindowsDragCursorWindow::setPixmap(const QPixmap &p) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsDropMimeData::retrieveDataObject() const @@ -217,7 +215,6 @@ static Qt::MouseButtons lastButtons = Qt::NoButton; \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ class QWindowsOleDropSource : public QWindowsComBase<IDropSource> @@ -485,7 +482,6 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : m_window(w) @@ -659,7 +655,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, \class QWindowsDrag \brief Windows drag implementation. \internal - \ingroup qt-lighthouse-win */ bool QWindowsDrag::m_canceled = false; diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp index c9dd1c7c17..a06a14a980 100644 --- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE (instead of creating local hyperlinks). \internal - \ingroup qt-lighthouse-win */ QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) : diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 76baa93d98..4ae087dfaa 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE there is no need to differentiate between dynamic or Angle-only builds in here. \internal - \ingroup qt-lighthouse-win */ QWindowsLibEGL QWindowsEGLStaticContext::libEGL; @@ -376,7 +375,6 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 7431f52e8a..b2ac2e3476 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -858,7 +858,6 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData() context and to apply to a QSurfaceFormat. \internal - \ingroup qt-lighthouse-win */ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current() @@ -913,7 +912,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const is a current GL context. \internal - \ingroup qt-lighthouse-win */ class QOpenGLTemporaryContext @@ -946,7 +944,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() /*! \class QWindowsOpenGLAdditionalFormat \brief Additional format information that is not in QSurfaceFormat - \ingroup qt-lighthouse-win */ /*! @@ -964,7 +961,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() \sa QWindowsGLContext \internal - \ingroup qt-lighthouse-win */ #define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample" @@ -1051,7 +1047,6 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) QOpenGLContextData and are released in doneCurrent(). \internal - \ingroup qt-lighthouse-win */ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 7c4ddbd2a1..03be0b9451 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -160,7 +160,6 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp needs to be checked (mouse grab might interfere with candidate window). \internal - \ingroup qt-lighthouse-win */ diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 8963f2ad17..977b5903a5 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -131,7 +131,6 @@ QT_BEGIN_NAMESPACE QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to these structs to avoid lookups in several places. - \ingroup qt-lighthouse-win */ struct QWindowsIntegrationPrivate diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp index 44b7523fa6..ad3f02f83b 100644 --- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp +++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp @@ -60,7 +60,6 @@ \sa QInternalMimeData, QWindowsMime, QWindowsMimeConverter \internal - \ingroup qt-lighthouse-win */ bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index e3edf7e81e..4f46c05f7a 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -88,7 +88,6 @@ QT_BEGIN_NAMESPACE \class QWindowsKeyMapper \brief Translates Windows keys to QWindowSystemInterface events. \internal - \ingroup qt-lighthouse-win In addition, handles some special keys to display system menus, etc. The code originates from \c qkeymapper_win.cpp. diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 7c3e87eec1..5f21bdfa33 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE Qt Widgets, either the containers or the items might be deleted first. \internal - \ingroup qt-lighthouse-win */ static uint nextId = 1; @@ -794,20 +793,13 @@ QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow) ? qobject_cast<QWindowsMenuBar *>(menuBarV.value<QObject *>()) : nullptr; } -static inline void forceNcCalcSize(HWND hwnd) -{ - // Force WM_NCCALCSIZE to adjust margin: Does not appear to work? - SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); -} - void QWindowsMenuBar::install(QWindowsWindow *window) { const HWND hwnd = window->handle(); const BOOL result = SetMenu(hwnd, m_hMenuBar); if (result) { window->setMenuBar(this); - forceNcCalcSize(hwnd); + QWindowsContext::forceNcCalcSize(hwnd); } } @@ -817,7 +809,7 @@ void QWindowsMenuBar::removeFromWindow() const HWND hwnd = window->handle(); SetMenu(hwnd, nullptr); window->setMenuBar(nullptr); - forceNcCalcSize(hwnd); + QWindowsContext::forceNcCalcSize(hwnd); } } diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 9bc79a10f9..f8cc5e76ff 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -450,7 +450,6 @@ QDebug operator<<(QDebug d, IDataObject *dataObj) \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. \internal - \ingroup qt-lighthouse-win Qt's drag-and-drop and clipboard facilities use the MIME standard. On X11, this maps trivially to the Xdnd protocol, but on Windows @@ -1498,7 +1497,6 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const \class QWindowsMimeConverter \brief Manages the list of QWindowsMime instances. \internal - \ingroup qt-lighthouse-win \sa QWindowsMime */ diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index b776efc942..1b2d831268 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -145,7 +145,6 @@ static inline QTouchDevice *createTouchDevice() Dispatches mouse and touch events. Separate for code cleanliness. \internal - \ingroup qt-lighthouse-win */ QWindowsMouseHandler::QWindowsMouseHandler() = default; diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 90ba7a44c9..387f65ae8f 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeInterface : public QPlatformNativeInterface diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index f3450e2806..0a7fef6c30 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) : @@ -228,7 +227,6 @@ QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) \class QWindowsOleEnumFmtEtc \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject. \internal - \ingroup qt-lighthouse-win */ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index c7a0c2e62e..9a4f8d152c 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -171,7 +171,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) \brief Windows screen. \sa QWindowsScreenManager \internal - \ingroup qt-lighthouse-win */ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : @@ -432,7 +431,6 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy \sa QWindowsScreen \internal - \ingroup qt-lighthouse-win */ QWindowsScreenManager::QWindowsScreenManager() = default; diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index d6a5b29a71..def011e4bd 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -184,7 +184,6 @@ static inline HWND createTrayIconMessageWindow() \brief Windows native system tray icon \internal - \ingroup qt-lighthouse-win */ QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index cd5a78abb6..287ba931d9 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -173,7 +173,6 @@ QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL; \brief Functions from wintabl32.dll shipped with WACOM tablets used by QWindowsTabletSupport. \internal - \ingroup qt-lighthouse-win */ bool QWindowsWinTab32DLL::init() @@ -205,7 +204,6 @@ bool QWindowsWinTab32DLL::init() \internal \since 5.2 - \ingroup qt-lighthouse-win */ QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context) diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h index ffe2e62069..a31e00c0ac 100644 --- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE to be done by using QWaitCondition/QMutex. \internal - \ingroup qt-lighthouse-win */ class QWindowsThreadPoolRunner { diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 3dfffa6de6..2b5f0b6075 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -489,7 +489,6 @@ static QMargins invisibleMargins(QPoint screenPoint) \sa QWindowCreationContext \internal - \ingroup qt-lighthouse-win */ struct WindowCreationData @@ -917,7 +916,6 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s) into account. \internal - \ingroup qt-lighthouse-win */ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle) @@ -1087,7 +1085,6 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w) \since 5.6 \internal - \ingroup qt-lighthouse-win */ bool QWindowsBaseWindow::isRtlLayout(HWND hwnd) @@ -1176,7 +1173,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \brief Window wrapping GetDesktopWindow not allowing any manipulation. \since 5.6 \internal - \ingroup qt-lighthouse-win */ /*! @@ -1189,7 +1185,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \since 5.6 \internal - \ingroup qt-lighthouse-win */ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) @@ -1248,7 +1243,6 @@ void QWindowsForeignWindow::setVisible(bool visible) \sa WindowCreationData, QWindowsContext \internal - \ingroup qt-lighthouse-win */ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *s, @@ -1318,7 +1312,6 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const \endlist \internal - \ingroup qt-lighthouse-win */ const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; @@ -2442,7 +2435,17 @@ void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins) void QWindowsWindow::updateFullFrameMargins() { - // Normally obtained from WM_NCCALCSIZE + // QTBUG-82580: If a native menu is present, force a WM_NCCALCSIZE. + if (GetMenu(m_data.hwnd)) + QWindowsContext::forceNcCalcSize(m_data.hwnd); + else + calculateFullFrameMargins(); +} + +void QWindowsWindow::calculateFullFrameMargins() +{ + // Normally obtained from WM_NCCALCSIZE. This calculation only works + // when no native menu is present. const auto systemMargins = testFlag(DisableNonClientScaling) ? QWindowsGeometryHint::frameOnPrimaryScreen(m_data.hwnd) : frameMargins_sys(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e1f7908687..b35081d41d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -373,6 +373,7 @@ private: void handleWindowStateChange(Qt::WindowStates state); inline void destroyIcon(); void fireExpose(const QRegion ®ion, bool force=false); + void calculateFullFrameMargins(); mutable QWindowsWindowData m_data; QPointer<QWindowsMenuBar> m_menuBar; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp index 32a57473ad..fef5346eaf 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -105,6 +105,7 @@ static QString alertSound(const QObject *object) case Critical: return QStringLiteral("SystemHand"); } + return QString(); } return QStringLiteral("SystemAsterisk"); } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 59360616a1..3962d2d27f 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -305,11 +305,9 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow } break; case UIA_TogglePatternId: - // Checkbox controls. - if (accessible->role() == QAccessible::CheckBox - || (accessible->role() == QAccessible::MenuItem && accessible->state().checkable)) { + // Checkboxes and other checkable controls. + if (accessible->state().checkable) *pRetVal = new QWindowsUiaToggleProvider(id()); - } break; case UIA_SelectionPatternId: // Lists of items. diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index b27c408f40..04d7417801 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -43,6 +43,7 @@ #include <QtCore/QDir> #include <QtCore/QCoreApplication> #include <QtCore/qfunctions_winrt.h> +#include <private/qeventdispatcher_winrt_p.h> #include <wrl.h> #include <windows.foundation.h> @@ -94,13 +95,17 @@ bool QWinRTServices::openUrl(const QUrl &url) HRESULT hr = d->uriFactory->CreateUri(uriString.Get(), &uri); RETURN_FALSE_IF_FAILED("Failed to create URI from QUrl."); - ComPtr<IAsyncOperation<bool>> op; - hr = d->launcher->LaunchUriAsync(uri.Get(), &op); - RETURN_FALSE_IF_FAILED("Failed to start URI launch."); - boolean result; - hr = QWinRTFunctions::await(op, &result); - RETURN_FALSE_IF_FAILED("Failed to launch URI."); + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, uri, &result]() { + ComPtr<IAsyncOperation<bool>> op; + HRESULT hr = d->launcher->LaunchUriAsync(uri.Get(), &op); + RETURN_HR_IF_FAILED("Failed to start URI launch."); + + hr = QWinRTFunctions::await(op, &result); + RETURN_HR_IF_FAILED("Failed to launch URI."); + return hr; + }); + RETURN_FALSE_IF_FAILED("Failed to launch URI from Xaml thread."); return result; } @@ -131,12 +136,16 @@ bool QWinRTServices::openDocument(const QUrl &url) boolean result; { - ComPtr<IAsyncOperation<bool>> op; - hr = d->launcher->LaunchFileAsync(file.Get(), &op); - RETURN_FALSE_IF_FAILED("Failed to start file launch."); - - hr = QWinRTFunctions::await(op, &result); - RETURN_FALSE_IF_FAILED("Failed to launch file."); + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, file, &result]() { + ComPtr<IAsyncOperation<bool>> op; + HRESULT hr = d->launcher->LaunchFileAsync(file.Get(), &op); + RETURN_HR_IF_FAILED("Failed to start file launch."); + + hr = QWinRTFunctions::await(op, &result); + RETURN_HR_IF_FAILED("Failed to launch file."); + return hr; + }); + RETURN_FALSE_IF_FAILED("Failed to launch file from Xaml thread."); } return result; diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp index 7bf2b38d7d..77d0caf649 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <QtCore/qrandom.h> + #include <private/qpixmapcache_p.h> #include <private/qpaintengine_p.h> #include <private/qpolygonclipper_p.h> @@ -504,7 +506,7 @@ static Picture getPatternFill(int screen, const QBrush &b) return X11->pattern_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) { XRenderFreePicture (QXcbX11Info::display(), X11->pattern_fills[i].picture); diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp index 57b1882e4b..6a483fc7e5 100644 --- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <QtCore/qrandom.h> + #include "qxcbconnection.h" #include "qcolormap_x11_p.h" #include "qxcbnativepainting.h" @@ -279,7 +281,7 @@ Picture QXcbX11Data::getSolidFill(int screen, const QColor &c) return X11->solid_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { XRenderFreePicture (X11->display, X11->solid_fills[i].picture); diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index ff5c50b702..780816605a 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -182,6 +182,7 @@ static const char *xcb_atomnames = { "XdndActionCopy\0" "XdndActionLink\0" "XdndActionMove\0" + "XdndActionAsk\0" "XdndActionPrivate\0" // Xkb diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h index 80b5887395..9cf93ec314 100644 --- a/src/plugins/platforms/xcb/qxcbatom.h +++ b/src/plugins/platforms/xcb/qxcbatom.h @@ -183,6 +183,7 @@ public: XdndActionCopy, XdndActionLink, XdndActionMove, + XdndActionAsk, XdndActionPrivate, // Xkb diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 639e4f039c..42c7a52bd4 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -289,10 +289,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) if (pixmapCacheKey) { bitmapCacheKey = pixmapCacheKey; } else { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); + Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull()); + Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull()); + bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey(); + maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey(); } } } @@ -613,8 +613,8 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor) qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors"); } else { xcb_connection_t *conn = xcb_connection(); - xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage()); - xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage()); + xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap(Qt::ReturnByValue).toImage()); + xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask(Qt::ReturnByValue).toImage()); c = xcb_generate_id(conn); xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, spot.x(), spot.y()); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index e76fc8bd40..cc735f40a8 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -216,6 +216,22 @@ void QXcbDrag::endDrag() initiatorWindow.clear(); } +Qt::DropAction QXcbDrag::defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const +{ + if (currentDrag() || drop_actions.isEmpty()) + return QBasicDrag::defaultAction(possibleActions, modifiers); + + return toDropAction(drop_actions.first()); +} + +void QXcbDrag::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) +{ + if (event->window != xdnd_dragsource || event->atom != atom(QXcbAtom::XdndActionList)) + return; + + readActionList(); +} + static bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType) { @@ -470,16 +486,20 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod move.data.data32[1] = 0; // flags move.data.data32[2] = (globalPos.x() << 16) + globalPos.y(); move.data.data32[3] = connection()->time(); - move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), mods)); + const auto supportedActions = currentDrag()->supportedActions(); + const auto requestedAction = defaultAction(supportedActions, mods); + move.data.data32[4] = toXdndAction(requestedAction); qCDebug(lcQpaXDnd) << "sending XdndPosition to target:" << target; source_time = connection()->time(); - if (w) + if (w) { handle_xdnd_position(w, &move, b, mods); - else + } else { + setActionList(requestedAction, supportedActions); xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move); + } } static const bool isUnity = qgetenv("XDG_CURRENT_DESKTOP").toLower() == "unity"; @@ -560,6 +580,16 @@ Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const return Qt::CopyAction; } +Qt::DropActions QXcbDrag::toDropActions(const QVector<xcb_atom_t> &atoms) const +{ + Qt::DropActions actions; + for (const auto actionAtom : atoms) { + if (actionAtom != atom(QXcbAtom::XdndActionAsk)) + actions |= toDropAction(actionAtom); + } + return actions; +} + xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const { switch (a) { @@ -577,6 +607,60 @@ xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const } } +void QXcbDrag::readActionList() +{ + drop_actions.clear(); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource, + atom(QXcbAtom::XdndActionList), XCB_ATOM_ATOM, + 0, 1024); + if (reply && reply->type != XCB_NONE && reply->format == 32) { + int length = xcb_get_property_value_length(reply.get()) / 4; + + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); + for (int i = 0; i < length; ++i) + drop_actions.append(atoms[i]); + } +} + +void QXcbDrag::setActionList(Qt::DropAction requestedAction, Qt::DropActions supportedActions) +{ +#ifndef QT_NO_CLIPBOARD + QVector<xcb_atom_t> actions; + if (requestedAction != Qt::IgnoreAction) + actions.append(toXdndAction(requestedAction)); + + auto checkAppend = [this, requestedAction, supportedActions, &actions](Qt::DropAction action) { + if (requestedAction != action && supportedActions & action) + actions.append(toXdndAction(action)); + }; + + checkAppend(Qt::CopyAction); + checkAppend(Qt::MoveAction); + checkAppend(Qt::LinkAction); + + if (current_actions != actions) { + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(), + atom(QXcbAtom::XdndActionList), + XCB_ATOM_ATOM, 32, actions.size(), actions.constData()); + current_actions = actions; + } +#endif +} + +void QXcbDrag::startListeningForActionListChanges() +{ + connection()->addWindowEventListener(xdnd_dragsource, this); + const uint32_t event_mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; + xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask); +} + +void QXcbDrag::stopListeningForActionListChanges() +{ + const uint32_t event_mask[] = { XCB_EVENT_MASK_NO_EVENT }; + xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask); + connection()->removeWindowEventListener(xdnd_dragsource); +} + int QXcbDrag::findTransactionByWindow(xcb_window_t window) { int at = -1; @@ -657,6 +741,9 @@ void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t * return; xdnd_dragsource = event->data.data32[0]; + startListeningForActionListChanges(); + readActionList(); + if (!proxy) proxy = xdndProxy(connection(), xdnd_dragsource); current_proxy_target = proxy ? proxy : xdnd_dragsource; @@ -723,7 +810,9 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message supported_actions = currentDrag()->supportedActions(); } else { dropData = m_dropData; - supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); + supported_actions = toDropActions(drop_actions); + if (e->data.data32[4] != atom(QXcbAtom::XdndActionAsk)) + supported_actions |= Qt::DropActions(toDropAction(e->data.data32[4])); } auto buttons = currentDrag() ? b : connection()->queryMouseButtons(); @@ -867,8 +956,10 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t // If the target receives XdndLeave, it frees any cached data and forgets the whole incident. qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndLeave"; - if (!currentWindow || w != currentWindow.data()->handle()) + if (!currentWindow || w != currentWindow.data()->handle()) { + stopListeningForActionListChanges(); return; // sanity + } // ### // if (checkEmbedded(current_embedding_widget, event)) { @@ -883,6 +974,8 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t event->data.data32[0], xdnd_dragsource); } + stopListeningForActionListChanges(); + QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, { }, { }); } @@ -929,6 +1022,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndDrop"; if (!currentWindow) { + stopListeningForActionListChanges(); xdnd_dragsource = 0; return; // sanity } @@ -951,7 +1045,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e supported_drop_actions = Qt::DropActions(l[4]); } else { dropData = m_dropData; - supported_drop_actions = accepted_drop_action; + supported_drop_actions = accepted_drop_action | toDropActions(drop_actions); } if (!dropData) @@ -986,6 +1080,8 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (char *)&finished); + stopListeningForActionListChanges(); + dropped = true; } diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 7bef7a818a..0d16afc47e 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -68,7 +68,7 @@ class QXcbScreen; class QDrag; class QShapedPixmapWindow; -class QXcbDrag : public QXcbObject, public QBasicDrag +class QXcbDrag : public QXcbObject, public QBasicDrag, public QXcbWindowEventListener { public: QXcbDrag(QXcbConnection *c); @@ -82,6 +82,10 @@ public: void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; void endDrag() override; + Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const override; + + void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override; + void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0); void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event); @@ -114,8 +118,14 @@ private: void send_leave(); Qt::DropAction toDropAction(xcb_atom_t atom) const; + Qt::DropActions toDropActions(const QVector<xcb_atom_t> &atoms) const; xcb_atom_t toXdndAction(Qt::DropAction a) const; + void readActionList(); + void setActionList(Qt::DropAction requestedAction, Qt::DropActions supportedActions); + void startListeningForActionListChanges(); + void stopListeningForActionListChanges(); + QPointer<QWindow> initiatorWindow; QPointer<QWindow> currentWindow; QPoint currentPosition; @@ -159,6 +169,9 @@ private: QVector<xcb_atom_t> drag_types; + QVector<xcb_atom_t> current_actions; + QVector<xcb_atom_t> drop_actions; + struct Transaction { xcb_timestamp_t timestamp; |