This sounds like a bug, please file a JIRA issue, thanks!

On 28 Jul 2026, at 17:33, Nuno Santos via Interest <[email protected]> 
wrote:


Hi all,

We ship several audio plug-ins (VST2/VST3/AU) that each statically link Qt, 
built with a custom namespace (configure -qtnamespace <ours>). Multiple such 
plug-ins are routinely loaded into the same host process (e.g. Ableton Live)

  *   the classic "several independent static-Qt instances in one process" 
scenario that -qtnamespace exists to support.

This has worked on Windows for many years. After moving to Qt 6.11, the second 
Qt-based plug-in loaded into a host now comes up with a blank/white UI. The 
logs show its Win32 window classes failing to register:

qt.qpa.windowclass: Failed to register window class
"Qt6110d<namespace>QWindowIcon" ( "Class already exists." )
...
QWindowsContext::windowsProc: No Qt Window found for event 0xf
(WM_PAINT), hwnd=0x...


i.e. the second instance reuses the first instance's already-registered class 
(and therefore its WNDPROC), its windows' messages are delivered to the wrong 
Qt instance, and it never paints.

________________________________
WHAT CHANGED

Bisecting src/plugins/platforms/windows:

Up to Qt 6.10, QWindowsContext::registerWindowClass(QString cname, WNDPROC 
proc, ...) appended a UUID to the final, prefixed class name whenever it 
detected the class already existed with a different WNDPROC (i.e. another Qt 
instance in the process):

const bool classExists =
    GetClassInfo(appInstance, (LPCWSTR)cname.utf16(), &wcinfo) != FALSE
    && wcinfo.lpfnWndProc != proc;
if (classExists)
    cname += QUuid::createUuid().toString();


This is what let multiple same-namespace static-Qt plug-ins coexist for years.

Qt 6.11 extracted this into a new QWindowsWindowClassRegistry (commits 
04f13038f5 "Extract window class registration into dedicated class", 
2025-11-20, and b23b9c8265 "Add shouldDecorateWindowClassName to detect window 
class conflicts", 2025-11-28). In the new code the collision check runs against 
the un-prefixed description.name, while registration uses the prefixed 
classNamePrefix() + description.name:

QString className = description.name;
if (description.shouldAddPrefix)
    className = classNamePrefix() + className;
    // e.g. "Qt6110d<namespace>QWindowIcon"

if (shouldDecorateWindowClassName(description))
    // -> uses description.name (unprefixed!)
    className += QUuid::createUuid().toString();
...
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, (LPCWSTR)name.utf16(), &wc) != FALSE
        && wc.lpfnWndProc != procedure;
}


Because nothing ever registers the bare QWindowIcon (the registered name is 
always the prefixed form), GetClassInfo on the un-prefixed name always returns 
FALSE, the UUID is never appended, and the second instance collides on the 
plain prefixed name. This still appears to be the case on the current dev 
branch, and there is no related entry in the 6.11.1 release notes.

________________________________
THE QUESTION

Is this a deliberate change - i.e. is the expectation now that every 
independently-loaded static-Qt plug-in must be built with a unique 
QT_NAMESPACE, so the class-name prefix is already unique and the runtime UUID 
de-duplication is no longer meant to be relied upon?

Or is it an unintended regression, where the check should have been performed 
against the final (prefixed) className rather than the un-prefixed 
description.name? If the latter, the fix looks like a one-liner - decorate 
based on the prefixed name, e.g.:

if (description.shouldAddPrefix)
    className = classNamePrefix() + className;

if (shouldDecorateWindowClassName(className, description.procedure))
    // prefixed name
    className += QUuid::createUuid().toString();

We don't yet have a workaround in place, but we plan to try applying the same 
approach macOS already uses (mangling the Qt namespace to a unique value per 
binary at build time) as a stopgap. In the meantime we'd like to know whether 
we should rely on unique namespaces going forward, or whether a fix is expected 
upstream. Happy to file a bug report with a minimal reproducer if that helps.

Thank you!

Best regards,

_______________________________________________
Interest mailing list
[email protected]
https://lists.qt-project.org/listinfo/interest

_______________________________________________
Interest mailing list
[email protected]
https://lists.qt-project.org/listinfo/interest

Reply via email to