diff options
11 files changed, 340 insertions, 206 deletions
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro index 5a1e71b962..4f986b57d7 100644 --- a/src/plugins/platforms/direct2d/direct2d.pro +++ b/src/plugins/platforms/direct2d/direct2d.pro @@ -22,7 +22,8 @@ SOURCES += \ qwindowsdirect2dintegration.cpp \ qwindowsdirect2dplatformplugin.cpp \ qwindowsdirect2ddevicecontext.cpp \ - qwindowsdirect2dnativeinterface.cpp + qwindowsdirect2dnativeinterface.cpp \ + qwindowsdirect2dwindow.cpp HEADERS += \ qwindowsdirect2dpaintengine.h \ @@ -34,6 +35,7 @@ HEADERS += \ qwindowsdirect2dbackingstore.h \ qwindowsdirect2dintegration.h \ qwindowsdirect2ddevicecontext.h \ - qwindowsdirect2dnativeinterface.h + qwindowsdirect2dnativeinterface.h \ + qwindowsdirect2dwindow.h OTHER_FILES += direct2d.json diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 379e75c26e..079ad6f127 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -45,108 +45,15 @@ #include "qwindowsdirect2dpaintdevice.h" #include "qwindowsdirect2dbitmap.h" #include "qwindowsdirect2ddevicecontext.h" +#include "qwindowsdirect2dwindow.h" -#include "qwindowswindow.h" #include "qwindowscontext.h" #include <QtGui/QWindow> #include <QtCore/QDebug> -#include <dxgi1_2.h> -#include <d3d11.h> -#include <wrl.h> - -using Microsoft::WRL::ComPtr; - QT_BEGIN_NAMESPACE -class QWindowsDirect2DBackingStorePrivate -{ -public: - QWindowsDirect2DBackingStorePrivate() {} - - ComPtr<IDXGISwapChain1> swapChain; - QSharedPointer<QWindowsDirect2DBitmap> backingStore; - QScopedPointer<QWindowsDirect2DPaintDevice> nativePaintDevice; - - bool init(HWND hwnd) - { - DXGI_SWAP_CHAIN_DESC1 desc = {}; - - desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - desc.BufferCount = 1; - desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; - - HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd( - QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice - hwnd, // [in] HWND hWnd - &desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc - NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc - NULL, // [in] IDXGIOutput *pRestrictToOutput - swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain - - if (FAILED(hr)) - qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr); - - return SUCCEEDED(hr); - } - - bool setupPaintDevice() - { - if (!backingStore) { - ComPtr<ID2D1DeviceContext> deviceContext; - ComPtr<IDXGISurface1> backBufferSurface; - ComPtr<ID2D1Bitmap1> backBufferBitmap; - - HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext( - D2D1_DEVICE_CONTEXT_OPTIONS_NONE, - deviceContext.ReleaseAndGetAddressOf()); - if (FAILED(hr)) { - qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr); - return false; - } - - hr = swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface)); - if (FAILED(hr)) { - qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr); - return false; - } - - hr = deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.ReleaseAndGetAddressOf()); - if (FAILED(hr)) { - qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr); - return false; - } - - backingStore.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), deviceContext.Get())); - } - - if (!nativePaintDevice) - nativePaintDevice.reset(new QWindowsDirect2DPaintDevice(backingStore.data(), QInternal::Widget)); - - return true; - } - - void releaseBackingStore() - { - nativePaintDevice.reset(); - backingStore.reset(); - } - - QPaintDevice *paintDevice() - { - setupPaintDevice(); - return nativePaintDevice.data(); - } - - void flush() - { - swapChain->Present(1, 0); - } -}; - /*! \class QWindowsDirect2DBackingStore \brief Backing store for windows. @@ -154,86 +61,43 @@ public: \ingroup qt-lighthouse-win */ -QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window) - : QPlatformBackingStore(window) - , d_ptr(new QWindowsDirect2DBackingStorePrivate) +static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p) { + return static_cast<QWindowsDirect2DPlatformPixmap *>(p->handle()); } -bool QWindowsDirect2DBackingStore::init() +QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window) + : QPlatformBackingStore(window) { - if (window()->surfaceType() == QSurface::RasterSurface) { - Q_D(QWindowsDirect2DBackingStore); - return d->init(windowsWindow()->handle()); - } - - return true; -} - -QWindowsDirect2DBackingStore *QWindowsDirect2DBackingStore::create(QWindow *window) -{ - QWindowsDirect2DBackingStore *result = new QWindowsDirect2DBackingStore(window); - - if (!result->init()) { - delete result; - result = 0; - } - - return result; } QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore() { - Q_D(QWindowsDirect2DBackingStore); - d->releaseBackingStore(); - d->swapChain.Reset(); } QPaintDevice *QWindowsDirect2DBackingStore::paintDevice() { - QPaintDevice *result = 0; - - if (window()->surfaceType() == QSurface::RasterSurface) { - Q_D(QWindowsDirect2DBackingStore); - result = d->paintDevice(); - } - - return result; + return m_pixmap.data(); } -void QWindowsDirect2DBackingStore::flush(QWindow *, const QRegion &, const QPoint &) +void QWindowsDirect2DBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - if (window()->surfaceType() == QSurface::RasterSurface) { - Q_D(QWindowsDirect2DBackingStore); - d->flush(); - } + QPlatformWindow *pw = window->handle(); + if (pw && m_pixmap) + static_cast<QWindowsDirect2DWindow *>(pw)->flush(platformPixmap(m_pixmap.data())->bitmap(), region, offset); } void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion ®ion) { Q_UNUSED(region); - if (window()->surfaceType() != QSurface::RasterSurface) - return; + QScopedPointer<QPixmap> oldPixmap(m_pixmap.take()); + m_pixmap.reset(new QPixmap(size.width(), size.height())); - Q_D(QWindowsDirect2DBackingStore); - d->releaseBackingStore(); - QWindowsDirect2DContext::instance()->d3dDeviceContext()->ClearState(); - - HRESULT hr = d->swapChain->ResizeBuffers(0, - size.width(), size.height(), - DXGI_FORMAT_UNKNOWN, - 0); - if (FAILED(hr)) - qWarning("%s: Could not resize buffers: %#x", __FUNCTION__, hr); -} - -QWindowsWindow *QWindowsDirect2DBackingStore::windowsWindow() const -{ - if (const QWindow *w = window()) - if (QPlatformWindow *pw = w->handle()) - return static_cast<QWindowsWindow *>(pw); - return 0; + if (oldPixmap) { + foreach (const QRect &rect, region.rects()) + platformPixmap(m_pixmap.data())->copy(oldPixmap->handle(), rect); + } } QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h index 89ecee67dd..9776d234e8 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h @@ -42,33 +42,28 @@ #ifndef QWINDOWSDIRECT2DBACKINGSTORE_H #define QWINDOWSDIRECT2DBACKINGSTORE_H +#include "qwindowsdirect2dplatformpixmap.h" + #include <QtCore/QScopedPointer> #include <QtGui/qpa/qplatformbackingstore.h> +#include <QtGui/QPixmap> QT_BEGIN_NAMESPACE -class QWindowsWindow; -class QWindowsDirect2DBackingStorePrivate; - class QWindowsDirect2DBackingStore : public QPlatformBackingStore { - Q_DECLARE_PRIVATE(QWindowsDirect2DBackingStore) Q_DISABLE_COPY(QWindowsDirect2DBackingStore) public: - static QWindowsDirect2DBackingStore *create(QWindow *window); + QWindowsDirect2DBackingStore(QWindow *window); ~QWindowsDirect2DBackingStore(); QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void flush(QWindow *, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; private: - QWindowsDirect2DBackingStore(QWindow *window); - bool init(); - - QWindowsWindow *windowsWindow() const; - QScopedPointer<QWindowsDirect2DBackingStorePrivate> d_ptr; + QScopedPointer<QPixmap> m_pixmap; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp index c2f3c05bde..1a26d7029e 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp @@ -44,11 +44,13 @@ #include "qwindowsdirect2dbackingstore.h" #include "qwindowsdirect2dplatformpixmap.h" #include "qwindowsdirect2dnativeinterface.h" +#include "qwindowsdirect2dwindow.h" #include "qwindowscontext.h" #include <QtCore/QDebug> #include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/qpa/qwindowsysteminterface.h> QT_BEGIN_NAMESPACE @@ -81,6 +83,13 @@ QWindowsDirect2DIntegration::~QWindowsDirect2DIntegration() return static_cast<QWindowsDirect2DIntegration *>(QWindowsIntegration::instance()); } + QPlatformWindow *QWindowsDirect2DIntegration::createPlatformWindow(QWindow *window) const + { + QWindowsWindowData data = createWindowData(window); + return data.hwnd ? new QWindowsDirect2DWindow(window, data) + : Q_NULLPTR; + } + QPlatformNativeInterface *QWindowsDirect2DIntegration::nativeInterface() const { return &d->m_nativeInterface; @@ -100,7 +109,7 @@ QPlatformPixmap *QWindowsDirect2DIntegration::createPlatformPixmap(QPlatformPixm QPlatformBackingStore *QWindowsDirect2DIntegration::createPlatformBackingStore(QWindow *window) const { - return QWindowsDirect2DBackingStore::create(window); + return new QWindowsDirect2DBackingStore(window); } QWindowsDirect2DContext *QWindowsDirect2DIntegration::direct2DContext() const diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h index 12412cbc0f..a46d5c0126 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h @@ -60,6 +60,7 @@ public: static QWindowsDirect2DIntegration *instance(); + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp new file mode 100644 index 0000000000..bf860f982e --- /dev/null +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsdirect2dcontext.h" +#include "qwindowsdirect2dwindow.h" +#include "qwindowsdirect2ddevicecontext.h" +#include "qwindowsdirect2dhelpers.h" + +#include <d3d11.h> +#include <d2d1_1.h> +using Microsoft::WRL::ComPtr; + +QT_BEGIN_NAMESPACE + +QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data) + : QWindowsWindow(window, data) + , m_needsFullFlush(true) +{ + DXGI_SWAP_CHAIN_DESC1 desc = {}; + + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferCount = 1; + desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; + + HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd( + QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice + handle(), // [in] HWND hWnd + &desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc + NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc + NULL, // [in] IDXGIOutput *pRestrictToOutput + m_swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain + + if (FAILED(hr)) + qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr); + + hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + m_deviceContext.GetAddressOf()); + if (FAILED(hr)) + qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr); +} + +QWindowsDirect2DWindow::~QWindowsDirect2DWindow() +{ +} + +void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset) +{ + DXGI_SWAP_CHAIN_DESC1 desc; + HRESULT hr = m_swapChain->GetDesc1(&desc); + QRect geom = geometry(); + + if (FAILED(hr) || (desc.Width != geom.width()) || (desc.Height != geom.height())) { + resizeSwapChain(geom.size()); + m_swapChain->GetDesc1(&desc); + } + + setupBitmap(); + if (!m_bitmap) + return; + + m_bitmap->deviceContext()->begin(); + + ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get(); + if (!m_needsFullFlush) { + QRegion clipped = region; + clipped &= QRect(0, 0, desc.Width, desc.Height); + + foreach (const QRect &rect, clipped.rects()) { + QRectF rectF(rect); + dc->DrawBitmap(bitmap->bitmap(), + to_d2d_rect_f(rectF), + 1.0, + D2D1_INTERPOLATION_MODE_LINEAR, + to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); + } + } else { + QRectF rectF(0, 0, desc.Width, desc.Height); + dc->DrawBitmap(bitmap->bitmap(), + to_d2d_rect_f(rectF), + 1.0, + D2D1_INTERPOLATION_MODE_LINEAR, + to_d2d_rect_f(rectF.translated(offset.x(), offset.y()))); + m_needsFullFlush = false; + } + + m_bitmap->deviceContext()->end(); + m_swapChain->Present(1, 0); +} + +void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size) +{ + if (!m_swapChain) + return; + + m_bitmap.reset(); + m_deviceContext->SetTarget(Q_NULLPTR); + + HRESULT hr = m_swapChain->ResizeBuffers(0, + size.width(), size.height(), + DXGI_FORMAT_UNKNOWN, + 0); + if (FAILED(hr)) + qWarning("%s: Could not resize swap chain: %#x", __FUNCTION__, hr); + + m_needsFullFlush = true; +} + +void QWindowsDirect2DWindow::setupBitmap() +{ + if (m_bitmap) + return; + + if (!m_deviceContext) + return; + + if (!m_swapChain) + return; + + ComPtr<IDXGISurface1> backBufferSurface; + HRESULT hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface)); + if (FAILED(hr)) { + qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr); + return; + } + + ComPtr<ID2D1Bitmap1> backBufferBitmap; + hr = m_deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.GetAddressOf()); + if (FAILED(hr)) { + qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr); + return; + } + + m_bitmap.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get())); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h new file mode 100644 index 0000000000..7996904639 --- /dev/null +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSDIRECT2DWINDOW_H +#define QWINDOWSDIRECT2DWINDOW_H + +#include "qwindowswindow.h" +#include "qwindowsdirect2dbitmap.h" + +#include <dxgi1_2.h> +#include <wrl.h> + +QT_BEGIN_NAMESPACE + +class QWindowsDirect2DWindow : public QWindowsWindow +{ +public: + QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data); + ~QWindowsDirect2DWindow(); + + void flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset); + +private: + void resizeSwapChain(const QSize &size); + void setupBitmap(); + +private: + Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain; + Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_deviceContext; + QScopedPointer<QWindowsDirect2DBitmap> m_bitmap; + bool m_needsFullFlush; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSDIRECT2DWINDOW_H diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 0c46e0092a..8a91929733 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -234,9 +234,9 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co return false; } -QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const +QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const { - QWindowsWindow::WindowData requested; + QWindowsWindowData requested; requested.flags = window->flags(); requested.geometry = window->geometry(); // Apply custom margins (see QWindowsWindow::setCustomMargins())). @@ -244,8 +244,8 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons if (customMarginsV.isValid()) requested.customMargins = qvariant_cast<QMargins>(customMarginsV); - const QWindowsWindow::WindowData obtained - = QWindowsWindow::WindowData::create(window, requested, window->title()); + const QWindowsWindowData obtained + = QWindowsWindowData::create(window, requested, window->title()); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << '<' << window << "\n Requested: " << requested.geometry << "frame incl.: " @@ -254,14 +254,23 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons << "\n Obtained : " << obtained.geometry << " Margins "<< obtained.frame << " Flags=" << QWindowsWindow::debugWindowFlags(obtained.flags) << " Handle=" << obtained.hwnd << '\n'; - if (!obtained.hwnd) - return 0; - if (requested.flags != obtained.flags) - window->setFlags(obtained.flags); - // Trigger geometry change signals of QWindow. - if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry) - QWindowSystemInterface::handleGeometryChange(window, obtained.geometry); - return new QWindowsWindow(window, obtained); + + if (obtained.hwnd) { + if (requested.flags != obtained.flags) + window->setFlags(obtained.flags); + // Trigger geometry change signals of QWindow. + if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry) + QWindowSystemInterface::handleGeometryChange(window, obtained.geometry); + } + + return obtained; +} + +QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const +{ + QWindowsWindowData data = createWindowData(window); + return data.hwnd ? new QWindowsWindow(window, data) + : Q_NULLPTR; } #ifndef QT_NO_OPENGL diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 30a39f67c4..2202ebd39e 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE struct QWindowsIntegrationPrivate; +struct QWindowsWindowData; +class QWindowsWindow; class QWindowsIntegration : public QPlatformIntegration { @@ -68,6 +70,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; + QWindowsWindowData createWindowData(QWindow *window) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; #ifndef QT_NO_OPENGL virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index aab93a8265..5b6fced031 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -358,7 +358,7 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo struct WindowCreationData { - typedef QWindowsWindow::WindowData WindowData; + typedef QWindowsWindowData WindowData; enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), @@ -534,7 +534,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag } } -QWindowsWindow::WindowData +QWindowsWindowData WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const { typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr; @@ -851,7 +851,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, \ingroup qt-lighthouse-win */ -QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : +QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : QPlatformWindow(aWindow), m_data(data), m_flags(WithinCreate), @@ -1017,14 +1017,14 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w) return w; } -QWindowsWindow::WindowData - QWindowsWindow::WindowData::create(const QWindow *w, - const WindowData ¶meters, +QWindowsWindowData + QWindowsWindowData::create(const QWindow *w, + const QWindowsWindowData ¶meters, const QString &title) { WindowCreationData creationData; creationData.fromWindow(w, parameters.flags); - WindowData result = creationData.create(w, parameters, title); + QWindowsWindowData result = creationData.create(w, parameters, title); // Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin. creationData.initialize(result.hwnd, !parameters.customMargins.isNull(), 1); return result; @@ -1452,7 +1452,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) << " geometry " << oldGeometry << "->" << newGeometry; } -QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, +QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags) const { WindowCreationData creationData; @@ -1460,7 +1460,7 @@ QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt creationData.applyWindowFlags(m_data.hwnd); creationData.initialize(m_data.hwnd, true, m_opacity); - WindowData result = m_data; + QWindowsWindowData result = m_data; result.flags = creationData.flags; result.embedded = creationData.embedded; setFlag(FrameDirty); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 61dc3e2dc2..3a9516e0e5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -111,6 +111,22 @@ struct QWindowCreationContext int frameHeight; }; +struct QWindowsWindowData +{ + QWindowsWindowData() : hwnd(0), embedded(false) {} + + Qt::WindowFlags flags; + QRect geometry; + QMargins frame; // Do not use directly for windows, see FrameDirty. + QMargins customMargins; // User-defined, additional frame for NCCALCSIZE + HWND hwnd; + bool embedded; + + static QWindowsWindowData create(const QWindow *w, + const QWindowsWindowData ¶meters, + const QString &title); +}; + class QWindowsWindow : public QPlatformWindow { public: @@ -140,23 +156,7 @@ public: WithinMaximize = 0x40000 }; - struct WindowData - { - WindowData() : hwnd(0) {} - - Qt::WindowFlags flags; - QRect geometry; - QMargins frame; // Do not use directly for windows, see FrameDirty. - QMargins customMargins; // User-defined, additional frame for NCCALCSIZE - HWND hwnd; - bool embedded; - - static WindowData create(const QWindow *w, - const WindowData ¶meters, - const QString &title); - }; - - QWindowsWindow(QWindow *window, const WindowData &data); + QWindowsWindow(QWindow *window, const QWindowsWindowData &data); ~QWindowsWindow(); virtual QSurfaceFormat format() const { return m_format; } @@ -274,7 +274,7 @@ private: inline void setGeometry_sys(const QRect &rect) const; inline QRect frameGeometry_sys() const; inline QRect geometry_sys() const; - inline WindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const; + inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const; inline bool isFullScreen_sys() const; inline void setWindowState_sys(Qt::WindowState newState); inline void setParent_sys(const QPlatformWindow *parent) const; @@ -287,7 +287,7 @@ private: inline void destroyIcon(); void fireExpose(const QRegion ®ion, bool force=false); - mutable WindowData m_data; + mutable QWindowsWindowData m_data; mutable unsigned m_flags; HDC m_hdc; Qt::WindowState m_windowState; |