feat: 增加关闭最后三个未驻留应用到任务栏上图标不消失的功能

增加最近打开区域的配置,在关闭未驻留应用的时候判断是否需要移除图标,同时更新配置

Log: 完成最近打开应用的功能
Influence: 任务栏-打开多个未驻留应用,然后依次关闭,当剩下最后三个的时候,观察是否还在任务栏
Bug: https://pms.uniontech.com/bug-view-147721.html
Change-Id: Ia78e973b41acb3e87c515f3bd8479f603b3dcdfd
This commit is contained in:
donghualin 2022-08-08 05:20:42 +00:00
parent 3e5a1d4992
commit 8b89bc9092
14 changed files with 379 additions and 188 deletions

View File

@ -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"
}
}
}

View File

@ -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<QString, QString> pathDirCodeMap {
{"/usr/share/applications/", "/S@"},
{"/usr/local/share/applications/", "/L@"},
{QDir::homePath() + "/.local/share/applications", "/H@"},
{QDir::homePath() + "/.local/dock/scratch", "/D@"},
};
const QMap<QString, QString> 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";

View File

@ -64,6 +64,18 @@ void DBusHandler::listenWaylandWMSignals()
});
}
void DBusHandler::loadClientList()
{
if (!kwaylandManager)
return;
// 加载已存在的窗口
QDBusPendingReply<QVariantList> 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<WindowInfoBase *>(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);
}
/**

View File

@ -45,6 +45,7 @@ public:
/************************* KWayland/WindowManager ***************************/
void listenWaylandWMSignals();
void loadClientList();
bool wlShowingDesktop();
uint wlActiveWindow();

View File

@ -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)
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;
QString prefix(app.data(), 3);
QString appId(app.data() + 3);
QString path;
if (pathCodeDirMap.find(prefix) != pathCodeDirMap.end())
path = pathCodeDirMap[prefix] + appId + ".desktop";
// 初始化驻留应用信息和最近使用的应用的信息
auto loadApps = [ this ](const QStringList &apps, bool isDocked) {
for (const QString &app : apps) {
QString path = app;
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->setIsDocked(isDocked);
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,6 +718,9 @@ void Dock::initDockedApps()
*/
void Dock::initClientList()
{
if (isWayland) {
dbusHandler->loadClientList();
} else {
QList<XWindow> clients;
for (auto c : XCB->instance()->getClientList())
clients.push_back(c);
@ -720,6 +733,7 @@ void Dock::initClientList()
attachOrDetachWindow(static_cast<WindowInfoBase *>(winInfo));
}
}
}
/**
* @brief Dock::findWindowByXidX id获取窗口信息
@ -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)
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<QString> 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<Entry *> 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<DisplayMode>(mode);
SETTING->setDisplayMode(displayMode);
entries->setDisplayMode(displayMode);
}
/**

View File

@ -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<XWindow> getActiveWinGroup(XWindow xid);
void updateRecentApps();
private:
WindowIdentify *windowIdentify; // 窗口识别
Entries *entries; // 所有应用实例
int entriesSum; // 累计打开的应用数量

View File

@ -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<QString> &apps)
QStringList DockSettings::getDockedApps()
{
if (!m_dockSettings)
return;
qDebug() << "docked apps:" << apps;
QVariantList list;
for (auto app : apps) {
list << QVariant(app);
return loadStringList(keyDockedApps);
}
m_dockSettings->setValue(keyDockedApps, list);
void DockSettings::setDockedApps(const QStringList &apps)
{
saveStringList(keyDockedApps, apps);
}
QStringList DockSettings::getRecentApps() const
{
return loadStringList(keyRecentApp);
}
void DockSettings::setRecentApps(const QStringList &apps)
{
saveStringList(keyRecentApp, apps);
}
double DockSettings::getOpacity()

View File

@ -228,7 +228,9 @@ public:
uint getWindowSizeFashion();
void setWindowSizeFashion(uint size);
QStringList getDockedApps();
void setDockedApps(QList<QString> &apps);
void setDockedApps(const QStringList &apps);
QStringList getRecentApps() const;
void setRecentApps(const QStringList &apps);
double getOpacity();
QVector<QString> 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;
};

View File

@ -31,7 +31,7 @@ Entries::Entries(Dock *_dock)
QVector<Entry *> Entries::filterDockedEntries()
{
QVector<Entry *> ret;
for (auto &entry : items) {
for (auto &entry : m_items) {
if (entry->isValid() && entry->getIsDocked())
ret.push_back(entry);
}
@ -42,7 +42,7 @@ QVector<Entry *> 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<Entry *> Entries::unDockedEntries() const
{
QList<Entry *> 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<Entry *> 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<Entry *> unDockEntrys;
QList<Entry *> 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);
}
}
}
}

View File

@ -23,9 +23,13 @@
#define ENTRIES_H
#include "entry.h"
#include "docksettings.h"
#include <QVector>
#include <QWeakPointer>
#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<Entry *> 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<Entry *> items;
QList<Entry *> m_items;
Dock *dock;
};

View File

@ -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<DisplayMode>(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<int, QVector<WindowInfoBase*>> 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<uint> 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<XWindow> Entry::getAllowedClosedWindowIds()
{
QVector<XWindow> 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<XWindow> Entry::getAllowedClosedWindowIds()
WindowInfoMap Entry::getExportWindowInfos()
{
return exportWindowInfos;
return m_exportWindowInfos;
}
QVector<WindowInfoBase *> Entry::getAllowedCloseWindows()
{
QVector<WindowInfoBase *> 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;
}

View File

@ -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<XWindow, WindowInfoBase *> windowInfoMap; // 该应用所有窗口
WindowInfoMap exportWindowInfos; // 该应用导出的窗口属性
WindowInfoBase *current; // 当前窗口
XWindow currentWindow; //当前窗口Id
bool winIconPreferred;
QString objctPath;
QMap<XWindow, WindowInfoBase *> m_windowInfoMap; // 该应用所有窗口
WindowInfoMap m_exportWindowInfos; // 该应用导出的窗口属性
WindowInfoBase *m_current; // 当前窗口
XWindow m_currentWindow; //当前窗口Id
bool m_winIconPreferred;
};
#endif // ENTRY_H

View File

@ -109,7 +109,6 @@ ProcessInfo::ProcessInfo(std::vector<std::string> &cmd)
ProcessInfo::~ProcessInfo()
{
}
std::string ProcessInfo::getEnv(std::string key)

View File

@ -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;
}
}