Tor,

Thanks for your reply.

I’ve just created the issue:

https://qt-project.atlassian.net/browse/QTBUG-148623

I’ve used Claude Code to generate the bug report, forgive me its not perfectly 
formatted.

Thank you!

Best,

Nuno

> On 28 Jul 2026, at 17:04, Tor Arne Vestbø <[email protected]> wrote:
> 
> 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