From 8b89bc909282b9bed361350ea8017e9c5a7eee8d Mon Sep 17 00:00:00 2001 From: donghualin Date: Mon, 8 Aug 2022 05:20:42 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=9C=80=E5=90=8E=E4=B8=89=E4=B8=AA=E6=9C=AA=E9=A9=BB=E7=95=99?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=88=B0=E4=BB=BB=E5=8A=A1=E6=A0=8F=E4=B8=8A?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E4=B8=8D=E6=B6=88=E5=A4=B1=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加最近打开区域的配置,在关闭未驻留应用的时候判断是否需要移除图标,同时更新配置 Log: 完成最近打开应用的功能 Influence: 任务栏-打开多个未驻留应用,然后依次关闭,当剩下最后三个的时候,观察是否还在任务栏 Bug: https://pms.uniontech.com/bug-view-147721.html Change-Id: Ia78e973b41acb3e87c515f3bd8479f603b3dcdfd --- misc/dconf/com.deepin.dde.dock.json | 10 ++ src/modules/dock/common.h | 14 +-- src/modules/dock/dbushandler.cpp | 24 +++-- src/modules/dock/dbushandler.h | 1 + src/modules/dock/dock.cpp | 149 ++++++++++++++++++--------- src/modules/dock/dock.h | 8 +- src/modules/dock/docksettings.cpp | 36 +++++-- src/modules/dock/docksettings.h | 8 +- src/modules/dock/entries.cpp | 122 ++++++++++++++++++---- src/modules/dock/entries.h | 13 ++- src/modules/dock/entry.cpp | 153 +++++++++++++++------------- src/modules/dock/entry.h | 20 ++-- src/modules/dock/processinfo.cpp | 1 - src/modules/dock/waylandmanager.cpp | 8 +- 14 files changed, 379 insertions(+), 188 deletions(-) diff --git a/misc/dconf/com.deepin.dde.dock.json b/misc/dconf/com.deepin.dde.dock.json index ae4bc02..6cd3f7d 100644 --- a/misc/dconf/com.deepin.dde.dock.json +++ b/misc/dconf/com.deepin.dde.dock.json @@ -141,6 +141,16 @@ "description": "The dock gets different display mode, for instance, dock looks like win7 taskbar on classic mode.", "permissions": "readwrite", "visibility": "private" + }, + "Recent_App": { + "value": [], + "serial": 0, + "flags": [], + "name": "Recent_App", + "name[zh_CN]": "*****", + "description": "The apps which has been opened recently when dock is started", + "permissions": "readwrite", + "visibility": "private" } } } diff --git a/src/modules/dock/common.h b/src/modules/dock/common.h index 9df0899..d691d52 100644 --- a/src/modules/dock/common.h +++ b/src/modules/dock/common.h @@ -41,21 +41,9 @@ const QString keyWinIconPreferredApps = "Win_Icon_Preferred_Apps"; const QString keyOpacity = "Opacity"; const QString keyPluginSettings = "Plugin_Settings"; const QString keyForceQuitApp = "Force_Quit_App"; +const QString keyRecentApp = "Recent_App"; const QString scratchDir = QDir::homePath() + "/.local/dock/scratch/"; -const QMap pathDirCodeMap { - {"/usr/share/applications/", "/S@"}, - {"/usr/local/share/applications/", "/L@"}, - {QDir::homePath() + "/.local/share/applications", "/H@"}, - {QDir::homePath() + "/.local/dock/scratch", "/D@"}, -}; - -const QMap pathCodeDirMap { - {"/S@", "/usr/share/applications/"}, - {"/L@", "/usr/local/share/applications/"}, - {"/H@", QDir::homePath() + "/.local/share/applications"}, - {"/D@", QDir::homePath() + "/.local/dock/scratch"}, -}; // DBus服务、路径 const QString dbusService = "org.deepin.dde.daemon.Dock1"; diff --git a/src/modules/dock/dbushandler.cpp b/src/modules/dock/dbushandler.cpp index 5ff93f0..b04883a 100644 --- a/src/modules/dock/dbushandler.cpp +++ b/src/modules/dock/dbushandler.cpp @@ -64,6 +64,18 @@ void DBusHandler::listenWaylandWMSignals() }); } +void DBusHandler::loadClientList() +{ + if (!kwaylandManager) + return; + + // 加载已存在的窗口 + QDBusPendingReply windowList = kwaylandManager->Windows(); + QVariantList windows = windowList.value(); + for (QVariant windowPath : windows) + dock->registerWindowWayland(windowPath.toString()); +} + void DBusHandler::handleLauncherItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID) { qInfo() << "handleLauncherItemChanged status:" << status << " Name:" << itemInfo.name << " ID:" << itemInfo.id; @@ -125,7 +137,7 @@ void DBusHandler::handleWlActiveWindowChange() return; WindowInfoK *info = dock->handleActiveWindowChangedK(activeWinInternalId); - if (info->getXid() != 0) { + if (info && info->getXid() != 0) { WindowInfoBase *base = static_cast(info); if (base) { dock->handleActiveWindowChanged(base); @@ -142,7 +154,7 @@ void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo) return; // Title changed - connect(window, &PlasmaWindow::TitleChanged, this, [&] { + connect(window, &PlasmaWindow::TitleChanged, this, [=] { windowInfo->updateTitle(); auto entry = dock->getEntryByWindowId(windowInfo->getXid()); if (!entry) @@ -155,7 +167,7 @@ void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo) }); // Icon changed - connect(window, &PlasmaWindow::IconChanged, this, [&] { + connect(window, &PlasmaWindow::IconChanged, this, [=] { windowInfo->updateIcon(); auto entry = dock->getEntryByWindowId(windowInfo->getXid()); if (!entry) @@ -165,7 +177,7 @@ void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo) }); // DemandingAttention changed - connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [&] { + connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [=] { windowInfo->updateDemandingAttention(); auto entry = dock->getEntryByWindowId(windowInfo->getXid()); if (!entry) @@ -175,7 +187,7 @@ void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo) }); // Geometry changed - connect(window, &PlasmaWindow::GeometryChanged, this, [&] { + connect(window, &PlasmaWindow::GeometryChanged, this, [=] { if (!windowInfo->updateGeometry()) return; @@ -185,7 +197,7 @@ void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo) PlasmaWindow *DBusHandler::createPlasmaWindow(QString objPath) { - return new PlasmaWindow("com.deepin.daemon.KWayland.PlasmaWindow", objPath, session, this); + return new PlasmaWindow("com.deepin.daemon.KWayland", objPath, session, this); } /** diff --git a/src/modules/dock/dbushandler.h b/src/modules/dock/dbushandler.h index ccb0f47..d1b2b74 100644 --- a/src/modules/dock/dbushandler.h +++ b/src/modules/dock/dbushandler.h @@ -45,6 +45,7 @@ public: /************************* KWayland/WindowManager ***************************/ void listenWaylandWMSignals(); + void loadClientList(); bool wlShowingDesktop(); uint wlActiveWindow(); diff --git a/src/modules/dock/dock.cpp b/src/modules/dock/dock.cpp index 1cf5499..baa1c48 100644 --- a/src/modules/dock/dock.cpp +++ b/src/modules/dock/dock.cpp @@ -99,7 +99,7 @@ Dock::~Dock() * @param entry 应用实例 * @return */ -bool Dock::dockEntry(Entry *entry) +bool Dock::dockEntry(Entry *entry, bool moveToEnd) { if (entry->getIsDocked()) return false; @@ -178,6 +178,10 @@ bool Dock::dockEntry(Entry *entry) entry->setInnerId(app->getInnerId()); } + // 如果是最近打开应用,通过右键菜单的方式驻留,且当前是时尚模式,那么就让entry驻留到末尾 + if (moveToEnd && SETTING->getDisplayMode() == DisplayMode::Fashion) + entries->moveEntryToLast(entry); + entry->setPropIsDocked(true); entry->updateMenu(); return true; @@ -187,7 +191,7 @@ bool Dock::dockEntry(Entry *entry) * @brief Dock::undockEntry 取消驻留 * @param entry 应用实例 */ -void Dock::undockEntry(Entry *entry) +void Dock::undockEntry(Entry *entry, bool moveToEnd) { if (!entry->getIsDocked()) { qInfo() << "undockEntry: " << entry->getId() << " is not docked"; @@ -214,7 +218,7 @@ void Dock::undockEntry(Entry *entry) } if (entry->hasWindow()) { - if (desktopFile.contains(scratchDir) && !!entry->getCurrentWindowInfo()) { + if (desktopFile.contains(scratchDir) && entry->getCurrentWindowInfo()) { QFileInfo info(desktopFile); QString baseName = info.baseName(); if (baseName.startsWith(windowHashPrefix)) { @@ -231,6 +235,10 @@ void Dock::undockEntry(Entry *entry) entry->setInnerId(innerId); } } + // 如果存在窗口,在时尚模式下,就会移动到最近打开区域,此时让它移动到最后 + if (moveToEnd && SETTING->getDisplayMode() == DisplayMode::Fashion) + entries->moveEntryToLast(entry); + entry->updateIcon(); entry->setPropIsDocked(false); entry->updateName(); @@ -667,39 +675,41 @@ void Dock::updateMenu() */ void Dock::initEntries() { - initDockedApps(); - if (!isWayland) - initClientList(); + loadAppInfos(); + initClientList(); } /** - * @brief Dock::initDockedApps 初始化驻留应用 + * @brief Dock::loadAppInfos 加载本地驻留和最近使用的应用信息 */ -void Dock::initDockedApps() +void Dock::loadAppInfos() { - // 初始化驻留应用信息 - for (const auto &app : SETTING->getDockedApps()) { - if (app.isEmpty() || app[0] != '/' || app.size() <= 3) - continue; + // 初始化驻留应用信息和最近使用的应用的信息 + auto loadApps = [ this ](const QStringList &apps, bool isDocked) { + for (const QString &app : apps) { + QString path = app; + DesktopInfo info(path.toStdString()); + if (!info.isValidDesktop()) + continue; - QString prefix(app.data(), 3); - QString appId(app.data() + 3); - QString path; - if (pathCodeDirMap.find(prefix) != pathCodeDirMap.end()) - path = pathCodeDirMap[prefix] + appId + ".desktop"; + AppInfo *appInfo = new AppInfo(info); + Entry *entryObj = new Entry(this, appInfo, appInfo->getInnerId()); + entryObj->setIsDocked(isDocked); + entryObj->updateMenu(); + entryObj->startExport(); + entries->append(entryObj); + } + }; - DesktopInfo info(path.toStdString()); - if (!info.isValidDesktop()) - continue; - - AppInfo *appInfo = new AppInfo(info); - Entry *entryObj = new Entry(this, appInfo, appInfo->getInnerId()); - entryObj->setIsDocked(true); - entryObj->updateMenu(); - entryObj->startExport(); - entries->append(entryObj); + loadApps(SETTING->getDockedApps(), true); + QStringList recentApps = SETTING->getRecentApps(); + if (recentApps.size() > MAX_UNOPEN_RECENT_COUNT) { + QStringList tempApps = recentApps; + recentApps.clear(); + for (int i = 0; i < MAX_UNOPEN_RECENT_COUNT; i++) + recentApps << tempApps[i]; } - + loadApps(recentApps, false); saveDockedApps(); } @@ -708,16 +718,20 @@ void Dock::initDockedApps() */ void Dock::initClientList() { - QList clients; - for (auto c : XCB->instance()->getClientList()) - clients.push_back(c); + if (isWayland) { + dbusHandler->loadClientList(); + } else { + QList clients; + for (auto c : XCB->instance()->getClientList()) + clients.push_back(c); - // 依次注册窗口 - qSort(clients.begin(), clients.end()); - clientList = clients; - for (auto winId : clientList) { - WindowInfoX *winInfo = x11Manager->registerWindow(winId); - attachOrDetachWindow(static_cast(winInfo)); + // 依次注册窗口 + qSort(clients.begin(), clients.end()); + clientList = clients; + for (auto winId : clientList) { + WindowInfoX *winInfo = x11Manager->registerWindow(winId); + attachOrDetachWindow(static_cast(winInfo)); + } } } @@ -1048,6 +1062,9 @@ void Dock::attachOrDetachWindow(WindowInfoBase *info) if (shouldShowOnDock(info)) attachWindow(info); } + + // 在新增窗口后,同步最近打开应用到com.deepin.dde.dock.json的DConfig配置文件中 + updateRecentApps(); } /** @@ -1062,6 +1079,7 @@ void Dock::attachWindow(WindowInfoBase *info) // entry existed entry->attachWindow(info); } else { + entries->removeLastRecent(); entry = new Entry(this, info->getAppInfo(), info->getEntryInnerId()); if (entry->attachWindow(info)) { entry->startExport(); @@ -1076,13 +1094,32 @@ void Dock::attachWindow(WindowInfoBase *info) */ void Dock::detachWindow(WindowInfoBase *info) { - auto entry = entries->getByWindowId(info->getXid()); + Entry *entry = entries->getByWindowId(info->getXid()); if (!entry) return; bool needRemove = entry->detachWindow(info); - if (needRemove) - removeAppEntry(entry); + if (needRemove) { + // 如果是最近打开应用 + if (entries->shouldInRecent()) { + // 更新entry的导出窗口信息 + entry->updateExportWindowInfos(); + // 更新entry的右键菜单的信息 + entry->updateMenu(); + // 更新entry的当前窗口的信息 + entry->setCurrentWindowInfo(nullptr); + // 移除应用后,同时更新最近打开的应用 + updateRecentApps(); + // 如果是高效模式,则发送消息 + if (SETTING->getDisplayMode() == DisplayMode::Efficient) { + Q_EMIT entryRemoved(entry->getId()); + } + } else { + removeAppEntry(entry); + // 移除应用后,同时更新最近打开的应用 + updateRecentApps(); + } + } } /** @@ -1165,19 +1202,29 @@ void Dock::handleActiveWindowChanged(WindowInfoBase *info) */ void Dock::saveDockedApps() { - QList dockedApps; + QStringList dockedApps; for (auto entry : entries->filterDockedEntries()) { QString path = entry->getApp()->getFileName(); - for (auto iter=pathDirCodeMap.begin(); iter != pathDirCodeMap.end(); iter++) { - if (path.startsWith(iter.key())) { - path = QString(path.data() + iter.key().size()); // 去头dir - path.truncate(path.size() - 8); // 去尾.desktop - dockedApps.push_back(iter.value() + path); - break; - } - } + dockedApps << path; } + SETTING->setDockedApps(dockedApps); + + // 在驻留任务栏的时候,同时更新最近打开应用的信息 + updateRecentApps(); +} + +void Dock::updateRecentApps() +{ + QStringList unDockedApps; + QList recentEntrys = entries->unDockedEntries(); + for (Entry *entry : recentEntrys) { + QString path = entry->getApp()->getFileName(); + unDockedApps << path; + } + + // 保存未驻留的应用作为最近打开的应用 + SETTING->setRecentApps(unDockedApps); } /** 移除应用实例 @@ -1357,7 +1404,9 @@ int Dock::getDisplayMode() */ void Dock::setDisplayMode(int mode) { - SETTING->setDisplayMode(DisplayMode(mode)); + DisplayMode displayMode = static_cast(mode); + SETTING->setDisplayMode(displayMode); + entries->setDisplayMode(displayMode); } /** diff --git a/src/modules/dock/dock.h b/src/modules/dock/dock.h index 06b260d..22ee4ac 100644 --- a/src/modules/dock/dock.h +++ b/src/modules/dock/dock.h @@ -54,8 +54,8 @@ public: explicit Dock(QObject *parent = nullptr); ~Dock(); - bool dockEntry(Entry *entry); - void undockEntry(Entry *entry); + bool dockEntry(Entry *entry, bool moveToEnd = false); + void undockEntry(Entry *entry, bool moveToEnd = false); QString allocEntryId(); bool shouldShowOnDock(WindowInfoBase *info); void setDdeLauncherVisible(bool visible); @@ -159,7 +159,7 @@ private: void initSettings(); void updateMenu(); void initEntries(); - void initDockedApps(); + void loadAppInfos(); void initClientList(); WindowInfoX *findWindowByXidX(XWindow xid); WindowInfoK *findWindowByXidK(XWindow xid); @@ -170,7 +170,9 @@ private: Entry *getDockedEntryByDesktopFile(const QString &desktopFile); bool shouldHideOnSmartHideMode(); QVector getActiveWinGroup(XWindow xid); + void updateRecentApps(); +private: WindowIdentify *windowIdentify; // 窗口识别 Entries *entries; // 所有应用实例 int entriesSum; // 累计打开的应用数量 diff --git a/src/modules/dock/docksettings.cpp b/src/modules/dock/docksettings.cpp index afff3dc..2092189 100644 --- a/src/modules/dock/docksettings.cpp +++ b/src/modules/dock/docksettings.cpp @@ -209,13 +209,21 @@ void DockSettings::setWindowSizeFashion(uint size) } } -QStringList DockSettings::getDockedApps() +void DockSettings::saveStringList(const QString &key, const QStringList &values) +{ + if (!m_dockSettings) + return; + + m_dockSettings->setValue(key, values); +} + +QStringList DockSettings::loadStringList(const QString &key) const { QStringList ret; if (!m_dockSettings) return ret; - for(const auto &var : m_dockSettings->value(keyDockedApps).toList()) { + for(const auto &var : m_dockSettings->value(key).toList()) { if (var.isValid()) ret.push_back(var.toString()); } @@ -223,18 +231,24 @@ QStringList DockSettings::getDockedApps() return ret; } -void DockSettings::setDockedApps(QList &apps) +QStringList DockSettings::getDockedApps() { - if (!m_dockSettings) - return; + return loadStringList(keyDockedApps); +} - qDebug() << "docked apps:" << apps; - QVariantList list; - for (auto app : apps) { - list << QVariant(app); - } +void DockSettings::setDockedApps(const QStringList &apps) +{ + saveStringList(keyDockedApps, apps); +} - m_dockSettings->setValue(keyDockedApps, list); +QStringList DockSettings::getRecentApps() const +{ + return loadStringList(keyRecentApp); +} + +void DockSettings::setRecentApps(const QStringList &apps) +{ + saveStringList(keyRecentApp, apps); } double DockSettings::getOpacity() diff --git a/src/modules/dock/docksettings.h b/src/modules/dock/docksettings.h index 9b1f331..d9ace2c 100644 --- a/src/modules/dock/docksettings.h +++ b/src/modules/dock/docksettings.h @@ -228,7 +228,9 @@ public: uint getWindowSizeFashion(); void setWindowSizeFashion(uint size); QStringList getDockedApps(); - void setDockedApps(QList &apps); + void setDockedApps(const QStringList &apps); + QStringList getRecentApps() const; + void setRecentApps(const QStringList &apps); double getOpacity(); QVector getWinIconPreferredApps(); @@ -249,12 +251,14 @@ Q_SIGNALS: // 强制退出应用开关改变 void forceQuitAppChanged(ForceQuitAppMode mode); - private: DockSettings(QObject *paret = nullptr); DockSettings(const DockSettings &); DockSettings& operator= (const DockSettings &); + void saveStringList(const QString &key, const QStringList &values); + QStringList loadStringList(const QString &key) const; +private: DConfig *m_dockSettings; DConfig *m_appearanceSettings; }; diff --git a/src/modules/dock/entries.cpp b/src/modules/dock/entries.cpp index 02ff600..070c516 100644 --- a/src/modules/dock/entries.cpp +++ b/src/modules/dock/entries.cpp @@ -31,7 +31,7 @@ Entries::Entries(Dock *_dock) QVector Entries::filterDockedEntries() { QVector ret; - for (auto &entry : items) { + for (auto &entry : m_items) { if (entry->isValid() && entry->getIsDocked()) ret.push_back(entry); } @@ -42,7 +42,7 @@ QVector Entries::filterDockedEntries() Entry *Entries::getByInnerId(QString innerId) { Entry *ret = nullptr; - for (auto &entry : items) { + for (auto &entry : m_items) { if (entry->getInnerId() == innerId) ret = entry; } @@ -57,13 +57,13 @@ void Entries::append(Entry *entry) void Entries::insert(Entry *entry, int index) { - if (index < 0 || index >= items.size()) { + if (index < 0 || index >= m_items.size()) { // append - index = items.size(); - items.push_back(entry); + index = m_items.size(); + m_items.push_back(entry); } else { // insert - items.insert(index, entry); + m_items.insert(index, entry); } insertCb(entry, index); @@ -71,9 +71,9 @@ void Entries::insert(Entry *entry, int index) void Entries::remove(Entry *entry) { - for (auto iter = items.begin(); iter != items.end();) { + for (auto iter = m_items.begin(); iter != m_items.end();) { if ((*iter)->getId() == entry->getId()) { - iter = items.erase(iter); + iter = m_items.erase(iter); removeCb(entry); delete entry; } else { @@ -84,16 +84,16 @@ void Entries::remove(Entry *entry) void Entries::move(int oldIndex, int newIndex) { - if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= items.size() || newIndex >= items.size()) + if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= m_items.size() || newIndex >= m_items.size()) return; - items.swap(oldIndex, newIndex); + m_items.swap(oldIndex, newIndex); } Entry *Entries::getByWindowPid(int pid) { Entry *ret = nullptr; - for (auto &entry : items) { + for (auto &entry : m_items) { if (entry->getWindowInfoByPid(pid)) { ret = entry; break; @@ -106,7 +106,7 @@ Entry *Entries::getByWindowPid(int pid) Entry *Entries::getByWindowId(XWindow windowId) { Entry *ret = nullptr; - for (auto &entry : items) { + for (auto &entry : m_items) { if (entry->getWindowInfoByWinId(windowId)) { ret = entry; break; @@ -119,7 +119,7 @@ Entry *Entries::getByWindowId(XWindow windowId) Entry *Entries::getByDesktopFilePath(QString filePath) { Entry *ret = nullptr; - for (auto &entry : items) { + for (auto &entry : m_items) { if (entry->getFileName() == filePath) { ret = entry; break; @@ -132,7 +132,7 @@ Entry *Entries::getByDesktopFilePath(QString filePath) QStringList Entries::getEntryIDs() { QStringList list; - for (auto item : items) + for (auto item : m_items) list.push_back(item->getId()); return list; @@ -157,7 +157,7 @@ Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile) QString Entries::queryWindowIdentifyMethod(XWindow windowId) { QString ret; - for (auto entry : items) { + for (auto entry : m_items) { auto window = entry->getWindowInfoByWinId(windowId); if (window) { auto app = window->getAppInfo(); @@ -175,7 +175,7 @@ QString Entries::queryWindowIdentifyMethod(XWindow windowId) void Entries::handleActiveWindowChanged(XWindow activeWindId) { - for (auto entry : items) { + for (auto entry : m_items) { auto windowInfo = entry->getWindowInfoByWinId(activeWindId); if (windowInfo) { entry->setPropIsActive(true); @@ -190,15 +190,35 @@ void Entries::handleActiveWindowChanged(XWindow activeWindId) void Entries::updateEntriesMenu() { - for (auto entry : items) { + for (auto entry : m_items) { entry->updateMenu(); } } +const QList Entries::unDockedEntries() const +{ + QList entrys; + for (Entry *entry : m_items) { + if (!entry->isValid() || entry->getIsDocked()) + continue; + + entrys << entry; + } + + return entrys; +} + +void Entries::moveEntryToLast(Entry *entry) +{ + if (m_items.contains(entry)) { + m_items.removeOne(entry); + m_items << entry; + } +} + void Entries::insertCb(Entry *entry, int index) { - QString objPath = entryDBusObjPathPrefix + entry->getId(); - Q_EMIT dock->entryAdded(QDBusObjectPath(objPath), index); + Q_EMIT dock->entryAdded(QDBusObjectPath(entry->path()), index); } void Entries::removeCb(Entry *entry) @@ -207,3 +227,67 @@ void Entries::removeCb(Entry *entry) entry->stopExport(); } +bool Entries::shouldInRecent() +{ + // 如果当前移除的应用是未驻留应用,则判断未驻留应用的数量是否小于等于3,则让其始终显示 + QList unDocktrys; + for (Entry *entry : m_items) { + if (entry->isValid() && !entry->getIsDocked()) + unDocktrys << entry; + } + + // 如果当前未驻留应用的数量小于3个,则认为后续的应用应该显示到最近打开应用 + return (unDocktrys.size() <= MAX_UNOPEN_RECENT_COUNT); +} + +void Entries::removeLastRecent() +{ + // 先查找最近使用的应用,删除没有使用的 + int unDockCount = 0; + QList unDockEntrys; + QList removeEntrys; + for (Entry *entry : m_items) { + if (entry->getIsDocked()) + continue; + + // 此处只移除没有子窗口的图标 + if (!entry->hasWindow()) { + if (!entry->isValid()) + removeEntrys << entry; // 如果应用已经被卸载,那么需要删除 + else + unDockEntrys << entry; + } + + unDockCount++; + } + if (unDockCount >= MAX_UNOPEN_RECENT_COUNT && unDockEntrys.size() > 0) { + // 只有当最近使用区域的图标大于等于某个数值(3)的时候,并且存在没有子窗口的Entry,那么就移除该Entry + Entry *entry = unDockEntrys[0]; + m_items.removeOne(entry); + removeEntrys << entry; + } + for (Entry *entry : removeEntrys) { + removeCb(entry); + delete entry; + } +} + +void Entries::setDisplayMode(DisplayMode displayMode) +{ + // 如果从时尚模式变成高效模式,对列表中所有的没有打开窗口的应用发送移除信号 + if (displayMode == DisplayMode::Efficient) { + for (Entry *entry : m_items) { + if (!entry->getIsDocked() && !entry->hasWindow()) + Q_EMIT dock->entryRemoved(entry->getId()); + } + } else { + // 如果从高效模式变成时尚模式,列表中所有的未驻留且不存在打开窗口的应用认为是最近打开应用,发送新增信号 + for (Entry *entry : m_items) { + if (!entry->getIsDocked() && !entry->hasWindow()) { + QString objPath = entry->path(); + int index = m_items.indexOf(entry); + Q_EMIT dock->entryAdded(QDBusObjectPath(objPath), index); + } + } + } +} diff --git a/src/modules/dock/entries.h b/src/modules/dock/entries.h index 298b38f..7f80bf6 100644 --- a/src/modules/dock/entries.h +++ b/src/modules/dock/entries.h @@ -23,9 +23,13 @@ #define ENTRIES_H #include "entry.h" +#include "docksettings.h" + #include #include +#define MAX_UNOPEN_RECENT_COUNT 3 + class Dock; // 所有应用管理类 @@ -48,11 +52,18 @@ public: QString queryWindowIdentifyMethod(XWindow windowId); void handleActiveWindowChanged(XWindow activeWindId); void updateEntriesMenu(); + const QList unDockedEntries() const; + void moveEntryToLast(Entry *entry); + bool shouldInRecent(); + void removeLastRecent(); + void setDisplayMode(DisplayMode displayMode); + +private: void insertCb(Entry *entry, int index); void removeCb(Entry *entry); private: - QList items; + QList m_items; Dock *dock; }; diff --git a/src/modules/dock/entry.cpp b/src/modules/dock/entry.cpp index 3b5077d..f078150 100644 --- a/src/modules/dock/entry.cpp +++ b/src/modules/dock/entry.cpp @@ -40,9 +40,9 @@ Entry::Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent) , isActive(false) , isDocked(false) , innerId(_innerId) - , current(nullptr) - , currentWindow(0) - , winIconPreferred(false) + , m_current(nullptr) + , m_currentWindow(0) + , m_winIconPreferred(false) { setApp(_app); id = dock->allocEntryId(); @@ -52,11 +52,11 @@ Entry::Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent) Entry::~Entry() { - for (auto winInfo : windowInfoMap) { + for (auto winInfo : m_windowInfoMap) { if (winInfo) delete winInfo; } - windowInfoMap.clear(); + m_windowInfoMap.clear(); if (app) { delete app; @@ -74,11 +74,16 @@ bool Entry::isValid() return app ? app->isValidApp() : false; } -QString Entry::getId() +QString Entry::getId() const { return id; } +QString Entry::path() const +{ + return entryDBusObjPathPrefix + getId(); +} + QString Entry::getName() { QString ret; @@ -86,8 +91,8 @@ QString Entry::getName() ret = app->getName(); } - if (ret.isEmpty() && !!current) { - ret = current->getDisplayName(); + if (ret.isEmpty() && m_current) { + ret = m_current->getDisplayName(); } return ret; @@ -102,14 +107,14 @@ QString Entry::getIcon() { QString ret; if (hasWindow()) { - if (!current) { + if (!m_current) { return ret; } // has window && current not nullptr - if (winIconPreferred) { + if (m_winIconPreferred) { // try current window icon first - ret = current->getIcon(); + ret = m_current->getIcon(); if (ret.size() > 0) { return ret; } @@ -122,7 +127,7 @@ QString Entry::getIcon() } } - return current->getIcon(); + return m_current->getIcon(); } if (app) { @@ -165,20 +170,20 @@ void Entry::setApp(AppInfo *appinfo) app = appinfo; if (!appinfo) { - winIconPreferred = true; + m_winIconPreferred = true; setPropDesktopFile(""); } else { - winIconPreferred = false; + m_winIconPreferred = false; setPropDesktopFile(appinfo->getFileName()); QString id = app->getId(); auto perferredApps = dock->getWinIconPreferredApps(); if (perferredApps.contains(id)) { - winIconPreferred = true; + m_winIconPreferred = true; return; } if (appinfo->getIcon().size() == 0) { - winIconPreferred = true; + m_winIconPreferred = true; } } } @@ -211,8 +216,7 @@ void Entry::startExport() return; } - objctPath = entryDBusObjPathPrefix + getId(); - if (!con.registerObject(objctPath, this)) { + if (!con.registerObject(path(), this)) { qWarning() << "register object Dock1 error:" << con.lastError().message(); } } @@ -226,8 +230,7 @@ void Entry::stopExport() } QDBusConnection con = QDBusConnection::sessionBus(); - objctPath.clear(); - con.unregisterObject(entryDBusObjPathPrefix + getId()); + con.unregisterObject(path()); } void Entry::setMenu(AppMenu *_menu) @@ -291,7 +294,7 @@ void Entry::updateIsActive() auto activeWin = dock->getActiveWindow(); if (activeWin) { // 判断活跃窗口是否属于当前应用 - isActive = windowInfoMap.find(activeWin->getXid()) != windowInfoMap.end(); + isActive = m_windowInfoMap.find(activeWin->getXid()) != m_windowInfoMap.end(); } setPropIsActive(isActive); @@ -299,7 +302,7 @@ void Entry::updateIsActive() WindowInfoBase *Entry::getWindowInfoByPid(int pid) { - for (const auto &windowInfo : windowInfoMap) { + for (const auto &windowInfo : m_windowInfoMap) { if (windowInfo->getPid() == pid) return windowInfo; } @@ -309,8 +312,8 @@ WindowInfoBase *Entry::getWindowInfoByPid(int pid) WindowInfoBase *Entry::getWindowInfoByWinId(XWindow windowId) { - if (windowInfoMap.find(windowId) != windowInfoMap.end()) - return windowInfoMap[windowId]; + if (m_windowInfoMap.find(windowId) != m_windowInfoMap.end()) + return m_windowInfoMap[windowId]; return nullptr; } @@ -349,21 +352,21 @@ void Entry::setPropIsActive(bool active) void Entry::setCurrentWindowInfo(WindowInfoBase *windowInfo) { - current = windowInfo; - setPropCurrentWindow(current ? current->getXid() : 0); + m_current = windowInfo; + setPropCurrentWindow(m_current ? m_current->getXid() : 0); } void Entry::setPropCurrentWindow(XWindow value) { - if (value != currentWindow) { - currentWindow = value; + if (value != m_currentWindow) { + m_currentWindow = value; Q_EMIT currentWindowChanged(value); } } WindowInfoBase *Entry::getCurrentWindowInfo() { - return current; + return m_current; } /** @@ -372,9 +375,9 @@ WindowInfoBase *Entry::getCurrentWindowInfo() */ WindowInfoBase *Entry::findNextLeader() { - auto xids = windowInfoMap.keys(); + auto xids = m_windowInfoMap.keys(); qSort(xids); - XWindow curWinId = current->getXid(); + XWindow curWinId = m_current->getXid(); int index = xids.indexOf(curWinId); if (index < 0) return nullptr; @@ -384,15 +387,15 @@ WindowInfoBase *Entry::findNextLeader() if (index < xids.size() - 1) nextIndex = index + 1; - return windowInfoMap[xids[nextIndex]]; + return m_windowInfoMap[xids[nextIndex]]; } QString Entry::getExec(bool oneLine) { - if (!current) + if (!m_current) return ""; - ProcessInfo *process = current->getProcess(); + ProcessInfo *process = m_current->getProcess(); if (process) { if (oneLine) return process->getOneCommandLine().c_str(); @@ -405,7 +408,7 @@ QString Entry::getExec(bool oneLine) bool Entry::hasWindow() { - return windowInfoMap.size() > 0; + return m_windowInfoMap.size() > 0; } /** @@ -414,7 +417,7 @@ bool Entry::hasWindow() void Entry::updateExportWindowInfos() { WindowInfoMap infos; - for (auto info : windowInfoMap) { + for (auto info : m_windowInfoMap) { WindowInfo winInfo; XWindow xid = info->getXid(); winInfo.title = info->getTitle(); @@ -423,12 +426,12 @@ void Entry::updateExportWindowInfos() } bool changed = true; - if (infos.size() == exportWindowInfos.size()) { + if (infos.size() == m_exportWindowInfos.size()) { changed = false; for (auto iter = infos.begin(); iter != infos.end(); iter++) { XWindow xid = iter.key(); - if (infos[xid].title != exportWindowInfos[xid].title || - infos[xid].attention != exportWindowInfos[xid].attention) { + if (infos[xid].title != m_exportWindowInfos[xid].title || + infos[xid].attention != m_exportWindowInfos[xid].attention) { changed = true; break; } @@ -440,7 +443,7 @@ void Entry::updateExportWindowInfos() } // 更新导出的窗口信息 - exportWindowInfos = infos; + m_exportWindowInfos = infos; } // 分离窗口, 返回是否需要从任务栏remove @@ -448,22 +451,22 @@ bool Entry::detachWindow(WindowInfoBase *info) { info->setEntry(nullptr); XWindow winId = info->getXid(); - if (windowInfoMap.contains(winId)) { - WindowInfoBase *info = windowInfoMap[winId]; - windowInfoMap.remove(winId); + if (m_windowInfoMap.contains(winId)) { + WindowInfoBase *info = m_windowInfoMap[winId]; + m_windowInfoMap.remove(winId); delete info; } - if (windowInfoMap.isEmpty()) { + if (m_windowInfoMap.isEmpty()) { if (!isDocked) { - // 既无窗口也非驻留应用,无需在任务栏显示 + // 既无窗口也非驻留应用,并且不是最近打开,无需在任务栏显示 return true; } Q_EMIT windowInfosChanged(WindowInfoMap()); setCurrentWindowInfo(nullptr); } else { - for (auto window : windowInfoMap) { + for (auto window : m_windowInfoMap) { if (window) { // 选择第一个窗口作为当前窗口 setCurrentWindowInfo(window); break; @@ -479,28 +482,43 @@ bool Entry::detachWindow(WindowInfoBase *info) return false; } +bool Entry::isShowOnDock() const +{ + // 当前应用显示图标的条件是 + // 1.时尚模式下,该应用如果有打开窗口,则正常显示,如果没有打开窗口,则显示为最近打开应用 + // 2.高效模式下,只有该应用有打开窗口才显示 + return (static_cast(dock->getDisplayMode()) == DisplayMode::Fashion + || m_exportWindowInfos.size() > 0); +} + bool Entry::attachWindow(WindowInfoBase *info) { XWindow winId = info->getXid(); qInfo() << "attatchWindow: window id:" << winId; info->setEntry(this); - if (windowInfoMap.find(winId) != windowInfoMap.end()) { + if (m_windowInfoMap.find(winId) != m_windowInfoMap.end()) { qInfo() << "attachWindow: window " << winId << " is already attached"; return false; } - windowInfoMap[winId] = info; + bool lastShowOnDock = isShowOnDock(); + m_windowInfoMap[winId] = info; updateExportWindowInfos(); updateIsActive(); - if (!current) { + if (!m_current) { // from no window to has window setCurrentWindowInfo(info); } updateIcon(); updateMenu(); + + if (!lastShowOnDock && isShowOnDock()) { + // 新打开的窗口始终显示到最后 + Q_EMIT dock->entryAdded(QDBusObjectPath(path()), -1); + } return true; } @@ -511,7 +529,7 @@ void Entry::launchApp(uint32_t timestamp) bool Entry::containsWindow(XWindow xid) { - return windowInfoMap.find(xid) != windowInfoMap.end(); + return m_windowInfoMap.find(xid) != m_windowInfoMap.end(); } // 处理菜单项 @@ -527,15 +545,15 @@ void Entry::handleDragDrop(uint32_t timestamp, QStringList files) } // 驻留 -void Entry::requestDock() +void Entry::requestDock(bool dockToEnd) { - if (dock->dockEntry(this)) { + if (dock->dockEntry(this, dockToEnd)) { dock->saveDockedApps(); } } // 取消驻留 -void Entry::requestUndock() +void Entry::requestUndock(bool dockToEnd) { dock->undockEntry(this); } @@ -549,7 +567,7 @@ void Entry::newInstance(uint32_t timestamp) // 检查应用窗口分离、合并状态 void Entry::check() { - for (auto iter = windowInfoMap.begin(); iter != windowInfoMap.end(); iter++) { + for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) { dock->attachOrDetachWindow(iter.value()); } } @@ -558,7 +576,7 @@ void Entry::check() void Entry::forceQuit() { QMap> pidWinInfoMap; - for (auto iter = windowInfoMap.begin(); iter != windowInfoMap.end(); iter++) { + for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) { int pid = iter.value()->getPid(); if (pid != 0) { pidWinInfoMap[pid].push_back(iter.value()); @@ -579,7 +597,7 @@ void Entry::forceQuit() void Entry::presentWindows() { QList windows; - for (auto iter = windowInfoMap.begin(); iter != windowInfoMap.end(); iter++) { + for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) { windows.push_back(iter.key()); } @@ -603,12 +621,12 @@ void Entry::active(uint32_t timestamp) return; } - if (!current) { + if (!m_current) { qWarning() << "active: current window is nullptr"; return; } - WindowInfoBase *winInfo = current; + WindowInfoBase *winInfo = m_current; if (dock->isWaylandEnv()) { // wayland环境 if (!dock->isActiveWindow(winInfo)) { @@ -617,7 +635,7 @@ void Entry::active(uint32_t timestamp) bool showing = dock->isShowingDesktop(); if (showing || winInfo->isMinimized()) { winInfo->activate(); - } else if (windowInfoMap.size() == 1) { + } else if (m_windowInfoMap.size() == 1) { winInfo->minimize(); } else { WindowInfoBase *nextWin = findNextLeader(); @@ -645,7 +663,7 @@ void Entry::active(uint32_t timestamp) if (found) { // 激活隐藏窗口 dock->doActiveWindow(xid); - } else if (windowInfoMap.size() == 1) { + } else if (m_windowInfoMap.size() == 1) { // 窗口图标化 XCB->minimizeWindow(xid); } else if (dock->getActiveWindow() && dock->getActiveWindow()->getXid() == xid) { @@ -660,7 +678,7 @@ void Entry::active(uint32_t timestamp) XWindow Entry::getCurrentWindow() { - return currentWindow; + return m_currentWindow; } QString Entry::getDesktopFile() @@ -681,7 +699,7 @@ QString Entry::getMenu() QVector Entry::getAllowedClosedWindowIds() { QVector ret; - for (auto iter = windowInfoMap.begin(); iter != windowInfoMap.end(); iter++) { + for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) { WindowInfoBase *info = iter.value(); if (info && info->allowClose()) ret.push_back(iter.key()); @@ -692,13 +710,13 @@ QVector Entry::getAllowedClosedWindowIds() WindowInfoMap Entry::getExportWindowInfos() { - return exportWindowInfos; + return m_exportWindowInfos; } QVector Entry::getAllowedCloseWindows() { QVector ret; - for (auto iter = windowInfoMap.begin(); iter != windowInfoMap.end(); iter++) { + for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) { WindowInfoBase *info = iter.value(); if (info && info->allowClose()) { ret.push_back(info); @@ -828,7 +846,7 @@ AppMenuItem Entry::getMenuItemDock() item.text = tr("Dock"); item.action = [this](uint32_t) { qInfo() << "do MenuItem: Dock"; - requestDock(); + requestDock(true); }; item.isActive = true; @@ -841,7 +859,7 @@ AppMenuItem Entry::getMenuItemUndock() item.text = tr("Undock"); item.action = [this](uint32_t) { qInfo() << "do MenuItem: Undock"; - requestUndock(); + requestUndock(true); }; item.isActive = true; @@ -883,6 +901,3 @@ bool Entry::setPropDesktopFile(QString value) return false; } - - - diff --git a/src/modules/dock/entry.h b/src/modules/dock/entry.h index 93d42df..bd34029 100644 --- a/src/modules/dock/entry.h +++ b/src/modules/dock/entry.h @@ -41,7 +41,8 @@ public: ~Entry(); bool isValid(); - QString getId(); + QString getId() const; + QString path() const; QString getName(); void updateName(); QString getIcon(); @@ -79,8 +80,8 @@ public: void handleMenuItem(uint32_t timestamp, QString itemId); void handleDragDrop(uint32_t timestamp, QStringList files); - void requestDock(); - void requestUndock(); + void requestDock(bool dockToEnd = false); + void requestUndock(bool dockToEnd = false); void newInstance(uint32_t timestamp); void check(); void forceQuit(); @@ -119,7 +120,9 @@ private: AppMenuItem getMenuItemAllWindows(); bool killProcess(int pid); bool setPropDesktopFile(QString value); + bool isShowOnDock() const; +private: Dock *dock; AppInfo *app; AppMenu *menu; @@ -134,12 +137,11 @@ private: QString desktopFile; // Dbus属性直接放到interface上 - QMap windowInfoMap; // 该应用所有窗口 - WindowInfoMap exportWindowInfos; // 该应用导出的窗口属性 - WindowInfoBase *current; // 当前窗口 - XWindow currentWindow; //当前窗口Id - bool winIconPreferred; - QString objctPath; + QMap m_windowInfoMap; // 该应用所有窗口 + WindowInfoMap m_exportWindowInfos; // 该应用导出的窗口属性 + WindowInfoBase *m_current; // 当前窗口 + XWindow m_currentWindow; //当前窗口Id + bool m_winIconPreferred; }; #endif // ENTRY_H diff --git a/src/modules/dock/processinfo.cpp b/src/modules/dock/processinfo.cpp index 2127c99..c9708b8 100644 --- a/src/modules/dock/processinfo.cpp +++ b/src/modules/dock/processinfo.cpp @@ -109,7 +109,6 @@ ProcessInfo::ProcessInfo(std::vector &cmd) ProcessInfo::~ProcessInfo() { - } std::string ProcessInfo::getEnv(std::string key) diff --git a/src/modules/dock/waylandmanager.cpp b/src/modules/dock/waylandmanager.cpp index 5930df1..89890a8 100644 --- a/src/modules/dock/waylandmanager.cpp +++ b/src/modules/dock/waylandmanager.cpp @@ -52,20 +52,20 @@ void WaylandManager::registerWindow(const QString &objPath) QString appId = plasmaWindow->AppId(); QStringList list {"dde-dock", "dde-launcher", "dde-clipboard", "dde-osd", "dde-polkit-agent", "dde-simple-egl", "dmcs"}; - if (list.indexOf(appId)) + if (list.indexOf(appId) >= 0) return; XWindow winId = XCB->allocId(); // XCB中未发现释放XID接口 XWindow realId = plasmaWindow->WindowId(); - if (!realId) + if (realId) winId = realId; WindowInfoK *winInfo = new WindowInfoK(plasmaWindow, winId); dock->listenKWindowSignals(winInfo); insertWindow(objPath, winInfo); dock->attachOrDetachWindow(winInfo); - if (realId) { - windowInfoMap[realId] = winInfo; + if (winId) { + windowInfoMap[winId] = winInfo; } }