Skip to content

Conversation

@wjyrich
Copy link
Contributor

@wjyrich wjyrich commented Oct 27, 2025

  1. Added ApplicationManager D-Bus integration for more accurate window identification
  2. Implemented pidfd-based process identification to get desktop IDs from ApplicationManager
  3. Removed desktopfileID from X11Window identity to avoid circular dependencies
  4. Reordered window tracking and signal emission to ensure proper initialization
  5. Added syscall and D-Bus dependencies for process identification

feat: 增强窗口识别功能,集成 ApplicationManager

  1. 添加 ApplicationManager D-Bus 集成以实现更精确的窗口识别
  2. 实现基于 pidfd 的进程识别,从 ApplicationManager 获取桌面 ID
  3. 从 X11Window 身份信息中移除 desktopfileID 以避免循环依赖
  4. 重新排序窗口跟踪和信号发射以确保正确初始化
  5. 添加系统调用和 D-Bus 依赖以支持进程识别

Summary by Sourcery

Use pidfd and ApplicationManager D-Bus integration to enhance window identification accuracy and adjust window tracking initialization sequence

New Features:

  • Integrate ApplicationManager D-Bus service for window identification via pidfd

Enhancements:

  • Implement pidfd-based process identification to retrieve desktop IDs
  • Remove desktopfileID from X11Window identity to avoid circular dependencies
  • Reorder window tracking and signal emission sequence for proper initialization
  • Add syscall and D-Bus dependencies for process identification

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 27, 2025

Reviewer's Guide

This PR integrates ApplicationManager for pidfd-based window identification in the TaskManager, refactors X11Window identity to remove circular desktopfileID dependencies, reorders window tracking signal emission for proper initialization, and updates dependencies for syscalls and D-Bus usage.

Sequence diagram for window identification with ApplicationManager D-Bus integration

sequenceDiagram
    participant TaskManager
    participant ApplicationManager
    participant Model
    TaskManager->>ApplicationManager: Identify(QDBusUnixFileDescriptor(pidfd))
    ApplicationManager-->>TaskManager: desktopId
    TaskManager->>Model: match(desktopId)
    Model-->>TaskManager: matchRes
    Note over TaskManager: If matchRes is valid, use it
    TaskManager->>Model: match(identifies.value(0))
    Model-->>TaskManager: fallbackRes
Loading

Entity relationship diagram for window and desktop ID matching

erDiagram
    WINDOW {
        pid int
        wm_class string
    }
    APPLICATION_MANAGER {
        desktop_id string
        pidfd int
    }
    MODEL {
        desktop_id string
    }
    WINDOW ||--o{ APPLICATION_MANAGER: "identified by pidfd"
    APPLICATION_MANAGER ||--o{ MODEL: "desktop_id used for matching"
Loading

Class diagram for updated X11Window identity and TaskManager integration

classDiagram
    class X11Window {
        +QStringList identity()
        -m_identity: QStringList
        -m_windowID: xcb_window_t
        -pid(): int
        -getAppItem() [removed desktopfileID usage]
    }
    class TaskManager {
        +init()
        -model: Model
        -roleNames: QHash
        -window identification logic (uses ApplicationManager)
    }
    X11Window <.. TaskManager: uses identity()
    class ApplicationManager {
        +Identify(QDBusUnixFileDescriptor)
    }
    TaskManager ..> ApplicationManager: D-Bus call
Loading

File-Level Changes

Change Details Files
Integrate ApplicationManager D-Bus and pidfd for enhanced window identification
  • Added DDBusSender, unistd, and syscall includes
  • Retrieve window PID and check ApplicationManager service availability
  • Open pidfd with SYS_pidfd_open and send Identify call via DDBusSender
  • Process reply arguments, extract desktop ID, and match against model
  • Handle Identify failures with debug logging
panels/dock/taskmanager/taskmanager.cpp
Remove desktopfileID from X11Window identity to avoid circular dependencies
  • Deleted logic appending desktopfileID from getAppItem()
  • Retained WMClass and PID-based identity only
panels/dock/taskmanager/x11window.cpp
Reorder windowAdded signal emission after tracking initialization
  • Moved Q_EMIT windowAdded call to after trackWindow invocation
panels/dock/taskmanager/x11windowmonitor.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

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 there - I've reviewed your changes - here's some feedback:

  • Wrap the pidfd_open syscall and ApplicationManager D-Bus logic in compile-time guards (e.g. check SYS_pidfd_open availability) to maintain portability on platforms that don’t support pidfd.
  • The synchronous D-Bus Identify call in init() could block the main thread—consider dispatching it asynchronously or moving it off the UI thread and caching results to avoid UI stutters.
  • Avoid recreating DDBusSender on every identify call by reusing a single sender instance or lazily initializing it for better performance.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Wrap the pidfd_open syscall and ApplicationManager D-Bus logic in compile-time guards (e.g. check SYS_pidfd_open availability) to maintain portability on platforms that don’t support pidfd.
- The synchronous D-Bus Identify call in init() could block the main thread—consider dispatching it asynchronously or moving it off the UI thread and caching results to avoid UI stutters.
- Avoid recreating DDBusSender on every identify call by reusing a single sender instance or lazily initializing it for better performance.

## Individual Comments

### Comment 1
<location> `panels/dock/taskmanager/taskmanager.cpp:152-162` </location>
<code_context>
+                        
+                        if (res.isValid()) {
+                            auto reply = res.reply();
+                            QList<QVariant> data = reply.arguments();
+                            QString desktopId = data.first().toString();
+                            
+                            if (!desktopId.isEmpty()) {
</code_context>

<issue_to_address>
**suggestion:** Check that 'data' is not empty before accessing 'first()'.

Consider adding a check to ensure 'data' is not empty before calling 'first()' to prevent a potential exception.

```suggestion
                            QList<QVariant> data = reply.arguments();
                            QString desktopId;
                            if (!data.isEmpty()) {
                                desktopId = data.first().toString();
                            }

                            if (!desktopId.isEmpty()) {
                                // 使用获取到的 desktop ID 进行匹配
                                auto matchRes = model->match(model->index(0, 0), roleNames.key(MODEL_DESKTOPID), desktopId, 1, Qt::MatchFixedString | Qt::MatchWrap).value(0);
                                if (matchRes.isValid()) {
                                    qCDebug(taskManagerLog) << "matched by AM desktop ID:" << desktopId << matchRes;
                                    return matchRes;
                                }
                            }
```
</issue_to_address>

### Comment 2
<location> `panels/dock/taskmanager/taskmanager.cpp:135` </location>
<code_context>
                 }
             }

+            pid_t windowPid = identifies.last().toInt();
+            if (windowPid > 0) {
+                bool amIsAvailable = QDBusConnection::sessionBus().interface()->isServiceRegistered("org.desktopspec.ApplicationManager1");
</code_context>

<issue_to_address>
**issue (complexity):** Consider refactoring the deeply nested logic into a guard-clause-based helper function to simplify and flatten the code.

Here’s one way to collapse that deep nesting into a small, testable helper with guard-clauses and Qt’s higher-level D-Bus API.  This preserves exactly the same logic but:

 1. fails early on any error
 2. lives in one place so your lambda stays flat
 3. avoids manual `DDBusSender` chaining

```cpp
// in desktopidentifier.h
#pragma once
#include <optional>
#include <QString>
#include <QDBusUnixFileDescriptor>

std::optional<QString> identifyDesktopId(pid_t windowPid);

// in desktopidentifier.cpp
#include "desktopidentifier.h"
#include <QDBusConnection>
#include <QDBusInterface>
#include <unistd.h>
#include <sys/syscall.h>

std::optional<QString> identifyDesktopId(pid_t windowPid)
{
    // 1) must have a valid PID
    if (windowPid <= 0) {
        return std::nullopt;
    }

    // 2) check ApplicationManager1 is up
    auto session = QDBusConnection::sessionBus();
    if (!session.interface()->isServiceRegistered("org.desktopspec.ApplicationManager1")) {
        return std::nullopt;
    }

    // 3) open pidfd
    int pidfd = syscall(SYS_pidfd_open, windowPid, 0);
    if (pidfd < 0) {
        return std::nullopt;
    }

    // 4) call Identify()
    QDBusInterface iface(
        "org.desktopspec.ApplicationManager1",
        "/org/desktopspec/ApplicationManager1",
        "org.desktopspec.ApplicationManager1",
        session);

    auto reply = iface.call("Identify", QDBusUnixFileDescriptor(pidfd));
    ::close(pidfd);

    if (!reply.isValid()) {
        qCDebug(taskManagerLog) << "AM Identify failed:" << reply.error().message();
        return std::nullopt;
    }

    // 5) extract desktopId
    const auto args = reply.arguments();
    const auto desktopId = args.value(0).toString();
    if (desktopId.isEmpty()) {
        return std::nullopt;
    }
    return desktopId;
}
```

Then your lambda becomes:

```cpp
pid_t windowPid = identifies.last().toInt();
if (auto desktopId = identifyDesktopId(windowPid)) {
    auto idx = model->match(
        model->index(0,0),
        roleNames.key(MODEL_DESKTOPID),
        *desktopId,
        /*count=*/1,
        Qt::MatchFixedString | Qt::MatchWrap);

    if (!idx.isEmpty()) {
        qCDebug(taskManagerLog) << "matched by AM desktop ID:" << *desktopId << idx.value(0);
        return idx.value(0);
    }
}

// fallback to old matching
auto res = model->match(
    model->index(0,0),
    roleNames.key(MODEL_DESKTOPID),
    identifies.value(0),
    /*count=*/1,
    Qt::MatchEndsWith);

qCDebug(taskManagerLog) << "matched" << res.value(0);
return res.value(0);
```

This pulls out all the nesting into a helper, uses guard‐clauses to exit on error, and keeps your original behavior intact.
</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.

}
}

pid_t windowPid = identifies.last().toInt();
Copy link
Contributor

Choose a reason for hiding this comment

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

调用dtkcore的DSGApplication::id这种接口试试,它获取的是AppId,应该跟这个是一样的,

}
}

pid_t windowPid = identifies.last().toInt();
Copy link
Contributor

Choose a reason for hiding this comment

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

identifies判断下是否为空,

Copy link
Contributor

@18202781743 18202781743 left a comment

Choose a reason for hiding this comment

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

分两笔提交,一个pr,先revert之前那一笔,再在基础上修改,

@wjyrich wjyrich force-pushed the fix-identify branch 2 times, most recently from 0d78d0e to d8956c2 Compare October 27, 2025 08:41
18202781743
18202781743 previously approved these changes Oct 27, 2025
@wjyrich wjyrich force-pushed the fix-identify branch 2 times, most recently from afebbd5 to 00942a7 Compare October 27, 2025 09:51
1. Added ApplicationManager D-Bus integration for more accurate window
identification
2. Implemented pidfd-based process identification to get desktop IDs
from ApplicationManager
3. Removed desktopfileID from X11Window identity to avoid circular
dependencies
4. Reordered window tracking and signal emission to ensure proper
initialization
5. Added syscall and D-Bus dependencies for process identification

feat: 增强窗口识别功能,集成 ApplicationManager

1. 添加 ApplicationManager D-Bus 集成以实现更精确的窗口识别
2. 实现基于 pidfd 的进程识别,从 ApplicationManager 获取桌面 ID
3. 从 X11Window 身份信息中移除 desktopfileID 以避免循环依赖
4. 重新排序窗口跟踪和信号发射以确保正确初始化
5. 添加系统调用和 D-Bus 依赖以支持进程识别
@deepin-ci-robot
Copy link

deepin pr auto review

我来对这段代码变更进行审查:

  1. 代码逻辑分析:
    主要变更点在于引入了AM(Application Manager)来匹配应用程序,并修改了X11窗口识别的逻辑。新的实现通过pid获取desktopId,并优先使用AM的匹配结果。

  2. 代码质量改进建议:

  • getDesktopIdByPid函数中缺少对DSGApplication::getId返回值的详细错误处理。建议增加更多的错误状态检查和日志记录。
  • 在taskmanager.cpp中,match操作使用了Qt::MatchFixedString | Qt::MatchWrap标志,但未考虑大小写敏感性问题。建议明确指定是否需要大小写敏感匹配。
  1. 性能优化建议:
  • getDesktopIdByPid函数每次都会调用DSGApplication::getId,这可能是一个系统调用。建议考虑缓存机制,特别是对于频繁访问的窗口。
  • 在TaskManager::init中的匹配逻辑是顺序执行的,可以考虑将多个匹配条件合并以减少遍历次数。
  1. 安全性改进建议:
  • 在getDesktopIdByPid函数中,identifies.last().toInt()的转换没有进行错误检查。建议使用更安全的转换方式,如QString::toInt(bool *ok)并检查转换结果。
  • pid_t windowPid的值范围检查应该更严格,除了检查是否<=0外,还应该检查是否在系统允许的pid范围内。
  1. 代码规范建议:
  • 建议为getDesktopIdByPid函数添加更详细的注释说明其工作原理和返回值。
  • 在x11window.cpp中删除的代码应该添加注释说明删除原因。
  • 在x11windowmonitor.cpp中,信号发射位置的变更应该添加注释说明原因。
  1. 具体修改建议:
static QString getDesktopIdByPid(const QStringList &identifies)
{
    if (identifies.isEmpty())
        return {};

    bool ok;
    pid_t windowPid = identifies.last().toInt(&ok);
    if (!ok || windowPid <= 0 || windowPid > PID_MAX_LIMIT) {
        qCWarning(taskManagerLog) << "Invalid pid value:" << identifies.last();
        return {};
    }

    auto appId = DSGApplication::getId(windowPid);
    if (appId.isEmpty()) {
        qCDebug(taskManagerLog) << "appId is empty, AM failed to identify window with pid:" << windowPid;
        return {};
    }
        
    return QString::fromUtf8(appId);
}
  1. 其他建议:
  • 考虑添加单元测试来验证新的匹配逻辑的正确性。
  • 建议在代码中添加性能监控点,以便跟踪AM匹配的效率。
  • 考虑添加配置选项,允许在AM匹配失败时回退到原有的匹配方式。

这些修改将提高代码的健壮性、可维护性和性能,同时保持代码的安全性。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@wjyrich
Copy link
Contributor Author

wjyrich commented Oct 28, 2025

/forcemerge

@deepin-bot
Copy link

deepin-bot bot commented Oct 28, 2025

This pr force merged! (status: behind)

@deepin-bot deepin-bot bot merged commit 927d287 into linuxdeepin:master Oct 28, 2025
9 of 11 checks passed
@wjyrich wjyrich deleted the fix-identify branch October 28, 2025 02:05
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