Files
RedBear-OS/local/recipes/qt/qtbase/scripts/patch-wayland-wrappers.py
T
vasilito f324023fde fix: Qt6 Wayland null guard — real fix deployed via post-build patching
The Qt6 Wayland QPA crashes at null+8 because auto-generated wrappers
pass NULL proxies to wl_*_add_listener(). Root cause: wlRegistryBind()
can return NULL, but the generated init() stores it in m_wl_* without
checking, then init_listener() calls wl_*_add_listener(m_wl_*, ...)
which page-faults writing to proxy->object.implementation.

Fix: post-build Python script patches generated qwayland-wayland.cpp
with null guards on every wl_*_add_listener(m_wl_*, ...) call:
    if (m_wl_*) wl_*_add_listener(m_wl_*, ...)

Patch-and-rebuild.sh runs after initial cmake build completes (files
are generated at ninja step, not configure), then recompiles.

This is the SYSTEMIC fix — no env vars, no plugin renaming, no
workarounds. Every Qt6 Wayland proxy is null-checked before use.
2026-05-06 17:00:55 +01:00

44 lines
1.3 KiB
Python

#!/usr/bin/env python3
"""Patch Qt6 generated Wayland wrappers with null guards.
Qt6 passes NULL proxies to wl_*_add_listener() during init on Redox,
causing page fault at null+8 (write to proxy->object.implementation).
This script wraps every wl_*_add_listener(m_wl_*, ...) call with:
if (m_wl_*) wl_*_add_listener(m_wl_*, ...)
"""
import re, sys, os
def patch_file(path):
if not os.path.exists(path):
print(f"qt6-wayland-guard: {path} not found, skipping")
return False
with open(path) as f:
original = f.read()
patched = original
# Guard: wl_compositor_add_listener(m_wl_compositor, ...)
patched = re.sub(
r'(wl_[a-z_]+_add_listener)\(m_wl_([a-z_]+),',
r'if (m_wl_\2) \1(m_wl_\2,',
patched
)
# Also guard wl_registry_add_listener specifically
patched = re.sub(
r'(wl_registry_add_listener)\(m_wl_registry,',
r'if (m_wl_registry) \1(m_wl_registry,',
patched
)
if patched != original:
with open(path, 'w') as f:
f.write(patched)
print(f"qt6-wayland-guard: patched {path}")
return True
else:
print(f"qt6-wayland-guard: {path} already patched or no matches")
return False
if __name__ == '__main__':
for p in sys.argv[1:]:
patch_file(p)