Skip to content

fix: restore the Dock after display reconnection - #1800

Open
gugullll wants to merge 1 commit into
linuxdeepin:masterfrom
gugullll:fix/hot-plug
Open

gugullll wants to merge 1 commit into
linuxdeepin:masterfrom
gugullll:fix/hot-plug

Conversation

@gugullll

@gugullll gugullll commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor
  1. Keep dde-shell running when the last window closes.
  2. Skip icon geometry updates while the platform window is unavailable.
  3. Reinstall layer-shell integration before showing the Dock again.

Log: Restore the Dock at its configured edge after a display reconnects.

Influence:

  1. Unplug and reconnect the only display, then check the Dock position.
  2. Unplug the active external display in external-only mode and check Dock.
  3. Repeat hotplug with open windows and check for crashes or restarts.

fix: 修复显示器重新接入后任务栏不恢复

  1. 最后一个窗口关闭后保持 dde-shell 运行。
  2. 平台窗口不可用时跳过任务图标位置上报。
  3. 恢复任务栏前重新绑定 layer-shell。

Log: 显示器重新接入后,任务栏恢复到配置的屏幕边缘。

Influence:

  1. 拔出并插回唯一显示器,确认任务栏恢复到原边缘。
  2. 仅使用外接显示器时拔掉外接屏,检查任务栏是否恢复。
  3. 打开多个窗口后反复拔插,检查 dde-shell 是否崩溃或重启。

Summary by Sourcery

Restore Dock availability and placement after displays are disconnected and reconnected.

Bug Fixes:

  • Restore the Dock to its configured screen edge after display reconnection, including external-display hotplug scenarios.
  • Prevent task icon geometry updates when the platform window or surface is unavailable during display transitions.
  • Keep dde-shell running after its last window closes so the Dock can recover after display reconnection.

Enhancements:

  • Re-establish Wayland layer-shell integration before showing the Dock after the display becomes available.

@sourcery-ai

sourcery-ai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

API

Add a method that ensures the Wayland layer-shell integration is installed and reports whether it succeeded.

  • frame/layershell/dlayershellwindow.cpp L276-301
  • frame/layershell/dlayershellwindow.h L150-151

Uses of the API

On display changes, restore the Dock only when the primary screen is ready and the Dock is eligible to show, reinstalling layer-shell integration first.

  • panels/dock/dockpanel.cpp L9, L34, L480-493

Implementation

Use the shared layer-shell setup helper when creating a layer-shell window, and avoid assigning the integration again when a shell surface already exists.

  • frame/layershell/dlayershellwindow.cpp L262-266

Skip task icon geometry updates when the base window or its Wayland platform window is unavailable.

  • panels/dock/taskmanager/treelandwindow.cpp L229-233

Configuration

Keep dde-shell running after its last window closes so it can recover when displays reconnect.

  • shell/main.cpp L142

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 5 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="panels/dock/dockpanel.cpp" line_range="487" />
<code_context>
-                delete shellIntegration;
-                shellIntegration = nullptr;
-                qCWarning(layershellwindow) << "failed to init dlayershell intergration";
-                return;
-            }
-        }
</code_context>
<issue_to_address>
**Non-primary Dock stays hidden**

When the Dock is assigned to an external display, `showInPrimary()` is false, and that display is removed and reconnected, `primaryScreenChanged` is not connected in this screen-selection mode, so `updateDockScreen()` does not select a replacement screen or reach `win->show()` after reconnection; the Dock stays hidden.

Register a display-change recovery path for non-primary screen-selection modes so the Dock selects a replacement screen and is shown after reconnection.

Also at `panels/dock/dockpanel.cpp:493`.
</issue_to_address>

### Comment 2
<location path="frame/layershell/dlayershellwindow.cpp" line_range="297-299" />
<code_context>
+        }
+    }
+
+    if (!waylandWindow->shellSurface())
+        waylandWindow->setShellIntegration(shellIntegration);
+    return waylandWindow->shellIntegration() == shellIntegration;
+}
+
</code_context>
<issue_to_address>
**Dock stays hidden after reconnect**

When a reconnected Wayland window has a non-null shell surface created with an integration other than the layer-shell integration, `ensureWaylandShellIntegration()` skips `setShellIntegration()` because `shellSurface()` is non-null, then returns false because the integrations differ; `updateDockScreen()` consequently does not call `win->show()`, and the Dock stays hidden.

Make `ensureWaylandShellIntegration()` install or otherwise ensure the layer-shell integration based on integration identity, rather than skipping installation whenever a shell surface exists.
</issue_to_address>

### Comment 3
<location path="panels/dock/dockpanel.cpp" line_range="491-492" />
<code_context>
-                delete shellIntegration;
-                shellIntegration = nullptr;
-                qCWarning(layershellwindow) << "failed to init dlayershell intergration";
-                return;
-            }
-        }
</code_context>
<issue_to_address>
**Dock stays hidden after readiness**

When a primary-screen change arrives before the Wayland output or layer-shell integration is ready, and readiness follows without another primary-screen change, `updateDockScreen()` returns when the output is unavailable or does not show the Dock when `ensureWaylandShellIntegration()` fails, and neither path schedules another attempt; the Dock stays hidden.

Retry `updateDockScreen()` when the Wayland output and layer-shell integration become ready.
</issue_to_address>

### Comment 4
<location path="panels/dock/dockpanel.cpp" line_range="487" />
<code_context>
-                delete shellIntegration;
-                shellIntegration = nullptr;
-                qCWarning(layershellwindow) << "failed to init dlayershell intergration";
-                return;
-            }
-        }
</code_context>
<issue_to_address>
**Dock stays unmapped after reconnect**

When the Dock retains its visible flag after its active output is disconnected and the primary-screen change is processed, `win->isVisible()` remains true even though the disconnected output left the Dock’s platform surface unmapped, so `updateDockScreen()` returns without reinstalling layer-shell integration or showing the Dock; the Dock remains missing after reconnection.

Check whether the Wayland platform surface and layer-shell surface are actually usable, and restore them on reconnect even when the QWindow’s visible flag is still true.
</issue_to_address>

### Comment 5
<location path="panels/dock/taskmanager/treelandwindow.cpp" line_range="233" />
<code_context>
+
     auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow*>(baseWindow->handle());
-    if (waylandWindow->surface() == nullptr || gemeotry.isEmpty())
+    if (!waylandWindow || waylandWindow->surface() == nullptr || gemeotry.isEmpty())
         return;

</code_context>
<issue_to_address>
**Skipped icon geometry is never retried**

When the one-shot icon-geometry update runs during a hotplug gap and the delegate geometry does not change after reconnection, `setWindowIconGeometry()` returns while the delegate’s platform window is unavailable, discarding the pending geometry. If the platform window returns without another delegate geometry or window-list change, the compositor keeps stale icon geometry until a later update.

Retain the latest requested geometry and resend it when the platform surface becomes available, or schedule a retry after reconnection.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread panels/dock/dockpanel.cpp Resolved
Comment thread frame/layershell/dlayershellwindow.cpp Resolved
Comment thread panels/dock/dockpanel.cpp Resolved
Comment thread panels/dock/dockpanel.cpp Resolved

@gugullll gugullll left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在四处关键改动旁补充了显示器热拔插时的触发条件和修改原因。

Comment thread shell/main.cpp
setenv("DSG_APP_ID", "org.deepin.dde.shell", 0);
DGuiApplicationHelper::setAttribute(DGuiApplicationHelper::UseInactiveColorGroup, false);
DApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

拔掉唯一输出时,合成器会向 Dock 的 layer surface 发送 closed,旧逻辑随即关闭 Dock 窗口。若它是最后一个可见的主窗口,Qt 默认会退出 dde-shell。保留进程后,Qt Wayland 客户端才能继续接收显示器插回和主屏变化的通知。

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果这个PR完全只设 setQuitOnLastWindowClosed(false) 不做别的修改的话,会有效果不?

@gugullll gugullll Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只是让这个进程没有直接退出,但是已经丢失了layshell角色,变成普通窗口了,需要重建


auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow*>(baseWindow->handle());
if (waylandWindow->surface() == nullptr || gemeotry.isEmpty())
if (!waylandWindow || waylandWindow->surface() == nullptr || gemeotry.isEmpty())

@gugullll gugullll Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dock 关闭后,QML 的延迟定时器仍可能触发图标位置上报。此时 QWindow 对象可以还在,但它的 QWaylandWindow 已被销毁。崩溃落在这里的空指针解引用,因此平台窗口或 surface 不可用时应跳过本次上报。

Comment thread panels/dock/dockpanel.cpp
auto *waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(primary->handle());
if (!waylandScreen || !waylandScreen->output())
return;
if (DS_NAMESPACE::DLayerShellWindow::get(win)->ensureWaylandShellIntegration())

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

零屏时 Qt 会提供没有真实 wl_output 的占位屏,所以要等有效主屏可用。切屏后先确认 layer-shell integration 已装好,再调用 show(),让新 surface 按原有锚点显示。直接 show() 在实测中会走默认的普通窗口角色,Dock 因而贴错边。

@18202781743
18202781743 requested a review from BLumia November 10, 2026 06:20
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, gugullll

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

1. Keep dde-shell running when the last window closes.
2. Skip icon geometry updates while the platform window is unavailable.
3. Reinstall layer-shell integration before showing the Dock again.

Log: Restore the Dock at its configured edge after a display reconnects.

Influence:
1. Unplug and reconnect the only display, then check the Dock position.
2. Unplug the active external display in external-only mode and check Dock.
3. Repeat hotplug with open windows and check for crashes or restarts.

fix: 修复显示器重新接入后任务栏不恢复

1. 最后一个窗口关闭后保持 dde-shell 运行。
2. 平台窗口不可用时跳过任务图标位置上报。
3. 恢复任务栏前重新绑定 layer-shell。

Log: 显示器重新接入后,任务栏恢复到配置的屏幕边缘。

Influence:
1. 拔出并插回唯一显示器,确认任务栏恢复到原边缘。
2. 仅使用外接显示器时拔掉外接屏,检查任务栏是否恢复。
3. 打开多个窗口后反复拔插,检查 dde-shell 是否崩溃或重启。

PMS: BUG-382863
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 95 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交修复了显示器重连后 Dock 不恢复的问题,通过提取 ensureWaylandShellIntegration 方法实现 Wayland shell 集成的可重复调用,在 updateDockScreen 中检测主屏变化后恢复 Dock 可见性,并修复了 treelandwindow 中的空指针崩溃问题。代码整体质量良好,重构合理,逻辑清晰,无安全漏洞。存在一处潜在的空指针解引用风险和一处缺少注释的复杂条件判断,建议改进。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['建议在调用 DLayerShellWindow::get(win) 后添加空指针检查:auto *layerShell = DLayerShellWindow::get(win); if (!layerShell) return; if (layerShell->ensureWaylandShellIntegration()) win->show();']


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ["建议在 updateDockScreen() 的复杂条件前添加注释,说明仅在'主屏变化信号来自 qApp、窗口在主屏上、窗口当前不可见但应处于显示状态'时才恢复 Dock 显示", '建议将参数名 gemeotry 修正为 geometry']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: []


💡 改进建议代码示例

// dockpanel.cpp - 建议添加空指针检查
void DockPanel::updateDockScreen()
{
    auto *win = window();
    if (!win)
        return;

    auto *primary = qApp->primaryScreen();
    setDockScreen(primary);
    // 仅在主屏变化且窗口需要恢复时重新显示
    if (sender() != qApp || !primary || win->screen() != primary || win->isVisible() || hideState() != Show)
        return;

    auto *waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(primary->handle());
    if (!waylandScreen || !waylandScreen->output())
        return;

    auto *layerShell = DS_NAMESPACE::DLayerShellWindow::get(win);
    if (!layerShell)  // 添加空指针检查
        return;
    if (layerShell->ensureWaylandShellIntegration())
        win->show();
}

本报告由 AI 代码审查工具自动生成

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants