Skip to content

WM-449: fix(surface): use dedicated field for fullscreen state snapshot - #1390

Closed
deepin-wm wants to merge 2 commits into
linuxdeepin:masterfrom
deepin-wm:agent/git-commit/32bad9104e57
Closed

WM-449: fix(surface): use dedicated field for fullscreen state snapshot#1390
deepin-wm wants to merge 2 commits into
linuxdeepin:masterfrom
deepin-wm:agent/git-commit/32bad9104e57

Conversation

@deepin-wm

@deepin-wm deepin-wm commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

修复内容

m_previousSurfaceState 同时被 leaveFullscreen()restoreFromMinimized() 复用,在「全屏 → 最小化 → 恢复 → 取消全屏」序列中快照被污染为 Minimized,导致窗口退出全屏后错误地恢复到最小化状态且此后无法回到 Normal。

改动

  • src/surface/surfacewrapper.h:新增独立成员 m_stateBeforeFullscreen,仅在进入全屏时一次性快照前置状态。
  • src/surface/surfacewrapper.cpp
    • enterFullscreen() 在两条路径(主路径 + XdgToplevel 未映射早返回路径)写入 m_stateBeforeFullscreen,并加 if (m_surfaceState != State::Fullscreen) 重入守卫,避免已全屏再次进入全屏时快照被污染为 Fullscreen
    • leaveFullscreen() 改读 m_stateBeforeFullscreen,不再依赖 m_previousSurfaceState
    • m_previousSurfaceState 继续服务于 restoreFromMinimized() 的原有职责,两者互不干扰。

验证链路

  1. enterFullscreen()m_stateBeforeFullscreen = Normal,状态 → Fullscreen
  2. 全屏期间 minimize():状态 → Minimized(m_stateBeforeFullscreen 不变)
  3. restoreFromMinimized():状态 → Fullscreen(m_stateBeforeFullscreen 仍 Normal)
  4. leaveFullscreen():恢复到 m_stateBeforeFullscreen = Normal

Multica issue: WM-449

Summary by Sourcery

Decouple minimized state from surface state to preserve fullscreen restoration and accurately represent minimized windows throughout the compositor.

New Features:

  • Expose minimized state independently from the surface layout state across QML, remote window data, and debugging tools.

Bug Fixes:

  • Preserve correct window visibility, decoration, focus, parent/child minimization, and fullscreen behavior when minimizing and restoring surfaces.

Enhancements:

  • Separate minimization state management from surface state transitions so fullscreen state and minimized state no longer interfere with each other.
  • Update workspace proxies and minimize animations to use the dedicated minimized-state property.

@deepin-wm
deepin-wm marked this pull request as draft September 10, 2026 09:25
@sourcery-ai

sourcery-ai Bot commented Sep 10, 2026

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

Reviewer's Guide

Fix fullscreen state restoration by storing the pre-fullscreen state in a dedicated member, keeping it independent from minimize/restore bookkeeping and preserving the correct state across fullscreen, minimize, restore, and exit transitions.

State diagram for fullscreen and minimized state restoration

stateDiagram-v2
    [*] --> Normal
    Normal --> Fullscreen: enterFullscreen()
    Fullscreen --> Minimized: minimize()
    Minimized --> Fullscreen: restoreFromMinimized()
    Fullscreen --> Normal: leaveFullscreen()

    state Fullscreen {
        [*] --> Active
        Active: m_stateBeforeFullscreen = Normal
    }

    note right of Fullscreen
        m_previousSurfaceState is used by minimize/restore.
        m_stateBeforeFullscreen remains Normal.
    end note
Loading

File-Level Changes

Change Details Files
Separate the fullscreen-entry snapshot from the minimized-state restoration snapshot.
  • Add a dedicated pre-fullscreen state member initialized to Normal.
  • Capture the state when entering fullscreen through both mapped and unmapped XdgToplevel paths.
  • Restore from the dedicated snapshot when leaving fullscreen, while retaining the existing previous-state field for minimized restoration.
src/surface/surfacewrapper.h
src/surface/surfacewrapper.cpp
Prevent fullscreen transitions from overwriting the original pre-fullscreen state.
  • Guard snapshot updates when already fullscreen or minimized.
  • Preserve the snapshot across minimize and restore cycles, including repeated fullscreen entry attempts.
src/surface/surfacewrapper.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

@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 ✨

@deepin-wm
deepin-wm force-pushed the agent/git-commit/32bad9104e57 branch from df160e0 to 1103357 Compare September 10, 2026 09:38
@deepin-wm
deepin-wm marked this pull request as ready for review September 10, 2026 09:58

@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 1 issue

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

## Individual Comments

### Comment 1
<location path="src/surface/surfacewrapper.cpp" line_range="1994-1996" />
<code_context>
         auto *xdgSurface = qobject_cast<WXdgToplevelSurface *>(m_shellSurface.data());
-        if (xdgSurface->isInitialized())
+        if (xdgSurface->isInitialized()) {
+            if (m_surfaceState != State::Fullscreen && m_surfaceState != State::Minimized)
+                m_stateBeforeFullscreen = m_surfaceState;
             setSurfaceStateDirectly(State::Fullscreen);
+        }
         return;
</code_context>
<issue_to_address>
**issue (bug_risk):** An unmapped XdgToplevel that is currently `Minimized` bypasses the normal-path minimized guard and is changed to `Fullscreen`; the mapped path returns without changing state. This produces different fullscreen behavior solely based on whether the surface is mapped.

**Triggers:** When `enterFullscreen()` is called for an initialized, unmapped XdgToplevel whose state is `Minimized`.

**Suggested fix:** Return when `m_surfaceState == State::Minimized` before the unmapped-path transition, or apply the same minimized guard to both paths.
</issue_to_address>

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

Comment thread src/surface/surfacewrapper.cpp Outdated
@deepin-wm
deepin-wm marked this pull request as draft September 10, 2026 11:30
@deepin-bot

deepin-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.10.0
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1392

@deepin-wm
deepin-wm force-pushed the agent/git-commit/32bad9104e57 branch from 1103357 to 27e22f6 Compare September 10, 2026 12:12
@deepin-wm
deepin-wm marked this pull request as ready for review September 10, 2026 12:21

@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 ✨

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@deepin-wm
deepin-wm force-pushed the agent/git-commit/32bad9104e57 branch 5 times, most recently from 9006fcf to c3a0a64 Compare September 11, 2026 07:38
Comment thread src/surface/surfacewrapper.cpp Outdated
if (modal() && m_parentSurface && !m_parentSurface->isMinimized())
m_parentSurface->minimize(false);

setVisibleDecoration(true);

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.

最小化为什么会 调用 setVisibleDecoration(true) 和 updateTitleBar() ?

@deepin-wm
deepin-wm force-pushed the agent/git-commit/32bad9104e57 branch from c3a0a64 to 6ba19c2 Compare September 11, 2026 08:03
… state

- Add independent `m_minimized` bitfield to SurfaceWrapper, decoupling
  minimized state from `m_surfaceState` so a window can be both minimized
  and fullscreen/maximized/tiling simultaneously.
- `minimize()` / `restoreFromMinimized()` no longer go through
  `doSetSurfaceState()`; they only toggle `m_minimized` and call
  `shellSurface->setMinimize()` with focus/active-control updates.
- `doSetSurfaceState()` removes the Minimized branch; `m_surfaceState`
  now only represents layout state (Normal/Maximized/Fullscreen/Tiling).
- `enterFullscreen()` / `leaveFullscreen()` skip animation when the
  window is not visible (`!isVisible()`), using
  `setSurfaceStateDirectly()` instead.
- QML: `WorkspaceProxy.qml` uses `!surface.minimized` instead of
  `surfaceState !== State.Minimized`; `MinimizeAnimation.qml`
  unifies `showShadow` on `surfaceState === State.Normal`.

Log: 修复全屏→最小化→恢复→取消全屏后窗口卡在最小化状态
PMS: BUG-376727
Influence: SurfaceWrapper 全屏与最小化状态恢复逻辑,不影响其他模块
Signed-off-by: glyvut <guolin@uniontech.com>
- Add `bool minimized` field to `WindowInfo` POD in
  `treelandwindowtree.rep` and populate it in
  `treelandremotesource.cpp`.
- `treeland-debug`: show minimized column in table/tree/top output,
  include it in JSON serialization, and report minimize/unminimize
  transitions in watch mode.

Log: treeland-debug 补上 minimized 状态显示
PMS: BUG-376727
Influence: treeland-debug 调试工具及 WindowInfo 序列化,不影响窗口管理逻辑
Signed-off-by: glyvut <guolin@uniontech.com>
@deepin-wm
deepin-wm force-pushed the agent/git-commit/32bad9104e57 branch from 6ba19c2 to d59d0d7 Compare September 11, 2026 08:14
@deepin-wm

Copy link
Copy Markdown
Contributor Author

该 issue 已取消,关闭此 PR。

@deepin-wm deepin-wm closed this Sep 11, 2026
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