diff --git a/panels/dock/taskmanager/appitem.cpp b/panels/dock/taskmanager/appitem.cpp index 35b7b69e3..09f31301a 100644 --- a/panels/dock/taskmanager/appitem.cpp +++ b/panels/dock/taskmanager/appitem.cpp @@ -15,6 +15,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(appitemLog, "org.deepin.dde.shell.dock.taskmanger.appitem") @@ -346,7 +347,15 @@ void AppItem::checkAppItemNeedDeleteAndDelete() return; } - deleteLater(); + // Grace period: delay deletion to allow a new window (e.g. Electron + // main window after splash closes) to re-attach before the AppItem + // is actually destroyed. If a new window arrives within the delay, + // hasWindow() will return true and the deletion is cancelled. + QTimer::singleShot(500, this, [this]() { + if (!hasWindow() && !isDocked()) { + deleteLater(); + } + }); } void AppItem::onWindowDestroyed() diff --git a/panels/dock/taskmanager/desktopfileamparser.cpp b/panels/dock/taskmanager/desktopfileamparser.cpp index 7b714a727..9f69f2fab 100644 --- a/panels/dock/taskmanager/desktopfileamparser.cpp +++ b/panels/dock/taskmanager/desktopfileamparser.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + #include #include #include @@ -147,17 +150,35 @@ QString DesktopFileAMParser::id2dbusPath(const QString& id) return QStringLiteral("/org/desktopspec/ApplicationManager1/") + escapeToObjectPath(id); } -QString DesktopFileAMParser::identifyWindow(QPointer window) +// Read PPID from /proc//status. Returns 0 on failure. +static pid_t findParentPid(pid_t pid) { - if (!m_amIsAvaliable) m_amIsAvaliable = QDBusConnection::sessionBus(). - interface()->isServiceRegistered(AM_DBUS_PATH); - - if (!m_amIsAvaliable) return QString(); + QFile statusFile(QStringLiteral("/proc/%1/status").arg(pid)); + if (!statusFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + return 0; + } + QTextStream stream(&statusFile); + QString line; + while (stream.readLineInto(&line)) { + if (line.startsWith(QStringLiteral("PPid:"))) { + bool ok = false; + pid_t ppid = line.mid(5).trimmed().toInt(&ok); + return ok ? ppid : 0; + } + } + return 0; +} - auto pidfd = pidfd_open(window->pid(),0); +// Try AM Identify with the given PID. Returns the identified desktop ID or empty string. +static QString tryAmIdentify(pid_t pid) +{ + auto pidfd = pidfd_open(pid, 0); + if (pidfd < 0) { + return QString(); + } auto res = DDBusSender().service("org.desktopspec.ApplicationManager1") .interface("org.desktopspec.ApplicationManager1") - .path("/org/desktopspec/ApplicationManager1") + .path("/org/desktopspec.ApplicationManager1") .method("Identify") .arg(QDBusUnixFileDescriptor(pidfd)) .call(); @@ -168,8 +189,41 @@ QString DesktopFileAMParser::identifyWindow(QPointer window) QList data = reply.arguments(); return data.first().toString(); } + qCDebug(amdesktopfileLog()) << "AM failed to identify pid" << pid + << ", reason is:" << res.error().message(); + return QString(); +} + +QString DesktopFileAMParser::identifyWindow(QPointer window) +{ + if (!m_amIsAvaliable) m_amIsAvaliable = QDBusConnection::sessionBus(). + interface()->isServiceRegistered(AM_DBUS_PATH); + + if (!m_amIsAvaliable) return QString(); + + // First attempt: identify using the window's own PID. + QString result = tryAmIdentify(window->pid()); + if (!result.isEmpty()) { + return result; + } - qCDebug(amdesktopfileLog()) << "AM failed to identify, reason is: " << res.error().message(); + // Fallback: walk up the process tree. Electron and similar multi-process + // apps may create windows with a renderer subprocess PID. The main process + // (parent or grandparent) is the one AM can identify. + pid_t currentPid = window->pid(); + for (int i = 0; i < 5; ++i) { + pid_t parentPid = findParentPid(currentPid); + if (parentPid <= 0 || parentPid == currentPid) { + break; + } + result = tryAmIdentify(parentPid); + if (!result.isEmpty()) { + qCDebug(amdesktopfileLog()) << "Identified via parent pid" << parentPid + << "after child pid" << window->pid() << "failed"; + return result; + } + currentPid = parentPid; + } return QString(); } diff --git a/panels/dock/taskmanager/taskmanager.cpp b/panels/dock/taskmanager/taskmanager.cpp index 29bd23c31..02ef7189e 100644 --- a/panels/dock/taskmanager/taskmanager.cpp +++ b/panels/dock/taskmanager/taskmanager.cpp @@ -352,6 +352,11 @@ void TaskManager::handleWindowAdded(QPointer window) qCDebug(taskManagerLog()) << "identify by Fallback:" << desktopId; } + if (desktopfile.isNull()) { + qCWarning(taskManagerLog()) << "Failed to identify window, desktopfile is null, skip window:" << window->id(); + return; + } + auto appitem = desktopfile->getAppItem(); if (appitem.isNull() || (appitem->hasWindow() && windowSplit())) {