feat(modules): introduce WineWindowState protocol module#851
Conversation
|
Skipping CI for Draft Pull Request. |
There was a problem hiding this comment.
Pull request overview
Introduces new Treeland Wayland protocol modules intended to expose Wine window state/control to clients, and refactors compositor initialization so protocol managers (prelaunch-splash, app-id-resolver, wine modules, xdg/layer/wallpaper shell, input method helper) are initialized from ShellHandler instead of Helper.
中文:新增用于向客户端暴露 Wine 窗口状态/控制的 Treeland Wayland 协议模块,并重构初始化流程,把相关协议管理器(prelaunch-splash、app-id-resolver、wine 模块、xdg/layer/wallpaper shell、输入法辅助)从 Helper 迁移到 ShellHandler 统一初始化。
Changes:
- Add
wine-window-stateandwine-window-managementprotocol manager modules and hook them into the server init path. - Consolidate shell/protocol initialization into
ShellHandler::init(server, seat)and adjustHelper::init()accordingly. - Remove now-unused prelaunch/app-id-resolver wiring from
Helper.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
src/seat/helper.h |
Removes unused includes/forward decls and drops prelaunch splash member. |
src/seat/helper.cpp |
Moves protocol initialization responsibilities to ShellHandler::init() and adjusts wallpaper-shell signal hookup timing. |
src/core/shellhandler.h |
Replaces multiple init methods with init(server, seat) and adds members for new protocol managers. |
src/core/shellhandler.cpp |
Implements unified init sequence; attaches prelaunch/app-id-resolver and new wine protocol managers. |
src/modules/wine-window-state/winewindowstate.h/.cpp |
Adds Wine window state protocol manager + per-toplevel state object. |
src/modules/wine-window-management/winewindowmanagement.h/.cpp |
Adds Wine window management protocol manager + per-toplevel control object. |
src/modules/wine-window-state/CMakeLists.txt |
Adds build rules/protocol generation for wine-window-state module. |
src/modules/wine-window-management/CMakeLists.txt |
Adds build rules/protocol generation for wine-window-management module. |
src/modules/CMakeLists.txt |
Registers the two new module subdirectories. |
4018369 to
92735b5
Compare
Reviewer's GuideIntroduces new Wine-specific Wayland protocol modules for window state and management, wires them into the shell initialization path, centralizes shell-related server initialization in ShellHandler::init, and tightens SurfaceWrapper/SimpleProxy lifetime semantics. Sequence diagram for WineWindowManagement get_window_control and z-order operationssequenceDiagram
participant Client
participant WineWindowManager as WineWindowManagementManagerPrivate
participant Helper
participant Root as RootSurfaceContainer
participant WXdg as WXdgToplevelSurface
participant Wrapper as SurfaceWrapper
participant Control as WineWindowControl
Client->>WineWindowManager: get_window_control(resource,id,toplevelResource)
WineWindowManager->>WXdg: from_resource(toplevelResource)
alt invalid_toplevel
WineWindowManager-->>Client: wl_resource_post_error(DEFUNCT_TOPLEVEL)
else valid_toplevel
WineWindowManager->>Helper: instance()
Helper-->>WineWindowManager: helper
WineWindowManager->>Helper: rootSurfaceContainer()
Helper-->>WineWindowManager: Root
WineWindowManager->>Root: getSurface(WXdg)
Root-->>WineWindowManager: Wrapper
alt no_wrapper
WineWindowManager-->>Client: wl_resource_post_error(DEFUNCT_TOPLEVEL)
else wrapper_found
WineWindowManager->>WineWindowManager: alreadyControlled?
alt already_controlled
WineWindowManager-->>Client: wl_resource_post_error(TOPLEVEL_ALREADY_CONTROLLED)
else not_controlled
WineWindowManager->>WineWindowManager: windowId = nextWindowId()
WineWindowManager->>Control: new WineWindowControl(windowId,Wrapper,...)
WineWindowManager->>WineWindowManager: registerControl(windowId,WXdg,Control)
Control-->>Client: send_window_id(windowId)
Control-->>Client: send_configure_position(x,y)
Control-->>Client: send_configure_stacking(alwaysOnTop)
end
end
end
Client->>Control: set_z_order(op=z_order_op_hwnd_topmost,sibling_id=0)
Control->>Wrapper: setAlwaysOnTop(true)
Control->>Wrapper: applyHwndTop() via stacking APIs
Class diagram for new WineWindowState protocol moduleclassDiagram
class WineWindowStateManager {
+WineWindowStateManager(parent)
+~WineWindowStateManager()
+void create(WServer* server)
+void destroy(WServer* server)
+wl_global* global() const
+QByteArrayView interfaceName() const
-unique_ptr~WineWindowStateManagerPrivate~ d
}
class WineWindowStateManagerPrivate {
+WineWindowStateManagerPrivate(WineWindowStateManager* q)
+wl_global* globalHandle() const
+void removeState(WineWindowState* state)
+void get_window_state(Resource* resource, uint32_t id, wl_resource* toplevelResource)
-void bindState(WXdgToplevelSurface* toplevel, WineWindowState* state)
-void destroy_global()
-void destroy(Resource* resource)
-WineWindowStateManager* q
-QList~StateEntry~ m_states
}
class StateEntry {
+WXdgToplevelSurface* toplevel
+WineWindowState* state
}
class WineWindowState {
+WineWindowState(QObject* parent, WineWindowStateManagerPrivate* manager, SurfaceWrapper* wrapper, wl_client* client, int version, uint32_t id)
-void destroy(Resource* resource)
-void destroy_resource(Resource* resource)
-void unminimize(Resource* resource)
-void activate(Resource* resource, uint32_t serial, uint32_t reason, wl_resource* seat)
-void set_attention(Resource* resource, uint32_t count, uint32_t timeoutMs)
-void clear_attention(Resource* resource)
-void sendStateChanged()
-WineWindowStateManagerPrivate* m_manager
-SurfaceWrapper* m_wrapper
-bool m_attention
}
class SurfaceWrapper {
+bool isMinimized() const
+void requestCancelMinimize()
+bool acceptKeyboardFocus() const
+bool hasActiveCapability() const
+WToplevelSurface* shellSurface() const
+bool alwaysOnTop() const
+Q_SIGNALS aboutToBeInvalidated()
}
class WToplevelSurface {
+enum Capability
+bool hasCapability(Capability cap) const
+Q_SIGNAL minimizeChanged()
}
class Helper {
+static Helper* instance()
+bool blockActivateSurface() const
+void forceActivateSurface(SurfaceWrapper* wrapper)
+RootSurfaceContainer* rootSurfaceContainer() const
}
class RootSurfaceContainer {
+SurfaceWrapper* getSurface(WXdgToplevelSurface* toplevel) const
}
class WXdgToplevelSurface
WineWindowStateManager --> WineWindowStateManagerPrivate : owns
WineWindowStateManagerPrivate *-- StateEntry : uses
WineWindowStateManagerPrivate --> WXdgToplevelSurface : tracks
WineWindowStateManagerPrivate --> WineWindowState : creates
WineWindowState --> WineWindowStateManagerPrivate : m_manager
WineWindowState --> SurfaceWrapper : m_wrapper
SurfaceWrapper --> WToplevelSurface : shellSurface
WineWindowState ..> Helper : uses Helper.instance
WineWindowStateManagerPrivate ..> Helper : uses
Helper --> RootSurfaceContainer : rootSurfaceContainer
RootSurfaceContainer --> WXdgToplevelSurface : key
RootSurfaceContainer --> SurfaceWrapper : returns
Class diagram for new WineWindowManagement protocol moduleclassDiagram
class WineWindowManagementManager {
+WineWindowManagementManager(parent)
+~WineWindowManagementManager()
+void create(WServer* server)
+void destroy(WServer* server)
+wl_global* global() const
+QByteArrayView interfaceName() const
-unique_ptr~WineWindowManagementManagerPrivate~ d
}
class WineWindowManagementManagerPrivate {
+WineWindowManagementManagerPrivate(WineWindowManagementManager* q)
+wl_global* globalHandle() const
+uint32_t nextWindowId()
+WineWindowControl* controlForId(uint32_t id) const
+void registerControl(uint32_t id, WXdgToplevelSurface* toplevel, WineWindowControl* control)
+void removeControl(WineWindowControl* control)
+void get_window_control(Resource* resource, uint32_t id, wl_resource* toplevelResource)
-void destroy_global()
-void destroy(Resource* resource)
-WineWindowManagementManager* q
-uint32_t m_nextId
-QList~ControlEntry~ m_controls
}
class ControlEntry {
+uint32_t id
+WXdgToplevelSurface* toplevel
+WineWindowControl* control
}
class WineWindowControl {
+WineWindowControl(QObject* parent, WineWindowManagementManagerPrivate* manager, uint32_t windowId, SurfaceWrapper* wrapper, wl_client* client, int version, uint32_t id)
+uint32_t windowId() const
+SurfaceWrapper* wrapper() const
-void destroy(Resource* resource)
-void destroy_resource(Resource* resource)
-void set_position(Resource* resource, int32_t x, int32_t y)
-void set_z_order(Resource* resource, uint32_t op, uint32_t sibling_id)
-void sendConfigurePosition()
-void sendConfigureStacking()
-void applyHwndTop()
-void applyHwndBottom()
-void applyHwndInsertAfter(uint32_t siblingId)
-WineWindowManagementManagerPrivate* m_manager
-uint32_t m_windowId
-SurfaceWrapper* m_wrapper
}
class SurfaceWrapper {
+void setPositionAutomatic(bool automatic)
+void setPosition(QPointF pos)
+bool alwaysOnTop() const
+void setAlwaysOnTop(bool onTop)
+QQuickItem* parentItem() const
+QList~QQuickItem*~ childItems() const
+void stackBefore(QQuickItem* sibling)
+void stackAfter(QQuickItem* sibling)
+Q_SIGNALS aboutToBeInvalidated()
+Q_SIGNALS alwaysOnTopChanged()
}
class Helper {
+static Helper* instance()
+RootSurfaceContainer* rootSurfaceContainer() const
}
class RootSurfaceContainer {
+SurfaceWrapper* getSurface(WXdgToplevelSurface* toplevel) const
}
class WXdgToplevelSurface
WineWindowManagementManager --> WineWindowManagementManagerPrivate : owns
WineWindowManagementManagerPrivate *-- ControlEntry : uses
WineWindowManagementManagerPrivate --> WineWindowControl : creates
WineWindowManagementManagerPrivate --> WXdgToplevelSurface : tracks
WineWindowManagementManagerPrivate ..> Helper : uses
Helper --> RootSurfaceContainer : rootSurfaceContainer
RootSurfaceContainer --> WXdgToplevelSurface
RootSurfaceContainer --> SurfaceWrapper
WineWindowControl --> WineWindowManagementManagerPrivate : m_manager
WineWindowControl --> SurfaceWrapper : m_wrapper
WineWindowControl ..> QQuickItem : stacking
Flow diagram for SurfaceProxy and SurfaceWrapper lifetime constraintsflowchart TD
A["SurfaceProxy::setSurface(newSurface)"] --> B{m_proxySurface exists?}
B -->|no| C["m_sourceSurface = newSurface"]
B -->|yes| D["m_proxySurface->markWrapperToRemoved()"]
D --> E["m_proxySurface = nullptr"]
E --> C
subgraph SurfaceWrapperLifecycle
C --> F["SurfaceWrapper marked via markWrapperToRemoved"]
F --> G["SurfaceWrapper destruction begins"]
G --> H{"m_wrapperAboutToRemove is true?"}
H -->|yes| I["Destructor continues"]
H -->|no| J["Q_ASSERT_X failure: must be removed via markWrapperToRemoved"]
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- In
WineWindowControl::set_z_order, theswitchhas nodefaultbranch and silently ignores out-of-rangeopvalues; consider explicitly validating the enum range and posting a Wayland error for unknown operations so protocol misuse is surfaced clearly. - Both
WineWindowManagementManagerPrivateandWineWindowStateManagerPrivatekeep containers of live controls/states butdestroy_global()only logs; it would be safer to clear these lists and null out manager back-references (or destroy remaining resources) when the global is torn down to avoid potential dangling pointers if globals are removed while clients are still connected.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `WineWindowControl::set_z_order`, the `switch` has no `default` branch and silently ignores out-of-range `op` values; consider explicitly validating the enum range and posting a Wayland error for unknown operations so protocol misuse is surfaced clearly.
- Both `WineWindowManagementManagerPrivate` and `WineWindowStateManagerPrivate` keep containers of live controls/states but `destroy_global()` only logs; it would be safer to clear these lists and null out manager back-references (or destroy remaining resources) when the global is torn down to avoid potential dangling pointers if globals are removed while clients are still connected.
## Individual Comments
### Comment 1
<location path="src/surface/surfaceproxy.cpp" line_range="33" />
<code_context>
m_sourceSurface = newSurface;
if (m_proxySurface) {
- m_proxySurface->deleteLater();
+ m_proxySurface->markWrapperToRemoved();
m_proxySurface = nullptr;
}
</code_context>
<issue_to_address>
**issue (bug_risk):** Switching from deleteLater() to markWrapperToRemoved() tightens the lifecycle and may assert in more cases.
Given the new `SurfaceWrapper` destructor assert and `deleteLater` being private, please verify that all destruction paths (including QObject parent cleanup and QML tree teardown) now route through `markWrapperToRemoved()`. Any remaining implicit deletions that bypass `markWrapperToRemoved()` will hit the new destructor assert.
</issue_to_address>
### Comment 2
<location path="src/surface/surfacewrapper.cpp" line_range="181" />
<code_context>
SurfaceWrapper::~SurfaceWrapper()
{
+ Q_ASSERT_X(m_wrapperAboutToRemove,
+ Q_FUNC_INFO,
+ "SurfaceWrapper must be removed via markWrapperToRemoved before destruction");
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The new destructor assert assumes every destruction goes through markWrapperToRemoved, which may not hold for all ownership paths.
This assert will catch incorrect destruction, but it will also abort on any valid implicit deletion path (e.g., parent QObject/QQuickItem destruction or QML engine shutdown) that doesn’t call `markWrapperToRemoved()`. Please audit all ownership paths where `SurfaceWrapper` is managed via QObject parentage/QML and either route them through `markWrapperToRemoved()` or adjust the assertion, otherwise you risk hard‑to‑reproduce crashes on shutdown or reparenting.
Suggested implementation:
```cpp
SurfaceWrapper::~SurfaceWrapper()
{
#ifndef QT_NO_DEBUG
if (!m_wrapperAboutToRemove) {
qWarning().nospace()
<< Q_FUNC_INFO
<< ": SurfaceWrapper destroyed without markWrapperToRemoved; "
"this may be expected for QObject/QML-managed lifetime "
"paths (e.g. parent destruction or engine shutdown), but "
"should be audited to ensure proper removal.";
}
#endif
Q_ASSERT(!m_ownsOutput);
Q_ASSERT(!m_container);
Q_ASSERT(!m_parentSurface);
```
If you want stricter checking after auditing all ownership paths, you can re-tighten this by:
1. Introducing a more specific flag (e.g. `m_qmlManagedLifetime`) set for QML/parent-owned instances.
2. Changing the `if (!m_wrapperAboutToRemove)` condition to only allow missing `markWrapperToRemoved()` for those instances, and reintroducing `Q_ASSERT_X` for all other cases.
</issue_to_address>
### Comment 3
<location path="src/modules/wine-window-state/winewindowstate.cpp" line_range="268-270" />
<code_context>
+ return d->globalHandle();
+}
+
+QByteArrayView WineWindowStateManager::interfaceName() const
+{
+ return QtWaylandServer::treeland_wine_window_state_manager_v1::interfaceName();
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** interfaceName() uses a static method that may not exist on the generated Wayland wrapper.
In `WineWindowManagementManager` you use `QtWaylandServer::treeland_wine_window_manager_v1::interface()->name`, but here you call `treeland_wine_window_state_manager_v1::interfaceName()`. The generated QtWaylandServer classes usually only expose `interface()`, not `interfaceName()`, so this may not compile. To keep it consistent and safe, use something like:
```cpp
return QtWaylandServer::treeland_wine_window_state_manager_v1::interface()->name;
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
978b423 to
5c76fe0
Compare
…tial integration Add a new Wayland server-side module under src/modules/wine-window-state implementing treeland_wine_window_state_manager_v1 and treeland_wine_window_state_v1. The module now supports per-toplevel state binding, minimized/attention state notifications, unminimize requests, and guarded activate requests. Build integration updates include adding the module subdirectory and generating protocol sources through local_qtwayland_server_protocol_treeland, with the generated server protocol C source compiled into the module target. In Helper initialization flow, remove direct attachment/wiring for prelaunch splash, app-id resolver, and wine window state managers, and drop related forward declarations/includes from helper header to prepare ownership migration toward ShellHandler.
…single-shot init Replace fragmented shell setup entry points with a single ShellHandler::init(WServer*, WSeat*) that performs one-time initialization for prelaunch splash, app-id resolver, wine window state manager, xdg shell, layer shell, wallpaper shell, and input method helper in a strict order. Remove redundant nullable/partial initialization branches and enforce single invocation semantics via explicit precondition checks and one-call wiring from Helper after seat readiness, so startup ownership and lifecycle are centralized in ShellHandler. Also clean related API/header surface by deleting obsolete split init declarations and removing stale includes/forward declarations that were no longer directly used by Helper.
Introduce a new Wine window management module implementing the treeland- wine-window-management-unstable-v1 protocol. This includes: 1. New CMakeLists entry and build logic for the module. 2. Addition of WineWindowManagementManager and its private implementation. 3. Integration into ShellHandler for initialization and lifecycle management. 4. WineWindowControl class, enabling fine-grained position and z-order control for managed XDG toplevel surfaces, specifically targeting Wine windows. 5. Protocol logic for window control creation, stacking, and position, with robust error handling for invalid or duplicate requests. This change enables advanced window management features for Wine clients, allowing for more accurate emulation of Windows-style window stacking and positioning within the compositor. The infrastructure is modular and only activated when the protocol is requested. Log: Added Wine window management protocol for advanced stacking and position control Influence: 1. Test protocol registration and ensure the global is advertised to clients. 2. Verify window control creation for valid and invalid XDG toplevel resources. 3. Test set_position and set_z_order requests, including all z-order operations (top, bottom, topmost, notopmost, insert_after). 4. Validate error handling for duplicate control requests and defunct toplevels. 5. Test window stacking and position changes visually and programmatically. 6. Confirm that destroying a control cleans up all associated mappings and does not leak resources. feat: 新增 Wine 窗口管理协议模块 引入全新的 Wine 窗口管理模块,实现 treeland-wine-window-management- unstable-v1 协议。主要内容包括: 1. 新增模块的 CMakeLists 构建配置。 2. 添加 WineWindowManagementManager 及其私有实现。 3. 在 ShellHandler 中集成初始化与生命周期管理。 4. 提供 WineWindowControl 类,实现对受管 XDG toplevel 窗口的精细位置和层 级控制,主要面向 Wine 窗口场景。 5. 实现协议逻辑,包括窗口控制创建、堆叠、位置调整,并对非法或重复请求做 出错误处理。 本次变更为 Wine 客户端带来更高级的窗口管理能力,使其在合成器中可更准确 地模拟 Windows 风格的窗口堆叠与定位。模块化设计,仅在客户端请求协议时 激活。 Log: 新增 Wine 窗口管理协议,支持高级堆叠与位置控制 Influence: 1. 测试协议注册,确认 global 能正常向客户端广播。 2. 验证对有效和无效 XDG toplevel 资源的窗口控制创建流程。 3. 测试 set_position 和 set_z_order 请求,覆盖全部堆叠操作(top、 bottom、topmost、notopmost、insert_after)。 4. 验证对重复控制请求和失效 toplevel 的错误处理。 5. 从界面和程序两方面测试窗口堆叠与位置变化。 6. 确认销毁控制对象后,所有相关映射均能正确清理,无资源泄漏。
1. Replace multiple QHash containers with single QList of struct entries in both WineWindowManagement and WineWindowState modules 2. Switch from imperative to reactive update pattern for position and stacking state changes 3. Add signal connections for xChanged, yChanged, and alwaysOnTopChanged to automatically trigger state updates 4. Remove redundant manual sendConfigurePosition and sendConfigureStacking calls 5. Add warning log for incomplete set_attention functionality 6. Remove unnecessary debug logging for manager lifecycle 7. Reorder header includes for better organization 8. Simplify null check for Helper::instance() access Influence: 1. Verify Wine window position synchronization still works correctly when windows are moved 2. Test z-order operations including topmost, notopmost, bottom, and insert_after 3. Verify toplevel already controlled/bound error handling still triggers correctly 4. Test window control registration and removal lifecycle 5. Verify no regression in Wine application window management behavior 6. Check that attention state warning is logged appropriately when triggered refactor: 简化 Wine 窗口数据结构 1. 在 WineWindowManagement 和 WineWindowState 模块中,将多个 QHash 容器 替换为单个 QList 结构体列表 2. 将位置和堆叠状态更新从命令式模式切换为响应式模式 3. 添加 xChanged、yChanged 和 alwaysOnTopChanged 信号连接以自动触发状态 更新 4. 移除冗余的手动 sendConfigurePosition 和 sendConfigureStacking 调用 5. 为不完整的 set_attention 功能添加警告日志 6. 移除管理器生命周期的不必要调试日志 7. 重新排序头文件包含以获得更好的组织结构 8. 简化 Helper::instance() 访问的空值检查 Influence: 1. 验证移动窗口时 Wine 窗口位置同步仍能正确工作 2. 测试 z-order 操作,包括 topmost、notopmost、bottom 和 insert_after 3. 验证 toplevel 已控制/已绑定错误处理仍能正确触发 4. 测试窗口控制注册和移除生命周期 5. 验证 Wine 应用程序窗口管理行为无回归 6. 检查触发 attention 状态时是否正确记录警告
1. Add assertion in SurfaceWrapper destructor to ensure markWrapperToRemoved is called before destruction 2. Hide QObject::deleteLater method in SurfaceWrapper to prevent direct deletion 3. Update SurfaceProxy to use markWrapperToRemoved instead of deleteLater 4. Remove redundant QObject::destroyed signal handlers in WineWindowManagement and WineWindowState that were workarounds for improper cleanup This change enforces a strict cleanup protocol for SurfaceWrapper objects, preventing dangling pointers and ensuring proper lifecycle management through a single controlled path Influence: 1. Verify Wine window creation and destruction works correctly without crashes 2. Test rapid window open/close cycles to ensure no memory leaks or dangling pointers 3. Verify assertion is not triggered during normal application usage 4. Test surface proxy replacement scenarios 5. Verify window state management still functions correctly after wrapper cleanup refactor: 强制通过 markWrapperToRemoved 清理 SurfaceWrapper 1. 在 SurfaceWrapper 析构函数中添加断言,确保在销毁前调用了 markWrapperToRemoved 2. 在 SurfaceWrapper 中隐藏 QObject::deleteLater 方法,防止直接删除 3. 更新 SurfaceProxy 使用 markWrapperToRemoved 替代 deleteLater 4. 移除 WineWindowManagement 和 WineWindowState 中冗余的 QObject::destroyed 信号处理器,这些是针对不当清理的变通方案 此更改强制 SurfaceWrapper 对象遵循严格的清理协议,防止悬空指针并通过单一 受控路径确保正确的生命周期管理 Influence: 1. 验证 Wine 窗口创建和销毁正常工作且无崩溃 2. 测试快速窗口打开/关闭循环,确保没有内存泄漏或悬空指针 3. 验证正常应用程序使用期间不会触发断言 4. 测试 surface 代理替换场景 5. 验证 wrapper 清理后窗口状态管理仍然正常工作
1. Remove m_alive boolean member variable from WineWindowControl and WineWindowState classes 2. Replace m_alive checks with m_wrapper null checks in all guard conditions 3. Remove applyHwndTop fallback calls in restack method when sibling validation fails 4. Simplify invalidation handling by relying on wrapper state instead of separate flag The m_alive flag was redundant because when aboutToBeInvalidated is emitted, the handler already removes the object from the manager and clears the manager pointer. Checking m_wrapper is sufficient since it becomes invalid when the surface is destroyed. This eliminates potential race conditions from maintaining separate state and simplifies the codebase. Influence: 1. Test window position changes after surface invalidation 2. Verify restack operations with valid and invalid sibling windows 3. Test unminimize functionality on invalidated windows 4. Verify activate requests are properly denied for invalidated surfaces 5. Test attention state changes after surface destruction 6. Verify no crashes or undefined behavior when operations are called on invalidated windows refactor: 移除冗余的 m_alive 标志 1. 从 WineWindowControl 和 WineWindowState 类中移除 m_alive 布尔成员变量 2. 在所有守卫条件中将 m_alive 检查替换为 m_wrapper 空指针检查 3. 当兄弟窗口验证失败时,移除 restack 方法中的 applyHwndTop 回退调用 4. 通过依赖 wrapper 状态而非单独标志来简化失效处理 m_alive 标志是冗余的,因为当发出 aboutToBeInvalidated 信号时,处理程序已 经将对象从管理器中移除并清空管理器指针。检查 m_wrapper 就足够了,因为当 surface 被销毁时它会变为无效。这消除了维护单独状态可能导致的竞态条件,并 简化了代码库。 Influence: 1. 测试 surface 失效后的窗口位置更改 2. 验证使用有效和无效兄弟窗口的 restack 操作 3. 测试对已失效窗口的取消最小化功能 4. 验证对已失效 surface 的激活请求被正确拒绝 5. 测试 surface 销毁后的注意力状态更改 6. 验证对已失效窗口调用操作时不会出现崩溃或未定义行为
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: wineee The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
1 similar comment
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: wineee The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
When SurfaceProxy is destroyed as part of QObject parent-child teardown, its child proxy SurfaceWrapper could be deleted via QObject::deleteChildren() without going through markWrapperToRemoved(), triggering the destructor assert in SurfaceWrapper. Add SurfaceProxy::~SurfaceProxy() and explicitly call markWrapperToRemoved() for m_proxySurface before QObject cascaded child deletion runs. This keeps the original invariant intact while supporting parent-driven destruction paths.
|
Archlinux的ci有问题,不是本次引入,先合入了 |
Summary by Sourcery
Introduce Wine-specific Wayland protocol modules for window state and window management, integrate them into the shell initialization flow, and tighten surface lifetime handling.
New Features:
Enhancements: