From e7ec9af9dd4595c3b5347d5c2f64aa859acd902d Mon Sep 17 00:00:00 2001 From: deepin-wm Date: Thu, 18 Jun 2026 20:39:56 +0800 Subject: [PATCH] fix: enhance appId matching for prelaunch splash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Add appIdCaseInsensitiveMatch helper for case-insensitive appId comparison 2. Extract matchPrelaunchWrapper with three-level matching: exact, case-insensitive, fallback using surface own appId 3. Unify ensureXdgWrapper and ensureXwaylandWrapper to use matchPrelaunchWrapper 4. Add diagnostic logging when appId matching fails with prelaunch wrappers present Log: Fixed window activation issue where WPS and browser windows do not appear on top when splash screen is enabled Influence: 1. Test window activation with WPS and browser when splash screen is enabled 2. Test window activation with file manager and terminal (should be unaffected) 3. Test case-insensitive appId matching scenario 4. Verify diagnostic log output when appId matching fails fix: 增强闪屏appId匹配逻辑 1. 新增 appIdCaseInsensitiveMatch 辅助函数 用于忽略大小写的 appId 比较 2. 提取 matchPrelaunchWrapper 实现三级匹配: 精确匹配、忽略大小写匹配、fallback使用 surface自身appId匹配 3. 统一 ensureXdgWrapper 和 ensureXwaylandWrapper 使用 matchPrelaunchWrapper 4. 当 appId 匹配失败且存在闪屏 wrapper 时 增加诊断日志 Log: 修复开启闪屏后鼠标点击激活WPS/浏览器 窗口未显示在最顶层的问题 Influence: 1. 测试开启闪屏时WPS和浏览器窗口激活是否 正常显示在最顶层 2. 测试文管和终端窗口激活是否不受影响 3. 测试appId忽略大小写匹配场景 4. 验证appId匹配失败时诊断日志输出 --- src/core/shellhandler.cpp | 111 +++++++++++++++++++++++++++++--------- src/core/shellhandler.h | 4 ++ 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/core/shellhandler.cpp b/src/core/shellhandler.cpp index 72521e125..25dd056e0 100644 --- a/src/core/shellhandler.cpp +++ b/src/core/shellhandler.cpp @@ -53,6 +53,15 @@ QW_USE_NAMESPACE WAYLIB_SERVER_USE_NAMESPACE +namespace { +bool appIdCaseInsensitiveMatch(const QString &splashAppId, const QString &appId) +{ + if (splashAppId.isEmpty() || appId.isEmpty()) + return false; + return splashAppId.compare(appId, Qt::CaseInsensitive) == 0; +} +} // anonymous namespace + #define TREELAND_XDG_SHELL_VERSION 5 ShellHandler::ShellHandler(RootSurfaceContainer *rootContainer, WServer *server) @@ -432,6 +441,72 @@ void ShellHandler::onXdgToplevelSurfaceAdded(WXdgToplevelSurface *surface) ensureXdgWrapper(surface, QString()); } + +SurfaceWrapper *ShellHandler::matchPrelaunchWrapper(const QString &surfaceAppId, + const QString &effectiveAppId) +{ + if (!m_prelaunchWrappers.isEmpty() && !effectiveAppId.isEmpty()) { + m_pendingPrelaunchAppIds.remove(effectiveAppId); + } + + // Level 1: Exact match + for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { + auto *candidate = m_prelaunchWrappers[i]; + if (candidate->appId() == effectiveAppId) { + qCDebug(lcTlShell) << "match prelaunch exact" << effectiveAppId; + m_prelaunchWrappers.removeAt(i); + return candidate; + } + } + + // Level 2: Case-insensitive match + for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { + auto *candidate = m_prelaunchWrappers[i]; + if (appIdCaseInsensitiveMatch(candidate->appId(), effectiveAppId)) { + qCDebug(lcTlShell) << "match prelaunch case-insensitive" + << candidate->appId() << effectiveAppId; + m_prelaunchWrappers.removeAt(i); + return candidate; + } + } + + // Level 3: Fallback using surface's own appId + if (!surfaceAppId.isEmpty()) { + // Exact match with surface appId + for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { + auto *candidate = m_prelaunchWrappers[i]; + if (candidate->appId() == surfaceAppId) { + qCDebug(lcTlShell) << "match prelaunch fallback exact" << surfaceAppId; + m_prelaunchWrappers.removeAt(i); + return candidate; + } + } + // Case-insensitive match with surface appId + for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { + auto *candidate = m_prelaunchWrappers[i]; + if (appIdCaseInsensitiveMatch(candidate->appId(), surfaceAppId)) { + qCDebug(lcTlShell) << "match prelaunch fallback case-insensitive" + << candidate->appId() << surfaceAppId; + m_prelaunchWrappers.removeAt(i); + return candidate; + } + } + } + + // Diagnostic log on match failure + if (!m_prelaunchWrappers.isEmpty()) { + QStringList splashAppIds; + for (const auto *w : m_prelaunchWrappers) + splashAppIds << w->appId(); + qCDebug(lcTlShell) << "appId matching failed" + << "targetAppId=" << effectiveAppId + << "surfaceAppId=" << surfaceAppId + << "splashAppIds=" << splashAppIds.join(","); + } + + return nullptr; +} + void ShellHandler::ensureXdgWrapper(WXdgToplevelSurface *surface, const QString &targetAppId) { // Check if this matches a closed splash screen @@ -445,20 +520,12 @@ void ShellHandler::ensureXdgWrapper(WXdgToplevelSurface *surface, const QString SurfaceWrapper *wrapper = nullptr; bool isNewWrapper = true; + QString surfaceAppId = surface->appId(); - if (!targetAppId.isEmpty()) { - m_pendingPrelaunchAppIds.remove(targetAppId); - for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { - auto *candidate = m_prelaunchWrappers[i]; - if (candidate->appId() == targetAppId) { - qCDebug(lcTlShell) << "match prelaunch xdg" << targetAppId; - m_prelaunchWrappers.removeAt(i); - candidate->convertToNormalSurface(surface, SurfaceWrapper::Type::XdgToplevel); - wrapper = candidate; - isNewWrapper = false; // matched from prelaunch, not newly created - break; - } - } + wrapper = matchPrelaunchWrapper(surfaceAppId, targetAppId); + if (wrapper) { + wrapper->convertToNormalSurface(surface, SurfaceWrapper::Type::XdgToplevel); + isNewWrapper = false; } if (!wrapper) { @@ -716,20 +783,12 @@ void ShellHandler::ensureXwaylandWrapper(WXWaylandSurface *surface, const QStrin SurfaceWrapper *wrapper = nullptr; bool isNewWrapper = true; + QString surfaceAppId = surface->appId(); - if (!targetAppId.isEmpty()) { - m_pendingPrelaunchAppIds.remove(targetAppId); - for (int i = 0; i < m_prelaunchWrappers.size(); ++i) { - auto *candidate = m_prelaunchWrappers[i]; - if (candidate->appId() == targetAppId) { - qCDebug(lcTlShell) << "match prelaunch xwayland" << targetAppId; - m_prelaunchWrappers.removeAt(i); - candidate->convertToNormalSurface(surface, SurfaceWrapper::Type::XWayland); - wrapper = candidate; - isNewWrapper = false; // matched from prelaunch, not newly created - break; - } - } + wrapper = matchPrelaunchWrapper(surfaceAppId, targetAppId); + if (wrapper) { + wrapper->convertToNormalSurface(surface, SurfaceWrapper::Type::XWayland); + isNewWrapper = false; } if (!wrapper) { diff --git a/src/core/shellhandler.h b/src/core/shellhandler.h index 362cb8772..b283b8ad7 100644 --- a/src/core/shellhandler.h +++ b/src/core/shellhandler.h @@ -159,6 +159,10 @@ private Q_SLOTS: // Creates or matches a wrapper from prelaunch splash, then initializes it void ensureXwaylandWrapper(WAYLIB_SERVER_NAMESPACE::WXWaylandSurface *surface, const QString &appId); + // Try to match a prelaunch splash wrapper for the given appId with + // progressive fallback: exact -> case-insensitive -> surface own appId. + SurfaceWrapper *matchPrelaunchWrapper(const QString &surfaceAppId, + const QString &effectiveAppId); // Unified parent/container update for Xdg & XWayland toplevel wrappers. void updateWrapperContainer(SurfaceWrapper *wrapper, WAYLIB_SERVER_NAMESPACE::WSurface *parentSurface);