feat: 实现Apps服务、Launcher服务、Dock服务
*重写Apps服务,新服务分为org.deepin.daemon.DFWatcher1和org.deepin.daemon.ALRecorder1两个服务 *重写Launcher服务, 新服务名为org.deepin.dde.daemon.Launcher1 *重写Dock服务, 新服务名为org.deepin.dde.daemon.Dock1 *重写部分go-lib接口,保存在src/lib目录, 后续从项目中提出统一存放至开发库 *使用XCB库实现与XServer交互,存放在src/lib目录 *放弃依赖dde-qt-dbus-factory包, 将xml文件生成的静态编译代码存放在frameworkdbus目录 Log: 实现Apps服务、Launcher服务、Dock服务 Task: https://pms.uniontech.com/task-view-109315.html Influence: 无 Change-Id: Ia9676060bfe81ce8d02c48972cc3d3cbaf665a31
This commit is contained in:
257
src/modules/apps/alrecorder.cpp
Normal file
257
src/modules/apps/alrecorder.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "alrecorder.h"
|
||||
#include "dfwatcher.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusError>
|
||||
#include <QtDebug>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
const QString userAppsCfgDir = QDir::homePath() + "/.config/deepin/dde-daemon/apps/";
|
||||
|
||||
AlRecorder::AlRecorder(DFWatcher *_watcher, QObject *parent)
|
||||
: QObject (parent)
|
||||
, watcher(_watcher)
|
||||
, mutex(QMutex(QMutex::NonRecursive))
|
||||
{
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
if (!con.registerService("org.deepin.daemon.AlRecorder1"))
|
||||
{
|
||||
qWarning() << "register service AlRecorder1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!con.registerObject("/org/deepin/daemon/AlRecorder1", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals))
|
||||
{
|
||||
qWarning() << "register object AlRecorder1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(watcher, &DFWatcher::Event, this, &AlRecorder::onDFChanged, Qt::QueuedConnection);
|
||||
Q_EMIT ServiceRestarted();
|
||||
}
|
||||
|
||||
AlRecorder::~AlRecorder()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject("/org/deepin/daemon/AlRecorder1");
|
||||
}
|
||||
|
||||
// 获取未启动应用列表
|
||||
QMap<QString, QStringList> AlRecorder::GetNew()
|
||||
{
|
||||
QMap<QString, QStringList> ret;
|
||||
QMutexLocker locker(&mutex);
|
||||
for (auto is = subRecoders.begin(); is != subRecoders.end(); is++) {
|
||||
QStringList apps;
|
||||
for (auto il = is.value().launchedMap.begin(); il != is.value().launchedMap.end(); il++) {
|
||||
if (!il.value()) // 未启动应用
|
||||
apps.push_back(il.key());
|
||||
}
|
||||
|
||||
if (apps.size() > 0)
|
||||
ret[is.key()] = apps;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 标记应用已启动状态
|
||||
void AlRecorder::MarkLaunched(const QString &filePath)
|
||||
{
|
||||
if (!filePath.endsWith(".desktop"))
|
||||
return;
|
||||
|
||||
QFileInfo info;
|
||||
QMutexLocker locker(&mutex);
|
||||
for (auto sri = subRecoders.begin(); sri != subRecoders.end(); sri++) {
|
||||
if (!filePath.contains(sri.key()))
|
||||
continue;
|
||||
|
||||
info.setFile(filePath);
|
||||
QString name = info.baseName();
|
||||
for (auto li = sri.value().launchedMap.begin(); li != sri.value().launchedMap.end(); li++) {
|
||||
if (li.key() == name && !li.value()) {
|
||||
li.value() = true;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据filePath匹配到唯一应用
|
||||
end:
|
||||
if (info.isDir()) {
|
||||
saveStatusFile(info.absolutePath() + "/");
|
||||
Q_EMIT Launched(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
// 记录Launcher服务卸载应用信息, 终端卸载不会调用该函数, desktopFiles为绝对路径
|
||||
void AlRecorder::UninstallHints(const QStringList &desktopFiles)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
for (auto desktop : desktopFiles) {
|
||||
for (auto sri = subRecoders.begin(); sri != subRecoders.end(); sri++) {
|
||||
if (!desktop.contains(sri.key()))
|
||||
continue;
|
||||
|
||||
QFileInfo info(desktop);
|
||||
sri.value().uninstallMap[info.baseName()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监控目录
|
||||
void AlRecorder::WatchDirs(const QStringList &dataDirs)
|
||||
{
|
||||
for (auto dirPath : dataDirs) {
|
||||
if (subRecoders.contains(dirPath))
|
||||
continue;
|
||||
|
||||
QDir dir(dirPath);
|
||||
QStringList files = dir.entryList(QDir::Files);
|
||||
for (auto &file : files)
|
||||
file = dirPath + file;
|
||||
|
||||
// 监听目录和文件
|
||||
watcher->addDir(dirPath);
|
||||
if (files.size() > 0)
|
||||
watcher->addPaths(files);
|
||||
|
||||
// 初始化对应目录和应用信息
|
||||
initSubRecoder(dirPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化应用目录记录
|
||||
void AlRecorder::initSubRecoder(const QString &dirPath)
|
||||
{
|
||||
subRecorder sub;
|
||||
QByteArray encryText = QCryptographicHash::hash(dirPath.toLatin1(), QCryptographicHash::Md5);
|
||||
QString statusFile = userAppsCfgDir + "launched-" + encryText.toHex() + ".csv";
|
||||
|
||||
// 读取App状态记录
|
||||
QMap<QString, bool> launchedApp;
|
||||
QFile file(statusFile);
|
||||
if (file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||
while (!file.atEnd()){
|
||||
QString line(file.readLine());
|
||||
QStringList strs = line.split(",");
|
||||
if (strs.length() != 2)
|
||||
continue;
|
||||
|
||||
if (strs[1].size() > 0 && strs[1][0] == 't')
|
||||
launchedApp[strs[0]] = true;
|
||||
else
|
||||
launchedApp[strs[0]] = false;
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
// 读取app desktop
|
||||
QDir dir(dirPath);
|
||||
QStringList files = dir.entryList(QDir::Files);
|
||||
QStringList apps;
|
||||
for (QString file : files) {
|
||||
if (!file.endsWith(".desktop"))
|
||||
continue;
|
||||
|
||||
int index = file.lastIndexOf(".");
|
||||
file.truncate(index);
|
||||
qInfo() << "entry =" << file;
|
||||
apps.push_back(file);
|
||||
}
|
||||
|
||||
// fallback 都打开过
|
||||
for (auto app : apps)
|
||||
launchedApp[app] = true;
|
||||
}
|
||||
|
||||
sub.statusFile = statusFile;
|
||||
sub.launchedMap = launchedApp;
|
||||
subRecoders[dirPath] = sub;
|
||||
}
|
||||
|
||||
void AlRecorder::onDFChanged(const QString &filePath, uint32_t op)
|
||||
{
|
||||
QFileInfo info(filePath);
|
||||
QString dirPath = info.absolutePath() + "/";
|
||||
QString name = info.baseName();
|
||||
subRecorder &sub = subRecoders[dirPath];
|
||||
QMap<QString, bool> &launchedMap = sub.launchedMap;
|
||||
|
||||
// 过滤文件, 仅保留.desktop类型
|
||||
if (!filePath.endsWith(".desktop"))
|
||||
return;
|
||||
|
||||
switch (op) {
|
||||
case DFWatcher::event::Add:
|
||||
qInfo() << "AlRecorder: Add " << filePath;
|
||||
if (!launchedMap.contains(name)) {
|
||||
bool launched = false;
|
||||
if (sub.removedLaunchedMap.find(name) != sub.removedLaunchedMap.end()) {
|
||||
launched = sub.removedLaunchedMap[name];
|
||||
sub.removedLaunchedMap.remove(name);
|
||||
}
|
||||
launchedMap[name] = launched;
|
||||
}
|
||||
sub.uninstallMap.remove(name);
|
||||
saveStatusFile(dirPath); // 刷新状态文件
|
||||
break;
|
||||
case DFWatcher::event::Del:
|
||||
qInfo() << "AlRecorder: Del" << filePath;
|
||||
if (launchedMap.contains(name)) {
|
||||
if (!sub.uninstallMap.contains(name))
|
||||
sub.removedLaunchedMap[name] = launchedMap[name];
|
||||
|
||||
launchedMap.remove(name);
|
||||
}
|
||||
saveStatusFile(dirPath); //刷新状态文件
|
||||
break;
|
||||
case DFWatcher::event::Mod:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AlRecorder::saveStatusFile(const QString &dirPath)
|
||||
{
|
||||
subRecorder sub = subRecoders[dirPath];
|
||||
QString tmpFile = sub.statusFile + "_tmp";
|
||||
QFile fp(tmpFile);
|
||||
bool ok = false;
|
||||
qInfo() << "saveStatusFile=" << dirPath << "create file=" << tmpFile;
|
||||
if (fp.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||
QTextStream out(&fp);
|
||||
out << "# " << dirPath << endl;
|
||||
for (auto rl = sub.launchedMap.begin(); rl != sub.launchedMap.end(); rl++) {
|
||||
out << rl.key() << "," << ((rl.value() == true) ? "t" : "f") << endl;
|
||||
}
|
||||
ok = true;
|
||||
fp.close();
|
||||
}
|
||||
|
||||
// 覆盖原文件
|
||||
QFile::remove(sub.statusFile);
|
||||
QFile::rename(tmpFile, sub.statusFile);
|
||||
Q_EMIT StatusSaved(dirPath, sub.statusFile, ok);
|
||||
}
|
||||
|
71
src/modules/apps/alrecorder.h
Normal file
71
src/modules/apps/alrecorder.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ALRECORDER_H
|
||||
#define ALRECORDER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
||||
class DFWatcher;
|
||||
|
||||
// 记录应用状态信息
|
||||
class AlRecorder: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.daemon.AlRecorder1")
|
||||
|
||||
public:
|
||||
struct subRecorder {
|
||||
QString statusFile; // 应用目录状态文件
|
||||
QMap<QString, bool> launchedMap; // 应用启动记录
|
||||
QMap<QString, bool> removedLaunchedMap; // desktop文件卸载记录
|
||||
QMap<QString, bool> uninstallMap; // 记录应用将被卸载状态
|
||||
};
|
||||
|
||||
AlRecorder(DFWatcher *_watcher, QObject *parent = nullptr);
|
||||
~AlRecorder();
|
||||
|
||||
Q_SIGNALS:
|
||||
void Launched(const QString &file);
|
||||
void StatusSaved(const QString &root, const QString &file, bool ok);
|
||||
void ServiceRestarted();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onDFChanged(const QString &filePath, uint32_t op);
|
||||
|
||||
public Q_SLOTS:
|
||||
QMap<QString, QStringList> GetNew();
|
||||
void MarkLaunched(const QString &filePath);
|
||||
void UninstallHints(const QStringList &desktopFiles);
|
||||
void WatchDirs(const QStringList &dataDirs);
|
||||
|
||||
private:
|
||||
void initSubRecoder(const QString &dirPath);
|
||||
void saveStatusFile(const QString &dirPath);
|
||||
|
||||
QMap<QString,subRecorder> subRecoders; // 记录不同应用目录的文件状态
|
||||
DFWatcher *watcher;
|
||||
QMutex mutex;
|
||||
};
|
||||
|
||||
#endif // ALRECODER_H
|
46
src/modules/apps/appmanager.cpp
Normal file
46
src/modules/apps/appmanager.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "appmanager.h"
|
||||
#include "dfwatcher.h"
|
||||
#include "alrecorder.h"
|
||||
#include "basedir.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
AppManager::AppManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, watcher(new DFWatcher(this))
|
||||
, recorder(new AlRecorder(watcher, this))
|
||||
{
|
||||
QStringList dataDirs;
|
||||
dataDirs << BaseDir::userAppDir().c_str();
|
||||
for (auto &dir : BaseDir::sysAppDirs())
|
||||
dataDirs << dir.c_str();
|
||||
|
||||
recorder->WatchDirs(dataDirs); // 监控应用desktop
|
||||
}
|
||||
|
||||
AppManager::~AppManager()
|
||||
{
|
||||
|
||||
}
|
41
src/modules/apps/appmanager.h
Normal file
41
src/modules/apps/appmanager.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPMANAGER_H
|
||||
#define APPMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class DFWatcher;
|
||||
class AlRecorder;
|
||||
class AppManager: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AppManager(QObject *parent = nullptr);
|
||||
~AppManager();
|
||||
|
||||
private:
|
||||
DFWatcher *watcher;
|
||||
AlRecorder *recorder;
|
||||
};
|
||||
|
||||
#endif // APPMANAGER_H
|
132
src/modules/apps/dfwatcher.cpp
Normal file
132
src/modules/apps/dfwatcher.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dfwatcher.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusError>
|
||||
#include <QtDebug>
|
||||
|
||||
const QString dfSuffix = ".desktop";
|
||||
const QString configSuffix = ".json";
|
||||
|
||||
DFWatcher::DFWatcher(QObject *parent)
|
||||
: QObject (parent)
|
||||
, watcher(new QFileSystemWatcher(this))
|
||||
{
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
if (!con.registerService("org.deepin.daemon.DFWatcher1"))
|
||||
{
|
||||
qInfo() << "register service app1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!con.registerObject("/org/deepin/daemon/DFWatcher1", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals))
|
||||
{
|
||||
qInfo() << "register object DFWatcher error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(watcher, &QFileSystemWatcher::fileChanged, this, &DFWatcher::fileUpdated, Qt::QueuedConnection);
|
||||
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &DFWatcher::directoryUpdated, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
DFWatcher::~DFWatcher()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject("/org/deepin/daemon/DFWatcher1");
|
||||
}
|
||||
|
||||
void DFWatcher::addDir(const QString &path)
|
||||
{
|
||||
// 记录当前目录内容
|
||||
qInfo() << "addDir :" << path;
|
||||
const QDir dir(path);
|
||||
dirContentMap[path] = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
|
||||
|
||||
watcher->addPath(path);
|
||||
}
|
||||
|
||||
void DFWatcher::addPaths(const QStringList &paths)
|
||||
{
|
||||
watcher->addPaths(paths);
|
||||
}
|
||||
|
||||
QStringList DFWatcher::files()
|
||||
{
|
||||
return watcher->files();
|
||||
}
|
||||
|
||||
void DFWatcher::removePath(const QString &filepath)
|
||||
{
|
||||
watcher->removePath(filepath);
|
||||
}
|
||||
|
||||
void DFWatcher::fileUpdated(const QString &filePath)
|
||||
{
|
||||
qInfo() << "event: modify filepath=" << filePath;
|
||||
if (filePath.endsWith(dfSuffix) || filePath.endsWith(configSuffix))
|
||||
Q_EMIT Event(filePath, int(event::Mod));
|
||||
}
|
||||
|
||||
void DFWatcher::directoryUpdated(const QString &dirPath)
|
||||
{
|
||||
QStringList recoderedContent = dirContentMap[dirPath];
|
||||
|
||||
const QDir dir(dirPath);
|
||||
QStringList newEntries = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
|
||||
|
||||
QSet<QString> newDirSet = QSet<QString>::fromList(newEntries);
|
||||
QSet<QString> currentDirSet = QSet<QString>::fromList(recoderedContent);
|
||||
|
||||
// 添加的文件
|
||||
QSet<QString> newFiles = newDirSet - currentDirSet;
|
||||
QStringList newFile = newFiles.toList();
|
||||
|
||||
// 移除的文件
|
||||
QSet<QString> deletedFiles = currentDirSet - newDirSet;
|
||||
QStringList deleteFile = deletedFiles.toList();
|
||||
|
||||
// 更新目录记录
|
||||
dirContentMap[dirPath] = newEntries;
|
||||
|
||||
// 新增文件
|
||||
if (newFile.size() > 0) {
|
||||
for (auto &file : newFile) {
|
||||
//qInfo() << "event: add filepath=" << file;
|
||||
if (file.endsWith(dfSuffix)) {
|
||||
Q_EMIT Event(dirPath + file, event::Add);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
if (deleteFile.size() > 0) {
|
||||
for (auto &file : deleteFile) {
|
||||
//qInfo() << "event: del filepath=" << file;
|
||||
if (file.endsWith(dfSuffix)) {
|
||||
Q_EMIT Event(dirPath + file, event::Del);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
59
src/modules/apps/dfwatcher.h
Normal file
59
src/modules/apps/dfwatcher.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DFWATCHER_H
|
||||
#define DFWATCHER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
class DFWatcher: public QObject {
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.daemon.DFWatcher1")
|
||||
|
||||
public:
|
||||
enum event{
|
||||
Add,
|
||||
Del,
|
||||
Mod,
|
||||
};
|
||||
|
||||
explicit DFWatcher(QObject *parent = nullptr);
|
||||
~DFWatcher();
|
||||
|
||||
void addDir(const QString & path);
|
||||
void addPaths(const QStringList &paths);
|
||||
QStringList files();
|
||||
void removePath(const QString &filepath);
|
||||
Q_SIGNALS:
|
||||
void Event(const QString &filepath, int op);
|
||||
|
||||
private Q_SLOTS:
|
||||
void fileUpdated(const QString &filePath);
|
||||
void directoryUpdated(const QString &dirPath);
|
||||
|
||||
private:
|
||||
QFileSystemWatcher *watcher;
|
||||
QMap<QString, QStringList> dirContentMap; // 监控的目录内容列表
|
||||
};
|
||||
|
||||
#endif
|
75
src/modules/dock/appinfo.cpp
Normal file
75
src/modules/dock/appinfo.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "appinfo.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
AppInfo::AppInfo(DesktopInfo &info)
|
||||
: isValid(true)
|
||||
{
|
||||
init(info);
|
||||
}
|
||||
|
||||
AppInfo::AppInfo(const QString &_fileName)
|
||||
: isValid(true)
|
||||
{
|
||||
DesktopInfo info(_fileName.toStdString());
|
||||
init(info);
|
||||
}
|
||||
|
||||
void AppInfo::init(DesktopInfo &info)
|
||||
{
|
||||
if (!info.isValidDesktop()) {
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string xDeepinVendor= info.kf.getStr(MainSection, "X-Deepin-Vendor");
|
||||
if (xDeepinVendor == "deepin") {
|
||||
name = info.getGenericName().c_str();
|
||||
if (name.isEmpty())
|
||||
name = info.getName().c_str();
|
||||
} else {
|
||||
name = info.getName().c_str();
|
||||
}
|
||||
|
||||
innerId = genInnerIdWithDesktopInfo(info);
|
||||
fileName = info.getFileName().c_str();
|
||||
id = info.getId().c_str();
|
||||
icon = info.getIcon().c_str();
|
||||
installed = info.isInstalled();
|
||||
for (const auto & action : info.getActions()) {
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
|
||||
QString AppInfo::genInnerIdWithDesktopInfo(DesktopInfo &info)
|
||||
{
|
||||
std::string cmdline = info.getCommandLine();
|
||||
QByteArray encryText = QCryptographicHash::hash(QString(cmdline.c_str()).toLatin1(), QCryptographicHash::Md5);
|
||||
QString innerId = desktopHashPrefix + encryText.toHex();
|
||||
qInfo() << "app " << info.getId().c_str() << " generate innerId :" << innerId;
|
||||
return innerId;
|
||||
}
|
62
src/modules/dock/appinfo.h
Normal file
62
src/modules/dock/appinfo.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPINFO_H
|
||||
#define APPINFO_H
|
||||
|
||||
#include "desktopinfo.h"
|
||||
|
||||
#include<QVector>
|
||||
|
||||
// 应用信息类
|
||||
class AppInfo
|
||||
{
|
||||
public:
|
||||
explicit AppInfo(DesktopInfo &info);
|
||||
explicit AppInfo(const QString &_fileName);
|
||||
|
||||
void init(DesktopInfo &info);
|
||||
QString getFileName() {return fileName;}
|
||||
QString getIcon() {return icon;}
|
||||
QString getId() {return id;}
|
||||
QString getInnerId() {return innerId;}
|
||||
QString getName() {return name;}
|
||||
QVector<DesktopAction> getActions() {return actions;}
|
||||
QString getIdentifyMethod() {return identifyMethod;}
|
||||
void setIdentifyMethod(QString method) {identifyMethod = method;}
|
||||
bool isInstalled() {return installed;}
|
||||
bool isValidApp() {return isValid;}
|
||||
|
||||
private:
|
||||
QString genInnerIdWithDesktopInfo(DesktopInfo &info);
|
||||
|
||||
QString fileName;
|
||||
QString id;
|
||||
QString icon;
|
||||
QString identifyMethod;
|
||||
QString innerId;
|
||||
QString name;
|
||||
QVector<DesktopAction> actions;
|
||||
bool installed;
|
||||
bool isValid;
|
||||
};
|
||||
|
||||
#endif // APPINFO_H
|
91
src/modules/dock/appmenu.cpp
Normal file
91
src/modules/dock/appmenu.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "appmenu.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
AppMenu::AppMenu()
|
||||
: checkableMenu(false)
|
||||
, singleCheck(false)
|
||||
, itemcount(0)
|
||||
, dirty(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 增加菜单选项
|
||||
void AppMenu::appendItem(AppMenuItem item)
|
||||
{
|
||||
if (!item.text.isEmpty()) {
|
||||
item.id = allocateId();
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
void AppMenu::handleAction(uint32_t timestamp, QString itemId)
|
||||
{
|
||||
for (auto &item : items) {
|
||||
if (item.id == itemId) {
|
||||
item.action(timestamp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppMenu::setDirtyStatus(bool isDirty)
|
||||
{
|
||||
dirty = isDirty;
|
||||
}
|
||||
|
||||
QString AppMenu::getMenuJsonStr()
|
||||
{
|
||||
QJsonObject obj;
|
||||
QJsonArray array;
|
||||
for (auto item : items) {
|
||||
QJsonObject objItem;
|
||||
objItem["itemId"] = item.id;
|
||||
objItem["itemText"] = item.text;
|
||||
objItem["isActive"] = item.isActive;
|
||||
objItem["isCheckable"] = item.isCheckable;
|
||||
objItem["checked"] = item.checked;
|
||||
objItem["itemIcon"] = item.icon;
|
||||
objItem["itemIconHover"] = item.iconHover;
|
||||
objItem["itemIconInactive"] = item.iconInactive;
|
||||
objItem["showCheckMark"] = item.showCheckMark;
|
||||
objItem["itemSubMenu"] = item.subMenu ? item.subMenu->getMenuJsonStr() : "";
|
||||
array.push_back(QJsonValue(objItem));
|
||||
}
|
||||
obj["items"] = QJsonValue(array);
|
||||
obj["checkableMenu"] = checkableMenu;
|
||||
obj["singleCheck"] = singleCheck;
|
||||
|
||||
QString ret = QJsonDocument(obj).toJson();
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString AppMenu::allocateId()
|
||||
{
|
||||
return QString::number(itemcount++);
|
||||
}
|
||||
|
||||
|
77
src/modules/dock/appmenu.h
Normal file
77
src/modules/dock/appmenu.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPMENU_H
|
||||
#define APPMENU_H
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
#include <QVector>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
typedef std::function<void(uint32_t)> AppMenuAction;
|
||||
|
||||
class AppMenu;
|
||||
|
||||
// 应用菜单选项
|
||||
struct AppMenuItem {
|
||||
QString id;
|
||||
QString text;
|
||||
bool isActive;
|
||||
QString isCheckable;
|
||||
QString checked;
|
||||
QString icon;
|
||||
QString iconHover;
|
||||
QString iconInactive;
|
||||
QString showCheckMark;
|
||||
std::shared_ptr<AppMenu> subMenu;
|
||||
|
||||
int hint;
|
||||
AppMenuAction action;
|
||||
};
|
||||
|
||||
|
||||
// 应用菜单类
|
||||
class AppMenu
|
||||
{
|
||||
public:
|
||||
AppMenu();
|
||||
|
||||
void appendItem(AppMenuItem item);
|
||||
void handleAction(uint32_t timestamp, QString itemId);
|
||||
void setDirtyStatus(bool isDirty);
|
||||
QString getMenuJsonStr();
|
||||
|
||||
private:
|
||||
QString allocateId();
|
||||
|
||||
QVector<AppMenuItem> items; // json:"items"
|
||||
bool checkableMenu; // json:"checkableMenu"
|
||||
bool singleCheck; // json:"singleCheck"
|
||||
|
||||
int itemcount;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
#endif // APPMENU_H
|
103
src/modules/dock/common.h
Normal file
103
src/modules/dock/common.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QDir>
|
||||
|
||||
const QString configDock = "com.deepin.dde.dock";
|
||||
const QString configAppearance = "com.deepin.dde.appearance";
|
||||
const QString keyHideMode = "Hide_Mode";
|
||||
const QString keyDisplayMode = "Display_Mode";
|
||||
const QString keyPosition = "Position";
|
||||
const QString keyIconSize = "Icon_Size";
|
||||
const QString keyDockedApps = "Docked_Apps";
|
||||
const QString keyShowTimeout = "Show_Timeout";
|
||||
const QString keyHideTimeout = "Hide_Timeout";
|
||||
const QString keyWindowSizeFashion = "Window_Size_Fashion";
|
||||
const QString keyWindowSizeEfficient = "Window_Size_Efficient";
|
||||
const QString keyWinIconPreferredApps = "Win_Icon_Preferred_Apps";
|
||||
const QString keyOpacity = "Opacity";
|
||||
const QString keyPluginSettings = "Plugin_Settings";
|
||||
const QString keyForceQuitApp = "Force_Quit_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";
|
||||
const QString dbusPath = "/org/deepin/dde/daemon/Dock1";
|
||||
const QString dbusInterface = dbusService;
|
||||
|
||||
const QString windowPatternsFile = "/usr/share/dde/data/window_patterns.json";
|
||||
const QString desktopHashPrefix = "d:";
|
||||
const QString windowHashPrefix = "w:";
|
||||
|
||||
const QString entryDBusObjPathPrefix = dbusPath + "/entries/";
|
||||
const QString entryDBusInterface = dbusInterface + ".Entry";
|
||||
|
||||
// 驻留应用desktop file模板
|
||||
const QString dockedItemTemplate = R"([Desktop Entry]
|
||||
Name=%1
|
||||
Exec=%2
|
||||
Icon=%3
|
||||
Type=Application
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
)";
|
||||
|
||||
const QString frontendWindowWmClass = "dde-dock";
|
||||
const int configureNotifyDelay = 100;
|
||||
const int smartHideTimerDelay = 400;
|
||||
|
||||
const int bestIconSize = 48;
|
||||
const int menuItemHintShowAllWindows = 1;
|
||||
|
||||
const int MotifHintFunctions = 1;
|
||||
const int MotifHintDecorations = 2;
|
||||
const int MotifHintInputMode = 4;
|
||||
const int MotifHintStatus = 8;
|
||||
|
||||
const int MotifFunctionNone = 0;
|
||||
const int MotifFunctionAll = 1;
|
||||
const int MotifFunctionResize = 2;
|
||||
const int MotifFunctionMove = 4;
|
||||
const int MotifFunctionMinimize = 8;
|
||||
const int MotifFunctionMaximize = 16;
|
||||
const int MotifFunctionClose = 32;
|
||||
|
||||
const QString ddeLauncherWMClass = "dde-launcher";
|
||||
#endif // COMMON_H
|
229
src/modules/dock/dbusadaptordock.cpp
Normal file
229
src/modules/dock/dbusadaptordock.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dbusadaptordock.h"
|
||||
|
||||
DBusAdaptorDock::DBusAdaptorDock(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
|
||||
Dock *dock = static_cast<Dock *>(QObject::parent());
|
||||
if (dock) {
|
||||
connect(dock, &Dock::serviceRestarted, this, [&] {
|
||||
Q_EMIT ServiceRestarted();});
|
||||
connect(dock, &Dock::entryAdded, this, [&](QString entryObjPath, int32_t index){
|
||||
Q_EMIT EntryAdded(QDBusObjectPath(entryObjPath), index);});
|
||||
connect(dock, &Dock::entryRemoved, this, &DBusAdaptorDock::EntryRemoved);
|
||||
connect(dock, &Dock::hideStateChanged, this, &DBusAdaptorDock::HideStateChanged);
|
||||
connect(dock, &Dock::frontendWindowRectChanged, this, &DBusAdaptorDock::FrontendWindowRectChanged);
|
||||
}
|
||||
}
|
||||
|
||||
DBusAdaptorDock::~DBusAdaptorDock()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
int DBusAdaptorDock::displayMode() const
|
||||
{
|
||||
return parent()->getDisplayMode();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setDisplayMode(int value)
|
||||
{
|
||||
if (displayMode() != value) {
|
||||
parent()->setDisplayMode(value);
|
||||
Q_EMIT DisplayModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DBusAdaptorDock::dockedApps() const
|
||||
{
|
||||
return parent()->getDockedApps();
|
||||
}
|
||||
|
||||
QList<QDBusObjectPath> DBusAdaptorDock::entries() const
|
||||
{
|
||||
QList<QDBusObjectPath> ret;
|
||||
for (auto path : parent()->getEntryPaths())
|
||||
ret.push_back(QDBusObjectPath(path));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DBusAdaptorDock::hideMode() const
|
||||
{
|
||||
return int(parent()->getHideMode());
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setHideMode(int value)
|
||||
{
|
||||
if (hideMode() != value) {
|
||||
parent()->setHideMode(HideMode(value));
|
||||
Q_EMIT HideModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int DBusAdaptorDock::hideState() const
|
||||
{
|
||||
return int(parent()->getHideState());
|
||||
}
|
||||
|
||||
uint DBusAdaptorDock::hideTimeout() const
|
||||
{
|
||||
return parent()->getHideTimeout();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setHideTimeout(uint value)
|
||||
{
|
||||
if (hideTimeout() != value) {
|
||||
parent()->setHideTimeout(value);
|
||||
Q_EMIT HideTimeoutChanged();
|
||||
}
|
||||
}
|
||||
|
||||
uint DBusAdaptorDock::windowSizeEfficient() const
|
||||
{
|
||||
return parent()->getWindowSizeEfficient();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setWindowSizeEfficient(uint value)
|
||||
{
|
||||
if (windowSizeEfficient() != value) {
|
||||
parent()->setWindowSizeEfficient(value);
|
||||
Q_EMIT WindowSizeEfficientChanged();
|
||||
}
|
||||
}
|
||||
|
||||
uint DBusAdaptorDock::windowSizeFashion() const
|
||||
{
|
||||
return parent()->getWindowSizeFashion();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setWindowSizeFashion(uint value)
|
||||
{
|
||||
if (windowSizeFashion() != value) {
|
||||
parent()->setWindowSizeFashion(value);
|
||||
Q_EMIT WindowSizeFashionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QRect DBusAdaptorDock::frontendWindowRect() const
|
||||
{
|
||||
return parent()->getFrontendWindowRect();
|
||||
}
|
||||
|
||||
double DBusAdaptorDock::opacity() const
|
||||
{
|
||||
return parent()->getOpacity();
|
||||
}
|
||||
|
||||
uint DBusAdaptorDock::iconSize() const
|
||||
{
|
||||
return parent()->getIconSize();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setIconSize(uint value)
|
||||
{
|
||||
if (iconSize() != value) {
|
||||
parent()->setIconSize(value);
|
||||
Q_EMIT IconSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int DBusAdaptorDock::position() const
|
||||
{
|
||||
return parent()->getPosition();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setPosition(int value)
|
||||
{
|
||||
if (position() != value) {
|
||||
parent()->setPosition(value);
|
||||
Q_EMIT PositionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
uint DBusAdaptorDock::showTimeout() const
|
||||
{
|
||||
return parent()->getShowTimeout();
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::setShowTimeout(uint value)
|
||||
{
|
||||
if (showTimeout() != value) {
|
||||
parent()->setShowTimeout(value);
|
||||
Q_EMIT ShowTimeoutChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Dock *DBusAdaptorDock::parent() const
|
||||
{
|
||||
return static_cast<Dock *>(QObject::parent());
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::CloseWindow(uint win)
|
||||
{
|
||||
parent()->closeWindow(win);
|
||||
}
|
||||
|
||||
// for debug
|
||||
QStringList DBusAdaptorDock::GetEntryIDs()
|
||||
{
|
||||
return parent()->getEntryIDs();
|
||||
}
|
||||
|
||||
bool DBusAdaptorDock::IsDocked(const QString &desktopFile)
|
||||
{
|
||||
return parent()->isDocked(desktopFile);
|
||||
}
|
||||
|
||||
bool DBusAdaptorDock::IsOnDock(const QString &desktopFile)
|
||||
{
|
||||
return parent()->isOnDock(desktopFile);
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::MoveEntry(int index, int newIndex)
|
||||
{
|
||||
parent()->moveEntry(index, newIndex);
|
||||
}
|
||||
|
||||
QString DBusAdaptorDock::QueryWindowIdentifyMethod(uint win)
|
||||
{
|
||||
return parent()->queryWindowIdentifyMethod(win);
|
||||
}
|
||||
|
||||
bool DBusAdaptorDock::RequestDock(const QString &desktopFile, int index)
|
||||
{
|
||||
return parent()->requestDock(desktopFile, index);
|
||||
}
|
||||
|
||||
bool DBusAdaptorDock::RequestUndock(const QString &desktopFile)
|
||||
{
|
||||
return parent()->requestUndock(desktopFile);
|
||||
}
|
||||
|
||||
void DBusAdaptorDock::SetFrontendWindowRect(int x, int y, uint width, uint height)
|
||||
{
|
||||
parent()->setFrontendWindowRect(x, y, width, height);
|
||||
}
|
||||
|
193
src/modules/dock/dbusadaptordock.h
Normal file
193
src/modules/dock/dbusadaptordock.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DBUSADAPTORDOCK_H
|
||||
#define DBUSADAPTORDOCK_H
|
||||
|
||||
#include "dock.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QRect>
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.deepin.dde.daemon.Dock1
|
||||
*/
|
||||
class DBusAdaptorDock: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Dock1")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.deepin.dde.daemon.Dock1\">\n"
|
||||
" <method name=\"CloseWindow\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetEntryIDs\">\n"
|
||||
" <arg direction=\"out\" type=\"as\" name=\"list\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"IsDocked\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"IsOnDock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"MoveEntry\">\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"newIndex\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"QueryWindowIdentifyMethod\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
|
||||
" <arg direction=\"out\" type=\"s\" name=\"identifyMethod\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestDock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestUndock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFrontendWindowRect\">\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"width\"/>\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"height\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"ServiceRestarted\"/>\n"
|
||||
" <signal name=\"EntryAdded\">\n"
|
||||
" <arg type=\"o\" name=\"path\"/>\n"
|
||||
" <arg type=\"i\" name=\"index\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"EntryRemoved\">\n"
|
||||
" <arg type=\"s\" name=\"entryId\"/>\n"
|
||||
" </signal>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"ShowTimeout\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"HideTimeout\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeEfficient\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeFashion\"/>\n"
|
||||
" <property access=\"read\" type=\"iiii\" name=\"FrontendWindowRect\"/>\n"
|
||||
" <property access=\"read\" type=\"d\" name=\"Opacity\"/>\n"
|
||||
" <property access=\"read\" type=\"ao\" name=\"Entries\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"HideMode\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"DisplayMode\"/>\n"
|
||||
" <property access=\"read\" type=\"i\" name=\"HideState\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"Position\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"IconSize\"/>\n"
|
||||
" <property access=\"read\" type=\"as\" name=\"DockedApps\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
public:
|
||||
DBusAdaptorDock(QObject *parent);
|
||||
virtual ~DBusAdaptorDock();
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
|
||||
int displayMode() const;
|
||||
void setDisplayMode(int value);
|
||||
|
||||
Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged)
|
||||
QStringList dockedApps() const;
|
||||
|
||||
Q_PROPERTY(QList<QDBusObjectPath> Entries READ entries NOTIFY EntriesChanged)
|
||||
QList<QDBusObjectPath> entries() const;
|
||||
|
||||
Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged)
|
||||
int hideMode() const;
|
||||
void setHideMode(int value);
|
||||
|
||||
Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged)
|
||||
int hideState() const;
|
||||
|
||||
Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged)
|
||||
uint hideTimeout() const;
|
||||
void setHideTimeout(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged)
|
||||
uint windowSizeEfficient() const;
|
||||
void setWindowSizeEfficient(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged)
|
||||
uint windowSizeFashion() const;
|
||||
void setWindowSizeFashion(uint value);
|
||||
|
||||
Q_PROPERTY(QRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged)
|
||||
QRect frontendWindowRect() const;
|
||||
|
||||
Q_PROPERTY(double Opacity READ opacity NOTIFY OpacityChanged)
|
||||
double opacity() const;
|
||||
|
||||
Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged)
|
||||
uint iconSize() const;
|
||||
void setIconSize(uint value);
|
||||
|
||||
Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged)
|
||||
int position() const;
|
||||
void setPosition(int value);
|
||||
|
||||
Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged)
|
||||
uint showTimeout() const;
|
||||
void setShowTimeout(uint value);
|
||||
|
||||
Dock *parent() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
void CloseWindow(uint win);
|
||||
QStringList GetEntryIDs();
|
||||
bool IsDocked(const QString &desktopFile);
|
||||
bool IsOnDock(const QString &desktopFile);
|
||||
void MoveEntry(int index, int newIndex);
|
||||
QString QueryWindowIdentifyMethod(uint win);
|
||||
bool RequestDock(const QString &desktopFile, int index);
|
||||
bool RequestUndock(const QString &desktopFile);
|
||||
void SetFrontendWindowRect(int x, int y, uint width, uint height);
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void ServiceRestarted();
|
||||
void EntryAdded(const QDBusObjectPath &path, int index);
|
||||
void EntryRemoved(const QString &entryId);
|
||||
|
||||
void DisplayModeChanged();
|
||||
void DockedAppsChanged();
|
||||
void OpacityChanged();
|
||||
void EntriesChanged();
|
||||
void HideModeChanged();
|
||||
void WindowSizeEfficientChanged();
|
||||
void WindowSizeFashionChanged();
|
||||
void HideStateChanged();
|
||||
void FrontendWindowRectChanged();
|
||||
void HideTimeoutChanged();
|
||||
void IconSizeChanged();
|
||||
void PositionChanged();
|
||||
void ShowTimeoutChanged();
|
||||
};
|
||||
|
||||
#endif
|
177
src/modules/dock/dbusadaptorentry.cpp
Normal file
177
src/modules/dock/dbusadaptorentry.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dbusadaptorentry.h"
|
||||
|
||||
DBusAdaptorEntry::DBusAdaptorEntry(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
//qDBusRegisterMetaType<ExportWindowInfo>();
|
||||
|
||||
Entry *entry = static_cast<Entry *>(QObject::parent());
|
||||
if (entry) {
|
||||
connect(entry, &Entry::isActiveChanged, this, &DBusAdaptorEntry::IsActiveChanged);
|
||||
connect(entry, &Entry::isDockedChanged, this, &DBusAdaptorEntry::IsDockedChanged);
|
||||
connect(entry, &Entry::menuChanged, this, &DBusAdaptorEntry::MenuChanged);
|
||||
connect(entry, &Entry::iconChanged, this, &DBusAdaptorEntry::IconChanged);
|
||||
connect(entry, &Entry::nameChanged, this, &DBusAdaptorEntry::NameChanged);
|
||||
connect(entry, &Entry::desktopFileChanged, this, &DBusAdaptorEntry::DesktopFileChanged);
|
||||
connect(entry, &Entry::currentWindowChanged, this, &DBusAdaptorEntry::CurrentWindowChanged);
|
||||
}
|
||||
}
|
||||
|
||||
DBusAdaptorEntry::~DBusAdaptorEntry()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
uint DBusAdaptorEntry::currentWindow() const
|
||||
{
|
||||
return parent()->getCurrentWindow();
|
||||
}
|
||||
|
||||
QString DBusAdaptorEntry::desktopFile() const
|
||||
{
|
||||
return parent()->getDesktopFile();
|
||||
}
|
||||
|
||||
QString DBusAdaptorEntry::icon() const
|
||||
{
|
||||
return parent()->getIcon();
|
||||
}
|
||||
|
||||
QString DBusAdaptorEntry::id() const
|
||||
{
|
||||
return parent()->getId();
|
||||
}
|
||||
|
||||
bool DBusAdaptorEntry::isActive() const
|
||||
{
|
||||
return parent()->getIsActive();
|
||||
}
|
||||
|
||||
bool DBusAdaptorEntry::isDocked() const
|
||||
{
|
||||
return parent()->getIsDocked();
|
||||
}
|
||||
|
||||
QString DBusAdaptorEntry::menu() const
|
||||
{
|
||||
return parent()->getMenu();
|
||||
}
|
||||
|
||||
QString DBusAdaptorEntry::name() const
|
||||
{
|
||||
return parent()->getName();
|
||||
}
|
||||
|
||||
/*
|
||||
QList<ExportWindowInfo> DBusAdaptorEntry::windowInfos()
|
||||
{
|
||||
return parent()->getExportWindowInfos();
|
||||
}
|
||||
*/
|
||||
Entry *DBusAdaptorEntry::parent() const
|
||||
{
|
||||
return static_cast<Entry *>(QObject::parent());
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::Activate(uint timestamp)
|
||||
{
|
||||
parent()->active(timestamp);
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::Check()
|
||||
{
|
||||
parent()->check();
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::ForceQuit()
|
||||
{
|
||||
parent()->forceQuit();
|
||||
}
|
||||
|
||||
QList<QVariant> DBusAdaptorEntry::GetAllowedCloseWindows()
|
||||
{
|
||||
auto ids = parent()->getAllowedClosedWindowIds();
|
||||
QList<QVariant> ret;
|
||||
for (auto id : ids)
|
||||
ret.push_back(id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::HandleDragDrop(uint timestamp, const QStringList &files)
|
||||
{
|
||||
parent()->handleDragDrop(timestamp, files);
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::HandleMenuItem(uint timestamp, const QString &id)
|
||||
{
|
||||
parent()->handleMenuItem(timestamp, id);
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::NewInstance(uint timestamp)
|
||||
{
|
||||
parent()->newInstance(timestamp);
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::PresentWindows()
|
||||
{
|
||||
parent()->presentWindows();
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::RequestDock()
|
||||
{
|
||||
parent()->requestDock();
|
||||
}
|
||||
|
||||
void DBusAdaptorEntry::RequestUndock()
|
||||
{
|
||||
parent()->requestUndock();
|
||||
}
|
||||
|
||||
|
||||
QDBusArgument &operator <<(QDBusArgument &argument, const ExportWindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << info.xid << info.title << info.flash;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator >>(const QDBusArgument &argument, ExportWindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> info.xid >> info.title >> info.flash;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug deg, const ExportWindowInfo &info)
|
||||
{
|
||||
qDebug() << "xid: " << info.xid << " title:" << info.title << " flash:" << info.flash;
|
||||
|
||||
return deg;
|
||||
}
|
145
src/modules/dock/dbusadaptorentry.h
Normal file
145
src/modules/dock/dbusadaptorentry.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DBUSADAPTORENTRY_H
|
||||
#define DBUSADAPTORENTRY_H
|
||||
|
||||
#include "entry.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <DBusExtendedAbstractInterface>
|
||||
|
||||
Q_DECLARE_METATYPE(ExportWindowInfo)
|
||||
|
||||
QDBusArgument &operator <<(QDBusArgument &argument, const ExportWindowInfo &info);
|
||||
const QDBusArgument &operator >>(const QDBusArgument &argument, ExportWindowInfo &info);
|
||||
QDebug operator<<(QDebug deg, const ExportWindowInfo &info);
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.deepin.dde.daemon.Dock1.Entry
|
||||
*/
|
||||
class DBusAdaptorEntry: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Dock1.Entry")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.deepin.dde.daemon.Dock1.Entry\">\n"
|
||||
" <method name=\"Activate\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"Check\"/>\n"
|
||||
" <method name=\"ForceQuit\"/>\n"
|
||||
" <method name=\"GetAllowedCloseWindows\">\n"
|
||||
" <arg direction=\"out\" type=\"au\" name=\"windows\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"HandleDragDrop\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
|
||||
" <arg direction=\"in\" type=\"as\" name=\"files\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"HandleMenuItem\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"NewInstance\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"PresentWindows\"/>\n"
|
||||
" <method name=\"RequestDock\"/>\n"
|
||||
" <method name=\"RequestUndock\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"Name\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"Icon\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"Id\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"IsActive\"/>\n"
|
||||
" <property access=\"read\" type=\"u\" name=\"CurrentWindow\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"IsDocked\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"Menu\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"DesktopFile\"/>\n"
|
||||
" <property access=\"read\" type=\"a(usb)\" name=\"WindowInfos\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
|
||||
public:
|
||||
DBusAdaptorEntry(QObject *parent);
|
||||
virtual ~DBusAdaptorEntry();
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(uint CurrentWindow READ currentWindow NOTIFY CurrentWindowChanged)
|
||||
uint currentWindow() const;
|
||||
|
||||
Q_PROPERTY(QString DesktopFile READ desktopFile NOTIFY DesktopFileChanged)
|
||||
QString desktopFile() const;
|
||||
|
||||
Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged)
|
||||
QString icon() const;
|
||||
|
||||
Q_PROPERTY(QString Id READ id)
|
||||
QString id() const;
|
||||
|
||||
Q_PROPERTY(bool IsActive READ isActive NOTIFY IsActiveChanged)
|
||||
bool isActive() const;
|
||||
|
||||
Q_PROPERTY(bool IsDocked READ isDocked NOTIFY IsDockedChanged)
|
||||
bool isDocked() const;
|
||||
|
||||
Q_PROPERTY(QString Menu READ menu NOTIFY MenuChanged)
|
||||
QString menu() const;
|
||||
|
||||
Q_PROPERTY(QString Name READ name NOTIFY NameChanged)
|
||||
QString name() const;
|
||||
|
||||
//Q_PROPERTY(QString WindowInfos READ windowInfos)
|
||||
//QList<ExportWindowInfo> windowInfos();
|
||||
|
||||
Entry *parent() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
void Activate(uint timestamp);
|
||||
void Check();
|
||||
void ForceQuit();
|
||||
QList<QVariant> GetAllowedCloseWindows();
|
||||
void HandleDragDrop(uint timestamp, const QStringList &files);
|
||||
void HandleMenuItem(uint timestamp, const QString &id);
|
||||
void NewInstance(uint timestamp);
|
||||
void PresentWindows();
|
||||
void RequestDock();
|
||||
void RequestUndock();
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void IsActiveChanged(bool value);
|
||||
void IsDockedChanged(bool value);
|
||||
void MenuChanged(QString value);
|
||||
void IconChanged(QString value);
|
||||
void NameChanged(QString value);
|
||||
void DesktopFileChanged(QString value);
|
||||
void CurrentWindowChanged(uint32_t value);
|
||||
};
|
||||
|
||||
#endif
|
214
src/modules/dock/dbushandler.cpp
Normal file
214
src/modules/dock/dbushandler.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dbushandler.h"
|
||||
#include "dock.h"
|
||||
#include "windowinfok.h"
|
||||
#include "dbusbamfapplication.h"
|
||||
|
||||
DBusHandler::DBusHandler(Dock *_dock, QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(_dock)
|
||||
, session(QDBusConnection::sessionBus())
|
||||
, launcherEnd(new LauncherBackEnd("org.deepin.dde.daemon.Launcher1", "/org/deepin/dde/daemon/Launcher1", session, this))
|
||||
, launcherFront(new LauncherFront("org.deepin.dde.Launcher1", "/org/deepin/dde/Launcher1", session, this))
|
||||
, wm(new com::deepin::WM("com.deepin.wm", "/com/deepin/wm", session, this))
|
||||
, wmSwitcher(new com::deepin::WMSwitcher("com.deepin.wmWMSwitcher", "/com/deepin/WMSwitcher", session, this))
|
||||
, kwaylandManager(nullptr)
|
||||
, bamfMatcher(new org::ayatana::bamf::BamfMatcher("org.ayatana.bamf.matcher", "/org/ayatana/bamf/matcher", session, this))
|
||||
{
|
||||
// 关联org.deepin.dde.daemon.Launcher1事件 ItemChanged
|
||||
connect(launcherEnd, &LauncherBackEnd::ItemChanged, this, &DBusHandler::handleLauncherItemChanged);
|
||||
|
||||
// 关联org.deepin.dde.Launcher1事件 VisibleChanged
|
||||
connect(launcherFront, &LauncherFront::VisibleChanged, this, [&](bool visible) {
|
||||
dock->setDdeLauncherVisible(visible);
|
||||
dock->updateHideState(false);
|
||||
});
|
||||
|
||||
// 关联com.deepin.WMSwitcher事件 WMChanged
|
||||
connect(wmSwitcher, &__WMSwitcher::WMChanged, this, [&](QString name) {dock->setWMName(name);});
|
||||
}
|
||||
|
||||
// 关联com.deepin.daemon.KWayland.WindowManager事件
|
||||
void DBusHandler::listenWaylandWMSignals()
|
||||
{
|
||||
kwaylandManager = new com::deepin::daemon::kwayland::WindowManager("com.deepin.daemon.KWayland", "/com/deepin/daemon/KWayland/WindowManager", session, this);
|
||||
|
||||
// ActiveWindowchanged
|
||||
connect(kwaylandManager, &__KwaylandManager::ActiveWindowChanged, this, &DBusHandler::handleWlActiveWindowchange);
|
||||
// WindowCreated
|
||||
connect(kwaylandManager, &__KwaylandManager::WindowCreated, this, [&] (const QString &ObjPath) {
|
||||
dock->registerWindowWayland(ObjPath);
|
||||
});
|
||||
// WindowRemove
|
||||
connect(kwaylandManager, &__KwaylandManager::WindowRemove, this, [&] (const QString &ObjPath) {
|
||||
dock->unRegisterWindowWayland(ObjPath);
|
||||
});
|
||||
}
|
||||
|
||||
void DBusHandler::handleLauncherItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID)
|
||||
{
|
||||
qInfo() << "handleLauncherItemChanged status:" << status << " Name:" << itemInfo.Name << " ID:" << itemInfo.ID;
|
||||
if (status == "deleted") {
|
||||
dock->handleLauncherItemDeleted(itemInfo.Path);
|
||||
} else if (status == "created") {
|
||||
// don't need to download to dock when app reinstall
|
||||
} else if (status == "updated") {
|
||||
dock->handleLauncherItemUpdated(itemInfo.Path);
|
||||
}
|
||||
}
|
||||
|
||||
QString DBusHandler::getCurrentWM()
|
||||
{
|
||||
return wmSwitcher->CurrentWM().value();
|
||||
}
|
||||
|
||||
// TODO 扩展ApplicationManager Run接口,允许带参数启动应用,暂时调用StartManager接口
|
||||
void DBusHandler::launchApp(uint32_t timestamp, QStringList files)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("com.deepin.StartManager", "/com/deepin/StartManager", "com.deepin.StartManager");
|
||||
interface.call("LaunchApp", files, timestamp);
|
||||
}
|
||||
|
||||
void DBusHandler::launchAppAction(uint32_t timestamp, QString file, QString section)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("com.deepin.StartManager", "/com/deepin/StartManager", "com.deepin.StartManager");
|
||||
interface.call("LaunchAppAction", file, section, timestamp);
|
||||
}
|
||||
|
||||
void DBusHandler::markAppLaunched(const QString &filePath)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("org.deepin.daemon.AlRecorder1", "/org/deepin/daemon/AlRecorder1", "org.deepin.daemon.AlRecorder1");
|
||||
interface.call("MarkLaunched", filePath);
|
||||
}
|
||||
|
||||
bool DBusHandler::wlShowingDesktop()
|
||||
{
|
||||
bool ret = false;
|
||||
if (kwaylandManager)
|
||||
ret = kwaylandManager->IsShowingDesktop().value();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint DBusHandler::wlActiveWindow()
|
||||
{
|
||||
uint ret = 0;
|
||||
if (kwaylandManager)
|
||||
ret = kwaylandManager->ActiveWindow().value();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBusHandler::handleWlActiveWindowchange()
|
||||
{
|
||||
uint activeWinInternalId = wlActiveWindow();
|
||||
if (activeWinInternalId == 0)
|
||||
return;
|
||||
|
||||
WindowInfoK *info = dock->handleActiveWindowChangedK(activeWinInternalId);
|
||||
if (info->getXid() != 0) {
|
||||
dock->handleActiveWindowChanged(info);
|
||||
} else {
|
||||
dock->updateHideState(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo)
|
||||
{
|
||||
PlasmaWindow *window = windowInfo->getPlasmaWindow();
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
// Title changed
|
||||
connect(window, &PlasmaWindow::TitleChanged, this, [&] {
|
||||
windowInfo->updateTitle();
|
||||
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
if (entry->getCurrentWindowInfo() == windowInfo)
|
||||
entry->updateName();
|
||||
|
||||
entry->updateWindowInfos();
|
||||
});
|
||||
|
||||
// Icon changed
|
||||
connect(window, &PlasmaWindow::IconChanged, this, [&] {
|
||||
windowInfo->updateIcon();
|
||||
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->updateIcon();
|
||||
});
|
||||
|
||||
// DemandingAttention changed
|
||||
connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [&] {
|
||||
windowInfo->updateDemandingAttention();
|
||||
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->updateWindowInfos();
|
||||
});
|
||||
|
||||
// Geometry changed
|
||||
connect(window, &PlasmaWindow::GeometryChanged, this, [&] {
|
||||
if (!windowInfo->updateGeometry())
|
||||
return;
|
||||
|
||||
dock->handleWindowGeometryChanged();
|
||||
});
|
||||
}
|
||||
|
||||
PlasmaWindow *DBusHandler::createPlasmaWindow(QString objPath)
|
||||
{
|
||||
return new PlasmaWindow("com.deepin.daemon.KWayland.PlasmaWindow", objPath, session, this);
|
||||
}
|
||||
|
||||
// 取消关联信号
|
||||
void DBusHandler::removePlasmaWindowHandler(PlasmaWindow *window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DBusHandler::presentWindows(QList<uint> windows)
|
||||
{
|
||||
wm->PresentWindows(windows);
|
||||
}
|
||||
|
||||
QString DBusHandler::getDesktopFromWindowByBamf(XWindow windowId)
|
||||
{
|
||||
QDBusPendingReply<QString> reply = bamfMatcher->ApplicationForXid(windowId);
|
||||
if (!reply.isValid())
|
||||
return "";
|
||||
|
||||
QString appObjPath = reply.value();
|
||||
|
||||
org::ayatana::bamf::BamfApplication bamfApp("org.ayatana.bamf.application", appObjPath, session, this);
|
||||
if (bamfApp.isValid())
|
||||
return bamfApp.DesktopFile();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
92
src/modules/dock/dbushandler.h
Normal file
92
src/modules/dock/dbushandler.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DBUSHANDLER_H
|
||||
#define DBUSHANDLER_H
|
||||
|
||||
#include "dbuslauncher.h"
|
||||
#include "dbuslauncherfront.h"
|
||||
#include "dbuswm.h"
|
||||
#include "dbuswmswitcher.h"
|
||||
#include "dbuskwaylandwindowmanager.h"
|
||||
#include "windowinfok.h"
|
||||
#include "dbusplasmawindow.h"
|
||||
#include "dbusbamfmatcher.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
|
||||
class Dock;
|
||||
|
||||
// 处理DBus交互
|
||||
class DBusHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DBusHandler(Dock *_dock, QObject *parent = nullptr);
|
||||
|
||||
/************************* KWayland/WindowManager ***************************/
|
||||
void listenWaylandWMSignals();
|
||||
bool wlShowingDesktop();
|
||||
uint wlActiveWindow();
|
||||
|
||||
/************************* daemon.Launcher1 ***************************/
|
||||
void handleLauncherItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID);
|
||||
|
||||
/************************* WMSwitcher ***************************/
|
||||
QString getCurrentWM();
|
||||
|
||||
/************************* StartManager ***************************/
|
||||
void launchApp(uint32_t timestamp, QStringList files);
|
||||
void launchAppAction(uint32_t timestamp, QString file, QString section);
|
||||
|
||||
/************************* AlRecorder1 ***************************/
|
||||
void markAppLaunched(const QString &filePath);
|
||||
|
||||
/************************* KWayland.PlasmaWindow ***************************/
|
||||
void listenKWindowSignals(WindowInfoK *windowInfo);
|
||||
PlasmaWindow *createPlasmaWindow(QString objPath);
|
||||
void removePlasmaWindowHandler(PlasmaWindow *window);
|
||||
|
||||
/************************* WM ***************************/
|
||||
void presentWindows(QList<uint> windows);
|
||||
|
||||
/************************* bamf ***************************/
|
||||
// XWindow -> desktopFile
|
||||
QString getDesktopFromWindowByBamf(XWindow windowId);
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleWlActiveWindowchange();
|
||||
|
||||
private:
|
||||
Dock *dock;
|
||||
QDBusConnection session;
|
||||
|
||||
LauncherBackEnd *launcherEnd;
|
||||
LauncherFront *launcherFront;
|
||||
com::deepin::WM *wm;
|
||||
com::deepin::WMSwitcher *wmSwitcher;
|
||||
com::deepin::daemon::kwayland::WindowManager *kwaylandManager;
|
||||
org::ayatana::bamf::BamfMatcher *bamfMatcher;
|
||||
};
|
||||
|
||||
#endif // DBUSHANDLER_H
|
1045
src/modules/dock/dock.cpp
Normal file
1045
src/modules/dock/dock.cpp
Normal file
File diff suppressed because it is too large
Load Diff
191
src/modules/dock/dock.h
Normal file
191
src/modules/dock/dock.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOCK_H
|
||||
#define DOCK_H
|
||||
|
||||
#include "synmodule.h"
|
||||
#include "docksettings.h"
|
||||
#include "entries.h"
|
||||
#include "dbusplasmawindow.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
|
||||
class WindowIdentify;
|
||||
class DBusHandler;
|
||||
class WaylandManager;
|
||||
class X11Manager;
|
||||
class WindowInfoK;
|
||||
class WindowInfoX;
|
||||
|
||||
// 任务栏
|
||||
class Dock : public SynModule
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum class HideState
|
||||
{
|
||||
Unknown,
|
||||
Show,
|
||||
Hide,
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Dock(QObject *parent = nullptr);
|
||||
~Dock();
|
||||
|
||||
bool dockEntry(Entry *entry);
|
||||
void undockEntry(Entry *entry);
|
||||
QString allocEntryId();
|
||||
bool shouldShowOnDock(WindowInfoBase *info);
|
||||
void setDdeLauncherVisible(bool visible);
|
||||
QString getWMName();
|
||||
void setWMName(QString name);
|
||||
void setPropHideMode(HideState state);
|
||||
void attachOrDetachWindow(WindowInfoBase *info);
|
||||
void attachWindow(WindowInfoBase *info);
|
||||
void detachWindow(WindowInfoBase *info);
|
||||
void markAppLaunched(const QString &filePath);
|
||||
void launchApp(uint32_t timestamp, QStringList files);
|
||||
void launchAppAction(uint32_t timestamp, QString file, QString section);
|
||||
bool is3DWM();
|
||||
bool isWaylandEnv();
|
||||
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
|
||||
void handleActiveWindowChanged(WindowInfoBase *info);
|
||||
void saveDockedApps();
|
||||
void removeAppEntry(Entry *entry);
|
||||
void handleWindowGeometryChanged();
|
||||
Entry *getEntryByWindowId(XWindow windowId);
|
||||
QString getDesktopFromWindowByBamf(XWindow windowId);
|
||||
|
||||
void registerWindowWayland(const QString &objPath);
|
||||
void unRegisterWindowWayland(const QString &objPath);
|
||||
|
||||
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
|
||||
void markAppLaunched(AppInfo *appInfo);
|
||||
void deleteWindow(XWindow xid);
|
||||
|
||||
ForceQuitAppMode getForceQuitAppStatus();
|
||||
QVector<QString> getWinIconPreferredApps();
|
||||
void handleLauncherItemDeleted(QString itemPath);
|
||||
void handleLauncherItemUpdated(QString itemPath);
|
||||
|
||||
double getOpacity();
|
||||
QRect getFrontendWindowRect();
|
||||
int getDisplayMode();
|
||||
void setDisplayMode(int mode);
|
||||
QStringList getDockedApps();
|
||||
QStringList getEntryPaths();
|
||||
HideMode getHideMode();
|
||||
void setHideMode(HideMode mode);
|
||||
HideState getHideState();
|
||||
void setHideState(HideState state);
|
||||
uint getHideTimeout();
|
||||
void setHideTimeout(uint timeout);
|
||||
uint getIconSize();
|
||||
void setIconSize(uint size);
|
||||
int getPosition();
|
||||
void setPosition(int position);
|
||||
uint getShowTimeout();
|
||||
void setShowTimeout(uint timeout);
|
||||
uint getWindowSizeEfficient();
|
||||
void setWindowSizeEfficient(uint size);
|
||||
uint getWindowSizeFashion();
|
||||
void setWindowSizeFashion(uint size);
|
||||
|
||||
// 设置配置
|
||||
void setSynConfig(QByteArray ba);
|
||||
QByteArray getSyncConfig();
|
||||
|
||||
/******************************** dbus handler ****************************/
|
||||
PlasmaWindow *createPlasmaWindow(QString objPath);
|
||||
void listenKWindowSignals(WindowInfoK *windowInfo);
|
||||
void removePlasmaWindowHandler(PlasmaWindow *window);
|
||||
void presentWindows(QList<uint> windows);
|
||||
|
||||
HideMode getDockHideMode();
|
||||
WindowInfoBase *getActiveWindow();
|
||||
QList<XWindow> getClientList();
|
||||
|
||||
void closeWindow(XWindow windowId);
|
||||
QStringList getEntryIDs();
|
||||
void setFrontendWindowRect(int32_t x, int32_t y, uint width, uint height);
|
||||
bool isDocked(const QString desktopFile);
|
||||
bool requestDock(QString desktopFile, int index);
|
||||
bool requestUndock(QString desktopFile);
|
||||
void moveEntry(int oldIndex, int newIndex);
|
||||
bool isOnDock(QString desktopFile);
|
||||
QString queryWindowIdentifyMethod(XWindow windowId);
|
||||
QStringList getDockedAppsDesktopFiles();
|
||||
QString getPluginSettings();
|
||||
void setPluginSettings(QString jsonStr);
|
||||
void mergePluginSettings(QString jsonStr);
|
||||
void removePluginSettings(QString pluginName, QStringList settingkeys);
|
||||
|
||||
void updateHideState(bool delay);
|
||||
|
||||
Q_SIGNALS:
|
||||
void serviceRestarted();
|
||||
void entryAdded(QString entryObjPath, int32_t index);
|
||||
void entryRemoved(QString id);
|
||||
void hideStateChanged();
|
||||
void frontendWindowRectChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void smartHideModeTimerExpired();
|
||||
|
||||
private:
|
||||
void initSettings();
|
||||
void updateMenu();
|
||||
void initEntries();
|
||||
void initDockedApps();
|
||||
void initClientList();
|
||||
WindowInfoX *findWindowByXidX(XWindow xid);
|
||||
WindowInfoK *findWindowByXidK(XWindow xid);
|
||||
bool isWindowDockOverlapX(XWindow xid);
|
||||
bool isWindowDockOverlapK(WindowInfoBase *info);
|
||||
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
|
||||
bool shouldHideOnSmartHideMode();
|
||||
QVector<XWindow> getActiveWinGroup(XWindow xid);
|
||||
|
||||
WindowIdentify *windowIdentify; // 窗口识别
|
||||
Entries *entries; // 所有应用实例
|
||||
int entriesSum; // 累计打开的应用数量
|
||||
bool ddeLauncherVisible; // 前端启动器是否可见
|
||||
QString wmName; // 窗管名称
|
||||
WaylandManager *waylandManager; // wayland窗口管理
|
||||
X11Manager *x11Manager; // X11窗口管理
|
||||
QList<XWindow> clientList; // 所有窗口
|
||||
QRect frontendWindowRect; // 前端任务栏大小, 用于智能隐藏时判断窗口是否重合
|
||||
HideState hideState; // 记录任务栏隐藏状态
|
||||
QTimer *smartHideTimer; // 任务栏智能隐藏定时器
|
||||
WindowInfoBase *activeWindow;// 记录当前活跃窗口信息
|
||||
WindowInfoBase *activeWindowOld;// 记录前一个活跃窗口信息
|
||||
bool isWayland; // 判断是否为wayland环境
|
||||
ForceQuitAppMode forceQuitAppStatus; // 强制退出应用状态
|
||||
DBusHandler *dbusHandler; // 处理dbus交互
|
||||
QMutex windowOperateMutex; // 窗口合并或拆分锁
|
||||
};
|
||||
|
||||
|
||||
#endif // DOCK_H
|
52
src/modules/dock/dockmanager.cpp
Normal file
52
src/modules/dock/dockmanager.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dockmanager.h"
|
||||
#include "dock.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDebug>
|
||||
#include <QDBusError>
|
||||
|
||||
DockManager::DockManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(new Dock(this))
|
||||
{
|
||||
adaptor = new DBusAdaptorDock(dock);
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
if (!con.registerService(dbusService)) {
|
||||
qWarning() << "register service Dock1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!con.registerObject(dbusPath, dock, QDBusConnection::ExportAdaptors))
|
||||
{
|
||||
qWarning() << "register object Dock1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
DockManager::~DockManager()
|
||||
{
|
||||
|
||||
}
|
48
src/modules/dock/dockmanager.h
Normal file
48
src/modules/dock/dockmanager.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOCKMANAGER_H
|
||||
#define DOCKMANAGER_H
|
||||
|
||||
#include "dbusadaptordock.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Dock;
|
||||
|
||||
// 任务栏管理类
|
||||
class DockManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DockManager(QObject *parent = nullptr);
|
||||
~DockManager();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
private:
|
||||
Dock *dock;
|
||||
DBusAdaptorDock *adaptor;
|
||||
};
|
||||
|
||||
#endif // DOCKMANAGER_H
|
354
src/modules/dock/docksettings.cpp
Normal file
354
src/modules/dock/docksettings.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "docksettings.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <DConfig>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
static DConfig *dockSettings = Settings::ConfigPtr(configDock);
|
||||
static DConfig *appearanceSettings = Settings::ConfigPtr(configAppearance);
|
||||
|
||||
DockSettings::DockSettings(QObject *parent)
|
||||
: QObject (parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void DockSettings::init()
|
||||
{
|
||||
// 绑定属性
|
||||
if (dockSettings) {
|
||||
connect(dockSettings, &DConfig::valueChanged, this, [&] (const QString &key) {
|
||||
if (key == keyHideMode) {
|
||||
Q_EMIT hideModeChanged(HideMode(dockSettings->value(key).toInt()));
|
||||
} else if(key == keyDisplayMode) {
|
||||
Q_EMIT displayModeChanged(DisplayMode(dockSettings->value(key).toInt()));
|
||||
} else if (key == keyPosition) {
|
||||
Q_EMIT positionModeChanged(PositonMode(dockSettings->value(key).toInt()));
|
||||
} else if (key == keyForceQuitApp){
|
||||
Q_EMIT forceQuitAppChanged(dockSettings->value(key).toBool());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
HideMode DockSettings::getHideMode()
|
||||
{
|
||||
HideMode ret = HideMode::Unknown;
|
||||
if (dockSettings) {
|
||||
QString mode = dockSettings->value(keyHideMode).toString();
|
||||
HideModeHandler handler(mode);
|
||||
ret = handler.toEnum();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setHideMode(HideMode mode)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyHideMode, HideModeHandler(mode).toString());
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMode DockSettings::getDisplayMode()
|
||||
{
|
||||
DisplayMode ret = DisplayMode::Unknown;
|
||||
if (dockSettings) {
|
||||
QString mode = dockSettings->value(keyDisplayMode).toString();
|
||||
DisplayModeHandler handler(mode);
|
||||
ret = handler.toEnum();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setDisplayMode(DisplayMode mode)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyHideMode, DisplayModeHandler(mode).toString());
|
||||
}
|
||||
}
|
||||
|
||||
PositonMode DockSettings::getPositionMode()
|
||||
{
|
||||
PositonMode ret = PositonMode::Unknown;
|
||||
if (dockSettings) {
|
||||
QString mode = dockSettings->value(keyPosition).toString();
|
||||
PositonModeHandler handler(mode);
|
||||
ret = handler.toEnum();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setPositionMode(PositonMode mode)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyPosition, PositonModeHandler(mode).toString());
|
||||
}
|
||||
}
|
||||
|
||||
ForceQuitAppMode DockSettings::getForceQuitAppMode()
|
||||
{
|
||||
ForceQuitAppMode ret = ForceQuitAppMode::Unknown;
|
||||
if (dockSettings) {
|
||||
QString mode = dockSettings->value(keyForceQuitApp).toString();
|
||||
ForceQuitAppModeHandler handler(mode);
|
||||
ret = handler.toEnum();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setForceQuitAppMode(ForceQuitAppMode mode)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyForceQuitApp, ForceQuitAppModeHandler(mode).toString());
|
||||
}
|
||||
}
|
||||
|
||||
uint DockSettings::getIconSize()
|
||||
{
|
||||
uint size = 36;
|
||||
if (dockSettings) {
|
||||
size = dockSettings->value(keyIconSize).toUInt();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void DockSettings::setIconSize(uint size)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyIconSize, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockSettings::getShowTimeout()
|
||||
{
|
||||
uint time = 100;
|
||||
if (dockSettings) {
|
||||
time = dockSettings->value(keyShowTimeout).toUInt();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
void DockSettings::setShowTimeout(uint time)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyShowTimeout, time);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockSettings::getHideTimeout()
|
||||
{
|
||||
uint time = 0;
|
||||
if (dockSettings) {
|
||||
time = dockSettings->value(keyHideTimeout).toUInt();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
void DockSettings::setHideTimeout(uint time)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyHideTimeout, time);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockSettings::getWindowSizeEfficient()
|
||||
{
|
||||
uint size = 40;
|
||||
if (dockSettings) {
|
||||
size = dockSettings->value(keyWindowSizeEfficient).toUInt();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void DockSettings::setWindowSizeEfficient(uint size)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyWindowSizeEfficient, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockSettings::getWindowSizeFashion()
|
||||
{
|
||||
uint size = 48;
|
||||
if (dockSettings) {
|
||||
size = dockSettings->value(keyWindowSizeFashion).toUInt();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void DockSettings::setWindowSizeFashion(uint size)
|
||||
{
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyWindowSizeFashion, size);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DockSettings::getDockedApps()
|
||||
{
|
||||
QStringList ret;
|
||||
if (!dockSettings)
|
||||
return ret;
|
||||
|
||||
for(const auto &var : dockSettings->value(keyDockedApps).toList()) {
|
||||
if (var.isValid())
|
||||
ret.push_back(var.toString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setDockedApps(QList<QString> &apps)
|
||||
{
|
||||
if (!dockSettings)
|
||||
return;
|
||||
|
||||
qDebug() << "docked apps:" << apps;
|
||||
QVariantList list;
|
||||
for (auto app : apps) {
|
||||
list << QVariant(app);
|
||||
}
|
||||
|
||||
dockSettings->setValue(keyDockedApps, list);
|
||||
}
|
||||
|
||||
double DockSettings::getOpacity()
|
||||
{
|
||||
double opacity = 0.4;
|
||||
if (appearanceSettings) {
|
||||
opacity = appearanceSettings->value(keyOpacity).toDouble();
|
||||
}
|
||||
return opacity;
|
||||
}
|
||||
|
||||
QVector<QString> DockSettings::getWinIconPreferredApps()
|
||||
{
|
||||
QVector<QString> ret;
|
||||
if (dockSettings) {
|
||||
for(const auto &var : dockSettings->value(keyWinIconPreferredApps).toList()) {
|
||||
if (var.isValid())
|
||||
ret.push_back(var.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString DockSettings::getPluginSettings()
|
||||
{
|
||||
QString ret;
|
||||
if (dockSettings) {
|
||||
ret = dockSettings->value(keyPluginSettings).toString();
|
||||
}
|
||||
|
||||
qInfo() << "getpluginsettings:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DockSettings::setPluginSettings(QString jsonStr)
|
||||
{
|
||||
if (jsonStr.isEmpty())
|
||||
return;
|
||||
|
||||
if (dockSettings) {
|
||||
dockSettings->setValue(keyPluginSettings, jsonStr);
|
||||
}
|
||||
}
|
||||
|
||||
void DockSettings::mergePluginSettings(QString jsonStr)
|
||||
{
|
||||
QString origin = getPluginSettings();
|
||||
QJsonObject originSettings = plguinSettingsStrToObj(origin);
|
||||
QJsonObject needMergeSettings = plguinSettingsStrToObj(jsonStr);
|
||||
for (auto pluginsIt = needMergeSettings.begin(); pluginsIt != needMergeSettings.end(); pluginsIt++) {
|
||||
const QString &pluginName = pluginsIt.key();
|
||||
const QJsonObject &needMergeSettingsObj = pluginsIt.value().toObject();
|
||||
QJsonObject originSettingsObj = originSettings.value(pluginName).toObject();
|
||||
for (auto settingsIt = needMergeSettingsObj.begin(); settingsIt != needMergeSettingsObj.end(); settingsIt++) {
|
||||
originSettingsObj.insert(settingsIt.key(), settingsIt.value());
|
||||
}
|
||||
|
||||
// 重写plugin对应的设置
|
||||
originSettings.remove(pluginName);
|
||||
originSettings.insert(pluginName, originSettingsObj);
|
||||
}
|
||||
|
||||
setPluginSettings(QJsonDocument(originSettings).toJson(QJsonDocument::JsonFormat::Compact));
|
||||
}
|
||||
|
||||
void DockSettings::removePluginSettings(QString pluginName, QStringList settingkeys)
|
||||
{
|
||||
if (pluginName.isEmpty())
|
||||
return;
|
||||
|
||||
QString origin = getPluginSettings();
|
||||
QJsonObject originSettings = plguinSettingsStrToObj(origin);
|
||||
if (settingkeys.size() == 0) {
|
||||
originSettings.remove(pluginName);
|
||||
} else {
|
||||
for (auto pluginsIt = originSettings.begin(); pluginsIt != originSettings.end(); pluginsIt++) {
|
||||
const QString &pluginName = pluginsIt.key();
|
||||
if (pluginName != pluginName)
|
||||
continue;
|
||||
|
||||
QJsonObject originSettingsObj = originSettings.value(pluginName).toObject();
|
||||
for (const auto &key : settingkeys) {
|
||||
originSettingsObj.remove(key);
|
||||
}
|
||||
|
||||
// 重写plugin对应的设置
|
||||
originSettings.remove(pluginName);
|
||||
originSettings.insert(pluginName, originSettingsObj);
|
||||
}
|
||||
}
|
||||
|
||||
setPluginSettings(QJsonDocument(originSettings).toJson(QJsonDocument::JsonFormat::Compact));
|
||||
}
|
||||
|
||||
// 借鉴自dde-dock
|
||||
QJsonObject DockSettings::plguinSettingsStrToObj(QString jsonStr)
|
||||
{
|
||||
QJsonObject ret;
|
||||
const QJsonObject &pluginSettingsObject = QJsonDocument::fromJson(jsonStr.toLocal8Bit()).object();
|
||||
if (pluginSettingsObject.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (auto pluginsIt = pluginSettingsObject.constBegin(); pluginsIt != pluginSettingsObject.constEnd(); ++pluginsIt) {
|
||||
const QString &pluginName = pluginsIt.key();
|
||||
const QJsonObject &settingsObject = pluginsIt.value().toObject();
|
||||
QJsonObject newSettingsObject = ret.value(pluginName).toObject();
|
||||
for (auto settingsIt = settingsObject.constBegin(); settingsIt != settingsObject.constEnd(); ++settingsIt) {
|
||||
newSettingsObject.insert(settingsIt.key(), settingsIt.value());
|
||||
}
|
||||
// TODO: remove not exists key-values
|
||||
ret.insert(pluginName, newSettingsObject);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
275
src/modules/dock/docksettings.h
Normal file
275
src/modules/dock/docksettings.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOCKSETTINGS_H
|
||||
#define DOCKSETTINGS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
// 隐藏模式
|
||||
enum class HideMode {
|
||||
KeepShowing,
|
||||
KeepHidden,
|
||||
SmartHide,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
class HideModeHandler {
|
||||
HideMode modeEnum;
|
||||
QString modeStr;
|
||||
|
||||
public:
|
||||
HideModeHandler(HideMode mode) : modeEnum(mode), modeStr("") {}
|
||||
HideModeHandler(QString mode) : modeEnum(HideMode::Unknown), modeStr(mode) {}
|
||||
|
||||
bool equal(HideModeHandler hideMode) {
|
||||
return toString() == hideMode.toString() || toEnum() == hideMode.toEnum();
|
||||
}
|
||||
|
||||
QString toString() {
|
||||
switch (modeEnum) {
|
||||
case HideMode::KeepShowing:
|
||||
return "keep-showing";
|
||||
case HideMode::KeepHidden:
|
||||
return "keep-hidden";
|
||||
case HideMode::SmartHide:
|
||||
return "smart-hide";
|
||||
case HideMode::Unknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
HideMode toEnum() {
|
||||
if (modeStr == "keep-showing")
|
||||
return HideMode::KeepHidden;
|
||||
else if (modeStr == "keep-hidden")
|
||||
return HideMode::KeepHidden;
|
||||
else if (modeStr == "smart-hide")
|
||||
return HideMode::SmartHide;
|
||||
else
|
||||
return HideMode::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
// 显示样式
|
||||
enum class DisplayMode {
|
||||
Fashion,
|
||||
Efficient,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
class DisplayModeHandler {
|
||||
DisplayMode modeEnum;
|
||||
QString modeStr;
|
||||
|
||||
public:
|
||||
DisplayModeHandler(DisplayMode mode) : modeEnum(mode), modeStr("") {}
|
||||
DisplayModeHandler(QString mode) : modeEnum(DisplayMode::Unknown), modeStr(mode) {}
|
||||
|
||||
bool equal(DisplayModeHandler displayMode) {
|
||||
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
|
||||
}
|
||||
|
||||
QString toString() {
|
||||
switch (modeEnum) {
|
||||
case DisplayMode::Fashion:
|
||||
return "fashion";
|
||||
case DisplayMode::Efficient:
|
||||
return "efficient";
|
||||
case DisplayMode::Unknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMode toEnum() {
|
||||
if (modeStr == "fashion")
|
||||
return DisplayMode::Fashion;
|
||||
else if (modeStr == "efficient")
|
||||
return DisplayMode::Efficient;
|
||||
else
|
||||
return DisplayMode::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
// 显示位置
|
||||
enum class PositonMode {
|
||||
TOP,
|
||||
Right,
|
||||
Bottom,
|
||||
Left,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
class PositonModeHandler {
|
||||
PositonMode modeEnum;
|
||||
QString modeStr;
|
||||
|
||||
public:
|
||||
PositonModeHandler(PositonMode mode) : modeEnum(mode), modeStr("") {}
|
||||
PositonModeHandler(QString mode) : modeEnum(PositonMode::Unknown), modeStr(mode) {}
|
||||
|
||||
bool equal(PositonModeHandler displayMode) {
|
||||
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
|
||||
}
|
||||
|
||||
QString toString() {
|
||||
switch (modeEnum) {
|
||||
case PositonMode::TOP:
|
||||
return "top";
|
||||
case PositonMode::Right:
|
||||
return "right";
|
||||
case PositonMode::Bottom:
|
||||
return "bottom";
|
||||
case PositonMode::Left:
|
||||
return "left";
|
||||
case PositonMode::Unknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
PositonMode toEnum() {
|
||||
if (modeStr == "top")
|
||||
return PositonMode::TOP;
|
||||
else if (modeStr == "right")
|
||||
return PositonMode::Right;
|
||||
else if (modeStr == "bottom")
|
||||
return PositonMode::Bottom;
|
||||
else if (modeStr == "left")
|
||||
return PositonMode::Left;
|
||||
else
|
||||
return PositonMode::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
// 强制退出应用菜单状态
|
||||
enum class ForceQuitAppMode {
|
||||
Enabled, // 开启
|
||||
Disabled, // 关闭
|
||||
Deactivated, // 置灰
|
||||
Unknown
|
||||
};
|
||||
|
||||
class ForceQuitAppModeHandler {
|
||||
ForceQuitAppMode modeEnum;
|
||||
QString modeStr;
|
||||
|
||||
public:
|
||||
ForceQuitAppModeHandler(ForceQuitAppMode mode) : modeEnum(mode), modeStr("") {}
|
||||
ForceQuitAppModeHandler(QString mode) : modeEnum(ForceQuitAppMode::Unknown), modeStr(mode) {}
|
||||
|
||||
bool equal(ForceQuitAppModeHandler displayMode) {
|
||||
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
|
||||
}
|
||||
|
||||
QString toString() {
|
||||
switch (modeEnum) {
|
||||
case ForceQuitAppMode::Enabled:
|
||||
return "enabled";
|
||||
case ForceQuitAppMode::Disabled:
|
||||
return "disabled";
|
||||
case ForceQuitAppMode::Deactivated:
|
||||
return "deactivated";
|
||||
case ForceQuitAppMode::Unknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
ForceQuitAppMode toEnum() {
|
||||
if (modeStr == "enabled")
|
||||
return ForceQuitAppMode::Enabled;
|
||||
else if (modeStr == "disabled")
|
||||
return ForceQuitAppMode::Disabled;
|
||||
else if (modeStr == "deactivated")
|
||||
return ForceQuitAppMode::Deactivated;
|
||||
else
|
||||
return ForceQuitAppMode::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
class Settings;
|
||||
|
||||
// 任务栏组策略配置类
|
||||
class DockSettings: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static inline DockSettings *instance() {
|
||||
static DockSettings instance;
|
||||
return &instance;
|
||||
}
|
||||
void init();
|
||||
|
||||
HideMode getHideMode();
|
||||
void setHideMode(HideMode mode);
|
||||
DisplayMode getDisplayMode();
|
||||
void setDisplayMode(DisplayMode mode);
|
||||
PositonMode getPositionMode();
|
||||
void setPositionMode(PositonMode mode);
|
||||
ForceQuitAppMode getForceQuitAppMode();
|
||||
void setForceQuitAppMode(ForceQuitAppMode mode);
|
||||
uint getIconSize();
|
||||
void setIconSize(uint size);
|
||||
uint getShowTimeout();
|
||||
void setShowTimeout(uint time);
|
||||
uint getHideTimeout();
|
||||
void setHideTimeout(uint time);
|
||||
uint getWindowSizeEfficient();
|
||||
void setWindowSizeEfficient(uint size);
|
||||
uint getWindowSizeFashion();
|
||||
void setWindowSizeFashion(uint size);
|
||||
QStringList getDockedApps();
|
||||
void setDockedApps(QList<QString> &apps);
|
||||
double getOpacity();
|
||||
QVector<QString> getWinIconPreferredApps();
|
||||
|
||||
// plugin settings
|
||||
QString getPluginSettings();
|
||||
void setPluginSettings(QString jsonStr);
|
||||
void mergePluginSettings(QString jsonStr);
|
||||
void removePluginSettings(QString pluginName, QStringList settingkeys);
|
||||
QJsonObject plguinSettingsStrToObj(QString jsonStr);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
// 隐藏模式改变
|
||||
void hideModeChanged(HideMode mode);
|
||||
// 显示样式改变
|
||||
void displayModeChanged(DisplayMode mode);
|
||||
// 显示位置改变
|
||||
void positionModeChanged(PositonMode mode);
|
||||
// 强制退出应用开关改变
|
||||
void forceQuitAppChanged(bool forced);
|
||||
|
||||
|
||||
private:
|
||||
DockSettings(QObject *paret = nullptr);
|
||||
DockSettings(const DockSettings &);
|
||||
DockSettings& operator= (const DockSettings &);
|
||||
};
|
||||
|
||||
#endif // DOCKSETTINGS_H
|
215
src/modules/dock/entries.cpp
Normal file
215
src/modules/dock/entries.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "entries.h"
|
||||
#include "dock.h"
|
||||
|
||||
Entries::Entries(Dock *_dock)
|
||||
: dock(_dock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVector<Entry *> Entries::filterDockedEntries()
|
||||
{
|
||||
QVector<Entry *> ret;
|
||||
for (auto &entry : items) {
|
||||
if (entry->isValid() && entry->getIsDocked())
|
||||
ret.push_back(entry);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Entry *Entries::getByInnerId(QString innerId)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : items) {
|
||||
if (entry->getInnerId() == innerId)
|
||||
ret = entry;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entries::append(Entry *entry)
|
||||
{
|
||||
insert(entry, -1);
|
||||
}
|
||||
|
||||
void Entries::insert(Entry *entry, int index)
|
||||
{
|
||||
if (index < 0 || index >= items.size()) {
|
||||
// append
|
||||
items.push_back(entry);
|
||||
} else {
|
||||
// insert
|
||||
items.insert(index, entry);
|
||||
}
|
||||
|
||||
insertCb(entry, index);
|
||||
}
|
||||
|
||||
void Entries::remove(Entry *entry)
|
||||
{
|
||||
for (auto iter = items.begin(); iter != items.end(); iter++) {
|
||||
if ((*iter)->getId() == entry->getId()) {
|
||||
items.erase(iter);
|
||||
removeCb(entry);
|
||||
delete entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::move(int oldIndex, int newIndex)
|
||||
{
|
||||
if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= items.size() || newIndex >= items.size())
|
||||
return;
|
||||
|
||||
items.swap(oldIndex, newIndex);
|
||||
}
|
||||
|
||||
Entry *Entries::getByWindowPid(int pid)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : items) {
|
||||
if (entry->getWindowInfoByPid(pid)) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Entry *Entries::getByWindowId(XWindow windowId)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : items) {
|
||||
if (entry->getWindowInfoByWinId(windowId)) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Entry *Entries::getByDesktopFilePath(QString filePath)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : items) {
|
||||
if (entry->getFileName() == filePath) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList Entries::getEntryIDs()
|
||||
{
|
||||
QStringList list;
|
||||
for (auto item : items)
|
||||
list.push_back(item->getId());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto entry : filterDockedEntries()) {
|
||||
if (!entry->isValid())
|
||||
continue;
|
||||
|
||||
if (desktopFile == entry->getFileName()) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Entries::queryWindowIdentifyMethod(XWindow windowId)
|
||||
{
|
||||
QString ret;
|
||||
for (auto entry : items) {
|
||||
auto window = entry->getWindowInfoByWinId(windowId);
|
||||
if (window) {
|
||||
auto app = window->getAppInfo();
|
||||
if (app) {
|
||||
ret = app->getIdentifyMethod();
|
||||
} else {
|
||||
ret = "Failed";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entries::handleActiveWindowChanged(XWindow activeWindId)
|
||||
{
|
||||
for (auto entry : items) {
|
||||
auto windowInfo = entry->getWindowInfoByWinId(activeWindId);
|
||||
if (windowInfo) {
|
||||
entry->setPropIsActive(true);
|
||||
entry->setCurrentWindowInfo(windowInfo);
|
||||
entry->updateName();
|
||||
entry->updateIcon();
|
||||
} else {
|
||||
entry->setPropIsActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::deleteWindow(XWindow xid)
|
||||
{
|
||||
for (auto entry : items) {
|
||||
if (entry->containsWindow(xid)) {
|
||||
entry->deleteWindow(xid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::updateEntriesMenu()
|
||||
{
|
||||
for (auto entry : items) {
|
||||
entry->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::insertCb(Entry *entry, int index)
|
||||
{
|
||||
QString objPath = entryDBusObjPathPrefix + entry->getId();
|
||||
Q_EMIT dock->entryAdded(objPath, index);
|
||||
}
|
||||
|
||||
void Entries::removeCb(Entry *entry)
|
||||
{
|
||||
Q_EMIT dock->entryRemoved(entry->getId());
|
||||
entry->stopExport();
|
||||
}
|
60
src/modules/dock/entries.h
Normal file
60
src/modules/dock/entries.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENTRIES_H
|
||||
#define ENTRIES_H
|
||||
|
||||
#include "entry.h"
|
||||
#include <QVector>
|
||||
#include <QWeakPointer>
|
||||
|
||||
class Dock;
|
||||
|
||||
// 所有应用管理类
|
||||
class Entries
|
||||
{
|
||||
public:
|
||||
Entries(Dock *_dock);
|
||||
|
||||
QVector<Entry *> filterDockedEntries();
|
||||
Entry *getByInnerId(QString innerId);
|
||||
void append(Entry *entry);
|
||||
void insert(Entry *entry, int index);
|
||||
void remove(Entry *entry);
|
||||
void move(int oldIndex, int newIndex);
|
||||
Entry *getByWindowPid(int pid);
|
||||
Entry *getByWindowId(XWindow windowId);
|
||||
Entry *getByDesktopFilePath(QString filePath);
|
||||
QStringList getEntryIDs();
|
||||
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
|
||||
QString queryWindowIdentifyMethod(XWindow windowId);
|
||||
void handleActiveWindowChanged(XWindow activeWindId);
|
||||
void deleteWindow(XWindow xid);
|
||||
void updateEntriesMenu();
|
||||
void insertCb(Entry *entry, int index);
|
||||
void removeCb(Entry *entry);
|
||||
|
||||
private:
|
||||
QList<Entry *> items;
|
||||
Dock *dock;
|
||||
};
|
||||
|
||||
#endif // ENTRIES_H
|
787
src/modules/dock/entry.cpp
Normal file
787
src/modules/dock/entry.cpp
Normal file
@ -0,0 +1,787 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "entry.h"
|
||||
#include "dock.h"
|
||||
#include "processinfo.h"
|
||||
#include "dbusadaptorentry.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDBusInterface>
|
||||
|
||||
#include<signal.h>
|
||||
|
||||
Entry::Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(_dock)
|
||||
, app(nullptr)
|
||||
, menu(nullptr)
|
||||
, isActive(false)
|
||||
, isDocked(false)
|
||||
, innerId(_innerId)
|
||||
, current(nullptr)
|
||||
, currentWindow(0)
|
||||
, winIconPreferred(false)
|
||||
{
|
||||
setApp(_app);
|
||||
id = dock->allocEntryId();
|
||||
name = getName();
|
||||
icon = getIcon();
|
||||
}
|
||||
|
||||
Entry::~Entry()
|
||||
{
|
||||
for (auto winInfo : windowInfos) {
|
||||
if (winInfo)
|
||||
delete winInfo;
|
||||
}
|
||||
windowInfos.clear();
|
||||
|
||||
if (app) {
|
||||
delete app;
|
||||
app = nullptr;
|
||||
}
|
||||
|
||||
if (menu) {
|
||||
delete menu;
|
||||
menu = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Entry::isValid()
|
||||
{
|
||||
bool valid = false;
|
||||
if (app)
|
||||
valid = app->isValidApp();
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
QString Entry::getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
QString Entry::getName()
|
||||
{
|
||||
QString ret;
|
||||
if (app)
|
||||
ret = app->getName();
|
||||
|
||||
if (ret.isEmpty() && !!current)
|
||||
ret = current->getDisplayName();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entry::updateName()
|
||||
{
|
||||
setPropName(getName());
|
||||
}
|
||||
|
||||
QString Entry::getIcon()
|
||||
{
|
||||
QString ret;
|
||||
if (hasWindow()) {
|
||||
if (!current)
|
||||
return ret;
|
||||
|
||||
// has window && current not nullptr
|
||||
if (winIconPreferred) {
|
||||
// try current window icon first
|
||||
ret = current->getIcon();
|
||||
if (ret.size() > 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (app) {
|
||||
icon = app->getIcon();
|
||||
if (icon.size() > 0)
|
||||
return ret;
|
||||
}
|
||||
ret = current->getIcon();
|
||||
} else if (app) {
|
||||
// no window
|
||||
ret = app->getIcon();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Entry::getInnerId()
|
||||
{
|
||||
return innerId;
|
||||
}
|
||||
|
||||
void Entry::setInnerId(QString _innerId)
|
||||
{
|
||||
innerId = _innerId;
|
||||
}
|
||||
|
||||
QString Entry::getFileName()
|
||||
{
|
||||
QString fileName;
|
||||
if (app)
|
||||
fileName = app->getFileName();
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
AppInfo *Entry::getApp()
|
||||
{
|
||||
return app;
|
||||
}
|
||||
|
||||
void Entry::setApp(AppInfo *appinfo)
|
||||
{
|
||||
if (app == appinfo)
|
||||
return;
|
||||
|
||||
if (app)
|
||||
delete app;
|
||||
|
||||
app = appinfo;
|
||||
if (!appinfo) {
|
||||
winIconPreferred = true;
|
||||
setPropDesktopFile("");
|
||||
} else {
|
||||
winIconPreferred = false;
|
||||
setPropDesktopFile(appinfo->getFileName());
|
||||
QString id = app->getId();
|
||||
auto perferredApps = dock->getWinIconPreferredApps();
|
||||
if (perferredApps.contains(id)) {
|
||||
winIconPreferred = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (appinfo->getIcon().size() == 0) {
|
||||
winIconPreferred = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Entry::getIsDocked()
|
||||
{
|
||||
return isDocked;
|
||||
}
|
||||
|
||||
void Entry::setIsDocked(bool value)
|
||||
{
|
||||
if (value != isDocked) {
|
||||
isDocked = value;
|
||||
Q_EMIT isDockedChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
// 导出Dbus服务
|
||||
void Entry::startExport()
|
||||
{
|
||||
if (getId().isEmpty()) {
|
||||
qWarning() << "startExport Entry " << getName() << " id is Empty";
|
||||
return;
|
||||
}
|
||||
|
||||
new DBusAdaptorEntry(this); // export dbus by Adaptor
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
if (!con.registerService(dbusService)) {
|
||||
qWarning() << "register service Dock1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
|
||||
objctPath = entryDBusObjPathPrefix + getId();
|
||||
if (!con.registerObject(objctPath, this))
|
||||
{
|
||||
qWarning() << "register object Dock1 error:" << con.lastError().message();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 停止导出Dbus服务
|
||||
void Entry::stopExport()
|
||||
{
|
||||
if (getId().isEmpty()) {
|
||||
qWarning() << "stopExport Entry " << getName() << " id is Empty";
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
objctPath.clear();
|
||||
con.unregisterObject(entryDBusObjPathPrefix + getId());
|
||||
}
|
||||
|
||||
void Entry::setMenu(AppMenu *_menu)
|
||||
{
|
||||
_menu->setDirtyStatus(true);
|
||||
if (menu)
|
||||
delete menu;
|
||||
|
||||
menu = _menu;
|
||||
Q_EMIT menuChanged(menu->getMenuJsonStr());
|
||||
}
|
||||
|
||||
void Entry::updateMenu()
|
||||
{
|
||||
qInfo() <<"Entry: updateMenu";
|
||||
AppMenu *appMenu = new AppMenu();
|
||||
appMenu->appendItem(getMenuItemLaunch());
|
||||
|
||||
for (auto &item :getMenuItemDesktopActions())
|
||||
appMenu->appendItem(item);
|
||||
|
||||
bool hasWin = hasWindow();
|
||||
if (hasWin)
|
||||
appMenu->appendItem(getMenuItemAllWindows());
|
||||
|
||||
// menu item dock or undock
|
||||
qInfo() << "entry " << id << " docked? " << isDocked;
|
||||
if (isDocked)
|
||||
appMenu->appendItem(getMenuItemUndock());
|
||||
else
|
||||
appMenu->appendItem(getMenuItemDock());
|
||||
|
||||
if (hasWindow()) {
|
||||
if (dock->getForceQuitAppStatus() != ForceQuitAppMode::Disabled) {
|
||||
if (app && app->getIdentifyMethod() == "Andriod")
|
||||
appMenu->appendItem(getMenuItemForceQuitAndroid());
|
||||
else
|
||||
appMenu->appendItem(getMenuItemForceQuit());
|
||||
}
|
||||
|
||||
if (getAllowedCloseWindows().size() > 0)
|
||||
appMenu->appendItem(getMenuItemCloseAll());
|
||||
}
|
||||
setMenu(appMenu);
|
||||
}
|
||||
|
||||
void Entry::updateIcon()
|
||||
{
|
||||
setPropIcon(getIcon());
|
||||
}
|
||||
|
||||
void Entry::forceUpdateIcon()
|
||||
{
|
||||
icon = getIcon();
|
||||
Q_EMIT iconChanged(icon);
|
||||
}
|
||||
|
||||
void Entry::updateIsActive()
|
||||
{
|
||||
bool isActive = false;
|
||||
auto activeWin = dock->getActiveWindow();
|
||||
if (activeWin)
|
||||
isActive = windowInfos.find(activeWin->getXid()) != windowInfos.end();
|
||||
|
||||
setPropIsActive(isActive);
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getWindowInfoByPid(int pid)
|
||||
{
|
||||
WindowInfoBase *ret = nullptr;
|
||||
for (const auto &windowInfo : windowInfos) {
|
||||
if (windowInfo->getPid() == pid) {
|
||||
ret = windowInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getWindowInfoByWinId(XWindow windowId)
|
||||
{
|
||||
WindowInfoBase *ret = nullptr;
|
||||
if (windowInfos.find(windowId) != windowInfos.end()) {
|
||||
ret = windowInfos[windowId];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entry::setPropIsDocked(bool docked)
|
||||
{
|
||||
if (isDocked != docked) {
|
||||
isDocked = docked;
|
||||
Q_EMIT isDockedChanged(docked);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setPropIcon(QString value)
|
||||
{
|
||||
if (value != icon) {
|
||||
icon = value;
|
||||
Q_EMIT iconChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setPropName(QString value)
|
||||
{
|
||||
if (value != name) {
|
||||
name = value;
|
||||
Q_EMIT nameChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setPropIsActive(bool active)
|
||||
{
|
||||
if (isActive != active) {
|
||||
isActive = active;
|
||||
Q_EMIT isActiveChanged(active);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setCurrentWindowInfo(WindowInfoBase *windowInfo)
|
||||
{
|
||||
current = windowInfo;
|
||||
setPropCurrentWindow(current ? current->getXid() : 0);
|
||||
}
|
||||
|
||||
void Entry::setPropCurrentWindow(XWindow value)
|
||||
{
|
||||
if (value != currentWindow) {
|
||||
currentWindow = value;
|
||||
Q_EMIT currentWindowChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getCurrentWindowInfo()
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
QString Entry::getExec(bool oneLine)
|
||||
{
|
||||
QString ret;
|
||||
if (!current)
|
||||
return ret;
|
||||
|
||||
ProcessInfo *process = current->getProcess();
|
||||
if (process) {
|
||||
if (oneLine)
|
||||
ret = process->getOneCommandLine().c_str();
|
||||
else
|
||||
ret = process->getShellScriptLines().c_str();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Entry::hasWindow()
|
||||
{
|
||||
return windowInfos.size() > 0;
|
||||
}
|
||||
|
||||
void Entry::updateWindowInfos()
|
||||
{
|
||||
QList<ExportWindowInfo> infos;
|
||||
bool changed = false;
|
||||
for (auto info : windowInfos) {
|
||||
XWindow xid = info->getXid();
|
||||
QString title = info->getTitle();
|
||||
bool flash = info->isDemandingAttention();
|
||||
infos.push_back({xid, title, flash});
|
||||
if (!changed) {
|
||||
for (auto info : exportWindowInfos) {
|
||||
if (info.title != title || info.flash != flash)
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
exportWindowInfos = infos;
|
||||
}
|
||||
}
|
||||
|
||||
// 分离窗口, 返回是否需要从任务栏remove
|
||||
bool Entry::detachWindow(WindowInfoBase *info)
|
||||
{
|
||||
info->setEntry(nullptr);
|
||||
XWindow winId = info->getXid();
|
||||
deleteWindow(winId);
|
||||
|
||||
if (windowInfos.size() == 0) {
|
||||
if (!isDocked) // 既无窗口也非驻留应用,无需在任务栏显示
|
||||
return true;
|
||||
|
||||
setCurrentWindowInfo(nullptr);
|
||||
} else {
|
||||
for (auto window : windowInfos) {
|
||||
if (window) { // 选择第一个窗口作为当前窗口
|
||||
setCurrentWindowInfo(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateWindowInfos();
|
||||
updateIcon();
|
||||
updateIsActive();
|
||||
updateMenu();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entry::attachWindow(WindowInfoBase *info)
|
||||
{
|
||||
XWindow winId = info->getXid();
|
||||
qInfo() << "attatchWindow: window id:" << winId;
|
||||
info->setEntry(this);
|
||||
|
||||
if (windowInfos.find(winId) != windowInfos.end()) {
|
||||
qInfo() << "attachWindow: window " << winId << " is already attached";
|
||||
return false;
|
||||
}
|
||||
|
||||
windowInfos[winId] = info;
|
||||
updateWindowInfos();
|
||||
updateIsActive();
|
||||
|
||||
if (!current) {
|
||||
// from no window to has window
|
||||
setCurrentWindowInfo(info);
|
||||
}
|
||||
|
||||
updateIcon();
|
||||
updateMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Entry::launchApp(uint32_t timestamp)
|
||||
{
|
||||
dock->launchApp(timestamp, QStringList() << app->getFileName());
|
||||
}
|
||||
|
||||
bool Entry::containsWindow(XWindow xid)
|
||||
{
|
||||
return windowInfos.find(xid) != windowInfos.end();
|
||||
}
|
||||
|
||||
void Entry::deleteWindow(XWindow xid)
|
||||
{
|
||||
WindowInfoBase *info = windowInfos[xid];
|
||||
windowInfos.remove(xid);
|
||||
for (int i = 0; i < exportWindowInfos.size(); i++) {
|
||||
if (exportWindowInfos[i].xid == xid) {
|
||||
exportWindowInfos.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info) {
|
||||
delete info;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理菜单项
|
||||
void Entry::handleMenuItem(uint32_t timestamp, QString itemId)
|
||||
{
|
||||
menu->handleAction(timestamp, itemId);
|
||||
}
|
||||
|
||||
// 处理拖拽事件
|
||||
void Entry::handleDragDrop(uint32_t timestamp, QStringList files)
|
||||
{
|
||||
dock->launchApp(timestamp, files);
|
||||
}
|
||||
|
||||
// 驻留
|
||||
void Entry::requestDock()
|
||||
{
|
||||
if (dock->dockEntry(this)) {
|
||||
dock->saveDockedApps();
|
||||
}
|
||||
}
|
||||
|
||||
// 取消驻留
|
||||
void Entry::requestUndock()
|
||||
{
|
||||
dock->undockEntry(this);
|
||||
}
|
||||
|
||||
void Entry::newInstance(uint32_t timestamp)
|
||||
{
|
||||
QStringList files;
|
||||
dock->launchApp(timestamp, files);
|
||||
}
|
||||
|
||||
// 检查应用窗口分离、合并状态
|
||||
void Entry::check()
|
||||
{
|
||||
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
|
||||
dock->attachOrDetachWindow(iter.value());
|
||||
}
|
||||
}
|
||||
|
||||
// 强制退出
|
||||
void Entry::forceQuit()
|
||||
{
|
||||
QMap<int, QVector<WindowInfoBase*>> pidWinInfoMap;
|
||||
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
|
||||
int pid = iter.value()->getPid();
|
||||
if (pid != 0) {
|
||||
pidWinInfoMap[pid].push_back(iter.value());
|
||||
} else {
|
||||
iter.value()->killClient();
|
||||
}
|
||||
|
||||
for (auto iter = pidWinInfoMap.begin(); iter != pidWinInfoMap.end(); iter++) {
|
||||
if (!killProcess(iter.key())) { // kill pid
|
||||
for (auto &info : iter.value()) { // kill window
|
||||
info->killClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::presentWindows()
|
||||
{
|
||||
QList<uint> windows;
|
||||
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++)
|
||||
windows.push_back(iter.key());
|
||||
|
||||
dock->presentWindows(windows);
|
||||
}
|
||||
|
||||
void Entry::active(uint32_t timestamp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XWindow Entry::getCurrentWindow()
|
||||
{
|
||||
return currentWindow;
|
||||
}
|
||||
|
||||
QString Entry::getDesktopFile()
|
||||
{
|
||||
return desktopFile;
|
||||
}
|
||||
|
||||
bool Entry::getIsActive()
|
||||
{
|
||||
return isActive;
|
||||
}
|
||||
|
||||
QString Entry::getMenu()
|
||||
{
|
||||
return menu->getMenuJsonStr();
|
||||
}
|
||||
|
||||
QVector<XWindow> Entry::getAllowedClosedWindowIds()
|
||||
{
|
||||
QVector<XWindow> ret;
|
||||
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
|
||||
WindowInfoBase *info = iter.value();
|
||||
if (info && info->allowClose())
|
||||
ret.push_back(iter.key());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<ExportWindowInfo> Entry::getExportWindowInfos()
|
||||
{
|
||||
return exportWindowInfos;
|
||||
}
|
||||
|
||||
QVector<WindowInfoBase *> Entry::getAllowedCloseWindows()
|
||||
{
|
||||
QVector<WindowInfoBase *> ret;
|
||||
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
|
||||
WindowInfoBase *info = iter.value();
|
||||
if (info && info->allowClose())
|
||||
ret.push_back(info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVector<AppMenuItem> Entry::getMenuItemDesktopActions()
|
||||
{
|
||||
QVector<AppMenuItem> ret;
|
||||
if (!app)
|
||||
return ret;
|
||||
|
||||
for (auto action : app->getActions()) {
|
||||
AppMenuAction fn = [&](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: " << action.name.c_str();
|
||||
dock->launchAppAction(timestamp, app->getFileName(), action.section.c_str());
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = action.name.c_str();
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
ret.push_back(item);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemLaunch()
|
||||
{
|
||||
QString itemName;
|
||||
if (hasWindow())
|
||||
itemName = getName();
|
||||
else
|
||||
itemName = "Open";
|
||||
|
||||
AppMenuAction fn = [&](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: Open";
|
||||
this->launchApp(timestamp);
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = itemName;
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemCloseAll()
|
||||
{
|
||||
AppMenuAction fn = [&](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: Close All";
|
||||
auto winInfos = getAllowedCloseWindows();
|
||||
|
||||
// 从大到小排序, 方便后面关闭窗口
|
||||
for (int i = 0; i < winInfos.size() - 1; i++) {
|
||||
for (int j = i + 1; j < winInfos.size(); j++) {
|
||||
if (winInfos[i]->getCreatedTime() < winInfos[j]->getCreatedTime()) {
|
||||
auto info = winInfos[i];
|
||||
winInfos[i] = winInfos[j];
|
||||
winInfos[j] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto info : winInfos) {
|
||||
qInfo() << "close WindowId " << info->getXid();
|
||||
info->close(timestamp);
|
||||
}
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = "Close All";
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemForceQuit()
|
||||
{
|
||||
bool active = dock->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
|
||||
AppMenuAction fn = [&](uint32_t) {
|
||||
qInfo() << "do MenuItem: Force Quit";
|
||||
forceQuit();
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = "Force Quit";
|
||||
item.action = fn;
|
||||
item.isActive = active;
|
||||
return item;
|
||||
}
|
||||
|
||||
//dock栏上Android程序的Force Quit功能
|
||||
AppMenuItem Entry::getMenuItemForceQuitAndroid()
|
||||
{
|
||||
bool active = dock->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
|
||||
auto allowedCloseWindows = getAllowedCloseWindows();
|
||||
AppMenuAction fn = [](uint32_t){};
|
||||
if (allowedCloseWindows.size() > 0) {
|
||||
qInfo() << "do MenuItem: Force Quit";
|
||||
AppMenuAction fn = [&](uint32_t timestamp) {
|
||||
for (auto info : allowedCloseWindows) {
|
||||
info->close(timestamp);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = "Force Quit";
|
||||
item.action = fn;
|
||||
item.isActive = active;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemDock()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = "Dock";
|
||||
item.action = [&](uint32_t) {
|
||||
qInfo() << "do MenuItem: Dock";
|
||||
requestDock();
|
||||
};
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemUndock()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = "Undock";
|
||||
item.action = [&](uint32_t) {
|
||||
qInfo() << "do MenuItem: Undock";
|
||||
requestUndock();
|
||||
};
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemAllWindows()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = "All Windows";
|
||||
item.action = [&](uint32_t) {
|
||||
qInfo() << "do MenuItem: All Windows";
|
||||
presentWindows();
|
||||
};
|
||||
item.isActive = true;
|
||||
item.hint = menuItemHintShowAllWindows;
|
||||
return item;
|
||||
}
|
||||
|
||||
bool Entry::killProcess(int pid)
|
||||
{
|
||||
bool ret = true;
|
||||
Process p(pid);
|
||||
if (p.isExist()) {
|
||||
ret = !kill(pid, SIGTERM);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Entry::setPropDesktopFile(QString value)
|
||||
{
|
||||
bool ret = false;
|
||||
if (value != desktopFile) {
|
||||
desktopFile = value;
|
||||
ret = true;
|
||||
Q_EMIT desktopFileChanged(value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
149
src/modules/dock/entry.h
Normal file
149
src/modules/dock/entry.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENTRY_H
|
||||
#define ENTRY_H
|
||||
|
||||
#include "appinfo.h"
|
||||
#include "appmenu.h"
|
||||
#include "windowinfobase.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QObject>
|
||||
|
||||
struct ExportWindowInfo {
|
||||
XWindow xid;
|
||||
QString title;
|
||||
bool flash;
|
||||
};
|
||||
|
||||
// 单个应用类
|
||||
class Dock;
|
||||
class Entry: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent = nullptr);
|
||||
~Entry();
|
||||
|
||||
bool isValid();
|
||||
QString getId();
|
||||
QString getName();
|
||||
void updateName();
|
||||
QString getIcon();
|
||||
QString getInnerId();
|
||||
void setInnerId(QString _innerId);
|
||||
QString getFileName();
|
||||
AppInfo *getApp();
|
||||
void setApp(AppInfo *appinfo);
|
||||
bool getIsDocked();
|
||||
void setIsDocked(bool value);
|
||||
void startExport();
|
||||
void stopExport();
|
||||
void setMenu(AppMenu *_menu);
|
||||
void updateMenu();
|
||||
void updateIcon();
|
||||
void forceUpdateIcon();
|
||||
void updateIsActive();
|
||||
WindowInfoBase *getWindowInfoByPid(int pid);
|
||||
WindowInfoBase *getWindowInfoByWinId(XWindow windowId);
|
||||
void setPropIsDocked(bool docked);
|
||||
void setPropIcon(QString value);
|
||||
void setPropName(QString value);
|
||||
void setPropIsActive(bool active);
|
||||
void setPropCurrentWindow(XWindow value);
|
||||
void setCurrentWindowInfo(WindowInfoBase *windowInfo);
|
||||
WindowInfoBase *getCurrentWindowInfo();
|
||||
QString getExec(bool oneLine);
|
||||
bool hasWindow();
|
||||
void updateWindowInfos();
|
||||
bool detachWindow(WindowInfoBase *info);
|
||||
bool attachWindow(WindowInfoBase *info);
|
||||
void launchApp(uint32_t timestamp);
|
||||
bool containsWindow(XWindow xid);
|
||||
void deleteWindow(XWindow xid);
|
||||
|
||||
void handleMenuItem(uint32_t timestamp, QString itemId);
|
||||
void handleDragDrop(uint32_t timestamp, QStringList files);
|
||||
void requestDock();
|
||||
void requestUndock();
|
||||
void newInstance(uint32_t timestamp);
|
||||
void check();
|
||||
void forceQuit();
|
||||
void presentWindows();
|
||||
void active(uint32_t timestamp);
|
||||
|
||||
XWindow getCurrentWindow();
|
||||
QString getDesktopFile();
|
||||
bool getIsActive();
|
||||
QString getMenu();
|
||||
QVector<XWindow> getAllowedClosedWindowIds();
|
||||
QList<ExportWindowInfo> getExportWindowInfos();
|
||||
|
||||
public Q_SLOTS:
|
||||
QVector<WindowInfoBase *> getAllowedCloseWindows();
|
||||
|
||||
Q_SIGNALS:
|
||||
void isActiveChanged(bool value);
|
||||
void isDockedChanged(bool value);
|
||||
void menuChanged(QString value);
|
||||
void iconChanged(QString value);
|
||||
void nameChanged(QString value);
|
||||
void desktopFileChanged(QString value);
|
||||
void currentWindowChanged(uint32_t value);
|
||||
|
||||
private:
|
||||
// 右键菜单项
|
||||
QVector<AppMenuItem> getMenuItemDesktopActions();
|
||||
AppMenuItem getMenuItemLaunch();
|
||||
AppMenuItem getMenuItemCloseAll();
|
||||
AppMenuItem getMenuItemForceQuit();
|
||||
AppMenuItem getMenuItemForceQuitAndroid();
|
||||
AppMenuItem getMenuItemDock();
|
||||
AppMenuItem getMenuItemUndock();
|
||||
AppMenuItem getMenuItemAllWindows();
|
||||
bool killProcess(int pid);
|
||||
bool setPropDesktopFile(QString value);
|
||||
|
||||
Dock *dock;
|
||||
AppInfo *app;
|
||||
AppMenu *menu;
|
||||
|
||||
bool isActive;
|
||||
bool isDocked;
|
||||
|
||||
QString id;
|
||||
QString name;
|
||||
QString icon;
|
||||
QString innerId;
|
||||
QString desktopFile;
|
||||
|
||||
// Dbus属性直接放到interface上
|
||||
QMap<XWindow, WindowInfoBase *> windowInfos; // 该应用所有窗口
|
||||
QList<ExportWindowInfo> exportWindowInfos;
|
||||
WindowInfoBase *current; // 当前窗口
|
||||
XWindow currentWindow; //当前窗口Id
|
||||
bool winIconPreferred;
|
||||
QString objctPath;
|
||||
};
|
||||
|
||||
#endif // ENTRY_H
|
141
src/modules/dock/processinfo.cpp
Normal file
141
src/modules/dock/processinfo.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "processinfo.h"
|
||||
#include "dstring.h"
|
||||
#include "dfile.h"
|
||||
|
||||
ProcessInfo::ProcessInfo(int pid)
|
||||
: hasPid(true)
|
||||
, process(Process(pid))
|
||||
{
|
||||
if (pid == 0)
|
||||
return;
|
||||
|
||||
// exe
|
||||
exe = process.getExe();
|
||||
// cwd
|
||||
cwd = process.getCwd();
|
||||
// cmdline
|
||||
cmdLine = process.getCmdLine();
|
||||
// ppid
|
||||
Status pstatus = process.getStatus();
|
||||
if (pstatus.size() > 0) {
|
||||
int ppid = process.getPpid();
|
||||
}
|
||||
// args
|
||||
auto verifyExe = [](std::string exe, std::string cwd, std::string firstArg){
|
||||
if (DFile::base(firstArg) == firstArg)
|
||||
return true;
|
||||
|
||||
if (!DFile::isAbs(firstArg))
|
||||
firstArg = cwd + firstArg;
|
||||
|
||||
return exe == firstArg;
|
||||
};
|
||||
if (!verifyExe(exe, cwd, cmdLine[0])) {
|
||||
auto parts = DString::splitStr(cmdLine[0], ' ');
|
||||
// try again
|
||||
if (verifyExe(exe, cwd, parts[0])) {
|
||||
for (int j = 1; j < parts.size(); j++) {
|
||||
args.push_back(parts[j]);
|
||||
}
|
||||
for (int i = 1; i < cmdLine.size(); i++) {
|
||||
args.push_back(cmdLine[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < cmdLine.size(); i++) {
|
||||
args.push_back(cmdLine[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessInfo::ProcessInfo(std::vector<std::string> &cmd)
|
||||
: hasPid(false)
|
||||
, process(Process())
|
||||
{
|
||||
if (cmd.size() == 0)
|
||||
return;
|
||||
|
||||
cmdLine = cmd;
|
||||
exe = cmd[0];
|
||||
for (ulong i=0; i < cmd.size(); i++) {
|
||||
if (i > 0) {
|
||||
args.push_back(cmd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string ProcessInfo::getEnv(std::string key)
|
||||
{
|
||||
return process.getEnv(key);
|
||||
}
|
||||
|
||||
std::vector<std::string> ProcessInfo::getCmdLine()
|
||||
{
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
std::vector<std::string> ProcessInfo::getArgs()
|
||||
{
|
||||
return args;
|
||||
}
|
||||
|
||||
int ProcessInfo::getPid()
|
||||
{
|
||||
return process.getPid();
|
||||
}
|
||||
|
||||
int ProcessInfo::getPpid()
|
||||
{
|
||||
return process.getPpid();
|
||||
}
|
||||
|
||||
std::string ProcessInfo::getExe()
|
||||
{
|
||||
return exe;
|
||||
}
|
||||
|
||||
std::string ProcessInfo::getOneCommandLine()
|
||||
{
|
||||
std::string cmdline = getJoinedExeArgs();
|
||||
return "sh -c 'cd " + cwd + "; exec " + cmdline + ";'";
|
||||
}
|
||||
|
||||
std::string ProcessInfo::getShellScriptLines()
|
||||
{
|
||||
std::string cmdline = getJoinedExeArgs();
|
||||
return "#!/bin/sh\n cd " + cwd + "\n exec " + cmdline + "\n";
|
||||
}
|
||||
|
||||
std::string ProcessInfo::getJoinedExeArgs()
|
||||
{
|
||||
std::string ret = "\"" + exe + "\"";
|
||||
for (auto arg : args) {
|
||||
ret += " \"" + arg + "\"";
|
||||
}
|
||||
|
||||
ret += " $@";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
58
src/modules/dock/processinfo.h
Normal file
58
src/modules/dock/processinfo.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESSINFO_H
|
||||
#define PROCESSINFO_H
|
||||
|
||||
#include "process.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// 进程信息
|
||||
class ProcessInfo
|
||||
{
|
||||
public:
|
||||
ProcessInfo(int pid);
|
||||
ProcessInfo(std::vector<std::string> &cmd);
|
||||
|
||||
std::string getEnv(std::string key);
|
||||
std::vector<std::string> getCmdLine();
|
||||
std::vector<std::string> getArgs();
|
||||
int getPid();
|
||||
int getPpid();
|
||||
std::string getExe();
|
||||
std::string getOneCommandLine();
|
||||
std::string getShellScriptLines();
|
||||
|
||||
private:
|
||||
std::string getJoinedExeArgs();
|
||||
|
||||
std::vector<std::string> cmdLine;
|
||||
std::vector<std::string> args;
|
||||
std::string exe;
|
||||
std::string cwd;
|
||||
|
||||
bool hasPid;
|
||||
Process process;
|
||||
};
|
||||
|
||||
#endif // PROCESSINFO_H
|
127
src/modules/dock/waylandmanager.cpp
Normal file
127
src/modules/dock/waylandmanager.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "waylandmanager.h"
|
||||
#include "dock.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
WaylandManager::WaylandManager(Dock *_dock, QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(_dock)
|
||||
, mutex(QMutex(QMutex::NonRecursive))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 注册窗口
|
||||
void WaylandManager::registerWindow(const QString &objPath)
|
||||
{
|
||||
qInfo() << "registerWindow: " << objPath;
|
||||
if (findWindowByObjPath(objPath))
|
||||
return;
|
||||
|
||||
PlasmaWindow *plasmaWindow = dock->createPlasmaWindow(objPath);
|
||||
if (!plasmaWindow) {
|
||||
qWarning() << "registerWindowWayland: createPlasmaWindow failed";
|
||||
return;
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
XWindow winId = XCB->allocId(); // XCB中未发现释放XID接口
|
||||
XWindow realId = plasmaWindow->WindowId();
|
||||
if (!realId)
|
||||
winId = realId;
|
||||
|
||||
WindowInfoK *winInfo = new WindowInfoK(plasmaWindow, winId);
|
||||
dock->listenKWindowSignals(winInfo);
|
||||
insertWindow(objPath, winInfo);
|
||||
dock->attachOrDetachWindow(winInfo);
|
||||
if (realId) {
|
||||
windowInfoMap[realId] = winInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// 取消注册窗口
|
||||
void WaylandManager::unRegisterWindow(const QString &objPath)
|
||||
{
|
||||
qInfo() << "unRegisterWindow: " << objPath;
|
||||
WindowInfoK *winInfo = findWindowByObjPath(objPath);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
dock->removePlasmaWindowHandler(winInfo->getPlasmaWindow());
|
||||
dock->detachWindow(winInfo);
|
||||
deleteWindow(objPath);
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::handleActiveWindowChangedK(uint activeWin)
|
||||
{
|
||||
WindowInfoK *winInfo = nullptr;
|
||||
QMutexLocker locker(&mutex);
|
||||
for (auto iter = kWinInfos.begin(); iter != kWinInfos.end(); iter++) {
|
||||
if (iter.value()->getInnerId() == activeWin) {
|
||||
winInfo = iter.value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return winInfo;
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::findWindowByXid(XWindow xid)
|
||||
{
|
||||
WindowInfoK *winInfo = nullptr;
|
||||
for (auto iter = kWinInfos.begin(); iter != kWinInfos.end(); iter++) {
|
||||
if (iter.value()->getXid() == xid) {
|
||||
winInfo = iter.value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return winInfo;
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::findWindowByObjPath(QString objPath)
|
||||
{
|
||||
if (kWinInfos.find(objPath) == kWinInfos.end())
|
||||
return nullptr;
|
||||
|
||||
return kWinInfos[objPath];
|
||||
}
|
||||
|
||||
void WaylandManager::insertWindow(QString objPath, WindowInfoK *windowInfo)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
kWinInfos[objPath] = windowInfo;
|
||||
}
|
||||
|
||||
void WaylandManager::deleteWindow(QString objPath)
|
||||
{
|
||||
kWinInfos.remove(objPath);
|
||||
}
|
||||
|
56
src/modules/dock/waylandmanager.h
Normal file
56
src/modules/dock/waylandmanager.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WAYLANDMANAGER_H
|
||||
#define WAYLANDMANAGER_H
|
||||
|
||||
#include "windowinfok.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
||||
class Dock;
|
||||
|
||||
// 管理wayland窗口
|
||||
class WaylandManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaylandManager(Dock *_dock, QObject *parent = nullptr);
|
||||
|
||||
void registerWindow(const QString &objPath);
|
||||
void unRegisterWindow(const QString &objPath);
|
||||
|
||||
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
|
||||
WindowInfoK *findWindowByXid(XWindow xid);
|
||||
WindowInfoK *findWindowByObjPath(QString objPath);
|
||||
void insertWindow(QString objPath, WindowInfoK *windowInfo);
|
||||
void deleteWindow(QString objPath);
|
||||
|
||||
private:
|
||||
Dock *dock;
|
||||
QMap<QString, WindowInfoK *> kWinInfos; // dbusObjectPath -> kwayland window Info
|
||||
QMap<XWindow, WindowInfoK *> windowInfoMap;
|
||||
QMutex mutex;
|
||||
};
|
||||
|
||||
#endif // WAYLANDMANAGER_H
|
545
src/modules/dock/windowidentify.cpp
Normal file
545
src/modules/dock/windowidentify.cpp
Normal file
@ -0,0 +1,545 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "windowidentify.h"
|
||||
#include "common.h"
|
||||
#include "appinfo.h"
|
||||
#include "dock.h"
|
||||
#include "processinfo.h"
|
||||
#include "dstring.h"
|
||||
#include "basedir.h"
|
||||
#include "dfile.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
WindowPatterns WindowIdentify::patterns;
|
||||
|
||||
static QMap<QString, QString> crxAppIdMap = {
|
||||
{"crx_onfalgmmmaighfmjgegnamdjmhpjpgpi", "apps.com.aiqiyi"},
|
||||
{"crx_gfhkopakpiiaeocgofdpcpjpdiglpkjl", "apps.cn.kugou.hd"},
|
||||
{"crx_gaoopbnflngfkoobibfgbhobdeiipcgh", "apps.cn.kuwo.kwmusic"},
|
||||
{"crx_jajaphleehpmpblokgighfjneejapnok", "apps.com.evernote"},
|
||||
{"crx_ebhffdbfjilfhahiinoijchmlceailfn", "apps.com.letv"},
|
||||
{"crx_almpoflgiciaanepplakjdkiaijmklld", "apps.com.tongyong.xxbox"},
|
||||
{"crx_heaphplipeblmpflpdcedfllmbehonfo", "apps.com.peashooter"},
|
||||
{"crx_dbngidmdhcooejaggjiochbafiaefndn", "apps.com.rovio.angrybirdsseasons"},
|
||||
{"crx_chfeacahlaknlmjhiagghobhkollfhip", "apps.com.sina.weibo"},
|
||||
{"crx_cpbmecbkmjjfemjiekledmejoakfkpec", "apps.com.openapp"},
|
||||
{"crx_lalomppgkdieklbppclocckjpibnlpjc", "apps.com.baidutieba"},
|
||||
{"crx_gejbkhjjmicgnhcdpgpggboldigfhgli", "apps.com.zhuishushenqi"},
|
||||
{"crx_gglenfcpioacendmikabbkecnfpanegk", "apps.com.duokan"},
|
||||
{"crx_nkmmgdfgabhefacpfdabadjfnpffhpio", "apps.com.zhihu.daily"},
|
||||
{"crx_ajkogonhhcighbinfgcgnjiadodpdicb", "apps.com.netease.newsreader"},
|
||||
{"crx_hgggjnaaklhemplabjhgpodlcnndhppo", "apps.com.baidu.music.pad"},
|
||||
{"crx_ebmgfebnlgilhandilnbmgadajhkkmob", "apps.cn.ibuka"},
|
||||
{"crx_nolebplcbgieabkblgiaacdpgehlopag", "apps.com.tianqitong"},
|
||||
{"crx_maghncnmccfbmkekccpmkjjfcmdnnlip", "apps.com.youjoy.strugglelandlord"},
|
||||
{"crx_heliimhfjgfabpgfecgdhackhelmocic", "apps.cn.emoney"},
|
||||
{"crx_jkgmneeafmgjillhgmjbaipnakfiidpm", "apps.com.instagram"},
|
||||
{"crx_cdbkhmfmikobpndfhiphdbkjklbmnakg", "apps.com.easymindmap"},
|
||||
{"crx_djflcciklfljleibeinjmjdnmenkciab", "apps.com.lgj.thunderbattle"},
|
||||
{"crx_ffdgbolnndgeflkapnmoefhjhkeilfff", "apps.com.qianlong"},
|
||||
{"crx_fmpniepgiofckbfgahajldgoelogdoap", "apps.com.windhd"},
|
||||
{"crx_dokjmallmkihbgefmladclcdcinjlnpj", "apps.com.youdao.hanyu"},
|
||||
{"crx_dicimeimfmbfcklbjdpnlmjgegcfilhm", "apps.com.ibookstar"},
|
||||
{"crx_cokkcjnpjfffianjbpjbcgjefningkjm", "apps.com.yidianzixun"},
|
||||
{"crx_ehflkacdpmeehailmcknlnkmjalehdah", "apps.com.xplane"},
|
||||
{"crx_iedokjbbjejfinokgifgecmboncmkbhb", "apps.com.wedevote"},
|
||||
{"crx_eaefcagiihjpndconigdpdmcbpcamaok", "apps.com.tongwei.blockbreaker"},
|
||||
{"crx_mkjjfibpccammnliaalefmlekiiikikj", "apps.com.dayima"},
|
||||
{"crx_gflkpppiigdigkemnjlonilmglokliol", "apps.com.cookpad"},
|
||||
{"crx_jfhpkchgedddadekfeganigbenbfaohe", "apps.com.issuu"},
|
||||
{"crx_ggkmfnbkldhmkehabgcbnmlccfbnoldo", "apps.bible.cbol"},
|
||||
{"crx_phlhkholfcljapmcidanddmhpcphlfng", "apps.com.kanjian.radio"},
|
||||
{"crx_bjgfcighhaahojkibojkdmpdihhcehfm", "apps.de.danoeh.antennapod"},
|
||||
{"crx_kldipknjommdfkifomkmcpbcnpmcnbfi", "apps.com.asoftmurmur"},
|
||||
{"crx_jfhlegimcipljdcionjbipealofoncmd", "apps.com.tencentnews"},
|
||||
{"crx_aikgmfkpmmclmpooohngmcdimgcocoaj", "apps.com.tonghuashun"},
|
||||
{"crx_ifimglalpdeoaffjmmihoofapmpflkad", "apps.com.letv.lecloud.disk"},
|
||||
{"crx_pllcekmbablpiogkinogefpdjkmgicbp", "apps.com.hwadzanebook"},
|
||||
{"crx_ohcknkkbjmgdfcejpbmhjbohnepcagkc", "apps.com.douban.radio"},
|
||||
};
|
||||
|
||||
WindowIdentify::WindowIdentify(Dock *_dock, QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(_dock)
|
||||
{
|
||||
identifyWindowFuns["Android"] = identifyWindowAndroid;
|
||||
identifyWindowFuns["PidEnv"] = identifyWindowByPidEnv;
|
||||
identifyWindowFuns["CmdlineTurboBooster"] = identifyWindowByCmdlineTurboBooster;
|
||||
identifyWindowFuns["Cmdline-XWalk"] = identifyWindowByCmdlineXWalk;
|
||||
identifyWindowFuns["FlatpakAppID"] = identifyWindowByFlatpakAppID;
|
||||
identifyWindowFuns["CrxId"] = identifyWindowByCrxId;
|
||||
identifyWindowFuns["Rule"] = identifyWindowByRule;
|
||||
identifyWindowFuns["Bamf"] = identifyWindowByBamf;
|
||||
identifyWindowFuns["Pid"] = identifyWindowByPid;
|
||||
identifyWindowFuns["Scratch"] = identifyWindowByScratch;
|
||||
identifyWindowFuns["GtkAppId"] = identifyWindowByGtkAppId;
|
||||
identifyWindowFuns["WmClass"] = identifyWindowByWmClass;
|
||||
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindow(WindowInfoBase *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
//qInfo() << "identifyWindow: window id " << winInfo->getXid() << " innerId " << winInfo->getInnerId();
|
||||
if (winInfo->getWindowType() == "X11")
|
||||
ret = identifyWindowX11(static_cast<WindowInfoX *>(winInfo), innerId);
|
||||
else if (winInfo->getWindowType() == "Wayland")
|
||||
ret = identifyWindowWayland(static_cast<WindowInfoK *>(winInfo), innerId);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowX11(WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *appInfo = nullptr;
|
||||
if (winInfo->getInnerId() == "") {
|
||||
qInfo() << "identify WindowX11: innerId is empty";
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
for (auto iter = identifyWindowFuns.begin(); iter != identifyWindowFuns.end(); iter++) {
|
||||
QString name = iter.key();
|
||||
IdentifyFunc func = iter.value();
|
||||
qInfo() << "identifyWindowX11: try " << name;
|
||||
appInfo = func(dock, winInfo, innerId);
|
||||
if (appInfo) { // TODO: if name == "Pid", appInfo may by nullptr
|
||||
// 识别成功
|
||||
qInfo() << "identify Window by " << name << " innerId " << appInfo->getInnerId() << " success!";
|
||||
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
|
||||
if (fixedAppInfo) {
|
||||
delete appInfo;
|
||||
appInfo = fixedAppInfo;
|
||||
appInfo->setIdentifyMethod(name + "+FixAutostart");
|
||||
innerId = appInfo->getInnerId();
|
||||
} else {
|
||||
appInfo->setIdentifyMethod(name);
|
||||
}
|
||||
return appInfo;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowX11: failed";
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowWayland(WindowInfoK *winInfo, QString &innerId)
|
||||
{
|
||||
// TODO: 对桌面调起的文管应用做规避处理,需要在此处添加,因为初始化时appId和title为空
|
||||
if (winInfo->getAppId() == "dde-desktop" && dock->shouldShowOnDock(winInfo)) {
|
||||
winInfo->setAppId("dde-file-manager");
|
||||
}
|
||||
|
||||
QString appId = winInfo->getAppId();
|
||||
if (appId.isEmpty()) {
|
||||
QString title = winInfo->getTitle();
|
||||
// TODO: 对于appId为空的情况,使用title过滤,此项修改针对浏览器下载窗口
|
||||
|
||||
}
|
||||
|
||||
// 先使用appId获取appInfo,如果不能成功获取再使用GIO_LAUNCHED_DESKTOP_FILE环境变量获取
|
||||
AppInfo *appInfo = new AppInfo(appId);
|
||||
if (!appInfo->isValidApp() && winInfo->getProcess()) {
|
||||
ProcessInfo *process = winInfo->getProcess();
|
||||
std::string desktopFilePath = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
|
||||
if (DString::endWith(desktopFilePath, ".desktop")) {
|
||||
appInfo = new AppInfo(desktopFilePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// autoStart
|
||||
if (appInfo->isValidApp()) {
|
||||
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
|
||||
if (fixedAppInfo) {
|
||||
delete appInfo;
|
||||
appInfo = fixedAppInfo;
|
||||
appInfo->setIdentifyMethod("FixAutostart");
|
||||
}
|
||||
} else {
|
||||
// bamf
|
||||
XWindow winId = winInfo->getXid();
|
||||
QString desktop = dock->getDesktopFromWindowByBamf(winId);
|
||||
if (!desktop.isEmpty()) {
|
||||
appInfo = new AppInfo(desktop);
|
||||
}
|
||||
|
||||
WMClass wmClass = XCB->getWMClass(winId);
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
QString instance(wmClass.instanceName.c_str());
|
||||
appInfo = new AppInfo("org.deepin.flatdeb." + instance);
|
||||
if (appInfo)
|
||||
return appInfo;
|
||||
|
||||
appInfo = new AppInfo(instance);
|
||||
if (appInfo)
|
||||
return appInfo;
|
||||
|
||||
if (wmClass.className.size() > 0) {
|
||||
appInfo = new AppInfo(wmClass.className.c_str());
|
||||
if (appInfo)
|
||||
return appInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appInfo)
|
||||
innerId = appInfo->getInnerId();
|
||||
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowAndroid(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int32_t androidId = getAndroidUengineId(winInfo->getXid());
|
||||
QString androidName = getAndroidUengineName(winInfo->getXid());
|
||||
if (androidId != -1 && androidName != "") {
|
||||
QString desktopPath = "/usr/share/applications/uengine." + androidName + ".desktop";
|
||||
DesktopInfo desktopInfo(desktopPath.toStdString());
|
||||
if (!desktopInfo.isValidDesktop()) {
|
||||
qInfo() << "identifyWindowAndroid: not exist DesktopFile " << desktopPath;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = new AppInfo(desktopInfo);
|
||||
ret->setIdentifyMethod("Android");
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByPidEnv(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int pid = winInfo->getPid();
|
||||
auto process = winInfo->getProcess();
|
||||
qInfo() << "identifyWindowByPidEnv: pid=" << pid << " WindowId=" << winInfo->getXid();
|
||||
if (pid != 0 && process) {
|
||||
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE").c_str();
|
||||
QString launchedDesktopFilePidStr = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE_PID").c_str();
|
||||
int launchedDesktopFilePid = launchedDesktopFilePidStr.toInt();
|
||||
qInfo() << "launchedDesktopFilePid=" << launchedDesktopFilePid << " launchedDesktopFile=" << launchedDesktopFile;
|
||||
|
||||
// 以下 2 种情况下,才能信任环境变量 GIO_LAUNCHED_DESKTOP_FILE。
|
||||
// 1. 当窗口 pid 和 launchedDesktopFilePid 相同时;
|
||||
// 2. 当窗口的进程的父进程 id(即 ppid)和 launchedDesktopFilePid 相同,
|
||||
// 并且该父进程是 sh 或 bash 时。
|
||||
bool needTry = false;
|
||||
if (pid == launchedDesktopFilePid) {
|
||||
needTry = true;
|
||||
} else if (process->getPpid() && process->getPpid() == launchedDesktopFilePid) {
|
||||
Process parentProcess(launchedDesktopFilePid);
|
||||
auto parentCmdLine = parentProcess.getCmdLine();
|
||||
if (parentCmdLine.size() > 0) {
|
||||
qInfo() << "ppid equal " << "parentCmdLine[0]:" << parentCmdLine[0].c_str();
|
||||
QString cmd0 = parentCmdLine[0].c_str();
|
||||
int pos = cmd0.lastIndexOf('/');
|
||||
if (pos > 0)
|
||||
cmd0 = cmd0.remove(0, pos + 1);
|
||||
|
||||
if (cmd0 == "sh" || cmd0 == "bash")
|
||||
needTry = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needTry) {
|
||||
ret = new AppInfo(launchedDesktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCmdlineTurboBooster(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int pid = winInfo->getPid();
|
||||
ProcessInfo *process = winInfo->getProcess();
|
||||
if (pid != 0 && process) {
|
||||
auto cmdline = process->getCmdLine();
|
||||
if (cmdline.size() > 0) {
|
||||
QString desktopFile;
|
||||
if (DString::endWith(cmdline[0], ".desktop")) {
|
||||
desktopFile = cmdline[0].c_str();
|
||||
} else if (QString(cmdline[0].c_str()).contains("/applications/")) {
|
||||
QFileInfo fileInfo(cmdline[0].c_str());
|
||||
QString path = fileInfo.path();
|
||||
QString base = fileInfo.baseName();
|
||||
QDir dir(path);
|
||||
QStringList files = dir.entryList(QDir::Files);
|
||||
for (auto f : files) {
|
||||
if (f.contains(path + "/" + base + ".desktop")) {
|
||||
desktopFile = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByCmdlineTurboBooster: desktopFile is " << desktopFile;
|
||||
if (!desktopFile.isEmpty()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCmdlineXWalk(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
qInfo() << "identifyWindowByCmdlineXWalk: windowId=" << winInfo->getXid();
|
||||
AppInfo *ret = nullptr;
|
||||
do {
|
||||
auto process = winInfo->getProcess();
|
||||
if (!process || !winInfo->getPid())
|
||||
break;
|
||||
|
||||
QString exe = process->getExe().c_str();
|
||||
QFileInfo file(exe);
|
||||
QString exeBase = file.baseName();
|
||||
auto args = process->getArgs();
|
||||
if (exe != "xwalk" || args.size() == 0)
|
||||
break;
|
||||
|
||||
QString lastArg = args[args.size() - 1].c_str();
|
||||
file.setFile(lastArg);
|
||||
if (file.baseName() == "manifest.json") {
|
||||
auto strs = lastArg.split("/");
|
||||
if (strs.size() > 3 && strs[strs.size() - 2].size() > 0) { // appId为 strs倒数第二个字符串
|
||||
ret = new AppInfo(strs[strs.size() - 2]);
|
||||
innerId = ret->getInnerId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByCmdlineXWalk: failed";
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByFlatpakAppID(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString flatpak = winInfo->getFlatpakAppId();
|
||||
qInfo() << "identifyWindowByFlatpakAppID: flatpak:" << flatpak;
|
||||
if (flatpak.startsWith("app/")) {
|
||||
auto parts = flatpak.split("/");
|
||||
if (parts.size() > 0) {
|
||||
QString appId = parts[1];
|
||||
ret = new AppInfo(appId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCrxId(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
WMClass wmClass = XCB->getWMClass(winInfo->getXid());
|
||||
QString className, instanceName;
|
||||
className.append(wmClass.className.c_str());
|
||||
instanceName.append(wmClass.instanceName.c_str());
|
||||
|
||||
if (className.toLower() == "chromium-browser" && instanceName.toLower().startsWith("crx_")) {
|
||||
if (crxAppIdMap.find(instanceName.toLower()) != crxAppIdMap.end()) {
|
||||
QString appId = crxAppIdMap[instanceName.toLower()];
|
||||
qInfo() << "identifyWindowByCrxId: appId " << appId;
|
||||
ret = new AppInfo(appId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByRule(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
qInfo() << "identifyWindowByRule: windowId=" << winInfo->getXid();
|
||||
AppInfo *ret = nullptr;
|
||||
QString matchStr = patterns.match(winInfo);
|
||||
if (matchStr.isEmpty())
|
||||
return ret;
|
||||
|
||||
if (matchStr.size() > 4 && matchStr.startsWith("id=")) {
|
||||
matchStr.remove(0, 3);
|
||||
ret = new AppInfo(matchStr);
|
||||
} else if (matchStr == "env") {
|
||||
auto process = winInfo->getProcess();
|
||||
if (process) {
|
||||
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE").c_str();
|
||||
if (!launchedDesktopFile.isEmpty())
|
||||
ret = new AppInfo(launchedDesktopFile);
|
||||
}
|
||||
} else {
|
||||
qInfo() << "patterns match bad result";
|
||||
}
|
||||
|
||||
if (ret)
|
||||
innerId = ret->getInnerId();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByBamf(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
XWindow xid = winInfo->getXid();
|
||||
qInfo() << "identifyWindowByBamf: windowId=" << xid;
|
||||
QString desktopFile;
|
||||
// 重试 bamf 识别,yozo office 的窗口经常要第二次时才能识别到。
|
||||
for (int i=0; i<3; i++) {
|
||||
desktopFile = _dock->getDesktopFromWindowByBamf(xid);
|
||||
if (!desktopFile.isEmpty())
|
||||
break;
|
||||
|
||||
QThread::msleep(100);
|
||||
}
|
||||
|
||||
if (!desktopFile.isEmpty()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByPid(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
if (winInfo->getPid() > 10) {
|
||||
auto entry = _dock->getEntryByWindowId(winInfo->getPid());
|
||||
if (entry) {
|
||||
ret = entry->getApp();
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByScratch(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString desktopFile = scratchDir + winInfo->getInnerId() + ".desktop";
|
||||
qInfo() << "identifyWindowByScratch: xid " << winInfo->getXid() << " desktopFile" << desktopFile;
|
||||
QFile file(desktopFile);
|
||||
|
||||
if (file.exists()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByGtkAppId(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString gtkAppId = winInfo->getGtkAppId();
|
||||
if (!gtkAppId.isEmpty()) {
|
||||
ret = new AppInfo(gtkAppId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByGtkAppId: gtkAppId:" << gtkAppId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByWmClass(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
do {
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
// example:
|
||||
// WM_CLASS(STRING) = "Brackets", "Brackets"
|
||||
// wm class instance is Brackets
|
||||
// try app id org.deepin.flatdeb.brackets
|
||||
ret = new AppInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower());
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = new AppInfo(wmClass.instanceName.c_str());
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (wmClass.className.size() > 0) {
|
||||
ret = new AppInfo(wmClass.className.c_str());
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (ret)
|
||||
innerId = ret->getInnerId();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::fixAutostartAppInfo(QString fileName)
|
||||
{
|
||||
QFileInfo file(fileName);
|
||||
QString filePath = file.absolutePath();
|
||||
bool isAutoStart = false;
|
||||
for (auto &dir : BaseDir::autoStartDirs()) {
|
||||
if (QString(dir.c_str()).contains(filePath)) {
|
||||
isAutoStart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isAutoStart ? new AppInfo(file.baseName()) : nullptr;
|
||||
}
|
||||
|
||||
int32_t WindowIdentify::getAndroidUengineId(XWindow winId)
|
||||
{
|
||||
// TODO 获取AndroidUengineId
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString WindowIdentify::getAndroidUengineName(XWindow winId)
|
||||
{
|
||||
// TODO 获取AndroidUengineName
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
75
src/modules/dock/windowidentify.h
Normal file
75
src/modules/dock/windowidentify.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWIDENTIFY_H
|
||||
#define WINDOWIDENTIFY_H
|
||||
|
||||
#include "windowpatterns.h"
|
||||
#include "windowinfok.h"
|
||||
#include "windowinfox.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
|
||||
class AppInfo;
|
||||
class Dock;
|
||||
|
||||
typedef AppInfo *(*IdentifyFunc)(Dock *, WindowInfoX*, QString &innerId);
|
||||
|
||||
// 应用窗口识别类
|
||||
class WindowIdentify : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WindowIdentify(Dock *_dock, QObject *parent = nullptr);
|
||||
|
||||
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
|
||||
AppInfo *identifyWindowX11(WindowInfoX *winInfo, QString &innerId);
|
||||
AppInfo *identifyWindowWayland(WindowInfoK *winInfo, QString &innerId);
|
||||
|
||||
static AppInfo *identifyWindowAndroid(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByPidEnv(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCmdlineTurboBooster(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCmdlineXWalk(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByFlatpakAppID(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCrxId(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByRule(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByBamf(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByPid(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByScratch(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByGtkAppId(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByWmClass(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
private:
|
||||
AppInfo *fixAutostartAppInfo(QString fileName);
|
||||
static int32_t getAndroidUengineId(XWindow winId);
|
||||
static QString getAndroidUengineName(XWindow winId);
|
||||
|
||||
static WindowPatterns patterns; // 根据rule识别
|
||||
Dock *dock;
|
||||
QMap<QString, IdentifyFunc> identifyWindowFuns;
|
||||
};
|
||||
|
||||
#endif // IDENTIFYWINDOW_H
|
80
src/modules/dock/windowinfobase.h
Normal file
80
src/modules/dock/windowinfobase.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWINFOBASE_H
|
||||
#define WINDOWINFOBASE_H
|
||||
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class Entry;
|
||||
class AppInfo;
|
||||
class ProcessInfo;
|
||||
class WindowInfoBase
|
||||
{
|
||||
public:
|
||||
WindowInfoBase() : entry(nullptr), app(nullptr), processInfo(nullptr) {}
|
||||
virtual ~WindowInfoBase() {}
|
||||
|
||||
|
||||
virtual bool shouldSkip() = 0;
|
||||
virtual QString getIcon() = 0;
|
||||
virtual QString getTitle() = 0;
|
||||
virtual bool isDemandingAttention() = 0;
|
||||
virtual void close(uint32_t timestamp) = 0;
|
||||
virtual void activate() = 0;
|
||||
virtual void minimize() = 0;
|
||||
virtual bool isMinimized() = 0;
|
||||
virtual int64_t getCreatedTime() = 0;
|
||||
virtual QString getWindowType() = 0;
|
||||
virtual QString getDisplayName() = 0;
|
||||
virtual bool allowClose() = 0;
|
||||
virtual void update() = 0;
|
||||
virtual void killClient() = 0;
|
||||
|
||||
XWindow getXid() {return xid;}
|
||||
void setEntry(Entry *value) {entry = value;}
|
||||
Entry *getEntry() {return entry;}
|
||||
QString getEntryInnerId() {return entryInnerId;}
|
||||
QString getInnerId() {return innerId;}
|
||||
void setEntryInnerId(QString value) {entryInnerId = value;}
|
||||
AppInfo *getAppInfo() {return app;}
|
||||
void setAppInfo(AppInfo *value) {app = value;}
|
||||
int getPid() {return pid;}
|
||||
ProcessInfo *getProcess() {return processInfo;}
|
||||
bool containAtom(QVector<XCBAtom> supports, XCBAtom ty) {return supports.indexOf(ty) != -1;}
|
||||
|
||||
protected:
|
||||
XWindow xid;
|
||||
QString title;
|
||||
QString icon;
|
||||
int pid;
|
||||
QString entryInnerId;
|
||||
QString innerId;
|
||||
Entry *entry;
|
||||
AppInfo *app;
|
||||
ProcessInfo *processInfo;
|
||||
int64_t createdTime;
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOBASE_H
|
210
src/modules/dock/windowinfok.cpp
Normal file
210
src/modules/dock/windowinfok.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "windowinfok.h"
|
||||
#include "entry.h"
|
||||
#include "processinfo.h"
|
||||
#include "appinfo.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
WindowInfoK::WindowInfoK(PlasmaWindow *window, XWindow _xid)
|
||||
: WindowInfoBase ()
|
||||
, updateCalled(false)
|
||||
, internalId(0)
|
||||
, demaningAttention(false)
|
||||
, closeable(true)
|
||||
, minimized(true)
|
||||
, plasmaWindow(window)
|
||||
{
|
||||
xid = _xid;
|
||||
createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
|
||||
}
|
||||
|
||||
WindowInfoK::~WindowInfoK()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool WindowInfoK::shouldSkip()
|
||||
{
|
||||
if (!updateCalled) {
|
||||
update();
|
||||
updateCalled = true;
|
||||
}
|
||||
|
||||
bool skip = plasmaWindow->SkipTaskbar();
|
||||
|
||||
// 添加窗口能否最小化判断, 如果窗口不能最小化则隐藏任务栏图标
|
||||
bool canMinimize = false;
|
||||
canMinimize = plasmaWindow->IsMinimizeable();
|
||||
if (!canMinimize)
|
||||
skip = true;
|
||||
|
||||
if (skip) {
|
||||
// 白名单, 过滤类似“欢迎应用”, 没有最小化窗口但是需要在任务栏显示图标
|
||||
QStringList list { "dde-introduction"};
|
||||
if (list.indexOf(appId) != -1)
|
||||
skip = false;
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
QString WindowInfoK::getIcon()
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
|
||||
QString WindowInfoK::getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
bool WindowInfoK::isDemandingAttention()
|
||||
{
|
||||
return demaningAttention;
|
||||
}
|
||||
|
||||
bool WindowInfoK::allowClose()
|
||||
{
|
||||
return closeable;
|
||||
}
|
||||
|
||||
void WindowInfoK::close(uint32_t timestamp)
|
||||
{
|
||||
plasmaWindow->RequestClose();
|
||||
}
|
||||
|
||||
QString WindowInfoK::getAppId()
|
||||
{
|
||||
return appId;
|
||||
}
|
||||
|
||||
void WindowInfoK::setAppId(QString _appId)
|
||||
{
|
||||
appId = _appId;
|
||||
}
|
||||
|
||||
void WindowInfoK::activate()
|
||||
{
|
||||
plasmaWindow->RequestActivate();
|
||||
}
|
||||
|
||||
void WindowInfoK::minimize()
|
||||
{
|
||||
plasmaWindow->RequestToggleMinimized();
|
||||
}
|
||||
|
||||
bool WindowInfoK::isMinimized()
|
||||
{
|
||||
return minimized;
|
||||
}
|
||||
|
||||
bool WindowInfoK::changeXid(XWindow _xid)
|
||||
{
|
||||
xid = _xid;
|
||||
return true;
|
||||
}
|
||||
|
||||
PlasmaWindow *WindowInfoK::getPlasmaWindow()
|
||||
{
|
||||
return plasmaWindow;
|
||||
}
|
||||
|
||||
bool WindowInfoK::updateGeometry()
|
||||
{
|
||||
Rect rect = plasmaWindow->Geometry();
|
||||
if (geometry == rect)
|
||||
return false;
|
||||
|
||||
geometry = rect;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowInfoK::updateTitle()
|
||||
{
|
||||
title = plasmaWindow->Title();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateDemandingAttention()
|
||||
{
|
||||
demaningAttention = plasmaWindow->IsDemandingAttention();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateIcon()
|
||||
{
|
||||
icon = plasmaWindow->Icon();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateAppId()
|
||||
{
|
||||
appId = plasmaWindow->AppId();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateInternalId()
|
||||
{
|
||||
internalId = plasmaWindow->InternalId();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateCloseable()
|
||||
{
|
||||
closeable = plasmaWindow->IsCloseable();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateProcessInfo()
|
||||
{
|
||||
pid = plasmaWindow->Pid();
|
||||
processInfo = new ProcessInfo(pid);
|
||||
}
|
||||
|
||||
int64_t WindowInfoK::getCreatedTime()
|
||||
{
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
// 主要是为兼容X11
|
||||
QString WindowInfoK::getDisplayName()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QString WindowInfoK::getWindowType()
|
||||
{
|
||||
return "Wayland";
|
||||
}
|
||||
|
||||
void WindowInfoK::update()
|
||||
{
|
||||
updateInternalId();
|
||||
updateAppId();
|
||||
updateIcon();
|
||||
updateTitle();
|
||||
updateGeometry();
|
||||
updateDemandingAttention();
|
||||
updateCloseable();
|
||||
updateProcessInfo();
|
||||
}
|
||||
|
||||
void WindowInfoK::killClient()
|
||||
{
|
||||
}
|
||||
|
79
src/modules/dock/windowinfok.h
Normal file
79
src/modules/dock/windowinfok.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWINFOK_H
|
||||
#define WINDOWINFOK_H
|
||||
|
||||
#include "windowinfobase.h"
|
||||
#include "dbusplasmawindow.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
class Entry;
|
||||
class ProcessInfo;
|
||||
|
||||
// wayland下窗口信息
|
||||
class WindowInfoK: public WindowInfoBase
|
||||
{
|
||||
public:
|
||||
WindowInfoK(PlasmaWindow *window, XWindow _xid = 0);
|
||||
virtual ~WindowInfoK();
|
||||
|
||||
virtual bool shouldSkip();
|
||||
virtual QString getIcon();
|
||||
virtual QString getTitle();
|
||||
virtual bool isDemandingAttention();
|
||||
virtual bool allowClose();
|
||||
virtual void close(uint32_t timestamp);
|
||||
virtual void activate();
|
||||
virtual void minimize();
|
||||
virtual bool isMinimized();
|
||||
virtual int64_t getCreatedTime();
|
||||
virtual QString getDisplayName();
|
||||
virtual QString getWindowType();
|
||||
virtual void update();
|
||||
virtual void killClient();
|
||||
|
||||
QString getAppId();
|
||||
void setAppId(QString _appId);
|
||||
bool changeXid(XWindow _xid);
|
||||
PlasmaWindow *getPlasmaWindow();
|
||||
bool updateGeometry();
|
||||
void updateTitle();
|
||||
void updateDemandingAttention();
|
||||
void updateIcon();
|
||||
void updateAppId();
|
||||
void updateInternalId();
|
||||
void updateCloseable();
|
||||
void updateProcessInfo();
|
||||
|
||||
private:
|
||||
bool updateCalled;
|
||||
QString appId;
|
||||
uint32_t internalId;
|
||||
bool demaningAttention;
|
||||
bool closeable;
|
||||
bool minimized;
|
||||
PlasmaWindow *plasmaWindow;
|
||||
Rect geometry;
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOK_H
|
447
src/modules/dock/windowinfox.cpp
Normal file
447
src/modules/dock/windowinfox.cpp
Normal file
@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "windowinfox.h"
|
||||
#include "appinfo.h"
|
||||
#include "xcbutils.h"
|
||||
#include "dstring.h"
|
||||
#include "common.h"
|
||||
#include "processinfo.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
WindowInfoX::WindowInfoX(XWindow _xid)
|
||||
: WindowInfoBase ()
|
||||
, x(0)
|
||||
, y(0)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, hasWMTransientFor(false)
|
||||
, hasXEmbedInfo(false)
|
||||
, updateCalled(false)
|
||||
{
|
||||
xid = _xid;
|
||||
createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
|
||||
}
|
||||
|
||||
WindowInfoX::~WindowInfoX()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool WindowInfoX::shouldSkip()
|
||||
{
|
||||
qInfo() << "window " << xid << " shouldSkip?";
|
||||
if (!updateCalled) {
|
||||
update();
|
||||
updateCalled = true;
|
||||
}
|
||||
|
||||
if (hasWmStateSkipTaskBar() || isValidModal() || shouldSkipWithWMClass())
|
||||
return true;
|
||||
|
||||
for (auto atom : wmWindowType) {
|
||||
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DIALOG") && !isActionMinimizeAllowed())
|
||||
return true;
|
||||
|
||||
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_UTILITY")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_COMBO")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DESKTOP")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DND")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DOCK")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_POPUP_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_SPLASH")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLBAR")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getIcon()
|
||||
{
|
||||
if (icon.isEmpty())
|
||||
icon = getIconFromWindow();
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void WindowInfoX::activate()
|
||||
{
|
||||
XCB->setActiveWindow(xid);
|
||||
}
|
||||
|
||||
void WindowInfoX::minimize()
|
||||
{
|
||||
XCB->minimizeWindow(xid);
|
||||
}
|
||||
|
||||
bool WindowInfoX::isMinimized()
|
||||
{
|
||||
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_HIDDEN"));
|
||||
}
|
||||
|
||||
int64_t WindowInfoX::getCreatedTime()
|
||||
{
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWindowType()
|
||||
{
|
||||
return "X11";
|
||||
}
|
||||
|
||||
bool WindowInfoX::allowClose()
|
||||
{
|
||||
// 允许关闭的条件:
|
||||
// 1. 不设置 functions 字段,即MotifHintFunctions 标志位;
|
||||
// 2. 或者设置了 functions 字段并且 设置了 MotifFunctionAll 标志位;
|
||||
// 3. 或者设置了 functions 字段并且 设置了 MotifFunctionClose 标志位。
|
||||
// 相关定义在 motif-2.3.8/lib/Xm/MwmUtil.h 。
|
||||
if ((motifWmHints.flags & MotifHintFunctions) == 0
|
||||
|| (motifWmHints.functions & MotifFunctionAll) != 0
|
||||
|| (motifWmHints.functions & MotifFunctionClose) != 0)
|
||||
return true;
|
||||
|
||||
for (auto action : wmAllowedActions) {
|
||||
if (action == XCB->getAtom("_NET_WM_ACTION_CLOSE")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getDisplayName()
|
||||
{
|
||||
XWindow winId = xid;
|
||||
//QString role = wmRole;
|
||||
QString className(wmClass.className.c_str());
|
||||
QString instance;
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
int pos = QString(wmClass.instanceName.c_str()).lastIndexOf('/');
|
||||
if (pos != -1)
|
||||
instance.remove(0, pos + 1);
|
||||
}
|
||||
qInfo() << "getDisplayName class:" << className << " ,instance:" << instance;
|
||||
|
||||
//if (!role.isEmpty() && !className.isEmpty())
|
||||
// return className + " " + role;
|
||||
|
||||
if (!className.isEmpty())
|
||||
return className;
|
||||
|
||||
if (!instance.isEmpty())
|
||||
return instance;
|
||||
|
||||
|
||||
QString _wmName = wmName;
|
||||
if (!_wmName.isEmpty()) {
|
||||
int pos = _wmName.lastIndexOf('-');
|
||||
if (pos != -1 && !_wmName.startsWith("-")) {
|
||||
_wmName.truncate(pos);
|
||||
return _wmName;
|
||||
}
|
||||
}
|
||||
|
||||
if (processInfo) {
|
||||
QString exe {processInfo->getEnv("exe").c_str()};
|
||||
if (!exe.isEmpty())
|
||||
return exe;
|
||||
}
|
||||
|
||||
return QString("window:%1").arg(winId);
|
||||
}
|
||||
|
||||
void WindowInfoX::killClient()
|
||||
{
|
||||
XCB->killClientChecked(xid);
|
||||
}
|
||||
|
||||
QString WindowInfoX::getGtkAppId()
|
||||
{
|
||||
return gtkAppId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getFlatpakAppId()
|
||||
{
|
||||
return flatpakAppId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWmRole()
|
||||
{
|
||||
return wmRole;
|
||||
}
|
||||
|
||||
WMClass WindowInfoX::getWMClass()
|
||||
{
|
||||
return wmClass;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWMName()
|
||||
{
|
||||
return wmName;
|
||||
}
|
||||
|
||||
ConfigureEvent *WindowInfoX::getLastConfigureEvent()
|
||||
{
|
||||
return lastConfigureNotifyEvent;
|
||||
}
|
||||
|
||||
void WindowInfoX::setLastConfigureEvent(ConfigureEvent *event)
|
||||
{
|
||||
lastConfigureNotifyEvent = event;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isGeometryChanged(int _x, int _y, int _width, int _height)
|
||||
{
|
||||
return !(_x == x && _y == y && _width == width && _height == height);
|
||||
}
|
||||
|
||||
void WindowInfoX::setGtkAppId(QString _gtkAppId)
|
||||
{
|
||||
gtkAppId = _gtkAppId;
|
||||
}
|
||||
|
||||
void WindowInfoX::updateMotifWmHints()
|
||||
{
|
||||
// get from XCB
|
||||
motifWmHints = XCB->getWindowMotifWMHints(xid);
|
||||
}
|
||||
|
||||
// XEmbed info
|
||||
// 一般 tray icon 会带有 _XEMBED_INFO 属性
|
||||
void WindowInfoX::updateHasXEmbedInfo()
|
||||
{
|
||||
hasXEmbedInfo = XCB->hasXEmbedInfo(xid);
|
||||
}
|
||||
|
||||
QString WindowInfoX::genInnerId(WindowInfoX *winInfo)
|
||||
{
|
||||
XWindow winId = winInfo->getXid();
|
||||
QString wmClassName, wmInstance;
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
if (wmClass.className.size() > 0)
|
||||
wmClassName = wmClass.className.c_str();
|
||||
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
QString instanceName(wmClass.instanceName.c_str());
|
||||
instanceName.remove(0, instanceName.lastIndexOf('/') + 1);
|
||||
wmInstance = instanceName;
|
||||
}
|
||||
|
||||
QString exe, args;
|
||||
if (winInfo->getProcess()) {
|
||||
exe = winInfo->getProcess()->getExe().c_str();
|
||||
for (auto arg : winInfo->getProcess()->getArgs()) {
|
||||
QString argStr(arg.c_str());
|
||||
if (argStr.contains("/") || argStr == "." || argStr == "..") {
|
||||
args += "%F ";
|
||||
} else {
|
||||
args += argStr + " ";
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 0)
|
||||
args.remove(args.size() - 2, 1);
|
||||
}
|
||||
|
||||
bool hasPid = winInfo->getPid() != 0;
|
||||
QString str;
|
||||
// NOTE: 不要使用 wmRole,有些程序总会改变这个值比如 GVim
|
||||
if (wmInstance.isEmpty() && wmClassName.isEmpty() && exe.isEmpty() && winInfo->getGtkAppId().isEmpty()) {
|
||||
if (!winInfo->getWMName().isEmpty())
|
||||
str = QString("wmName:%1").arg(winInfo->getWMName());
|
||||
else
|
||||
str = QString("windowId:%1").arg(winInfo->getXid());
|
||||
} else {
|
||||
str = QString("wmInstance:%1,wmClass:%2,exe:%3,args:%4,hasPid:%5,gtkAppId:%6").arg(wmInstance).arg(wmClassName).arg(exe).arg(args).arg(hasPid).arg(winInfo->getGtkAppId());
|
||||
}
|
||||
|
||||
QByteArray encryText = QCryptographicHash::hash(str.toLatin1(), QCryptographicHash::Md5);
|
||||
QString innerId = windowHashPrefix + encryText.toHex();
|
||||
qInfo() << "genInnerId window " << winId << " innerId :" << innerId;
|
||||
return innerId;
|
||||
}
|
||||
|
||||
// 更新窗口类型
|
||||
void WindowInfoX::updateWmWindowType()
|
||||
{
|
||||
wmWindowType.clear();
|
||||
for (auto ty : XCB->getWMWindoType(xid)) {
|
||||
wmWindowType.push_back(ty);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新窗口许可动作
|
||||
void WindowInfoX::updateWmAllowedActions()
|
||||
{
|
||||
wmAllowedActions.clear();
|
||||
for (auto action : XCB->getWMAllowedActions(xid)) {
|
||||
wmAllowedActions.push_back(action);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmState()
|
||||
{
|
||||
wmState.clear();
|
||||
for (auto a : XCB->getWMState(xid)) {
|
||||
wmState.push_back(a);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmClass()
|
||||
{
|
||||
wmClass = XCB->getWMClass(xid);
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmName()
|
||||
{
|
||||
auto name = XCB->getWMName(xid);
|
||||
if (!name.empty())
|
||||
wmName = name.c_str();
|
||||
|
||||
title = getTitle();
|
||||
}
|
||||
|
||||
void WindowInfoX::updateIcon()
|
||||
{
|
||||
icon = getIconFromWindow();
|
||||
}
|
||||
|
||||
void WindowInfoX::updateHasWmTransientFor()
|
||||
{
|
||||
if (XCB->getWMTransientFor(xid) == 1)
|
||||
hasWMTransientFor = true;
|
||||
}
|
||||
|
||||
void WindowInfoX::update()
|
||||
{
|
||||
updateWmClass();
|
||||
updateWmState();
|
||||
updateWmWindowType();
|
||||
updateWmAllowedActions();
|
||||
updateHasWmTransientFor();
|
||||
updateProcessInfo();
|
||||
updateWmName();
|
||||
innerId = genInnerId(this);
|
||||
}
|
||||
|
||||
// TODO 从窗口中获取图标, 并设置best size be used in Entry
|
||||
QString WindowInfoX::getIconFromWindow()
|
||||
{
|
||||
QString ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isActionMinimizeAllowed()
|
||||
{
|
||||
return containAtom(wmAllowedActions, XCB->getAtom("_NET_WM_ACTION_MINIMIZE"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateDemandsAttention()
|
||||
{
|
||||
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_DEMANDS_ATTENTION"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateSkipTaskBar()
|
||||
{
|
||||
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateModal()
|
||||
{
|
||||
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_MODAL"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::isValidModal()
|
||||
{
|
||||
return hasWmStateModal() && hasWmStateModal();
|
||||
}
|
||||
|
||||
// 通过WMClass判断是否需要隐藏此窗口
|
||||
bool WindowInfoX::shouldSkipWithWMClass()
|
||||
{
|
||||
bool ret = false;
|
||||
if (wmClass.instanceName == "explorer.exe" && wmClass.className == "Wine")
|
||||
ret = true;
|
||||
else if (wmClass.className == "dde-launcher")
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WindowInfoX::updateProcessInfo()
|
||||
{
|
||||
XWindow winId = xid;
|
||||
pid = XCB->getWMPid(winId);
|
||||
if (processInfo)
|
||||
delete processInfo;
|
||||
|
||||
processInfo = new ProcessInfo(pid);
|
||||
if (!processInfo) {
|
||||
// try WM_COMMAND
|
||||
auto wmComand = XCB->getWMCommand(winId);
|
||||
if (wmComand.size() > 0)
|
||||
processInfo = new ProcessInfo(wmComand);
|
||||
}
|
||||
|
||||
qInfo() << "updateProcessInfo: pid is " << pid;
|
||||
}
|
||||
|
||||
bool WindowInfoX::getUpdateCalled()
|
||||
{
|
||||
return updateCalled;
|
||||
}
|
||||
|
||||
void WindowInfoX::setInnerId(QString _innerId)
|
||||
{
|
||||
innerId = _innerId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getTitle()
|
||||
{
|
||||
QString name = wmName;
|
||||
if (name.isEmpty())
|
||||
name = getDisplayName();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isDemandingAttention()
|
||||
{
|
||||
return hasWmStateDemandsAttention();
|
||||
}
|
||||
|
||||
void WindowInfoX::close(uint32_t timestamp)
|
||||
{
|
||||
XCB->requestCloseWindow(xid, timestamp);
|
||||
}
|
||||
|
||||
|
108
src/modules/dock/windowinfox.h
Normal file
108
src/modules/dock/windowinfox.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWINFOX_H
|
||||
#define WINDOWINFOX_H
|
||||
|
||||
#include "windowinfobase.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
class AppInfo;
|
||||
|
||||
// X11下窗口信息 在明确X11环境下使用
|
||||
class WindowInfoX: public WindowInfoBase
|
||||
{
|
||||
public:
|
||||
WindowInfoX(XWindow _xid = 0);
|
||||
virtual ~WindowInfoX();
|
||||
|
||||
virtual bool shouldSkip();
|
||||
virtual QString getIcon();
|
||||
virtual QString getTitle();
|
||||
virtual bool isDemandingAttention();
|
||||
virtual void close(uint32_t timestamp);
|
||||
virtual void activate();
|
||||
virtual void minimize();
|
||||
virtual bool isMinimized();
|
||||
virtual int64_t getCreatedTime();
|
||||
virtual QString getDisplayName();
|
||||
virtual QString getWindowType();
|
||||
virtual bool allowClose();
|
||||
virtual void update();
|
||||
virtual void killClient();
|
||||
|
||||
QString genInnerId(WindowInfoX *winInfo);
|
||||
QString getGtkAppId();
|
||||
QString getFlatpakAppId();
|
||||
QString getWmRole();
|
||||
WMClass getWMClass();
|
||||
QString getWMName();
|
||||
void updateProcessInfo();
|
||||
bool getUpdateCalled();
|
||||
void setInnerId(QString _innerId);
|
||||
ConfigureEvent *getLastConfigureEvent();
|
||||
void setLastConfigureEvent(ConfigureEvent *event);
|
||||
bool isGeometryChanged(int _x, int _y, int _width, int _height);
|
||||
void setGtkAppId(QString _gtkAppId);
|
||||
|
||||
/************************更新XCB窗口属性*********************/
|
||||
void updateWmWindowType();
|
||||
void updateWmAllowedActions();
|
||||
void updateWmState();
|
||||
void updateWmClass();
|
||||
void updateMotifWmHints();
|
||||
void updateWmName();
|
||||
void updateIcon();
|
||||
void updateHasXEmbedInfo();
|
||||
void updateHasWmTransientFor();
|
||||
|
||||
private:
|
||||
QString getIconFromWindow();
|
||||
bool isActionMinimizeAllowed();
|
||||
bool hasWmStateDemandsAttention();
|
||||
bool hasWmStateSkipTaskBar();
|
||||
bool hasWmStateModal();
|
||||
bool isValidModal();
|
||||
bool shouldSkipWithWMClass();
|
||||
|
||||
int16_t x, y;
|
||||
uint16_t width, height;
|
||||
QVector<XCBAtom> wmState;
|
||||
QVector<XCBAtom> wmWindowType;
|
||||
QVector<XCBAtom> wmAllowedActions;
|
||||
bool hasWMTransientFor;
|
||||
WMClass wmClass;
|
||||
QString wmName;
|
||||
bool hasXEmbedInfo;
|
||||
|
||||
// 自定义atom属性
|
||||
QString gtkAppId;
|
||||
QString flatpakAppId;
|
||||
QString wmRole;
|
||||
MotifWMHints motifWmHints;
|
||||
|
||||
bool updateCalled;
|
||||
ConfigureEvent *lastConfigureNotifyEvent;
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOX_H
|
229
src/modules/dock/windowpatterns.cpp
Normal file
229
src/modules/dock/windowpatterns.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "windowpatterns.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QDebug>
|
||||
#include <dstring.h>
|
||||
#include <QRegExp>
|
||||
#include <QFile>
|
||||
|
||||
const int parsedFlagNegative = 0x001;
|
||||
const int parsedFlagIgnoreCase = 0x010;
|
||||
|
||||
bool contains(QString key, QString value) {
|
||||
return key.contains(value);
|
||||
}
|
||||
|
||||
bool containsIgnoreCase(QString key, QString value) {
|
||||
QString _key = key.toLower();
|
||||
QString _value = value.toLower();
|
||||
return _key.contains(_value);
|
||||
}
|
||||
|
||||
bool equal(QString key, QString value) {
|
||||
return key == value;
|
||||
}
|
||||
|
||||
bool equalIgnoreCase(QString key, QString value) {
|
||||
return key.toLower() == value.toLower();
|
||||
}
|
||||
|
||||
bool regexMatch(QString key, QString value) {
|
||||
QRegExp ruleRegex(value);
|
||||
return ruleRegex.exactMatch(key);
|
||||
}
|
||||
|
||||
bool regexMatchIgnoreCase(QString key, QString value) {
|
||||
QRegExp ruleRegex(value, Qt::CaseInsensitive);
|
||||
return ruleRegex.exactMatch(key);
|
||||
}
|
||||
|
||||
|
||||
RuleValueParse::RuleValueParse()
|
||||
: negative(0)
|
||||
, type(0)
|
||||
, flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool RuleValueParse::parse(QString parsedKey)
|
||||
{
|
||||
if (!fn)
|
||||
return false;
|
||||
|
||||
return negative ? fn(parsedKey, value) : !fn(parsedKey, value);
|
||||
}
|
||||
|
||||
bool RuleValueParse::match(const WindowInfoX *winInfo)
|
||||
{
|
||||
QString parsedKey;
|
||||
|
||||
return parse(parsedKey);
|
||||
}
|
||||
|
||||
|
||||
WindowPatterns::WindowPatterns()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString WindowPatterns::match(WindowInfoX *winInfo)
|
||||
{
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void WindowPatterns::loadWindowPatterns()
|
||||
{
|
||||
qInfo() << "---loadWindowPatterns";
|
||||
QFile file(windowPatternsFile);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
||||
file.close();
|
||||
if (!doc.isArray())
|
||||
return;
|
||||
|
||||
QJsonArray arr = doc.array();
|
||||
if (arr.size() == 0)
|
||||
return;
|
||||
|
||||
patterns.clear();
|
||||
for (auto iterp = arr.begin(); iterp != arr.end(); iterp++) {
|
||||
// 过滤非Object
|
||||
if (!(*iterp).isObject())
|
||||
continue;
|
||||
|
||||
QJsonObject patternObj = (*iterp).toObject();
|
||||
QVariantMap patternMap = patternObj.toVariantMap();
|
||||
WindowPattern pattern;
|
||||
for (auto infoIter = patternMap.begin(); infoIter != patternMap.end(); infoIter++) {
|
||||
QString ret = infoIter.key();
|
||||
QVariant value = infoIter.value();
|
||||
|
||||
if (ret == "ret") {
|
||||
pattern.result = value.toString();
|
||||
} else if (ret == "rules") {
|
||||
for (auto &item : value.toList()) {
|
||||
if (!item.isValid())
|
||||
continue;
|
||||
|
||||
if (item.toList().size() != 2)
|
||||
continue;
|
||||
|
||||
pattern.rules.push_back({item.toList()[0].toString(), item.toList()[1].toString()});
|
||||
}
|
||||
}
|
||||
}
|
||||
qInfo() << pattern.result;
|
||||
for (const auto &item : pattern.rules) {
|
||||
qInfo() << item[0] << " " << item[1];
|
||||
}
|
||||
patterns.push_back(pattern);
|
||||
}
|
||||
|
||||
// 解析patterns
|
||||
for (auto &pattern : patterns) {
|
||||
for (int i=0; i < pattern.rules.size(); i++) {
|
||||
RuleValueParse ruleValue = parseRule(pattern.rules[i]);
|
||||
pattern.parseRules.push_back(ruleValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "=:XXX" equal XXX
|
||||
// "=!XXX" not equal XXX
|
||||
|
||||
// "c:XXX" contains XXX
|
||||
// "c!XXX" not contains XXX
|
||||
|
||||
// "r:XXX" match regexp XXX
|
||||
// "r!XXX" not match regexp XXX
|
||||
|
||||
// e c r ignore case
|
||||
// = E C R not ignore case
|
||||
// 解析窗口类型规则
|
||||
RuleValueParse WindowPatterns::parseRule(QVector<QString> rule)
|
||||
{
|
||||
RuleValueParse ret;
|
||||
ret.key = rule[0];
|
||||
ret.original = rule[1];
|
||||
if (rule[1].size() < 2)
|
||||
return ret;
|
||||
|
||||
int len = ret.original.size() + 1;
|
||||
char *orig = static_cast<char *>(calloc(1, size_t(len)));
|
||||
if (!orig)
|
||||
return ret;
|
||||
|
||||
strncpy(orig, ret.original.toStdString().c_str(), size_t(len));
|
||||
switch (orig[1]) {
|
||||
case ':':
|
||||
case '!':
|
||||
ret.flags |= parsedFlagNegative;
|
||||
ret.negative = true;
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.value = QString(&orig[2]);
|
||||
ret.type = uint8_t(orig[0]);
|
||||
switch (orig[0]) {
|
||||
case 'C':
|
||||
ret.fn = contains;
|
||||
break;
|
||||
case 'c':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = containsIgnoreCase;
|
||||
break;
|
||||
case '=':
|
||||
case 'E':
|
||||
ret.fn = equal;
|
||||
break;
|
||||
case 'e':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = equalIgnoreCase;
|
||||
break;
|
||||
case 'R':
|
||||
ret.fn = regexMatch;
|
||||
break;
|
||||
case 'r':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = regexMatchIgnoreCase;
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
65
src/modules/dock/windowpatterns.h
Normal file
65
src/modules/dock/windowpatterns.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWPATTERNS_H
|
||||
#define WINDOWPATTERNS_H
|
||||
|
||||
#include "windowinfox.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
struct RuleValueParse {
|
||||
RuleValueParse();
|
||||
bool parse(QString parsedKey);
|
||||
bool match(const WindowInfoX *winInfo);
|
||||
QString key;
|
||||
bool negative;
|
||||
bool (*fn)(QString, QString);
|
||||
uint8_t type;
|
||||
uint flags;
|
||||
QString original;
|
||||
QString value;
|
||||
};
|
||||
|
||||
class WindowPatterns
|
||||
{
|
||||
// 窗口类型匹配
|
||||
struct WindowPattern {
|
||||
QVector<QVector<QString>> rules; // rules
|
||||
QString result; // ret
|
||||
QVector< RuleValueParse> parseRules;
|
||||
};
|
||||
|
||||
public:
|
||||
WindowPatterns();
|
||||
|
||||
QString match(WindowInfoX *winInfo);
|
||||
|
||||
private:
|
||||
void loadWindowPatterns();
|
||||
RuleValueParse parseRule(QVector<QString> rule);
|
||||
QVector<WindowPattern> patterns;
|
||||
|
||||
};
|
||||
|
||||
#endif // WINDOWPATTERNS_H
|
438
src/modules/dock/x11manager.cpp
Normal file
438
src/modules/dock/x11manager.cpp
Normal file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "x11manager.h"
|
||||
#include "dock.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
/*
|
||||
* 使用Xlib监听X Events
|
||||
* 使用XCB接口与X进行交互
|
||||
* */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
X11Manager::X11Manager(Dock *_dock, QObject *parent)
|
||||
: QObject(parent)
|
||||
, dock(_dock)
|
||||
, mutex(QMutex(QMutex::NonRecursive))
|
||||
, listenXEvent(true)
|
||||
{
|
||||
rootWindow = XCB->getRootWindow();
|
||||
}
|
||||
|
||||
void X11Manager::listenXEventUseXlib()
|
||||
{
|
||||
|
||||
Display *dpy;
|
||||
int screen;
|
||||
char *displayname = nullptr;
|
||||
Window w;
|
||||
XSetWindowAttributes attr;
|
||||
XWindowAttributes wattr;
|
||||
|
||||
dpy = XOpenDisplay (displayname);
|
||||
if (!dpy) {
|
||||
exit (1);
|
||||
}
|
||||
|
||||
screen = DefaultScreen (dpy);
|
||||
w = RootWindow(dpy, screen);
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
long mask;
|
||||
} events[] = {
|
||||
{ "keyboard", KeyPressMask | KeyReleaseMask | KeymapStateMask },
|
||||
{ "mouse", ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
|
||||
LeaveWindowMask | PointerMotionMask | Button1MotionMask |
|
||||
Button2MotionMask | Button3MotionMask | Button4MotionMask |
|
||||
Button5MotionMask | ButtonMotionMask },
|
||||
{ "button", ButtonPressMask | ButtonReleaseMask },
|
||||
{ "expose", ExposureMask },
|
||||
{ "visibility", VisibilityChangeMask },
|
||||
{ "structure", StructureNotifyMask },
|
||||
{ "substructure", SubstructureNotifyMask | SubstructureRedirectMask },
|
||||
{ "focus", FocusChangeMask },
|
||||
{ "property", PropertyChangeMask },
|
||||
{ "colormap", ColormapChangeMask },
|
||||
{ "owner_grab_button", OwnerGrabButtonMask },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
long mask = 0;
|
||||
for (int i = 0; events[i].name; i++)
|
||||
mask |= events[i].mask;
|
||||
|
||||
attr.event_mask = mask;
|
||||
|
||||
XGetWindowAttributes(dpy, w, &wattr);
|
||||
|
||||
attr.event_mask &= ~SubstructureRedirectMask;
|
||||
XSelectInput(dpy, w, attr.event_mask);
|
||||
|
||||
while (listenXEvent) {
|
||||
XEvent event;
|
||||
XNextEvent (dpy, &event);
|
||||
|
||||
if (event.type == DestroyNotify) {
|
||||
XDestroyWindowEvent *eD = (XDestroyWindowEvent *) (&event);
|
||||
//qInfo() << "DestroyNotify windowId=" << eD->window;
|
||||
|
||||
handleDestroyNotifyEvent(XWindow(eD->window));
|
||||
} else if (event.type == MapNotify) {
|
||||
XMapEvent *eM = (XMapEvent *)(&event);
|
||||
//qInfo() << "MapNotify windowId=" << eM->window;
|
||||
|
||||
handleMapNotifyEvent(XWindow(eM->window));
|
||||
} else if (event.type == ConfigureNotify ) {
|
||||
XConfigureEvent *eC = (XConfigureEvent *) (&event);
|
||||
//qInfo() << "ConfigureNotify windowId=" << eC->window;
|
||||
|
||||
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
|
||||
} else if (event.type == PropertyNotify) {
|
||||
XPropertyEvent *eP = (XPropertyEvent *) (&event);
|
||||
//qInfo() << "PropertyNotify windowId=" << eP->window;
|
||||
|
||||
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
|
||||
} else {
|
||||
//qInfo() << "Unknown event type " << event.type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XCloseDisplay (dpy);
|
||||
}
|
||||
|
||||
void X11Manager::listenXEventUseXCB()
|
||||
{
|
||||
/*
|
||||
xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(XCB->getConnect(), XCB->getRootWindow());
|
||||
xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(XCB->getConnect(), cookie, NULL);
|
||||
if (reply) {
|
||||
uint32_t valueMask = reply->your_event_mask;
|
||||
valueMask &= ~XCB_CW_OVERRIDE_REDIRECT;
|
||||
uint32_t mask[2] = {0};
|
||||
mask[0] = valueMask;
|
||||
//xcb_change_window_attributes(XCB->getConnect(), XCB->getRootWindow(), valueMask, mask);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
xcb_generic_event_t *event;
|
||||
while ( (event = xcb_wait_for_event (XCB->getConnect())) ) {
|
||||
eventHandler(event->response_type & ~0x80, event);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 注册X11窗口
|
||||
WindowInfoX *X11Manager::registerWindow(XWindow xid)
|
||||
{
|
||||
qInfo() << "registWindow: windowId=" << xid;
|
||||
WindowInfoX *ret = nullptr;
|
||||
do {
|
||||
if (windowInfoMap.find(xid) != windowInfoMap.end()) {
|
||||
ret = windowInfoMap[xid];
|
||||
break;
|
||||
}
|
||||
|
||||
WindowInfoX *winInfo = new WindowInfoX(xid);
|
||||
if (!winInfo)
|
||||
break;
|
||||
|
||||
listenWindowXEvent(winInfo);
|
||||
windowInfoMap[xid] = winInfo;
|
||||
ret = winInfo;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 取消注册X11窗口
|
||||
void X11Manager::unregisterWindow(XWindow xid)
|
||||
{
|
||||
qInfo() << "unregisterWindow: windowId=" << xid;
|
||||
if (windowInfoMap.find(xid) != windowInfoMap.end()) {
|
||||
windowInfoMap.remove(xid);
|
||||
}
|
||||
}
|
||||
|
||||
WindowInfoX *X11Manager::findWindowByXid(XWindow xid)
|
||||
{
|
||||
WindowInfoX *ret = nullptr;
|
||||
if (windowInfoMap.find(xid) != windowInfoMap.end())
|
||||
ret = windowInfoMap[xid];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11Manager::handleClientListChanged()
|
||||
{
|
||||
QSet<XWindow> newClientList, oldClientList, addClientList, rmClientList;
|
||||
for (auto atom : XCB->getClientList())
|
||||
newClientList.insert(atom);
|
||||
|
||||
for (auto atom : dock->getClientList())
|
||||
oldClientList.insert(atom);
|
||||
|
||||
addClientList = newClientList - oldClientList;
|
||||
rmClientList = oldClientList - newClientList;
|
||||
|
||||
for (auto xid : addClientList) {
|
||||
WindowInfoX *info = registerWindow(xid);
|
||||
if (!XCB->isGoodWindow(xid))
|
||||
continue;
|
||||
|
||||
uint32_t pid = XCB->getWMPid(xid);
|
||||
WMClass wmClass = XCB->getWMClass(xid);
|
||||
QString wmName(XCB->getWMName(xid).c_str());
|
||||
if (pid != 0 || (wmClass.className.size() > 0 && wmClass.instanceName.size() > 0)
|
||||
|| wmName.size() > 0 || XCB->getWMCommand(xid).size() > 0)
|
||||
dock->attachWindow(info);
|
||||
}
|
||||
|
||||
for (auto xid : rmClientList) {
|
||||
WindowInfoX *info = windowInfoMap[xid];
|
||||
if (info) {
|
||||
dock->detachWindow(info);
|
||||
unregisterWindow(xid);
|
||||
} else {
|
||||
// no window
|
||||
auto entry = dock->getEntryByWindowId(xid);
|
||||
if (entry && !dock->isDocked(entry->getFileName())) {
|
||||
dock->removeAppEntry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::handleActiveWindowChangedX()
|
||||
{
|
||||
XWindow active = XCB->getActiveWindow();
|
||||
WindowInfoX *info = findWindowByXid(active);
|
||||
dock->handleActiveWindowChanged(info);
|
||||
}
|
||||
|
||||
void X11Manager::listenRootWindowXEvent()
|
||||
{
|
||||
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||
XCB->registerEvents(rootWindow, eventMask);
|
||||
handleActiveWindowChangedX();
|
||||
handleClientListChanged();
|
||||
}
|
||||
|
||||
void X11Manager::listenWindowXEvent(WindowInfoX *winInfo)
|
||||
{
|
||||
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | EventMask::XCB_EVENT_MASK_STRUCTURE_NOTIFY | EventMask::XCB_EVENT_MASK_VISIBILITY_CHANGE;
|
||||
XCB->registerEvents(winInfo->getXid(), eventMask);
|
||||
}
|
||||
|
||||
void X11Manager::handleRootWindowPropertyNotifyEvent(XCBAtom atom)
|
||||
{
|
||||
if (atom == XCB->getAtom("_NET_CLIENT_LIST"))
|
||||
handleClientListChanged();
|
||||
else if (atom == XCB->getAtom("_NET_ACTIVE_WINDOW"))
|
||||
handleActiveWindowChangedX();
|
||||
else if (atom == XCB->getAtom("_NET_SHOWING_DESKTOP"))
|
||||
Q_EMIT needUpdateHideState(false);
|
||||
}
|
||||
|
||||
// destory event
|
||||
void X11Manager::handleDestroyNotifyEvent(XWindow xid)
|
||||
{
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
dock->detachWindow(winInfo);
|
||||
unregisterWindow(xid);
|
||||
}
|
||||
|
||||
// map event
|
||||
void X11Manager::handleMapNotifyEvent(XWindow xid)
|
||||
{
|
||||
WindowInfoX *winInfo = registerWindow(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
QTimer::singleShot(2 * 1000, this, [&] {
|
||||
qInfo() << "handleMapNotifyEvent: pass 2s, now call idnetifyWindow, windowId=" << winInfo->getXid();
|
||||
QString innerId;
|
||||
AppInfo *appInfo = dock->identifyWindow(winInfo, innerId);
|
||||
dock->markAppLaunched(appInfo);
|
||||
});
|
||||
}
|
||||
|
||||
// config changed event 检测窗口大小调整和重绘应用
|
||||
void X11Manager::handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height)
|
||||
{
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo || dock->getDockHideMode() != HideMode::SmartHide)
|
||||
return;
|
||||
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
if (wmClass.className.c_str() == frontendWindowWmClass)
|
||||
return; // ignore frontend window ConfigureNotify event
|
||||
|
||||
Q_EMIT needUpdateHideState(winInfo->isGeometryChanged(x, y, width, height));
|
||||
}
|
||||
|
||||
// property changed event
|
||||
void X11Manager::handlePropertyNotifyEvent(XWindow xid, XCBAtom atom)
|
||||
{
|
||||
if (xid == rootWindow) {
|
||||
handleRootWindowPropertyNotifyEvent(atom);
|
||||
return;
|
||||
}
|
||||
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
QString newInnerId;
|
||||
bool needAttachOrDetach = false;
|
||||
if (atom == XCB->getAtom("_NET_WM_STATE")) {
|
||||
winInfo->updateWmState();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_GTK_APPLICATION_ID")) {
|
||||
QString gtkAppId;
|
||||
winInfo->setGtkAppId(gtkAppId);
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_PID")) {
|
||||
winInfo->updateProcessInfo();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
|
||||
winInfo->updateWmName();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
|
||||
winInfo->updateIcon();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
|
||||
winInfo->updateWmAllowedActions();
|
||||
} else if (atom == XCB->getAtom("_MOTIF_WM_HINTS")) {
|
||||
winInfo->updateMotifWmHints();
|
||||
} else if (atom == XCB_ATOM_WM_CLASS) {
|
||||
winInfo->updateWmClass();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_XEMBED_INFO")) {
|
||||
winInfo->updateHasXEmbedInfo();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE")) {
|
||||
winInfo->updateWmWindowType();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB_ATOM_WM_TRANSIENT_FOR) {
|
||||
winInfo->updateHasWmTransientFor();
|
||||
needAttachOrDetach = true;
|
||||
}
|
||||
|
||||
if (!newInnerId.isEmpty() && winInfo->getUpdateCalled() && winInfo->getInnerId() != newInnerId) {
|
||||
// winInfo.innerId changed
|
||||
dock->detachWindow(winInfo);
|
||||
winInfo->setInnerId(newInnerId);
|
||||
needAttachOrDetach = true;
|
||||
}
|
||||
|
||||
if (needAttachOrDetach)
|
||||
dock->attachWindow(winInfo);
|
||||
|
||||
Entry *entry = dock->getEntryByWindowId(xid);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
if (atom == XCB->getAtom("_NET_WM_STATE")) {
|
||||
entry->updateWindowInfos();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
|
||||
if (entry->getCurrentWindowInfo() == winInfo) {
|
||||
entry->updateIcon();
|
||||
}
|
||||
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
|
||||
if (entry->getCurrentWindowInfo() == winInfo) {
|
||||
entry->updateName();
|
||||
}
|
||||
entry->updateWindowInfos();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
|
||||
entry->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::eventHandler(uint8_t type, void *event)
|
||||
{
|
||||
qInfo() << "eventHandler" << "type = " << type;
|
||||
switch (type) {
|
||||
case XCB_MAP_NOTIFY: // 17 注册新窗口
|
||||
qInfo() << "eventHandler: XCB_MAP_NOTIFY";
|
||||
break;
|
||||
case XCB_DESTROY_NOTIFY: // 19 销毁窗口
|
||||
qInfo() << "eventHandler: XCB_DESTROY_NOTIFY";
|
||||
break;
|
||||
case XCB_CONFIGURE_NOTIFY: // 22 窗口变化
|
||||
qInfo() << "eventHandler: XCB_CONFIGURE_NOTIFY";
|
||||
break;
|
||||
case XCB_PROPERTY_NOTIFY: // 28 窗口属性改变
|
||||
qInfo() << "eventHandler: XCB_PROPERTY_NOTIFY";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::addWindowLastConfigureEvent(XWindow xid, ConfigureEvent *event)
|
||||
{
|
||||
delWindowLastConfigureEvent(xid);
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
QTimer *timer = new QTimer();
|
||||
timer->setInterval(configureNotifyDelay);
|
||||
windowLastConfigureEventMap[xid] = QPair(event, timer);
|
||||
}
|
||||
|
||||
QPair<ConfigureEvent *, QTimer *> X11Manager::getWindowLastConfigureEvent(XWindow xid)
|
||||
{
|
||||
QPair<ConfigureEvent *, QTimer *> ret;
|
||||
QMutexLocker locker(&mutex);
|
||||
if (windowLastConfigureEventMap.find(xid) != windowLastConfigureEventMap.end())
|
||||
ret = windowLastConfigureEventMap[xid];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11Manager::delWindowLastConfigureEvent(XWindow xid)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
if (windowLastConfigureEventMap.find(xid) != windowLastConfigureEventMap.end()) {
|
||||
QPair<ConfigureEvent*, QTimer*> item = windowLastConfigureEventMap[xid];
|
||||
windowLastConfigureEventMap.remove(xid);
|
||||
delete item.first;
|
||||
item.second->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
77
src/modules/dock/x11manager.h
Normal file
77
src/modules/dock/x11manager.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef X11MANAGER_H
|
||||
#define X11MANAGER_H
|
||||
|
||||
#include "windowinfox.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QTimer>
|
||||
|
||||
class Dock;
|
||||
|
||||
class X11Manager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit X11Manager(Dock *_dock, QObject *parent = nullptr);
|
||||
|
||||
WindowInfoX *findWindowByXid(XWindow xid);
|
||||
WindowInfoX *registerWindow(XWindow xid);
|
||||
void unregisterWindow(XWindow xid);
|
||||
|
||||
void handleClientListChanged();
|
||||
void handleActiveWindowChangedX();
|
||||
void listenRootWindowXEvent();
|
||||
void listenWindowXEvent(WindowInfoX *winInfo);
|
||||
|
||||
void handleRootWindowPropertyNotifyEvent(XCBAtom atom);
|
||||
void handleDestroyNotifyEvent(XWindow xid);
|
||||
void handleMapNotifyEvent(XWindow xid);
|
||||
void handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height);
|
||||
void handlePropertyNotifyEvent(XWindow xid, XCBAtom atom);
|
||||
|
||||
void eventHandler(uint8_t type, void *event);
|
||||
void listenWindowEvent(WindowInfoX *winInfo);
|
||||
void listenXEventUseXlib();
|
||||
void listenXEventUseXCB();
|
||||
|
||||
signals:
|
||||
void needUpdateHideState(bool delay);
|
||||
|
||||
private:
|
||||
void addWindowLastConfigureEvent(XWindow xid, ConfigureEvent* event);
|
||||
QPair<ConfigureEvent*, QTimer*> getWindowLastConfigureEvent(XWindow xid);
|
||||
void delWindowLastConfigureEvent(XWindow xid);
|
||||
|
||||
QMap<XWindow, WindowInfoX *> windowInfoMap;
|
||||
Dock *dock;
|
||||
QMap<XWindow, QPair<ConfigureEvent*, QTimer*>> windowLastConfigureEventMap; // 手动回收ConfigureEvent和QTimer
|
||||
QMutex mutex;
|
||||
XWindow rootWindow; // 根窗口
|
||||
bool listenXEvent; // 监听X事件
|
||||
};
|
||||
|
||||
#endif // X11MANAGER_H
|
291
src/modules/launcher/category.cpp
Normal file
291
src/modules/launcher/category.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "category.h"
|
||||
|
||||
Category::Category()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Category::~Category()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString Category::getStr(Categorytype ty) {
|
||||
QMap<Categorytype, QString> ty2str = {
|
||||
{Categorytype::CategoryInternet, "Internet"},
|
||||
{Categorytype::CategoryChat, "Chat"},
|
||||
{Categorytype::CategoryMusic, "Music"},
|
||||
{Categorytype::CategoryVideo, "Video"},
|
||||
{Categorytype::CategoryGraphics, "Graphics"},
|
||||
{Categorytype::CategoryOffice, "Office"},
|
||||
{Categorytype::CategoryGame, "Game"},
|
||||
{Categorytype::CategoryReading, "Reading"},
|
||||
{Categorytype::CategoryDevelopment, "Development"},
|
||||
{Categorytype::CategorySystem, "System"},
|
||||
{Categorytype::CategoryOthers, "Others"},
|
||||
};
|
||||
return ty2str.find(ty) != ty2str.end() ? ty2str[ty] : "Others";
|
||||
}
|
||||
|
||||
QString Category::pinYin(Categorytype ty) {
|
||||
QMap<Categorytype, QString> ty2py = {
|
||||
{Categorytype::CategoryInternet, "wangluo"},
|
||||
{Categorytype::CategoryChat, "shejiaogoutong"},
|
||||
{Categorytype::CategoryMusic, "yinyuexinshang"},
|
||||
{Categorytype::CategoryVideo, "shipinbofang"},
|
||||
{Categorytype::CategoryGraphics, "tuxintuxiang"},
|
||||
{Categorytype::CategoryOffice, "bangongxuexi"},
|
||||
{Categorytype::CategoryGame, "youxiyule"},
|
||||
{Categorytype::CategoryReading, "yuedufanyi"},
|
||||
{Categorytype::CategoryDevelopment, "bianchengkaifai"},
|
||||
{Categorytype::CategorySystem, "xitongguanli"},
|
||||
{Categorytype::CategoryOthers, "qita"},
|
||||
};
|
||||
return ty2py.find(ty) != ty2py.end() ? ty2py[ty] : "qita";
|
||||
}
|
||||
|
||||
Categorytype Category::parseCategoryString(QString str) {
|
||||
QMap<QString, Categorytype> name2ty {
|
||||
{"internet", Categorytype::CategoryInternet},
|
||||
{"chat", Categorytype::CategoryChat},
|
||||
{"music", Categorytype::CategoryMusic},
|
||||
{"video", Categorytype::CategoryVideo},
|
||||
{"graphics", Categorytype::CategoryGraphics},
|
||||
{"office", Categorytype::CategoryOffice},
|
||||
{"game", Categorytype::CategoryGame},
|
||||
{"reading", Categorytype::CategoryReading},
|
||||
{"development", Categorytype::CategoryDevelopment},
|
||||
{"system", Categorytype::CategorySystem},
|
||||
{"others", Categorytype::CategoryOthers},
|
||||
};
|
||||
return name2ty.find(str) != name2ty.end() ? name2ty[str] : Categorytype::CategoryErr;
|
||||
}
|
||||
|
||||
QList<Categorytype> Category::parseXCategoryString(QString str) {
|
||||
QMultiMap<QString, Categorytype> xname2ty {
|
||||
{"2dgraphics", Categorytype::CategoryGraphics},
|
||||
{"3dgraphics", Categorytype::CategoryGraphics},
|
||||
{"accessibility", Categorytype::CategorySystem},
|
||||
{"accessories", Categorytype::CategoryOthers},
|
||||
{"actiongame", Categorytype::CategoryGame},
|
||||
{"advancedsettings", Categorytype::CategorySystem},
|
||||
{"adventuregame", Categorytype::CategoryGame},
|
||||
{"amusement", Categorytype::CategoryGame},
|
||||
{"applet", Categorytype::CategoryOthers},
|
||||
{"arcadegame", Categorytype::CategoryGame},
|
||||
{"archiving", Categorytype::CategorySystem},
|
||||
{"art", Categorytype::CategoryOffice},
|
||||
{"artificialintelligence", Categorytype::CategoryOffice},
|
||||
{"astronomy", Categorytype::CategoryOffice},
|
||||
{"audio", Categorytype::CategoryMusic},
|
||||
{"audiovideo", Categorytype::CategoryMusic},
|
||||
{"audiovideo", Categorytype::CategoryVideo},
|
||||
{"audiovideoediting", Categorytype::CategoryMusic},
|
||||
{"audiovideoediting", Categorytype::CategoryVideo},
|
||||
{"biology", Categorytype::CategoryOffice},
|
||||
{"blocksgame", Categorytype::CategoryGame},
|
||||
{"boardgame", Categorytype::CategoryGame},
|
||||
{"building", Categorytype::CategoryDevelopment},
|
||||
{"calculator", Categorytype::CategorySystem},
|
||||
{"calendar", Categorytype::CategorySystem},
|
||||
{"cardgame", Categorytype::CategoryGame},
|
||||
{"cd", Categorytype::CategoryMusic},
|
||||
{"chart", Categorytype::CategoryOffice},
|
||||
{"chat", Categorytype::CategoryChat},
|
||||
{"chemistry", Categorytype::CategoryOffice},
|
||||
{"clock", Categorytype::CategorySystem},
|
||||
{"compiz", Categorytype::CategorySystem},
|
||||
{"compression", Categorytype::CategorySystem},
|
||||
{"computerscience", Categorytype::CategoryOffice},
|
||||
{"consoleonly", Categorytype::CategoryOthers},
|
||||
{"contactmanagement", Categorytype::CategoryChat},
|
||||
{"core", Categorytype::CategoryOthers},
|
||||
{"debugger", Categorytype::CategoryDevelopment},
|
||||
{"desktopsettings", Categorytype::CategorySystem},
|
||||
{"desktoputility", Categorytype::CategorySystem},
|
||||
{"development", Categorytype::CategoryDevelopment},
|
||||
{"dialup", Categorytype::CategorySystem},
|
||||
{"dictionary", Categorytype::CategoryOffice},
|
||||
{"discburning", Categorytype::CategorySystem},
|
||||
{"documentation", Categorytype::CategoryOffice},
|
||||
{"editors", Categorytype::CategoryOthers},
|
||||
{"education", Categorytype::CategoryOffice},
|
||||
{"electricity", Categorytype::CategoryOffice},
|
||||
{"electronics", Categorytype::CategoryOffice},
|
||||
{"email", Categorytype::CategoryInternet},
|
||||
{"emulator", Categorytype::CategoryGame},
|
||||
{"engineering", Categorytype::CategorySystem},
|
||||
{"favorites", Categorytype::CategoryOthers},
|
||||
{"filemanager", Categorytype::CategorySystem},
|
||||
{"filesystem", Categorytype::CategorySystem},
|
||||
{"filetools", Categorytype::CategorySystem},
|
||||
{"filetransfer", Categorytype::CategoryInternet},
|
||||
{"finance", Categorytype::CategoryOffice},
|
||||
{"game", Categorytype::CategoryGame},
|
||||
{"geography", Categorytype::CategoryOffice},
|
||||
{"geology", Categorytype::CategoryOffice},
|
||||
{"geoscience", Categorytype::CategoryOthers},
|
||||
{"gnome", Categorytype::CategorySystem},
|
||||
{"gpe", Categorytype::CategoryOthers},
|
||||
{"graphics", Categorytype::CategoryGraphics},
|
||||
{"guidesigner", Categorytype::CategoryDevelopment},
|
||||
{"hamradio", Categorytype::CategoryOffice},
|
||||
{"hardwaresettings", Categorytype::CategorySystem},
|
||||
{"ide", Categorytype::CategoryDevelopment},
|
||||
{"imageprocessing", Categorytype::CategoryGraphics},
|
||||
{"instantmessaging", Categorytype::CategoryChat},
|
||||
{"internet", Categorytype::CategoryInternet},
|
||||
{"ircclient", Categorytype::CategoryChat},
|
||||
{"kde", Categorytype::CategorySystem},
|
||||
{"kidsgame", Categorytype::CategoryGame},
|
||||
{"literature", Categorytype::CategoryOffice},
|
||||
{"logicgame", Categorytype::CategoryGame},
|
||||
{"math", Categorytype::CategoryOffice},
|
||||
{"medicalsoftware", Categorytype::CategoryOffice},
|
||||
{"meteorology", Categorytype::CategoryOthers},
|
||||
{"midi", Categorytype::CategoryMusic},
|
||||
{"mixer", Categorytype::CategoryMusic},
|
||||
{"monitor", Categorytype::CategorySystem},
|
||||
{"motif", Categorytype::CategoryOthers},
|
||||
{"multimedia", Categorytype::CategoryVideo},
|
||||
{"music", Categorytype::CategoryMusic},
|
||||
{"network", Categorytype::CategoryInternet},
|
||||
{"news", Categorytype::CategoryReading},
|
||||
{"numericalanalysis", Categorytype::CategoryOffice},
|
||||
{"ocr", Categorytype::CategoryGraphics},
|
||||
{"office", Categorytype::CategoryOffice},
|
||||
{"p2p", Categorytype::CategoryInternet},
|
||||
{"packagemanager", Categorytype::CategorySystem},
|
||||
{"panel", Categorytype::CategorySystem},
|
||||
{"pda", Categorytype::CategorySystem},
|
||||
{"photography", Categorytype::CategoryGraphics},
|
||||
{"physics", Categorytype::CategoryOffice},
|
||||
{"pim", Categorytype::CategoryOthers},
|
||||
{"player", Categorytype::CategoryMusic},
|
||||
{"player", Categorytype::CategoryVideo},
|
||||
{"playonlinux", Categorytype::CategoryOthers},
|
||||
{"presentation", Categorytype::CategoryOffice},
|
||||
{"printing", Categorytype::CategoryOffice},
|
||||
{"profiling", Categorytype::CategoryDevelopment},
|
||||
{"projectmanagement", Categorytype::CategoryOffice},
|
||||
{"publishing", Categorytype::CategoryOffice},
|
||||
{"puzzlegame", Categorytype::CategoryGame},
|
||||
{"rastergraphics", Categorytype::CategoryGraphics},
|
||||
{"recorder", Categorytype::CategoryMusic},
|
||||
{"recorder", Categorytype::CategoryVideo},
|
||||
{"remoteaccess", Categorytype::CategorySystem},
|
||||
{"revisioncontrol", Categorytype::CategoryDevelopment},
|
||||
{"robotics", Categorytype::CategoryOffice},
|
||||
{"roleplaying", Categorytype::CategoryGame},
|
||||
{"scanning", Categorytype::CategoryOffice},
|
||||
{"science", Categorytype::CategoryOffice},
|
||||
{"screensaver", Categorytype::CategoryOthers},
|
||||
{"sequencer", Categorytype::CategoryMusic},
|
||||
{"settings", Categorytype::CategorySystem},
|
||||
{"security", Categorytype::CategorySystem},
|
||||
{"simulation", Categorytype::CategoryGame},
|
||||
{"sportsgame", Categorytype::CategoryGame},
|
||||
{"spreadsheet", Categorytype::CategoryOffice},
|
||||
{"strategygame", Categorytype::CategoryGame},
|
||||
{"system", Categorytype::CategorySystem},
|
||||
{"systemsettings", Categorytype::CategorySystem},
|
||||
{"technical", Categorytype::CategoryOthers},
|
||||
{"telephony", Categorytype::CategorySystem},
|
||||
{"telephonytools", Categorytype::CategorySystem},
|
||||
{"terminalemulator", Categorytype::CategorySystem},
|
||||
{"texteditor", Categorytype::CategoryOffice},
|
||||
{"texttools", Categorytype::CategoryOffice},
|
||||
{"transiation", Categorytype::CategoryDevelopment},
|
||||
{"translation", Categorytype::CategoryReading},
|
||||
{"trayicon", Categorytype::CategorySystem},
|
||||
{"tuner", Categorytype::CategoryMusic},
|
||||
{"tv", Categorytype::CategoryVideo},
|
||||
{"utility", Categorytype::CategorySystem},
|
||||
{"vectorgraphics", Categorytype::CategoryGraphics},
|
||||
{"video", Categorytype::CategoryVideo},
|
||||
{"videoconference", Categorytype::CategoryInternet},
|
||||
{"viewer", Categorytype::CategoryGraphics},
|
||||
{"webbrowser", Categorytype::CategoryInternet},
|
||||
{"webdevelopment", Categorytype::CategoryDevelopment},
|
||||
{"wine", Categorytype::CategoryOthers},
|
||||
{"wine-programs-accessories", Categorytype::CategoryOthers},
|
||||
{"wordprocessor", Categorytype::CategoryOffice},
|
||||
{"x-alsa", Categorytype::CategoryMusic},
|
||||
{"x-bible", Categorytype::CategoryReading},
|
||||
{"x-bluetooth", Categorytype::CategorySystem},
|
||||
{"x-debian-applications-emulators", Categorytype::CategoryGame},
|
||||
{"x-digital_processing", Categorytype::CategorySystem},
|
||||
{"x-enlightenment", Categorytype::CategorySystem},
|
||||
{"x-geeqie", Categorytype::CategoryGraphics},
|
||||
{"x-gnome-networksettings", Categorytype::CategorySystem},
|
||||
{"x-gnome-personalsettings", Categorytype::CategorySystem},
|
||||
{"x-gnome-settings-panel", Categorytype::CategorySystem},
|
||||
{"x-gnome-systemsettings", Categorytype::CategorySystem},
|
||||
{"x-gnustep", Categorytype::CategorySystem},
|
||||
{"x-islamic-software", Categorytype::CategoryReading},
|
||||
{"x-jack", Categorytype::CategoryMusic},
|
||||
{"x-kde-edu-misc", Categorytype::CategoryReading},
|
||||
{"x-kde-internet", Categorytype::CategorySystem},
|
||||
{"x-kde-more", Categorytype::CategorySystem},
|
||||
{"x-kde-utilities-desktop", Categorytype::CategorySystem},
|
||||
{"x-kde-utilities-file", Categorytype::CategorySystem},
|
||||
{"x-kde-utilities-peripherals", Categorytype::CategorySystem},
|
||||
{"x-kde-utilities-pim", Categorytype::CategorySystem},
|
||||
{"x-lxde-settings", Categorytype::CategorySystem},
|
||||
{"x-mandriva-office-publishing", Categorytype::CategoryOthers},
|
||||
{"x-mandrivalinux-internet-other", Categorytype::CategorySystem},
|
||||
{"x-mandrivalinux-office-other", Categorytype::CategoryOffice},
|
||||
{"x-mandrivalinux-system-archiving-backup", Categorytype::CategorySystem},
|
||||
{"x-midi", Categorytype::CategoryMusic},
|
||||
{"x-misc", Categorytype::CategorySystem},
|
||||
{"x-multitrack", Categorytype::CategoryMusic},
|
||||
{"x-novell-main", Categorytype::CategorySystem},
|
||||
{"x-quran", Categorytype::CategoryReading},
|
||||
{"x-red-hat-base", Categorytype::CategorySystem},
|
||||
{"x-red-hat-base-only", Categorytype::CategorySystem},
|
||||
{"x-red-hat-extra", Categorytype::CategorySystem},
|
||||
{"x-red-hat-serverconfig", Categorytype::CategorySystem},
|
||||
{"x-religion", Categorytype::CategoryReading},
|
||||
{"x-sequencers", Categorytype::CategoryMusic},
|
||||
{"x-sound", Categorytype::CategoryMusic},
|
||||
{"x-sun-supported", Categorytype::CategorySystem},
|
||||
{"x-suse-backup", Categorytype::CategorySystem},
|
||||
{"x-suse-controlcenter-lookandfeel", Categorytype::CategorySystem},
|
||||
{"x-suse-controlcenter-system", Categorytype::CategorySystem},
|
||||
{"x-suse-core", Categorytype::CategorySystem},
|
||||
{"x-suse-core-game", Categorytype::CategoryGame},
|
||||
{"x-suse-core-office", Categorytype::CategoryOffice},
|
||||
{"x-suse-sequencer", Categorytype::CategoryMusic},
|
||||
{"x-suse-yast", Categorytype::CategorySystem},
|
||||
{"x-suse-yast-high_availability", Categorytype::CategorySystem},
|
||||
{"x-synthesis", Categorytype::CategorySystem},
|
||||
{"x-turbolinux-office", Categorytype::CategoryOffice},
|
||||
{"x-xfce", Categorytype::CategorySystem},
|
||||
{"x-xfce-toplevel", Categorytype::CategorySystem},
|
||||
{"x-xfcesettingsdialog", Categorytype::CategorySystem},
|
||||
{"x-ximian-main", Categorytype::CategorySystem},
|
||||
};
|
||||
|
||||
return {xname2ty.values(str)};
|
||||
}
|
62
src/modules/launcher/category.h
Normal file
62
src/modules/launcher/category.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CATEGORY_H
|
||||
#define CATEGORY_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QMultiMap>
|
||||
|
||||
// 应用类型
|
||||
enum class Categorytype {
|
||||
CategoryInternet,
|
||||
CategoryChat,
|
||||
CategoryMusic,
|
||||
CategoryVideo,
|
||||
CategoryGraphics,
|
||||
CategoryGame,
|
||||
CategoryOffice,
|
||||
CategoryReading,
|
||||
CategoryDevelopment,
|
||||
CategorySystem,
|
||||
CategoryOthers,
|
||||
CategoryErr,
|
||||
};
|
||||
|
||||
class Category
|
||||
{
|
||||
public:
|
||||
Category();
|
||||
~Category();
|
||||
|
||||
// 类型转字符串
|
||||
static QString getStr(Categorytype ty);
|
||||
// 类型转拼音
|
||||
static QString pinYin(Categorytype ty);
|
||||
// 字符串转类型
|
||||
static Categorytype parseCategoryString(QString str);
|
||||
// Xorg类型字符串转类型列表
|
||||
static QList<Categorytype> parseXCategoryString(QString str);
|
||||
};
|
||||
|
||||
#endif // CATEGORY_H
|
59
src/modules/launcher/common.h
Normal file
59
src/modules/launcher/common.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMultiMap>
|
||||
|
||||
// DBus服务、路径名
|
||||
const QString dbusService = "org.deepin.dde.daemon.Launcher1";
|
||||
const QString dbusPath = "/org/deepin/dde/daemon/Launcher1";
|
||||
|
||||
// 组策略配置
|
||||
const QString configLauncher = "com.deepin.dde.launcher";
|
||||
const QString keyDisplayMode = "Display_Mode";
|
||||
const QString keyFullscreen = "Fullscreen";
|
||||
const QString keyAppsUseProxy = "Apps_Use_Proxy";
|
||||
const QString keyAppsDisableScaling = "Apps_Disable_Scaling";
|
||||
const QString keyAppsHidden = "Apps_Hidden";
|
||||
const QString keyPackageNameSearch = "Search_Package_Name";
|
||||
|
||||
// 应用配置
|
||||
const QString lastoreDataDir = "/var/lib/lastore";
|
||||
const QString desktopPkgMapFile = lastoreDataDir + "/desktop_package.json";
|
||||
const QString applicationsFile = lastoreDataDir + "/applications.json";
|
||||
|
||||
const QString ddeDataDir = "/usr/share/dde/data/";
|
||||
const QString appNameTranslationsFile = ddeDataDir + "app_name_translations.json";
|
||||
|
||||
// 应用状态
|
||||
const QString appStatusCreated = "created";
|
||||
const QString appStatusModified = "updated";
|
||||
const QString appStatusDeleted = "deleted";
|
||||
|
||||
// flatpak应用
|
||||
const QString flatpakBin = "flatpak";
|
||||
|
||||
// 启动器执行程序
|
||||
const QString launcherExe = "/usr/bin/dde-launcher";
|
||||
#endif // COMMON_H
|
126
src/modules/launcher/dbusadaptorlauncher.cpp
Normal file
126
src/modules/launcher/dbusadaptorlauncher.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "dbusadaptorlauncher.h"
|
||||
|
||||
DBusAdaptorLauncher::DBusAdaptorLauncher(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
|
||||
Launcher *launcher = static_cast<Launcher *>(QObject::parent());
|
||||
if (launcher) {
|
||||
connect(launcher, &Launcher::displayModeChanged, this, &DBusAdaptorLauncher::DisplayModeChanged);
|
||||
connect(launcher, &Launcher::fullScreenChanged, this, &DBusAdaptorLauncher::FullScreenChanged);
|
||||
}
|
||||
}
|
||||
|
||||
DBusAdaptorLauncher::~DBusAdaptorLauncher()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
Launcher *DBusAdaptorLauncher::parent() const
|
||||
{
|
||||
return static_cast<Launcher *>(QObject::parent());
|
||||
}
|
||||
|
||||
int DBusAdaptorLauncher::displayMode() const
|
||||
{
|
||||
return parent()->getDisplayMode();
|
||||
}
|
||||
|
||||
void DBusAdaptorLauncher::setDisplayMode(int value)
|
||||
{
|
||||
parent()->setDisplayMode(value);
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::fullscreen() const
|
||||
{
|
||||
return parent()->getFullScreen();
|
||||
}
|
||||
|
||||
void DBusAdaptorLauncher::setFullscreen(bool value)
|
||||
{
|
||||
parent()->setFullScreen(value);
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::AddAutostart(const QString &desktopFile)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("com.deepin.daemon.Display", "/com/deepin/StartManager", "com.deepin.StartManager");
|
||||
QDBusReply<bool> reply = interface.call("AddAutostart", desktopFile);
|
||||
return reply.isValid() ? reply.value() : false;
|
||||
}
|
||||
|
||||
// TODO
|
||||
QString DBusAdaptorLauncher::GetAllItemInfos()
|
||||
{
|
||||
// return parent()->getAllItemInfos();
|
||||
return "";
|
||||
}
|
||||
|
||||
QStringList DBusAdaptorLauncher::GetAllNewInstalledApps()
|
||||
{
|
||||
return parent()->getAllNewInstalledApps();
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::GetDisableScaling(const QString &id)
|
||||
{
|
||||
return parent()->getDisableScaling(id);
|
||||
}
|
||||
|
||||
// TODO
|
||||
QString DBusAdaptorLauncher::GetItemInfo(const QString &id)
|
||||
{
|
||||
//return parent()->getItemInfo();
|
||||
return "";
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::GetUseProxy(const QString &id)
|
||||
{
|
||||
return parent()->getUseProxy(id);
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::IsItemOnDesktop(const QString &id)
|
||||
{
|
||||
return parent()->isItemOnDesktop(id);
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::LaunchWithTimestamp(const QString &desktopFile, int time)
|
||||
{
|
||||
|
||||
QDBusInterface interface = QDBusInterface("com.deepin.daemon.Display", "/com/deepin/StartManager", "com.deepin.StartManager");
|
||||
QDBusReply<bool> reply = interface.call("LaunchWithTimestamp", desktopFile, time);
|
||||
return reply.isValid() ? reply.value() : false;
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::RemoveAutostart(const QString &desktopFile)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("com.deepin.daemon.Display", "/com/deepin/StartManager", "com.deepin.StartManager");
|
||||
QDBusReply<bool> reply = interface.call("RemoveAutostart", desktopFile);
|
||||
return reply.isValid() ? reply.value() : false;
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::RequestRemoveFromDesktop(const QString &id)
|
||||
{
|
||||
return parent()->requestRemoveFromDesktop(id);
|
||||
}
|
||||
|
||||
bool DBusAdaptorLauncher::RequestSendToDesktop(const QString &id)
|
||||
{
|
||||
return parent()->requestSendToDesktop(id);
|
||||
}
|
||||
|
||||
void DBusAdaptorLauncher::RequestUninstall(const QString &id)
|
||||
{
|
||||
parent()->requestUninstall(id);
|
||||
}
|
||||
|
||||
void DBusAdaptorLauncher::SetDisableScaling(const QString &id, bool value)
|
||||
{
|
||||
parent()->setDisableScaling(id, value);
|
||||
}
|
||||
|
||||
void DBusAdaptorLauncher::SetUseProxy(const QString &id, bool value)
|
||||
{
|
||||
parent()->setUseProxy(id, value);
|
||||
}
|
||||
|
139
src/modules/launcher/dbusadaptorlauncher.h
Normal file
139
src/modules/launcher/dbusadaptorlauncher.h
Normal file
@ -0,0 +1,139 @@
|
||||
#ifndef DBUSADAPTORLAUNCHER_H
|
||||
#define DBUSADAPTORLAUNCHER_H
|
||||
|
||||
#include "launcher.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.deepin.dde.daemon.Launcher1
|
||||
*/
|
||||
class DBusAdaptorLauncher: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Launcher1")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.deepin.dde.daemon.Launcher1\">\n"
|
||||
" <method name=\"GetAllItemInfos\">\n"
|
||||
" <arg direction=\"out\" type=\"s\" name=\"itemInfoList\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetAllNewInstalledApps\">\n"
|
||||
" <arg direction=\"out\" type=\"as\" name=\"apps\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetDisableScaling\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetItemInfo\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"s\" name=\"itemInfo\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetUseProxy\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"IsItemOnDesktop\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"result\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestRemoveFromDesktop\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestSendToDesktop\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestUninstall\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetDisableScaling\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"in\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetUseProxy\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
|
||||
" <arg direction=\"in\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"LaunchWithTimestamp\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"time\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RemoveAutostart\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"AddAutostart\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"ItemChanged\">\n"
|
||||
" <arg type=\"s\" name=\"status\"/>\n"
|
||||
" <arg type=\"s\" name=\"itemInfo\"/>\n"
|
||||
" <arg type=\"x\" name=\"categoryID\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"NewAppLaunched\">\n"
|
||||
" <arg type=\"s\" name=\"appID\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"UninstallSuccess\">\n"
|
||||
" <arg type=\"s\" name=\"appID\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"UninstallFailed\">\n"
|
||||
" <arg type=\"s\" name=\"appId\"/>\n"
|
||||
" <arg type=\"s\" name=\"errMsg\"/>\n"
|
||||
" </signal>\n"
|
||||
" <property access=\"readwrite\" type=\"b\" name=\"Fullscreen\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"DisplayMode\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
public:
|
||||
DBusAdaptorLauncher(QObject *parent);
|
||||
virtual ~DBusAdaptorLauncher();
|
||||
|
||||
Launcher *parent() const;
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
|
||||
int displayMode() const;
|
||||
void setDisplayMode(int value);
|
||||
|
||||
Q_PROPERTY(bool Fullscreen READ fullscreen WRITE setFullscreen NOTIFY FullScreenChanged)
|
||||
bool fullscreen() const;
|
||||
void setFullscreen(bool value);
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
bool AddAutostart(const QString &desktopFile);
|
||||
QString GetAllItemInfos();
|
||||
QStringList GetAllNewInstalledApps();
|
||||
bool GetDisableScaling(const QString &id);
|
||||
QString GetItemInfo(const QString &id);
|
||||
bool GetUseProxy(const QString &id);
|
||||
bool IsItemOnDesktop(const QString &id);
|
||||
bool LaunchWithTimestamp(const QString &desktopFile, int time);
|
||||
bool RemoveAutostart(const QString &desktopFile);
|
||||
bool RequestRemoveFromDesktop(const QString &id);
|
||||
bool RequestSendToDesktop(const QString &id);
|
||||
void RequestUninstall(const QString &id);
|
||||
void SetDisableScaling(const QString &id, bool value);
|
||||
void SetUseProxy(const QString &id, bool value);
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void ItemChanged(const QString &status, const QString &itemInfo, qlonglong categoryID);
|
||||
void NewAppLaunched(const QString &appID);
|
||||
void UninstallFailed(const QString &appId, const QString &errMsg);
|
||||
void UninstallSuccess(const QString &appID);
|
||||
|
||||
void DisplayModeChanged(int mode);
|
||||
void FullScreenChanged(bool isFull);
|
||||
};
|
||||
|
||||
#endif
|
1111
src/modules/launcher/launcher.cpp
Normal file
1111
src/modules/launcher/launcher.cpp
Normal file
File diff suppressed because it is too large
Load Diff
158
src/modules/launcher/launcher.h
Normal file
158
src/modules/launcher/launcher.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LAUNCHER_H
|
||||
#define LAUNCHER_H
|
||||
|
||||
#include "common.h"
|
||||
#include "synmodule.h"
|
||||
#include "category.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusContext>
|
||||
|
||||
// 同步数据
|
||||
struct SyncData {
|
||||
QString version;
|
||||
QString display_mode;
|
||||
bool fullscreen;
|
||||
};
|
||||
|
||||
// 应用类型
|
||||
enum class AppType {
|
||||
Flatpak,
|
||||
ChromeShortcut,
|
||||
CrossOver,
|
||||
WineApp,
|
||||
Default
|
||||
};
|
||||
|
||||
// 应用基本信息
|
||||
struct ItemInfo
|
||||
{
|
||||
QString path;
|
||||
QString name;
|
||||
QString enName;
|
||||
QString id;
|
||||
QString icon;
|
||||
Categorytype categoryId;
|
||||
int64_t timeInstalled;
|
||||
};
|
||||
|
||||
// 应用信息类
|
||||
struct Item {
|
||||
inline bool isValid() {return !info.path.isEmpty();}
|
||||
|
||||
ItemInfo info;
|
||||
QStringList keywords;
|
||||
QStringList categories;
|
||||
QString xDeepinCategory;
|
||||
QString exec;
|
||||
QString genericName;
|
||||
QString comment;
|
||||
std::map<QString, int> searchTargets;
|
||||
};
|
||||
|
||||
|
||||
class DesktopInfo;
|
||||
class Launcher : public SynModule, public QDBusContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Launcher(QObject *parent);
|
||||
~Launcher();
|
||||
|
||||
// 设置配置
|
||||
void setSynConfig(QByteArray ba);
|
||||
QByteArray getSyncConfig();
|
||||
const QMap<QString, Item> *getItems();
|
||||
|
||||
int getDisplayMode();
|
||||
bool getFullScreen();
|
||||
void setDisplayMode(int value);
|
||||
void setFullScreen(bool isFull);
|
||||
|
||||
QVector<ItemInfo> getAllItemInfos();
|
||||
QStringList getAllNewInstalledApps();
|
||||
bool getDisableScaling(QString appId);
|
||||
ItemInfo getItemInfo(QString appId);
|
||||
bool getUseProxy(QString appId);
|
||||
bool isItemOnDesktop(QString appId);
|
||||
bool requestRemoveFromDesktop(QString appId);
|
||||
bool requestSendToDesktop(QString appId);
|
||||
void requestUninstall(QString appId);
|
||||
void setDisableScaling(QString appId, bool value);
|
||||
void setUseProxy(QString appId, bool value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void ItemChanged(QString status, ItemInfo itemInfo, Categorytype ty);
|
||||
void NewAppLaunched(QString appId);
|
||||
void UninstallSuccess(QString appId);
|
||||
void UninstallFailed(QString appId, QString errMsg);
|
||||
|
||||
void displayModeChanged(int mode);
|
||||
void fullScreenChanged(bool isFull);
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleFSWatcherEvents(QDBusMessage msg);
|
||||
void handleLRecoderRestart(QDBusMessage msg);
|
||||
|
||||
private:
|
||||
void initSettings();
|
||||
void loadDesktopPkgMap();
|
||||
void loadPkgCategoryMap();
|
||||
void checkDesktopFile(QString filePath);
|
||||
void handleAppHiddenChanged();
|
||||
void loadNameMap();
|
||||
void initItems();
|
||||
QString getAppIdByFilePath(QString filePath, QStringList dirs);
|
||||
bool isDeepinCustomDesktopFile(QString fileName);
|
||||
Item NewItemWithDesktopInfo(DesktopInfo &info);
|
||||
void addItem(Item item);
|
||||
Categorytype queryCategoryId(const Item *item);
|
||||
Categorytype getXCategory(const Item *item);
|
||||
QString queryPkgName(const QString &itemID, const QString &itemPath);
|
||||
QString queryPkgNameWithDpkg(const QString &itemPath);
|
||||
Item getItemByPath(QString itemPath);
|
||||
void watchDataDirs();
|
||||
void emitItemChanged(const Item *item, QString status);
|
||||
AppType getAppType(DesktopInfo &info, const Item &item);
|
||||
bool doUninstall(DesktopInfo &info, const Item &item);
|
||||
bool uninstallFlatpak(DesktopInfo &info, const Item &item);
|
||||
bool uninstallWineApp(const Item &item);
|
||||
bool uninstallSysApp(const QString &name, const QString &pkg);
|
||||
bool removeDesktop(const Item &item);
|
||||
void notifyUninstallDone(const Item &item, bool result);
|
||||
|
||||
|
||||
QMap<QString, Item> itemsMap;
|
||||
QMap<QString, QString> desktopPkgMap;
|
||||
QMap<QString, Categorytype> pkgCategoryMap;
|
||||
QMap<QString, QString> nameMap;
|
||||
QMap<QString, int> noPkgItemIds;
|
||||
QVector<QString> appsHidden;
|
||||
QStringList appDirs;
|
||||
};
|
||||
|
||||
#endif // LAUNCHER_H
|
47
src/modules/launcher/launchermanager.cpp
Normal file
47
src/modules/launcher/launchermanager.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "launchermanager.h"
|
||||
#include "launcher.h"
|
||||
#include "dbusadaptorlauncher.h"
|
||||
|
||||
LauncherManager::LauncherManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, launcher(new Launcher(this))
|
||||
{
|
||||
new DBusAdaptorLauncher(launcher);
|
||||
QDBusConnection con = QDBusConnection::sessionBus();
|
||||
if (!con.registerService(dbusService))
|
||||
{
|
||||
qInfo() << "register service Launcher1 error:" << con.lastError().message();
|
||||
}
|
||||
|
||||
if (!con.registerObject(dbusPath, launcher))
|
||||
{
|
||||
qInfo() << "register object Launcher1 error:" << con.lastError().message();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LauncherManager::~LauncherManager()
|
||||
{
|
||||
|
||||
}
|
39
src/modules/launcher/launchermanager.h
Normal file
39
src/modules/launcher/launchermanager.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LAUNCHERMANAGER_H
|
||||
#define LAUNCHERMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Launcher;
|
||||
class LauncherManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LauncherManager(QObject *parent = nullptr);
|
||||
~LauncherManager();
|
||||
|
||||
private:
|
||||
Launcher *launcher;
|
||||
};
|
||||
|
||||
#endif // LAUNCHERMANAGER_H
|
128
src/modules/launcher/launchersettings.cpp
Normal file
128
src/modules/launcher/launchersettings.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "launchersettings.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <DConfig>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
static DConfig *dconfig = Settings::ConfigPtr(configLauncher);
|
||||
|
||||
QString LauncherSettings::getDisplayMode()
|
||||
{
|
||||
return dconfig ? dconfig->value(keyDisplayMode).toString() : "";
|
||||
}
|
||||
|
||||
void LauncherSettings::setDisplayMode(QString value)
|
||||
{
|
||||
if (dconfig) {
|
||||
dconfig->setValue(keyDisplayMode, value);
|
||||
}
|
||||
}
|
||||
|
||||
int LauncherSettings::getFullscreenMode()
|
||||
{
|
||||
return dconfig ? dconfig->value(keyFullscreen).toBool() : false;
|
||||
}
|
||||
|
||||
void LauncherSettings::setFullscreenMode(int value)
|
||||
{
|
||||
if (dconfig) {
|
||||
dconfig->setValue(keyFullscreen, value);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QString> LauncherSettings::getDisableScalingApps()
|
||||
{
|
||||
QVector<QString> ret;
|
||||
if (dconfig) {
|
||||
QList<QVariant> apps = dconfig->value(keyAppsDisableScaling).toList();
|
||||
for (auto app : apps) {
|
||||
ret.push_back(app.toString());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LauncherSettings::setDisableScalingApps(const QVector<QString> &value)
|
||||
{
|
||||
if (dconfig) {
|
||||
QList<QVariant> apps;
|
||||
for (const auto &app : value)
|
||||
apps.push_back(app);
|
||||
|
||||
dconfig->setValue(keyAppsDisableScaling, apps);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QString> LauncherSettings::getUseProxyApps()
|
||||
{
|
||||
QVector<QString> ret;
|
||||
if (dconfig) {
|
||||
QList<QVariant> apps = dconfig->value(keyAppsUseProxy).toList();
|
||||
for (auto app : apps) {
|
||||
ret.push_back(app.toString());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LauncherSettings::setUseProxy(const QVector<QString> &value)
|
||||
{
|
||||
if (dconfig) {
|
||||
QList<QVariant> apps;
|
||||
for (const auto &app : value)
|
||||
apps.push_back(app);
|
||||
|
||||
dconfig->setValue(keyAppsUseProxy, apps);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QString> LauncherSettings::getHiddenApps()
|
||||
{
|
||||
QVector<QString> ret;
|
||||
if (dconfig) {
|
||||
QList<QVariant> hiddenApps = dconfig->value(keyAppsHidden).toList();
|
||||
for (auto app : hiddenApps) {
|
||||
ret.push_back(app.toString());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LauncherSettings::LauncherSettings(QObject *parent) : QObject(parent)
|
||||
{
|
||||
// 绑定属性
|
||||
connect(dconfig, &DConfig::valueChanged, this, [&] (const QString &key) {
|
||||
if (key == keyDisplayMode) {
|
||||
Q_EMIT displayModeChanged(dconfig->value(key).toString());
|
||||
} else if (key == keyFullscreen) {
|
||||
Q_EMIT fullscreenChanged(dconfig->value(key).toBool());
|
||||
} else if (key == keyAppsHidden) {
|
||||
Q_EMIT hiddenAppsChanged();
|
||||
}
|
||||
});
|
||||
}
|
64
src/modules/launcher/launchersettings.h
Normal file
64
src/modules/launcher/launchersettings.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LAUNCHERSETTINGS_H
|
||||
#define LAUNCHERSETTINGS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class LauncherSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static inline LauncherSettings *instance() {
|
||||
static LauncherSettings instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
QString getDisplayMode();
|
||||
void setDisplayMode(QString value);
|
||||
|
||||
int getFullscreenMode();
|
||||
void setFullscreenMode(int value);
|
||||
|
||||
QVector<QString> getDisableScalingApps();
|
||||
void setDisableScalingApps(const QVector<QString> &value);
|
||||
|
||||
QVector<QString> getUseProxyApps();
|
||||
void setUseProxy(const QVector<QString> &value);
|
||||
|
||||
QVector<QString> getHiddenApps();
|
||||
|
||||
Q_SIGNALS:
|
||||
void displayModeChanged(QString mode);
|
||||
void fullscreenChanged(bool isFull);
|
||||
void hiddenAppsChanged();
|
||||
|
||||
private:
|
||||
LauncherSettings(QObject *paret = nullptr);
|
||||
LauncherSettings(const LauncherSettings &);
|
||||
LauncherSettings& operator= (const LauncherSettings &);
|
||||
};
|
||||
|
||||
#endif // LAUNCHERSETTINGS_H
|
Reference in New Issue
Block a user