Skip to content

Conversation

@BLumia
Copy link
Member

@BLumia BLumia commented Dec 25, 2025

支持在 wayland 环境下为 Xembed 支持注册 selectionowner 并暴露相关托盘到 dbus 接口上。

Summary by Sourcery

Add a Wayland-capable XEmbed tray selection manager and expose embedded tray icons over a new DBus TrayManager1 interface.

New Features:

  • Introduce FdoSelectionManager to own the FDO/XEmbed system tray selection and manage tray icons via XDamage events.
  • Expose embedded X11 tray icons through a new org.deepin.dde.TrayManager1 DBus interface with registration, change notifications, and metadata access.
  • Automatically register the FDO selection manager when running on non-X11 platforms where an X display is available.

Enhancements:

  • Refine the application-tray plugin build configuration to explicitly list tray sources, generate a DBus adaptor, and link against KF6WindowSystem.
  • Update the project DTL version to 2.0.99 and extend X11 dependencies to include xcb-damage for tray damage tracking.

Build:

  • Link application-tray plugin against KF6::WindowSystem and add xcb-damage to the X11 pkg-config modules.
  • Generate the TrayManager1 DBus adaptor source from the org.deepin.dde.TrayManager1.xml definition and include it in the tray plugin build.

@BLumia BLumia requested a review from tsic404 December 25, 2025 09:20
@sourcery-ai
Copy link

sourcery-ai bot commented Dec 25, 2025

Reviewer's Guide

Implements a Wayland-compatible XEmbed system tray selection manager by introducing FdoSelectionManager and TrayManager1 DBus service, wiring them into TrayPlugin when not on X11, and updating build configuration and dependencies accordingly.

Sequence diagram for XEmbed tray icon docking via FdoSelectionManager and TrayManager1

sequenceDiagram
    autonumber
    participant TrayPlugin
    participant FdoSelectionManager
    participant KSelectionOwner
    participant X11Server
    participant TrayManager1
    participant DBusSession as DBusSessionBus
    participant ClientTrayApp as XEmbedClient

    TrayPlugin->>TrayPlugin: constructor
    TrayPlugin->>TrayPlugin: registerDBusMetaTypes
    TrayPlugin->>FdoSelectionManager: new FdoSelectionManager(this) when not X11 and XAvaliable

    activate FdoSelectionManager
    FdoSelectionManager->>KSelectionOwner: new KSelectionOwner(_NET_SYSTEM_TRAY,...)
    FdoSelectionManager->>FdoSelectionManager: QTimer singleShot init

    FdoSelectionManager->>X11Server: xcb_damage_query_version
    FdoSelectionManager->>QGuiApplication: installNativeEventFilter
    FdoSelectionManager->>KSelectionOwner: claim(false)

    KSelectionOwner-->>FdoSelectionManager: claimedOwnership()
    FdoSelectionManager->>FdoSelectionManager: onClaimedOwnership
    FdoSelectionManager->>FdoSelectionManager: initTrayManager
    FdoSelectionManager->>TrayManager1: new TrayManager1(this)
    FdoSelectionManager->>DBusSession: registerObject /org/deepin/dde/TrayManager1
    FdoSelectionManager->>DBusSession: registerService org.deepin.dde.TrayManager1

    FdoSelectionManager->>X11Server: setSystemTrayVisual property

    XEmbedClient->>X11Server: send _NET_SYSTEM_TRAY_OPCODE DOCK(winId)
    X11Server-->>FdoSelectionManager: XCB_CLIENT_MESSAGE via nativeEventFilter

    FdoSelectionManager->>FdoSelectionManager: dock(winId)
    FdoSelectionManager->>FdoSelectionManager: addDamageWatch(winId)
    FdoSelectionManager->>TrayManager1: registerIcon(winId)

    TrayManager1-->>DBusSession: signal Added(winId)
    DBusSession-->>Clients: TrayManager1 Added(winId)
Loading

Class diagram for new Wayland tray selection manager integration

classDiagram
    direction LR

    class TrayPlugin {
        +TrayPlugin(QObject *parent)
        +~TrayPlugin()
        -QHash~QString, QWidget*~ m_widget
        -QHash~QString, QWidget*~ m_tooltip
        -PluginProxyInterface* m_proyInter
        -FdoSelectionManager* m_selectionManager
    }

    class FdoSelectionManager {
        +FdoSelectionManager(QObject *parent)
        +~FdoSelectionManager()
        +bool nativeEventFilter(QByteArray eventType, void* message, qintptr* result)
        -void init()
        -bool addDamageWatch(xcb_window_t client)
        -void dock(xcb_window_t embed_win)
        -void undock(xcb_window_t client)
        -void setSystemTrayVisual()
        -void initTrayManager()
        -void onClaimedOwnership()
        -void onFailedToClaimOwnership()
        -void onLostOwnership()
        -TrayManager1* m_trayManager
        -uint8_t m_damageEventBase
        -QHash~xcb_window_t, u_int32_t~ m_damageWatches
        -KSelectionOwner* m_selectionOwner
    }

    class TrayManager1 {
        +TrayManager1(QObject *parent)
        +~TrayManager1()
        +void registerIcon(xcb_window_t win)
        +void unregisterIcon(xcb_window_t win)
        +void notifyIconChanged(xcb_window_t win)
        +TrayList trayIcons() const
        +bool haveIcon(xcb_window_t win) const
        +bool Manage()
        +QString GetName(uint32_t win)
        +void EnableNotification(uint32_t win, bool enabled)
        +signal void Added(uint32_t id)
        +signal void Removed(uint32_t id)
        +signal void Changed(uint32_t id)
        +signal void Inited()
        -TrayManager1Adaptor* m_adaptor
        -QHash~xcb_window_t, bool~ m_icons
    }

    class TrayManager1Adaptor {
        <<qt_dbus_adaptor>>
    }

    class KSelectionOwner {
    }

    class Util {
        +static Util* instance()
        +xcb_connection_t* getX11Connection()
        +xcb_window_t getRootWindow()
        +xcb_atom_t getAtomFromDisplay(const char* name)
        +xcb_atom_t getAtomByName(const char* name)
    }

    class UniqueCPointer~T~ {
        -CDeleter m_deleter
    }

    class CDeleter {
        +void operator()(T* ptr)
    }

    TrayPlugin --> FdoSelectionManager : owns
    FdoSelectionManager --> TrayManager1 : creates and owns
    FdoSelectionManager --> KSelectionOwner : owns
    FdoSelectionManager --> Util : uses
    FdoSelectionManager --> UniqueCPointer : uses
    TrayManager1 --> TrayManager1Adaptor : owns
    UniqueCPointer --|> std_unique_ptr
    CDeleter --> UniqueCPointer : deleter type
Loading

File-Level Changes

Change Details Files
Wire new FdoSelectionManager into the tray plugin lifecycle to manage XEmbed tray icons when running under non-X11 platforms.
  • Include fdoselectionmanager header and KF6 KWindowSystem in trayplugin.cpp.
  • Instantiate FdoSelectionManager in TrayPlugin constructor when not on X11 but X11 connection is available.
  • Store the FdoSelectionManager instance as a member pointer in TrayPlugin with forward declaration in the header.
plugins/application-tray/trayplugin.cpp
plugins/application-tray/trayplugin.h
Add FdoSelectionManager implementation to own the X11 system tray selection, watch damage events, and forward tray icon lifecycle to TrayManager1 over DBus.
  • Create FdoSelectionManager class that owns a KSelectionOwner for _NET_SYSTEM_TRAY and claims the selection on startup.
  • Install a native XCB event filter to handle system tray client messages, destroy and damage notifications, and call dock/undock or notifyIconChanged accordingly.
  • Integrate XDamage to watch tray window updates and track damage handles in an internal hash map.
  • Set the _NET_SYSTEM_TRAY_VISUAL property on the selection owner window based on a suitable visual from the root screen.
  • Initialize and export a TrayManager1 instance on the session bus at /org/deepin/dde/TrayManager1 with service org.deepin.dde.TrayManager1 when ownership is claimed.
plugins/application-tray/fdoselectionmanager.h
plugins/application-tray/fdoselectionmanager.cpp
plugins/application-tray/c_ptr.h
Introduce TrayManager1 DBus manager for tray icons to expose XEmbed tray state and basic operations.
  • Define TrayManager1 class with a TrayIcons DBus property, Added/Removed/Changed/Inited signals, and DBus methods Manage, GetName, and EnableNotification.
  • Track tray icons in an internal QHash keyed by X11 window ID, with a boolean to control change notifications.
  • Emit DBus signals when icons are registered, unregistered, or changed, and provide helpers to query icon presence and list.
plugins/application-tray/traymanager1.h
plugins/application-tray/traymanager1.cpp
Adjust CMake build configuration to explicitly list tray sources, generate DBus adaptor code for TrayManager1, and add new dependencies.
  • Replace globbing of tray sources with an explicit TRAY_SOURCES list including new FdoSelectionManager, TrayManager1, support headers, and existing tray components.
  • Invoke qt_add_dbus_adaptor to generate the TrayManager1 DBus adaptor from the org.deepin.dde.TrayManager1.xml interface.
  • Add KF6WindowSystem as a required package and link dependency, and extend X11 pkg-config modules to include xcb-damage.
  • Bump DTL_VERSION from 1.99.0 to 2.0.99 in the top-level CMakeLists.txt.
plugins/application-tray/CMakeLists.txt
CMakeLists.txt

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 found 5 issues, and left some high level feedback:

  • In FdoSelectionManager::undock(), the early return condition uses if (m_trayManager->haveIcon(winId)) { return; }, which looks inverted compared to dock(); this prevents unregistering existing icons and likely should be if (!m_trayManager->haveIcon(winId)) { return; }.
  • In fdoselectionmanager.h the hash is declared as QHash<xcb_window_t, u_int32_t> m_damageWatches; – consider using the standard uint32_t type for consistency with the rest of the xcb-related code and platform headers.
  • FdoSelectionManager::init and ownership handlers call qApp->exit(-1) on failures; since this code runs inside a plugin, it may be safer to signal the error back to the host instead of terminating the entire application.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In FdoSelectionManager::undock(), the early return condition uses `if (m_trayManager->haveIcon(winId)) { return; }`, which looks inverted compared to dock(); this prevents unregistering existing icons and likely should be `if (!m_trayManager->haveIcon(winId)) { return; }`.
- In fdoselectionmanager.h the hash is declared as `QHash<xcb_window_t, u_int32_t> m_damageWatches;` – consider using the standard `uint32_t` type for consistency with the rest of the xcb-related code and platform headers.
- FdoSelectionManager::init and ownership handlers call `qApp->exit(-1)` on failures; since this code runs inside a plugin, it may be safer to signal the error back to the host instead of terminating the entire application.

## Individual Comments

### Comment 1
<location> `plugins/application-tray/fdoselectionmanager.cpp:44-47` </location>
<code_context>
+    QTimer::singleShot(0, this, &FdoSelectionManager::init);
+}
+
+FdoSelectionManager::~FdoSelectionManager()
+{
+    qCDebug(SELECTIONMGR) << "closing";
+    m_selectionOwner->release();
+}
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Native event filter is never removed in the destructor.

Since the constructor installs this as a native event filter via `qApp->installNativeEventFilter(this)`, the destructor should also call `qApp->removeNativeEventFilter(this)` before releasing state to avoid dangling event filter callbacks into a destroyed object.
</issue_to_address>

### Comment 2
<location> `plugins/application-tray/fdoselectionmanager.cpp:154-163` </location>
<code_context>
+    return false;
+}
+
+void FdoSelectionManager::dock(xcb_window_t winId)
+{
+    Q_CHECK_PTR(m_trayManager);
+    qCDebug(SELECTIONMGR) << "trying to dock window " << winId;
+
+    if (m_trayManager->haveIcon(winId)) {
+        return;
+    }
+
+    if (addDamageWatch(winId)) {
+        // Register with TrayManager1 if available
+        m_trayManager->registerIcon(winId);
+    }
+}
</code_context>

<issue_to_address>
**issue (bug_risk):** Potential race/use-before-init of m_trayManager in dock/undock paths.

`dock`/`undock` dereference `m_trayManager` unconditionally, but it’s only created in `initTrayManager()` (from `onClaimedOwnership()`). A tray client message can arrive before `claimedOwnership`, so `dock()` may run with `m_trayManager == nullptr`, tripping `Q_CHECK_PTR` in debug or causing UB in release. Please either ensure `m_trayManager` is constructed earlier (e.g. in `init()`) or skip/defer handling until it is initialized.
</issue_to_address>

### Comment 3
<location> `plugins/application-tray/fdoselectionmanager.cpp:169-178` </location>
<code_context>
+    }
+}
+
+void FdoSelectionManager::undock(xcb_window_t winId)
+{
+    Q_CHECK_PTR(m_trayManager);
+    qCDebug(SELECTIONMGR) << "trying to undock window " << winId;
+
+    if (m_trayManager->haveIcon(winId)) {
+        return;
+    }
+    
+    // Unregister from TrayManager1 if available
+    m_trayManager->unregisterIcon(winId);
+    
+    // m_proxies[winId]->deleteLater();
+    // m_proxies.remove(winId);
+}
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Undock logic returns early when an icon exists, preventing proper unregister.

```cpp
if (m_trayManager->haveIcon(winId)) {
    return;
}
// ...
m_trayManager->unregisterIcon(winId);
```

This condition looks reversed: when the icon exists we return and never call `unregisterIcon`, so the icon is never removed. I think this should be:

```cpp
if (!m_trayManager->haveIcon(winId)) {
    return;
}

m_trayManager->unregisterIcon(winId);
```
</issue_to_address>

### Comment 4
<location> `plugins/application-tray/fdoselectionmanager.h:49` </location>
<code_context>
+
+    uint8_t m_damageEventBase;
+
+    QHash<xcb_window_t, u_int32_t> m_damageWatches;
+    // QHash<xcb_window_t, TrayManagerProxy *> m_proxies;
+    KSelectionOwner *m_selectionOwner;
</code_context>

<issue_to_address>
**suggestion:** Use of non‑standard `u_int32_t` type for damage IDs.

`m_damageWatches` is declared as `QHash<xcb_window_t, u_int32_t>`. `u_int32_t` is a non‑standard extension and may not exist on all platforms/compilers. Please switch to a portable type such as `uint32_t` from `<cstdint>` or, if it better reflects the intent, an appropriate XCB damage type like `xcb_damage_direct_t`/`xcb_damage_damage_t`.

Suggested implementation:

```c
    QHash<xcb_window_t, uint32_t> m_damageWatches;

```

To ensure `uint32_t` is available in this header on all platforms, add `#include <cstdint>` (or `<stdint.h>`) in the include section of `fdoselectionmanager.h` if it is not already indirectly included. Place it alongside the other standard-library includes.
</issue_to_address>

### Comment 5
<location> `plugins/application-tray/CMakeLists.txt:11-12` </location>
<code_context>
 find_package(PkgConfig REQUIRED)
 find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED Core Gui Widgets DBus)
 find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core Gui Widget)
+find_package(KF6WindowSystem 6.6 REQUIRED) # for x11 tray section owner

-pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11 xcb xcb-image xcb-composite xcb-xfixes xcb-util xcb-shape xtst xcb-xtest xcb-res xcb-ewmh)
</code_context>

<issue_to_address>
**suggestion (typo):** Typo and capitalization in inline comment: use "X11 tray selection owner".

In `# for x11 tray section owner`, "section" should be "selection" (per the X11 "selection owner" concept), and "x11" should be capitalized to "X11": `# for X11 tray selection owner`.

```suggestion
find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core Gui Widget)
find_package(KF6WindowSystem 6.6 REQUIRED) # for X11 tray selection owner
```
</issue_to_address>

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.

Comment on lines +44 to +47
FdoSelectionManager::~FdoSelectionManager()
{
qCDebug(SELECTIONMGR) << "closing";
m_selectionOwner->release();
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Native event filter is never removed in the destructor.

Since the constructor installs this as a native event filter via qApp->installNativeEventFilter(this), the destructor should also call qApp->removeNativeEventFilter(this) before releasing state to avoid dangling event filter callbacks into a destroyed object.

Comment on lines +154 to +167
void FdoSelectionManager::dock(xcb_window_t winId)
{
Q_CHECK_PTR(m_trayManager);
qCDebug(SELECTIONMGR) << "trying to dock window " << winId;

if (m_trayManager->haveIcon(winId)) {
return;
}

if (addDamageWatch(winId)) {
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Potential race/use-before-init of m_trayManager in dock/undock paths.

dock/undock dereference m_trayManager unconditionally, but it’s only created in initTrayManager() (from onClaimedOwnership()). A tray client message can arrive before claimedOwnership, so dock() may run with m_trayManager == nullptr, tripping Q_CHECK_PTR in debug or causing UB in release. Please either ensure m_trayManager is constructed earlier (e.g. in init()) or skip/defer handling until it is initialized.

Comment on lines +169 to +182
void FdoSelectionManager::undock(xcb_window_t winId)
{
Q_CHECK_PTR(m_trayManager);
qCDebug(SELECTIONMGR) << "trying to undock window " << winId;

if (m_trayManager->haveIcon(winId)) {
return;
}

// Unregister from TrayManager1 if available
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Undock logic returns early when an icon exists, preventing proper unregister.

if (m_trayManager->haveIcon(winId)) {
    return;
}
// ...
m_trayManager->unregisterIcon(winId);

This condition looks reversed: when the icon exists we return and never call unregisterIcon, so the icon is never removed. I think this should be:

if (!m_trayManager->haveIcon(winId)) {
    return;
}

m_trayManager->unregisterIcon(winId);


uint8_t m_damageEventBase;

QHash<xcb_window_t, u_int32_t> m_damageWatches;
Copy link

Choose a reason for hiding this comment

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

suggestion: Use of non‑standard u_int32_t type for damage IDs.

m_damageWatches is declared as QHash<xcb_window_t, u_int32_t>. u_int32_t is a non‑standard extension and may not exist on all platforms/compilers. Please switch to a portable type such as uint32_t from <cstdint> or, if it better reflects the intent, an appropriate XCB damage type like xcb_damage_direct_t/xcb_damage_damage_t.

Suggested implementation:

    QHash<xcb_window_t, uint32_t> m_damageWatches;

To ensure uint32_t is available in this header on all platforms, add #include <cstdint> (or <stdint.h>) in the include section of fdoselectionmanager.h if it is not already indirectly included. Place it alongside the other standard-library includes.

Comment on lines 11 to 12
find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core Gui Widget)
find_package(KF6WindowSystem 6.6 REQUIRED) # for x11 tray section owner
Copy link

Choose a reason for hiding this comment

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

suggestion (typo): Typo and capitalization in inline comment: use "X11 tray selection owner".

In # for x11 tray section owner, "section" should be "selection" (per the X11 "selection owner" concept), and "x11" should be capitalized to "X11": # for X11 tray selection owner.

Suggested change
find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core Gui Widget)
find_package(KF6WindowSystem 6.6 REQUIRED) # for x11 tray section owner
find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core Gui Widget)
find_package(KF6WindowSystem 6.6 REQUIRED) # for X11 tray selection owner

void FdoSelectionManager::onLostOwnership()
{
qCWarning(SELECTIONMGR) << "lost ownership of Systray Manager";
qApp->exit(-1);
Copy link
Contributor

Choose a reason for hiding this comment

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

selection 并非独占。

Copy link
Member Author

Choose a reason for hiding this comment

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

已修改为强制claim,保留了此信号的日志输出以防万一。退出行为已删除

{
// Create and register the TrayManager1 DBus interface
if (!m_trayManager) {
m_trayManager = new TrayManager1(this);
Copy link
Contributor

Choose a reason for hiding this comment

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

Manage() 调用对接到 claim(true)

Copy link
Member Author

Choose a reason for hiding this comment

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

done

registerDBusToolTipMetaType();
registerDBusImageListMetaType();

if (!KWindowSystem::isPlatformX11() && UTIL->isXAvaliable()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

不能用 qpa,使用 XDG_SESSION_TYPE 判断

Copy link
Member Author

Choose a reason for hiding this comment

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

done

QHash<QString, QWidget*> m_widget;
QHash<QString, QWidget*> m_tooltip;
PluginProxyInterface *m_proyInter;
FdoSelectionManager *m_selectionManager = nullptr;
Copy link
Contributor

Choose a reason for hiding this comment

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

FdoSelectionManager 属于 Xembed 的实现,不应该在 TrayPlugin 这个抽象类上。

Copy link
Member Author

Choose a reason for hiding this comment

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

done

@deepin-bot
Copy link

deepin-bot bot commented Dec 25, 2025

TAG Bot

New tag: 2.0.20
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #407

xcb_damage_query_version_unchecked(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
} else {
// no XDamage means
qCCritical(SELECTIONMGR) << "could not load damage extension.";
Copy link
Member Author

Choose a reason for hiding this comment

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

这里该退出么?

Copy link
Contributor

Choose a reason for hiding this comment

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

走到这了,那就是 X server 缺少必要的扩展。业务逻辑依赖这些扩展,可以退出。

Copy link
Member Author

Choose a reason for hiding this comment

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

done

{
qApp->installNativeEventFilter(this);

m_trayManager->Manage();
Copy link
Contributor

Choose a reason for hiding this comment

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

Dbus 的注册是下面执行的,那么此处的调用是不是应该延后?

Copy link
Member Author

Choose a reason for hiding this comment

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

done

xcb_damage_query_version_unchecked(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
} else {
// no XDamage means
qCCritical(SELECTIONMGR) << "could not load damage extension.";
Copy link
Contributor

Choose a reason for hiding this comment

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

走到这了,那就是 X server 缺少必要的扩展。业务逻辑依赖这些扩展,可以退出。

@BLumia BLumia force-pushed the xembed-tray branch 2 times, most recently from 1ea5c5e to c259057 Compare December 26, 2025 08:11
tsic404
tsic404 previously approved these changes Dec 29, 2025
支持在 wayland 环境下为 Xembed 支持注册 selectionowner 并暴露相关
托盘到 dbus 接口上。

Log:
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia

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 similar comment
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia

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-ci-robot
Copy link

deepin pr auto review

我来对这个 diff 进行详细的代码审查:

  1. 版本更新和依赖变更:
  • DTL_VERSION 从 1.99.0 升级到 2.0.99,这是一个主版本升级,需要特别注意兼容性
  • 新增了 libkf6windowsystem-dev 依赖,表明项目开始使用 KDE Framework 6 的窗口系统组件
  1. 许可证文件:
  • 新增了 LGPL-2.1-or-later.txt 许可证文件,这是正确的做法,确保代码许可的合规性
  1. 构建系统变更:
  • 在 application-tray 插件的 CMakeLists.txt 中:
    • 添加了 KF6WindowSystem 依赖
    • 增加了 xcb-damage 依赖
    • 显式列出了所有源文件,替代了之前的 GLOB 方式,这是更好的实践
  1. 新增的核心组件:
  • FdoSelectionManager:实现了 freedesktop.org 系统托盘协议
  • TrayManager1:实现了 DDE 特有的托盘管理 DBus 接口
  • c_ptr.h:提供了 C 风格指针的 RAII 包装器
  1. 代码质量分析:

优点:

  1. 代码结构清晰,职责分离明确
  2. 使用了 RAII 和智能指针管理资源
  3. 实现了完整的错误处理
  4. 日志系统使用规范

需要改进的地方:

  1. FdoSelectionManager::undock() 方法中存在逻辑错误:
if (m_trayManager->haveIcon(winId)) {
    return;  // 这里应该用 !m_trayManager->haveIcon(winId)
}
  1. 在 FdoSelectionManager::nativeEventFilter() 中,有被注释掉的代码,应该清理或添加 TODO 注释说明原因

  2. TrayManager1::registerIcon() 中的日志注释不完整:

qCDebug(TRAYMGR) << "Icon registered:" << win ;//<< "name:" << proxy->name();
  1. XembedProtocol 构造函数中的环境检查可以更健壮:
if ((qgetenv("XDG_SESSION_TYPE") == "wayland") && UTIL->isXAvaliable()) {

建议使用 QString::compare() 进行更严格的比较

  1. 缺少对 KSelectionOwner 失败的恢复机制
  1. 性能考虑:
  • FdoSelectionManager 中的 damage 事件处理是高效的
  • 使用了哈希表来跟踪托盘图标,查找效率高
  • 建议在 TrayManager1 中考虑使用 QHash::reserve() 预分配空间
  1. 安全性:
  • X11 相关的操作都进行了错误检查
  • DBus 接口实现了基本的参数验证
  • 建议在处理 X11 窗口 ID 时添加更多的有效性检查
  1. 建议的改进:
  1. 在 FdoSelectionManager 中添加对 X11 连接断开的处理
  2. 为 DBus 接口添加更详细的文档
  3. 考虑添加单元测试
  4. 在关键操作处添加更多的日志记录
  5. 考虑使用 QPointer 替代原始指针以防止悬空指针

总体而言,这是一个质量较高的代码提交,实现了重要的功能更新,但还有一些细节需要完善。建议在合并前修复上述问题,并添加适当的测试用例。

@BLumia BLumia merged commit 67b9919 into linuxdeepin:master Dec 29, 2025
9 checks passed
@BLumia BLumia deleted the xembed-tray branch December 29, 2025 03:12
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