Skip to content

fix(surface): restore keyboard focus after minimizing the focused window - #1498

Merged
wineee merged 1 commit into
linuxdeepin:masterfrom
deepin-wm:fix/wm633-minimize-focus-fallback
Oct 29, 2026
Merged

wineee merged 1 commit into
linuxdeepin:masterfrom
deepin-wm:fix/wm633-minimize-focus-fallback

Conversation

@deepin-wm

@deepin-wm deepin-wm commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

问题

最小化当前持有键盘焦点的窗口后,焦点没有回落到上一个窗口。复现:依次打开 A、B、C(C 激活并持焦),最小化 C 后 B 既没有被激活、也没有拿到键盘焦点。

原因

SurfaceWrapper::minimize() 里两个能力位的更新顺序有问题:

  1. 先 updateFocusControlState(UnMinimized, false) → SeatSurfaceManager::onActivatedSurfaceFocusCapabilityChanged() 无条件把该 seat 的键盘焦点清成 nullptr;
  2. 再 updateHasActiveCapability(UnMinimized, false) → ShellHandler::onSurfaceInactivationRequested()。

第 2 步用 seatContainer->keyboardFocusSurface() == wrapper 判断"要不要回退焦点",而此时焦点已在第 1 步被清空,判断为 false,于是只清了激活态,回退分支被跳过 —— 结果没有任何窗口获得焦点。

改动

  • src/surface/surfacewrapper.cpp(minimize()):交换两处能力位更新的顺序,先丢 active capability(触发焦点回退,此时本窗口仍是焦点所有者),再丢 focus capability。这是治本的一步。
  • src/core/shellhandler.cpp(onSurfaceInactivationRequested()):让 handler 不再依赖能力位顺序 —— 进入"焦点所有者"分支时先 setActivatedSurface(nullptr, seat),同时覆盖非主 seat(原本只清焦点、会残留"已最小化但仍激活")和回退被拒(activateSurface 提前 return,例如候选窗口带最小化模态)两种情况;回退被拒后再兜底清一次键盘焦点,保证最小化的窗口不会残留激活态或键盘焦点。

验证

测试机 10.20.33.125(treeland 0.10.0 源码等价回移 + Debug 构建,全量 1414/1414 通过),判定依据是 treeland-debug 读合成器状态:GET /api/windows 的 active / state、GET /api/focused,不看像素。

步骤 预期 实际
打开 A、B、C 并激活 C C 激活且持焦 focused=C,C active=true
最小化 C B 激活并持焦 focused=B,B active=true,C state=2 active=false
再最小化 B A 激活并持焦 focused=A,A active=true
全部最小化 无窗口激活/持焦 focused=0,三个窗口 state=2 active=false
从任务栏恢复 C C 激活并持焦 focused=C,C active=true state=0

master 上的构建验证在 10.20.33.81:/tmp/wm633 完成,全量 1961/1961 通过。

未覆盖项

  • 最小化时焦点在 layer surface(dock/通知)上的分支未真实执行:测试机上 treeland-debug activate 对 layer surface 是空操作,指针注入在该机也不会激活窗口,因此 isActivatedOwner 且非焦点所有者的既有分支没有被真实跑到。
  • 带模态子窗口的最小化路径未验证:测试机无法构造真实的 xdg modal(没有 qml 运行时、zenity/yad,xmessage 设不了 transient parent)。
  • 验证是在 0.10.0 源码上做等价回移后进行的,不是直接跑本 PR 的 diff(0.11 产物依赖 libddm ≥ 0.4.0.3 / dtk 6.7.51,测试机没有,且 /usr 是只读 overlay)。
  • 键盘焦点是从合成器状态读的,未用真实击键验证:该机输入注入落不到客户端(日志 Cannot map device ... to output),属测试机 seat/设备映射问题,与本改动无关。

相关 issue

WM-633

Summary by Sourcery

Restore reliable focus fallback when minimizing the focused window.

Bug Fixes:

  • Restore keyboard focus to the previous eligible window when minimizing the currently focused window.
  • Prevent minimized surfaces from retaining activated or keyboard-focused state when fallback activation is unavailable or occurs on a non-primary seat.

Enhancements:

  • Make surface inactivation handling robust against focus-fallback ordering and refused fallback activation.

@deepin-ci-robot

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@sourcery-ai

sourcery-ai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Restores activation and keyboard-focus fallback when minimizing the focused window by correcting capability-update ordering and hardening inactivation cleanup against non-primary seats and refused fallback activation.

Sequence diagram for keyboard focus fallback when minimizing a focused window

sequenceDiagram
    participant SurfaceWrapper
    participant ShellHandler
    participant SeatSurfaceManager
    participant Server
    participant PreviousWindow

    SurfaceWrapper->>SurfaceWrapper: minimize(false)
    SurfaceWrapper->>ShellHandler: updateHasActiveCapability(UnMinimized, false)
    ShellHandler->>ShellHandler: onSurfaceInactivationRequested(wrapper)
    ShellHandler->>Server: setActivatedSurface(nullptr, seat)
    ShellHandler->>Server: activateSurface(PreviousWindow, seat)
    Server-->>PreviousWindow: set activated and keyboard focus
    SurfaceWrapper->>SeatSurfaceManager: updateFocusControlState(UnMinimized, false)
    SeatSurfaceManager->>Server: requestKeyboardFocus(nullptr, OtherFocusReason, seat)
Loading

File-Level Changes

Change Details Files
Preserve the focused surface during capability updates so minimizing it triggers the normal activation and keyboard-focus fallback.
  • Reordered minimize capability removal to drop active capability before focus capability.
  • Allows the inactivation handler to observe the minimized surface as the current focus owner when selecting a fallback.
src/surface/surfacewrapper.cpp
Make surface inactivation cleanup independent of capability-update ordering and fallback success.
  • Clears the activated surface before attempting fallback activation, including non-primary seats.
  • Explicitly clears keyboard focus if fallback activation is refused or leaves focus on the minimized surface.
src/core/shellhandler.cpp

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

@Groveer
Groveer marked this pull request as ready for review October 23, 2026 08:09
@Groveer
Groveer force-pushed the fix/wm633-minimize-focus-fallback branch from d982c0d to f6d41c9 Compare October 23, 2026 08:09

@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 reviewed your changes and they look great!


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

minimize() dropped the focus capability before the active capability, so
SeatSurfaceManager cleared the seat keyboard focus first. When ShellHandler
handled the inactivation it no longer saw this surface as the focus owner
and only cleared the activated state, leaving no window focused.

Drop the active capability first so the fallback still sees this surface as
the focus owner, and harden onSurfaceInactivationRequested to clear the
activated state up front and to clear the keyboard focus when the fallback
is refused.

Log: 修复最小化当前焦点窗口后焦点没有回落到上一个窗口的问题
Influence:
1. Open A, B, C and minimize C: B becomes activated and focused.
2. Minimize every window: no window stays activated or focused.
3. Restore a minimized window: it becomes activated and focused.
4. Minimize a window while a layer surface holds focus: the layer surface
   keeps focus and the window no longer stays activated.
5. Minimize a window whose modal is minimized: no window stays activated or
   keyboard-focused.

Multica Issue: WM-633
@Groveer
Groveer force-pushed the fix/wm633-minimize-focus-fallback branch from f6d41c9 to efb6b32 Compare October 29, 2026 06:13
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deepin-wm, wineee

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

@wineee
wineee merged commit 3e707c8 into linuxdeepin:master Oct 29, 2026
6 of 7 checks passed
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