diff options
Diffstat (limited to 'src/plugins/platforms/windows')
4 files changed, 134 insertions, 67 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp b/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp index 63e16260b62..6962d28e7d0 100644 --- a/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp +++ b/src/plugins/platforms/windows/qwindowswindowclassdescription.cpp @@ -11,68 +11,112 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -QWindowsWindowClassDescription QWindowsWindowClassDescription::fromName(QString name, WNDPROC procedure) +QString QWindowsWindowClassDescription::classNameSuffix(Qt::WindowFlags type, unsigned int style, bool hasIcon) { - return { std::move(name), procedure }; + QString suffix; + + switch (type) { + case Qt::Popup: + suffix += "Popup"_L1; + break; + case Qt::Tool: + suffix += "Tool"_L1; + break; + case Qt::ToolTip: + suffix += "ToolTip"_L1; + break; + default: + break; + } + + if (style & CS_DROPSHADOW) + suffix += "DropShadow"_L1; + if (style & CS_SAVEBITS) + suffix += "SaveBits"_L1; + if (style & CS_OWNDC) + suffix += "OwnDC"_L1; + if (hasIcon) + suffix += "Icon"_L1; + + return suffix; } -QWindowsWindowClassDescription QWindowsWindowClassDescription::fromWindow(const QWindow *window, WNDPROC procedure) +bool QWindowsWindowClassDescription::computeHasIcon(Qt::WindowFlags flags, Qt::WindowFlags type) { - Q_ASSERT(window); - - QWindowsWindowClassDescription description; - description.procedure = procedure; + bool hasIcon = true; - const Qt::WindowFlags flags = window->flags(); - const Qt::WindowFlags type = flags & Qt::WindowType_Mask; - // Determine style and icon. - description.style = CS_DBLCLKS; - description.hasIcon = true; - // The following will not set CS_OWNDC for any widget window, even if it contains a - // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage. - if (window->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC)) - description.style |= CS_OWNDC; - if (!(flags & Qt::NoDropShadowWindowHint) - && (type == Qt::Popup || window->property("_q_windowsDropShadow").toBool())) { - description.style |= CS_DROPSHADOW; - } switch (type) { case Qt::Tool: case Qt::ToolTip: case Qt::Popup: - description.style |= CS_SAVEBITS; // Save/restore background - description.hasIcon = false; + hasIcon = false; break; case Qt::Dialog: if (!(flags & Qt::WindowSystemMenuHint)) - description.hasIcon = false; // QTBUG-2027, dialogs without system menu. + hasIcon = false; // QTBUG-2027, dialogs without system menu. break; } - // Create a unique name for the flag combination - description.name = "QWindow"_L1; + + return hasIcon; +} + +unsigned int QWindowsWindowClassDescription::computeWindowStyles(Qt::WindowFlags flags, Qt::WindowFlags type, WindowStyleOptions options) +{ + unsigned int style = CS_DBLCLKS; + + // The following will not set CS_OWNDC for any widget window, even if it contains a + // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage. + if (options.testFlag(WindowStyleOption::GLSurface) || (flags & Qt::MSWindowsOwnDC)) + style |= CS_OWNDC; + if (!(flags & Qt::NoDropShadowWindowHint) && (type == Qt::Popup || options.testFlag(WindowStyleOption::DropShadow))) + style |= CS_DROPSHADOW; + switch (type) { case Qt::Tool: - description.name += "Tool"_L1; - break; case Qt::ToolTip: - description.name += "ToolTip"_L1; - break; case Qt::Popup: - description.name += "Popup"_L1; - break; - default: + style |= CS_SAVEBITS; // Save/restore background break; } - if (description.style & CS_DROPSHADOW) - description.name += "DropShadow"_L1; - if (description.style & CS_SAVEBITS) - description.name += "SaveBits"_L1; - if (description.style & CS_OWNDC) - description.name += "OwnDC"_L1; - if (description.hasIcon) - description.name += "Icon"_L1; + + return style; +} + +QWindowsWindowClassDescription QWindowsWindowClassDescription::fromName(QString name, WNDPROC procedure) +{ + return { std::move(name), procedure }; +} + +QWindowsWindowClassDescription QWindowsWindowClassDescription::fromWindow(const QWindow *window, WNDPROC procedure) +{ + Q_ASSERT(window); + + const Qt::WindowFlags flags = window->flags(); + const Qt::WindowFlags type = flags & Qt::WindowType_Mask; + + WindowStyleOptions options = WindowStyleOption::None; + if (window->surfaceType() == QSurface::OpenGLSurface) + options |= WindowStyleOption::GLSurface; + if (window->property("_q_windowsDropShadow").toBool()) + options |= WindowStyleOption::DropShadow; + + QWindowsWindowClassDescription description; + description.procedure = procedure; + description.style = computeWindowStyles(flags, type, options); + description.hasIcon = computeHasIcon(flags, type); + description.name = "QWindow"_L1 + classNameSuffix(type, description.style, description.hasIcon); return description; } +QDebug operator<<(QDebug dbg, const QWindowsWindowClassDescription &description) +{ + dbg << description.name + << " style=0x" << Qt::hex << description.style << Qt::dec + << " brush=" << description.brush + << " hasIcon=" << description.hasIcon; + + return dbg; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindowclassdescription.h b/src/plugins/platforms/windows/qwindowswindowclassdescription.h index 9423abf9d2d..f0019f8f3c2 100644 --- a/src/plugins/platforms/windows/qwindowswindowclassdescription.h +++ b/src/plugins/platforms/windows/qwindowswindowclassdescription.h @@ -14,6 +14,14 @@ class QWindow; struct QWindowsWindowClassDescription { + enum class WindowStyleOption + { + None = 0x00, + GLSurface = 0x01, + DropShadow = 0x02 + }; + Q_DECLARE_FLAGS(WindowStyleOptions, WindowStyleOption) + static QWindowsWindowClassDescription fromName(QString name, WNDPROC procedure); static QWindowsWindowClassDescription fromWindow(const QWindow *window, WNDPROC procedure); @@ -23,8 +31,17 @@ struct QWindowsWindowClassDescription HBRUSH brush{ nullptr }; bool hasIcon{ false }; bool shouldAddPrefix{ true }; + +private: + static QString classNameSuffix(Qt::WindowFlags type, unsigned int style, bool hasIcon); + static bool computeHasIcon(Qt::WindowFlags flags, Qt::WindowFlags type); + static unsigned int computeWindowStyles(Qt::WindowFlags flags, Qt::WindowFlags type, WindowStyleOptions options); + + friend QDebug operator<<(QDebug dbg, const QWindowsWindowClassDescription &description); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowClassDescription::WindowStyleOptions) + QT_END_NAMESPACE #endif // QWINDOWSWINDOWCLASSDESCRIPTION_H diff --git a/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp b/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp index c330720a09c..8bf2fb887f1 100644 --- a/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp +++ b/src/plugins/platforms/windows/qwindowswindowclassregistry.cpp @@ -18,8 +18,8 @@ Q_LOGGING_CATEGORY(lcQpaWindowClass, "qt.qpa.windowclass") QWindowsWindowClassRegistry *QWindowsWindowClassRegistry::m_instance = nullptr; -QWindowsWindowClassRegistry::QWindowsWindowClassRegistry(WNDPROC proc) - : m_proc(proc) +QWindowsWindowClassRegistry::QWindowsWindowClassRegistry(WNDPROC defaultProcedure) + : m_defaultProcedure(defaultProcedure) { m_instance = this; } @@ -69,25 +69,19 @@ QString QWindowsWindowClassRegistry::registerWindowClass(const QWindowsWindowCla // add a UUID. The check needs to be performed for each name // in case new message windows are added (QTBUG-81347). // Note: GetClassInfo() returns != 0 when a class exists. - const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); - WNDCLASS wcinfo; - const bool classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(className.utf16()), &wcinfo) != FALSE - && wcinfo.lpfnWndProc != description.procedure; - - if (classExists) + if (shouldDecorateWindowClassName(description)) className += QUuid::createUuid().toString(); if (m_registeredWindowClassNames.contains(className)) // already registered in our list return className; - WNDCLASSEX wc; + const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); + + WNDCLASSEX wc{}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = description.style; wc.lpfnWndProc = description.procedure; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; wc.hInstance = appInstance; - wc.hCursor = nullptr; wc.hbrBackground = description.brush; if (description.hasIcon) { wc.hIcon = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); @@ -98,31 +92,25 @@ QString QWindowsWindowClassRegistry::registerWindowClass(const QWindowsWindowCla } else { wc.hIcon = static_cast<HICON>(LoadImage(nullptr, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED)); - wc.hIconSm = nullptr; } } - else { - wc.hIcon = nullptr; - wc.hIconSm = nullptr; - } - wc.lpszMenuName = nullptr; wc.lpszClassName = reinterpret_cast<LPCWSTR>(className.utf16()); ATOM atom = RegisterClassEx(&wc); if (!atom) - qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.", - qPrintable(className)); + qCWarning(lcQpaWindowClass) << "Failed to register window class" << className + << "(" << qt_error_string(-1) << ")"; m_registeredWindowClassNames.insert(className); - qCDebug(lcQpaWindowClass).nospace() << __FUNCTION__ << ' ' << className - << " style=0x" << Qt::hex << description.style << Qt::dec - << " brush=" << description.brush << " icon=" << description.hasIcon << " atom=" << atom; + + qCDebug(lcQpaWindowClass).nospace() << __FUNCTION__ << ' ' << className << ' ' << description << " atom=" << atom; + return className; } QString QWindowsWindowClassRegistry::registerWindowClass(const QWindow *window) { - return registerWindowClass(QWindowsWindowClassDescription::fromWindow(window, m_proc)); + return registerWindowClass(QWindowsWindowClassDescription::fromWindow(window, m_defaultProcedure)); } QString QWindowsWindowClassRegistry::registerWindowClass(QString name, WNDPROC procedure) @@ -130,13 +118,29 @@ QString QWindowsWindowClassRegistry::registerWindowClass(QString name, WNDPROC p return registerWindowClass(QWindowsWindowClassDescription::fromName(name, procedure)); } +bool QWindowsWindowClassRegistry::shouldDecorateWindowClassName(const QWindowsWindowClassDescription &description) const +{ + return shouldDecorateWindowClassName(description.name, description.procedure); +} + +bool QWindowsWindowClassRegistry::shouldDecorateWindowClassName(const QString &name, WNDPROC procedure) const +{ + const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); + + WNDCLASS wc{}; + + return GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(name.utf16()), &wc) != FALSE + && wc.lpfnWndProc != procedure; +} + void QWindowsWindowClassRegistry::unregisterWindowClasses() { const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr)); for (const QString &name : std::as_const(m_registeredWindowClassNames)) { if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose) - qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name)); + qCWarning(lcQpaWindowClass) << "Failed to unregister window class" << name + << "(" << qt_error_string(-1) << ")"; } m_registeredWindowClassNames.clear(); } diff --git a/src/plugins/platforms/windows/qwindowswindowclassregistry.h b/src/plugins/platforms/windows/qwindowswindowclassregistry.h index c19b4f616fb..c4a36b7f3c4 100644 --- a/src/plugins/platforms/windows/qwindowswindowclassregistry.h +++ b/src/plugins/platforms/windows/qwindowswindowclassregistry.h @@ -22,7 +22,7 @@ class QWindowsWindowClassRegistry { Q_DISABLE_COPY_MOVE(QWindowsWindowClassRegistry) public: - QWindowsWindowClassRegistry(WNDPROC proc); + QWindowsWindowClassRegistry(WNDPROC defaultProcedure); ~QWindowsWindowClassRegistry(); static QWindowsWindowClassRegistry *instance(); @@ -34,11 +34,13 @@ public: private: static QString classNamePrefix(); + bool shouldDecorateWindowClassName(const QWindowsWindowClassDescription &description) const; + bool shouldDecorateWindowClassName(const QString &name, WNDPROC procedure) const; void unregisterWindowClasses(); static QWindowsWindowClassRegistry *m_instance; - WNDPROC m_proc; + WNDPROC m_defaultProcedure; QSet<QString> m_registeredWindowClassNames; }; |
