Skip to content

feat: Add support for modifying the plugin popup cursor shape via the…#424

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
yixinshark:feat-addCursorShape
Mar 3, 2026
Merged

feat: Add support for modifying the plugin popup cursor shape via the…#424
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
yixinshark:feat-addCursorShape

Conversation

@yixinshark
Copy link
Contributor

@yixinshark yixinshark commented Feb 5, 2026

… protocol.

add support in plugin-manager-v1.xml

Log: Add support for modifying the plugin popup cursor shape via the protocol.

Summary by Sourcery

Add support for changing the plugin popup cursor shape via the Wayland plugin manager protocol and integrate it with widget event handling.

New Features:

  • Allow plugin popups to request cursor shape changes through the Wayland plugin manager protocol.

Enhancements:

  • Propagate widget cursor change events to plugin popups so they can notify the compositor of updated cursor shapes.

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 5, 2026

Reviewer's Guide

Adds Wayland protocol and plumbing to allow plugins to request cursor shape changes for popup widgets, wiring widget cursor changes through PluginPopup to the plugin-manager-v1 set_cursor request.

Sequence diagram for plugin popup cursor shape change flow

sequenceDiagram
    actor User
    participant PopupWidget
    participant EventFilter
    participant PluginPopup
    participant PluginPopupSurface
    participant PluginManagerV1
    participant WaylandCompositor

    User->>PopupWidget: Move pointer over popup
    PopupWidget->>EventFilter: QEvent::CursorChange
    EventFilter->>EventFilter: handleCursorChange(widget)
    EventFilter->>PluginPopup: requestSetCursor(cursorShape)
    PluginPopup->>PluginPopupSurface: signal requestSetCursor(cursorShape)
    PluginPopupSurface->>PluginPopupSurface: set_cursor(cursorShape)
    PluginPopupSurface->>PluginManagerV1: request set_cursor(cursor_shape)
    PluginManagerV1->>WaylandCompositor: set_cursor(cursor_shape)
    WaylandCompositor-->>User: Updated cursor shape
Loading

Class diagram for updated PluginPopup and EventFilter cursor handling

classDiagram
    class QObject
    class QWidget
    class QWindow
    class QEvent
    class QHelpEvent
    class QTimer

    class EventFilter {
        +bool eventFilter(QObject watched, QEvent event)
        -void updateToolTipPosition(QPoint globalPos)
        -void handleCursorChange(QWidget widget)
    }

    class PluginPopup {
        -QWindow window
        +int x()
        +int y()
        +void xChanged()
        +void yChanged()
        +void pluginPosChanged(QPoint point)
        +void requestSetCursor(int cursorShape)
        -PluginPopup(QWindow window)
        +static PluginPopup getWithoutCreating(QWindow window)
    }

    class PluginPopupSurface {
        -PluginManagerIntegration manager
        -QtWaylandClientShellSurface shellSurface
        -PluginPopup popup
        -QTimer m_dirtyTimer
        +PluginPopupSurface(PluginManagerIntegration manager, QtWaylandClientShellSurface shellSurface, PluginPopup popup)
        +~PluginPopupSurface()
        -void set_position(int x, int y)
        -void set_cursor(int cursorShape)
    }

    QObject <|-- EventFilter
    QObject <|-- PluginPopup
    QWidget <|-- PopupWidget
    QWindow <.. PluginPopup
    PluginPopupSurface o-- PluginPopup
    PluginPopupSurface o-- QTimer

    EventFilter ..> QWidget : handleCursorChange
    EventFilter ..> PluginPopup : getWithoutCreating
    EventFilter ..> PluginPopup : requestSetCursor
    PluginPopupSurface ..> PluginPopup : requestSetCursor signal
    PluginPopupSurface ..> QTimer : timeout connection
Loading

File-Level Changes

Change Details Files
Forward widget cursor shape changes from the popup widget to the plugin popup abstraction.
  • Extend the EventFilter to handle QEvent::CursorChange in addition to tooltip events
  • On cursor change, obtain the QWidget from the watched object, resolve its window handle, and fetch the associated PluginPopup via Plugin::PluginPopup::getWithoutCreating
  • Emit a new requestSetCursor(int cursorShape) signal on the PluginPopup with the current widget cursor shape
src/loader/widgetplugin.cpp
src/tray-wayland-integration/plugin.h
Extend the Wayland plugin-manager protocol and surface integration to support cursor shape updates requested by PluginPopup.
  • Add a set_cursor request with an int cursor_shape argument to plugin-manager-v1.xml, documenting that it follows Qt::CursorShape enum values
  • Add a requestSetCursor(int) signal to PluginPopup in the Wayland tray plugin interface
  • In PluginPopupSurface, connect the PluginPopup::requestSetCursor signal to the Wayland surface set_cursor request so cursor changes are propagated to the compositor
src/protocol/plugin-manager-v1.xml
src/tray-wayland-integration/pluginsurface.cpp
src/tray-wayland-integration/plugin.h

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The handleCursorChange path assumes any QEvent::CursorChange should be forwarded; consider validating that the cursor shape actually changed from the last sent value to avoid spamming set_cursor requests during rapid cursor updates.
  • Since the protocol now relies on integer values matching Qt::CursorShape, it may be safer to introduce an explicit mapping/validation layer (e.g. a small switch or helper) rather than sending static_cast<int>(cursorShape) directly, to guard against enum changes or unexpected values.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `handleCursorChange` path assumes any `QEvent::CursorChange` should be forwarded; consider validating that the cursor shape actually changed from the last sent value to avoid spamming `set_cursor` requests during rapid cursor updates.
- Since the protocol now relies on integer values matching `Qt::CursorShape`, it may be safer to introduce an explicit mapping/validation layer (e.g. a small switch or helper) rather than sending `static_cast<int>(cursorShape)` directly, to guard against enum changes or unexpected values.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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-bot
Copy link

deepin-bot bot commented Feb 5, 2026

TAG Bot

New tag: 2.0.25
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #426

@deepin-bot
Copy link

deepin-bot bot commented Feb 27, 2026

TAG Bot

New tag: 2.0.26
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #431

… protocol.

add support in plugin-manager-v1.xml

Log: Add support for modifying the plugin popup cursor shape via the protocol.
@yixinshark yixinshark force-pushed the feat-addCursorShape branch from ceb6fcf to 396fd27 Compare March 3, 2026 02:40
@deepin-ci-robot
Copy link

deepin pr auto review

这段代码实现了一个在 Wayland 环境下,当 Widget 鼠标光标形状发生变化时,通过 Wayland 协议同步更新到插件弹窗(PluginPopup)的功能。整体逻辑是通顺的,但在语法逻辑、代码质量、性能和安全性方面有如下改进意见:

1. 语法逻辑与代码质量

  • Q_UNUSED 的移除

    • 现状:移除了 Q_UNUSED(watched),并在 QEvent::CursorChange 分支中使用了 watched
    • 意见:这是正确的修改,消除了未使用变量的警告,同时复用了参数。
  • qobject_cast 的使用

    • 现状auto widget = qobject_cast<QWidget*>(watched);
    • 意见:用法正确。在 Qt 中处理事件过滤器时,这是将 QObject* 转换为具体子类指针的安全方式。
  • 函数调用与空指针检查

    • 现状handleCursorChange 中检查了 widgetwidget->window() 以及 widget->window()->windowHandle()
    • 意见:逻辑严密。如果在事件过滤时对象尚未完全初始化或已被销毁,这些检查能有效防止崩溃。
  • 类型转换

    • 现状Qt::CursorShape cursorShape = widget->cursor().shape();static_cast<int>(cursorShape)
    • 意见:逻辑正确。将枚举转为整数传递给 Wayland 协议是合理的,因为 Wayland XML 协议定义中 cursor_shapeint 类型。

2. 代码性能

  • 事件过滤器的频率

    • 分析eventFilter 会在应用程序的每一个事件循环中被调用(针对安装了过滤器的对象)。QEvent::CursorChange 只有在光标形状实际改变时才会触发,因此性能开销较小。
    • 建议:当前实现是按需处理,性能良好,无需优化。
  • 信号槽连接

    • 分析:在 PluginPopupSurface 构造函数中使用了 Lambda 表达式连接 requestSetCursor 信号。
    • 建议:这是现代 C++ 和 Qt 的推荐写法,性能开销极小,可读性好。

3. 代码安全

  • 协议类型安全(主要隐患)

    • 现状:XML 协议定义中 cursor_shapeint,注释提到 "follows Qt::CursorShape enum values"。
    • 风险:这造成了 Wayland 协议与 Qt 实现的强耦合。如果 Qt 的 Qt::CursorShape 枚举值在未来版本发生变化(例如插入新值),或者 Compositor 端(服务端)不是基于 Qt 实现的,可能会导致两端对 int 值的理解不一致,从而显示错误的光标或引发未定义行为。
    • 改进建议
      1. 协议层面:如果可能,Wayland 协议最好定义自己的枚举类型(如 enum { cursor_default, cursor_pointer, ... }),而不是直接透传 Qt 的 int 值。这样可以解耦协议与具体 UI 框架。
      2. 代码层面:在发送请求前(handleCursorChangeset_cursor 调用处),可以添加断言或日志,确保 cursorShape 在预期的有效范围内(例如 0Qt::LastCursor 之间),防止发送非法值。
  • PluginPopup 对象生命周期

    • 现状Plugin::PluginPopup::getWithoutCreating(windowHandle)
    • 分析:函数名 getWithoutCreating 暗示如果对象不存在则返回空指针。代码中通过 if (auto pluginPopup = ...) 进行了判空处理,这是安全的。
    • 建议:确认 getWithoutCreating 的实现确实是线程安全的(如果涉及多线程),或者在单线程 GUI 线程中运行(通常 Qt GUI 如此),则无需额外担心。
  • Lambda 捕获

    • 现状QMetaObject::invokeMethodconnect 中使用了 [this] 捕获。
    • 建议:确保 EventFilterPluginPopupSurface 的生命周期长于它们所触发的异步操作。由于它们通常是依附于窗口生命周期的对象,这通常是安全的。

4. 详细代码改进建议

针对 handleCursorChange 函数,建议增加防御性编程逻辑,确保传递的枚举值是合法的:

    void handleCursorChange(QWidget *widget)
    {
        if (!widget || !widget->window() || !widget->window()->windowHandle())
            return;

        auto windowHandle = widget->window()->windowHandle();
        if (auto pluginPopup = Plugin::PluginPopup::getWithoutCreating(windowHandle)) {
            Qt::CursorShape cursorShape = widget->cursor().shape();
            
            // 安全性改进:检查枚举值是否在 Qt 定义的合法范围内
            // 假设 Qt::LastCursor 是最后一个枚举值
            if (cursorShape < 0 || cursorShape > Qt::LastCursor) {
                qWarning() << "Invalid cursor shape detected:" << static_cast<int>(cursorShape);
                return; // 或者设置为一个默认值,如 Qt::ArrowCursor
            }

            Q_EMIT pluginPopup->requestSetCursor(static_cast<int>(cursorShape));
        }
    }

总结

这段代码实现了功能需求,逻辑清晰,Qt 风格运用得当。
主要改进点在于加强协议与实现的解耦以及边界值的检查。虽然目前直接传递 Qt::CursorShapeint 值在纯 Qt 环境下能工作,但从软件工程角度看,定义独立的协议枚举或增加数值校验能提高系统的健壮性和兼容性。

@yixinshark
Copy link
Contributor Author

/forcemerge

@deepin-bot
Copy link

deepin-bot bot commented Mar 3, 2026

This pr force merged! (status: blocked)

@deepin-bot deepin-bot bot merged commit e82424b into linuxdeepin:master Mar 3, 2026
9 of 11 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.

3 participants