diff options
Diffstat (limited to 'src/plugins/platforms')
112 files changed, 2800 insertions, 2242 deletions
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 03592bfa7d..73db9e93a3 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -11,6 +11,8 @@ QT += \ eventdispatcher_support-private accessibility_support-private \ fontdatabase_support-private egl_support-private +qtConfig(vulkan): QT += vulkan_support-private + OTHER_FILES += $$PWD/android.json INCLUDEPATH += \ @@ -78,6 +80,13 @@ HEADERS += $$PWD/qandroidplatformintegration.h \ qtConfig(android-style-assets): SOURCES += $$PWD/extract.cpp else: SOURCES += $$PWD/extract-dummy.cpp +qtConfig(vulkan) { + SOURCES += $$PWD/qandroidplatformvulkaninstance.cpp \ + $$PWD/qandroidplatformvulkanwindow.cpp + HEADERS += $$PWD/qandroidplatformvulkaninstance.h \ + $$PWD/qandroidplatformvulkanwindow.h +} + PLUGIN_TYPE = platforms load(qt_plugin) diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index 08498d0582..ced35c4cfa 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -103,11 +103,7 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags if (!str.isEmpty()) m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); - // http://developer.android.com/design/building-blocks/dialogs.html - // dismissive action on the left, affirmative on the right - // There don't seem to be more fine-grained rules, but the OS X layout - // at least conforms to this one rule and makes the rest deterministic. - const int * currentLayout = buttonLayout(Qt::Horizontal, MacLayout); + const int * currentLayout = buttonLayout(Qt::Horizontal, AndroidLayout); while (*currentLayout != QPlatformDialogHelper::EOL) { int role = (*currentLayout & ~QPlatformDialogHelper::Reverse); addButtons(opt, static_cast<ButtonRole>(role)); diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index d8bba4f8e9..ec09965f45 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -69,6 +69,11 @@ #include <QtPlatformHeaders/QEGLNativeContext> +#if QT_CONFIG(vulkan) +#include "qandroidplatformvulkanwindow.h" +#include "qandroidplatformvulkaninstance.h" +#endif + QT_BEGIN_NAMESPACE int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320; @@ -119,6 +124,23 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA return 0; } +void *QAndroidPlatformNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window) +{ +#if QT_CONFIG(vulkan) + if (resource == "vkSurface") { + if (window->surfaceType() == QSurface::VulkanSurface) { + QAndroidPlatformVulkanWindow *w = static_cast<QAndroidPlatformVulkanWindow *>(window->handle()); + // return a pointer to the VkSurfaceKHR, not the value + return w ? w->vkSurface() : nullptr; + } + } +#else + Q_UNUSED(resource); + Q_UNUSED(window); +#endif + return nullptr; +} + void QAndroidPlatformNativeInterface::customEvent(QEvent *event) { if (event->type() == QEvent::User) @@ -238,6 +260,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const case ForeignWindows: return QtAndroid::activity(); case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroid::activity(); case RasterGLSurface: return QtAndroid::activity(); + case TopStackedNativeChildWindows: return false; default: return QPlatformIntegration::hasCapability(cap); } @@ -290,6 +313,11 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind if (!QtAndroid::activity()) return nullptr; +#if QT_CONFIG(vulkan) + if (window->surfaceType() == QSurface::VulkanSurface) + return new QAndroidPlatformVulkanWindow(window); +#endif + return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay); } @@ -430,4 +458,13 @@ void QAndroidPlatformIntegration::setScreenSize(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +#if QT_CONFIG(vulkan) + +QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + return new QAndroidPlatformVulkanInstance(instance); +} + +#endif // QT_CONFIG(vulkan) + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 923670b9e6..047eaf122e 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -40,6 +40,8 @@ #ifndef QANDROIDPLATFORMINTERATION_H #define QANDROIDPLATFORMINTERATION_H +#include <QtGui/qtguiglobal.h> + #include <qpa/qplatformintegration.h> #include <qpa/qplatformmenu.h> #include <qpa/qplatformnativeinterface.h> @@ -64,6 +66,7 @@ class QAndroidPlatformNativeInterface: public QPlatformNativeInterface { public: void *nativeResourceForIntegration(const QByteArray &resource) override; + void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override; std::shared_ptr<AndroidStyle> m_androidStyle; protected: @@ -126,6 +129,10 @@ public: QTouchDevice *touchDevice() const { return m_touchDevice; } void setTouchDevice(QTouchDevice *touchDevice) { m_touchDevice = touchDevice; } +#if QT_CONFIG(vulkan) + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; +#endif + private: EGLDisplay m_eglDisplay; QTouchDevice *m_touchDevice; diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index 06b297a1ad..d9cecebf2c 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE QAndroidPlatformMenu::QAndroidPlatformMenu() { - m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick m_enabled = true; m_isVisible = true; } @@ -92,16 +91,6 @@ void QAndroidPlatformMenu::syncSeparatorsCollapsible(bool enable) Q_UNUSED(enable) } -void QAndroidPlatformMenu::setTag(quintptr tag) -{ - m_tag = tag; -} - -quintptr QAndroidPlatformMenu::tag() const -{ - return m_tag; -} - void QAndroidPlatformMenu::setText(const QString &text) { m_text = text; diff --git a/src/plugins/platforms/android/qandroidplatformmenu.h b/src/plugins/platforms/android/qandroidplatformmenu.h index 00968672c5..47e650f2d7 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.h +++ b/src/plugins/platforms/android/qandroidplatformmenu.h @@ -61,8 +61,6 @@ public: void syncMenuItem(QPlatformMenuItem *menuItem) override; void syncSeparatorsCollapsible(bool enable) override; - void setTag(quintptr tag) override; - quintptr tag() const override; void setText(const QString &text) override; QString text() const; void setIcon(const QIcon &icon) override; @@ -81,7 +79,6 @@ public: private: PlatformMenuItemsType m_menuItems; - quintptr m_tag; QString m_text; QIcon m_icon; bool m_enabled; diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp index 0591522e55..e24c5f974e 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp @@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE QAndroidPlatformMenuItem::QAndroidPlatformMenuItem() { - m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick m_menu = 0; m_isVisible = true; m_isSeparator = false; @@ -54,16 +53,6 @@ QAndroidPlatformMenuItem::QAndroidPlatformMenuItem() m_isEnabled = true; } -void QAndroidPlatformMenuItem::setTag(quintptr tag) -{ - m_tag = tag; -} - -quintptr QAndroidPlatformMenuItem::tag() const -{ - return m_tag; -} - void QAndroidPlatformMenuItem::setText(const QString &text) { m_text = text; diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.h b/src/plugins/platforms/android/qandroidplatformmenuitem.h index be5240cfa6..b8782f995d 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.h +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.h @@ -49,8 +49,6 @@ class QAndroidPlatformMenuItem: public QPlatformMenuItem { public: QAndroidPlatformMenuItem(); - void setTag(quintptr tag) override; - quintptr tag() const override; void setText(const QString &text) override; QString text() const; @@ -86,7 +84,6 @@ public: void setIconSize(int size) override; private: - quintptr m_tag; QString m_text; QIcon m_icon; QAndroidPlatformMenu *m_menu; diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 3b59b293a5..3a79e32abe 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -85,7 +85,8 @@ private: # define PROFILE_SCOPE #endif -QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen() +QAndroidPlatformScreen::QAndroidPlatformScreen() + : QObject(), QPlatformScreen() { m_availableGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight); m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight); @@ -100,9 +101,6 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen() } m_physicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight); m_physicalSize.setWidth(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth); - m_redrawTimer.setSingleShot(true); - m_redrawTimer.setInterval(0); - connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw())); connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged); } @@ -136,6 +134,16 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const return 0; } +bool QAndroidPlatformScreen::event(QEvent *event) +{ + if (event->type() == QEvent::UpdateRequest) { + doRedraw(); + m_updatePending = false; + return true; + } + return QObject::event(event); +} + void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) { if (window->parent() && window->isRaster()) @@ -209,8 +217,10 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window) void QAndroidPlatformScreen::scheduleUpdate() { - if (!m_redrawTimer.isActive()) - m_redrawTimer.start(); + if (!m_updatePending) { + m_updatePending = true; + QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); + } } void QAndroidPlatformScreen::setDirty(const QRect &rect) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index 923c9e8832..f15aeae3fd 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -89,10 +89,12 @@ public slots: void setSize(const QSize &size); protected: + bool event(QEvent *event) override; + typedef QList<QAndroidPlatformWindow *> WindowStackType; WindowStackType m_windowStack; QRect m_dirtyRect; - QTimer m_redrawTimer; + bool m_updatePending = false; QRect m_availableGeometry; int m_depth; diff --git a/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp b/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp new file mode 100644 index 0000000000..a411d0f007 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidplatformvulkaninstance.h" + +QT_BEGIN_NAMESPACE + +QAndroidPlatformVulkanInstance::QAndroidPlatformVulkanInstance(QVulkanInstance *instance) + : m_instance(instance) +{ + m_lib.setFileName(QStringLiteral("vulkan")); + + if (!m_lib.load()) { + qWarning("Failed to load %s", qPrintable(m_lib.fileName())); + return; + } + + init(&m_lib); +} + +void QAndroidPlatformVulkanInstance::createOrAdoptInstance() +{ + initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_android_surface")); +} + +QAndroidPlatformVulkanInstance::~QAndroidPlatformVulkanInstance() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformvulkaninstance.h b/src/plugins/platforms/android/qandroidplatformvulkaninstance.h new file mode 100644 index 0000000000..67edcceed9 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformvulkaninstance.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDPLATFORMVULKANINSTANCE_H +#define QANDROIDPLATFORMVULKANINSTANCE_H + +#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h> +#include <QLibrary> + +QT_BEGIN_NAMESPACE + +class QAndroidPlatformVulkanInstance : public QBasicPlatformVulkanInstance +{ +public: + QAndroidPlatformVulkanInstance(QVulkanInstance *instance); + ~QAndroidPlatformVulkanInstance(); + + void createOrAdoptInstance() override; + +private: + QVulkanInstance *m_instance; + QLibrary m_lib; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDPLATFORMVULKANINSTANCE_H diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp new file mode 100644 index 0000000000..cc41a871f3 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidplatformvulkanwindow.h" +#include "qandroidplatformscreen.h" +#include "androidjnimain.h" +#include "qandroideventdispatcher.h" +#include "androiddeadlockprotector.h" + +#include <QSurfaceFormat> +#include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatformscreen.h> + +#include <android/native_window.h> +#include <android/native_window_jni.h> + +QT_BEGIN_NAMESPACE + +QAndroidPlatformVulkanWindow::QAndroidPlatformVulkanWindow(QWindow *window) + : QAndroidPlatformWindow(window), + m_nativeSurfaceId(-1), + m_nativeWindow(nullptr), + m_vkSurface(0), + m_createVkSurface(nullptr), + m_destroyVkSurface(nullptr) +{ +} + +QAndroidPlatformVulkanWindow::~QAndroidPlatformVulkanWindow() +{ + m_surfaceWaitCondition.wakeOne(); + lockSurface(); + if (m_nativeSurfaceId != -1) + QtAndroid::destroySurface(m_nativeSurfaceId); + clearSurface(); + unlockSurface(); +} + +void QAndroidPlatformVulkanWindow::setGeometry(const QRect &rect) +{ + if (rect == geometry()) + return; + + m_oldGeometry = geometry(); + + QAndroidPlatformWindow::setGeometry(rect); + if (m_nativeSurfaceId != -1) + QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect); + + QRect availableGeometry = screen()->availableGeometry(); + if (m_oldGeometry.width() == 0 + && m_oldGeometry.height() == 0 + && rect.width() > 0 + && rect.height() > 0 + && availableGeometry.width() > 0 + && availableGeometry.height() > 0) { + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size())); + } + + if (rect.topLeft() != m_oldGeometry.topLeft()) + repaint(QRegion(rect)); +} + +void QAndroidPlatformVulkanWindow::applicationStateChanged(Qt::ApplicationState state) +{ + QAndroidPlatformWindow::applicationStateChanged(state); + if (state <= Qt::ApplicationHidden) { + lockSurface(); + if (m_nativeSurfaceId != -1) { + QtAndroid::destroySurface(m_nativeSurfaceId); + m_nativeSurfaceId = -1; + } + clearSurface(); + unlockSurface(); + } +} + +QSurfaceFormat QAndroidPlatformVulkanWindow::format() const +{ + return window()->requestedFormat(); +} + +void QAndroidPlatformVulkanWindow::clearSurface() +{ + if (m_vkSurface && m_destroyVkSurface) { + m_destroyVkSurface(window()->vulkanInstance()->vkInstance(), m_vkSurface, nullptr); + m_vkSurface = 0; + } + + if (m_nativeWindow) { + ANativeWindow_release(m_nativeWindow); + m_nativeWindow = nullptr; + } +} + +void QAndroidPlatformVulkanWindow::sendExpose() +{ + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size()))); +} + +void QAndroidPlatformVulkanWindow::surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) +{ + Q_UNUSED(jniEnv); + Q_UNUSED(w); + Q_UNUSED(h); + + lockSurface(); + m_androidSurfaceObject = surface; + if (surface) + m_surfaceWaitCondition.wakeOne(); + unlockSurface(); + + if (surface) + sendExpose(); +} + +VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface() +{ + if (QAndroidEventDispatcherStopper::stopped()) + return &m_vkSurface; + + bool needsExpose = false; + if (!m_vkSurface) { + clearSurface(); + + QMutexLocker lock(&m_surfaceMutex); + if (m_nativeSurfaceId == -1) { + AndroidDeadlockProtector protector; + if (!protector.acquire()) + return &m_vkSurface; + const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint); + m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32); + m_surfaceWaitCondition.wait(&m_surfaceMutex); + } + + if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid()) + return &m_vkSurface; + + QJNIEnvironmentPrivate env; + m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object()); + + VkAndroidSurfaceCreateInfoKHR surfaceInfo; + memset(&surfaceInfo, 0, sizeof(surfaceInfo)); + surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surfaceInfo.window = m_nativeWindow; + QVulkanInstance *inst = window()->vulkanInstance(); + if (!inst) { + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + return &m_vkSurface; + } + if (!m_createVkSurface) { + m_createVkSurface = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>( + inst->getInstanceProcAddr("vkCreateAndroidSurfaceKHR")); + } + if (!m_destroyVkSurface) { + m_destroyVkSurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>( + inst->getInstanceProcAddr("vkDestroySurfaceKHR")); + } + VkResult err = m_createVkSurface(inst->vkInstance(), &surfaceInfo, nullptr, &m_vkSurface); + if (err != VK_SUCCESS) + qWarning("Failed to create Android VkSurface: %d", err); + + needsExpose = true; + } + + if (needsExpose) + sendExpose(); + + return &m_vkSurface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.h b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h new file mode 100644 index 0000000000..19eca98720 --- /dev/null +++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDPLATFORMVULKANWINDOW_H +#define QANDROIDPLATFORMVULKANWINDOW_H + +#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_ANDROID_KHR) +#error "vulkan.h included without Android WSI" +#endif + +#define VK_USE_PLATFORM_ANDROID_KHR + +#include <QWaitCondition> +#include <QtCore/private/qjni_p.h> + +#include "androidsurfaceclient.h" +#include "qandroidplatformwindow.h" + +#include "qandroidplatformvulkaninstance.h" + +QT_BEGIN_NAMESPACE + +class QAndroidPlatformVulkanWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient +{ +public: + explicit QAndroidPlatformVulkanWindow(QWindow *window); + ~QAndroidPlatformVulkanWindow(); + + void setGeometry(const QRect &rect) override; + QSurfaceFormat format() const override; + void applicationStateChanged(Qt::ApplicationState) override; + + VkSurfaceKHR *vkSurface(); + +protected: + void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override; + +private: + void sendExpose(); + void clearSurface(); + + int m_nativeSurfaceId; + ANativeWindow *m_nativeWindow; + QJNIObjectPrivate m_androidSurfaceObject; + QWaitCondition m_surfaceWaitCondition; + QSurfaceFormat m_format; + QRect m_oldGeometry; + VkSurfaceKHR m_vkSurface; + PFN_vkCreateAndroidSurfaceKHR m_createVkSurface; + PFN_vkDestroySurfaceKHR m_destroyVkSurface; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDPLATFORMVULKANWINDOW_H diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index 424cfefc6c..98b93508ce 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -56,7 +56,7 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) m_windowState = Qt::WindowNoState; static QAtomicInt winIdGenerator(1); m_windowId = winIdGenerator.fetchAndAddRelaxed(1); - setWindowState(window->windowState()); + setWindowState(window->windowStates()); } void QAndroidPlatformWindow::lower() @@ -98,7 +98,7 @@ void QAndroidPlatformWindow::setVisible(bool visible) QPlatformWindow::setVisible(visible); } -void QAndroidPlatformWindow::setWindowState(Qt::WindowState state) +void QAndroidPlatformWindow::setWindowState(Qt::WindowStates state) { if (m_windowState == state) return; diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h index 91cb1e76e6..f2e51bd3df 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/qandroidplatformwindow.h @@ -59,7 +59,7 @@ public: void setVisible(bool visible) override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; void setWindowFlags(Qt::WindowFlags flags) override; Qt::WindowFlags windowFlags() const; void setParent(const QPlatformWindow *window) override; @@ -91,7 +91,7 @@ protected: protected: Qt::WindowFlags m_windowFlags; - Qt::WindowState m_windowState; + Qt::WindowStates m_windowState; WId m_windowId; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index b15c486e9d..8b6dcb35a6 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -41,8 +41,6 @@ #include <QtGui/qaccessible.h> #include <private/qcore_mac_p.h> -#include <Carbon/Carbon.h> - QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY @@ -369,7 +367,7 @@ id getValueAttribute(QAccessibleInterface *interface) QString text; if (interface->state().passwordEdit) { // return round password replacement chars - text = QString(end, QChar(kBulletUnicode)); + text = QString(end, QChar(0x2022)); } else { // VoiceOver will read out the entire text string at once when returning // text as a value. For large text edits the size of the returned string diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h index 9ebb090989..c7277a47bf 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.h +++ b/src/plugins/platforms/cocoa/qcocoadrag.h @@ -55,7 +55,7 @@ public: QCocoaDrag(); ~QCocoaDrag(); - QMimeData *platformDropData() Q_DECL_OVERRIDE; + QMimeData *dragMimeData(); Qt::DropAction drag(QDrag *m_drag) Q_DECL_OVERRIDE; Qt::DropAction defaultAction(Qt::DropActions possibleActions, diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index c71e80d191..3bd0b05725 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -68,7 +68,7 @@ void QCocoaDrag::setLastMouseEvent(NSEvent *event, NSView *view) m_lastView = view; } -QMimeData *QCocoaDrag::platformDropData() +QMimeData *QCocoaDrag::dragMimeData() { if (m_drag) return m_drag->mimeData(); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index d2f985ec87..cc63213904 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -86,7 +86,6 @@ #include <qdebug.h> #include <AppKit/AppKit.h> -#include <Carbon/Carbon.h> QT_BEGIN_NAMESPACE @@ -285,7 +284,7 @@ bool QCocoaEventDispatcher::hasPendingEvents() { extern uint qGlobalPostedEventsCount(); extern bool qt_is_gui_used; //qapplication.cpp - return qGlobalPostedEventsCount() || (qt_is_gui_used && GetNumEventsInQueue(GetMainEventQueue())); + return qGlobalPostedEventsCount() || (qt_is_gui_used && !CFRunLoopIsWaiting(CFRunLoopGetMain())); } static bool IsMouseOrKeyEvent( NSEvent* event ) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 232e40769b..87efd97e79 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -55,8 +55,6 @@ #include <algorithm> -#include <Carbon/Carbon.h> - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window"); diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm index 1ef7f11011..5fa062bbe0 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -72,14 +72,6 @@ static const Qt::KeyboardModifiers ModsTbl[] = { bool qt_mac_eat_unicode_key = false; -Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b) -{ - static bool secure = false; - if (b != secure){ - b ? EnableSecureEventInput() : DisableSecureEventInput(); - secure = b; - } -} /* key maps */ struct qt_mac_enum_mapper diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index b77071536b..903d41220a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -55,11 +55,6 @@ public: QCocoaMenu(); ~QCocoaMenu(); - void setTag(quintptr tag) Q_DECL_OVERRIDE - { m_tag = tag; } - quintptr tag() const Q_DECL_OVERRIDE - { return m_tag; } - void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE; void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE; void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE; @@ -103,7 +98,6 @@ private: QList<QCocoaMenuItem *> m_menuItems; NSMenu *m_nativeMenu; NSMenuItem *m_attachedItem; - quintptr m_tag; bool m_enabled:1; bool m_parentEnabled:1; bool m_visible:1; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 8e47974d12..ada6334cf4 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -259,7 +259,6 @@ QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : m_attachedItem(0), - m_tag(0), m_enabled(true), m_parentEnabled(true), m_visible(true), diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 23f788687c..53862d0484 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -78,11 +78,6 @@ public: QCocoaMenuItem(); ~QCocoaMenuItem(); - void setTag(quintptr tag) Q_DECL_OVERRIDE - { m_tag = tag; } - quintptr tag() const Q_DECL_OVERRIDE - { return m_tag; } - void setText(const QString &text) Q_DECL_OVERRIDE; void setIcon(const QIcon &icon) Q_DECL_OVERRIDE; void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; @@ -129,7 +124,6 @@ private: #ifndef QT_NO_SHORTCUT QKeySequence m_shortcut; #endif - quintptr m_tag; int m_iconSize; bool m_textSynced:1; bool m_isVisible:1; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 21f2b4de85..d135b244e0 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -95,7 +95,6 @@ QCocoaMenuItem::QCocoaMenuItem() : m_itemView(nil), m_menu(NULL), m_role(NoRole), - m_tag(0), m_iconSize(16), m_textSynced(false), m_isVisible(true), diff --git a/src/plugins/platforms/cocoa/qcocoamimetypes.mm b/src/plugins/platforms/cocoa/qcocoamimetypes.mm index 093f86da6e..f7662a92a4 100644 --- a/src/plugins/platforms/cocoa/qcocoamimetypes.mm +++ b/src/plugins/platforms/cocoa/qcocoamimetypes.mm @@ -105,101 +105,9 @@ QList<QByteArray> QMacPasteboardMimeTraditionalMacPlainText::convertFromMime(con return ret; } -class QMacPasteboardMimeTiff : public QMacInternalPasteboardMime { -public: - QMacPasteboardMimeTiff() : QMacInternalPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeTiff::convertorName() -{ - return QLatin1String("Tiff"); -} - -QString QMacPasteboardMimeTiff::flavorFor(const QString &mime) -{ - if (mime.startsWith(QLatin1String("application/x-qt-image"))) - return QLatin1String("public.tiff"); - return QString(); -} - -QString QMacPasteboardMimeTiff::mimeFor(QString flav) -{ - if (flav == QLatin1String("public.tiff")) - return QLatin1String("application/x-qt-image"); - return QString(); -} - -bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav) -{ - return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image"); -} - -QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) -{ - if (data.count() > 1) - qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data"); - QVariant ret; - if (!canConvert(mime, flav)) - return ret; - const QByteArray &a = data.first(); - QCFType<CGImageRef> image; - QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0, - reinterpret_cast<const UInt8 *>(a.constData()), - a.size(), kCFAllocatorNull); - QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0); - image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - if (image != 0) - ret = QVariant(qt_mac_toQImage(image)); - return ret; -} - -QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav) -{ - QList<QByteArray> ret; - if (!canConvert(mime, flav)) - return ret; - - QImage img = qvariant_cast<QImage>(variant); - QCFType<CGImageRef> cgimage = qt_mac_toCGImage(img); - - QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0); - QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0); - if (imageDestination != 0) { - CFTypeRef keys[2]; - QCFType<CFTypeRef> values[2]; - QCFType<CFDictionaryRef> options; - keys[0] = kCGImagePropertyPixelWidth; - keys[1] = kCGImagePropertyPixelHeight; - int width = img.width(); - int height = img.height(); - values[0] = CFNumberCreate(0, kCFNumberIntType, &width); - values[1] = CFNumberCreate(0, kCFNumberIntType, &height); - options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys), - reinterpret_cast<const void **>(values), 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CGImageDestinationAddImage(imageDestination, cgimage, options); - CGImageDestinationFinalize(imageDestination); - } - QByteArray ar(CFDataGetLength(data), 0); - CFDataGetBytes(data, - CFRangeMake(0, ar.size()), - reinterpret_cast<UInt8 *>(ar.data())); - ret.append(ar); - return ret; -} - void QCocoaMimeTypes::initializeMimeTypes() { new QMacPasteboardMimeTraditionalMacPlainText; - new QMacPasteboardMimeTiff; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index d2345f9abc..ad2b27999b 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -330,7 +330,7 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const case IconPixmapSizes: return QVariant::fromValue(QCocoaFileIconEngine::availableIconSizes()); case QPlatformTheme::PasswordMaskCharacter: - return QVariant(QChar(kBulletUnicode)); + return QVariant(QChar(0x2022)); case QPlatformTheme::UiEffects: return QVariant(int(HoverEffect)); default: diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 567eb7438b..586e59bff4 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -168,7 +168,7 @@ public: void hide(bool becauseOfAncestor = false); void setVisible(bool visible) Q_DECL_OVERRIDE; void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; - void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE; void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; void setWindowFilePath(const QString &filePath) Q_DECL_OVERRIDE; void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; @@ -292,7 +292,7 @@ protected: void removeChildWindow(QCocoaWindow *child); Qt::WindowState windowState() const; - void applyWindowState(Qt::WindowState newState); + void applyWindowState(Qt::WindowStates newState); void toggleMaximized(); void toggleFullScreen(); bool isTransitioningToFullScreen() const; @@ -313,7 +313,7 @@ public: // for QNSView bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy Qt::WindowFlags m_windowFlags; - Qt::WindowState m_lastReportedWindowState; + Qt::WindowStates m_lastReportedWindowState; Qt::WindowModality m_windowModality; QPointer<QWindow> m_enterLeaveTargetWindow; bool m_windowUnderMouse; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b453da818f..cfa7541dfa 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -766,7 +766,7 @@ void QCocoaWindow::setVisible(bool visible) // setWindowState might have been called while the window was hidden and // will not change the NSWindow state in that case. Sync up here: - applyWindowState(window()->windowState()); + applyWindowState(window()->windowStates()); if (window()->windowState() != Qt::WindowMinimized) { if ((window()->modality() == Qt::WindowModal @@ -1014,7 +1014,7 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) m_windowFlags = flags; } -void QCocoaWindow::setWindowState(Qt::WindowState state) +void QCocoaWindow::setWindowState(Qt::WindowStates state) { if (window()->isVisible()) applyWindowState(state); // Window state set for hidden windows take effect when show() is called @@ -1823,9 +1823,11 @@ QRect QCocoaWindow::nativeWindowGeometry() const updated yet, so window()->windowState() will reflect the previous state that was reported to QtGui. */ -void QCocoaWindow::applyWindowState(Qt::WindowState newState) +void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState) { const Qt::WindowState currentState = windowState(); + const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState); + if (newState == currentState) return; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 296b6a28cc..bbdf9ad44f 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -2066,7 +2066,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); if (nativeDrag->currentDrag()) { // The drag was started from within the application - response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed); + response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed); [self updateCursorFromDragResponse:response drag:nativeDrag]; } else { QCocoaDropData mimeData([sender draggingPasteboard]); @@ -2110,7 +2110,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); if (nativeDrag->currentDrag()) { // The drag was started from within the application - response = QWindowSystemInterface::handleDrop(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed); + response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed); } else { QCocoaDropData mimeData([sender draggingPasteboard]); response = QWindowSystemInterface::handleDrop(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed); diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro index 224f122fc4..87405ae19f 100644 --- a/src/plugins/platforms/direct2d/direct2d.pro +++ b/src/plugins/platforms/direct2d/direct2d.pro @@ -5,6 +5,8 @@ QT += \ eventdispatcher_support-private accessibility_support-private \ fontdatabase_support-private theme_support-private +qtConfig(vulkan): QT += vulkan_support-private + LIBS += -ldwmapi -ld2d1 -ld3d11 -ldwrite -lVersion -lgdi32 include(../windows/windows.pri) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h index 513a5063fb..be5524cba3 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h @@ -45,7 +45,7 @@ #include <QtCore/QLoggingCategory> #include <QtCore/QFunctionPointer> -typedef const char *(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC) (); +typedef QByteArray (EGLAPIENTRYP PFNQGSGETDISPLAYSPROC) (); typedef void (EGLAPIENTRYP PFNQGSSETDISPLAYPROC) (uint screen); QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp index 4546088327..7654034f85 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp @@ -110,6 +110,11 @@ uint QEglFSEmulatorScreen::id() const return m_id; } +QString QEglFSEmulatorScreen::name() const +{ + return m_description; +} + void QEglFSEmulatorScreen::initFromJsonObject(const QJsonObject &description) { QJsonValue value; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h index 3e5113c9c2..c4994720fa 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h @@ -62,6 +62,7 @@ public: qreal refreshRate() const override; Qt::ScreenOrientation nativeOrientation() const override; Qt::ScreenOrientation orientation() const override; + QString name() const override; uint id() const; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp index 3951f46a82..6920a81e94 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -173,6 +173,28 @@ qreal QEglFSKmsScreen::refreshRate() const return refresh > 0 ? refresh : 60; } +QVector<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const +{ + QVector<QPlatformScreen::Mode> list; + list.reserve(m_output.modes.size()); + + for (const drmModeModeInfo &info : qAsConst(m_output.modes)) + list.append({QSize(info.hdisplay, info.vdisplay), + qreal(info.vrefresh > 0 ? info.vrefresh : 60)}); + + return list; +} + +int QEglFSKmsScreen::currentMode() const +{ + return m_output.mode; +} + +int QEglFSKmsScreen::preferredMode() const +{ + return m_output.preferred_mode; +} + QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const { return m_output.subpixelAntialiasingTypeHint(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h index 80bbb0c7f1..c90e917f0a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -77,6 +77,11 @@ public: QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; } void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; } + QVector<QPlatformScreen::Mode> modes() const override; + + int currentMode() const override; + int preferredMode() const override; + QKmsDevice *device() const { return m_device; } void destroySurface(); diff --git a/src/plugins/platforms/haiku/qhaikuwindow.cpp b/src/plugins/platforms/haiku/qhaikuwindow.cpp index 4634012eda..e19918d7bf 100644 --- a/src/plugins/platforms/haiku/qhaikuwindow.cpp +++ b/src/plugins/platforms/haiku/qhaikuwindow.cpp @@ -205,26 +205,23 @@ void QHaikuWindow::requestActivateWindow() m_window->Activate(true); } -void QHaikuWindow::setWindowState(Qt::WindowState state) +void QHaikuWindow::setWindowState(Qt::WindowStates state) { if (m_windowState == state) return; - const Qt::WindowState oldState = m_windowState; + const Qt::WindowStates oldState = m_windowState; m_windowState = state; - if (m_windowState == Qt::WindowMaximized) { - m_window->zoomByQt(); - } else if (m_windowState == Qt::WindowMinimized) { + if (m_windowState & Qt::WindowMinimized) m_window->Minimize(true); - } else if (m_windowState == Qt::WindowNoState) { - if (oldState == Qt::WindowMaximized) - m_window->zoomByQt(); // undo zoom - - if (oldState == Qt::WindowMinimized) - m_window->Minimize(false); // undo minimize - } + else if (m_windowState & Qt::WindowMaximized) + m_window->zoomByQt(); + else if (oldState & Qt::WindowMinimized) + m_window->Minimize(false); // undo minimize + else if (oldState & Qt::WindowMaximized) + m_window->zoomByQt(); // undo zoom } void QHaikuWindow::setWindowFlags(Qt::WindowFlags flags) diff --git a/src/plugins/platforms/haiku/qhaikuwindow.h b/src/plugins/platforms/haiku/qhaikuwindow.h index 75403fb421..5bfb99e532 100644 --- a/src/plugins/platforms/haiku/qhaikuwindow.h +++ b/src/plugins/platforms/haiku/qhaikuwindow.h @@ -94,7 +94,7 @@ public: BWindow* nativeHandle() const; void requestActivateWindow() Q_DECL_OVERRIDE; - void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE; void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; @@ -120,7 +120,7 @@ private Q_SLOTS: void haikuDrawRequest(const QRect &rect); private: - Qt::WindowState m_windowState; + Qt::WindowStates m_windowState; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm index ef3b453bbf..15deb3332e 100644 --- a/src/plugins/platforms/ios/qiosclipboard.mm +++ b/src/plugins/platforms/ios/qiosclipboard.mm @@ -227,7 +227,19 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) if (uti.isEmpty() || !converter->canConvert(mimeType, uti)) continue; - QByteArray byteArray = converter->convertFromMime(mimeType, mimeData->data(mimeType), uti).first(); + QVariant mimeDataAsVariant; + if (mimeData->hasImage()) { + mimeDataAsVariant = mimeData->imageData(); + } else if (mimeData->hasUrls()) { + QVariantList urlList; + for (QUrl url : mimeData->urls()) + urlList << url; + mimeDataAsVariant = QVariant(urlList); + } else { + mimeDataAsVariant = QVariant(mimeData->data(mimeType)); + } + + QByteArray byteArray = converter->convertFromMime(mimeType, mimeDataAsVariant, uti).first(); NSData *nsData = [NSData dataWithBytes:byteArray.constData() length:byteArray.size()]; [pbItem setValue:nsData forKey:uti.toNSString()]; break; diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h index b7371a5f49..61cadab56d 100644 --- a/src/plugins/platforms/ios/qiosmenu.h +++ b/src/plugins/platforms/ios/qiosmenu.h @@ -56,9 +56,6 @@ class QIOSMenuItem : public QPlatformMenuItem public: QIOSMenuItem(); - void setTag(quintptr tag) Q_DECL_OVERRIDE; - quintptr tag()const Q_DECL_OVERRIDE; - void setText(const QString &text) Q_DECL_OVERRIDE; void setIcon(const QIcon &) Q_DECL_OVERRIDE {} void setMenu(QPlatformMenu *) Q_DECL_OVERRIDE; @@ -74,7 +71,6 @@ public: void setEnabled(bool enabled) Q_DECL_OVERRIDE; void setIconSize(int) Q_DECL_OVERRIDE {} - quintptr m_tag; bool m_visible; QString m_text; MenuRole m_role; @@ -97,9 +93,6 @@ public: void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE; void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {} - void setTag(quintptr tag) Q_DECL_OVERRIDE; - quintptr tag()const Q_DECL_OVERRIDE; - void setText(const QString &) Q_DECL_OVERRIDE; void setIcon(const QIcon &) Q_DECL_OVERRIDE {} void setEnabled(bool enabled) Q_DECL_OVERRIDE; @@ -121,7 +114,6 @@ protected: bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; private: - quintptr m_tag; bool m_enabled; bool m_visible; QString m_text; diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 01cb3badea..6c70676a31 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -259,7 +259,6 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; QIOSMenuItem::QIOSMenuItem() : QPlatformMenuItem() - , m_tag(0) , m_visible(true) , m_text(QString()) , m_role(MenuRole(0)) @@ -269,16 +268,6 @@ QIOSMenuItem::QIOSMenuItem() { } -void QIOSMenuItem::setTag(quintptr tag) -{ - m_tag = tag; -} - -quintptr QIOSMenuItem::tag() const -{ - return m_tag; -} - void QIOSMenuItem::setText(const QString &text) { m_text = QPlatformTheme::removeMnemonics(text); @@ -319,7 +308,6 @@ void QIOSMenuItem::setEnabled(bool enabled) QIOSMenu::QIOSMenu() : QPlatformMenu() - , m_tag(0) , m_enabled(true) , m_visible(false) , m_text(QString()) @@ -371,16 +359,6 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *) } } -void QIOSMenu::setTag(quintptr tag) -{ - m_tag = tag; -} - -quintptr QIOSMenu::tag() const -{ - return m_tag; -} - void QIOSMenu::setText(const QString &text) { m_text = text; diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index eab6792266..671e0f0c28 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -879,9 +879,10 @@ - (UITextPosition *)closestPositionToPoint:(CGPoint)point { - // No API in Qt for determining this. Use sensible default instead: - Q_UNUSED(point); - return [QUITextPosition positionWithIndex:[self currentImeState:Qt::ImCursorPosition].toInt()]; + QPointF p = QPointF::fromCGPoint(point); + const QTransform mapToLocal = QGuiApplication::inputMethod()->inputItemTransform().inverted(); + int textPos = QInputMethod::queryFocusObject(Qt::ImCursorPosition, p * mapToLocal).toInt(); + return [QUITextPosition positionWithIndex:textPos]; } - (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index c47b6d68b1..a4c151ed8b 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -176,8 +176,8 @@ return; // Re-apply window states to update geometry - if (window->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized)) - window->handle()->setWindowState(window->windowState()); + if (window->windowStates() & (Qt::WindowFullScreen | Qt::WindowMaximized)) + window->handle()->setWindowState(window->windowStates()); } // Even if the root view controller has both wantsFullScreenLayout and diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 81fad420f6..da8a6aabdc 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -62,7 +62,7 @@ public: void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; - void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE; void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE; void setVisible(bool visible) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 8ff0dfbd5f..4e6d48423d 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -73,7 +73,7 @@ QIOSWindow::QIOSWindow(QWindow *window) m_normalGeometry = initialGeometry(window, QPlatformWindow::geometry(), screen()->availableGeometry().width(), screen()->availableGeometry().height()); - setWindowState(window->windowState()); + setWindowState(window->windowStates()); setOpacity(window->opacity()); Qt::ScreenOrientation initialOrientation = window->contentOrientation(); @@ -229,7 +229,7 @@ bool QIOSWindow::isExposed() const && window()->isVisible() && !window()->geometry().isEmpty(); } -void QIOSWindow::setWindowState(Qt::WindowState state) +void QIOSWindow::setWindowState(Qt::WindowStates state) { // Update the QWindow representation straight away, so that // we can update the statusbar visibility based on the new @@ -239,25 +239,15 @@ void QIOSWindow::setWindowState(Qt::WindowState state) if (window()->isTopLevel() && window()->isVisible() && window()->isActive()) [m_view.qtViewController updateProperties]; - switch (state) { - case Qt::WindowNoState: - applyGeometry(m_normalGeometry); - break; - case Qt::WindowMaximized: + if (state & Qt::WindowMinimized) + applyGeometry(QRect()); + else if (state & Qt::WindowFullScreen) + applyGeometry(screen()->geometry()); + else if (state & Qt::WindowMaximized) applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ? screen()->geometry() : screen()->availableGeometry()); - break; - case Qt::WindowFullScreen: - applyGeometry(screen()->geometry()); - break; - case Qt::WindowMinimized: - applyGeometry(QRect()); - break; - case Qt::WindowActive: - Q_UNREACHABLE(); - default: - Q_UNREACHABLE(); - } + else + applyGeometry(m_normalGeometry); } void QIOSWindow::setParent(const QPlatformWindow *parentWindow) diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp index adc8ae652a..369073a70e 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp +++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp @@ -785,8 +785,16 @@ void QMirClientWindow::handleSurfaceStateChanged(Qt::WindowState state) QWindowSystemInterface::handleWindowStateChanged(window(), state); } -void QMirClientWindow::setWindowState(Qt::WindowState state) +void QMirClientWindow::setWindowState(Qt::WindowStates states) { + Qt::WindowState state = Qt::WindowNoState; + if (states & Qt::WindowMinimized) + state = Qt::WindowMinimized; + else if (states & Qt::WindowFullScreen) + state = Qt::WindowFullScreen; + else if (states & Qt::WindowMaximized) + state = Qt::WindowMaximized; + QMutexLocker lock(&mMutex); qCDebug(mirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state)); diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h index 324e7691ff..6c5695d62f 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.h +++ b/src/plugins/platforms/mirclient/qmirclientwindow.h @@ -73,7 +73,7 @@ public: WId winId() const override; QRect geometry() const override; void setGeometry(const QRect&) override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; void setWindowFlags(Qt::WindowFlags flags) override; void setVisible(bool visible) override; void setWindowTitle(const QString &title) override; diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index 72d6f16d26..1a9d65972d 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -75,7 +75,6 @@ public: class QOffscreenDrag : public QPlatformDrag { public: - QMimeData *platformDropData() Q_DECL_OVERRIDE { return 0; } Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE { return Qt::IgnoreAction; } }; #endif diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp index 81f262f9ed..832e94034d 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp @@ -56,7 +56,7 @@ QOffscreenWindow::QOffscreenWindow(QWindow *window) if (window->windowState() == Qt::WindowNoState) setGeometry(window->geometry()); else - setWindowState(window->windowState()); + setWindowState(window->windowStates()); QWindowSystemInterface::flushWindowSystemEvents(); @@ -166,26 +166,19 @@ void QOffscreenWindow::setFrameMarginsEnabled(bool enabled) } } -void QOffscreenWindow::setWindowState(Qt::WindowState state) +void QOffscreenWindow::setWindowState(Qt::WindowStates state) { - setFrameMarginsEnabled(state != Qt::WindowFullScreen); + setFrameMarginsEnabled(!(state & Qt::WindowFullScreen)); m_positionIncludesFrame = false; - switch (state) { - case Qt::WindowFullScreen: + if (state & Qt::WindowMinimized) + ; // nothing to do + else if (state & Qt::WindowFullScreen) setGeometryImpl(screen()->geometry()); - break; - case Qt::WindowMaximized: + else if (state & Qt::WindowMaximized) setGeometryImpl(screen()->availableGeometry().adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom())); - break; - case Qt::WindowMinimized: - break; - case Qt::WindowNoState: + else setGeometryImpl(m_normalGeometry); - break; - default: - break; - } QWindowSystemInterface::handleWindowStateChanged(window(), state); } diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h index f75458eb8e..0dced9680a 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.h +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h @@ -54,7 +54,7 @@ public: ~QOffscreenWindow(); void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; - void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowStates states) Q_DECL_OVERRIDE; QMargins frameMargins() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 30288ccb20..2253e3b23d 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -586,7 +586,7 @@ void QQnxWindow::setFocus(screen_window_t newFocusWindow) } } -void QQnxWindow::setWindowState(Qt::WindowState state) +void QQnxWindow::setWindowState(Qt::WindowStates state) { qWindowDebug() << "state =" << state; @@ -749,32 +749,19 @@ void QQnxWindow::updateZorder(screen_window_t window, int &topZorder) void QQnxWindow::applyWindowState() { - switch (m_windowState) { - - // WindowActive is not an accepted parameter according to the docs - case Qt::WindowActive: - return; - - case Qt::WindowMinimized: + if (m_windowState & Qt::WindowMinimized) { minimize(); if (m_unmaximizedGeometry.isValid()) setGeometry(m_unmaximizedGeometry); else setGeometry(m_screen->geometry()); - - break; - - case Qt::WindowMaximized: - case Qt::WindowFullScreen: + } else if (m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen)) { m_unmaximizedGeometry = geometry(); - setGeometry(m_windowState == Qt::WindowMaximized ? m_screen->availableGeometry() : m_screen->geometry()); - break; - - case Qt::WindowNoState: - if (m_unmaximizedGeometry.isValid()) - setGeometry(m_unmaximizedGeometry); - break; + setGeometry(m_windowState & Qt::WindowFullScreen ? m_screen->geometry() + : m_screen->availableGeometry()); + } else if (m_unmaximizedGeometry.isValid()) { + setGeometry(m_unmaximizedGeometry); } } diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index e248e04462..f96edc49e4 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -85,7 +85,7 @@ public: void raise() override; void lower() override; void requestActivateWindow() override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; void setExposed(bool exposed); void propagateSizeHints() override; @@ -141,7 +141,7 @@ private: bool m_visible; bool m_exposed; QRect m_unmaximizedGeometry; - Qt::WindowState m_windowState; + Qt::WindowStates m_windowState; QString m_mmRendererWindowName; screen_window_t m_mmRendererWindow; diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index d5cd9ac6db..d9c3d6ac14 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -61,40 +61,7 @@ static inline T *coTaskMemAllocArray(int size) /**************************************************************\ * AccessibleApplication * **************************************************************/ -// IUnknown -HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) { - qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IUnknown"; - *iface = static_cast<IUnknown *>(this); - } else if (id == IID_IAccessibleApplication) { - qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IAccessibleApplication"; - *iface = static_cast<IAccessibleApplication*>(this); - } - - if (*iface) { - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef() -{ - return ++m_ref; -} -ULONG STDMETHODCALLTYPE AccessibleApplication::Release() -{ - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; -} - -/* IAccessibleApplication */ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name) { const QString appName = QGuiApplication::applicationName(); @@ -127,40 +94,11 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][ **************************************************************/ AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets, QAccessible::Relation relation) - : m_targets(targets), m_relation(relation), m_ref(1) + : m_targets(targets), m_relation(relation) { Q_ASSERT(m_targets.count()); } -/* IUnknown */ -HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown || id == IID_IAccessibleRelation) - *iface = static_cast<IUnknown *>(this); - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef() -{ - return ++m_ref; -} - -ULONG STDMETHODCALLTYPE AccessibleRelation::Release() -{ - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; -} - /* IAccessibleRelation */ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType( /* [retval][out] */ BSTR *relationType) @@ -237,56 +175,53 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface) { + *iface = nullptr; QAccessibleInterface *accessible = accessibleInterface(); if (!accessible) return E_NOINTERFACE; - HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); - if (!SUCCEEDED(hr)) { - if (id == IID_IServiceProvider) { - *iface = static_cast<IServiceProvider *>(this); - } else if (id == IID_IAccessible2) { - *iface = static_cast<IAccessible2 *>(this); - } else if (id == IID_IAccessibleAction) { - if (accessible->actionInterface()) - *iface = static_cast<IAccessibleAction *>(this); - } else if (id == IID_IAccessibleComponent) { - *iface = static_cast<IAccessibleComponent *>(this); - } else if (id == IID_IAccessibleEditableText) { - if (accessible->editableTextInterface() || - accessible->role() == QAccessible::EditableText) - { - *iface = static_cast<IAccessibleEditableText *>(this); - } - } else if (id == IID_IAccessibleHyperlink) { - //*iface = static_cast<IAccessibleHyperlink *>(this); - } else if (id == IID_IAccessibleHypertext) { - //*iface = static_cast<IAccessibleHypertext *>(this); - } else if (id == IID_IAccessibleImage) { - //*iface = static_cast<IAccessibleImage *>(this); - } else if (id == IID_IAccessibleTable) { - //*iface = static_cast<IAccessibleTable *>(this); // not supported - } else if (id == IID_IAccessibleTable2) { - if (accessible->tableInterface()) - *iface = static_cast<IAccessibleTable2 *>(this); - } else if (id == IID_IAccessibleTableCell) { - if (accessible->tableCellInterface()) - *iface = static_cast<IAccessibleTableCell *>(this); - } else if (id == IID_IAccessibleText) { - if (accessible->textInterface()) - *iface = static_cast<IAccessibleText *>(this); - } else if (id == IID_IAccessibleValue) { - if (accessible->valueInterface()) - *iface = static_cast<IAccessibleValue *>(this); - } - if (*iface) { - AddRef(); - hr = S_OK; - } else { - hr = E_NOINTERFACE; + if (SUCCEEDED(QWindowsMsaaAccessible::QueryInterface(id, iface)) + || qWindowsComQueryInterface<IServiceProvider>(this, id, iface) + || qWindowsComQueryInterface<IAccessible2>(this, id, iface) + || qWindowsComQueryInterface<IAccessibleComponent>(this, id, iface)) { + return S_OK; + } + + if (id == IID_IAccessibleAction) { + if (accessible->actionInterface()) + *iface = static_cast<IAccessibleAction *>(this); + } else if (id == IID_IAccessibleEditableText) { + if (accessible->editableTextInterface() || + accessible->role() == QAccessible::EditableText) + { + *iface = static_cast<IAccessibleEditableText *>(this); } + } else if (id == IID_IAccessibleHyperlink) { + //*iface = static_cast<IAccessibleHyperlink *>(this); + } else if (id == IID_IAccessibleHypertext) { + //*iface = static_cast<IAccessibleHypertext *>(this); + } else if (id == IID_IAccessibleImage) { + //*iface = static_cast<IAccessibleImage *>(this); + } else if (id == IID_IAccessibleTable) { + //*iface = static_cast<IAccessibleTable *>(this); // not supported + } else if (id == IID_IAccessibleTable2) { + if (accessible->tableInterface()) + *iface = static_cast<IAccessibleTable2 *>(this); + } else if (id == IID_IAccessibleTableCell) { + if (accessible->tableCellInterface()) + *iface = static_cast<IAccessibleTableCell *>(this); + } else if (id == IID_IAccessibleText) { + if (accessible->textInterface()) + *iface = static_cast<IAccessibleText *>(this); + } else if (id == IID_IAccessibleValue) { + if (accessible->valueInterface()) + *iface = static_cast<IAccessibleValue *>(this); } - return hr; + if (*iface) { + AddRef(); + return S_OK; + } + return E_NOINTERFACE; } @@ -1593,7 +1528,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidServic return E_POINTER; Q_UNUSED(guidService); *iface = 0; - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << IIDToString(riid); + qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << QWindowsAccessibleGuid(riid); if (guidService == IID_IAccessible) { @@ -1692,45 +1627,6 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface* return count > 0 ? S_OK : S_FALSE; } -#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) - -QByteArray QWindowsIA2Accessible::IIDToString(REFIID id) -{ - QByteArray strGuid = QWindowsMsaaAccessible::IIDToString(id); - if (!strGuid.isEmpty()) - return strGuid; - - IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue); - - // else... -#if 0 // Can be useful for debugging, but normally we'd like to reduce the noise a bit... - OLECHAR szGuid[39]={0}; - ::StringFromGUID2(id, szGuid, 39); - strGuid.reserve(40); - ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL); - strGuid[38] = '\0'; -#endif - return strGuid; -} - // Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast<IA2Role>(QAccessible::ColorChooser)); Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast<IA2Role>(QAccessible::Footer)); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index bc5f5be60f..d5c67f8b51 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -42,6 +42,7 @@ #include <QtCore/QtConfig> #ifndef QT_NO_ACCESSIBILITY +#include "qwindowscombase.h" #include "qwindowsmsaaaccessible.h" #include "comutils.h" @@ -249,7 +250,6 @@ private: HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0); HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount); - QByteArray IIDToString(REFIID id); QString textForRange(int startOffset, int endOffset) const; void replaceTextFallback(long startOffset, long endOffset, const QString &txt); @@ -258,28 +258,18 @@ private: /**************************************************************\ * AccessibleApplication * **************************************************************/ -class AccessibleApplication : public IAccessibleApplication +class AccessibleApplication : public QWindowsComBase<IAccessibleApplication> { public: - AccessibleApplication() : m_ref(1) - { - - } + AccessibleApplication() {} virtual ~AccessibleApplication() {} - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - /* IAccessibleApplication */ HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name); HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version); HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name); HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version); -private: - ULONG m_ref; }; @@ -287,7 +277,7 @@ private: /**************************************************************\ * AccessibleRelation * **************************************************************/ -class AccessibleRelation : public IAccessibleRelation +class AccessibleRelation : public QWindowsComBase<IAccessibleRelation> { public: AccessibleRelation(const QList<QAccessibleInterface *> &targets, @@ -295,11 +285,6 @@ public: virtual ~AccessibleRelation() {} - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - /* IAccessibleRelation */ HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType); HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType); @@ -341,7 +326,6 @@ private: QList<QAccessibleInterface *> m_targets; QAccessible::Relation m_relation; - ULONG m_ref; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 25b1577772..308ff59c49 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -42,6 +42,7 @@ #include "qwindowsmsaaaccessible.h" #include "qwindowsaccessibility.h" +#include "qwindowscombase.h" #include <oleacc.h> #include <servprov.h> #include <winuser.h> @@ -71,61 +72,22 @@ QT_BEGIN_NAMESPACE -class QWindowsEnumerate : public IEnumVARIANT +class QWindowsEnumerate : public QWindowsComBase<IEnumVARIANT> { public: - QWindowsEnumerate(const QVector<int> &a) - : ref(0), current(0),array(a) - { - } - + QWindowsEnumerate(const QVector<int> &a) : QWindowsComBase<IEnumVARIANT>(0), current(0),array(a) {} virtual ~QWindowsEnumerate() {} - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum); HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched); HRESULT STDMETHODCALLTYPE Reset(); HRESULT STDMETHODCALLTYPE Skip(unsigned long celt); private: - ULONG ref; ULONG current; QVector<int> array; }; -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) - *iface = static_cast<IUnknown *>(this); - else if (id == IID_IEnumVARIANT) - *iface = static_cast<IEnumVARIANT *>(this); - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef() -{ - return ++ref; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release() -{ - if (!--ref) { - delete this; - return 0; - } - return ref; -} - HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum) { QWindowsEnumerate *penum = 0; @@ -193,29 +155,17 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVOID *iface) { - *iface = 0; - - QByteArray strIID = IIDToString(id); - if (!strIID.isEmpty()) { - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - IID:" - << strIID << ", iface:" << accessibleInterface(); + *iface = nullptr; + const bool result = qWindowsComQueryUnknownInterfaceMulti<AccessibleBase>(this, id, iface) + || qWindowsComQueryInterface<IDispatch>(this, id, iface) + || qWindowsComQueryInterface<IAccessible>(this, id, iface) + || qWindowsComQueryInterface<IOleWindow>(this, id, iface); + + if (result) { + qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - " + << QWindowsAccessibleGuid(id) << ", iface:" << accessibleInterface(); } - if (id == IID_IUnknown) { - *iface = static_cast<IUnknown *>(static_cast<IDispatch *>(this)); - } else if (id == IID_IDispatch) { - *iface = static_cast<IDispatch *>(this); - } else if (id == IID_IAccessible) { - *iface = static_cast<IAccessible *>(this); - } else if (id == IID_IOleWindow) { - *iface = static_cast<IOleWindow *>(this); - } - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; + return result ? S_OK : E_NOINTERFACE; } ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::AddRef() @@ -1209,16 +1159,66 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL) return S_OK; } -#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) -QByteArray QWindowsMsaaAccessible::IIDToString(REFIID id) +const char *QWindowsAccessibleGuid::iidToString(const GUID &id) { - IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow); + const char *result = nullptr; + if (id == IID_IUnknown) + result = "IID_IUnknown"; + else if (id == IID_IDispatch) + result = "IID_IDispatch"; + else if (id == IID_IAccessible) + result = "IID_IAccessible"; + else if (id == IID_IOleWindow) + result = "IID_IOleWindow"; + else if (id == IID_IServiceProvider) + result = "IID_IServiceProvider"; +#ifndef Q_CC_MINGW + else if (id == IID_IAccessible2) + result = "IID_IAccessible2"; + else if (id == IID_IAccessibleAction) + result = "IID_IAccessibleAction"; + else if (id == IID_IAccessibleApplication) + result = "IID_IAccessibleApplication"; + else if (id == IID_IAccessibleComponent) + result = "IID_IAccessibleComponent"; + else if (id == IID_IAccessibleEditableText) + result = "IID_IAccessibleEditableText"; + else if (id == IID_IAccessibleHyperlink) + result = "IID_IAccessibleHyperlink"; + else if (id == IID_IAccessibleHypertext) + result = "IID_IAccessibleHypertext"; + else if (id == IID_IAccessibleImage) + result = "IID_IAccessibleImage"; + else if (id == IID_IAccessibleRelation) + result = "IID_IAccessibleRelation"; + else if (id == IID_IAccessibleTable) + result = "IID_IAccessibleTable"; + else if (id == IID_IAccessibleTable2) + result = "IID_IAccessibleTable2"; + else if (id == IID_IAccessibleTableCell) + result = "IID_IAccessibleTableCell"; + else if (id == IID_IAccessibleText) + result = "IID_IAccessibleText"; + else if (id == IID_IAccessibleValue) + result = "IID_IAccessibleValue"; +#endif // !Q_CC_MINGW + return result; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const GUID &); - return QByteArray(); +QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid) +{ + QDebugStateSaver saver(d); + d.nospace(); + if (const char *ids = QWindowsAccessibleGuid::iidToString(aguid.guid())) + d << ids; + else + d << aguid.guid(); + return d; } +#endif // !QT_NO_DEBUG_STREAM QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index fd00f8ac8b..07f10da99a 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -69,16 +69,32 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn QWindow *window_helper(const QAccessibleInterface *iface); +class QWindowsAccessibleGuid // Helper for QDebug, outputs known ids by name. +{ +public: + explicit QWindowsAccessibleGuid(const GUID &g) : m_guid(g) {} + GUID guid () const { return m_guid; } + static const char *iidToString(const GUID &id); + +private: + GUID m_guid; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid); +#endif + /**************************************************************\ * QWindowsAccessible * **************************************************************/ -class QWindowsMsaaAccessible : public -#ifdef Q_CC_MINGW - IAccessible + +#ifndef Q_CC_MINGW +typedef IAccessible2 AccessibleBase; #else - IAccessible2 +typedef IAccessible AccessibleBase; #endif - , public IOleWindow + +class QWindowsMsaaAccessible : public AccessibleBase, public IOleWindow { public: QWindowsMsaaAccessible(QAccessibleInterface *a) @@ -132,8 +148,6 @@ public: HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); protected: - virtual QByteArray IIDToString(REFIID id); - QAccessible::Id id; QAccessibleInterface *accessibleInterface() const diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h new file mode 100644 index 0000000000..f8afcc81cf --- /dev/null +++ b/src/plugins/platforms/windows/qwindowscombase.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCOMBASE_H +#define QWINDOWSCOMBASE_H + +#include <QtCore/QtGlobal> + +#include <unknwn.h> + +QT_BEGIN_NAMESPACE + +// Helper for implementing IUnknown::QueryInterface. +template <class DesiredInterface, class Derived> +bool qWindowsComQueryInterface(Derived *d, REFIID id, LPVOID *iface) +{ + if (id == __uuidof(DesiredInterface)) { + *iface = static_cast<DesiredInterface *>(d); + d->AddRef(); + return true; + } + return false; +} + +// Helper for implementing IUnknown::QueryInterface for IUnknown +// in the case of multiple inheritance via the first inherited class. +template <class FirstInheritedInterface, class Derived> +bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface) +{ + if (id == __uuidof(IUnknown)) { + *iface = static_cast<FirstInheritedInterface *>(d); + d->AddRef(); + return true; + } + return false; +} + +// Helper base class to provide IUnknown methods for COM classes (single inheritance) +template <class ComInterface> class QWindowsComBase : public ComInterface +{ + Q_DISABLE_COPY(QWindowsComBase) +public: + explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {} + virtual ~QWindowsComBase() {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) + { + *iface = nullptr; + return qWindowsComQueryInterface<IUnknown>(this, id, iface) || qWindowsComQueryInterface<ComInterface>(this, id, iface) + ? S_OK : E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref; } + + ULONG STDMETHODCALLTYPE Release() + { + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; + } + +private: + ULONG m_ref; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSCOMBASE_H diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index ff4ab1accb..f017929148 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -121,12 +121,20 @@ static inline bool useRTL_Extensions() return false; } -#if !defined(QT_NO_SESSIONMANAGER) -static inline QWindowsSessionManager *platformSessionManager() { +#if QT_CONFIG(sessionmanager) +static inline QWindowsSessionManager *platformSessionManager() +{ QGuiApplicationPrivate *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp)); QSessionManagerPrivate *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager)); return static_cast<QWindowsSessionManager *>(managerPrivate->platformSessionManager); } + +static inline bool sessionManagerInteractionBlocked() +{ + return platformSessionManager()->isInteractionBlocked(); +} +#else // QT_CONFIG(sessionmanager) +static inline bool sessionManagerInteractionBlocked() { return false; } #endif static inline int windowDpiAwareness(HWND hwnd) @@ -896,11 +904,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, switch (et) { case QtWindows::GestureEvent: -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); -#else - return d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. @@ -989,11 +993,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: case QtWindows::AppCommandEvent: -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); -#else - return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); case QtWindows::MoveEvent: platformWindow->handleMoved(); return true; @@ -1013,18 +1013,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: if (platformWindow->frameStrutEventsEnabled()) -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); -#else - return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); break; case QtWindows::ScrollEvent: -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); -#else - return d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: @@ -1034,18 +1026,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, window = window->parent(); if (!window) return false; -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); -#else - return d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); } case QtWindows::TouchEvent: -#if !defined(QT_NO_SESSIONMANAGER) - return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); -#else - return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); -#endif + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index f4527bcc60..0c4f27def2 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -41,6 +41,7 @@ #define _WIN32_WINNT 0x0600 +#include "qwindowscombase.h" #include "qwindowsdialoghelpers.h" #include "qwindowscontext.h" @@ -52,7 +53,7 @@ #include <QtGui/QColor> #include <QtCore/QDebug> -#include <QtCore/QRegExp> +#include <QtCore/QRegularExpression> #include <QtCore/QTimer> #include <QtCore/QDir> #include <QtCore/QScopedArrayPointer> @@ -504,33 +505,11 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile class QWindowsNativeFileDialogBase; -class QWindowsNativeFileDialogEventHandler : public IFileDialogEvents +class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents> { public: static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog); - // IUnknown methods - IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) - { - if (riid != IID_IUnknown && riid != IID_IFileDialogEvents) { - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); - } - *ppv = this; - AddRef(); - return NOERROR; - } - - IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_ref); } - - IFACEMETHODIMP_(ULONG) Release() - { - const long ref = InterlockedDecrement(&m_ref); - if (!ref) - delete this; - return ref; - } - // IFileDialogEvents methods IFACEMETHODIMP OnFileOk(IFileDialog *); IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; } @@ -546,7 +525,6 @@ public: virtual ~QWindowsNativeFileDialogEventHandler() {} private: - long m_ref = 1; QWindowsNativeFileDialogBase *m_nativeFileDialog; }; @@ -1039,7 +1017,7 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters, result.reserve(filters.size()); *totalStringLength = 0; - const QRegExp filterSeparatorRE(QStringLiteral("[;\\s]+")); + const QRegularExpression filterSeparatorRE(QStringLiteral("[;\\s]+")); const QString separator = QStringLiteral(";"); Q_ASSERT(filterSeparatorRE.isValid()); // Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc' diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 58175b39fa..a326ccac3e 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -215,7 +215,7 @@ static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState) \ingroup qt-lighthouse-win */ -class QWindowsOleDropSource : public IDropSource +class QWindowsOleDropSource : public QWindowsComBase<IDropSource> { public: enum Mode { @@ -228,11 +228,6 @@ public: void createCursors(); - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IDropSource methods STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState); STDMETHOD(GiveFeedback)(DWORD dwEffect); @@ -257,7 +252,6 @@ private: ActionCursorMap m_cursors; QWindowsDragCursorWindow *m_touchDragWindow; - ULONG m_refs; #ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug, const QWindowsOleDropSource::CursorEntry &); #endif @@ -268,7 +262,6 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) , m_drag(drag) , m_currentButtons(Qt::NoButton) , m_touchDragWindow(0) - , m_refs(1) { qCDebug(lcQpaMime) << __FUNCTION__ << m_mode; } @@ -373,38 +366,6 @@ void QWindowsOleDropSource::createCursors() #endif // !QT_NO_DEBUG_OUTPUT } -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - -STDMETHODIMP -QWindowsOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDropSource) { - *ppv = this; - ++m_refs; - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropSource::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropSource::Release(void) -{ - if (--m_refs == 0) { - delete this; - return 0; - } - return m_refs; -} - /*! \brief Check for cancel. */ @@ -509,34 +470,6 @@ QWindowsOleDropTarget::~QWindowsOleDropTarget() qCDebug(lcQpaMime) << __FUNCTION__ << this; } -STDMETHODIMP -QWindowsOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDropTarget) { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropTarget::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropTarget::Release(void) -{ - if (--m_refs == 0) { - delete this; - return 0; - } - return m_refs; -} - void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &point, LPDWORD pdwEffect) { diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 983f3a67b4..2b4ca2dce1 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -40,6 +40,7 @@ #ifndef QWINDOWSDRAG_H #define QWINDOWSDRAG_H +#include "qwindowscombase.h" #include "qwindowsinternalmimedata.h" #include <qpa/qplatformdrag.h> @@ -57,17 +58,12 @@ public: IDataObject *retrieveDataObject() const override; }; -class QWindowsOleDropTarget : public IDropTarget +class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget> { public: explicit QWindowsOleDropTarget(QWindow *w); virtual ~QWindowsOleDropTarget(); - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG, AddRef)(void); - STDMETHOD_(ULONG, Release)(void); - // IDropTarget methods STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); @@ -77,7 +73,6 @@ public: private: void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect); - ULONG m_refs = 1; QWindow *const m_window; QRect m_answerRect; QPoint m_lastPoint; @@ -91,8 +86,6 @@ public: QWindowsDrag(); virtual ~QWindowsDrag(); - QMimeData *platformDropData() override { return &m_dropData; } - Qt::DropAction drag(QDrag *drag) override; static QWindowsDrag *instance(); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 751807e897..78368d87de 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -145,6 +145,10 @@ #define RESET_NOTIFICATION_STRATEGY_ARB 0x8256 #define LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#ifndef WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif + QT_BEGIN_NAMESPACE QWindowsOpengl32DLL QOpenGLStaticContext::opengl32; @@ -489,7 +493,7 @@ static int choosePixelFormat(HDC hdc, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd) { - enum { attribSize =40 }; + enum { attribSize = 42 }; if ((additional.formatFlags & QWindowsGLRenderToPixmap) || !staticContext.hasExtensions()) return 0; @@ -570,7 +574,15 @@ static int choosePixelFormat(HDC hdc, iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = FALSE; } - // If sample buffer request cannot be satisfied, reduce request. + // must be the last + bool srgbRequested = format.colorSpace() == QSurfaceFormat::sRGBColorSpace; + int srgbValuePosition = 0; + if (srgbRequested) { + srgbValuePosition = i; + iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT; + iAttributes[i++] = TRUE; + } + // If sample or sRGB request cannot be satisfied, reduce request. int pixelFormat = 0; uint numFormats = 0; while (true) { @@ -578,20 +590,25 @@ static int choosePixelFormat(HDC hdc, staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1, &pixelFormat, &numFormats) && numFormats >= 1; - if (valid || !sampleBuffersRequested) - break; - if (iAttributes[samplesValuePosition] > 1) { - iAttributes[samplesValuePosition] /= 2; - } else if (iAttributes[samplesValuePosition] == 1) { - // Fallback in case it is unable to initialize with any - // samples to avoid falling back to the GDI path - // NB: The sample attributes needs to be at the end for this - // to work correctly - iAttributes[samplesValuePosition - 1] = FALSE; - iAttributes[samplesValuePosition] = 0; - iAttributes[samplesValuePosition + 1] = 0; - } else { + if (valid || (!sampleBuffersRequested && !srgbRequested)) break; + if (srgbRequested) { + iAttributes[srgbValuePosition] = 0; + srgbRequested = false; + } else if (sampleBuffersRequested) { + if (iAttributes[samplesValuePosition] > 1) { + iAttributes[samplesValuePosition] /= 2; + } else if (iAttributes[samplesValuePosition] == 1) { + // Fallback in case it is unable to initialize with any + // samples to avoid falling back to the GDI path + // NB: The sample attributes needs to be at the end for this + // to work correctly + iAttributes[samplesValuePosition - 1] = FALSE; + iAttributes[samplesValuePosition] = 0; + iAttributes[samplesValuePosition + 1] = 0; + } else { + break; + } } } // Verify if format is acceptable. Note that the returned @@ -628,7 +645,7 @@ static QSurfaceFormat HDC hdc, int pixelFormat, QWindowsOpenGLAdditionalFormat *additionalIn = 0) { - enum { attribSize =40 }; + enum { attribSize = 42 }; QSurfaceFormat result; result.setRenderableType(QSurfaceFormat::OpenGL); @@ -641,6 +658,7 @@ static QSurfaceFormat int i = 0; const bool hasSampleBuffers = testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers); + const bool hasSrgbSupport = testFlag(staticContext.extensions, QOpenGLStaticContext::sRGBCapableFramebuffer); iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0 iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1 @@ -658,6 +676,9 @@ static QSurfaceFormat iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; // 12 iAttributes[i++] = WGL_SAMPLES_ARB; // 13 } + if (hasSrgbSupport) + iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT; // 12 or 14 + if (!staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i, iAttributes, iValues)) { qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for basic parameters.", __FUNCTION__); @@ -673,8 +694,14 @@ static QSurfaceFormat if (iValues[9]) result.setOption(QSurfaceFormat::StereoBuffers); - if (hasSampleBuffers) + if (hasSampleBuffers) { result.setSamples(iValues[13]); + if (hasSrgbSupport && iValues[14]) + result.setColorSpace(QSurfaceFormat::sRGBColorSpace); + } else { + if (hasSrgbSupport && iValues[12]) + result.setColorSpace(QSurfaceFormat::sRGBColorSpace); + } if (additionalIn) { if (iValues[7]) additionalIn->formatFlags |= QWindowsGLAccumBuffer; @@ -947,7 +974,8 @@ QOpenGLStaticContext::QOpenGLStaticContext() : wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")), wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")), wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")), - wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")) + wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")), + wglGetExtensionsStringARB((WglGetExtensionsStringARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB")) { if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ") || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1) @@ -1091,6 +1119,14 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, && !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb); QWindowsOpenGLAdditionalFormat obtainedAdditional; if (tryExtensions) { + if (m_staticContext->wglGetExtensionsStringARB) { + const char *exts = m_staticContext->wglGetExtensionsStringARB(hdc); + if (exts) { + qCDebug(lcQpaGl) << __FUNCTION__ << "WGL extensions:" << exts; + if (strstr(exts, "WGL_EXT_framebuffer_sRGB")) + m_staticContext->extensions |= QOpenGLStaticContext::sRGBCapableFramebuffer; + } + } m_pixelFormat = ARB::choosePixelFormat(hdc, *m_staticContext, format, requestedAdditional, &m_obtainedPixelFormatDescriptor); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index dfaa428520..2d5b94af0e 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -139,7 +139,8 @@ class QOpenGLStaticContext : public QWindowsStaticOpenGLContext public: enum Extensions { - SampleBuffers = 0x1 + SampleBuffers = 0x1, + sRGBCapableFramebuffer = 0x2 }; typedef bool @@ -160,6 +161,9 @@ public: typedef int (APIENTRY *WglGetSwapInternalExt)(void); + typedef const char * + (APIENTRY *WglGetExtensionsStringARB)(HDC); + bool hasExtensions() const { return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; } @@ -185,6 +189,7 @@ public: WglCreateContextAttribsARB wglCreateContextAttribsARB; WglSwapInternalExt wglSwapInternalExt; WglGetSwapInternalExt wglGetSwapInternalExt; + WglGetExtensionsStringARB wglGetExtensionsStringARB; static QWindowsOpengl32DLL opengl32; }; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 31062b681d..a049b8c40c 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -611,4 +611,11 @@ void QWindowsIntegration::beep() const MessageBeep(MB_OK); // For QApplication } +#if QT_CONFIG(vulkan) +QPlatformVulkanInstance *QWindowsIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + return new QWindowsVulkanInstance(instance); +} +#endif + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 607203829f..fbdb341dab 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -113,6 +113,10 @@ public: QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; #endif +#if QT_CONFIG(vulkan) + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; +#endif + protected: virtual QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const; diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 34c34fd28e..0e15ab08c1 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -572,7 +572,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, - touchPoints); + touchPoints, + QWindowsKeyMapper::queryKeyboardModifiers()); return true; } diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index d750eef19d..dc8e97c886 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -64,7 +64,8 @@ enum ResourceType { HandleType, GlHandleType, GetDCType, - ReleaseDCType + ReleaseDCType, + VkSurface }; static int resourceType(const QByteArray &key) @@ -77,7 +78,8 @@ static int resourceType(const QByteArray &key) "handle", "glhandle", "getdc", - "releasedc" + "releasedc", + "vkSurface" }; const char ** const end = names + sizeof(names) / sizeof(names[0]); const char **result = std::find(names, end, key); @@ -112,6 +114,12 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc case QWindow::OpenGLSurface: case QWindow::OpenVGSurface: break; + case QWindow::VulkanSurface: +#if QT_CONFIG(vulkan) + if (type == VkSurface) + return bw->surface(nullptr, nullptr); // returns the address of the VkSurfaceKHR, not the value, as expected +#endif + break; } qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); return 0; diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index 9b71061aa5..0ceb0d82fa 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -99,39 +99,6 @@ DWORD QWindowsOleDataObject::reportedPerformedEffect() const return performedEffect; } -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - -STDMETHODIMP -QWindowsOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDataObject) { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDataObject::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDataObject::Release(void) -{ - if (--m_refs == 0) { - releaseQt(); - delete this; - return 0; - } - return m_refs; -} - STDMETHODIMP QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { @@ -323,35 +290,6 @@ bool QWindowsOleEnumFmtEtc::isNull() const return m_isNull; } -// IUnknown methods -STDMETHODIMP -QWindowsOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj) -{ - if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) { - *ppvObj = this; - AddRef(); - return NOERROR; - } - *ppvObj = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleEnumFmtEtc::AddRef(void) -{ - return ++m_dwRefs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleEnumFmtEtc::Release(void) -{ - if (--m_dwRefs == 0) { - delete this; - return 0; - } - return m_dwRefs; -} - // IEnumFORMATETC methods STDMETHODIMP QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h index 643011272b..fc58858f2c 100644 --- a/src/plugins/platforms/windows/qwindowsole.h +++ b/src/plugins/platforms/windows/qwindowsole.h @@ -40,6 +40,7 @@ #ifndef QWINDOWSOLE_H #define QWINDOWSOLE_H +#include "qwindowscombase.h" #include <QtCore/qt_windows.h> #include <QtCore/QMap> @@ -53,7 +54,7 @@ QT_BEGIN_NAMESPACE class QMimeData; class QWindow; -class QWindowsOleDataObject : public IDataObject +class QWindowsOleDataObject : public QWindowsComBase<IDataObject> { public: explicit QWindowsOleDataObject(QMimeData *mimeData); @@ -63,11 +64,6 @@ public: QMimeData *mimeData() const; DWORD reportedPerformedEffect() const; - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IDataObject methods STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium); STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium); @@ -82,13 +78,12 @@ public: STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise); private: - ULONG m_refs = 1; QPointer<QMimeData> data; const int CF_PERFORMEDDROPEFFECT; DWORD performedEffect = DROPEFFECT_NONE; }; -class QWindowsOleEnumFmtEtc : public IEnumFORMATETC +class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC> { public: explicit QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs); @@ -97,11 +92,6 @@ public: bool isNull() const; - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IEnumFORMATETC methods STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched); STDMETHOD(Skip)(ULONG celt); @@ -111,7 +101,6 @@ public: private: bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const; - ULONG m_dwRefs = 1; ULONG m_nIndex = 0; QVector<LPFORMATETC> m_lpfmtetcs; bool m_isNull = false; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 3e2cb5e9e9..e1cbbc9311 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -415,13 +415,7 @@ static inline QStringList iconThemeSearchPaths() static inline QStringList styleNames() { - QStringList result; - if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) - result.append(QStringLiteral("WindowsVista")); - if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) - result.append(QStringLiteral("WindowsXP")); - result.append(QStringLiteral("Windows")); - return result; + return { QStringLiteral("WindowsVista"), QStringLiteral("Windows") }; } static inline int uiEffects() diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp new file mode 100644 index 0000000000..d81ee8ba29 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsvulkaninstance.h" + +QT_BEGIN_NAMESPACE + +QWindowsVulkanInstance::QWindowsVulkanInstance(QVulkanInstance *instance) + : m_instance(instance), + m_getPhysDevPresSupport(nullptr), + m_createSurface(nullptr), + m_destroySurface(nullptr) +{ + if (qEnvironmentVariableIsSet("QT_VULKAN_LIB")) + m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB"))); + else + m_lib.setFileName(QStringLiteral("vulkan-1")); + + if (!m_lib.load()) { + qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString())); + return; + } + + init(&m_lib); +} + +void QWindowsVulkanInstance::createOrAdoptInstance() +{ + initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_win32_surface")); + + if (!m_vkInst) + return; + + m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceWin32PresentationSupportKHR")); + if (!m_getPhysDevPresSupport) + qWarning("Failed to find vkGetPhysicalDeviceWin32PresentationSupportKHR"); +} + +QWindowsVulkanInstance::~QWindowsVulkanInstance() +{ +} + +bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + QWindow *window) +{ + if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport) + return true; + + bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex); + + VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window); + VkBool32 supported = false; + m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported); + ok &= bool(supported); + + return ok; +} + +VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win) +{ + VkSurfaceKHR surface = 0; + + if (!m_createSurface) { + m_createSurface = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkCreateWin32SurfaceKHR")); + } + if (!m_createSurface) { + qWarning("Failed to find vkCreateWin32SurfaceKHR"); + return surface; + } + if (!m_destroySurface) { + m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR")); + } + if (!m_destroySurface) { + qWarning("Failed to find vkDestroySurfaceKHR"); + return surface; + } + + VkWin32SurfaceCreateInfoKHR surfaceInfo; + memset(&surfaceInfo, 0, sizeof(surfaceInfo)); + surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surfaceInfo.hinstance = GetModuleHandle(nullptr); + surfaceInfo.hwnd = win; + VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); + if (err != VK_SUCCESS) + qWarning("Failed to create Vulkan surface: %d", err); + + return surface; +} + +void QWindowsVulkanInstance::destroySurface(VkSurfaceKHR surface) +{ + if (m_destroySurface && surface) + m_destroySurface(m_vkInst, surface, nullptr); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h new file mode 100644 index 0000000000..ca60ab7627 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSVULKANINSTANCE_H +#define QWINDOWSVULKANINSTANCE_H + +#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_WIN32_KHR) +#error "vulkan.h included without Win32 WSI" +#endif + +#define VK_USE_PLATFORM_WIN32_KHR + +#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h> +#include <QLibrary> + +QT_BEGIN_NAMESPACE + +class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance +{ +public: + QWindowsVulkanInstance(QVulkanInstance *instance); + ~QWindowsVulkanInstance(); + + void createOrAdoptInstance() override; + bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; + + VkSurfaceKHR createSurface(HWND win); + void destroySurface(VkSurfaceKHR surface); + +private: + QVulkanInstance *m_instance; + QLibrary m_lib; + PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR m_getPhysDevPresSupport; + PFN_vkCreateWin32SurfaceKHR m_createSurface; + PFN_vkDestroySurfaceKHR m_destroySurface; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSVULKANINSTANCE_H diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 2875463e62..a3337509a7 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -67,6 +67,10 @@ #include <dwmapi.h> +#if QT_CONFIG(vulkan) +#include "qwindowsvulkaninstance.h" +#endif + QT_BEGIN_NAMESPACE enum { @@ -224,6 +228,23 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp) << ", rcNormalPosition=" << wp.rcNormalPosition; return d; } + +QDebug operator<<(QDebug d, const GUID &guid) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0')) + << qSetFieldWidth(8) << guid.Data1 + << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << guid.Data3 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1] + << qSetFieldWidth(0) << '-' << qSetFieldWidth(2); + for (int i = 2; i < 8; ++i) + d << guid.Data4[i]; + d << qSetFieldWidth(0) << '}'; + return d; +} #endif // !QT_NO_DEBUG_STREAM // QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT @@ -291,13 +312,15 @@ static QWindow::Visibility windowVisibility_sys(HWND hwnd) return QWindow::Windowed; } -static inline bool windowIsOpenGL(const QWindow *w) +static inline bool windowIsAccelerated(const QWindow *w) { switch (w->surfaceType()) { case QSurface::OpenGLSurface: return true; case QSurface::RasterGLSurface: return qt_window_private(const_cast<QWindow *>(w))->compositing; + case QSurface::VulkanSurface: + return true; default: return false; } @@ -358,11 +381,11 @@ bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool has return needsLayered; } -static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool openGL, qreal level) +static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level) { if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) { const BYTE alpha = BYTE(qRound(255.0 * level)); - if (hasAlpha && !openGL && (flags & Qt::FramelessWindowHint)) { + if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) { // Non-GL windows with alpha: Use blend function to update. BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; UpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA); @@ -376,13 +399,13 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity) { - const bool isGL = windowIsOpenGL(w); + const bool isAccelerated = windowIsAccelerated(w); const bool hasAlpha = w->format().hasAlpha(); - if (isGL && hasAlpha) + if (isAccelerated && hasAlpha) applyBlurBehindWindow(hwnd); - setWindowOpacity(hwnd, flags, hasAlpha, isGL, opacity); + setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity); } /*! @@ -1036,6 +1059,9 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) m_data(data), m_cursor(new CursorHandle), m_format(aWindow->requestedFormat()) +#if QT_CONFIG(vulkan) + , m_vkSurface(0) +#endif { // Clear the creation context as the window can be found in QWindowsContext's map. QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>()); @@ -1051,10 +1077,14 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) setFlag(OpenGL_ES2); } #endif // QT_NO_OPENGL +#if QT_CONFIG(vulkan) + if (aWindow->surfaceType() == QSurface::VulkanSurface) + setFlag(VulkanSurface); +#endif updateDropSite(window()->isTopLevel()); registerTouchWindow(); - setWindowState(aWindow->windowState()); + setWindowState(aWindow->windowStates()); const qreal opacity = qt_window_private(aWindow)->opacity; if (!qFuzzyCompare(opacity, qreal(1.0))) setOpacity(opacity); @@ -1104,6 +1134,14 @@ void QWindowsWindow::destroyWindow() if (hasMouseCapture()) setMouseGrabEnabled(false); setDropSiteEnabled(false); +#if QT_CONFIG(vulkan) + if (m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface); + m_vkSurface = 0; + } +#endif #ifndef QT_NO_OPENGL if (m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) @@ -1321,20 +1359,48 @@ static inline bool testShowWithoutActivating(const QWindow *window) return showWithoutActivating.isValid() && showWithoutActivating.toBool(); } +static void setMinimizedGeometry(HWND hwnd, const QRect &r) +{ + WINDOWPLACEMENT windowPlacement; + windowPlacement.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(hwnd, &windowPlacement)) { + windowPlacement.showCmd = SW_SHOWMINIMIZED; + windowPlacement.rcNormalPosition = RECTfromQRect(r); + SetWindowPlacement(hwnd, &windowPlacement); + } +} + +static void setRestoreMaximizedFlag(HWND hwnd, bool set = true) +{ + // Let Windows know that we need to restore as maximized + WINDOWPLACEMENT windowPlacement; + windowPlacement.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(hwnd, &windowPlacement)) { + if (set) + windowPlacement.flags |= WPF_RESTORETOMAXIMIZED; + else + windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED; + SetWindowPlacement(hwnd, &windowPlacement); + } +} + // partially from QWidgetPrivate::show_sys() void QWindowsWindow::show_sys() const { int sm = SW_SHOWNORMAL; bool fakedMaximize = false; + bool restoreMaximize = false; const QWindow *w = window(); const Qt::WindowFlags flags = w->flags(); const Qt::WindowType type = w->type(); if (w->isTopLevel()) { - const Qt::WindowState state = w->windowState(); + const Qt::WindowStates state = w->windowStates(); if (state & Qt::WindowMinimized) { sm = SW_SHOWMINIMIZED; if (!isVisible()) sm = SW_SHOWMINNOACTIVE; + if (state & Qt::WindowMaximized) + restoreMaximize = true; } else { updateTransientParent(); if (state & Qt::WindowMaximized) { @@ -1355,7 +1421,7 @@ void QWindowsWindow::show_sys() const if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w)) sm = SW_SHOWNOACTIVATE; - if (w->windowState() & Qt::WindowMaximized) + if (w->windowStates() & Qt::WindowMaximized) setFlag(WithinMaximize); // QTBUG-8361 ShowWindow(m_data.hwnd, sm); @@ -1368,6 +1434,8 @@ void QWindowsWindow::show_sys() const SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } + if (restoreMaximize) + setRestoreMaximizedFlag(m_data.hwnd); } void QWindowsWindow::setParent(const QPlatformWindow *newParent) @@ -1423,8 +1491,10 @@ void QWindowsWindow::handleHidden() void QWindowsWindow::handleCompositionSettingsChanged() { const QWindow *w = window(); - if (w->surfaceType() == QWindow::OpenGLSurface && w->format().hasAlpha()) + if ((w->surfaceType() == QWindow::OpenGLSurface || w->surfaceType() == QWindow::VulkanSurface) + && w->format().hasAlpha()) { applyBlurBehindWindow(handle()); + } } static QRect normalFrameGeometry(HWND hwnd) @@ -1441,7 +1511,8 @@ static QRect normalFrameGeometry(HWND hwnd) QRect QWindowsWindow::normalGeometry() const { // Check for fake 'fullscreen' mode. - const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen; + const bool fakeFullScreen = + m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen); const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd); const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins(); return frame.isValid() ? frame.marginsRemoved(margins) : frame; @@ -1456,13 +1527,15 @@ void QWindowsWindow::setGeometry(const QRect &rectIn) const QMargins margins = frameMargins(); rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top())); } - if (m_windowState == Qt::WindowMinimized) + if (m_windowState & Qt::WindowMinimized) m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event. if (m_data.hwnd) { // A ResizeEvent with resulting geometry will be sent. If we cannot // achieve that size (for example, window title minimal constraint), // notify and warn. + setFlag(WithinSetGeometry); setGeometry_sys(rect); + clearFlag(WithinSetGeometry); if (m_data.geometry != rect) { qWarning("%s: Unable to set geometry %dx%d+%d+%d on %s/'%s'." " Resulting geometry: %dx%d+%d+%d " @@ -1499,18 +1572,21 @@ void QWindowsWindow::handleResized(int wParam) case SIZE_MAXSHOW: return; case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change - if (!testFlag(WithinSetStyle)) - handleWindowStateChange(Qt::WindowMinimized); + if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) + handleWindowStateChange(m_windowState | Qt::WindowMinimized); return; case SIZE_MAXIMIZED: - if (!testFlag(WithinSetStyle)) - handleWindowStateChange(Qt::WindowMaximized); + if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) + handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen + : Qt::WindowNoState)); handleGeometryChange(); break; case SIZE_RESTORED: - if (!testFlag(WithinSetStyle)) { + if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) { if (isFullScreen_sys()) - handleWindowStateChange(Qt::WindowFullScreen); + handleWindowStateChange( + Qt::WindowFullScreen + | (testFlag(MaximizeToFullScreen) ? Qt::WindowMaximized : Qt::WindowNoState)); else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen)) handleWindowStateChange(Qt::WindowNoState); } @@ -1640,8 +1716,11 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, BeginPaint(hwnd, &ps); // Observed painting problems with Aero style disabled (QTBUG-7865). - if (Q_UNLIKELY(testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered) && !dwmIsCompositionEnabled())) + if (Q_UNLIKELY(!dwmIsCompositionEnabled()) + && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface))) + { SelectClipRgn(ps.hdc, NULL); + } // If the a window is obscured by another window (such as a child window) // we still need to send isExposed=true, for compatibility. @@ -1697,20 +1776,16 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, return result; } -void QWindowsWindow::handleWindowStateChange(Qt::WindowState state) +void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << "\n from " << m_windowState << " to " << state; m_windowState = state; QWindowSystemInterface::handleWindowStateChanged(window(), state); - switch (state) { - case Qt::WindowMinimized: + if (state & Qt::WindowMinimized) { handleHidden(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now. - break; - case Qt::WindowMaximized: - case Qt::WindowFullScreen: - case Qt::WindowNoState: { + } else { // QTBUG-17548: We send expose events when receiving WM_Paint, but for // layered windows and transient children, we won't receive any WM_Paint. QWindow *w = window(); @@ -1731,13 +1806,9 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state) if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose()) QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); } - break; - default: - break; - } } -void QWindowsWindow::setWindowState(Qt::WindowState state) +void QWindowsWindow::setWindowState(Qt::WindowStates state) { if (m_data.hwnd) { setWindowState_sys(state); @@ -1766,18 +1837,19 @@ bool QWindowsWindow::isFullScreen_sys() const to ShowWindow. */ -void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) +void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState) { - const Qt::WindowState oldState = m_windowState; + const Qt::WindowStates oldState = m_windowState; if (oldState == newState) return; qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << " from " << oldState << " to " << newState; const bool visible = isVisible(); + auto stateChange = oldState ^ newState; - if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) { - if (newState == Qt::WindowFullScreen) { + if (stateChange & Qt::WindowFullScreen) { + if (newState & Qt::WindowFullScreen) { #ifndef Q_FLATTEN_EXPOSE UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; #else @@ -1788,7 +1860,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) // Window state but emulated by changing geometry and style. if (!m_savedStyle) { m_savedStyle = style(); - if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) { + if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) { const QRect nf = normalFrameGeometry(m_data.hwnd); if (nf.isValid()) m_savedFrameGeometry = nf; @@ -1796,6 +1868,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) m_savedFrameGeometry = frameGeometry_sys(); } } + if (newState & Qt::WindowMaximized) + setFlag(MaximizeToFullScreen); if (m_savedStyle & WS_SYSMENU) newStyle |= WS_SYSMENU; if (visible) @@ -1809,15 +1883,23 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) if (!screen) screen = QGuiApplication::primaryScreen(); const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry; - const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE; - const bool wasSync = testFlag(SynchronousGeometryChangeEvent); - setFlag(SynchronousGeometryChangeEvent); - SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); - if (!wasSync) - clearFlag(SynchronousGeometryChangeEvent); - QWindowSystemInterface::handleGeometryChange(window(), r); - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); - } else if (newState != Qt::WindowMinimized) { + + if (newState & Qt::WindowMinimized) { + setMinimizedGeometry(m_data.hwnd, r); + if (stateChange & Qt::WindowMaximized) + setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized); + } else { + const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE; + const bool wasSync = testFlag(SynchronousGeometryChangeEvent); + setFlag(SynchronousGeometryChangeEvent); + SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); + if (!wasSync) + clearFlag(SynchronousGeometryChangeEvent); + clearFlag(MaximizeToFullScreen); + QWindowSystemInterface::handleGeometryChange(window(), r); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + } + } else { // Restore saved state. unsigned newStyle = m_savedStyle ? m_savedStyle : style(); if (visible) @@ -1831,43 +1913,58 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) if (!screen->geometry().intersects(m_savedFrameGeometry)) m_savedFrameGeometry.moveTo(screen->geometry().topLeft()); - UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE; - if (!m_savedFrameGeometry.isValid()) - swpf |= SWP_NOSIZE | SWP_NOMOVE; - const bool wasSync = testFlag(SynchronousGeometryChangeEvent); - setFlag(SynchronousGeometryChangeEvent); - // After maximized/fullscreen; the window can be in a maximized state. Clear - // it before applying the normal geometry. - if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized) - ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE); - SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(), - m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf); - if (!wasSync) - clearFlag(SynchronousGeometryChangeEvent); - // preserve maximized state - if (visible) { - setFlag(WithinMaximize); - ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA); - clearFlag(WithinMaximize); + if (newState & Qt::WindowMinimized) { + setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry); + if (stateChange & Qt::WindowMaximized) + setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized); + } else { + UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE; + if (!m_savedFrameGeometry.isValid()) + swpf |= SWP_NOSIZE | SWP_NOMOVE; + const bool wasSync = testFlag(SynchronousGeometryChangeEvent); + setFlag(SynchronousGeometryChangeEvent); + // After maximized/fullscreen; the window can be in a maximized state. Clear + // it before applying the normal geometry. + if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized) + ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE); + SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(), + m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf); + if (!wasSync) + clearFlag(SynchronousGeometryChangeEvent); + // preserve maximized state + if (visible) { + setFlag(WithinMaximize); + ShowWindow(m_data.hwnd, + (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA); + clearFlag(WithinMaximize); + } } m_savedStyle = 0; m_savedFrameGeometry = QRect(); } - } else if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) { - if (visible && !(newState == Qt::WindowMinimized)) { + } else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) { + if (visible && !(newState & Qt::WindowMinimized)) { setFlag(WithinMaximize); - if (newState == Qt::WindowFullScreen) + if (newState & Qt::WindowFullScreen) setFlag(MaximizeToFullScreen); - ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + ShowWindow(m_data.hwnd, + (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); clearFlag(WithinMaximize); clearFlag(MaximizeToFullScreen); + } else if (visible && (oldState & newState & Qt::WindowMinimized)) { + // change of the maximized state while keeping minimized + setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized); } } - if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) { - if (visible) - ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE : - (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL); + if (stateChange & Qt::WindowMinimized) { + if (visible) { + ShowWindow(m_data.hwnd, + (newState & Qt::WindowMinimized) ? SW_MINIMIZE : + (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL); + if ((newState & Qt::WindowMinimized) && (stateChange & Qt::WindowMaximized)) + setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized); + } } qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window() << newState; } @@ -1959,7 +2056,7 @@ void QWindowsWindow::setOpacity(qreal level) m_opacity = level; if (m_data.hwnd) setWindowOpacity(m_data.hwnd, m_data.flags, - window()->format().hasAlpha(), testFlag(OpenGLSurface), + window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface), level); } } @@ -2128,7 +2225,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const hint.applyToMinMaxInfo(m_data.hwnd, mmi); } - if ((testFlag(WithinMaximize) || (window()->windowState() == Qt::WindowMinimized)) + if ((testFlag(WithinMaximize) || (window()->windowStates() & Qt::WindowMinimized)) && (m_data.flags & Qt::FramelessWindowHint)) { // This block fixes QTBUG-8361: Frameless windows shouldn't cover the // taskbar when maximized @@ -2158,7 +2255,7 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re // QTBUG-32663, suppress resize cursor for fixed size windows. const QWindow *w = window(); if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input. - || (m_windowState != Qt::WindowNoState && m_windowState != Qt::WindowActive) + || !(m_windowState & ~Qt::WindowActive) || (m_data.flags & Qt::FramelessWindowHint)) { return false; } @@ -2377,11 +2474,27 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) void *QWindowsWindow::surface(void *nativeConfig, int *err) { -#ifdef QT_NO_OPENGL +#if QT_CONFIG(vulkan) + Q_UNUSED(nativeConfig); + Q_UNUSED(err); + if (window()->surfaceType() == QSurface::VulkanSurface) { + if (!m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + m_vkSurface = static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle()); + else + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + } + // Different semantics for VkSurfaces: the return value is the address, + // not the value, given that this is a 64-bit handle even on x86. + return &m_vkSurface; + } +#elif defined(QT_NO_OPENGL) Q_UNUSED(err) Q_UNUSED(nativeConfig) return 0; -#else +#endif +#ifndef QT_NO_OPENGL if (!m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err); @@ -2393,6 +2506,14 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err) void QWindowsWindow::invalidateSurface() { +#if QT_CONFIG(vulkan) + if (m_vkSurface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface); + m_vkSurface = 0; + } +#endif #ifndef QT_NO_OPENGL if (m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e541b110a6..46236c10b5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -46,6 +46,10 @@ #include <qpa/qplatformwindow.h> #include <QtPlatformHeaders/qwindowswindowfunctions.h> +#if QT_CONFIG(vulkan) +#include "qwindowsvulkaninstance.h" +#endif + QT_BEGIN_NAMESPACE class QWindowsOleDropTarget; @@ -188,6 +192,7 @@ public: { AutoMouseCapture = 0x1, //! Automatic mouse capture on button press. WithinSetParent = 0x2, + WithinSetGeometry = 0x8, OpenGLSurface = 0x10, OpenGL_ES2 = 0x20, OpenGLDoubleBuffered = 0x40, @@ -208,6 +213,7 @@ public: Compositing = 0x200000, HasBorderInFullScreen = 0x400000, WithinDpiChanged = 0x800000, + VulkanSurface = 0x1000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -230,7 +236,7 @@ public: QPoint mapFromGlobal(const QPoint &pos) const override; void setWindowFlags(Qt::WindowFlags flags) override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; void setParent(const QPlatformWindow *window) override; @@ -323,7 +329,7 @@ private: inline void show_sys() 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 setWindowState_sys(Qt::WindowStates newState); inline void setParent_sys(const QPlatformWindow *parent); inline void updateTransientParent() const; void destroyWindow(); @@ -331,14 +337,14 @@ private: void setDropSiteEnabled(bool enabled); void updateDropSite(bool topLevel); void handleGeometryChange(); - void handleWindowStateChange(Qt::WindowState state); + void handleWindowStateChange(Qt::WindowStates state); inline void destroyIcon(); void fireExpose(const QRegion ®ion, bool force=false); mutable QWindowsWindowData m_data; mutable unsigned m_flags = WithinCreate; HDC m_hdc = 0; - Qt::WindowState m_windowState = Qt::WindowNoState; + Qt::WindowStates m_windowState = Qt::WindowNoState; qreal m_opacity = 1; #ifndef QT_NO_CURSOR CursorHandlePtr m_cursor; @@ -350,6 +356,11 @@ private: HICON m_iconSmall = 0; HICON m_iconBig = 0; void *m_surface = nullptr; + +#if QT_CONFIG(vulkan) + // note: intentionally not using void * in order to avoid breaking x86 + VkSurfaceKHR m_vkSurface = 0; +#endif }; #ifndef QT_NO_DEBUG_STREAM @@ -359,6 +370,7 @@ QDebug operator<<(QDebug d, const MINMAXINFO &i); QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p); QDebug operator<<(QDebug d, const WINDOWPLACEMENT &); QDebug operator<<(QDebug d, const WINDOWPOS &); +QDebug operator<<(QDebug d, const GUID &guid); #endif // !QT_NO_DEBUG_STREAM // ---------- QWindowsGeometryHint inline functions. diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 7d3ecc8aa2..7694824d20 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -29,6 +29,7 @@ SOURCES += \ $$PWD/qwin10helpers.cpp HEADERS += \ + $$PWD/qwindowscombase.h \ $$PWD/qwindowswindow.h \ $$PWD/qwindowsintegration.h \ $$PWD/qwindowscontext.h \ @@ -67,6 +68,11 @@ qtConfig(dynamicgl) { HEADERS += $$PWD/qwindowseglcontext.h } +qtConfig(vulkan) { + SOURCES += $$PWD/qwindowsvulkaninstance.cpp + HEADERS += $$PWD/qwindowsvulkaninstance.h +} + !contains( DEFINES, QT_NO_CLIPBOARD ) { SOURCES += $$PWD/qwindowsclipboard.cpp HEADERS += $$PWD/qwindowsclipboard.h diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 23168c10dc..4d788d91f8 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -5,6 +5,8 @@ QT += \ eventdispatcher_support-private accessibility_support-private \ fontdatabase_support-private theme_support-private +qtConfig(vulkan): QT += vulkan_support-private + LIBS += -lgdi32 -ldwmapi include(windows.pri) diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index 15ae024d20..43c406e1fb 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -773,12 +773,6 @@ void QWinRTDrag::setDropTarget(QWindow *target) m_dragTarget = target; } -QMimeData *QWinRTDrag::platformDropData() -{ - qCDebug(lcQpaMime) << __FUNCTION__; - return m_mimeData; -} - void QWinRTDrag::setUiElement(ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element) { qCDebug(lcQpaMime) << __FUNCTION__; diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h index 6cbabfbf41..2371201507 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.h +++ b/src/plugins/platforms/winrt/qwinrtdrag.h @@ -94,7 +94,6 @@ public: virtual ~QWinRTDrag(); static QWinRTDrag *instance(); - QMimeData *platformDropData(void) override; Qt::DropAction drag(QDrag *) override; void setDropTarget(QWindow *target); diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index c40a1b8c45..cbf0ba36c9 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -91,7 +91,7 @@ public: QSurfaceFormat surfaceFormat; QString windowTitle; - Qt::WindowState state; + Qt::WindowStates state; EGLDisplay display; EGLSurface surface; @@ -158,7 +158,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window) Q_ASSERT_SUCCEEDED(hr); setWindowFlags(window->flags()); - setWindowState(window->windowState()); + setWindowState(window->windowStates()); setWindowTitle(window->title()); setGeometry(window->geometry()); @@ -323,7 +323,7 @@ qreal QWinRTWindow::devicePixelRatio() const return screen()->devicePixelRatio(); } -void QWinRTWindow::setWindowState(Qt::WindowState state) +void QWinRTWindow::setWindowState(Qt::WindowStates state) { Q_D(QWinRTWindow); qCDebug(lcQpaWindows) << __FUNCTION__ << this << state; @@ -331,7 +331,13 @@ void QWinRTWindow::setWindowState(Qt::WindowState state) if (d->state == state) return; - if (state == Qt::WindowFullScreen) { + if (state & Qt::WindowMinimized) { + setUIElementVisibility(d->uiElement.Get(), false); + d->state = state; + return; + } + + if (state & Qt::WindowFullScreen) { HRESULT hr; boolean success; hr = QEventDispatcherWinRT::runOnXamlThread([&hr, &success]() { @@ -356,7 +362,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state) return; } - if (d->state == Qt::WindowFullScreen) { + if (d->state & Qt::WindowFullScreen) { HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([&hr]() { ComPtr<IApplicationViewStatics2> applicationViewStatics; @@ -378,10 +384,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state) } } - if (state == Qt::WindowMinimized) - setUIElementVisibility(d->uiElement.Get(), false); - - if (d->state == Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive) + if (d->state & Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive) setUIElementVisibility(d->uiElement.Get(), true); d->state = state; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 26c2fa800d..a8992450b9 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -68,7 +68,7 @@ public: WId winId() const override; qreal devicePixelRatio() const override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h index 48e774bbb2..fe50afa62a 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h @@ -47,38 +47,28 @@ QT_BEGIN_NAMESPACE -//####todo remove the noops (looks like their where there in the initial commit) class QXcbEglContext : public QEGLPlatformContext { public: QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, - EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle) + EGLDisplay display, const QVariant &nativeHandle) : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle) - , m_connection(c) { - Q_XCB_NOOP(m_connection); } void swapBuffers(QPlatformSurface *surface) { - Q_XCB_NOOP(m_connection); QEGLPlatformContext::swapBuffers(surface); - Q_XCB_NOOP(m_connection); } bool makeCurrent(QPlatformSurface *surface) { - Q_XCB_NOOP(m_connection); - bool ret = QEGLPlatformContext::makeCurrent(surface); - Q_XCB_NOOP(m_connection); - return ret; + return QEGLPlatformContext::makeCurrent(surface); } void doneCurrent() { - Q_XCB_NOOP(m_connection); QEGLPlatformContext::doneCurrent(); - Q_XCB_NOOP(m_connection); } EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) @@ -92,9 +82,6 @@ public: QVariant nativeHandle() const { return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay())); } - -private: - QXcbConnection *m_connection; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp index 4852d38f7e..40ecd9e58d 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp @@ -102,7 +102,6 @@ QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLC QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()), context->shareHandle(), eglDisplay(), - screen->connection(), context->nativeHandle()); context->setNativeHandle(platformContext->nativeHandle()); return platformContext; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 7640a711a9..bcd6e46fc6 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -729,8 +729,7 @@ void QGLXContext::queryDummyContext() bool QGLXContext::supportsThreading() { - if (!m_queriedDummyContext) - queryDummyContext(); + queryDummyContext(); return m_supportsThreading; } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index 77cbdd5fba..0d02062421 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -111,18 +111,13 @@ bool QXcbGlxIntegration::initialize(QXcbConnection *connection) m_glx_first_event = reply->first_event; - xcb_generic_error_t *error = 0; - xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection->xcb_connection(), - XCB_GLX_MAJOR_VERSION, - XCB_GLX_MINOR_VERSION); - xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection->xcb_connection(), - xglx_query_cookie, &error); - if (!xglx_query || error) { + auto xglx_query = Q_XCB_REPLY(xcb_glx_query_version, m_connection->xcb_connection(), + XCB_GLX_MAJOR_VERSION, + XCB_GLX_MINOR_VERSION); + if (!xglx_query) { qCWarning(lcQpaGl) << "QXcbConnection: Failed to initialize GLX"; - free(error); return false; } - free(xglx_query); #endif m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface())); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp index 8df8b28f72..61fed6f5e3 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp @@ -41,6 +41,7 @@ #include "qxcbscreen.h" #include <QtGlxSupport/private/qglxconvenience_p.h> +#include <QDebug> QT_BEGIN_NAMESPACE @@ -58,13 +59,27 @@ const xcb_visualtype_t *QXcbGlxWindow::createVisual() QXcbScreen *scr = xcbScreen(); if (!scr) return Q_NULLPTR; - XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format); + + qDebug(lcQpaGl) << "Requested format before FBConfig/Visual selection:" << m_format; + + const char *glxExts = glXQueryExtensionsString(DISPLAY_FROM_XCB(scr), scr->screenNumber()); + int flags = 0; + if (glxExts) { + qCDebug(lcQpaGl, "Available GLX extensions: %s", glxExts); + if (strstr(glxExts, "GLX_EXT_framebuffer_sRGB") || strstr(glxExts, "GLX_ARB_framebuffer_sRGB")) + flags |= QGLX_SUPPORTS_SRGB; + } + + XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format, GLX_WINDOW_BIT, flags); if (!visualInfo) { qWarning() << "No XVisualInfo for format" << m_format; return Q_NULLPTR; } const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid); XFree(visualInfo); + + qDebug(lcQpaGl) << "Got format:" << m_format; + return xcb_visualtype; } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index f095288221..e0a12f57c2 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -150,8 +150,6 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI , m_gc_drawable(0) , m_xcb_pixmap(0) { - Q_XCB_NOOP(connection()); - const xcb_format_t *fmt = connection()->formatForDepth(depth); Q_ASSERT(fmt); @@ -206,11 +204,11 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI if (!hasShm()) { m_xcb_pixmap = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_pixmap(xcb_connection(), - m_xcb_image->depth, - m_xcb_pixmap, - screen->screen()->root, - m_xcb_image->width, m_xcb_image->height)); + xcb_create_pixmap(xcb_connection(), + m_xcb_image->depth, + m_xcb_pixmap, + screen->screen()->root, + m_xcb_image->width, m_xcb_image->height); } } @@ -234,13 +232,13 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) const QRect bounds(QPoint(0, 0), size()); for (const QRect &src : area) { const QRect dst = src.translated(delta).intersected(bounds); - Q_XCB_CALL(xcb_copy_area(xcb_connection(), - m_xcb_pixmap, - m_xcb_pixmap, - m_gc, - src.x(), src.y(), - dst.x(), dst.y(), - dst.width(), dst.height())); + xcb_copy_area(xcb_connection(), + m_xcb_pixmap, + m_xcb_pixmap, + m_gc, + src.x(), src.y(), + dst.x(), dst.y(), + dst.width(), dst.height()); } } @@ -251,7 +249,7 @@ void QXcbShmImage::destroy() { const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0; if (segmentSize && m_shm_info.shmaddr) - Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg)); + xcb_shm_detach(xcb_connection(), m_shm_info.shmseg); if (segmentSize) { if (m_shm_info.shmaddr) { @@ -265,12 +263,12 @@ void QXcbShmImage::destroy() xcb_image_destroy(m_xcb_image); if (m_gc) - Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); + xcb_free_gc(xcb_connection(), m_gc); delete m_graphics_buffer; m_graphics_buffer = Q_NULLPTR; if (m_xcb_pixmap) { - Q_XCB_CALL(xcb_free_pixmap(xcb_connection(), m_xcb_pixmap)); + xcb_free_pixmap(xcb_connection(), m_xcb_pixmap); m_xcb_pixmap = 0; } } @@ -279,13 +277,13 @@ void QXcbShmImage::ensureGC(xcb_drawable_t dst) { if (m_gc_drawable != dst) { if (m_gc) - Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); + xcb_free_gc(xcb_connection(), m_gc); static const uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES; static const uint32_t values[] = { 0 }; m_gc = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, dst, mask, values)); + xcb_create_gc(xcb_connection(), m_gc, dst, mask, values); m_gc_drawable = dst; } @@ -425,10 +423,7 @@ void QXcbShmImage::setClip(const QRegion ®ion) if (region.isEmpty()) { static const uint32_t mask = XCB_GC_CLIP_MASK; static const uint32_t values[] = { XCB_NONE }; - Q_XCB_CALL(xcb_change_gc(xcb_connection(), - m_gc, - mask, - values)); + xcb_change_gc(xcb_connection(), m_gc, mask, values); } else { const QVector<QRect> qrects = region.rects(); QVector<xcb_rectangle_t> xcb_rects(qrects.size()); @@ -440,18 +435,16 @@ void QXcbShmImage::setClip(const QRegion ®ion) xcb_rects[i].height = qrects[i].height(); } - Q_XCB_CALL(xcb_set_clip_rectangles(xcb_connection(), - XCB_CLIP_ORDERING_YX_BANDED, - m_gc, - 0, 0, - xcb_rects.size(), xcb_rects.constData())); + xcb_set_clip_rectangles(xcb_connection(), + XCB_CLIP_ORDERING_YX_BANDED, + m_gc, + 0, 0, + xcb_rects.size(), xcb_rects.constData()); } } void QXcbShmImage::put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset) { - Q_XCB_NOOP(connection()); - ensureGC(dst); setClip(region); @@ -460,33 +453,32 @@ void QXcbShmImage::put(xcb_drawable_t dst, const QRegion ®ion, const QPoint & const QRect source = bounds.translated(offset); if (hasShm()) { - Q_XCB_CALL(xcb_shm_put_image(xcb_connection(), - dst, - m_gc, - m_xcb_image->width, - m_xcb_image->height, - source.x(), source.y(), - source.width(), source.height(), - target.x(), target.y(), - m_xcb_image->depth, - m_xcb_image->format, - 0, // send event? - m_shm_info.shmseg, - m_xcb_image->data - m_shm_info.shmaddr)); + xcb_shm_put_image(xcb_connection(), + dst, + m_gc, + m_xcb_image->width, + m_xcb_image->height, + source.x(), source.y(), + source.width(), source.height(), + target.x(), target.y(), + m_xcb_image->depth, + m_xcb_image->format, + 0, // send event? + m_shm_info.shmseg, + m_xcb_image->data - m_shm_info.shmaddr); m_dirtyShm |= region.translated(offset); } else { flushPixmap(region); - Q_XCB_CALL(xcb_copy_area(xcb_connection(), - m_xcb_pixmap, - dst, - m_gc, - source.x(), source.y(), - target.x(), target.y(), - source.width(), source.height())); + xcb_copy_area(xcb_connection(), + m_xcb_pixmap, + dst, + m_gc, + source.x(), source.y(), + target.x(), target.y(), + source.width(), source.height()); } setClip(QRegion()); - Q_XCB_NOOP(connection()); } void QXcbShmImage::preparePaint(const QRegion ®ion) @@ -592,8 +584,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin if (bounds.isNull()) return; - Q_XCB_NOOP(connection()); - QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); if (!platformWindow) { qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)"); @@ -602,8 +592,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin m_image->put(platformWindow->xcb_window(), clipped, offset); - Q_XCB_NOOP(connection()); - if (platformWindow->needsSync()) platformWindow->updateSyncRequestCounter(); else @@ -617,8 +605,6 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, c { QPlatformBackingStore::composeAndFlush(window, region, offset, textures, context, translucentBackground); - Q_XCB_NOOP(connection()); - QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); if (platformWindow->needsSync()) { platformWindow->updateSyncRequestCounter(); @@ -632,7 +618,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) { if (m_image && size == m_image->size()) return; - Q_XCB_NOOP(connection()); QXcbScreen *screen = static_cast<QXcbScreen *>(window()->screen()->handle()); QPlatformWindow *pw = window()->handle(); @@ -649,7 +634,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) if (win->imageNeedsRgbSwap()) { m_rgbImage = QImage(size, win->imageFormat()); } - Q_XCB_NOOP(connection()); } bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 01b3bca0d2..30ab669432 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -278,22 +278,22 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) #ifndef QT_NO_DEBUG QByteArray ba("Qt clipboard window"); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_owner, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_owner, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); #endif if (connection()->hasXFixes()) { const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; - Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask)); - Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask)); + xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask); + xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask); } } @@ -305,8 +305,7 @@ QXcbClipboard::~QXcbClipboard() m_timestamp[QClipboard::Selection] != XCB_CURRENT_TIME) { // First we check if there is a clipboard manager. - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (reply && reply->owner != XCB_NONE) { // we delete the property so the manager saves all TARGETS. xcb_delete_property(xcb_connection(), m_owner, atom(QXcbAtom::_QT_SELECTION)); @@ -320,7 +319,6 @@ QXcbClipboard::~QXcbClipboard() "clipboard manager in a reasonable time"); } } - free(reply); } if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) @@ -459,26 +457,26 @@ xcb_window_t QXcbClipboard::requestor() const QXcbClipboard *that = const_cast<QXcbClipboard *>(this); xcb_window_t window = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - window, // window id - platformScreen->screen()->root, // parent window id - x, y, w, h, - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - platformScreen->screen()->root_visual, // visual - 0, // value mask - 0)); // value list + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + window, // window id + platformScreen->screen()->root, // parent window id + x, y, w, h, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + platformScreen->screen()->root_visual, // visual + 0, // value mask + 0); // value list #ifndef QT_NO_DEBUG QByteArray ba("Qt clipboard requestor window"); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - window, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + window, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); #endif uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE; @@ -759,17 +757,14 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, format = &dummy_format; // Don't read anything, just get the size of the property data - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0); if (!reply || reply->type == XCB_NONE) { - free(reply); buffer->resize(0); return false; } *type = reply->type; *format = reply->format; bytes_left = reply->bytes_after; - free(reply); int offset = 0, buffer_offset = 0; @@ -784,17 +779,15 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, while (bytes_left) { // more to read... - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4)); - reply = xcb_get_property_reply(xcb_connection(), cookie, 0); - if (!reply || reply->type == XCB_NONE) { - free(reply); + reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4); + if (!reply || reply->type == XCB_NONE) break; - } + *type = reply->type; *format = reply->format; bytes_left = reply->bytes_after; - char *data = (char *)xcb_get_property_value(reply); - int length = xcb_get_property_value_length(reply); + char *data = (char *)xcb_get_property_value(reply.get()); + int length = xcb_get_property_value_length(reply.get()); // Here we check if we get a buffer overflow and tries to // recover -- this shouldn't normally happen, but it doesn't @@ -814,7 +807,6 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, // offset is specified in 32-bit multiples offset += length / 4; } - free(reply); } } @@ -891,13 +883,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int return e; if (checkManager) { - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0); - if (!reply || reply->owner == XCB_NONE) { - free(reply); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); + if (!reply || reply->owner == XCB_NONE) return 0; - } - free(reply); } // process other clipboard events, since someone is probably requesting data from us diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5c15a9cbcb..c2e4edf2d5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -243,11 +243,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { // New XRandR output is available and it's enabled if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { - xcb_randr_get_output_info_cookie_t outputInfoCookie = - xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( - xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); - + auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(), + output.output, output.config_timestamp); // Find a fake screen const auto scrs = virtualDesktop->screens(); for (QPlatformScreen *scr : scrs) { @@ -261,12 +258,12 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) if (screen) { QString nameWas = screen->name(); // Transform the fake screen into a physical screen - screen->setOutput(output.output, outputInfo.data()); + screen->setOutput(output.output, outputInfo.get()); updateScreen(screen, output); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled; was fake:" << nameWas; } else { - screen = createScreen(virtualDesktop, output, outputInfo.data()); + screen = createScreen(virtualDesktop, output, outputInfo.get()); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; } QHighDpiScaling::updateHighDpiScaling(); @@ -274,10 +271,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else if (screen) { if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { // Screen has been disabled - xcb_randr_get_output_info_cookie_t outputInfoCookie = - xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( - xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); + auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(), + output.output, output.config_timestamp); if (outputInfo->crtc == XCB_NONE) { qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; destroyScreen(screen); @@ -299,16 +294,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) { - xcb_generic_error_t *error = 0; - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), rootWindow); - QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary ( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { + auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), rootWindow); + if (!primary) qWarning("failed to get the primary output of the screen"); - free(error); - error = NULL; - } + const bool isPrimary = primary ? (primary->output == output) : false; return isPrimary; @@ -404,72 +393,59 @@ void QXcbConnection::initializeScreens() m_virtualDesktops.append(virtualDesktop); QList<QPlatformScreen *> siblings; if (has_randr_extension) { - xcb_generic_error_t *error = NULL; // RRGetScreenResourcesCurrent is fast but it may return nothing if the // configuration is not initialized wrt to the hardware. We should call // RRGetScreenResources in this case. - QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources; - xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); - QScopedPointer<xcb_randr_get_screen_resources_current_reply_t, QScopedPointerPodDeleter> resources_current( - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources_current || error) { + auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current, + xcb_connection(), xcbScreen->root); + if (!resources_current) { qWarning("failed to get the current screen resources"); - free(error); } else { xcb_timestamp_t timestamp = 0; xcb_randr_output_t *outputs = Q_NULLPTR; - int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data()); + int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get()); if (outputCount) { timestamp = resources_current->config_timestamp; - outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data()); + outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get()); } else { - xcb_randr_get_screen_resources_cookie_t resourcesCookie = - xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); - resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources || error) { + auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources, + xcb_connection(), xcbScreen->root); + if (!resources) { qWarning("failed to get the screen resources"); - free(error); } else { timestamp = resources->config_timestamp; - outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); - outputs = xcb_randr_get_screen_resources_outputs(resources.data()); + outputCount = xcb_randr_get_screen_resources_outputs_length(resources.get()); + outputs = xcb_randr_get_screen_resources_outputs(resources.get()); } } if (outputCount) { - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); - QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { + auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), xcbScreen->root); + if (!primary) { qWarning("failed to get the primary output of the screen"); - free(error); } else { for (int i = 0; i < outputCount; i++) { - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output( - xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); - + auto output = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_output_info, + xcb_connection(), outputs[i], timestamp); // Invalid, disconnected or disabled output - if (output == NULL) + if (!output) continue; if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()), + xcb_randr_get_output_info_name_length(output.get())))); continue; } if (output->crtc == XCB_NONE) { qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()), + xcb_randr_get_output_info_name_length(output.get())))); continue; } - QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data()); + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.get()); siblings << screen; m_screens << screen; @@ -492,12 +468,9 @@ void QXcbConnection::initializeScreens() } } else if (has_xinerama_extension) { // Xinerama is available - xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(m_connection); - xcb_xinerama_query_screens_reply_t *screens = xcb_xinerama_query_screens_reply(m_connection, - cookie, - Q_NULLPTR); + auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, m_connection); if (screens) { - xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens); + xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get()); while (it.rem) { xcb_xinerama_screen_info_t *screen_info = it.data; QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, @@ -507,7 +480,6 @@ void QXcbConnection::initializeScreens() m_screens << screen; xcb_xinerama_screen_info_next(&it); } - free(screens); } } if (siblings.isEmpty()) { @@ -951,18 +923,6 @@ const char *xcb_protocol_request_codes[] = "Unknown" }; -#ifdef Q_XCB_DEBUG -void QXcbConnection::log(const char *file, int line, int sequence) -{ - QMutexLocker locker(&m_callLogMutex); - CallInfo info; - info.sequence = sequence; - info.file = file; - info.line = line; - m_callLog << info; -} -#endif - void QXcbConnection::handleXcbError(xcb_generic_error_t *error) { long result = 0; @@ -978,26 +938,6 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) int(error->sequence), int(error->resource_id), int(error->major_code), xcb_protocol_request_codes[clamped_major_code], int(error->minor_code)); -#ifdef Q_XCB_DEBUG - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) { - if (m_callLog.at(i).sequence == error->sequence) { - qDebug("Caused by: %s:%d", m_callLog.at(i).file.constData(), m_callLog.at(i).line); - break; - } else if (m_callLog.at(i).sequence > error->sequence) { - qDebug("Caused some time before: %s:%d", m_callLog.at(i).file.constData(), - m_callLog.at(i).line); - if (i > 0) - qDebug("and after: %s:%d", m_callLog.at(i-1).file.constData(), - m_callLog.at(i-1).line); - break; - } - } - if (i == m_callLog.size() && !m_callLog.isEmpty()) - qDebug("Caused some time after: %s:%d", qAsConst(m_callLog).first().file.constData(), - qAsConst(m_callLog).first().line); -#endif } static Qt::MouseButtons translateMouseButtons(int s) @@ -1067,17 +1007,6 @@ namespace { void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) { -#ifdef Q_XCB_DEBUG - { - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) - if (m_callLog.at(i).sequence >= event->sequence) - break; - m_callLog.remove(0, i); - } -#endif - long result = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result); @@ -1392,10 +1321,10 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) const xcb_window_t eventListener = xcb_generate_id(m_connection); xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); xcb_screen_t *screen = it.data; - Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, - eventListener, screen->root, - 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, - screen->root_visual, 0, 0)); + xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, + eventListener, screen->root, + 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, + screen->root_visual, 0, 0); event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; @@ -1404,8 +1333,8 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) event.type = atom(a); event.data.data32[0] = id; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event))); - Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener)); + xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event)); + xcb_destroy_window(m_connection, eventListener); xcb_flush(xcb_connection()); } @@ -1463,13 +1392,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp() xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const { - xcb_connection_t *c = xcb_connection(); - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom); - xcb_get_selection_owner_reply_t *reply; - reply = xcb_get_selection_owner_reply(c, cookie, 0); - xcb_window_t win = reply->owner; - free(reply); - return win; + return Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom)->owner; } xcb_window_t QXcbConnection::getQtSelectionOwner() @@ -1479,16 +1402,16 @@ xcb_window_t QXcbConnection::getQtSelectionOwner() int16_t x = 0, y = 0; uint16_t w = 3, h = 3; m_qtSelectionOwner = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_qtSelectionOwner, // window id - xcbScreen->root, // parent window id - x, y, w, h, - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - xcbScreen->root_visual, // visual - 0, // value mask - 0)); // value list + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_qtSelectionOwner, // window id + xcbScreen->root, // parent window id + x, y, w, h, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + xcbScreen->root_visual, // visual + 0, // value mask + 0); // value list } return m_qtSelectionOwner; } @@ -1504,47 +1427,47 @@ xcb_window_t QXcbConnection::clientLeader() if (m_clientLeader == 0) { m_clientLeader = xcb_generate_id(xcb_connection()); QXcbScreen *screen = primaryScreen(); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, - m_clientLeader, - screen->root(), - 0, 0, 1, 1, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - screen->screen()->root_visual, - 0, 0)); + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, + m_clientLeader, + screen->root(), + 0, 0, 1, 1, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->screen()->root_visual, + 0, 0); #ifndef QT_NO_DEBUG QByteArray ba("Qt client leader window"); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_clientLeader, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_clientLeader, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); #endif - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_clientLeader, - atom(QXcbAtom::WM_CLIENT_LEADER), - XCB_ATOM_WINDOW, - 32, - 1, - &m_clientLeader)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_clientLeader, + atom(QXcbAtom::WM_CLIENT_LEADER), + XCB_ATOM_WINDOW, + 32, + 1, + &m_clientLeader); #if !defined(QT_NO_SESSIONMANAGER) && defined(XCB_USE_SM) // If we are session managed, inform the window manager about it QByteArray session = qGuiApp->sessionId().toLatin1(); if (!session.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_clientLeader, - atom(QXcbAtom::SM_CLIENT_ID), - XCB_ATOM_STRING, - 8, - session.length(), - session.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_clientLeader, + atom(QXcbAtom::SM_CLIENT_ID), + XCB_ATOM_STRING, + 8, + session.length(), + session.constData()); } #endif } @@ -1995,11 +1918,7 @@ xcb_atom_t QXcbConnection::internAtom(const char *name) if (!name || *name == 0) return XCB_NONE; - xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name); - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0); - int atom = reply->atom; - free(reply); - return atom; + return Q_XCB_REPLY(xcb_intern_atom, xcb_connection(), false, strlen(name), name)->atom; } QByteArray QXcbConnection::atomName(xcb_atom_t atom) @@ -2007,18 +1926,12 @@ QByteArray QXcbConnection::atomName(xcb_atom_t atom) if (!atom) return QByteArray(); - xcb_generic_error_t *error = 0; - xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom)); - xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error); - if (error) { + auto reply = Q_XCB_REPLY(xcb_get_atom_name, xcb_connection(), atom); + if (!reply) qWarning() << "QXcbConnection::atomName: bad Atom" << atom; - free(error); - } - if (reply) { - QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); - free(reply); - return result; - } + else + return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get())); + return QByteArray(); } @@ -2040,29 +1953,24 @@ const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const void QXcbConnection::sync() { // from xcb_aux_sync - xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection())); + xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(xcb_connection()); free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); } void QXcbConnection::initializeXFixes() { - xcb_generic_error_t *error = 0; const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id); if (!reply || !reply->present) return; xfixes_first_event = reply->first_event; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection, - xfixes_query_cookie, &error); - if (!xfixes_query || error || xfixes_query->major_version < 2) { + auto xfixes_query = Q_XCB_REPLY(xcb_xfixes_query_version, m_connection, + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + if (!xfixes_query || xfixes_query->major_version < 2) { qWarning("QXcbConnection: Failed to initialize XFixes"); - free(error); xfixes_first_event = 0; } - free(xfixes_query); } void QXcbConnection::initializeXRender() @@ -2072,17 +1980,11 @@ void QXcbConnection::initializeXRender() if (!reply || !reply->present) return; - xcb_generic_error_t *error = 0; - xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection, - XCB_RENDER_MAJOR_VERSION, - XCB_RENDER_MINOR_VERSION); - xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection, - xrender_query_cookie, &error); - if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) { + auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection, + XCB_RENDER_MAJOR_VERSION, + XCB_RENDER_MINOR_VERSION); + if (!xrender_query || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) qWarning("QXcbConnection: Failed to initialize XRender"); - free(error); - } - free(xrender_query); #endif } @@ -2094,21 +1996,16 @@ void QXcbConnection::initializeXRandr() xrandr_first_event = reply->first_event; - xcb_generic_error_t *error = 0; - xcb_randr_query_version_cookie_t xrandr_query_cookie = xcb_randr_query_version(m_connection, - XCB_RANDR_MAJOR_VERSION, - XCB_RANDR_MINOR_VERSION); + auto xrandr_query = Q_XCB_REPLY(xcb_randr_query_version, m_connection, + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); has_randr_extension = true; - xcb_randr_query_version_reply_t *xrandr_query = xcb_randr_query_version_reply(m_connection, - xrandr_query_cookie, &error); - if (!xrandr_query || error || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) { + if (!xrandr_query || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) { qWarning("QXcbConnection: Failed to initialize XRandr"); - free(error); has_randr_extension = false; } - free(xrandr_query); xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup); for (; rootIter.rem; xcb_screen_next(&rootIter)) { @@ -2128,14 +2025,8 @@ void QXcbConnection::initializeXinerama() if (!reply || !reply->present) return; - xcb_generic_error_t *error = Q_NULLPTR; - xcb_xinerama_is_active_cookie_t xinerama_query_cookie = xcb_xinerama_is_active(m_connection); - xcb_xinerama_is_active_reply_t *xinerama_is_active = xcb_xinerama_is_active_reply(m_connection, - xinerama_query_cookie, - &error); - has_xinerama_extension = xinerama_is_active && !error && xinerama_is_active->state; - free(error); - free(xinerama_is_active); + auto xinerama_is_active = Q_XCB_REPLY(xcb_xinerama_is_active, m_connection); + has_xinerama_extension = xinerama_is_active && xinerama_is_active->state; } void QXcbConnection::initializeXShape() @@ -2145,16 +2036,13 @@ void QXcbConnection::initializeXShape() return; has_shape_extension = true; - xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection); - xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection, - cookie, NULL); + auto shape_query = Q_XCB_REPLY(xcb_shape_query_version, m_connection); if (!shape_query) { qWarning("QXcbConnection: Failed to initialize SHAPE extension"); } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) { // The input shape is the only thing added in SHAPE 1.1 has_input_shape = true; } - free(shape_query); } void QXcbConnection::initializeXKB() @@ -2169,11 +2057,10 @@ void QXcbConnection::initializeXKB() xkb_first_event = reply->first_event; xcb_connection_t *c = connection()->xcb_connection(); - xcb_xkb_use_extension_cookie_t xkb_query_cookie; - xcb_xkb_use_extension_reply_t *xkb_query; - xkb_query_cookie = xcb_xkb_use_extension(c, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION); - xkb_query = xcb_xkb_use_extension_reply(c, xkb_query_cookie, 0); + auto xkb_query = Q_XCB_REPLY(xcb_xkb_use_extension, c, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION); if (!xkb_query) { qWarning("Qt: Failed to initialize XKB extension"); @@ -2182,12 +2069,10 @@ void QXcbConnection::initializeXKB() qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)", XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION, xkb_query->serverMajor, xkb_query->serverMinor); - free(xkb_query); return; } has_xkb = true; - free(xkb_query); const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | @@ -2232,52 +2117,6 @@ bool QXcbConnection::xi2MouseEvents() const } #endif -#if defined(XCB_USE_XINPUT2) -static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number) -{ - int offset = 0; - for (int i = 0; i < maskLen; i++) { - if (number < 8) { - if ((maskPtr[i] & (1 << number)) == 0) - return -1; - } - for (int j = 0; j < 8; j++) { - if (j == number) - return offset; - if (maskPtr[i] & (1 << j)) - offset++; - } - number -= 8; - } - return -1; -} - -bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value) -{ - const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event); - const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1]; - const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4; - FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4); - - int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum); - if (valuatorOffset < 0) - return false; - - *value = valuatorsValuesAddr[valuatorOffset].integral; - *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16)); - return true; -} - -void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event) -{ - // xcb event structs contain stuff that wasn't on the wire, the full_sequence field - // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. - // Move this data back to have the same layout in memory as it was on the wire - // and allow casting, overwriting the full_sequence field. - memmove((char*) event + 32, (char*) event + 36, event->length * 4); -} -#endif // defined(XCB_USE_XINPUT2) - QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const { if (!m_systemTrayTracker) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6089265304..512a1d09b9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -56,6 +56,8 @@ #include <QtCore/QLoggingCategory> #include <QtCore/private/qglobal_p.h> +#include <memory> + // This is needed to make Qt compile together with XKB. xkb.h is using a variable // which is called 'explicit', this is a reserved keyword in c++ #if QT_CONFIG(xkb) @@ -81,8 +83,6 @@ struct XInput2TouchDeviceData; struct xcb_randr_get_output_info_reply_t; -//#define Q_XCB_DEBUG - QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput) @@ -647,23 +647,6 @@ private: } m_startSystemResizeInfo; #endif #endif -#ifdef Q_XCB_DEBUG - struct CallInfo { - int sequence; - QByteArray file; - int line; - }; - QVector<CallInfo> m_callLog; - QMutex m_callLogMutex; - void log(const char *file, int line, int sequence); - template <typename cookie_t> - friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, - const char *file, int line); - template <typename reply_t> - friend reply_t *q_xcb_call_template(reply_t *reply, QXcbConnection *connection, - const char *file, int line); -#endif - WindowMapper m_mapper; QVector<PeekFunc> m_peekFuncs; @@ -731,6 +714,20 @@ private: QXcbConnection *m_connection; }; +#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection + +#define Q_XCB_REPLY(call, ...) \ + std::unique_ptr<call##_reply_t, decltype(std::free) *>( \ + call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr), \ + std::free \ + ) + +#define Q_XCB_REPLY_UNCHECKED(call, ...) \ + std::unique_ptr<call##_reply_t, decltype(std::free) *>( \ + call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr), \ + std::free \ + ) + template <typename T> union q_padded_xcb_event { T event; @@ -744,30 +741,6 @@ union q_padded_xcb_event { q_padded_xcb_event<event_type> store = {}; \ auto &event_var = store.event; -#ifdef Q_XCB_DEBUG -template <typename cookie_t> -cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, - int line) -{ - connection->log(file, line, cookie.sequence); - return cookie; -} - -template <typename reply_t> -reply_t *q_xcb_call_template(reply_t *reply, QXcbConnection *connection, const char *file, int line) -{ - connection->log(file, line, reply->sequence); - return reply; -} -#define Q_XCB_CALL(x) q_xcb_call_template(x, connection(), __FILE__, __LINE__) -#define Q_XCB_CALL2(x, connection) q_xcb_call_template(x, connection, __FILE__, __LINE__) -#define Q_XCB_NOOP(c) q_xcb_call_template(xcb_no_operation(c->xcb_connection()), c, __FILE__, __LINE__); -#else -#define Q_XCB_CALL(x) x -#define Q_XCB_CALL2(x, connection) x -#define Q_XCB_NOOP(c) (void)c; -#endif - QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 14c138a911..c77e7b6269 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1011,6 +1011,50 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin #endif // XCB_USE_XINPUT21 } +static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number) +{ + int offset = 0; + for (int i = 0; i < maskLen; i++) { + if (number < 8) { + if ((maskPtr[i] & (1 << number)) == 0) + return -1; + } + for (int j = 0; j < 8; j++) { + if (j == number) + return offset; + if (maskPtr[i] & (1 << j)) + offset++; + } + number -= 8; + } + return -1; +} + +bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value) +{ + const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event); + const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1]; + const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4; + FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4); + + int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum); + if (valuatorOffset < 0) + return false; + + *value = valuatorsValuesAddr[valuatorOffset].integral; + *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16)); + return true; +} + +void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event) +{ + // xcb event structs contain stuff that wasn't on the wire, the full_sequence field + // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. + // Move this data back to have the same layout in memory as it was on the wire + // and allow casting, overwriting the full_sequence field. + memmove((char*) event + 32, (char*) event + 36, event->length * 4); +} + Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b) { switch (b) { diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index d257ab1242..d522e593fe 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -631,10 +631,9 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes *pos = QPoint(); xcb_window_t root = c->primaryVirtualDesktop()->root(); - xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root); - xcb_generic_error_t *err = 0; - xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err); - if (!err && reply) { + + auto reply = Q_XCB_REPLY(xcb_query_pointer, c->xcb_connection(), root); + if (reply) { if (virtualDesktop) { const auto virtualDesktops = c->virtualDesktops(); for (QXcbVirtualDesktop *vd : virtualDesktops) { @@ -648,11 +647,8 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes *pos = QPoint(reply->root_x, reply->root_y); if (keybMask) *keybMask = reply->mask; - free(reply); return; } - free(err); - free(reply); } QPoint QXcbCursor::pos() const diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 60d142157f..d4521de8e0 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -94,32 +94,27 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w) { xcb_window_t proxy = XCB_NONE; - xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, w, c->atom(QXcbAtom::XdndProxy), - XCB_ATOM_WINDOW, 0, 1), c); - xcb_get_property_reply_t *reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), + false, w, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1); if (reply && reply->type == XCB_ATOM_WINDOW) - proxy = *((xcb_window_t *)xcb_get_property_value(reply)); - free(reply); + proxy = *((xcb_window_t *)xcb_get_property_value(reply.get())); if (proxy == XCB_NONE) return proxy; // exists and is real? - cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, proxy, c->atom(QXcbAtom::XdndProxy), - XCB_ATOM_WINDOW, 0, 1), c); - reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0); + reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), + false, proxy, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1); if (reply && reply->type == XCB_ATOM_WINDOW) { - xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply)); + xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply.get())); if (proxy != p) proxy = 0; } else { proxy = 0; } - free(reply); - return proxy; } @@ -142,7 +137,7 @@ protected: QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c) { - dropData = new QXcbDropData(this); + m_dropData = new QXcbDropData(this); init(); cleanup_timer = -1; @@ -150,7 +145,7 @@ QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c) QXcbDrag::~QXcbDrag() { - delete dropData; + delete m_dropData; } void QXcbDrag::init() @@ -172,11 +167,6 @@ void QXcbDrag::init() drag_types.clear(); } -QMimeData *QXcbDrag::platformDropData() -{ - return dropData; -} - bool QXcbDrag::eventFilter(QObject *o, QEvent *e) { /* We are setting a mouse grab on the QShapedPixmapWindow in order not to @@ -228,28 +218,19 @@ void QXcbDrag::endDrag() initiatorWindow.clear(); } -static xcb_translate_coordinates_reply_t * -translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int x, int y) -{ - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(c->xcb_connection(), from, to, x, y); - return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0); -} - static bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType) { bool interacts = false; - xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL); + auto reply = Q_XCB_REPLY(xcb_shape_get_rectangles, connection, w, shapeType); if (reply) { - xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply); + xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply.get()); if (rectangles) { - const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply); + const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply.get()); for (int i = 0; !interacts && i < nRectangles; ++i) { interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos); } } - free(reply); } return interacts; @@ -261,33 +242,25 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md return 0; if (md) { - xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w); - xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_window_attributes, xcb_connection(), w); if (!reply) return 0; if (reply->map_state != XCB_MAP_STATE_VIEWABLE) return 0; - free(reply); - - xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w); - xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0); + auto greply = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), w); if (!greply) return 0; QRect windowRect(greply->x, greply->y, greply->width, greply->height); - free(greply); if (windowRect.contains(pos)) { bool windowContainsMouse = !ignoreNonXdndAwareWindows; { - xcb_get_property_cookie_t cookie = - Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware), - XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); - + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, w, connection()->atom(QXcbAtom::XdndAware), + XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool isAware = reply && reply->type != XCB_NONE; - free(reply); if (isAware) { const QPoint relPos = pos - windowRect.topLeft(); // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we @@ -303,19 +276,16 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md } } - xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w); - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0); - + auto reply = Q_XCB_REPLY(xcb_query_tree, xcb_connection(), w); if (!reply) return 0; - int nc = xcb_query_tree_children_length(reply); - xcb_window_t *c = xcb_query_tree_children(reply); + int nc = xcb_query_tree_children_length(reply.get()); + xcb_window_t *c = xcb_query_tree_children(reply.get()); xcb_window_t r = 0; for (uint i = nc; !r && i--;) r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows); - free(reply); if (r) return r; @@ -356,15 +326,14 @@ void QXcbDrag::move(const QPoint &globalPos) } xcb_window_t rootwin = current_virtual_desktop->root(); - xcb_translate_coordinates_reply_t *translate = - ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); + auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(), + rootwin, rootwin, globalPos.x(), globalPos.y()); if (!translate) return; xcb_window_t target = translate->child; int lx = translate->dst_x; int ly = translate->dst_y; - free (translate); if (target && target != rootwin) { xcb_window_t src = rootwin; @@ -372,7 +341,8 @@ void QXcbDrag::move(const QPoint &globalPos) DNDDEBUG << "checking target for XdndAware" << target << lx << ly; // translate coordinates - translate = ::translateCoordinates(connection(), src, target, lx, ly); + auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(), + src, target, lx, ly); if (!translate) { target = 0; break; @@ -381,14 +351,11 @@ void QXcbDrag::move(const QPoint &globalPos) ly = translate->dst_y; src = target; xcb_window_t child = translate->child; - free(translate); // check if it has XdndAware - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, target, - atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target, + atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool aware = reply && reply->type != XCB_NONE; - free(reply); if (aware) { DNDDEBUG << "Found XdndAware on " << target; break; @@ -422,16 +389,14 @@ void QXcbDrag::move(const QPoint &globalPos) int target_version = 1; if (proxy_target) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target, - atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, proxy_target, + atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); if (!reply || reply->type == XCB_NONE) target = 0; - target_version = *(uint32_t *)xcb_get_property_value(reply); + target_version = *(uint32_t *)xcb_get_property_value(reply.get()); target_version = qMin(xdnd_version, target_version ? target_version : 1); - - free(reply); } if (target != current_target) { @@ -714,21 +679,19 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve if (event->data.data32[1] & 1) { // get the types from XdndTypeList - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, xdnd_dragsource, - atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM, - 0, xdnd_max_type); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource, + atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM, + 0, xdnd_max_type); if (reply && reply->type != XCB_NONE && reply->format == 32) { - int length = xcb_get_property_value_length(reply) / 4; + int length = xcb_get_property_value_length(reply.get()) / 4; if (length > xdnd_max_type) length = xdnd_max_type; - xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); xdnd_types.reserve(length); for (int i = 0; i < length; ++i) xdnd_types.append(atoms[i]); } - free(reply); } else { // get the types from the message for(int i = 2; i < 5; i++) { @@ -769,7 +732,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message dropData = currentDrag()->mimeData(); supported_actions = currentDrag()->supportedActions(); } else { - dropData = platformDropData(); + dropData = m_dropData; supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); } @@ -812,8 +775,8 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message handle_xdnd_status(&response); else #endif - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target, - XCB_EVENT_MASK_NO_EVENT, (const char *)&response)); + xcb_send_event(xcb_connection(), false, current_proxy_target, + XCB_EVENT_MASK_NO_EVENT, (const char *)&response); } namespace @@ -990,7 +953,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e dropData = currentDrag()->mimeData(); supported_drop_actions = Qt::DropActions(l[4]); } else { - dropData = platformDropData(); + dropData = m_dropData; supported_drop_actions = accepted_drop_action; // Drop coming from another app? Update keyboard modifiers. @@ -1017,8 +980,8 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE; finished.data.data32[1] = response.isAccepted(); // flags finished.data.data32[2] = toXdndAction(response.acceptedAction()); - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target, - XCB_EVENT_MASK_NO_EVENT, (char *)&finished)); + xcb_send_event(xcb_connection(), false, current_proxy_target, + XCB_EVENT_MASK_NO_EVENT, (char *)&finished); xdnd_dragsource = 0; currentWindow.clear(); @@ -1132,28 +1095,20 @@ static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window) xcb_window_t target = 0; forever { // check if window has XdndAware - xcb_get_property_cookie_t gpCookie = Q_XCB_CALL( - xcb_get_property(c->xcb_connection(), false, window, - c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *gpReply = xcb_get_property_reply( - c->xcb_connection(), gpCookie, 0); + auto gpReply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), false, window, + c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool aware = gpReply && gpReply->type != XCB_NONE; - free(gpReply); if (aware) { target = window; break; } // try window's parent - xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL( - xcb_query_tree_unchecked(c->xcb_connection(), window)); - xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply( - c->xcb_connection(), qtCookie, NULL); + auto qtReply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, c->xcb_connection(), window); if (!qtReply) break; xcb_window_t root = qtReply->root; xcb_window_t parent = qtReply->parent; - free(qtReply); if (window == root) break; window = parent; diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 2d152edf76..f261cc1322 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -74,7 +74,6 @@ public: QXcbDrag(QXcbConnection *c); ~QXcbDrag(); - QMimeData *platformDropData() override; bool eventFilter(QObject *o, QEvent *e) override; void startDrag() override; @@ -117,7 +116,7 @@ private: QPointer<QWindow> currentWindow; QPoint currentPosition; - QXcbDropData *dropData; + QXcbDropData *m_dropData; Qt::DropAction accepted_drop_action; QWindow *desktop_proxy; diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index d4bdb6c771..67a959d8a4 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -91,19 +91,14 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap { xcb_connection_t *conn = connection->xcb_connection(); - xcb_get_image_cookie_t get_image_cookie = - xcb_get_image_unchecked(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, - 0, 0, width, height, 0xffffffff); - - xcb_get_image_reply_t *image_reply = - xcb_get_image_reply(conn, get_image_cookie, NULL); - + auto image_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_image, conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, + 0, 0, width, height, 0xffffffff); if (!image_reply) { return QPixmap(); } - uint8_t *data = xcb_get_image_data(image_reply); - uint32_t length = xcb_get_image_data_length(image_reply); + uint8_t *data = xcb_get_image_data(image_reply.get()); + uint32_t length = xcb_get_image_data_length(image_reply.get()); QPixmap result; @@ -165,7 +160,6 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap result = QPixmap::fromImage(image.copy()); } - free(image_reply); return result; } @@ -203,22 +197,15 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_connection_t *conn = screen->xcb_connection(); const int w = image.width(); const int h = image.height(); - xcb_generic_error_t *error = 0; - xcb_render_query_pict_formats_cookie_t formatsCookie = xcb_render_query_pict_formats(conn); - xcb_render_query_pict_formats_reply_t *formatsReply = xcb_render_query_pict_formats_reply(conn, - formatsCookie, - &error); - if (!formatsReply || error) { + auto formats = Q_XCB_REPLY(xcb_render_query_pict_formats, conn); + if (!formats) { qWarning("qt_xcb_createCursorXRender: query_pict_formats failed"); - free(formatsReply); - free(error); return XCB_NONE; } - xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply, + xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formats.get(), XCB_PICT_STANDARD_ARGB_32); if (!fmt) { qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32"); - free(formatsReply); return XCB_NONE; } @@ -230,14 +217,12 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, 0, 0, 0); if (!xi) { qWarning("qt_xcb_createCursorXRender: xcb_image_create failed"); - free(formatsReply); return XCB_NONE; } xi->data = (uint8_t *) malloc(xi->stride * h); if (!xi->data) { qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data"); xcb_image_destroy(xi); - free(formatsReply); return XCB_NONE; } memcpy(xi->data, img.constBits(), img.byteCount()); @@ -260,7 +245,6 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_image_destroy(xi); xcb_render_free_picture(conn, pic); xcb_free_pixmap(conn, pix); - free(formatsReply); return cursor; #else diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index b414bee204..396d8837e9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -83,6 +83,11 @@ #include <QtCore/QFileInfo> +#if QT_CONFIG(vulkan) +#include "qxcbvulkaninstance.h" +#include "qxcbvulkanwindow.h" +#endif + QT_BEGIN_NAMESPACE // Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,. @@ -199,11 +204,19 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const { QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle()); QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); - if (window->type() != Qt::Desktop && window->supportsOpenGL()) { - if (glIntegration) { - QXcbWindow *xcbWindow = glIntegration->createWindow(window); + if (window->type() != Qt::Desktop) { + if (window->supportsOpenGL()) { + if (glIntegration) { + QXcbWindow *xcbWindow = glIntegration->createWindow(window); + xcbWindow->create(); + return xcbWindow; + } +#if QT_CONFIG(vulkan) + } else if (window->surfaceType() == QSurface::VulkanSurface) { + QXcbWindow *xcbWindow = new QXcbVulkanWindow(window); xcbWindow->create(); return xcbWindow; +#endif } } @@ -498,4 +511,11 @@ void QXcbIntegration::beep() const xcb_bell(connection, 0); } +#if QT_CONFIG(vulkan) +QPlatformVulkanInstance *QXcbIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const +{ + return new QXcbVulkanInstance(instance); +} +#endif + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index baa5c9d835..6e12739138 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -113,6 +113,10 @@ public: void beep() const override; +#if QT_CONFIG(vulkan) + QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override; +#endif + static QXcbIntegration *instance() { return m_instance; } private: diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 2e29c208c7..891b53d2dc 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -612,23 +612,18 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const void QXcbKeyboard::readXKBConfig() { clearXKBConfig(); - xcb_generic_error_t *error; - xcb_get_property_cookie_t cookie; - xcb_get_property_reply_t *config_reply; xcb_connection_t *c = xcb_connection(); xcb_window_t rootWindow = connection()->rootWindow(); - cookie = xcb_get_property(c, 0, rootWindow, - atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024); - - config_reply = xcb_get_property_reply(c, cookie, &error); + auto config_reply = Q_XCB_REPLY(xcb_get_property, c, 0, rootWindow, + atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024); if (!config_reply) { qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property"); return; } - char *xkb_config = (char *)xcb_get_property_value(config_reply); - int length = xcb_get_property_value_length(config_reply); + char *xkb_config = (char *)xcb_get_property_value(config_reply.get()); + int length = xcb_get_property_value_length(config_reply.get()); // on old X servers xkb_config can be 0 even if config_reply indicates a succesfull read if (!xkb_config || length == 0) @@ -653,8 +648,6 @@ void QXcbKeyboard::readXKBConfig() xkb_names.layout = qstrdup(names[2]); xkb_names.variant = qstrdup(names[3]); xkb_names.options = qstrdup(names[4]); - - free(config_reply); } void QXcbKeyboard::clearXKBConfig() @@ -1172,23 +1165,19 @@ QXcbKeyboard::~QXcbKeyboard() void QXcbKeyboard::updateVModMapping() { #if QT_CONFIG(xkb) - xcb_xkb_get_names_cookie_t names_cookie; - xcb_xkb_get_names_reply_t *name_reply; xcb_xkb_get_names_value_list_t names_list; memset(&vmod_masks, 0, sizeof(vmod_masks)); - names_cookie = xcb_xkb_get_names(xcb_connection(), - XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); - - name_reply = xcb_xkb_get_names_reply(xcb_connection(), names_cookie, 0); + auto name_reply = Q_XCB_REPLY(xcb_xkb_get_names, xcb_connection(), + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); if (!name_reply) { qWarning("Qt: failed to retrieve the virtual modifier names from XKB"); return; } - const void *buffer = xcb_xkb_get_names_value_list(name_reply); + const void *buffer = xcb_xkb_get_names_value_list(name_reply.get()); xcb_xkb_get_names_value_list_unpack(buffer, name_reply->nTypes, name_reply->indicators, @@ -1233,32 +1222,27 @@ void QXcbKeyboard::updateVModMapping() else if (qstrcmp(vmod_name, "Hyper") == 0) vmod_masks.hyper = bit; } - - free(name_reply); #endif } void QXcbKeyboard::updateVModToRModMapping() { #if QT_CONFIG(xkb) - xcb_xkb_get_map_cookie_t map_cookie; - xcb_xkb_get_map_reply_t *map_reply; xcb_xkb_get_map_map_t map; memset(&rmod_masks, 0, sizeof(rmod_masks)); - map_cookie = xcb_xkb_get_map(xcb_connection(), - XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_MAP_PART_VIRTUAL_MODS, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - map_reply = xcb_xkb_get_map_reply(xcb_connection(), map_cookie, 0); + auto map_reply = Q_XCB_REPLY(xcb_xkb_get_map, + xcb_connection(), + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_MAP_PART_VIRTUAL_MODS, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (!map_reply) { qWarning("Qt: failed to retrieve the virtual modifier map from XKB"); return; } - const void *buffer = xcb_xkb_get_map_map(map_reply); + const void *buffer = xcb_xkb_get_map_map(map_reply.get()); xcb_xkb_get_map_map_unpack(buffer, map_reply->nTypes, map_reply->nKeySyms, @@ -1301,7 +1285,6 @@ void QXcbKeyboard::updateVModToRModMapping() rmod_masks.hyper = modmap; } - free(map_reply); resolveMaskConflicts(); #endif } @@ -1315,14 +1298,10 @@ void QXcbKeyboard::updateModifiers() // process for all modifiers whenever any part of the modifier mapping is changed. memset(&rmod_masks, 0, sizeof(rmod_masks)); - xcb_generic_error_t *error = 0; xcb_connection_t *conn = xcb_connection(); - xcb_get_modifier_mapping_cookie_t modMapCookie = xcb_get_modifier_mapping(conn); - xcb_get_modifier_mapping_reply_t *modMapReply = - xcb_get_modifier_mapping_reply(conn, modMapCookie, &error); - if (error) { + auto modMapReply = Q_XCB_REPLY(xcb_get_modifier_mapping, conn); + if (!modMapReply) { qWarning("Qt: failed to get modifier mapping"); - free(error); return; } @@ -1338,7 +1317,7 @@ void QXcbKeyboard::updateModifiers() for (size_t i = 0; i < numSymbols; ++i) modKeyCodes[i] = xcb_key_symbols_get_keycode(m_key_symbols, symbols[i]); - xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply); + xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply.get()); const int w = modMapReply->keycodes_per_modifier; for (size_t i = 0; i < numSymbols; ++i) { for (int bit = 0; bit < 8; ++bit) { @@ -1366,7 +1345,6 @@ void QXcbKeyboard::updateModifiers() for (size_t i = 0; i < numSymbols; ++i) free(modKeyCodes[i]); - free(modMapReply); resolveMaskConflicts(); } @@ -1449,8 +1427,6 @@ private: void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time) { - Q_XCB_NOOP(connection()); - if (!m_config) return; @@ -1471,30 +1447,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, updateXKBStateFromState(kb_state, state); xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code); - - QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); - QMetaMethod method; - - if (inputContext) { - int methodIndex = inputContext->metaObject()->indexOfMethod("x11FilterEvent(uint,uint,uint,bool)"); - if (methodIndex != -1) - method = inputContext->metaObject()->method(methodIndex); - } - - if (method.isValid()) { - bool retval = false; - method.invoke(inputContext, Qt::DirectConnection, - Q_RETURN_ARG(bool, retval), - Q_ARG(uint, sym), - Q_ARG(uint, code), - Q_ARG(uint, state), - Q_ARG(bool, type == QEvent::KeyPress)); - if (retval) { - xkb_state_unref(kb_state); - return; - } - } - QString string = lookupString(kb_state, code); // Ιf control modifier is set we should prefer latin character, this is @@ -1526,6 +1478,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, } bool filtered = false; + QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); if (inputContext) { QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); event.setTimestamp(time); @@ -1548,16 +1501,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, if (isAutoRepeat && type == QEvent::KeyRelease) { // since we removed it from the event queue using checkEvent we need to send the key press here filtered = false; - if (method.isValid()) { - method.invoke(inputContext, Qt::DirectConnection, - Q_RETURN_ARG(bool, filtered), - Q_ARG(uint, sym), - Q_ARG(uint, code), - Q_ARG(uint, state), - Q_ARG(bool, true)); - } - - if (!filtered && inputContext) { + if (inputContext) { QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); event.setTimestamp(time); filtered = inputContext->filterEvent(&event); diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 725288633a..eff38fc868 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -67,6 +67,10 @@ #include "qxcbnativeinterfacehandler.h" +#if QT_CONFIG(vulkan) +#include "qxcbvulkanwindow.h" +#endif + QT_BEGIN_NAMESPACE // return QXcbNativeInterface::ResourceType for the key. @@ -82,7 +86,8 @@ static int resourceType(const QByteArray &key) QByteArrayLiteral("rootwindow"), QByteArrayLiteral("subpixeltype"), QByteArrayLiteral("antialiasingenabled"), QByteArrayLiteral("atspibus"), - QByteArrayLiteral("compositingenabled") + QByteArrayLiteral("compositingenabled"), + QByteArrayLiteral("vksurface") }; const QByteArray *end = names + sizeof(names) / sizeof(names[0]); const QByteArray *result = std::find(names, end, key); @@ -121,28 +126,19 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const { if (m_sysTraySelectionAtom == XCB_ATOM_NONE) { const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1(); - xcb_intern_atom_cookie_t intern_c = - xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray); - - xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0); - + auto intern_r = Q_XCB_REPLY_UNCHECKED(xcb_intern_atom, conn, + true, net_sys_tray.length(), net_sys_tray); if (!intern_r) return XCB_WINDOW_NONE; m_sysTraySelectionAtom = intern_r->atom; - free(intern_r); } - xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom); - xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0); - + auto sel_owner_r = Q_XCB_REPLY_UNCHECKED(xcb_get_selection_owner, conn, m_sysTraySelectionAtom); if (!sel_owner_r) return XCB_WINDOW_NONE; - xcb_window_t selection_window = sel_owner_r->owner; - free(sel_owner_r); - - return selection_window; + return sel_owner_r->owner; } bool QXcbNativeInterface::systrayVisualHasAlphaChannel() @@ -266,6 +262,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr case Screen: result = screenForWindow(window); break; +#if QT_CONFIG(vulkan) + case VkSurface: + if (window->surfaceType() == QSurface::VulkanSurface && window->handle()) { + // return a pointer to the VkSurfaceKHR value, not the value itself + result = static_cast<QXcbVulkanWindow *>(window->handle())->surface(); + } + break; +#endif default: break; } @@ -457,21 +461,13 @@ void *QXcbNativeInterface::atspiBus() QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) { xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS"); - xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property( - defaultConnection->xcb_connection(), - false, defaultConnection->rootWindow(), - atspiBusAtom, XCB_ATOM_STRING, 0, 128), - defaultConnection); - xcb_get_property_reply_t *reply = Q_XCB_CALL2(xcb_get_property_reply( - defaultConnection->xcb_connection(), - cookie, 0), - defaultConnection); + auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(), + false, defaultConnection->rootWindow(), + atspiBusAtom, XCB_ATOM_STRING, 0, 128); Q_ASSERT(!reply->bytes_after); - char *data = (char *)xcb_get_property_value(reply); - int length = xcb_get_property_value_length(reply); - QByteArray *busAddress = new QByteArray(data, length); - free(reply); - return busAddress; + char *data = (char *)xcb_get_property_value(reply.get()); + int length = xcb_get_property_value_length(reply.get()); + return new QByteArray(data, length); } return 0; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 4186d77f4d..b9f1ebcdc6 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -73,7 +73,8 @@ public: ScreenSubpixelType, ScreenAntialiasingEnabled, AtspiBus, - CompositingEnabled + CompositingEnabled, + VkSurface }; QXcbNativeInterface(); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 5e136b5d7e..0fc872cf7e 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -65,6 +65,67 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t m_compositingActive = connection->getSelectionOwner(m_net_wm_cm_atom); m_workArea = getWorkArea(); + + readXResources(); + + auto rootAttribs = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(), + screen->root); + const quint32 existingEventMask = !rootAttribs ? 0 : rootAttribs->your_event_mask; + + const quint32 mask = XCB_CW_EVENT_MASK; + const quint32 values[] = { + // XCB_CW_EVENT_MASK + XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW + | XCB_EVENT_MASK_PROPERTY_CHANGE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification). + | existingEventMask // don't overwrite the event mask on the root window + }; + + xcb_change_window_attributes(xcb_connection(), screen->root, mask, values); + + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, screen->root, + atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), + XCB_ATOM_WINDOW, 0, 1024); + if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { + xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get())); + + if (windowManager != XCB_WINDOW_NONE) { + auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, windowManager, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), 0, 1024); + if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { + m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply.get()), + xcb_get_property_value_length(windowManagerReply.get())); + } + } + } + + const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id); + if (!sync_reply || !sync_reply->present) + m_syncRequestSupported = false; + else + m_syncRequestSupported = true; + + xcb_depth_iterator_t depth_iterator = + xcb_screen_allowed_depths_iterator(screen); + + while (depth_iterator.rem) { + xcb_depth_t *depth = depth_iterator.data; + xcb_visualtype_iterator_t visualtype_iterator = + xcb_depth_visuals_iterator(depth); + + while (visualtype_iterator.rem) { + xcb_visualtype_t *visualtype = visualtype_iterator.data; + m_visuals.insert(visualtype->visual_id, *visualtype); + m_visualDepths.insert(visualtype->visual_id, depth->depth); + xcb_visualtype_next(&visualtype_iterator); + } + + xcb_depth_next(&depth_iterator); + } } QXcbVirtualDesktop::~QXcbVirtualDesktop() @@ -123,18 +184,16 @@ void QXcbVirtualDesktop::subscribeToXFixesSelectionNotify() const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; - Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask)); + xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask); } } QRect QXcbVirtualDesktop::getWorkArea() const { QRect r; - xcb_get_property_reply_t * workArea = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - atom(QXcbAtom::_NET_WORKAREA), - XCB_ATOM_CARDINAL, 0, 1024), NULL); + auto workArea = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), false, screen()->root, + atom(QXcbAtom::_NET_WORKAREA), + XCB_ATOM_CARDINAL, 0, 1024); if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) { // If workArea->value_len > 4, the remaining ones seem to be for WM's virtual desktops // (don't mess with QXcbVirtualDesktop which represents an X screen). @@ -142,12 +201,11 @@ QRect QXcbVirtualDesktop::getWorkArea() const // "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop. // But for now just assume the first 4 values give us the geometry of the // "work area", AKA "available geometry" - uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea); + uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea.get()); r = QRect(geom[0], geom[1], geom[2], geom[3]); } else { r = QRect(QPoint(), size()); } - free(workArea); return r; } @@ -167,6 +225,170 @@ static inline QSizeF sizeInMillimeters(const QSize &size, const QDpi &dpi) Q_MM_PER_INCH * size.height() / dpi.second); } +bool QXcbVirtualDesktop::xResource(const QByteArray &identifier, + const QByteArray &expectedIdentifier, + QByteArray& stringValue) +{ + if (identifier.startsWith(expectedIdentifier)) { + stringValue = identifier.mid(expectedIdentifier.size()); + return true; + } + return false; +} + +static bool parseXftInt(const QByteArray& stringValue, int *value) +{ + Q_ASSERT(value != 0); + bool ok; + *value = stringValue.toInt(&ok); + return ok; +} + +static QFontEngine::HintStyle parseXftHintStyle(const QByteArray& stringValue) +{ + if (stringValue == "hintfull") + return QFontEngine::HintFull; + else if (stringValue == "hintnone") + return QFontEngine::HintNone; + else if (stringValue == "hintmedium") + return QFontEngine::HintMedium; + else if (stringValue == "hintslight") + return QFontEngine::HintLight; + + return QFontEngine::HintStyle(-1); +} + +static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stringValue) +{ + if (stringValue == "none") + return QFontEngine::Subpixel_None; + else if (stringValue == "rgb") + return QFontEngine::Subpixel_RGB; + else if (stringValue == "bgr") + return QFontEngine::Subpixel_BGR; + else if (stringValue == "vrgb") + return QFontEngine::Subpixel_VRGB; + else if (stringValue == "vbgr") + return QFontEngine::Subpixel_VBGR; + + return QFontEngine::SubpixelAntialiasingType(-1); +} + +void QXcbVirtualDesktop::readXResources() +{ + int offset = 0; + QByteArray resources; + while (true) { + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, screen()->root, + XCB_ATOM_RESOURCE_MANAGER, + XCB_ATOM_STRING, offset/4, 8192); + bool more = false; + if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { + resources += QByteArray((const char *)xcb_get_property_value(reply.get()), xcb_get_property_value_length(reply.get())); + offset += xcb_get_property_value_length(reply.get()); + more = reply->bytes_after != 0; + } + + if (!more) + break; + } + + QList<QByteArray> split = resources.split('\n'); + for (int i = 0; i < split.size(); ++i) { + const QByteArray &r = split.at(i); + int value; + QByteArray stringValue; + if (xResource(r, "Xft.dpi:\t", stringValue)) { + if (parseXftInt(stringValue, &value)) + m_forcedDpi = value; + } else if (xResource(r, "Xft.hintstyle:\t", stringValue)) { + m_hintStyle = parseXftHintStyle(stringValue); + } else if (xResource(r, "Xft.antialias:\t", stringValue)) { + if (parseXftInt(stringValue, &value)) + m_antialiasingEnabled = value; + } else if (xResource(r, "Xft.rgba:\t", stringValue)) { + m_subpixelType = parseXftRgba(stringValue); + } + } +} + +QSurfaceFormat QXcbVirtualDesktop::surfaceFormatFor(const QSurfaceFormat &format) const +{ + const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId() + : screen()->root_visual; + const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid); + + const int redSize = qPopulationCount(xcb_visualtype->red_mask); + const int greenSize = qPopulationCount(xcb_visualtype->green_mask); + const int blueSize = qPopulationCount(xcb_visualtype->blue_mask); + + QSurfaceFormat result = format; + + if (result.redBufferSize() < 0) + result.setRedBufferSize(redSize); + + if (result.greenBufferSize() < 0) + result.setGreenBufferSize(greenSize); + + if (result.blueBufferSize() < 0) + result.setBlueBufferSize(blueSize); + + return result; +} + +const xcb_visualtype_t *QXcbVirtualDesktop::visualForFormat(const QSurfaceFormat &format) const +{ + const xcb_visualtype_t *candidate = nullptr; + + for (const xcb_visualtype_t &xcb_visualtype : m_visuals) { + + const int redSize = qPopulationCount(xcb_visualtype.red_mask); + const int greenSize = qPopulationCount(xcb_visualtype.green_mask); + const int blueSize = qPopulationCount(xcb_visualtype.blue_mask); + const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize; + + if (format.redBufferSize() != -1 && redSize != format.redBufferSize()) + continue; + + if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize()) + continue; + + if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize()) + continue; + + if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize()) + continue; + + // Try to find a RGB visual rather than e.g. BGR or GBR + if (qCountTrailingZeroBits(xcb_visualtype.blue_mask) == 0) + return &xcb_visualtype; + + // In case we do not find anything we like, just remember the first one + // and hope for the best: + if (!candidate) + candidate = &xcb_visualtype; + } + + return candidate; +} + +const xcb_visualtype_t *QXcbVirtualDesktop::visualForId(xcb_visualid_t visualid) const +{ + QMap<xcb_visualid_t, xcb_visualtype_t>::const_iterator it = m_visuals.find(visualid); + if (it == m_visuals.constEnd()) + return 0; + return &*it; +} + +quint8 QXcbVirtualDesktop::depthOfVisual(xcb_visualid_t visualid) const +{ + QMap<xcb_visualid_t, quint8>::const_iterator it = m_visualDepths.find(visualid); + if (it == m_visualDepths.constEnd()) + return 0; + return *it; +} + QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, const xcb_xinerama_screen_info_t *xineramaScreenInfo, int xineramaScreenIdx) @@ -181,14 +403,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe { if (connection->hasXRandr()) { xcb_randr_select_input(xcb_connection(), screen()->root, true); - xcb_randr_get_crtc_info_cookie_t crtcCookie = - xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0); - xcb_randr_get_crtc_info_reply_t *crtc = - xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); + auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(), + m_crtc, output ? output->timestamp : 0); if (crtc) { updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); updateRefreshRate(crtc->mode); - free(crtc); } } else if (xineramaScreenInfo) { m_geometry = QRect(xineramaScreenInfo->x_org, xineramaScreenInfo->y_org, @@ -208,73 +427,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe if (m_sizeMillimeters.isEmpty()) m_sizeMillimeters = m_virtualSizeMillimeters; - readXResources(); - - QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs( - xcb_get_window_attributes_reply(xcb_connection(), - xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL)); - const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask; - - const quint32 mask = XCB_CW_EVENT_MASK; - const quint32 values[] = { - // XCB_CW_EVENT_MASK - XCB_EVENT_MASK_ENTER_WINDOW - | XCB_EVENT_MASK_LEAVE_WINDOW - | XCB_EVENT_MASK_PROPERTY_CHANGE - | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification). - | existingEventMask // don't overwrite the event mask on the root window - }; - - xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), - XCB_ATOM_WINDOW, 0, 1024), NULL); - - if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { - xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply)); - - if (windowManager != XCB_WINDOW_NONE) { - xcb_get_property_reply_t *windowManagerReply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, windowManager, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), 0, 1024), NULL); - if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { - m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply)); - } - - free(windowManagerReply); - } - } - free(reply); - - const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id); - if (!sync_reply || !sync_reply->present) - m_syncRequestSupported = false; - else - m_syncRequestSupported = true; - - xcb_depth_iterator_t depth_iterator = - xcb_screen_allowed_depths_iterator(screen()); - - while (depth_iterator.rem) { - xcb_depth_t *depth = depth_iterator.data; - xcb_visualtype_iterator_t visualtype_iterator = - xcb_depth_visuals_iterator(depth); - - while (visualtype_iterator.rem) { - xcb_visualtype_t *visualtype = visualtype_iterator.data; - m_visuals.insert(visualtype->visual_id, *visualtype); - m_visualDepths.insert(visualtype->visual_id, depth->depth); - xcb_visualtype_next(&visualtype_iterator); - } - - xcb_depth_next(&depth_iterator); - } - m_cursor = new QXcbCursor(connection, this); } @@ -311,12 +463,7 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const xcb_window_t child = root; do { - xcb_translate_coordinates_cookie_t translate_cookie = - xcb_translate_coordinates_unchecked(xcb_connection(), parent, child, x, y); - - xcb_translate_coordinates_reply_t *translate_reply = - xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL); - + auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, xcb_connection(), parent, child, x, y); if (!translate_reply) { return 0; } @@ -326,8 +473,6 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const x = translate_reply->dst_x; y = translate_reply->dst_y; - free(translate_reply); - if (!child || child == root) return 0; @@ -350,62 +495,12 @@ void QXcbScreen::windowShown(QXcbWindow *window) QSurfaceFormat QXcbScreen::surfaceFormatFor(const QSurfaceFormat &format) const { - const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId() - : screen()->root_visual; - const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid); - - const int redSize = qPopulationCount(xcb_visualtype->red_mask); - const int greenSize = qPopulationCount(xcb_visualtype->green_mask); - const int blueSize = qPopulationCount(xcb_visualtype->blue_mask); - - QSurfaceFormat result = format; - - if (result.redBufferSize() < 0) - result.setRedBufferSize(redSize); - - if (result.greenBufferSize() < 0) - result.setGreenBufferSize(greenSize); - - if (result.blueBufferSize() < 0) - result.setBlueBufferSize(blueSize); - - return result; + return m_virtualDesktop->surfaceFormatFor(format); } -const xcb_visualtype_t *QXcbScreen::visualForFormat(const QSurfaceFormat &format) const +const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const { - const xcb_visualtype_t *candidate = nullptr; - - for (const xcb_visualtype_t &xcb_visualtype : m_visuals) { - - const int redSize = qPopulationCount(xcb_visualtype.red_mask); - const int greenSize = qPopulationCount(xcb_visualtype.green_mask); - const int blueSize = qPopulationCount(xcb_visualtype.blue_mask); - const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize; - - if (format.redBufferSize() != -1 && redSize != format.redBufferSize()) - continue; - - if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize()) - continue; - - if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize()) - continue; - - if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize()) - continue; - - // Try to find a RGB visual rather than e.g. BGR or GBR - if (qCountTrailingZeroBits(xcb_visualtype.blue_mask) == 0) - return &xcb_visualtype; - - // In case we do not find anything we like, just remember the first one - // and hope for the best: - if (!candidate) - candidate = &xcb_visualtype; - } - - return candidate; + return m_virtualDesktop->visualForId(visualid); } void QXcbScreen::sendStartupMessage(const QByteArray &message) const @@ -434,22 +529,6 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const } while (sent < length); } -const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const -{ - QMap<xcb_visualid_t, xcb_visualtype_t>::const_iterator it = m_visuals.find(visualid); - if (it == m_visuals.constEnd()) - return 0; - return &*it; -} - -quint8 QXcbScreen::depthOfVisual(xcb_visualid_t visualid) const -{ - QMap<xcb_visualid_t, quint8>::const_iterator it = m_visualDepths.find(visualid); - if (it == m_visualDepths.constEnd()) - return 0; - return *it; -} - QImage::Format QXcbScreen::format() const { return qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual)); @@ -468,8 +547,9 @@ QDpi QXcbScreen::logicalDpi() const if (overrideDpi) return QDpi(overrideDpi, overrideDpi); - if (m_forcedDpi > 0) { - return QDpi(m_forcedDpi, m_forcedDpi); + const int forcedDpi = m_virtualDesktop->forcedDpi(); + if (forcedDpi > 0) { + return QDpi(forcedDpi, forcedDpi); } return virtualDpi(); } @@ -581,14 +661,10 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) if (!connection()->hasXRandr()) return; - xcb_randr_get_crtc_info_cookie_t crtcCookie = - xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp); - xcb_randr_get_crtc_info_reply_t *crtc = - xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); - if (crtc) { + auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(), + m_crtc, timestamp); + if (crtc) updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); - free(crtc); - } } void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) @@ -645,13 +721,11 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) // we can safely use get_screen_resources_current here, because in order to // get here, we must have called get_screen_resources before - xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), screen()->root); - xcb_randr_get_screen_resources_current_reply_t *resources = - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); + auto resources = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_screen_resources_current, + xcb_connection(), screen()->root); if (resources) { xcb_randr_mode_info_iterator_t modesIter = - xcb_randr_get_screen_resources_current_modes_iterator(resources); + xcb_randr_get_screen_resources_current_modes_iterator(resources.get()); for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { xcb_randr_mode_info_t *modeInfo = modesIter.data; if (modeInfo->id == mode) { @@ -662,29 +736,19 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) } } - free(resources); QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate); } } -static xcb_get_geometry_reply_t *getGeometryUnchecked(xcb_connection_t *connection, xcb_window_t window) -{ - const xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(connection, window); - return xcb_get_geometry_reply(connection, geometry_cookie, NULL); -} - static inline bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent, int *x, int *y) { - const xcb_translate_coordinates_cookie_t translate_cookie = - xcb_translate_coordinates_unchecked(connection, child, parent, *x, *y); - xcb_translate_coordinates_reply_t *translate_reply = - xcb_translate_coordinates_reply(connection, translate_cookie, NULL); + auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, + connection, child, parent, *x, *y); if (!translate_reply) return false; *x = translate_reply->dst_x; *y = translate_reply->dst_y; - free(translate_reply); return true; } @@ -698,22 +762,20 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig QXcbScreen *screen = const_cast<QXcbScreen *>(this); xcb_window_t root = screen->root(); - xcb_get_geometry_reply_t *rootReply = getGeometryUnchecked(xcb_connection(), root); + auto rootReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), root); if (!rootReply) return QPixmap(); const quint8 rootDepth = rootReply->depth; - free(rootReply); QSize windowSize; quint8 effectiveDepth = 0; if (window) { - xcb_get_geometry_reply_t *windowReply = getGeometryUnchecked(xcb_connection(), window); + auto windowReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), window); if (!windowReply) return QPixmap(); windowSize = QSize(windowReply->width, windowReply->height); effectiveDepth = windowReply->depth; - free(windowReply); if (effectiveDepth == rootDepth) { // if the depth of the specified window and the root window are the // same, grab pixels from the root window (so that we get the any @@ -738,14 +800,12 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig if (height < 0) height = windowSize.height() - yIn; - xcb_get_window_attributes_reply_t *attributes_reply = - xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL); + auto attributes_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(), window); if (!attributes_reply) return QPixmap(); const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); - free(attributes_reply); xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection()); xcb_create_pixmap(xcb_connection(), effectiveDepth, pixmap, window, width, height); @@ -765,98 +825,6 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig return result; } -static bool parseXftInt(const QByteArray& stringValue, int *value) -{ - Q_ASSERT(value != 0); - bool ok; - *value = stringValue.toInt(&ok); - return ok; -} - -static QFontEngine::HintStyle parseXftHintStyle(const QByteArray& stringValue) -{ - if (stringValue == "hintfull") - return QFontEngine::HintFull; - else if (stringValue == "hintnone") - return QFontEngine::HintNone; - else if (stringValue == "hintmedium") - return QFontEngine::HintMedium; - else if (stringValue == "hintslight") - return QFontEngine::HintLight; - - return QFontEngine::HintStyle(-1); -} - -static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stringValue) -{ - if (stringValue == "none") - return QFontEngine::Subpixel_None; - else if (stringValue == "rgb") - return QFontEngine::Subpixel_RGB; - else if (stringValue == "bgr") - return QFontEngine::Subpixel_BGR; - else if (stringValue == "vrgb") - return QFontEngine::Subpixel_VRGB; - else if (stringValue == "vbgr") - return QFontEngine::Subpixel_VBGR; - - return QFontEngine::SubpixelAntialiasingType(-1); -} - -bool QXcbScreen::xResource(const QByteArray &identifier, - const QByteArray &expectedIdentifier, - QByteArray& stringValue) -{ - if (identifier.startsWith(expectedIdentifier)) { - stringValue = identifier.mid(expectedIdentifier.size()); - return true; - } - return false; -} - -void QXcbScreen::readXResources() -{ - int offset = 0; - QByteArray resources; - while(1) { - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - XCB_ATOM_RESOURCE_MANAGER, - XCB_ATOM_STRING, offset/4, 8192), NULL); - bool more = false; - if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { - resources += QByteArray((const char *)xcb_get_property_value(reply), xcb_get_property_value_length(reply)); - offset += xcb_get_property_value_length(reply); - more = reply->bytes_after != 0; - } - - if (reply) - free(reply); - - if (!more) - break; - } - - QList<QByteArray> split = resources.split('\n'); - for (int i = 0; i < split.size(); ++i) { - const QByteArray &r = split.at(i); - int value; - QByteArray stringValue; - if (xResource(r, "Xft.dpi:\t", stringValue)) { - if (parseXftInt(stringValue, &value)) - m_forcedDpi = value; - } else if (xResource(r, "Xft.hintstyle:\t", stringValue)) { - m_hintStyle = parseXftHintStyle(stringValue); - } else if (xResource(r, "Xft.antialias:\t", stringValue)) { - if (parseXftInt(stringValue, &value)) - m_antialiasingEnabled = value; - } else if (xResource(r, "Xft.rgba:\t", stringValue)) { - m_subpixelType = parseXftRgba(stringValue); - } - } -} - QXcbXSettings *QXcbScreen::xSettings() const { return m_virtualDesktop->xSettings(); diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 4163be2969..21f583ccf7 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -91,9 +91,28 @@ public: void handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event); void subscribeToXFixesSelectionNotify(); + int forcedDpi() const { return m_forcedDpi; } + QFontEngine::HintStyle hintStyle() const { return m_hintStyle; } + QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_subpixelType; } + int antialiasingEnabled() const { return m_antialiasingEnabled; } + + QString windowManagerName() const { return m_windowManagerName; } + bool syncRequestSupported() const { return m_syncRequestSupported; } + + QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const; + + const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const; + const xcb_visualtype_t *visualForId(xcb_visualid_t) const; + quint8 depthOfVisual(xcb_visualid_t) const; + private: QRect getWorkArea() const; + static bool xResource(const QByteArray &identifier, + const QByteArray &expectedIdentifier, + QByteArray &stringValue); + void readXResources(); + xcb_screen_t *m_screen; const int m_number; QList<QPlatformScreen *> m_screens; @@ -103,6 +122,15 @@ private: bool m_compositingActive = false; QRect m_workArea; + + int m_forcedDpi = -1; + QFontEngine::HintStyle m_hintStyle = QFontEngine::HintStyle(-1); + QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1); + int m_antialiasingEnabled = -1; + QString m_windowManagerName; + bool m_syncRequestSupported = false; + QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals; + QMap<xcb_visualid_t, quint8> m_visualDepths; }; class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen @@ -152,14 +180,14 @@ public: void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; } void windowShown(QXcbWindow *window); - QString windowManagerName() const { return m_windowManagerName; } - bool syncRequestSupported() const { return m_syncRequestSupported; } + QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); } + bool syncRequestSupported() const { return m_virtualDesktop->syncRequestSupported(); } QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const; - const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const; - const xcb_visualtype_t *visualForId(xcb_visualid_t) const; - quint8 depthOfVisual(xcb_visualid_t) const; + const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const { return m_virtualDesktop->visualForFormat(format); } + const xcb_visualtype_t *visualForId(xcb_visualid_t visualid) const; + quint8 depthOfVisual(xcb_visualid_t visualid) const { return m_virtualDesktop->depthOfVisual(visualid); } QString name() const override { return m_outputName; } @@ -169,18 +197,13 @@ public: void updateAvailableGeometry(); void updateRefreshRate(xcb_randr_mode_t mode); - void readXResources(); - - QFontEngine::HintStyle hintStyle() const { return m_hintStyle; } - QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_subpixelType; } - int antialiasingEnabled() const { return m_antialiasingEnabled; } + QFontEngine::HintStyle hintStyle() const { return m_virtualDesktop->hintStyle(); } + QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_virtualDesktop->subpixelType(); } + int antialiasingEnabled() const { return m_virtualDesktop->antialiasingEnabled(); } QXcbXSettings *xSettings() const; private: - static bool xResource(const QByteArray &identifier, - const QByteArray &expectedIdentifier, - QByteArray &stringValue); void sendStartupMessage(const QByteArray &message) const; QXcbVirtualDesktop *m_virtualDesktop; @@ -198,17 +221,9 @@ private: QSize m_virtualSize; QSizeF m_virtualSizeMillimeters; Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; - QString m_windowManagerName; - bool m_syncRequestSupported = false; - QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals; - QMap<xcb_visualid_t, quint8> m_visualDepths; QXcbCursor *m_cursor; int m_refreshRate = 60; - int m_forcedDpi = -1; int m_pixelDensity = 1; - QFontEngine::HintStyle m_hintStyle = QFontEngine::HintStyle(-1); - QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1); - int m_antialiasingEnabled = -1; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index fb0a4a3939..c98879c7df 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -85,13 +85,10 @@ QXcbSystemTrayTracker::QXcbSystemTrayTracker(QXcbConnection *connection, xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection) { - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(connection->xcb_connection(), selection); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(connection->xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, connection->xcb_connection(), selection); if (!reply) return 0; - const xcb_window_t result = reply->owner; - free(reply); - return result; + return reply->owner; } // API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Request a window @@ -119,7 +116,7 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow() m_connection->addWindowEventListener(m_trayWindow, this); const quint32 mask = XCB_CW_EVENT_MASK; const quint32 value = XCB_EVENT_MASK_STRUCTURE_NOTIFY; - Q_XCB_CALL2(xcb_change_window_attributes(m_connection->xcb_connection(), m_trayWindow, mask, &value), m_connection); + xcb_change_window_attributes(m_connection->xcb_connection(), m_trayWindow, mask, &value); } } return m_trayWindow; @@ -130,23 +127,16 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow() // does not work for the QWindow parented on the tray. QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const { - xcb_connection_t *conn = m_connection->xcb_connection(); - xcb_get_geometry_reply_t *geomReply = - xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), 0); + auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window); if (!geomReply) return QRect(); - xcb_translate_coordinates_reply_t *translateReply = - xcb_translate_coordinates_reply(conn, xcb_translate_coordinates(conn, window, m_connection->rootWindow(), 0, 0), 0); - if (!translateReply) { - free(geomReply); + auto translateReply = Q_XCB_REPLY(xcb_translate_coordinates, conn, window, m_connection->rootWindow(), 0, 0); + if (!translateReply) return QRect(); - } - const QRect result(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height)); - free(translateReply); - return result; + return QRect(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height)); } inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged() @@ -180,24 +170,18 @@ bool QXcbSystemTrayTracker::visualHasAlphaChannel() xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL); // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom - xcb_get_property_cookie_t systray_atom_cookie; - xcb_get_property_reply_t *systray_atom_reply; - - systray_atom_cookie = xcb_get_property_unchecked(m_connection->xcb_connection(), false, m_trayWindow, + auto systray_atom_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, m_connection->xcb_connection(), + false, m_trayWindow, tray_atom, XCB_ATOM_VISUALID, 0, 1); - systray_atom_reply = xcb_get_property_reply(m_connection->xcb_connection(), systray_atom_cookie, 0); - if (!systray_atom_reply) return false; xcb_visualid_t systrayVisualId = XCB_NONE; - if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) { - xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply); + if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply.get()) > 0) { + xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply.get()); systrayVisualId = vids[0]; } - free(systray_atom_reply); - if (systrayVisualId != XCB_NONE) { quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId); return depth == 32; diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp new file mode 100644 index 0000000000..4d540defa9 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbvulkaninstance.h" +#include "qxcbwindow.h" +#include "qxcbscreen.h" + +QT_BEGIN_NAMESPACE + +QXcbVulkanInstance::QXcbVulkanInstance(QVulkanInstance *instance) + : m_instance(instance), + m_getPhysDevPresSupport(nullptr), + m_createSurface(nullptr), + m_destroySurface(nullptr) +{ + if (qEnvironmentVariableIsSet("QT_VULKAN_LIB")) + m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB"))); + else + m_lib.setFileName(QStringLiteral("vulkan")); + + if (!m_lib.load()) { + qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString())); + return; + } + + init(&m_lib); +} + +QXcbVulkanInstance::~QXcbVulkanInstance() +{ +} + +void QXcbVulkanInstance::createOrAdoptInstance() +{ + initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_xcb_surface")); + + if (!m_vkInst) + return; + + m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceXcbPresentationSupportKHR")); + if (!m_getPhysDevPresSupport) + qWarning("Failed to find vkGetPhysicalDeviceXcbPresentationSupportKHR"); +} + +bool QXcbVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + QWindow *window) +{ + if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport) + return true; + + QXcbWindow *w = static_cast<QXcbWindow *>(window->handle()); + if (!w) { + qWarning("Attempted to call supportsPresent() without a valid platform window"); + return false; + } + xcb_connection_t *connection = w->xcbScreen()->xcb_connection(); + bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex, connection, w->visualId()); + + VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window); + VkBool32 supported = false; + m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported); + ok &= bool(supported); + + return ok; +} + +VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window) +{ + VkSurfaceKHR surface = 0; + + if (!m_createSurface) { + m_createSurface = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkCreateXcbSurfaceKHR")); + } + if (!m_createSurface) { + qWarning("Failed to find vkCreateXcbSurfaceKHR"); + return surface; + } + if (!m_destroySurface) { + m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>( + m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR")); + } + if (!m_destroySurface) { + qWarning("Failed to find vkDestroySurfaceKHR"); + return surface; + } + + VkXcbSurfaceCreateInfoKHR surfaceInfo; + memset(&surfaceInfo, 0, sizeof(surfaceInfo)); + surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surfaceInfo.connection = window->xcbScreen()->xcb_connection(); + surfaceInfo.window = window->xcb_window(); + VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); + if (err != VK_SUCCESS) + qWarning("Failed to create Vulkan surface: %d", err); + + return surface; +} + +void QXcbVulkanInstance::destroySurface(VkSurfaceKHR surface) +{ + if (m_destroySurface && surface) + m_destroySurface(m_vkInst, surface, nullptr); +} + +void QXcbVulkanInstance::presentQueued(QWindow *window) +{ + QXcbWindow *w = static_cast<QXcbWindow *>(window->handle()); + if (!w) { + qWarning("Attempted to call presentQueued() without a valid platform window"); + return; + } + + if (w->needsSync()) + w->postSyncWindowRequest(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.h b/src/plugins/platforms/xcb/qxcbvulkaninstance.h new file mode 100644 index 0000000000..dbe057d944 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBVULKANINSTANCE_H +#define QXCBVULKANINSTANCE_H + +#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_XCB_KHR) +#error "vulkan.h included without xcb WSI" +#endif + +#define VK_USE_PLATFORM_XCB_KHR + +#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h> +#include <QLibrary> + +QT_BEGIN_NAMESPACE + +class QXcbWindow; + +class QXcbVulkanInstance : public QBasicPlatformVulkanInstance +{ +public: + QXcbVulkanInstance(QVulkanInstance *instance); + ~QXcbVulkanInstance(); + + void createOrAdoptInstance() override; + bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; + void presentQueued(QWindow *window) override; + + VkSurfaceKHR createSurface(QXcbWindow *window); + void destroySurface(VkSurfaceKHR surface); + +private: + QVulkanInstance *m_instance; + QLibrary m_lib; + PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR m_getPhysDevPresSupport; + PFN_vkCreateXcbSurfaceKHR m_createSurface; + PFN_vkDestroySurfaceKHR m_destroySurface; +}; + +QT_END_NAMESPACE + +#endif // QXCBVULKANINSTANCE_H diff --git a/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp new file mode 100644 index 0000000000..25bc340f97 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbvulkanwindow.h" + +QT_BEGIN_NAMESPACE + +QXcbVulkanWindow::QXcbVulkanWindow(QWindow *window) + : QXcbWindow(window), + m_surface(0) +{ +} + +QXcbVulkanWindow::~QXcbVulkanWindow() +{ + if (m_surface) { + QVulkanInstance *inst = window()->vulkanInstance(); + if (inst) + static_cast<QXcbVulkanInstance *>(inst->handle())->destroySurface(m_surface); + } +} + +void QXcbVulkanWindow::resolveFormat(const QSurfaceFormat &format) +{ + m_format = format; + if (m_format.redBufferSize() <= 0) + m_format.setRedBufferSize(8); + if (m_format.greenBufferSize() <= 0) + m_format.setGreenBufferSize(8); + if (m_format.blueBufferSize() <= 0) + m_format.setBlueBufferSize(8); +} + +// No createVisual() needed, use the default that picks one based on the R/G/B/A size. + +VkSurfaceKHR *QXcbVulkanWindow::surface() +{ + if (m_surface) + return &m_surface; + + QVulkanInstance *inst = window()->vulkanInstance(); + if (!inst) { + qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?"); + return nullptr; + } + QXcbVulkanInstance *xcbinst = static_cast<QXcbVulkanInstance *>(inst->handle()); + m_surface = xcbinst->createSurface(this); + + return &m_surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbvulkanwindow.h b/src/plugins/platforms/xcb/qxcbvulkanwindow.h new file mode 100644 index 0000000000..43c96820c5 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbvulkanwindow.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBVULKANWINDOW_H +#define QXCBVULKANWINDOW_H + +#include "qxcbwindow.h" +#include "qxcbvulkaninstance.h" + +QT_BEGIN_NAMESPACE + +class QXcbVulkanWindow : public QXcbWindow +{ +public: + QXcbVulkanWindow(QWindow *window); + ~QXcbVulkanWindow(); + + VkSurfaceKHR *surface(); + +protected: + void resolveFormat(const QSurfaceFormat &format) override; + +private: + VkSurfaceKHR m_surface; +}; + +QT_END_NAMESPACE + +#endif // QXCBVULKANWINDOW_H diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6365a6e9cb..ff4408e3f1 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -412,6 +412,19 @@ void QXcbWindow::create() qWarning() << "Failed to use requested visual id."; } + if (parent()) { + // When using a Vulkan QWindow via QWidget::createWindowContainer() we + // must make sure the visuals are compatible. Now, the parent will be + // of RasterGLSurface which typically chooses a GLX/EGL compatible + // visual which may not be what the Vulkan window would choose. + // Therefore, take the parent's visual. + if (window()->surfaceType() == QSurface::VulkanSurface + && parent()->window()->surfaceType() != QSurface::VulkanSurface) + { + visual = platformScreen->visualForId(static_cast<QXcbWindow *>(parent())->visualId()); + } + } + if (!visual) visual = createVisual(); @@ -437,11 +450,11 @@ void QXcbWindow::create() if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) { m_cmap = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_colormap(xcb_connection(), - XCB_COLORMAP_ALLOC_NONE, - m_cmap, - xcb_parent_id, - m_visualId)); + xcb_create_colormap(xcb_connection(), + XCB_COLORMAP_ALLOC_NONE, + m_cmap, + xcb_parent_id, + m_visualId); mask |= XCB_CW_COLORMAP; } @@ -457,23 +470,23 @@ void QXcbWindow::create() }; m_window = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - m_depth, - m_window, // window id - xcb_parent_id, // parent window id - rect.x(), - rect.y(), - rect.width(), - rect.height(), - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_visualId, // visual - mask, - values)); + xcb_create_window(xcb_connection(), + m_depth, + m_window, // window id + xcb_parent_id, // parent window id + rect.x(), + rect.y(), + rect.width(), + rect.height(), + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_visualId, // visual + mask, + values); connection()->addWindowEventListener(m_window, this); - Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); propagateSizeHints(); @@ -491,43 +504,43 @@ void QXcbWindow::create() if (window()->flags() & Qt::WindowContextHelpButtonHint) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::WM_PROTOCOLS), - XCB_ATOM_ATOM, - 32, - propertyCount, - properties)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::WM_PROTOCOLS), + XCB_ATOM_ATOM, + 32, + propertyCount, + properties); m_syncValue.hi = 0; m_syncValue.lo = 0; const QByteArray wmClass = QXcbIntegration::instance()->wmClass(); if (!wmClass.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, - m_window, atom(QXcbAtom::WM_CLASS), - XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, + m_window, atom(QXcbAtom::WM_CLASS), + XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData()); } if (m_usingSyncProtocol) { m_syncCounter = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), - XCB_ATOM_CARDINAL, - 32, - 1, - &m_syncCounter)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), + XCB_ATOM_CARDINAL, + 32, + 1, + &m_syncCounter); } // set the PID to let the WM kill the application if unresponsive quint32 pid = getpid(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, - 1, &pid)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, + 1, &pid); xcb_wm_hints_t hints; memset(&hints, 0, sizeof(hints)); @@ -538,23 +551,23 @@ void QXcbWindow::create() xcb_set_wm_hints(xcb_connection(), m_window, &hints); xcb_window_t leader = connection()->clientLeader(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, - 1, &leader)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, + 1, &leader); /* Add XEMBED info; this operation doesn't initiate the embedding. */ quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED }; - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_XEMBED_INFO), - atom(QXcbAtom::_XEMBED_INFO), - 32, 2, (void *)data)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_XEMBED_INFO), + atom(QXcbAtom::_XEMBED_INFO), + 32, 2, (void *)data); #if defined(XCB_USE_XINPUT2) connection()->xi2Select(m_window); #endif - setWindowState(window()->windowState()); + setWindowState(window()->windowStates()); setWindowFlags(window()->flags()); setWindowTitle(window()->title()); @@ -606,7 +619,7 @@ void QXcbWindow::destroy() connection()->setMouseGrabber(Q_NULLPTR); if (m_syncCounter && m_usingSyncProtocol) - Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); + xcb_sync_destroy_counter(xcb_connection(), m_syncCounter); if (m_window) { if (m_netWmUserTimeWindow) { xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW)); @@ -617,7 +630,7 @@ void QXcbWindow::destroy() m_netWmUserTimeWindow = XCB_NONE; } connection()->removeWindowEventListener(m_window); - Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); + xcb_destroy_window(xcb_connection(), m_window); m_window = 0; } if (m_cmap) { @@ -652,7 +665,7 @@ void QXcbWindow::setGeometry(const QRect &rect) qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values))); + xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)); } else { const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const qint32 values[] = { @@ -661,7 +674,7 @@ void QXcbWindow::setGeometry(const QRect &rect) qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values))); + xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)); } xcb_flush(xcb_connection()); @@ -671,12 +684,10 @@ QMargins QXcbWindow::frameMargins() const { if (m_dirtyFrameMargins) { if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_FRAME_EXTENTS))) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, m_window, - atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); - QScopedPointer<xcb_get_property_reply_t, QScopedPointerPodDeleter> reply( - xcb_get_property_reply(xcb_connection(), cookie, NULL)); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, m_window, + atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); if (reply && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && reply->value_len == 4) { - quint32 *data = (quint32 *)xcb_get_property_value(reply.data()); + quint32 *data = (quint32 *)xcb_get_property_value(reply.get()); // _NET_FRAME_EXTENTS format is left, right, top, bottom m_frameMargins = QMargins(data[0], data[2], data[1], data[3]); m_dirtyFrameMargins = false; @@ -695,9 +706,7 @@ QMargins QXcbWindow::frameMargins() const connection()->wmSupport()->virtualRoots(); while (!foundRoot) { - xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked(xcb_connection(), parent); - - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, xcb_connection(), parent); if (reply) { if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) { foundRoot = true; @@ -705,8 +714,6 @@ QMargins QXcbWindow::frameMargins() const window = parent; parent = reply->parent; } - - free(reply); } else { m_dirtyFrameMargins = false; m_frameMargins = QMargins(); @@ -716,23 +723,12 @@ QMargins QXcbWindow::frameMargins() const QPoint offset; - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply( - xcb_connection(), - xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0), - NULL); - + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), window, parent, 0, 0); if (reply) { offset = QPoint(reply->dst_x, reply->dst_y); - free(reply); } - xcb_get_geometry_reply_t *geom = - xcb_get_geometry_reply( - xcb_connection(), - xcb_get_geometry(xcb_connection(), parent), - NULL); - + auto geom = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), parent); if (geom) { // -- // add the border_width for the window managers frame... some window managers @@ -749,8 +745,6 @@ QMargins QXcbWindow::frameMargins() const int bottom = geom->height + geom->border_width - geometry().height() - offset.y(); m_frameMargins = QMargins(left, top, right, bottom); - - free(geom); } m_dirtyFrameMargins = false; @@ -777,12 +771,13 @@ static inline bool testShowWithoutActivating(const QWindow *window) void QXcbWindow::show() { if (window()->isTopLevel()) { + xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window); xcb_wm_hints_t hints; xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL); - if (window()->windowState() & Qt::WindowMinimized) + if (window()->windowStates() & Qt::WindowMinimized) xcb_wm_hints_set_iconic(&hints); else xcb_wm_hints_set_normal(&hints); @@ -808,13 +803,13 @@ void QXcbWindow::show() if (!transientXcbParent) transientXcbParent = connection()->clientLeader(); if (transientXcbParent) { // ICCCM 4.1.2.6 - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, - 1, &transientXcbParent)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &transientXcbParent); } } if (!transientXcbParent) - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR)); + xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR); // update _MOTIF_WM_HINTS updateMotifWmHintsBeforeMap(); @@ -831,7 +826,7 @@ void QXcbWindow::show() if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow")) return; // defer showing until XEMBED_EMBEDDED_NOTIFY - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + xcb_map_window(xcb_connection(), m_window); if (QGuiApplication::modalWindow() == window()) requestActivateWindow(); @@ -843,7 +838,7 @@ void QXcbWindow::show() void QXcbWindow::hide() { - Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); + xcb_unmap_window(xcb_connection(), m_window); // send synthetic UnmapNotify event according to icccm 4.1.4 Q_DECLARE_XCB_EVENT(event, xcb_unmap_notify_event_t); @@ -851,8 +846,8 @@ void QXcbWindow::hide() event.event = xcbScreen()->root(); event.window = m_window; event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), false, xcbScreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event); xcb_flush(xcb_connection()); @@ -1000,15 +995,11 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) { QtMotifWmHints hints; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS), - c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(c->xcb_connection(), get_cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, c->xcb_connection(), 0, window, + c->atom(QXcbAtom::_MOTIF_WM_HINTS), c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) { - hints = *((QtMotifWmHints *)xcb_get_property_value(reply)); + hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get())); } else { hints.flags = 0L; hints.functions = MWM_FUNC_ALL; @@ -1017,24 +1008,22 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) hints.status = 0L; } - free(reply); - return hints; } static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints) { if (hints.flags != 0l) { - Q_XCB_CALL2(xcb_change_property(c->xcb_connection(), - XCB_PROP_MODE_REPLACE, - window, - c->atom(QXcbAtom::_MOTIF_WM_HINTS), - c->atom(QXcbAtom::_MOTIF_WM_HINTS), - 32, - 5, - &hints), c); + xcb_change_property(c->xcb_connection(), + XCB_PROP_MODE_REPLACE, + window, + c->atom(QXcbAtom::_MOTIF_WM_HINTS), + c->atom(QXcbAtom::_MOTIF_WM_HINTS), + 32, + 5, + &hints); } else { - Q_XCB_CALL2(xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)), c); + xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)); } } @@ -1042,15 +1031,12 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() { NetWmStates result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *statesEnd = states + reply->length; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE))) result |= NetWmStateAbove; @@ -1068,7 +1054,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() result |= NetWmStateStaysOnTop; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) result |= NetWmStateDemandsAttention; - free(reply); } else { #ifdef NET_WM_STATE_DEBUG printf("getting net wm state (%x), empty\n", m_window); @@ -1082,21 +1067,15 @@ void QXcbWindow::setNetWmStates(NetWmStates states) { QVector<xcb_atom_t> atoms; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) { - const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); atoms.resize(reply->value_len); memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t)); } - free(reply); - if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) @@ -1115,11 +1094,11 @@ void QXcbWindow::setNetWmStates(NetWmStates states) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); if (atoms.isEmpty()) { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE))); + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE)); } else { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32, - atoms.count(), atoms.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32, + atoms.count(), atoms.constData()); } xcb_flush(xcb_connection()); } @@ -1242,67 +1221,48 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); } -void QXcbWindow::setWindowState(Qt::WindowState state) +void QXcbWindow::setWindowState(Qt::WindowStates state) { if (state == m_windowState) return; - // unset old state - switch (m_windowState) { - case Qt::WindowMinimized: - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); - break; - case Qt::WindowMaximized: - changeNetWmState(false, - atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ), - atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); - break; - case Qt::WindowFullScreen: - changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - break; - default: - break; + if ((m_windowState & Qt::WindowMinimized) && !(state & Qt::WindowMinimized)) { + xcb_map_window(xcb_connection(), m_window); + } else if (!(m_windowState & Qt::WindowMinimized) && (state & Qt::WindowMinimized)) { + xcb_client_message_event_t event; + + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.sequence = 0; + event.window = m_window; + event.type = atom(QXcbAtom::WM_CHANGE_STATE); + event.data.data32[0] = XCB_WM_STATE_ICONIC; + event.data.data32[1] = 0; + event.data.data32[2] = 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); + m_minimized = true; } - // set new state - switch (state) { - case Qt::WindowMinimized: - { - xcb_client_message_event_t event; - - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.sequence = 0; - event.window = m_window; - event.type = atom(QXcbAtom::WM_CHANGE_STATE); - event.data.data32[0] = XCB_WM_STATE_ICONIC; - event.data.data32[1] = 0; - event.data.data32[2] = 0; - event.data.data32[3] = 0; - event.data.data32[4] = 0; - - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); - } - break; - case Qt::WindowMaximized: - changeNetWmState(true, - atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ), + if ((m_windowState ^ state) & Qt::WindowMaximized) { + changeNetWmState(state & Qt::WindowMaximized, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ), atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); - break; - case Qt::WindowFullScreen: - changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - break; - case Qt::WindowNoState: - break; - default: - break; } - connection()->sync(); + if ((m_windowState ^ state) & Qt::WindowFullScreen) { + changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); + } + connection()->sync(); m_windowState = state; } @@ -1374,10 +1334,10 @@ void QXcbWindow::updateNetWmStateBeforeMap() states |= NetWmStateBelow; } - if (window()->windowState() & Qt::WindowFullScreen) + if (window()->windowStates() & Qt::WindowFullScreen) states |= NetWmStateFullScreen; - if (window()->windowState() & Qt::WindowMaximized) { + if (window()->windowStates() & Qt::WindowMaximized) { states |= NetWmStateMaximizedHorz; states |= NetWmStateMaximizedVert; } @@ -1410,30 +1370,30 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) if (m_netWmUserTimeWindow || isSupportedByWM) { if (!m_netWmUserTimeWindow) { m_netWmUserTimeWindow = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_netWmUserTimeWindow, // window id - m_window, // parent window id - -1, -1, 1, 1, - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_visualId, // visual - 0, // value mask - 0)); // value list + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_netWmUserTimeWindow, // window id + m_window, // parent window id + -1, -1, 1, 1, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_visualId, // visual + 0, // value mask + 0); // value list wid = m_netWmUserTimeWindow; xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW), XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow); xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME)); #ifndef QT_NO_DEBUG QByteArray ba("Qt NET_WM user time window"); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_netWmUserTimeWindow, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_netWmUserTimeWindow, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); #endif } else if (!isSupportedByWM) { // WM no longer supports it, then we should remove the @@ -1507,21 +1467,21 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) xcb_parent_id = xcbScreen()->root(); m_embedded = false; } - Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y())); + xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y()); } void QXcbWindow::setWindowTitle(const QString &title) { QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH const QByteArray ba = std::move(fullTitle).toUtf8(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_NAME), atom(QXcbAtom::UTF8_STRING), 8, ba.length(), - ba.constData())); + ba.constData()); #ifdef XCB_USE_XLIB XTextProperty *text = qstringToXTP(DISPLAY_FROM_XCB(this), title); @@ -1534,14 +1494,14 @@ void QXcbWindow::setWindowTitle(const QString &title) void QXcbWindow::setWindowIconText(const QString &title) { const QByteArray ba = title.toUtf8(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_ICON_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_ICON_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); } void QXcbWindow::setWindowIcon(const QIcon &icon) @@ -1571,18 +1531,18 @@ void QXcbWindow::setWindowIcon(const QIcon &icon) } if (!icon_data.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_ICON), - atom(QXcbAtom::CARDINAL), - 32, - icon_data.size(), - (unsigned char *) icon_data.data())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_ICON), + atom(QXcbAtom::CARDINAL), + 32, + icon_data.size(), + (unsigned char *) icon_data.data()); } else { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), - m_window, - atom(QXcbAtom::_NET_WM_ICON))); + xcb_delete_property(xcb_connection(), + m_window, + atom(QXcbAtom::_NET_WM_ICON)); } } @@ -1590,14 +1550,14 @@ void QXcbWindow::raise() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_ABOVE }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); + xcb_configure_window(xcb_connection(), m_window, mask, values); } void QXcbWindow::lower() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_BELOW }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); + xcb_configure_window(xcb_connection(), m_window, mask, values); } // Adapt the geometry to match the WM expection with regards @@ -1691,9 +1651,11 @@ void QXcbWindow::requestActivateWindow() event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); } else { - Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time())); + xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()); } connection()->sync(); @@ -1737,15 +1699,11 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { QXcbWindowFunctions::WmWindowTypes result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *types_end = types + reply->length; for (; types != types_end; types++) { QXcbAtom::Atom type = connection()->qatom(*types); @@ -1799,7 +1757,6 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const break; } } - free(reply); } return result; } @@ -1882,20 +1839,20 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL)); if (atoms.isEmpty()) { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE))); + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE)); } else { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, - atoms.count(), atoms.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, + atoms.count(), atoms.constData()); } xcb_flush(xcb_connection()); } void QXcbWindow::setWmWindowRole(const QByteArray &role) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8, - role.size(), role.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8, + role.size(), role.constData()); } void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window) @@ -1908,7 +1865,7 @@ void QXcbWindow::setParentRelativeBackPixmap() { const quint32 mask = XCB_CW_BACK_PIXMAP; const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE }; - Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); } bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window) @@ -2085,13 +2042,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QPoint pos(event->x, event->y); if (!parent() && !fromSendEvent) { // Do not trust the position, query it instead. - xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), - xcbScreen()->root(), 0, 0); - xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), 0, 0); if (reply) { pos.setX(reply->dst_x); pos.setY(reply->dst_y); - free(reply); } } @@ -2146,15 +2101,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2166,15 +2118,12 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcbScreen()->root(), xcb_window(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2525,44 +2474,33 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev if (propertyDeleted) return; - Qt::WindowState newState = Qt::WindowNoState; - if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. - const xcb_get_property_cookie_t get_cookie = - xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE), - XCB_ATOM_ANY, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + Qt::WindowStates newState = Qt::WindowNoState; + if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::WM_STATE), + XCB_ATOM_ANY, 0, 1024); if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { - const quint32 *data = (const quint32 *)xcb_get_property_value(reply); - if (reply->length != 0) { - if (data[0] == XCB_WM_STATE_ICONIC - || (data[0] == XCB_WM_STATE_WITHDRAWN - && m_lastWindowStateEvent == Qt::WindowMinimized)) { - newState = Qt::WindowMinimized; - } - } + const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get()); + if (reply->length != 0) + m_minimized = (data[0] == XCB_WM_STATE_ICONIC + || (data[0] == XCB_WM_STATE_WITHDRAWN && m_minimized)); } - free(reply); - } else { // _NET_WM_STATE can't change minimized state - if (m_lastWindowStateEvent == Qt::WindowMinimized) - newState = Qt::WindowMinimized; - } - - if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE. - const NetWmStates states = netWmStates(); - if (states & NetWmStateFullScreen) - newState = Qt::WindowFullScreen; - else if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) - newState = Qt::WindowMaximized; } + if (m_minimized) + newState = Qt::WindowMinimized; + + const NetWmStates states = netWmStates(); + if (states & NetWmStateFullScreen) + newState |= Qt::WindowFullScreen; + if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) + newState |= Qt::WindowMaximized; // Send Window state, compress events in case other flags (modality, etc) are changed. if (m_lastWindowStateEvent != newState) { QWindowSystemInterface::handleWindowStateChanged(window(), newState); m_lastWindowStateEvent = newState; m_windowState = newState; - if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this) + if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this) connection()->setMouseGrabber(Q_NULLPTR); } return; @@ -2597,7 +2535,7 @@ void QXcbWindow::updateSyncRequestCounter() return; } if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { - Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue); xcb_flush(xcb_connection()); m_syncValue.lo = 0; @@ -2621,13 +2559,11 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_keyboard_cookie_t cookie = xcb_grab_keyboard(xcb_connection(), false, - m_window, XCB_TIME_CURRENT_TIME, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - xcb_grab_keyboard_reply_t *reply = xcb_grab_keyboard_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); - return result; + + auto reply = Q_XCB_REPLY(xcb_grab_keyboard, xcb_connection(), false, + m_window, XCB_TIME_CURRENT_TIME, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + return reply && reply->status == XCB_GRAB_STATUS_SUCCESS; } bool QXcbWindow::setMouseGrabEnabled(bool grab) @@ -2649,16 +2585,16 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(xcb_connection(), false, m_window, - (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW - | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, - XCB_WINDOW_NONE, XCB_CURSOR_NONE, - XCB_TIME_CURRENT_TIME); - xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); + + auto reply = Q_XCB_REPLY(xcb_grab_pointer, xcb_connection(), + false, m_window, + (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, + XCB_WINDOW_NONE, XCB_CURSOR_NONE, + XCB_TIME_CURRENT_TIME); + bool result = reply && reply->status == XCB_GRAB_STATUS_SUCCESS; if (result) connection()->setMouseGrabber(this); return result; @@ -2766,8 +2702,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, event.data.data32[2] = detail; event.data.data32[3] = data1; event.data.data32[4] = data2; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, window, - XCB_EVENT_MASK_NO_EVENT, (const char *)&event)); + xcb_send_event(xcb_connection(), false, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); } static bool activeWindowChangeQueued(const QWindow *window) @@ -2789,12 +2724,12 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) case XEMBED_WINDOW_DEACTIVATE: break; case XEMBED_EMBEDDED_NOTIFY: - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + xcb_map_window(xcb_connection(), m_window); xcbScreen()->windowShown(this); // Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap. // Clear the whole tray icon window to its background color as early as possible // so that we can get a clean result from grabWindow() later. - Q_XCB_CALL(xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height())); + xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height()); xcb_flush(xcb_connection()); break; case XEMBED_FOCUS_IN: @@ -2841,14 +2776,14 @@ void QXcbWindow::setOpacity(qreal level) quint32 value = qRound64(qBound(qreal(0), level, qreal(1)) * 0xffffffff); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_WINDOW_OPACITY), - XCB_ATOM_CARDINAL, - 32, - 1, - (uchar *)&value)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_WINDOW_OPACITY), + XCB_ATOM_CARDINAL, + 32, + 1, + (uchar *)&value); } void QXcbWindow::setMask(const QRegion ®ion) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index b4d947e700..3e539337b1 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -82,7 +82,7 @@ public: void setVisible(bool visible) override; void setWindowFlags(Qt::WindowFlags flags) override; - void setWindowState(Qt::WindowState state) override; + void setWindowState(Qt::WindowStates state) override; WId winId() const override; void setParent(const QPlatformWindow *window) override; @@ -243,7 +243,7 @@ protected: xcb_sync_int64_t m_syncValue; xcb_sync_counter_t m_syncCounter = 0; - Qt::WindowState m_windowState = Qt::WindowNoState; + Qt::WindowStates m_windowState = Qt::WindowNoState; xcb_gravity_t m_gravity = XCB_GRAVITY_STATIC; @@ -253,6 +253,7 @@ protected: bool m_deferredActivation = false; bool m_embedded = false; bool m_alertState = false; + bool m_minimized = false; xcb_window_t m_netWmUserTimeWindow = XCB_NONE; QSurfaceFormat m_format; @@ -264,7 +265,8 @@ protected: QSize m_oldWindowSize; xcb_visualid_t m_visualId = 0; - int m_lastWindowStateEvent = -1; + // Last sent state. Initialized to an invalid state, on purpose. + Qt::WindowStates m_lastWindowStateEvent = Qt::WindowActive; enum SyncState { NoSyncNeeded, diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index 470f021314..2619892b19 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -66,16 +66,15 @@ void QXcbWMSupport::updateNetWMAtoms() int offset = 0; int remaining = 0; do { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024); if (!reply) break; remaining = 0; if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); - xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); + int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_atom_t); + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); int s = net_wm_atoms.size(); net_wm_atoms.resize(s + len); memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t)); @@ -83,8 +82,6 @@ void QXcbWMSupport::updateNetWMAtoms() remaining = reply->bytes_after; offset += len; } - - free(reply); } while (remaining > 0); } @@ -100,16 +97,16 @@ void QXcbWMSupport::updateVirtualRoots() int offset = 0; int remaining = 0; do { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024); if (!reply) break; remaining = 0; if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t); - xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply); + int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_window_t); + xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply.get()); int s = net_virtual_roots.size(); net_virtual_roots.resize(s + len); memcpy(net_virtual_roots.data() + s, roots, len*sizeof(xcb_window_t)); @@ -118,10 +115,10 @@ void QXcbWMSupport::updateVirtualRoots() offset += len; } - free(reply); } while (remaining > 0); -#ifdef Q_XCB_DEBUG +//#define VIRTUAL_ROOTS_DEBUG +#ifdef VIRTUAL_ROOTS_DEBUG qDebug("======== updateVirtualRoots"); for (int i = 0; i < net_virtual_roots.size(); ++i) qDebug() << connection()->atomName(net_virtual_roots.at(i)); diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index 401eb8043c..bd398ea049 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -45,10 +45,6 @@ #include <vector> #include <algorithm> -#ifdef XCB_USE_XLIB -#include <X11/extensions/XIproto.h> -#endif //XCB_USE_XLIB - QT_BEGIN_NAMESPACE /* Implementation of http://standards.freedesktop.org/xsettings-spec/xsettings-0.5.html */ @@ -110,26 +106,23 @@ public: QByteArray settings; xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::_XSETTINGS_SETTINGS); while (1) { - xcb_get_property_cookie_t get_prop_cookie = - xcb_get_property_unchecked(screen->xcb_connection(), + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, + screen->xcb_connection(), false, x_settings_window, _xsettings_atom, _xsettings_atom, offset/4, 8192); - xcb_get_property_reply_t *reply = xcb_get_property_reply(screen->xcb_connection(), get_prop_cookie, NULL); bool more = false; if (!reply) return settings; - const auto property_value_length = xcb_get_property_value_length(reply); - settings.append(static_cast<const char *>(xcb_get_property_value(reply)), property_value_length); + const auto property_value_length = xcb_get_property_value_length(reply.get()); + settings.append(static_cast<const char *>(xcb_get_property_value(reply.get())), property_value_length); offset += property_value_length; more = reply->bytes_after != 0; - free(reply); - if (!more) break; } @@ -145,19 +138,18 @@ public: return value + 4 - remainder; } -#ifdef XCB_USE_XLIB void populateSettings(const QByteArray &xSettings) { if (xSettings.length() < 12) return; char byteOrder = xSettings.at(0); - if (byteOrder != LSBFirst && byteOrder != MSBFirst) { + if (byteOrder != XCB_IMAGE_ORDER_LSB_FIRST && byteOrder != XCB_IMAGE_ORDER_MSB_FIRST) { qWarning("ByteOrder byte %d not 0 or 1", byteOrder); return; } #define ADJUST_BO(b, t, x) \ - ((b == LSBFirst) ? \ + ((b == XCB_IMAGE_ORDER_LSB_FIRST) ? \ qFromLittleEndian<t>(x) : \ qFromBigEndian<t>(x)) #define VALIDATE_LENGTH(x) \ @@ -220,7 +212,6 @@ public: } } -#endif //XCB_USE_XLIB QXcbVirtualDesktop *screen; xcb_window_t x_settings_window; @@ -234,43 +225,31 @@ QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen) { QByteArray settings_atom_for_screen("_XSETTINGS_S"); settings_atom_for_screen.append(QByteArray::number(screen->number())); - xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(), - true, - settings_atom_for_screen.length(), - settings_atom_for_screen.constData()); - xcb_generic_error_t *error = 0; - xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error); - if (error) { - free(error); + auto atom_reply = Q_XCB_REPLY(xcb_intern_atom, + screen->xcb_connection(), + true, + settings_atom_for_screen.length(), + settings_atom_for_screen.constData()); + if (!atom_reply) return; - } - xcb_atom_t selection_owner_atom = atom_reply->atom; - free(atom_reply); - xcb_get_selection_owner_cookie_t selection_cookie = - xcb_get_selection_owner(screen->xcb_connection(), selection_owner_atom); + xcb_atom_t selection_owner_atom = atom_reply->atom; - xcb_get_selection_owner_reply_t *selection_result = - xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error); - if (error) { - free(error); + auto selection_result = Q_XCB_REPLY(xcb_get_selection_owner, + screen->xcb_connection(), selection_owner_atom); + if (!selection_result) return; - } d_ptr->x_settings_window = selection_result->owner; - free(selection_result); - if (!d_ptr->x_settings_window) { + if (!d_ptr->x_settings_window) return; - } const uint32_t event = XCB_CW_EVENT_MASK; const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes(screen->xcb_connection(),d_ptr->x_settings_window,event,event_mask); -#ifdef XCB_USE_XLIB d_ptr->populateSettings(d_ptr->getSettings()); d_ptr->initialized = true; -#endif //XCB_USE_XLIB } QXcbXSettings::~QXcbXSettings() @@ -290,9 +269,8 @@ void QXcbXSettings::handlePropertyNotifyEvent(const xcb_property_notify_event_t Q_D(QXcbXSettings); if (event->window != d->x_settings_window) return; -#ifdef XCB_USE_XLIB + d->populateSettings(d->getSettings()); -#endif //XCB_USE_XLIB } void QXcbXSettings::registerCallbackForProperty(const QByteArray &property, QXcbXSettings::PropertyChangeFunc func, void *handle) diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 6db0c76dea..c7f2993220 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -10,6 +10,8 @@ QT += \ qtHaveModule(linuxaccessibility_support-private): \ QT += linuxaccessibility_support-private +qtConfig(vulkan): QT += vulkan_support-private + SOURCES = \ qxcbclipboard.cpp \ qxcbconnection.cpp \ @@ -70,6 +72,16 @@ qtConfig(xcb-sm) { include(gl_integrations/gl_integrations.pri) +qtConfig(vulkan) { + SOURCES += \ + qxcbvulkaninstance.cpp \ + qxcbvulkanwindow.cpp + + HEADERS += \ + qxcbvulkaninstance.h \ + qxcbvulkanwindow.h +} + !qtConfig(system-xcb) { DEFINES += XCB_USE_RENDER QMAKE_USE += xcb-static xcb |