refactor: add taskmanager from dde-application-manager

1. taskmanager used to identify which entry should map to window
  in x11 environmrnt, listen to xevent in anohter thread, and handle those event
when window create, destory, changed. use some way to identify which entry(desktopfile)
should mapped to changed window.
  in wayland, connected plsamawindow signal(window created destoried.
2. use taskmanager instead of dbus in old dock code

log: as title
This commit is contained in:
tsic404 2023-06-13 15:05:44 +08:00 committed by deepin-bot[bot]
parent 9e364902bf
commit 9de057e2cc
86 changed files with 9421 additions and 1672 deletions

View File

@ -123,7 +123,7 @@
"visibility": "private"
},
"Display_Mode": {
"value": "",
"value": "fashion",
"serial": 0,
"flags": [],
"name": "Display_Mode",

View File

@ -34,7 +34,7 @@ find_package(DWayland REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
pkg_check_modules(XCB_EWMH REQUIRED IMPORTED_TARGET xcb-image xcb-ewmh xcb-composite xtst x11 dbusmenu-qt5 xext xcursor xkbcommon)
pkg_check_modules(XCB_EWMH REQUIRED IMPORTED_TARGET x11 xcb xcb-icccm xcb-image xcb-ewmh xcb-composite xtst dbusmenu-qt5 xext xcursor xkbcommon xres)
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt)
pkg_check_modules(WAYLAND REQUIRED IMPORTED_TARGET wayland-client wayland-cursor wayland-egl)
@ -113,3 +113,5 @@ endif()
# bin
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
# window_patterns
install(FILES taskmanager/window_patterns.json DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-dock/)

View File

@ -7,6 +7,9 @@
#include "appitem.h"
#include "launcheritem.h"
#include "pluginsitem.h"
#include "taskmanager/entry.h"
#include "taskmanager/taskmanager.h"
#include "taskmanager/windowinfobase.h"
#include "traypluginitem.h"
#include "utils.h"
#include "docksettings.h"
@ -25,24 +28,24 @@ const QGSettings *DockItemManager::m_dockedSettings = Utils::ModuleSettingsPtr("
DockItemManager::DockItemManager(QObject *parent)
: QObject(parent)
, m_appInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
, m_taskmanager(TaskManager::instance())
, m_loadFinished(false)
{
//固定区域:启动器
m_itemList.append(new LauncherItem);
// 应用区域
for (auto entry : m_appInter->entries()) {
for (auto entry : m_taskmanager->getEntries()) {
AppItem *it = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry);
manageItem(it);
connect(it, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
connect(it, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
connect(it, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
connect(it, &AppItem::requestPreviewWindow, m_taskmanager, &TaskManager::previewWindow);
connect(it, &AppItem::requestCancelPreview, m_taskmanager, &TaskManager::cancelPreviewWindow);
connect(it, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
connect(this, &DockItemManager::requestUpdateDockItem, it, &AppItem::requestUpdateEntryGeometries);
m_itemList.append(it);
m_appIDist.append(it->appId());
updateMultiItems(it);
}
@ -61,9 +64,9 @@ DockItemManager::DockItemManager(QObject *parent)
connect(quickController, &QuickSettingController::pluginLoaderFinished, this, &DockItemManager::onPluginLoadFinished, Qt::QueuedConnection);
// 应用信号
connect(m_appInter, &DockInter::EntryAdded, this, &DockItemManager::appItemAdded);
connect(m_appInter, &DockInter::EntryRemoved, this, static_cast<void (DockItemManager::*)(const QString &)>(&DockItemManager::appItemRemoved), Qt::QueuedConnection);
connect(m_appInter, &DockInter::ServiceRestarted, this, &DockItemManager::reloadAppItems);
connect(m_taskmanager, &TaskManager::entryAdded, this, &DockItemManager::appItemAdded);
connect(m_taskmanager, &TaskManager::entryRemoved, this, static_cast<void (DockItemManager::*)(const QString &)>(&DockItemManager::appItemRemoved), Qt::QueuedConnection);
connect(m_taskmanager, &TaskManager::serviceRestarted, this, &DockItemManager::reloadAppItems);
connect(DockSettings::instance(), &DockSettings::showMultiWindowChanged, this, &DockItemManager::onShowMultiWindowChanged);
DApplication *app = qobject_cast<DApplication *>(qApp);
@ -99,7 +102,7 @@ const QList<QPointer<DockItem>> DockItemManager::itemList() const
bool DockItemManager::appIsOnDock(const QString &appDesktop) const
{
return m_appInter->IsOnDock(appDesktop);
return m_taskmanager->isOnDock(appDesktop);
}
void DockItemManager::refreshItemsIcon()
@ -167,15 +170,15 @@ void DockItemManager::itemMoved(DockItem *const sourceItem, DockItem *const targ
// for app move, index 0 is launcher item, need to pass it.
if (moveType == DockItem::App && replaceType == DockItem::App)
m_appInter->MoveEntry(moveIndex - 1, replaceIndex - 1);
m_taskmanager->moveEntry(moveIndex - 1, replaceIndex - 1);
}
void DockItemManager::itemAdded(const QString &appDesktop, int idx)
{
m_appInter->RequestDock(appDesktop, idx);
m_taskmanager->requestDock(appDesktop, idx);
}
void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
void DockItemManager::appItemAdded(const Entry *entry, const int index)
{
// 第一个是启动器
int insertIndex = 1;
@ -189,18 +192,17 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
++insertIndex;
}
AppItem *item = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, path);
AppItem *item = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry);
if (m_appIDist.contains(item->appId())) {
delete item;
item->deleteLater();
return;
}
manageItem(item);
connect(item, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
connect(item, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
connect(item, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
connect(item, &AppItem::requestPreviewWindow, m_taskmanager, &TaskManager::previewWindow);
connect(item, &AppItem::requestCancelPreview, m_taskmanager, &TaskManager::cancelPreviewWindow);
connect(item, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
connect(this, &DockItemManager::requestUpdateDockItem, item, &AppItem::requestUpdateEntryGeometries);
@ -256,8 +258,8 @@ void DockItemManager::reloadAppItems()
appItemRemoved(static_cast<AppItem *>(item.data()));
// append new item
for (auto path : m_appInter->entries())
appItemAdded(path, -1);
for (Entry* entry : m_taskmanager->getEntries())
appItemAdded(entry, -1);
}
void DockItemManager::manageItem(DockItem *item)
@ -366,11 +368,11 @@ void DockItemManager::onAppWindowCountChanged()
void DockItemManager::updateMultiItems(AppItem *appItem, bool emitSignal)
{
// 如果系统设置不开启应用多窗口拆分,则无需之后的操作
if (!m_appInter->showMultiWindow())
if (!m_taskmanager->showMultiWindow())
return;
// 如果开启了多窗口拆分,则同步窗口和多窗口应用的信息
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
const WindowInfoMap &windowInfoMap = appItem->windowsInfos();
QList<AppMultiItem *> removeItems;
// 同步当前已经存在的多开窗口的列表,删除不存在的多开窗口
for (int i = 0; i < m_itemList.size(); i++) {
@ -431,7 +433,7 @@ bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const
// 查找多分窗口对应的窗口在应用所有的打开的窗口中是否存在,只要它对应的窗口存在,就无需删除
// 只要不存在,就需要删除
AppItem *appItem = multiItem->appItem();
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
const WindowInfoMap &windowInfoMap = appItem->windowsInfos();
for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) {
if (it.key() == multiItem->winId())
return false;
@ -442,7 +444,7 @@ bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const
void DockItemManager::onShowMultiWindowChanged()
{
if (m_appInter->showMultiWindow()) {
if (m_taskmanager->showMultiWindow()) {
// 如果当前设置支持窗口多开那么就依次对每个APPItem加载多开窗口
for (int i = 0; i < m_itemList.size(); i++) {
const QPointer<DockItem> &dockItem = m_itemList[i];

View File

@ -11,6 +11,8 @@
#include "appitem.h"
#include "placeholderitem.h"
#include "dbusutil.h"
#include "taskmanager/taskmanager.h"
#include "taskmanager/windowinfobase.h"
#include <QObject>
@ -56,7 +58,7 @@ private Q_SLOTS:
private:
explicit DockItemManager(QObject *parent = nullptr);
void appItemAdded(const QDBusObjectPath &path, const int index);
void appItemAdded(const Entry *entry, const int index);
void appItemRemoved(const QString &appId);
void appItemRemoved(AppItem *appItem);
void updatePluginsItemOrderKey();
@ -69,7 +71,7 @@ private:
bool needRemoveMultiWindow(AppMultiItem *multiItem) const;
private:
DockInter *m_appInter;
TaskManager *m_taskmanager;
static DockItemManager *INSTANCE;

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "recentapphelper.h"
#include "dockitemmanager.h"
#include "appitem.h"
#include <QWidget>
@ -16,7 +17,6 @@ RecentAppHelper::RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, QObj
: QObject(parent)
, m_appWidget(appWidget)
, m_recentWidget(recentWidget)
, m_dockInter(new DockInter("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus(), this))
{
m_appWidget->installEventFilter(this);
m_recentWidget->installEventFilter(this);
@ -188,7 +188,7 @@ int RecentAppHelper::getEntryIndex(DockItem *dockItem, QWidget *widget) const
return -1;
// 查找当前的应用在所有的应用中的排序
QStringList entryIds = m_dockInter->GetEntryIDs();
QStringList entryIds = TaskManager::instance()->getEntryIDs();
int index = entryIds.indexOf(appItem->appId());
if (index < 0)
return -1;

View File

@ -61,7 +61,6 @@ private:
QWidget *m_appWidget;
QWidget *m_recentWidget;
Dock::DisplayMode m_displayMode;
DockInter *m_dockInter;
};
#endif // RECENTAPPHELPER_H

View File

@ -1,16 +0,0 @@
<interface name="dde.dock.ClientManager">
<method name="ActivateWindow">
<arg type="u" direction="in"></arg>
<arg type="b" direction="out"></arg>
</method>
<method name="CloseWindow">
<arg type="u" direction="in"></arg>
<arg type="b" direction="out"></arg>
</method>
<method name="CurrentActiveWindow">
<arg type="u" direction="out"></arg>
</method>
<signal name="ActiveWindowChanged">
<arg type="u"></arg>
</signal>
</interface>

View File

@ -1,13 +0,0 @@
<interface name="dde.dock.Entry">
<method name="Activate">
</method>
<signal name="DataChanged">
<arg type="s"></arg>
<arg type="s"></arg>
</signal>
<property name="Id" type="s" access="read"></property>
<property name="Type" type="s" access="read"></property>
<property name="Data" type="a{ss}" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="Dict"/>
</property>
</interface>

View File

@ -0,0 +1,235 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "dockdaemonadaptors.h"
#include "docksettings.h"
#include "taskmanager/taskmanager.h"
DockDaemonDBusAdaptor::DockDaemonDBusAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
// constructor
setAutoRelaySignals(true);
connect(TaskManager::instance(), &TaskManager::entryAdded, this, &DockDaemonDBusAdaptor::EntryAdded);
connect(TaskManager::instance(), &TaskManager::entryRemoved, this, &DockDaemonDBusAdaptor::EntryRemoved);
connect(TaskManager::instance(), &TaskManager::hideStateChanged, this, &DockDaemonDBusAdaptor::HideStateChanged);
connect(TaskManager::instance(), &TaskManager::frontendWindowRectChanged, this, &DockDaemonDBusAdaptor::FrontendWindowRectChanged);
connect(TaskManager::instance(), &TaskManager::showRecentChanged, this, &DockDaemonDBusAdaptor::showRecentChanged);
connect(TaskManager::instance(), &TaskManager::showMultiWindowChanged, this, &DockDaemonDBusAdaptor::ShowMultiWindowChanged);
}
DockDaemonDBusAdaptor::~DockDaemonDBusAdaptor()
{
// destructor
}
int DockDaemonDBusAdaptor::displayMode() const
{
return TaskManager::instance()->getDisplayMode();
}
void DockDaemonDBusAdaptor::setDisplayMode(int value)
{
if (displayMode() != value) {
TaskManager::instance()->setDisplayMode(value);
Q_EMIT DisplayModeChanged(value);
}
}
QStringList DockDaemonDBusAdaptor::dockedApps() const
{
return TaskManager::instance()->getDockedApps();
}
int DockDaemonDBusAdaptor::hideMode() const
{
return TaskManager::instance()->getHideMode();
}
void DockDaemonDBusAdaptor::setHideMode(int value)
{
if (hideMode() != value) {
TaskManager::instance()->setHideMode(static_cast<HideMode>(value));
Q_EMIT HideModeChanged(value);
}
}
int DockDaemonDBusAdaptor::hideState() const
{
return TaskManager::instance()->getHideState();
}
uint DockDaemonDBusAdaptor::hideTimeout() const
{
return TaskManager::instance()->getHideTimeout();
}
void DockDaemonDBusAdaptor::setHideTimeout(uint value)
{
if (hideTimeout() != value) {
TaskManager::instance()->setHideTimeout(value);
Q_EMIT HideTimeoutChanged(value);
}
}
uint DockDaemonDBusAdaptor::windowSizeEfficient() const
{
return TaskManager::instance()->getWindowSizeEfficient();
}
void DockDaemonDBusAdaptor::setWindowSizeEfficient(uint value)
{
if (windowSizeEfficient() != value) {
TaskManager::instance()->setWindowSizeEfficient(value);
Q_EMIT WindowSizeEfficientChanged(value);
}
}
uint DockDaemonDBusAdaptor::windowSizeFashion() const
{
return TaskManager::instance()->getWindowSizeFashion();
}
void DockDaemonDBusAdaptor::setWindowSizeFashion(uint value)
{
if (windowSizeFashion() != value) {
TaskManager::instance()->setWindowSizeFashion(value);
Q_EMIT WindowSizeFashionChanged(value);
}
}
QRect DockDaemonDBusAdaptor::frontendWindowRect() const
{
return TaskManager::instance()->getFrontendWindowRect();
}
uint DockDaemonDBusAdaptor::iconSize() const
{
return TaskManager::instance()->getIconSize();
}
void DockDaemonDBusAdaptor::setIconSize(uint value)
{
if (iconSize() != value) {
TaskManager::instance()->setIconSize(value);
Q_EMIT IconSizeChanged(value);
}
}
int DockDaemonDBusAdaptor::position() const
{
return TaskManager::instance()->getPosition();
}
void DockDaemonDBusAdaptor::setPosition(int value)
{
if (position() != value) {
TaskManager::instance()->setPosition(value);
Q_EMIT PositionChanged(value);
}
}
uint DockDaemonDBusAdaptor::showTimeout() const
{
return TaskManager::instance()->getShowTimeout();
}
void DockDaemonDBusAdaptor::setShowTimeout(uint value)
{
if (showTimeout() != value) {
TaskManager::instance()->setShowTimeout(value);
Q_EMIT ShowTimeoutChanged(value);
}
}
bool DockDaemonDBusAdaptor::showRecent() const
{
return DockSettings::instance()->showRecent();
}
bool DockDaemonDBusAdaptor::showMultiWindow() const
{
return TaskManager::instance()->showMultiWindow();
}
void DockDaemonDBusAdaptor::CloseWindow(uint win)
{
TaskManager::instance()->closeWindow(win);
}
// for debug
QStringList DockDaemonDBusAdaptor::GetEntryIDs()
{
return TaskManager::instance()->getEntryIDs();
}
bool DockDaemonDBusAdaptor::IsDocked(const QString &desktopFile)
{
return TaskManager::instance()->isDocked(desktopFile);
}
bool DockDaemonDBusAdaptor::IsOnDock(const QString &desktopFile)
{
return TaskManager::instance()->isOnDock(desktopFile);
}
void DockDaemonDBusAdaptor::MoveEntry(int index, int newIndex)
{
TaskManager::instance()->moveEntry(index, newIndex);
}
QString DockDaemonDBusAdaptor::QueryWindowIdentifyMethod(uint win)
{
return TaskManager::instance()->queryWindowIdentifyMethod(win);
}
QStringList DockDaemonDBusAdaptor::GetDockedAppsDesktopFiles()
{
return TaskManager::instance()->getDockedAppsDesktopFiles();
}
QString DockDaemonDBusAdaptor::GetPluginSettings()
{
return TaskManager::instance()->getPluginSettings();
}
void DockDaemonDBusAdaptor::SetPluginSettings(QString jsonStr)
{
TaskManager::instance()->setPluginSettings(jsonStr);
}
void DockDaemonDBusAdaptor::MergePluginSettings(QString jsonStr)
{
TaskManager::instance()->mergePluginSettings(jsonStr);
}
void DockDaemonDBusAdaptor::RemovePluginSettings(QString key1, QStringList key2List)
{
TaskManager::instance()->removePluginSettings(key1, key2List);
}
bool DockDaemonDBusAdaptor::RequestDock(const QString &desktopFile, int index)
{
return TaskManager::instance()->requestDock(desktopFile, index);
}
bool DockDaemonDBusAdaptor::RequestUndock(const QString &desktopFile)
{
return TaskManager::instance()->requestUndock(desktopFile);
}
void DockDaemonDBusAdaptor::SetShowRecent(bool visible)
{
DockSettings::instance()->setShowRecent(visible);
}
void DockDaemonDBusAdaptor::SetShowMultiWindow(bool showMultiWindow)
{
TaskManager::instance()->setShowMultiWindow(showMultiWindow);
}
void DockDaemonDBusAdaptor::SetFrontendWindowRect(int x, int y, uint width, uint height)
{
TaskManager::instance()->setFrontendWindowRect(x, y, width, height);
}

View File

@ -0,0 +1,203 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "taskmanager/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 <QDBusObjectPath>
#include <QRect>
/*
* Adaptor class for interface org.deepin.dde.daemon.Dock1
*/
class Entry;
class DockDaemonDBusAdaptor: 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=\"GetDockedAppsDesktopFiles\">\n"
" <arg direction=\"out\" type=\"as\" name=\"desktopFiles\"/>\n"
" </method>\n"
" <method name=\"GetPluginSettings\">\n"
" <arg direction=\"out\" type=\"s\" name=\"jsonStr\"/>\n"
" </method>\n"
" <method name=\"SetPluginSettings\">\n"
" <arg direction=\"in\" type=\"s\" name=\"jsonStr\"/>\n"
" </method>\n"
" <method name=\"MergePluginSettings\">\n"
" <arg direction=\"in\" type=\"s\" name=\"jsonStr\"/>\n"
" </method>\n"
" <method name=\"RemovePluginSettings\">\n"
" <arg direction=\"in\" type=\"s\" name=\"key1\"/>\n"
" <arg direction=\"in\" type=\"as\" name=\"key2List\"/>\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=\"SetShowRecent\">\n"
" <arg direction=\"in\" type=\"b\" name=\"visible\"/>\n"
" </method>\n"
" <method name=\"SetShowMultiWindow\">\n"
" <arg direction=\"in\" type=\"b\" name=\"visible\"/>\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=\"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"
" <property access=\"read\" type=\"b\" name=\"ShowRecent\"/>\n"
" <property access=\"read\" type=\"b\" name=\"ShowMultiWindow\"/>\n"
" </interface>\n"
"")
public:
DockDaemonDBusAdaptor(QObject *parent);
virtual ~DockDaemonDBusAdaptor();
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(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(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);
Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged)
bool showRecent() const;
Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged)
bool showMultiWindow() 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);
QStringList GetDockedAppsDesktopFiles();
QString GetPluginSettings();
void SetPluginSettings(QString jsonStr);
void MergePluginSettings(QString jsonStr);
void RemovePluginSettings(QString key1, QStringList key2List);
bool RequestDock(const QString &desktopFile, int index);
bool RequestUndock(const QString &desktopFile);
void SetShowRecent(bool visible);
void SetShowMultiWindow(bool showMultiWindow);
void SetFrontendWindowRect(int x, int y, uint width, uint height);
Q_SIGNALS: // SIGNALS
void ServiceRestarted();
void EntryAdded(const Entry *entry, int index);
void EntryRemoved(const QString &entryId);
void DisplayModeChanged(int value) const;
void DockedAppsChanged(const QStringList &value) const;
void EntriesChanged(const QList<QDBusObjectPath> &value) const;
void FrontendWindowRectChanged(const QRect &dockRect) const;
void HideModeChanged(int value) const;
void HideStateChanged(int value) const;
void HideTimeoutChanged(uint value) const;
void IconSizeChanged(uint value) const;
void PositionChanged(int value) const;
void ShowTimeoutChanged(uint value) const;
void WindowSizeEfficientChanged(uint value) const;
void WindowSizeFashionChanged(uint value) const;
void showRecentChanged(bool) const;
void ShowMultiWindowChanged(bool) const;
};

View File

@ -1,339 +0,0 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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 "dockinterface.h"
#include "org_deepin_dde_daemon_dock1.h"
// 因为 types/dockrect.h 文件中定义了DockRect类而在此处也定义了DockRect
// 所以在此处先加上DOCKRECT_H宏(types/dockrect.h文件中定义的宏)来禁止包含types/dockrect.h头文件
// 否则会出现重复定义的错误
#define DOCKRECT_H
/*
* Implementation of interface class __Dock
*/
class DockPrivate
{
public:
DockPrivate() = default;
// begin member variables
int DisplayMode;
QStringList DockedApps;
QList<QDBusObjectPath> Entries;
DockRect FrontendWindowRect;
int HideMode;
int HideState;
uint HideTimeout;
uint IconSize;
double Opacity;
int Position;
uint ShowTimeout;
uint WindowSize;
uint WindowSizeEfficient;
uint WindowSizeFashion;
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
// 窗管中提供的ActiveWindow接口MinimizeWindow目前还在开发过程中因此关于这两个接口暂时使用v23的后端接口
// 等窗管完成了这几个接口后删除此处v20的接口改成v23提供的新接口即可
using DockInter = org::deepin::dde::daemon::Dock1;
/**
* @brief DBUS接口是通过窗管获取的AM后端并未提供窗管的相关接口
* 使
*/
class WM : public QDBusAbstractInterface
{
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.wm"; }
public:
explicit WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = Q_NULLPTR);
~WM();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> ActivateWindow(uint in0)
{
return m_dockInter->ActivateWindow(in0);
}
QDBusPendingReply<> MinimizeWindow(uint in0)
{
return m_dockInter->MinimizeWindow(in0);
}
inline QDBusPendingReply<> CancelPreviewWindow()
{
return asyncCallWithArgumentList(QStringLiteral("CancelPreviewWindow"), QList<QVariant>());
}
inline QDBusPendingReply<> PreviewWindow(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("PreviewWindow"), argumentList);
}
private:
DockInter *m_dockInter;
};
WM::WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, m_dockInter(new DockInter("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus(), this))
{
}
WM::~WM()
{
}
Dde_Dock::Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new DockPrivate)
, m_wm(new WM("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this))
{
QDBusConnection::sessionBus().connect(this->service(), this->path(),
"org.freedesktop.DBus.Properties",
"PropertiesChanged","sa{sv}as",
this,
SLOT(onPropertyChanged(const QDBusMessage &)));
if (QMetaType::type("DockRect") == QMetaType::UnknownType)
registerDockRectMetaType();
}
Dde_Dock::~Dde_Dock()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void Dde_Dock::onPropertyChanged(const QDBusMessage& msg)
{
QList<QVariant> arguments = msg.arguments();
if (3 != arguments.count())
return;
QString interfaceName = msg.arguments().at(0).toString();
if (interfaceName != staticInterfaceName())
return;
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
QStringList keys = changedProps.keys();
foreach(const QString &prop, keys) {
const QMetaObject* self = metaObject();
for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) {
QMetaProperty p = self->property(i);
if (p.name() == prop)
Q_EMIT p.notifySignal().invoke(this);
}
}
}
int Dde_Dock::displayMode()
{
return qvariant_cast<int>(property("DisplayMode"));
}
void Dde_Dock::setDisplayMode(int value)
{
setProperty("DisplayMode", QVariant::fromValue(value));
}
QStringList Dde_Dock::dockedApps()
{
return qvariant_cast<QStringList>(property("DockedApps"));
}
QList<QDBusObjectPath> Dde_Dock::entries()
{
return qvariant_cast<QList<QDBusObjectPath>>(property("Entries"));
}
DockRect Dde_Dock::frontendWindowRect()
{
return qvariant_cast<DockRect>(property("FrontendWindowRect"));
}
int Dde_Dock::hideMode()
{
return qvariant_cast<int>(property("HideMode"));
}
void Dde_Dock::setHideMode(int value)
{
internalPropSet("HideMode", QVariant::fromValue(value));
}
int Dde_Dock::hideState()
{
return qvariant_cast<int>(property("HideState"));
}
uint Dde_Dock::hideTimeout()
{
return qvariant_cast<uint>(property("HideTimeout"));
}
void Dde_Dock::setHideTimeout(uint value)
{
setProperty("HideTimeout", QVariant::fromValue(value));
}
uint Dde_Dock::iconSize()
{
return qvariant_cast<uint>(property("IconSize"));
}
void Dde_Dock::setIconSize(uint value)
{
setProperty("IconSize", QVariant::fromValue(value));
}
double Dde_Dock::opacity()
{
return qvariant_cast<double>(property("Opacity"));
}
void Dde_Dock::setOpacity(double value)
{
setProperty("Opacity", QVariant::fromValue(value));
}
int Dde_Dock::position()
{
return qvariant_cast<int>(property("Position"));
}
void Dde_Dock::setPosition(int value)
{
setProperty("Position", QVariant::fromValue(value));
}
uint Dde_Dock::showTimeout()
{
return qvariant_cast<uint>(property("ShowTimeout"));
}
void Dde_Dock::setShowTimeout(uint value)
{
setProperty("ShowTimeout", QVariant::fromValue(value));
}
uint Dde_Dock::windowSize()
{
return qvariant_cast<uint>(property("WindowSize"));
}
void Dde_Dock::setWindowSize(uint value)
{
setProperty("WindowSize", QVariant::fromValue(value));
}
uint Dde_Dock::windowSizeEfficient()
{
return qvariant_cast<uint>(property("WindowSizeEfficient"));
}
void Dde_Dock::setWindowSizeEfficient(uint value)
{
setProperty("WindowSizeEfficient", QVariant::fromValue(value));
}
uint Dde_Dock::windowSizeFashion()
{
return qvariant_cast<uint>(property("WindowSizeFashion"));
}
void Dde_Dock::setWindowSizeFashion(uint value)
{
setProperty("WindowSizeFashion", QVariant::fromValue(value));
}
bool Dde_Dock::showRecent() const
{
return qvariant_cast<bool>(property("ShowRecent"));
}
bool Dde_Dock::showMultiWindow() const
{
return qvariant_cast<bool>(property("ShowMultiWindow"));
}
QDBusPendingReply<> Dde_Dock::ActivateWindow(uint in0)
{
return m_wm->ActivateWindow(in0);
}
QDBusPendingReply<> Dde_Dock::PreviewWindow(uint in0)
{
return m_wm->PreviewWindow(in0);
}
QDBusPendingReply<> Dde_Dock::CancelPreviewWindow()
{
return m_wm->CancelPreviewWindow();
}
QDBusPendingReply<> Dde_Dock::MinimizeWindow(uint in0)
{
return m_wm->MinimizeWindow(in0);
}
void Dde_Dock::CallQueued(const QString &callName, const QList<QVariant> &args)
{
if (d_ptr->m_waittingCalls.contains(callName)) {
d_ptr->m_waittingCalls[callName] = args;
return;
}
if (d_ptr->m_processingCalls.contains(callName)) {
d_ptr->m_waittingCalls.insert(callName, args);
} else {
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args));
connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dde_Dock::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void Dde_Dock::onPendingCallFinished(QDBusPendingCallWatcher *w)
{
w->deleteLater();
const auto callName = d_ptr->m_processingCalls.key(w);
Q_ASSERT(!callName.isEmpty());
if (callName.isEmpty())
return;
d_ptr->m_processingCalls.remove(callName);
if (!d_ptr->m_waittingCalls.contains(callName))
return;
const auto args = d_ptr->m_waittingCalls.take(callName);
CallQueued(callName, args);
}

View File

@ -1,338 +0,0 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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_INTERFACE
#define DOCK_INTERFACE
#include "types/dockrect.h"
#include <QObject>
#include <QByteArray>
#include <QList>
#include <QMap>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QtDBus>
/*
* Proxy class for interface org.deepin.dde.daemon.Dock1
*/
class DockPrivate;
class WM;
void registerDockRectMetaType();
class Dde_Dock : public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.deepin.dde.daemon.Dock1"; }
public:
explicit Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~Dde_Dock();
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
int displayMode();
void setDisplayMode(int value);
Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged)
QStringList dockedApps();
Q_PROPERTY(QList<QDBusObjectPath> Entries READ entries NOTIFY EntriesChanged)
QList<QDBusObjectPath> entries();
Q_PROPERTY(DockRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged)
DockRect frontendWindowRect();
Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged)
int hideMode();
void setHideMode(int value);
Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged)
int hideState();
Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged)
uint hideTimeout();
void setHideTimeout(uint value);
Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged)
uint iconSize();
void setIconSize(uint value);
Q_PROPERTY(double Opacity READ opacity WRITE setOpacity NOTIFY OpacityChanged)
double opacity();
void setOpacity(double value);
Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged)
int position();
void setPosition(int value);
Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged)
uint showTimeout();
void setShowTimeout(uint value);
Q_PROPERTY(uint WindowSize READ windowSize WRITE setWindowSize NOTIFY WindowSizeChanged)
uint windowSize();
void setWindowSize(uint value);
Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged)
uint windowSizeEfficient();
void setWindowSizeEfficient(uint value);
Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged)
uint windowSizeFashion();
void setWindowSizeFashion(uint value);
Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged)
bool showRecent() const;
Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged)
bool showMultiWindow() const;
public Q_SLOTS: // METHODS
QDBusPendingReply<> ActivateWindow(uint in0);
QDBusPendingReply<> PreviewWindow(uint in0);
QDBusPendingReply<> CancelPreviewWindow();
QDBusPendingReply<> MinimizeWindow(uint in0);
inline void ActivateWindowQueued(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("ActivateWindow"), argumentList);
}
inline QDBusPendingReply<> CloseWindow(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("CloseWindow"), argumentList);
}
inline void CloseWindowQueued(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("CloseWindow"), argumentList);
}
inline QDBusPendingReply<QStringList> GetDockedAppsDesktopFiles()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetDockedAppsDesktopFiles"), argumentList);
}
inline QDBusPendingReply<QStringList> GetEntryIDs()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetEntryIDs"), argumentList);
}
inline QDBusPendingReply<QString> GetPluginSettings()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetPluginSettings"), argumentList);
}
inline QDBusPendingReply<bool> IsDocked(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("IsDocked"), argumentList);
}
inline QDBusPendingReply<bool> IsOnDock(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("IsOnDock"), argumentList);
}
inline QDBusPendingReply<> MergePluginSettings(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("MergePluginSettings"), argumentList);
}
inline void MergePluginSettingsQueued(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("MergePluginSettings"), argumentList);
}
inline QDBusPendingReply<> MoveEntry(int in0, int in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
return asyncCallWithArgumentList(QStringLiteral("MoveEntry"), argumentList);
}
inline void MoveEntryQueued(int in0, int in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
CallQueued(QStringLiteral("MoveEntry"), argumentList);
}
inline void MoveWindowQueued(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("MoveWindow"), argumentList);
}
inline QDBusPendingReply<QString> QueryWindowIdentifyMethod(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("QueryWindowIdentifyMethod"), argumentList);
}
inline QDBusPendingReply<> RemovePluginSettings(const QString &in0, const QStringList &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
return asyncCallWithArgumentList(QStringLiteral("RemovePluginSettings"), argumentList);
}
inline void RemovePluginSettingsQueued(const QString &in0, const QStringList &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
CallQueued(QStringLiteral("RemovePluginSettings"), argumentList);
}
inline QDBusPendingReply<bool> RequestDock(const QString &in0, int in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList);
}
inline QDBusPendingReply<bool> RequestUndock(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList);
}
inline void SetShowRecent(bool in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("SetShowRecent"), argumentList);
}
inline QDBusPendingReply<> SetFrontendWindowRect(int in0, int in1, uint in2, uint in3)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
return asyncCallWithArgumentList(QStringLiteral("SetFrontendWindowRect"), argumentList);
}
inline void SetFrontendWindowRectQueued(int in0, int in1, uint in2, uint in3)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
CallQueued(QStringLiteral("SetFrontendWindowRect"), argumentList);
}
inline QDBusPendingReply<> SetPluginSettings(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("SetPluginSettings"), argumentList);
}
inline void SetPluginSettingsQueued(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("SetPluginSettings"), argumentList);
}
Q_SIGNALS: // SIGNALS
void DockAppSettingsSynced();
void EntryAdded(const QDBusObjectPath &in0, int in1);
void EntryRemoved(const QString &in0);
void PluginSettingsSynced();
void ServiceRestarted();
// begin property changed signals
void DisplayModeChanged(int value) const;
void DockedAppsChanged(const QStringList &value) const;
void EntriesChanged(const QList<QDBusObjectPath> &value) const;
void FrontendWindowRectChanged(DockRect value) const;
void HideModeChanged(int value) const;
void HideStateChanged(int value) const;
void HideTimeoutChanged(uint value) const;
void IconSizeChanged(uint value) const;
void OpacityChanged(double value) const;
void PositionChanged(int value) const;
void ShowTimeoutChanged(uint value) const;
void WindowSizeChanged(uint value) const;
void WindowSizeEfficientChanged(uint value) const;
void WindowSizeFashionChanged(uint value) const;
void showRecentChanged(bool) const;
void ShowMultiWindowChanged(bool) const;
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
void onPropertyChanged(const QDBusMessage& msg);
private:
DockPrivate *d_ptr;
WM *m_wm;
};
namespace org {
namespace deepin {
namespace dde {
namespace daemon {
typedef ::Dde_Dock DdeDock;
}
}
}
}
#endif // DOCK_INTERFACE

View File

@ -1,295 +0,0 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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 "entryinterface.h"
/*
* Implementation of interface class __Entry
*/
void registerWindowListMetaType()
{
qRegisterMetaType<WindowList>();
qDBusRegisterMetaType<WindowList>();
}
void registerWindowInfoMapMetaType()
{
registerWindowInfoMetaType();
qRegisterMetaType<WindowInfoMap>("WindowInfoMap");
qDBusRegisterMetaType<WindowInfoMap>();
}
void registerWindowInfoMetaType()
{
qRegisterMetaType<WindowInfo>("WindowInfo");
qDBusRegisterMetaType<WindowInfo>();
}
QDebug operator<<(QDebug argument, const WindowInfo &info)
{
argument << '(' << info.title << ',' << info.attention << info.uuid << ')';
return argument;
}
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
{
argument.beginStructure();
argument << info.title << info.attention << info.uuid;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
{
argument.beginStructure();
argument >> info.title >> info.attention >> info.uuid;
argument.endStructure();
return argument;
}
bool WindowInfo::operator==(const WindowInfo &rhs) const
{
return (attention == rhs.attention &&
title == rhs.title &&
uuid == rhs.uuid);
}
class EntryPrivate
{
public:
EntryPrivate()
: CurrentWindow(0)
, IsActive(false)
, IsDocked(false)
, mode(0)
{}
// begin member variables
uint CurrentWindow;
QString DesktopFile;
QString Icon;
QString Id;
bool IsActive;
bool IsDocked;
QString Menu;
QString Name;
WindowInfoMap WindowInfos;
int mode;
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
Dock_Entry::Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new EntryPrivate)
{
QDBusConnection::sessionBus().connect(this->service(), this->path(),
"org.freedesktop.DBus.Properties",
"PropertiesChanged","sa{sv}as",
this,
SLOT(onPropertyChanged(const QDBusMessage &)));
if (QMetaType::type("WindowList") == QMetaType::UnknownType)
registerWindowListMetaType();
if (QMetaType::type("WindowInfoMap") == QMetaType::UnknownType)
registerWindowInfoMapMetaType();
}
Dock_Entry::~Dock_Entry()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void Dock_Entry::onPropertyChanged(const QString &propName, const QVariant &value)
{
if (propName == QStringLiteral("CurrentWindow")) {
const uint &CurrentWindow = qvariant_cast<uint>(value);
if (d_ptr->CurrentWindow != CurrentWindow) {
d_ptr->CurrentWindow = CurrentWindow;
Q_EMIT CurrentWindowChanged(d_ptr->CurrentWindow);
}
return;
}
if (propName == QStringLiteral("DesktopFile")) {
const QString &DesktopFile = qvariant_cast<QString>(value);
if (d_ptr->DesktopFile != DesktopFile) {
d_ptr->DesktopFile = DesktopFile;
Q_EMIT DesktopFileChanged(d_ptr->DesktopFile);
}
return;
}
if (propName == QStringLiteral("Icon")) {
const QString &Icon = qvariant_cast<QString>(value);
if (d_ptr->Icon != Icon)
{
d_ptr->Icon = Icon;
Q_EMIT IconChanged(d_ptr->Icon);
}
return;
}
if (propName == QStringLiteral("IsActive")) {
const bool &IsActive = qvariant_cast<bool>(value);
if (d_ptr->IsActive != IsActive) {
d_ptr->IsActive = IsActive;
Q_EMIT IsActiveChanged(d_ptr->IsActive);
}
return;
}
if (propName == QStringLiteral("IsDocked")) {
const bool &IsDocked = qvariant_cast<bool>(value);
if (d_ptr->IsDocked != IsDocked) {
d_ptr->IsDocked = IsDocked;
Q_EMIT IsDockedChanged(d_ptr->IsDocked);
}
return;
}
if (propName == QStringLiteral("Menu")) {
const QString &Menu = qvariant_cast<QString>(value);
if (d_ptr->Menu != Menu) {
d_ptr->Menu = Menu;
Q_EMIT MenuChanged(d_ptr->Menu);
}
return;
}
if (propName == QStringLiteral("Name")) {
const QString &Name = qvariant_cast<QString>(value);
if (d_ptr->Name != Name) {
d_ptr->Name = Name;
Q_EMIT NameChanged(d_ptr->Name);
}
return;
}
if (propName == QStringLiteral("WindowInfos")) {
const WindowInfoMap &WindowInfos = qvariant_cast<WindowInfoMap>(value);
if (d_ptr->WindowInfos != WindowInfos) {
d_ptr->WindowInfos = WindowInfos;
Q_EMIT WindowInfosChanged(d_ptr->WindowInfos);
}
return;
}
if (propName == QStringLiteral("Mode")) {
const int mode = qvariant_cast<int>(value);
if (d_ptr->mode != mode) {
d_ptr->mode = mode;
Q_EMIT ModeChanged(d_ptr->mode);
}
}
qWarning() << "property not handle: " << propName;
return;
}
uint Dock_Entry::currentWindow()
{
return qvariant_cast<uint>(property("CurrentWindow"));
}
QString Dock_Entry::desktopFile()
{
return qvariant_cast<QString>(property("DesktopFile"));
}
QString Dock_Entry::icon()
{
return qvariant_cast<QString>(property("Icon"));
}
QString Dock_Entry::id()
{
return qvariant_cast<QString>(property("Id"));
}
bool Dock_Entry::isActive()
{
return qvariant_cast<bool>(property("IsActive"));
}
bool Dock_Entry::isDocked()
{
return qvariant_cast<bool>(property("IsDocked"));
}
int Dock_Entry::mode() const
{
return qvariant_cast<int>(property("Mode"));
}
QString Dock_Entry::menu()
{
return qvariant_cast<QString>(property("Menu"));
}
QString Dock_Entry::name()
{
return qvariant_cast<QString>(property("Name"));
}
WindowInfoMap Dock_Entry::windowInfos()
{
return qvariant_cast<WindowInfoMap>(property("WindowInfos"));
}
void Dock_Entry::CallQueued(const QString &callName, const QList<QVariant> &args)
{
if (d_ptr->m_waittingCalls.contains(callName)) {
d_ptr->m_waittingCalls[callName] = args;
return;
}
if (d_ptr->m_processingCalls.contains(callName)) {
d_ptr->m_waittingCalls.insert(callName, args);
} else {
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args));
connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dock_Entry::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void Dock_Entry::onPendingCallFinished(QDBusPendingCallWatcher *w)
{
w->deleteLater();
const auto callName = d_ptr->m_processingCalls.key(w);
Q_ASSERT(!callName.isEmpty());
if (callName.isEmpty())
return;
d_ptr->m_processingCalls.remove(callName);
if (!d_ptr->m_waittingCalls.contains(callName))
return;
const auto args = d_ptr->m_waittingCalls.take(callName);
CallQueued(callName, args);
}

View File

@ -1,282 +0,0 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@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_ENTRY_H
#define DOCK_ENTRY_H
#define WINDOWLIST_H
#define WINDOWINFOLIST_H
#include <QObject>
#include <QByteArray>
#include <QList>
#include <QMap>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <DDBusExtendedAbstractInterface>
#include <QtDBus>
typedef QList<quint32> WindowList;
void registerWindowListMetaType();
class WindowInfo
{
public:
friend QDebug operator<<(QDebug argument, const WindowInfo &info);
friend QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info);
friend const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info);
bool operator==(const WindowInfo &rhs) const;
public:
bool attention;
QString title;
QString uuid;
};
Q_DECLARE_METATYPE(WindowInfo)
typedef QMap<quint32, WindowInfo> WindowInfoMap;
Q_DECLARE_METATYPE(WindowInfoMap)
void registerWindowInfoMetaType();
void registerWindowInfoMapMetaType();
/*
* Proxy class for interface org.deepin.dde.daemon.Dock1.Entry
*/
class EntryPrivate;
class Dock_Entry : public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.deepin.dde.daemon.Dock1.Entry"; }
public:
explicit Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~Dock_Entry();
Q_PROPERTY(uint CurrentWindow READ currentWindow NOTIFY CurrentWindowChanged)
uint currentWindow();
Q_PROPERTY(QString DesktopFile READ desktopFile NOTIFY DesktopFileChanged)
QString desktopFile();
Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged)
QString icon();
Q_PROPERTY(QString Id READ id)
QString id();
Q_PROPERTY(bool IsActive READ isActive NOTIFY IsActiveChanged)
bool isActive();
Q_PROPERTY(bool IsDocked READ isDocked NOTIFY IsDockedChanged)
bool isDocked();
Q_PROPERTY(QString Menu READ menu NOTIFY MenuChanged)
QString menu();
Q_PROPERTY(QString Name READ name NOTIFY NameChanged)
QString name();
Q_PROPERTY(WindowInfoMap WindowInfos READ windowInfos NOTIFY WindowInfosChanged)
WindowInfoMap windowInfos();
Q_PROPERTY(int Mode READ mode NOTIFY ModeChanged)
int mode() const;
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> Activate(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("Activate"), argumentList);
}
inline void ActivateQueued(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("Activate"), argumentList);
}
inline QDBusPendingReply<> Check()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Check"), argumentList);
}
inline void CheckQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Check"), argumentList);
}
inline QDBusPendingReply<> ForceQuit()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ForceQuit"), argumentList);
}
inline QDBusPendingReply<> ActiveWindow(quint32 in0)
{
QList<QVariant> argumentList;
argumentList << in0;
return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList);
}
inline void ForceQuitQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ForceQuit"), argumentList);
}
inline QDBusPendingReply<WindowList> GetAllowedCloseWindows()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetAllowedCloseWindows"), argumentList);
}
inline QDBusPendingReply<> HandleDragDrop(uint in0, const QStringList &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
return asyncCallWithArgumentList(QStringLiteral("HandleDragDrop"), argumentList);
}
inline void HandleDragDropQueued(uint in0, const QStringList &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
CallQueued(QStringLiteral("HandleDragDrop"), argumentList);
}
inline QDBusPendingReply<> HandleMenuItem(uint in0, const QString &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
return asyncCallWithArgumentList(QStringLiteral("HandleMenuItem"), argumentList);
}
inline void HandleMenuItemQueued(uint in0, const QString &in1)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
CallQueued(QStringLiteral("HandleMenuItem"), argumentList);
}
inline QDBusPendingReply<> NewInstance(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("NewInstance"), argumentList);
}
inline void NewInstanceQueued(uint in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("NewInstance"), argumentList);
}
inline QDBusPendingReply<> PresentWindows()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("PresentWindows"), argumentList);
}
inline void PresentWindowsQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("PresentWindows"), argumentList);
}
inline QDBusPendingReply<> RequestDock()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList);
}
inline void RequestDockQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestDock"), argumentList);
}
inline QDBusPendingReply<> RequestUndock()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList);
}
inline void RequestUndockQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestUndock"), argumentList);
}
Q_SIGNALS: // SIGNALS
// begin property changed signals
void IsActiveChanged(bool value) const;
void IsDockedChanged(bool value) const;
void MenuChanged(const QString &value) const;
void IconChanged(const QString &value) const;
void NameChanged(const QString &value) const;
void DesktopFileChanged(const QString &value) const;
void CurrentWindowChanged(uint32_t value) const;
void WindowInfosChanged(WindowInfoMap value) const;
void ModeChanged(int value) const;
private:
QVariant asyncProperty(const QString &propertyName);
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
void onPropertyChanged(const QString &propName, const QVariant &value);
private:
EntryPrivate *d_ptr;
};
namespace org {
namespace deepin {
namespace dde {
namespace daemon {
namespace dock {
typedef ::Dock_Entry DockEntry;
}
}
}
}
}
#endif // DOCK_ENTRY_H

View File

@ -1,31 +0,0 @@
<interface name="org.deepin.dde.daemon.Dock1">
<method name="ActivateWindow">
<arg type="u" direction="in"></arg>
</method>
<method name="CloseWindow">
<arg type="u" direction="in"></arg>
</method>
<method name="GetEntryIDs">
<arg type="as" direction="out"></arg>
</method>
<method name="ReorderEntries">
<arg type="as" direction="in"></arg>
</method>
<method name="SetFrontendWindow">
<arg type="u" direction="in"></arg>
</method>
<signal name="ServiceRestarted"></signal>
<signal name="EntryAdded">
<arg type="o"></arg>
</signal>
<signal name="EntryRemoved">
<arg type="s"></arg>
</signal>
<property name="Entries" type="ao" access="read"></property>
<property name="HideMode" type="i" access="readwrite"></property>
<property name="DisplayMode" type="i" access="readwrite"></property>
<property name="Position" type="i" access="readwrite"></property>
<property name="ActiveWindow" type="u" access="read"></property>
<property name="HideState" type="i" access="read"></property>
</interface>

View File

@ -18,7 +18,6 @@ public:
friend const QDBusArgument &operator>>(const QDBusArgument &arg, DockRect &rect);
friend QDBusArgument &operator<<(QDBusArgument &arg, const DockRect &rect);
private:
int x;
int y;
uint w;

View File

@ -0,0 +1,166 @@
<interface name="com.deepin.wm">
<property access="readwrite" type="b" name="compositingEnabled"/>
<property access="read" type="b" name="compositingPossible"/>
<property access="read" type="b" name="compositingAllowSwitch"/>
<property access="readwrite" type="b" name="zoneEnabled"/>
<property access="readwrite" type="s" name="cursorTheme"/>
<property access="readwrite" type="i" name="cursorSize"/>
<method name="SwitchApplication">
<arg direction="in" type="b" name="backward"/>
</method>
<method name="TileActiveWindow">
<arg direction="in" type="u" name="side"/>
</method>
<method name="BeginToMoveActiveWindow"/>
<method name="ToggleActiveWindowMaximize"/>
<method name="MinimizeActiveWindow"/>
<method name="ShowWorkspace"/>
<method name="ShowWindow"/>
<method name="ShowAllWindow"/>
<method name="PerformAction">
<arg direction="in" type="i" name="type"/>
</method>
<method name="PreviewWindow">
<arg direction="in" type="u" name="xid"/>
</method>
<method name="CancelPreviewWindow"/>
<method name="GetCurrentWorkspaceBackground">
<arg direction="out" type="s" name="result"/>
</method>
<method name="SetCurrentWorkspaceBackground">
<arg direction="in" type="s" name="uri"/>
</method>
<method name="GetWorkspaceBackground">
<arg direction="in" type="i" name="index"/>
<arg direction="out" type="s" name="result"/>
</method>
<method name="SetWorkspaceBackground">
<arg direction="in" type="i" name="index"/>
<arg direction="in" type="s" name="uri"/>
</method>
<method name="SetTransientBackground">
<arg direction="in" type="s"/>
</method>
<method name="GetCurrentWorkspaceBackgroundForMonitor">
<arg direction="in" type="s" name="strMonitorName"/>
<arg direction="out" type="s" name="result"/>
</method>
<method name="SetCurrentWorkspaceBackgroundForMonitor">
<arg direction="in" type="s" name="uri"/>
<arg direction="in" type="s" name="strMonitorName"/>
</method>
<method name="GetWorkspaceBackgroundForMonitor">
<arg direction="in" type="i" name="index"/>
<arg direction="in" type="s" name="strMonitorName"/>
<arg direction="out" type="s" name="result"/>
</method>
<method name="SetWorkspaceBackgroundForMonitor">
<arg direction="in" type="i" name="index"/>
<arg direction="in" type="s" name="strMonitorName"/>
<arg direction="in" type="s" name="uri"/>
</method>
<method name="SetTransientBackgroundForMonitor">
<arg direction="in" type="s" name="uri"/>
<arg direction="in" type="s" name="strMonitorName"/>
</method>
<method name="GetCurrentWorkspace">
<arg direction="out" type="i" name="index"/>
</method>
<method name="WorkspaceCount">
<arg direction="out" type="i" name="count"/>
</method>
<method name="SetCurrentWorkspace">
<arg direction="in" type="i" name="index"/>
</method>
<method name="PreviousWorkspace"/>
<method name="NextWorkspace"/>
<method name="GetAllAccels">
<arg direction="out" type="s" name="data"/>
</method>
<method name="GetAccel">
<arg direction="in" type="s" name="id"/>
<arg direction="out" type="as" name="data"/>
</method>
<method name="GetDefaultAccel">
<arg direction="in" type="s" name="id"/>
<arg direction="out" type="as" name="data"/>
</method>
<method name="SetAccel">
<arg direction="in" type="s" name="data"/>
<arg direction="out" type="b" name="result"/>
</method>
<method name="RemoveAccel">
<arg direction="in" type="s" name="id"/>\
</method>
<method name="SetDecorationTheme">
<arg direction="in" type="s" name="themeType"/>
<arg direction="in" type="s" name="themeName"/>
</method>
<method name="SetDecorationDeepinTheme">
<arg direction="in" type="s" name="deepinThemeName"/>
</method>
<signal name="WorkspaceBackgroundChanged">
<arg type="i" name="index"/>
<arg type="s" name="newUri"/>
</signal>
<signal name="WorkspaceBackgroundChangedForMonitor">
<arg type="i" name="index"/>
<arg type="s" name="strMonitorName"/>
<arg type="s" name="uri"/>
</signal>
<signal name="compositingEnabledChanged">
<arg type="b" name="enabled"/>
</signal>
<signal name="wmCompositingEnabledChanged">
<arg type="b" name="enabled"/>
</signal>
<signal name="workspaceCountChanged">
<arg type="i" name="count"/>
</signal>
<signal name="BeginToMoveActiveWindowChanged"/>
<signal name="SwitchApplicationChanged">
<arg type="b" name="backward"/>
</signal>
<signal name="TileActiveWindowChanged">
<arg type="i" name="side"/>
</signal>
<signal name="ToggleActiveWindowMaximizeChanged"/>
<signal name="ShowAllWindowChanged"/>
<signal name="ShowWindowChanged"/>
<signal name="ShowWorkspaceChanged"/>
<signal name="ResumeCompositorChanged">
<arg type="i" name="reason"/>
</signal>
<signal name="SuspendCompositorChanged">
<arg type="i" name="reason"/>
</signal>
<method name="ChangeCurrentWorkspaceBackground">
<arg direction="in" type="s" name="uri"/>
</method>
<method name="SwitchToWorkspace">
<arg direction="in" type="b" name="backward"/>
</method>
<method name="PresentWindows">
<arg direction="in" type="au" name="xids"/>
<annotation value="QList&lt;uint&gt;" name="org.qtproject.QtDBus.QtTypeName.In0"/>
</method>
<method name="EnableZoneDetected">
<arg direction="in" type="b" name="enabled"/>
</method>
<signal name="WorkspaceSwitched">
<arg type="i" name="from"/>
<arg type="i" name="to"/>
</signal>
<method name="GetMultiTaskingStatus">
<arg direction="out" type="b" name="isActive"/>
</method>
<method name="SetMultiTaskingStatus">
<arg direction="in" type="b" name="isActive"/>
</method>
<method name="GetIsShowDesktop">
<arg direction="out" type="b" name="isShowDesktop"/>
</method>
<method name="SetShowDesktop">
<arg direction="in" type="b" name="isShowDesktop"/>
</method>
</interface>

View File

@ -0,0 +1,12 @@
<interface name="org.deepin.dde.WMSwitcher1">
<method name="AllowSwitch">
<arg direction="out" type="b" name="outArg0"/>
</method>
<method name="CurrentWM">
<arg direction="out" type="s" name="outArg0"/>
</method>
<method name="RequestSwitchWM"/>
<signal name="WMChanged">
<arg type="s" name="wmName"/>
</signal>
</interface>

View File

@ -1,100 +0,0 @@
<interface name="org.deepin.dde.daemon.Dock1">
<method name="ActivateWindow">
<arg type="u" direction="in"/>
</method>
<method name="CancelPreviewWindow"/>
<method name="CloseWindow">
<arg type="u" direction="in"/>
</method>
<method name="GetDockedAppsDesktopFiles">
<arg type="as" direction="out"/>
</method>
<method name="GetEntryIDs">
<arg type="as" direction="out"/>
</method>
<method name="GetPluginSettings">
<arg type="s" direction="out"/>
</method>
<method name="IsDocked">
<arg type="s" direction="in"/>
<arg type="b" direction="out"/>
</method>
<method name="IsOnDock">
<arg type="s" direction="in"/>
<arg type="b" direction="out"/>
</method>
<method name="MakeWindowAbove">
<arg type="u" direction="in"/>
</method>
<method name="MaximizeWindow">
<arg type="u" direction="in"/>
</method>
<method name="MinimizeWindow">
<arg type="u" direction="in"/>
</method>
<method name="MoveEntry">
<arg type="i" direction="in"/>
<arg type="i" direction="in"/>
</method>
<method name="MoveWindow">
<arg type="u" direction="in"/>
</method>
<method name="PreviewWindow">
<arg type="u" direction="in"/>
</method>
<method name="QueryWindowIdentifyMethod">
<arg type="u" direction="in"/>
<arg type="s" direction="out"/>
</method>
<method name="RemovePluginSettings">
<arg type="s" direction="in"/>
<arg type="as" direction="in"/>
</method>
<method name="RequestDock">
<arg type="s" direction="in"/>
<arg type="i" direction="in"/>
<arg type="b" direction="out"/>
</method>
<method name="RequestUndock">
<arg type="s" direction="in"/>
<arg type="b" direction="out"/>
</method>
<method name="SetFrontendWindowRect">
<arg type="i" direction="in"/>
<arg type="i" direction="in"/>
<arg type="u" direction="in"/>
<arg type="u" direction="in"/>
</method>
<method name="SetPluginSettings">
<arg type="s" direction="in"/>
</method>
<method name="MergePluginSettings">
<arg type="s" direction="in"/>
</method>
<signal name="ServiceRestarted"/>
<signal name="EntryAdded">
<arg type="o"/>
<arg type="i"/>
</signal>
<signal name="EntryRemoved">
<arg type="s"/>
</signal>
<signal name="PluginSettingsSynced"/>
<signal name="DockAppSettingsSynced"/>
<property name="Entries" type="ao" access="read"/>
<property name="HideMode" type="i" access="readwrite"/>
<property name="DisplayMode" type="i" access="readwrite"/>
<property name="Position" type="i" access="readwrite"/>
<property name="IconSize" type="u" access="readwrite"/>
<property name="WindowSize" type="u" access="readwrite"/>
<property name="WindowSizeEfficient" type="u" access="readwrite"/>
<property name="WindowSizeFashion" type="u" access="readwrite"/>
<property name="ShowTimeout" type="u" access="readwrite"/>
<property name="HideTimeout" type="u" access="readwrite"/>
<property name="DockedApps" type="as" access="read"/>
<property name="HideState" type="i" access="read"/>
<property name="FrontendWindowRect" type="(iiuu)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="DockRect"/>
</property>
<property name="Opacity" type="d" access="readwrite"/>
</interface>

View File

@ -0,0 +1,146 @@
<interface name="org.deepin.dde.KWayland1.PlasmaWindow">
<signal name="ActiveChanged"/>
<signal name="AppIdChanged"/>
<signal name="CloseableChanged"/>
<signal name="DemandsAttentionChanged"/>
<signal name="FullscreenableChanged"/>
<signal name="FullscreenChanged"/>
<signal name="GeometryChanged"/>
<signal name="IconChanged"/>
<signal name="KeepAboveChanged"/>
<signal name="KeepBelowChanged"/>
<signal name="MaximizeableChanged"/>
<signal name="MaximizedChanged"/>
<signal name="MinimizeableChanged"/>
<signal name="MinimizedChanged"/>
<signal name="MovableChanged"/>
<signal name="OnAllDesktopsChanged"/>
<signal name="ParentWindowChanged"/>
<signal name="PlasmaVirtualDesktopEntered">
<arg name="id" type="s" direction="out"/>
</signal>
<signal name="PlasmaVirtualDesktopLeft">
<arg name="id" type="s" direction="out"/>
</signal>
<signal name="ResizableChanged"/>
<signal name="ShadeableChanged"/>
<signal name="ShadedChanged"/>
<signal name="SkipSwitcherChanged"/>
<signal name="SkipTaskbarChanged"/>
<signal name="TitleChanged"/>
<signal name="Unmapped"/>
<signal name="VirtualDesktopChangeableChanged"/>
<signal name="VirtualDesktopChanged"/>
<method name="AppId">
<arg type="s" direction="out"/>
</method>
<method name="Destroy"/>
<method name="Geometry">
<arg type="(iiii)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="DockRect"/>
</method>
<method name="Icon">
<arg type="s" direction="out"/>
</method>
<method name="InternalId">
<arg type="u" direction="out"/>
</method>
<method name="IsActive">
<arg type="b" direction="out"/>
</method>
<method name="IsCloseable">
<arg type="b" direction="out"/>
</method>
<method name="IsDemandingAttention">
<arg type="b" direction="out"/>
</method>
<method name="IsFullscreen">
<arg type="b" direction="out"/>
</method>
<method name="IsFullscreenable">
<arg type="b" direction="out"/>
</method>
<method name="IsKeepAbove">
<arg type="b" direction="out"/>
</method>
<method name="IsKeepBelow">
<arg type="b" direction="out"/>
</method>
<method name="IsMaximizeable">
<arg type="b" direction="out"/>
</method>
<method name="IsMaximized">
<arg type="b" direction="out"/>
</method>
<method name="IsMinimizeable">
<arg type="b" direction="out"/>
</method>
<method name="IsMinimized">
<arg type="b" direction="out"/>
</method>
<method name="IsMovable">
<arg type="b" direction="out"/>
</method>
<method name="IsOnAllDesktops">
<arg type="b" direction="out"/>
</method>
<method name="IsResizable">
<arg type="b" direction="out"/>
</method>
<method name="IsShadeable">
<arg type="b" direction="out"/>
</method>
<method name="IsShaded">
<arg type="b" direction="out"/>
</method>
<method name="IsValid">
<arg type="b" direction="out"/>
</method>
<method name="IsVirtualDesktopChangeable">
<arg type="b" direction="out"/>
</method>
<method name="Pid">
<arg type="u" direction="out"/>
</method>
<method name="PlasmaVirtualDesktops">
<arg type="as" direction="out"/>
</method>
<method name="Release"/>
<method name="RequestActivate"/>
<method name="RequestClose"/>
<method name="RequestEnterNewVirtualDesktop"/>
<method name="RequestEnterVirtualDesktop">
<arg name="id" type="s" direction="in"/>
</method>
<method name="RequestLeaveVirtualDesktop">
<arg name="id" type="s" direction="in"/>
</method>
<method name="RequestMove"/>
<method name="RequestResize"/>
<method name="RequestToggleKeepAbove"/>
<method name="RequestToggleKeepBelow"/>
<method name="RequestToggleMaximized"/>
<method name="RequestToggleMinimized"/>
<method name="RequestToggleShaded"/>
<method name="RequestVirtualDesktop">
<arg name="desktop" type="u" direction="in"/>
</method>
<method name="SkipSwitcher">
<arg type="b" direction="out"/>
</method>
<method name="SkipTaskbar">
<arg type="b" direction="out"/>
</method>
<method name="Title">
<arg type="s" direction="out"/>
</method>
<method name="VirtualDesktop">
<arg type="u" direction="out"/>
</method>
<method name="WindowId">
<arg type="u" direction="out"/>
</method>
<method name="uuid">
<arg type="ay" direction="out"/>
</method>
</interface>

View File

@ -0,0 +1,31 @@
<interface name="org.deepin.dde.KWayland1.WindowManager">
<signal name="InterfaceAboutToBeReleased"/>
<signal name="InterfaceAboutToBeDestroyed"/>
<signal name="ShowingDesktopChanged">
<arg type="b" direction="out"/>
</signal>
<signal name="WindowCreated">
<arg name="dbus" type="s" direction="out"/>
</signal>
<signal name="WindowRemove">
<arg name="dbus" type="s" direction="out"/>
</signal>
<signal name="ActiveWindowChanged"/>
<method name="IsValid">
<arg type="b" direction="out"/>
</method>
<method name="IsShowingDesktop">
<arg type="b" direction="out"/>
</method>
<method name="SetShowingDesktop">
<arg name="show" type="b" direction="in"/>
</method>
<method name="ShowDesktop"/>
<method name="HideDesktop"/>
<method name="Windows">
<arg type="av" direction="out"/>
</method>
<method name="ActiveWindow">
<arg type="u" direction="out"/>
</method>
</interface>

View File

@ -5,6 +5,7 @@
#include "appitem.h"
#include "docksettings.h"
#include "taskmanager/windowinfobase.h"
#include "themeappicon.h"
#include "xcb_misc.h"
#include "appswingeffectbuilder.h"
@ -27,8 +28,8 @@
#include <DGuiApplicationHelper>
#include <DPlatformTheme>
#include <DConfig>
#include <cstdint>
#include <qobjectdefs.h>
#include <sys/types.h>
DGUI_USE_NAMESPACE
@ -38,13 +39,13 @@ DCORE_USE_NAMESPACE
QPoint AppItem::MousePressPos;
AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent)
AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const Entry *entry, QWidget *parent)
: DockItem(parent)
, m_appSettings(appSettings)
, m_activeAppSettings(activeAppSettings)
, m_dockedAppSettings(dockedAppSettings)
, m_itemEntry(const_cast<Entry*>(entry))
, m_appPreviewTips(nullptr)
, m_itemEntryInter(new DockEntryInter(dockServiceName(), entry.path(), QDBusConnection::sessionBus(), this))
, m_swingEffectView(nullptr)
, m_itemAnimation(nullptr)
, m_wmHelper(DWindowManagerHelper::instance())
@ -69,13 +70,13 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
setAcceptDrops(true);
setLayout(centralLayout);
m_id = m_itemEntryInter->id();
m_active = m_itemEntryInter->isActive();
m_name = m_itemEntryInter->name();
m_icon = m_itemEntryInter->icon();
m_mode = m_itemEntryInter->mode();
m_isDocked = m_itemEntryInter->isDocked();
m_menu = m_itemEntryInter->menu();
m_id = m_itemEntry->getId();
m_active = m_itemEntry->getIsActive();
m_name = m_itemEntry->getName();
m_icon = m_itemEntry->getIcon();
m_mode = m_itemEntry->mode();
m_isDocked = m_itemEntry->getIsDocked();
m_menu = m_itemEntry->getMenu();
setObjectName(m_name);
@ -88,32 +89,32 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
m_refershIconTimer->setInterval(1000);
m_refershIconTimer->setSingleShot(false);
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, &AppItem::activeChanged);
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, static_cast<void (AppItem::*)()>(&AppItem::update));
connect(m_itemEntryInter, &DockEntryInter::WindowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection);
connect(m_itemEntryInter, &DockEntryInter::IconChanged, this, [=](QString icon) {
connect(m_itemEntry, &Entry::isActiveChanged, this, &AppItem::activeChanged);
connect(m_itemEntry, &Entry::isActiveChanged, this, static_cast<void (AppItem::*)()>(&AppItem::update));
connect(m_itemEntry, &Entry::windowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection);
connect(m_itemEntry, &Entry::iconChanged, this, [=](QString icon) {
if (!icon.isEmpty() && icon != m_icon)
m_icon = icon;
});
connect(m_itemEntryInter, &DockEntryInter::IconChanged, this, &AppItem::refreshIcon);
connect(m_itemEntryInter, &DockEntryInter::ModeChanged, this, [=] (int32_t mode) { m_mode = mode; Q_EMIT modeChanged(m_mode);});
connect(m_itemEntry, &Entry::iconChanged, this, &AppItem::refreshIcon);
connect(m_itemEntry, &Entry::modeChanged, this, [=] (int32_t mode) { m_mode = mode; Q_EMIT modeChanged(m_mode);});
connect(m_updateIconGeometryTimer, &QTimer::timeout, this, &AppItem::updateWindowIconGeometries, Qt::QueuedConnection);
connect(m_retryObtainIconTimer, &QTimer::timeout, this, &AppItem::refreshIcon, Qt::QueuedConnection);
connect(DockSettings::instance(), &DockSettings::showMultiWindowChanged, this, [=] (bool show) {
m_showMultiWindow = show;
});
connect(m_itemEntryInter, &DockEntryInter::NameChanged, this, [=](const QString& name){ m_name = name; });
connect(m_itemEntryInter, &DockEntryInter::DesktopFileChanged, this, [=](const QString& desktopfile){ m_desktopfile = desktopfile; });
connect(m_itemEntryInter, &DockEntryInter::IsDockedChanged, this, [=](bool docked){ m_isDocked = docked; });
connect(m_itemEntryInter, &DockEntryInter::MenuChanged, this, [=](const QString& menu){ m_menu = menu; });
connect(m_itemEntryInter, &DockEntryInter::CurrentWindowChanged, this, [=](uint32_t currentWindow){
connect(m_itemEntry, &Entry::nameChanged, this, [=](const QString& name){ m_name = name; });
connect(m_itemEntry, &Entry::desktopFileChanged, this, [=](const QString& desktopfile){ m_desktopfile = desktopfile; });
connect(m_itemEntry, &Entry::isDockedChanged, this, [=](bool docked){ m_isDocked = docked; });
connect(m_itemEntry, &Entry::menuChanged, this, [=](const QString& menu){ m_menu = menu; });
connect(m_itemEntry, &Entry::currentWindowChanged, this, [=](uint32_t currentWindow){
m_currentWindow = currentWindow;
Q_EMIT onCurrentWindowChanged(m_currentWindow);
});
connect(this, &AppItem::requestUpdateEntryGeometries, this, &AppItem::updateWindowIconGeometries);
updateWindowInfos(m_itemEntryInter->windowInfos());
updateWindowInfos(m_itemEntry->getExportWindowInfos());
if (m_appSettings)
connect(m_appSettings, &QGSettings::changed, this, &AppItem::onGSettingsChanged);
@ -135,7 +136,7 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
*/
void AppItem::checkEntry()
{
m_itemEntryInter->Check();
m_itemEntry->check();
}
const QString AppItem::appId() const
@ -150,7 +151,7 @@ QString AppItem::name() const
bool AppItem::isValid() const
{
return m_itemEntryInter->isValid() && !m_id.isEmpty();
return m_itemEntry->isValid() && !m_id.isEmpty();
}
// Update _NET_WM_ICON_GEOMETRY property for windows that every item
@ -180,7 +181,7 @@ void AppItem::updateWindowIconGeometries()
*/
void AppItem::undock()
{
m_itemEntryInter->RequestUndock();
m_itemEntry->requestUndock();
}
QWidget *AppItem::appDragWidget()
@ -230,9 +231,9 @@ int AppItem::mode() const
}
DockEntryInter *AppItem::itemEntryInter() const
Entry *AppItem::itemEntry() const
{
return m_itemEntryInter;
return m_itemEntry;
}
QString AppItem::accessibleName()
@ -242,7 +243,7 @@ QString AppItem::accessibleName()
void AppItem::requestDock()
{
m_itemEntryInter->RequestDock();
m_itemEntry->requestDock();
}
bool AppItem::isDocked() const
@ -260,7 +261,7 @@ void AppItem::updateMSecs()
m_createMSecs = QDateTime::currentMSecsSinceEpoch();
}
const WindowInfoMap &AppItem::windowsMap() const
const WindowInfoMap &AppItem::windowsInfos() const
{
return m_windowInfos;
}
@ -396,7 +397,7 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e)
return;
if (e->button() == Qt::MiddleButton) {
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
m_itemEntry->newInstance(QX11Info::getTimestamp());
// play launch effect
if (m_windowInfos.isEmpty())
@ -408,15 +409,12 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e)
return;
}
qDebug() << "app item clicked, name:" << m_name
<< "id:" << m_id << "my-id:" << m_id << "icon:" << m_icon;
if (m_showMultiWindow) {
// 如果开启了多窗口显示,则直接新建一个窗口
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
m_itemEntry->newInstance(QX11Info::getTimestamp());
} else {
// 如果没有开启新窗口显示,则
m_itemEntryInter->Activate(QX11Info::getTimestamp());
m_itemEntry->active(QX11Info::getTimestamp());
// play launch effect
if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment())
playSwingEffect();
@ -469,7 +467,7 @@ void AppItem::wheelEvent(QWheelEvent *e)
QWidget::wheelEvent(e);
if (qAbs(e->angleDelta().y()) > 20) {
m_itemEntryInter->PresentWindows();
m_itemEntry->presentWindows();
}
}
@ -523,7 +521,7 @@ void AppItem::dropEvent(QDropEvent *e)
}
qDebug() << "accept drop event with URIs: " << uriList;
m_itemEntryInter->HandleDragDrop(QX11Info::getTimestamp(), uriList);
m_itemEntry->handleDragDrop(QX11Info::getTimestamp(), uriList);
}
void AppItem::leaveEvent(QEvent *e)
@ -553,7 +551,7 @@ void AppItem::invokedMenuItem(const QString &itemId, const bool checked)
{
Q_UNUSED(checked);
m_itemEntryInter->HandleMenuItem(QX11Info::getTimestamp(), itemId);
m_itemEntry->handleMenuItem(QX11Info::getTimestamp(), itemId);
}
const QString AppItem::contextMenu() const
@ -663,7 +661,7 @@ void AppItem::updateWindowInfos(const WindowInfoMap &info)
m_windowInfos = info;
if (m_appPreviewTips)
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value());
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntry->getAllowedClosedWindowIds().toList());
m_updateIconGeometryTimer->start();
// process attention effect
@ -754,14 +752,14 @@ void AppItem::showPreview()
return;
m_appPreviewTips = new PreviewContainer;
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value());
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntry->getAllowedClosedWindowIds().toList());
m_appPreviewTips->updateLayoutDirection(DockPosition);
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::requestActivateWindow, Qt::QueuedConnection);
connect(m_appPreviewTips, &PreviewContainer::requestPreviewWindow, this, &AppItem::requestPreviewWindow, Qt::QueuedConnection);
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, this, &AppItem::requestCancelPreview);
connect(m_appPreviewTips, &PreviewContainer::requestHidePopup, this, &AppItem::hidePopup);
connect(m_appPreviewTips, &PreviewContainer::requestCheckWindows, m_itemEntryInter, &DockEntryInter::Check);
connect(m_appPreviewTips, &PreviewContainer::requestCheckWindows, m_itemEntry, &Entry::check);
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::onResetPreview);
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, this, &AppItem::onResetPreview);
@ -878,5 +876,5 @@ void AppItem::showEvent(QShowEvent *e)
void AppItem::activeWindow(WId wid)
{
m_itemEntryInter->ActiveWindow(wid);
}
m_itemEntry->activeWindow(wid);
}

View File

@ -11,11 +11,13 @@
#include "appdrag.h"
#include "../widgets/tipswidget.h"
#include "dbusutil.h"
#include "taskmanager/entry.h"
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsItemAnimation>
#include <DGuiApplicationHelper>
#include <cstdint>
class QGSettings;
@ -26,7 +28,7 @@ class AppItem : public DockItem
Q_OBJECT
public:
explicit AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr);
explicit AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const Entry *entry, QWidget *parent = nullptr);
~AppItem() override;
void checkEntry() override;
@ -43,7 +45,7 @@ public:
bool supportSplitWindow();
bool splitWindowOnScreen(ScreenSpliter::SplitDirection direction);
int mode() const;
DockEntryInter *itemEntryInter() const;
Entry *itemEntry() const;
inline ItemType itemType() const override { return App; }
QPixmap appIcon(){ return m_appIcon; }
uint32_t currentWindow(){ return m_currentWindow; }
@ -52,7 +54,7 @@ public:
bool isDocked() const;
qint64 appOpenMSecs() const;
void updateMSecs();
const WindowInfoMap &windowsMap() const;
const WindowInfoMap &windowsInfos() const;
void activeWindow(WId wid);
signals:
@ -108,9 +110,9 @@ private:
const QGSettings *m_appSettings;
const QGSettings *m_activeAppSettings;
const QGSettings *m_dockedAppSettings;
Entry *m_itemEntry;
PreviewContainer *m_appPreviewTips;
DockEntryInter *m_itemEntryInter;
QGraphicsView *m_swingEffectView;
QGraphicsItemAnimation *m_itemAnimation;

View File

@ -8,6 +8,7 @@
#include "dockitem.h"
#include "dbusutil.h"
#include "taskmanager/windowinfomap.h"
class AppItem;

View File

@ -6,6 +6,8 @@
#include "appsnapshot.h"
#include "previewcontainer.h"
#include "../widgets/tipswidget.h"
#include "taskmanager/taskmanager.h"
#include "taskmanager/xcbutils.h"
#include "utils.h"
#include "imageutil.h"
@ -23,6 +25,9 @@
#include <QSizeF>
#include <QTimer>
#include <QPainterPath>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDBusReply>
struct SHMInfo {
long shmid;
@ -51,7 +56,6 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
, m_waitLeaveTimer(new QTimer(this))
, m_closeBtn2D(new DIconButton(this))
, m_wmHelper(DWindowManagerHelper::instance())
, m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
{
m_closeBtn2D->setFixedSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH);
m_closeBtn2D->setIconSize(QSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH));
@ -79,7 +83,7 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
void AppSnapshot::setWindowState()
{
if (m_isWidowHidden) {
m_dockDaemonInter->MinimizeWindow(m_wid);
TaskManager::instance()->MinimizeWindow(m_wid);
}
}
@ -130,7 +134,7 @@ void AppSnapshot::setTitleVisible(bool bVisible)
void AppSnapshot::closeWindow() const
{
if (Utils::IS_WAYLAND_DISPLAY) {
m_dockDaemonInter->CloseWindow(static_cast<uint>(m_wid));
TaskManager::instance()->closeWindow(static_cast<uint>(m_wid));
} else {
const auto display = QX11Info::display();
if (!display) {

View File

@ -7,6 +7,7 @@
#define APPSNAPSHOT_H
#include "dbusutil.h"
#include "taskmanager/windowinfomap.h"
#include <DIconButton>
#include <DWindowManagerHelper>
@ -99,7 +100,6 @@ private:
QTimer *m_waitLeaveTimer;
DIconButton *m_closeBtn2D;
DWindowManagerHelper *m_wmHelper;
DockInter *m_dockDaemonInter;
};
#endif // APPSNAPSHOT_H

View File

@ -68,9 +68,7 @@ void PreviewContainer::setWindowInfos(const WindowInfoMap &infos, const WindowLi
if (!m_snapshots.contains(key))
appendSnapWidget(key);
m_snapshots[key]->setWindowInfo(it.value());
// FIXME: "GetAllowedCloseWindows" has remove form dde-daemon
// 由于相关接口被移除,暂时无法正确设置 m_closeAble 属性,暂改为默认 true
// m_snapshots[key]->setCloseAble(allowClose.contains(key));
m_snapshots[key]->setCloseAble(allowClose.contains(key));
}
if (m_snapshots.isEmpty()) {

View File

@ -17,7 +17,7 @@
#include <DWindowManagerHelper>
DWIDGET_USE_NAMESPACE
typedef QList<quint32> WindowList;
class PreviewContainer : public QWidget
{
Q_OBJECT

View File

@ -14,6 +14,7 @@
#include <QMouseEvent>
#include <QApplication>
#include <QGSettings>
#include <QtConcurrent>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <DDBusSender>
@ -84,15 +85,17 @@ void LauncherItem::mouseReleaseEvent(QMouseEvent *e)
if (e->button() != Qt::LeftButton)
return;
DDBusSender dbusSender = DDBusSender()
QtConcurrent::run([=] {
DDBusSender dbusSender = DDBusSender()
.service(launcherService)
.path(launcherPath)
.interface(launcherInterface);
QDBusPendingReply<bool> visibleReply = dbusSender.property("Visible").get();
if (!visibleReply.value())
dbusSender.method("Toggle").call();
QDBusPendingReply<bool> visibleReply = dbusSender.property("Visible").get();
if (!visibleReply.value())
dbusSender.method("Toggle").call();
});
}
QWidget *LauncherItem::popupTips()

View File

@ -5,9 +5,9 @@
#include "mainwindow.h"
#include "dbusdockadaptors.h"
#include "dockdaemonadaptors.h"
#include "utils.h"
#include "themeappicon.h"
#include "dockitemmanager.h"
#include "dockapplication.h"
#include "traymainwindow.h"
#include "windowmanager.h"
@ -221,10 +221,15 @@ int main(int argc, char *argv[])
// 注册任务栏的DBus服务
DBusDockAdaptors adaptor(&windowManager);
DockDaemonDBusAdaptor daemonAdaptor(&windowManager);
QDBusConnection::sessionBus().registerService("org.deepin.dde.Dock1");
QDBusConnection::sessionBus().registerObject("/org/deepin/dde/Dock1", "org.deepin.dde.Dock1", &windowManager);
//保证dock daemon接口兼容性,dde-desktop,dde-clipboard,deepin-system-monitor,dde-osd等在调用。
QDBusConnection::sessionBus().registerService("org.deepin.dde.daemon.Dock1");
QDBusConnection::sessionBus().registerObject("/org/deepin/dde/daemon/Dock1", "org.deepin.dde.daemon.Dock1", &windowManager);
// 当任务栏以-r参数启动时设置CANSHOW未false之后调用launch不显示任务栏
qApp->setProperty("CANSHOW", !parser.isSet(runOption));

View File

@ -68,7 +68,7 @@ bool ScreenSpliter_Wayland::split(SplitDirection direction)
if (!suportSplitScreen())
return false;
WindowInfoMap windowInfos = appItem()->windowsMap();
WindowInfoMap windowInfos = appItem()->windowsInfos();
m_splitManager->requestSplitWindow(windowInfos.first().uuid.toStdString().c_str(), direction);
return true;
@ -82,7 +82,7 @@ bool ScreenSpliter_Wayland::windowSupportSplit(const QString &uuid) const
bool ScreenSpliter_Wayland::suportSplitScreen()
{
// 判断所有打开的窗口列表,只要有一个窗口支持分屏,就认为它支持分屏
const WindowInfoMap &windowsInfo = appItem()->windowsMap();
const WindowInfoMap &windowsInfo = appItem()->windowsInfos();
for (const WindowInfo &windowInfo : windowsInfo) {
if (windowSupportSplit(windowInfo.uuid))
return true;

View File

@ -9,6 +9,7 @@
#include "screenspliter.h"
#include <QWidget>
#include <QMap>
namespace KWayland {
namespace Client {

View File

@ -79,7 +79,7 @@ bool ScreenSpliter_Xcb::split(ScreenSpliter::SplitDirection direction)
if (!suportSplitScreen())
return false;
quint32 WId = appItem()->windowsMap().keys().first();
quint32 WId = appItem()->windowsInfos().keys().first();
xcb_client_message_event_t xev;
xev.response_type = XCB_CLIENT_MESSAGE;
xev.type = internAtom("_DEEPIN_SPLIT_WINDOW", false);
@ -116,7 +116,7 @@ void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible)
if (!suportSplitScreen())
return;
quint32 WId = appItem()->windowsMap().keys().first();
quint32 WId = appItem()->windowsInfos().keys().first();
// 触发分屏的效果
xcb_client_message_event_t xev;
xev.response_type = XCB_CLIENT_MESSAGE;
@ -137,7 +137,7 @@ void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible)
bool ScreenSpliter_Xcb::suportSplitScreen()
{
// 判断所有的窗口,只要有一个窗口支持分屏,就认为它支持分屏
QList<quint32> winIds = appItem()->windowsMap().keys();
QList<quint32> winIds = appItem()->windowsInfos().keys();
for (const quint32 &winId : winIds) {
if (windowSupportSplit(winId))
return true;

View File

@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "appinfo.h"
#include "common.h"
#include <QDebug>
#include <QString>
#include <QCryptographicHash>
AppInfo::AppInfo(DesktopInfo &info)
: m_isValid(true)
{
init(info);
}
AppInfo::AppInfo(const QString &_fileName)
: m_isValid(true)
{
DesktopInfo info(_fileName);
init(info);
}
void AppInfo::init(DesktopInfo &info)
{
if (!info.isValidDesktop()) {
m_isValid = false;
return;
}
QString xDeepinVendor = info.getDesktopFile()->value(MainSection + "/X-Deepin-Vendor").toString();
if (xDeepinVendor == "deepin") {
m_name = info.getGenericName();
if (m_name.isEmpty()) {
m_name = info.getName();
}
} else {
m_name = info.getName();
}
m_innerId = genInnerIdWithDesktopInfo(info);
m_fileName = info.getDesktopFilePath();
m_id = info.getId();
m_icon = info.getIcon();
for (const auto & action : info.getActions()) {
m_actions.push_back(action);
}
}
QString AppInfo::genInnerIdWithDesktopInfo(DesktopInfo &info)
{
QString cmdline = info.getCommandLine();
QByteArray encryText = QCryptographicHash::hash(QString(cmdline).toLatin1(), QCryptographicHash::Md5);
QString innerId = desktopHashPrefix + encryText.toHex();
qInfo() << "app: " << info.getId() << " generate innerId: " << innerId;
return innerId;
}

View File

@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#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);
void setIdentifyMethod(QString method) {m_identifyMethod = method;}
bool isValidApp() {return m_isValid;}
bool isInstalled() {return m_installed;}
QString getId() {return m_id;}
QString getIcon() {return m_icon;}
QString getName() {return m_name;}
QString getInnerId() {return m_innerId;}
QString getFileName() {return m_fileName;}
QString getIdentifyMethod() {return m_identifyMethod;}
QVector<DesktopAction> getActions() {return m_actions;}
private:
QString genInnerIdWithDesktopInfo(DesktopInfo &info);
private:
bool m_installed;
bool m_isValid;
QString m_id;
QString m_name;
QString m_icon;
QString m_innerId;
QString m_fileName;
QString m_identifyMethod;
QVector<DesktopAction> m_actions;
};
#endif // APPINFO_H

View File

@ -0,0 +1,80 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "appmenu.h"
#include <QJsonArray>
#include <QJsonDocument>
AppMenu::AppMenu()
: m_itemCount(0)
, m_dirty(false)
, m_checkableMenu(false)
, m_singleCheck(false)
{
}
/**
* @brief AppMenu::appendItem
* @param item
*/
void AppMenu::appendItem(AppMenuItem item)
{
if (!item.text.isEmpty()) {
item.id = allocateId();
m_items.push_back(item);
}
}
/**
* @brief AppMenu::handleAction
* @param timestamp
* @param itemId
*/
void AppMenu::handleAction(uint32_t timestamp, QString itemId)
{
for (auto &item : m_items) {
if (item.id == itemId) {
item.action(timestamp);
break;
}
}
}
void AppMenu::setDirtyStatus(bool isDirty)
{
m_dirty = isDirty;
}
QString AppMenu::getMenuJsonStr()
{
QJsonObject obj;
QJsonArray array;
for (auto item : m_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(objItem);
}
obj["items"] = QJsonValue(array);
obj["checkableMenu"] = m_checkableMenu;
obj["singleCheck"] = m_singleCheck;
QString ret = QJsonDocument(obj).toJson();
return ret;
}
QString AppMenu::allocateId()
{
return QString::number(m_itemCount++);
}

View File

@ -0,0 +1,67 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#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
{
AppMenuItem()
: isActive(true)
, hint(0)
{
}
QString id;
QString text;
QString isCheckable;
QString checked;
QString icon;
QString iconHover;
QString iconInactive;
QString showCheckMark;
std::shared_ptr<AppMenu> subMenu;
bool isActive;
int hint;
AppMenuAction action;
};
// 应用菜单类
class AppMenu
{
public:
AppMenu();
void appendItem(AppMenuItem item);
void setDirtyStatus(bool isDirty);
void handleAction(uint32_t timestamp, QString itemId);
QString getMenuJsonStr();
private:
QString allocateId();
private:
int m_itemCount;
bool m_dirty;
bool m_checkableMenu; // json:"checkableMenu"
bool m_singleCheck; // json:"singleCheck"
QVector<AppMenuItem> m_items; // json:"items"
};
#endif // APPMENU_H

View File

@ -0,0 +1,89 @@
// SPDX-FileCopyrightText: 2022 ~ 2022 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "bamfdesktop.h"
#include <QDir>
#include <qstandardpaths.h>
#define BAMF_INDEX_NAME "bamf-2.index"
BamfDesktop *BamfDesktop::instance()
{
static BamfDesktop instance;
return &instance;
}
QString BamfDesktop::fileName(const QString &instanceName) const
{
for (const BamfData &lineData: m_bamfLineData) {
if (lineData.instanceName.toLower() == instanceName.toLower()) {
QString name = lineData.lineData.split("\t").first();
return QString("%1%2").arg(lineData.directory).arg(name);
}
}
// 如果根据instanceName没有找到则根据空格来进行分隔
for (const BamfData &lineData: m_bamfLineData) {
QStringList lines = lineData.lineData.split("\t");
if (lines.size() < 2)
continue;
QStringList cmds = lines[2].split(" ");
if (cmds.size() > 1 && cmds[1].toLower() == instanceName.toLower())
return QString("%1%2").arg(lineData.directory).arg(lines.first());
}
return instanceName;
}
BamfDesktop::BamfDesktop()
{
loadDesktopFiles();
}
BamfDesktop::~BamfDesktop()
{
}
QStringList BamfDesktop::applicationDirs() const
{
QStringList appDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
QStringList directions;
for (auto appDir : appDirs)
directions << appDir;
return directions;
}
void BamfDesktop::loadDesktopFiles()
{
QStringList directions = applicationDirs();
for (const QString &direction : directions) {
// 读取后缀名为
QDir dir(direction);
dir.setNameFilters(QStringList() << BAMF_INDEX_NAME);
QFileInfoList fileList = dir.entryInfoList();
if (fileList.size() == 0)
continue;
QFileInfo fileInfo = fileList.at(0);
QFile file(fileInfo.absoluteFilePath());
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
continue;
QList<QPair<QString, QString>> bamfLine;
while (!file.atEnd()) {
QString line = file.readLine();
QStringList part = line.split("\t");
BamfData bamf;
bamf.directory = direction;
if (part.size() > 2)
bamf.instanceName = part[2].trimmed();
bamf.lineData = line;
m_bamfLineData << bamf;
}
}
}

View File

@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2022 ~ 2022 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef BAMFDESKTOP_H
#define BAMFDESKTOP_H
#include <QObject>
#include <QMap>
struct BamfData {
QString directory;
QString instanceName;
QString lineData;
};
class BamfDesktop
{
public:
static BamfDesktop *instance();
QString fileName(const QString &instanceName) const;
protected:
BamfDesktop();
~BamfDesktop();
private:
QStringList applicationDirs() const;
void loadDesktopFiles();
private:
QList<BamfData> m_bamfLineData;
};
#endif // BAMFDESKTOP_H

View File

@ -0,0 +1,85 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef COMMON_H
#define COMMON_H
#include <QMap>
#include <QDir>
#include <QString>
#include <QStandardPaths>
const QString configDock = "com.deepin.dde.dock";
const QString configAppearance = "com.deepin.dde.appearance";
const QString keyOpacity = "Opacity";
const QString keyPosition = "Position";
const QString keyIconSize = "Icon_Size";
const QString keyHideMode = "Hide_Mode";
const QString keyRecentApp = "Recent_App";
const QString keyShowRecent = "Show_Recent";
const QString keyDockedApps = "Docked_Apps";
const QString keyDisplayMode = "Display_Mode";
const QString keyShowTimeout = "Show_Timeout";
const QString keyHideTimeout = "Hide_Timeout";
const QString keyForceQuitApp = "Force_Quit_App";
const QString keyPluginSettings = "Plugin_Settings";
const QString keyShowMultiWindow = "Show_MultiWindow";
const QString keyWindowSizeFashion = "Window_Size_Fashion";
const QString keyWindowSizeEfficient = "Window_Size_Efficient";
const QString keyWinIconPreferredApps = "Win_Icon_Preferred_Apps";
static const QString scratchDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).append("/deepin/dde-dock/scratch/");
const QString desktopHashPrefix = "d:";
const QString windowHashPrefix = "w:";
// 驻留应用desktop file模板
// 由于Icon存储的直接是icon base64压缩后的数据需要“”防止被desktopfile当成stringlist从而导致获取icon失败
const QString dockedItemTemplate = R"([Desktop Entry]
Name=%1
Exec=%2
Icon="%3"
Type=Application
Terminal=false
StartupNotify=false
)";
const QString frontendWindowWmClass = "dde-dock";
const QString ddeLauncherWMClass = "dde-launcher";
const int smartHideTimerDelay = 400;
const int configureNotifyDelay = 100;
const int bestIconSize = 48;
const int menuItemHintShowAllWindows = 1;
const int MotifHintStatus = 8;
const int MotifHintFunctions = 1;
const int MotifHintInputMode = 4;
const int MotifHintDecorations = 2;
const int MotifFunctionNone = 0;
const int MotifFunctionAll = 1;
const int MotifFunctionMove = 4;
const int MotifFunctionClose = 32;
const int MotifFunctionResize = 2;
const int MotifFunctionMinimize = 8;
const int MotifFunctionMaximize = 16;
static inline QByteArray sessionType() {
static QByteArray type = qgetenv("XDG_SESSION_TYPE");
return type;
}
static inline bool isWaylandSession() {
return sessionType().compare("wayland") == 0;
}
static inline bool isX11Session() {
return sessionType().compare("x11") == 0;
}
#endif // COMMON_H

View File

@ -0,0 +1,211 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "dbushandler.h"
#include "taskmanager.h"
#include "common.h"
#include "entry.h"
#include "windowinfok.h"
DBusHandler::DBusHandler(TaskManager *taskmanager, QObject *parent)
: QObject(parent)
, m_taskmanager(taskmanager)
, m_wm(new com::deepin::wm("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this))
, m_wmSwitcher(new org::deepin::dde::WMSwitcher1("org.deepin.dde.WMSwitcher1", "/org/deepin/dde/WMSwitcher1", QDBusConnection::sessionBus(), this))
, m_kwaylandManager(nullptr)
, m_xEventMonitor(nullptr)
{
connect(m_wmSwitcher, &org::deepin::dde::WMSwitcher1::WMChanged, this, [&](QString name) {m_taskmanager->setWMName(name);});
if (!isWaylandSession()) {
m_xEventMonitor = new org::deepin::dde::XEventMonitor1("org.deepin.dde.XEventMonitor1", "/org/deepin/dde/XEventMonitor1", QDBusConnection::sessionBus(), this);
m_activeWindowMonitorKey = m_xEventMonitor->RegisterFullScreen();
connect(m_xEventMonitor, &org::deepin::dde::XEventMonitor1::ButtonRelease, this, &DBusHandler::onActiveWindowButtonRelease);
}
}
void DBusHandler::listenWaylandWMSignals()
{
m_kwaylandManager = new org::deepin::dde::kwayland1::WindowManager("org.deepin.dde.KWayland1", "/org/deepin/dde/KWayland1/WindowManager", QDBusConnection::sessionBus(), this);
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::ActiveWindowChanged, this, &DBusHandler::handleWlActiveWindowChange);
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::WindowCreated, this, [&] (const QString &ObjPath) {
m_taskmanager->registerWindowWayland(ObjPath);
});
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::WindowRemove, this, [&] (const QString &ObjPath) {
m_taskmanager->unRegisterWindowWayland(ObjPath);
});
}
void DBusHandler::loadClientList()
{
if (!m_kwaylandManager)
return;
QDBusPendingReply<QVariantList> windowList = m_kwaylandManager->Windows();
QVariantList windows = windowList.value();
for (QVariant windowPath : windows)
m_taskmanager->registerWindowWayland(windowPath.toString());
}
QString DBusHandler::getCurrentWM()
{
return m_wmSwitcher->CurrentWM().value();
}
void DBusHandler::launchApp(QString desktopFile, uint32_t timestamp, QStringList files)
{
QDBusInterface interface = QDBusInterface("org.deepin.dde.Application1.Manager", "/org/deepin/dde/Application1/Manager", "org.deepin.dde.Application1.Manager");
interface.call("LaunchApp", desktopFile, timestamp, files);
}
void DBusHandler::launchAppAction(QString desktopFile, QString action, uint32_t timestamp)
{
QDBusInterface interface = QDBusInterface("org.deepin.dde.Application1.Manager", "/org/deepin/dde/Application1/Manager", "org.deepin.dde.Application1.Manager");
interface.call("LaunchAppAction", desktopFile, action, timestamp);
}
void DBusHandler::markAppLaunched(const QString &filePath)
{
QDBusInterface interface = QDBusInterface("org.deepin.dde.AlRecorder1", "/org/deepin/dde/AlRecorder1", "org.deepin.dde.AlRecorder1");
interface.call("MarkLaunched", filePath);
}
bool DBusHandler::wlShowingDesktop()
{
bool ret = false;
if (m_kwaylandManager)
ret = m_kwaylandManager->IsShowingDesktop().value();
return ret;
}
uint DBusHandler::wlActiveWindow()
{
uint ret = 0;
if (m_kwaylandManager)
ret = m_kwaylandManager->ActiveWindow().value();
return ret;
}
void DBusHandler::handleWlActiveWindowChange()
{
uint activeWinInternalId = wlActiveWindow();
if (activeWinInternalId == 0)
return;
WindowInfoK *info = m_taskmanager->handleActiveWindowChangedK(activeWinInternalId);
if (info && info->getXid() != 0) {
m_taskmanager->handleActiveWindowChanged(info);
} else {
m_taskmanager->updateHideState(false);
}
}
void DBusHandler::onActiveWindowButtonRelease(int type, int x, int y, const QString &key)
{
// 当鼠标松开区域事件的时候,取消注册,同时调用激活窗口的方法来触发智能隐藏的相关信号
if (key != m_activeWindowMonitorKey)
return;
uint activeWinInternalId = wlActiveWindow();
if (activeWinInternalId == 0)
return;
WindowInfoK *info = m_taskmanager->handleActiveWindowChangedK(activeWinInternalId);
if (!info)
return;
// 如果是在当前激活窗口区域内释放的,则触发检测智能隐藏的方法
DockRect dockRect = info->getGeometry();
if (dockRect.x <= x && x <= int(dockRect.x + dockRect.w) && dockRect.y <= y && y <= int(dockRect.y + dockRect.h)) {
// 取消智能隐藏
m_taskmanager->updateHideState(false);
}
}
void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo)
{
PlasmaWindow *window = windowInfo->getPlasmaWindow();
if (!window)
return;
connect(window, &PlasmaWindow::TitleChanged, this, [=] {
windowInfo->updateTitle();
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
if (entry && entry->getCurrentWindowInfo() == windowInfo)
entry->updateName();
});
connect(window, &PlasmaWindow::IconChanged, this, [=] {
windowInfo->updateIcon();
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
if (!entry) return;
entry->updateIcon();
});
// DemandingAttention changed
connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [=] {
windowInfo->updateDemandingAttention();
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
if (!entry) return;
entry->updateExportWindowInfos();
});
// Geometry changed
connect(window, &PlasmaWindow::GeometryChanged, this, [=] {
if (!windowInfo->updateGeometry()) return;
m_taskmanager->handleWindowGeometryChanged();
});
}
PlasmaWindow *DBusHandler::createPlasmaWindow(QString objPath)
{
return new PlasmaWindow("org.deepin.dde.KWayland1", objPath, QDBusConnection::sessionBus(), this);
}
/**
* @brief DBusHandler::removePlasmaWindowHandler TODO
* @param window
*/
void DBusHandler::removePlasmaWindowHandler(PlasmaWindow *window)
{
}
void DBusHandler::presentWindows(QList<uint> windows)
{
m_wm->PresentWindows(windows);
}
void DBusHandler::previewWindow(uint xid)
{
m_wm->PreviewWindow(xid);
}
void DBusHandler::cancelPreviewWindow()
{
m_wm->CancelPreviewWindow();
}
// TODO: 待优化点, 查看Bamf根据windowId获取对应应用desktopFile路径实现方式, 移除bamf依赖
QString DBusHandler::getDesktopFromWindowByBamf(XWindow windowId)
{
QDBusInterface interface0 = QDBusInterface("org.ayatana.bamf", "/org/ayatana/bamf/matcher", "org.ayatana.bamf.matcher");
QDBusReply<QString> replyApplication = interface0.call("ApplicationForXid", windowId);
QString appObjPath = replyApplication.value();
if (!replyApplication.isValid() || appObjPath.isEmpty())
return "";
QDBusInterface interface = QDBusInterface("org.ayatana.bamf", appObjPath, "org.ayatana.bamf.application");
QDBusReply<QString> replyDesktopFile = interface.call("DesktopFile");
if (replyDesktopFile.isValid())
return replyDesktopFile.value();
return "";
}

View File

@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef DBUSHANDLER_H
#define DBUSHANDLER_H
#include "com_deepin_wm.h"
#include "org_deepin_dde_wmswitcher1.h"
#include "org_deepin_dde_xeventmonitor1.h"
#include "org_deepin_dde_kwayland_windowmanager.h"
#include "org_deepin_dde_kwayland_plasmawindow.h"
#include "windowinfok.h"
#include <QObject>
#include <QDBusConnection>
#include <QDBusMessage>
class TaskManager;
// 处理DBus交互
class DBusHandler : public QObject
{
Q_OBJECT
public:
explicit DBusHandler(TaskManager *taskmanager, QObject *parent = nullptr);
/************************* KWayland/WindowManager ***************************/
void listenWaylandWMSignals();
void loadClientList();
bool wlShowingDesktop();
uint wlActiveWindow();
/************************* WMSwitcher ***************************/
QString getCurrentWM();
/************************* StartManager ***************************/
void launchApp(QString desktopFile, uint32_t timestamp, QStringList files);
void launchAppAction(QString desktopFile, QString action, uint32_t timestamp);
/************************* AlRecorder1 ***************************/
void markAppLaunched(const QString &filePath);
/************************* KWayland.PlasmaWindow ***************************/
void listenKWindowSignals(WindowInfoK *windowInfo);
void removePlasmaWindowHandler(PlasmaWindow *window);
PlasmaWindow *createPlasmaWindow(QString objPath);
/************************* WM ***************************/
void presentWindows(QList<uint> windows);
void previewWindow(uint xid);
void cancelPreviewWindow();
/************************* bamf ***************************/
// XWindow -> desktopFile
QString getDesktopFromWindowByBamf(XWindow windowId);
private Q_SLOTS:
void handleWlActiveWindowChange();
void onActiveWindowButtonRelease(int type, int x, int y, const QString &key);
private:
QString m_activeWindowMonitorKey;
TaskManager *m_taskmanager;
com::deepin::wm *m_wm;
org::deepin::dde::WMSwitcher1 *m_wmSwitcher;
org::deepin::dde::kwayland1::WindowManager *m_kwaylandManager;
org::deepin::dde::XEventMonitor1 *m_xEventMonitor;
};
#endif // DBUSHANDLER_H

View File

@ -0,0 +1,247 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "desktopinfo.h"
#include "locale.h"
#include "unistd.h"
#include <QDebug>
#include <algorithm>
#include <QFileInfo>
#include <QSettings>
#include <QStandardPaths>
#include <QVector>
#include <qlocale.h>
QStringList DesktopInfo::currentDesktops;
static QString desktopFileSuffix = ".desktop";
DesktopInfo::DesktopInfo(const QString &desktopfile)
: m_isValid(true)
{
QString desktopfilepath(desktopfile);
QFileInfo desktopFileInfo(desktopfilepath);
if (!(desktopfilepath.endsWith(desktopFileSuffix))) {
desktopfilepath = desktopfilepath + desktopFileSuffix;
desktopFileInfo.setFile(desktopfilepath);
}
if (!desktopFileInfo.isAbsolute()) {
for (auto dir: QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)) {
QString path = dir.append("/").append(desktopfilepath);
if (QFile::exists(path)) desktopFileInfo.setFile(path);
}
}
m_desktopFilePath = desktopFileInfo.absoluteFilePath();
m_isValid = desktopFileInfo.isAbsolute() && QFile::exists(desktopFileInfo.absoluteFilePath());
m_desktopFile.reset(new QSettings(m_desktopFilePath, QSettings::IniFormat));
m_desktopFile->setIniCodec("utf-8");
// check DesktopInfo valid
QStringList mainKeys = m_desktopFile->childGroups();
if (mainKeys.size() == 0)
m_isValid = false;
bool found = std::any_of(mainKeys.begin(), mainKeys.end(),
[](const auto &key) {return key == MainSection;});
if (!found)
m_isValid = false;
if (m_desktopFile->value(MainSection + '/' + KeyType).toString() != TypeApplication)
m_isValid = false;
m_name = getLocaleStr(MainSection, KeyName);
m_icon = m_desktopFile->value(MainSection + '/' + KeyIcon).toString();
m_id = getId();
}
DesktopInfo::~DesktopInfo()
{
}
QString DesktopInfo::getDesktopFilePath()
{
return m_desktopFilePath;
}
bool DesktopInfo::isValidDesktop()
{
return m_isValid;
}
/** if return true, item is shown
* @brief DesktopInfo::shouldShow
* @return
*/
bool DesktopInfo::shouldShow()
{
if (getNoDisplay() || getIsHidden()) {
qDebug() << "hidden desktop file path: " << m_desktopFilePath;
return false;
}
QStringList desktopEnvs;
return getShowIn(desktopEnvs);
}
bool DesktopInfo::getNoDisplay()
{
return m_desktopFile->value(MainSection + '/' + KeyNoDisplay).toBool();
}
bool DesktopInfo::getIsHidden()
{
return m_desktopFile->value(MainSection + '/' + KeyHidden).toBool();
}
bool DesktopInfo::getShowIn(QStringList desktopEnvs)
{
#ifdef QT_DEBUG
qDebug() << "desktop file path: " << m_desktopFilePath;
#endif
if (desktopEnvs.size() == 0) {
const QString env = getenv("XDG_CURRENT_DESKTOP");
QVector<QString> desktops = env.split(":").toVector();
currentDesktops.fromVector(desktops);
desktopEnvs.fromVector(desktops);
}
QStringList onlyShowIn = m_desktopFile->value(MainSection + '/' + KeyOnlyShowIn).toStringList();
QStringList notShowIn = m_desktopFile->value(MainSection + '/' + KeyNotShowIn).toStringList();
#ifdef QT_DEBUG
qDebug() << "onlyShowIn:" << onlyShowIn <<
", notShowIn:" << notShowIn <<
", desktopEnvs:" << desktopEnvs;
#endif
for (const auto &desktop : desktopEnvs) {
bool ret = std::any_of(onlyShowIn.begin(), onlyShowIn.end(),
[&desktop](const auto &d) {return d == desktop;});
#ifdef QT_DEBUG
qInfo() << Q_FUNC_INFO << "onlyShowIn, result:" << ret;
#endif
if (ret)
return true;
ret = std::any_of(notShowIn.begin(), notShowIn.end(),
[&desktop](const auto &d) {return d == desktop;});
#ifdef QT_DEBUG
qInfo() << Q_FUNC_INFO << "notShowIn, result:" << ret;
#endif
if (ret)
return false;
}
return onlyShowIn.size() == 0;
}
QString DesktopInfo::getExecutable()
{
return m_desktopFile->value(MainSection + '/' + KeyExec).toString();
}
QList<DesktopAction> DesktopInfo::getActions()
{
QList<DesktopAction> actions;
for (const auto &mainKey : m_desktopFile->childGroups()) {
if (mainKey.startsWith("Desktop Action")
|| mainKey.endsWith("Shortcut Group")) {
DesktopAction action;
action.name = getLocaleStr(mainKey, KeyName);
action.exec = m_desktopFile->value(mainKey + '/' + KeyExec).toString();
action.section = mainKey;
actions.push_back(action);
}
}
return actions;
}
// 使用appId获取DesktopInfo需检查有效性
DesktopInfo DesktopInfo::getDesktopInfoById(const QString &appId)
{
QString desktopfile(appId);
if (!desktopfile.endsWith(".desktop")) desktopfile.append(".desktop");
for (const auto & dir : QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)) {
QString filePath = dir + desktopfile;
//检测文件有效性
if (QFile::exists(filePath)) {
return DesktopInfo(filePath);
}
}
return DesktopInfo("");
}
bool DesktopInfo::getTerminal()
{
return m_desktopFile->value(MainSection + '/' + KeyTerminal).toBool();
}
// TryExec is Path to an executable file on disk used to determine if the program is actually installed
QString DesktopInfo::getTryExec()
{
return m_desktopFile->value(MainSection + '/' + KeyTryExec).toString();
}
// 按$PATH路径查找执行文件
bool DesktopInfo::findExecutable(const QString &exec)
{
static const char *path = getenv("PATH");
static QStringList paths = QString(path).split(':');
return std::any_of(paths.begin(), paths.end(), [&exec](QString path) {return QFile::exists(path + '/' + exec);});
}
QString DesktopInfo::getGenericName()
{
return getLocaleStr(MainSection, KeyGenericName);
}
QString DesktopInfo::getName()
{
return m_name;
}
QString DesktopInfo::getIcon()
{
return m_icon;
}
QString DesktopInfo::getCommandLine()
{
return m_desktopFile->value(MainSection + '/' + KeyExec).toString();
}
QStringList DesktopInfo::getKeywords()
{
return m_desktopFile->value(MainSection + '/' + KeyKeywords).toStringList();
}
QStringList DesktopInfo::getCategories()
{
return m_desktopFile->value(MainSection + '/' + KeyCategories).toStringList();
}
QSettings *DesktopInfo::getDesktopFile()
{
return m_desktopFile.data();
}
QString DesktopInfo::getId()
{
return m_id;
}
QString DesktopInfo::getLocaleStr(const QString &section, const QString &key)
{
QString currentLanguageCode = QLocale::system().name();
QString res = m_desktopFile->value(section + '/' + key + QString("[%1]").arg(currentLanguageCode)).toString();
if (res.isEmpty()) res = m_desktopFile->value(section + '/' + key).toString();
return res;
}

View File

@ -0,0 +1,108 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef DESKTOPINFO_H
#define DESKTOPINFO_H
#include <QSettings>
#include <qscopedpointer.h>
#include <string>
#include <vector>
const QString MainSection = "Desktop Entry";
const QString KeyType = "Type";
const QString KeyVersion = "Version";
const QString KeyName = "Name";
const QString KeyGenericName = "GenericName";
const QString KeyNoDisplay = "NoDisplay";
const QString KeyComment = "Comment";
const QString KeyIcon = "Icon";
const QString KeyHidden = "Hidden";
const QString KeyOnlyShowIn = "OnlyShowIn";
const QString KeyNotShowIn = "NotShowIn";
const QString KeyTryExec = "TryExec";
const QString KeyExec = "Exec";
const QString KeyPath = "Path";
const QString KeyTerminal = "Terminal";
const QString KeyMimeType = "MimeType";
const QString KeyCategories = "Categories";
const QString KeyKeywords = "Keywords";
const QString KeyStartupNotify = "StartupNotify";
const QString KeyStartupWMClass = "StartupWMClass";
const QString KeyURL = "URL";
const QString KeyActions = "Actions";
const QString KeyDBusActivatable = "DBusActivatable";
const QString TypeApplication = "Application";
const QString TypeLink = "Link";
const QString TypeDirectory = "Directory";
typedef struct DesktopAction
{
DesktopAction()
: section("")
, name("")
, exec("")
{
}
QString section;
QString name;
QString exec;
} DesktopAction;
// 应用Desktop信息类
class DesktopInfo {
public:
explicit DesktopInfo(const QString &desktopfile);
~DesktopInfo();
static bool isDesktopAction(const QString &name);
static DesktopInfo getDesktopInfoById(const QString &appId);
bool shouldShow();
bool getIsHidden();
bool isInstalled();
bool getTerminal();
bool getNoDisplay();
bool isExecutableOk();
bool isValidDesktop();
bool getShowIn(QStringList desktopEnvs);
void setDesktopOverrideExec(const QString &execStr);
QString getId();
QString getName();
QString getIcon();
QString getExecutable();
QString getGenericName();
QString getCommandLine();
QString getDesktopFilePath();
QStringList getKeywords();
QStringList getCategories();
QList<DesktopAction> getActions();
QSettings *getDesktopFile();
private:
bool findExecutable(const QString &exec);
QString getTryExec();
QString getLocaleStr(const QString &section, const QString &key);
private:
static QStringList currentDesktops;
bool m_isValid;
QString m_id;
QString m_name;
QString m_icon;
QString m_desktopFilePath;
// Desktopfile ini format
QScopedPointer<QSettings> m_desktopFile;
};
#endif // DESKTOPINFO_H

View File

@ -0,0 +1,349 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "entries.h"
#include "taskmanager.h"
#include "docksettings.h"
#include "taskmanager/windowinfobase.h"
#include <QList>
#include <algorithm>
#include <iterator>
Entries::Entries(TaskManager *_taskmanager)
: m_taskmanager(_taskmanager)
{
}
QVector<Entry *> Entries::filterDockedEntries()
{
QVector<Entry *> ret;
for (auto entry : m_items) {
if (entry->isValid() && entry->getIsDocked()) ret.push_back(entry);
}
return ret;
}
Entry *Entries::getByInnerId(QString innerId)
{
Entry *ret = nullptr;
for (auto &entry : m_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 (m_items.contains(entry))
m_items.removeOne(entry);
if (index < 0 || index >= m_items.size()) {
// append
index = m_items.size();
m_items.push_back(entry);
} else {
// insert
m_items.insert(index, entry);
}
insertCb(entry, index);
}
void Entries::remove(Entry *entry)
{
for (auto iter = m_items.begin(); iter != m_items.end();) {
if ((*iter)->getId() == entry->getId()) {
iter = m_items.erase(iter);
} else {
iter++;
}
}
removeCb(entry);
entry->deleteLater();
}
void Entries::move(int oldIndex, int newIndex)
{
if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= m_items.size() || newIndex >= m_items.size())
return;
m_items.swapItemsAt(oldIndex, newIndex);
}
Entry *Entries::getByWindowPid(int pid)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getWindowInfoByPid(pid)) {
ret = entry;
break;
}
}
return ret;
}
QStringList Entries::getEntryIDs()
{
QStringList list;
if (m_taskmanager->getDisplayMode() == DisplayMode::Fashion
&& DockSettings::instance()->showRecent()) {
for (Entry *item : m_items) list << item->getId();
} else {
// 如果是高效模式或者没有开启显示最近应用的功能,那么未驻留并且没有子窗口的就不显示
// 换句话说,只显示已经驻留或者有子窗口的应用
for (Entry *item : m_items) {
if (item->getIsDocked() || item->hasWindow())
list << item->getId();
}
}
return list;
}
Entry *Entries::getByWindowId(XWindow windowId)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getWindowInfoByWinId(windowId)) {
ret = entry;
break;
}
}
return ret;
}
Entry *Entries::getByDesktopFilePath(const QString &filePath)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
qDebug() << entry->getName();
if (entry->getFileName() == filePath) {
ret = entry;
break;
}
}
return ret;
}
QList<Entry*> Entries::getEntries()
{
QList<Entry*> list;
if (static_cast<DisplayMode>(m_taskmanager->getDisplayMode()) == DisplayMode::Fashion
&& DockSettings::instance()->showRecent()) {
for (Entry *item : m_items)
list << item;
} else {
// 如果是高效模式或者没有开启显示最近应用的功能,那么未驻留并且没有子窗口的就不显示
// 换句话说,只显示已经驻留或者有子窗口的应用
for (Entry *item : m_items) {
if (!item->getIsDocked() && !item->hasWindow())
continue;
list << item;
}
}
return list;
}
Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile)
{
Entry *ret = nullptr;
for (auto entry : filterDockedEntries()) {
if ((entry->isValid()) && desktopFile == entry->getFileName()) {
ret = entry;
break;
}
}
return ret;
}
QString Entries::queryWindowIdentifyMethod(XWindow windowId)
{
QString ret;
for (auto entry : m_items) {
auto window = entry->getWindowInfoByWinId(windowId);
if (window) {
auto app = window->getAppInfo();
ret = app ? app->getIdentifyMethod() : "Failed";
break;
}
}
return ret;
}
void Entries::handleActiveWindowChanged(XWindow activeWindId)
{
for (auto entry : m_items) {
auto windowInfo = entry->getWindowInfoByWinId(activeWindId);
if (windowInfo) {
entry->setPropIsActive(true);
entry->setCurrentWindowInfo(windowInfo);
entry->updateName();
entry->updateIcon();
} else {
entry->setPropIsActive(false);
}
}
}
void Entries::updateEntriesMenu()
{
for (auto entry : m_items) {
entry->updateMenu();
}
}
const QList<Entry *> Entries::unDockedEntries() const
{
QList<Entry *> entrys;
for (Entry *entry : m_items) {
if (!entry->isValid() || entry->getIsDocked())
continue;
entrys << entry;
}
return entrys;
}
void Entries::moveEntryToLast(Entry *entry)
{
if (m_items.contains(entry)) {
m_items.removeOne(entry);
m_items << entry;
}
}
void Entries::insertCb(Entry *entry, int index)
{
if (entry->getIsDocked() || entry->hasWindow() ||
((m_taskmanager->getDisplayMode() == DisplayMode::Fashion) && DockSettings::instance()->showRecent())){
Q_EMIT m_taskmanager->entryAdded(entry, index);
}
}
void Entries::removeCb(Entry *entry)
{
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
}
bool Entries::shouldInRecent()
{
// 如果当前移除的应用是未驻留应用则判断未驻留应用的数量是否小于等于3则让其始终显示
QList<Entry *> unDocktrys;
for (Entry *entry : m_items) {
if (entry->isValid() && !entry->getIsDocked())
unDocktrys << entry;
}
// 如果当前未驻留应用的数量小于3个则认为后续的应用应该显示到最近打开应用
return (unDocktrys.size() <= MAX_UNOPEN_RECENT_COUNT);
}
void Entries::removeLastRecent()
{
// 先查找最近使用的应用,删除没有使用的
int unDockCount = 0;
QList<Entry *> unDockEntrys;
QList<Entry *> removeEntrys;
for (Entry *entry : m_items) {
if (entry->getIsDocked())
continue;
// 此处只移除没有子窗口的图标
if (!entry->hasWindow()) {
if (!entry->isValid())
removeEntrys << entry; // 如果应用已经被卸载,那么需要删除
else
unDockEntrys << entry;
}
unDockCount++;
}
if (unDockCount >= MAX_UNOPEN_RECENT_COUNT && unDockEntrys.size() > 0) {
// 只有当最近使用区域的图标大于等于某个数值3的时候并且存在没有子窗口的Entry那么就移除该Entry
Entry *entry = unDockEntrys[0];
removeEntrys << entry;
}
for (Entry *entry : removeEntrys) {
m_items.removeOne(entry);
removeCb(entry);
entry->deleteLater();
}
}
void Entries::setDisplayMode(DisplayMode displayMode)
{
if (!DockSettings::instance()->showRecent())
return;
// 如果从时尚模式变成高效模式,对列表中所有的没有打开窗口的应用发送移除信号
if (displayMode == DisplayMode::Efficient) {
for (Entry *entry : m_items) {
entry->updateMode();
if (!entry->getIsDocked() && !entry->hasWindow())
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
}
} else {
// 如果从高效模式变成时尚模式,列表中所有的未驻留且不存在打开窗口的应用认为是最近打开应用,发送新增信号
for (Entry *entry : m_items) {
entry->updateMode();
if (!entry->getIsDocked() && !entry->hasWindow()) {
// QString objPath = entry->path();
int index = m_items.indexOf(entry);
Q_EMIT m_taskmanager->entryAdded(entry, index);
qDebug() << entry->getName();
}
}
}
}
void Entries::updateShowRecent()
{
// 高效模式无需做任何操作
if (static_cast<DisplayMode>(m_taskmanager->getDisplayMode()) != DisplayMode::Fashion)
return;
bool showRecent = DockSettings::instance()->showRecent();
if (showRecent) {
// 如果显示最近打开应用,则发送新增信号
for (Entry *entry : m_items) {
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
entry->updateMode();
if (entry->getIsDocked() || entry->hasWindow())
continue;
// QString objPath = entry->path();
int index = m_items.indexOf(entry);
Q_EMIT m_taskmanager->entryAdded(entry, index);
}
} else {
// 如果是隐藏最近打开的应用,则发送移除的信号
for (Entry *entry : m_items) {
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
entry->updateMode();
if (entry->getIsDocked() || entry->hasWindow())
continue;
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
}
}
}

View File

@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef ENTRIES_H
#define ENTRIES_H
#include "entry.h"
#include "constants.h"
#include "taskmanager/windowinfobase.h"
#include <QVector>
#include <QWeakPointer>
#include <qlist.h>
#define MAX_UNOPEN_RECENT_COUNT 3
class TaskManager;
// 所有应用管理类
class Entries
{
public:
Entries(TaskManager *_taskmanager);
const QList<Entry *> unDockedEntries() const;
bool shouldInRecent();
void removeLastRecent();
void updateShowRecent();
void updateEntriesMenu();
void append(Entry *entry);
void remove(Entry *entry);
void moveEntryToLast(Entry *entry);
void insert(Entry *entry, int index);
void move(int oldIndex, int newIndex);
void setDisplayMode(Dock::DisplayMode displayMode);
void handleActiveWindowChanged(XWindow activeWindId);
QString queryWindowIdentifyMethod(XWindow windowId);
QStringList getEntryIDs();
Entry *getByWindowPid(int pid);
Entry *getByInnerId(QString innerId);
Entry *getByWindowId(XWindow windowId);
Entry *getByDesktopFilePath(const QString &filePath);
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
QList<Entry*> getEntries();
QVector<Entry *> filterDockedEntries();
private:
void insertCb(Entry *entry, int index);
void removeCb(Entry *entry);
private:
QList<Entry *> m_items;
TaskManager *m_taskmanager;
};
#endif // ENTRIES_H

883
frame/taskmanager/entry.cpp Normal file
View File

@ -0,0 +1,883 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "entry.h"
#include "docksettings.h"
#include "xcbutils.h"
#include "taskmanager.h"
#include "processinfo.h"
#include "windowinfomap.h"
#include <QDebug>
#include <QDBusInterface>
#include <algorithm>
#include <signal.h>
#define XCB XCBUtils::instance()
Entry::Entry(TaskManager *_taskmanager, AppInfo *_app, QString _innerId, QObject *parent)
: QObject(parent)
, m_isActive(false)
, m_isDocked(false)
, m_winIconPreferred(false)
, m_innerId(_innerId)
, m_adapterEntry(nullptr)
, m_taskmanager(_taskmanager)
, m_current(nullptr)
, m_currentWindow(0)
{
setAppInfo(_app);
m_id = m_taskmanager->allocEntryId();
m_mode = getCurrentMode();
m_name = getName();
m_icon = getIcon();
}
Entry::~Entry()
{
for (auto winInfo : m_windowInfoMap) {
if (winInfo) winInfo->deleteLater();
}
m_windowInfoMap.clear();
}
bool Entry::isValid()
{
// desktopfile 无效时且没有窗口时该entry是无效的
// 虽然也就是desktop是无效时但是当前存在窗口该entry也是有效的。
return m_isValid || m_current;
}
QString Entry::getId() const
{
return m_id;
}
QString Entry::getName()
{
QString ret = m_current ? m_current->getDisplayName() : QString();
if (m_appInfo.isNull()) return ret;
ret = m_appInfo->getName();
return ret;
}
void Entry::updateName()
{
setPropName(getName());
}
QString Entry::getIcon()
{
QString ret;
if (hasWindow()) {
if (!m_current) {
return ret;
}
// has window && current not nullptr
if (m_winIconPreferred) {
// try current window icon first
ret = m_current->getIcon();
if (ret.size() > 0) {
return ret;
}
}
if (m_appInfo) {
m_icon = m_appInfo->getIcon();
if (m_icon.size() > 0) {
return m_icon;
}
}
return m_current->getIcon();
}
if (m_appInfo) {
// no window
return m_appInfo->getIcon();
}
return ret;
}
QString Entry::getInnerId()
{
return m_innerId;
}
void Entry::setInnerId(QString _innerId)
{
qDebug() << "setting innerID from: " << m_innerId << " to: " << _innerId;
m_innerId = _innerId;
}
QString Entry::getFileName()
{
return m_appInfo.isNull() ? QString() : m_appInfo->getFileName();
}
AppInfo *Entry::getAppInfo()
{
return m_appInfo.data();
}
void Entry::setAppInfo(AppInfo *appinfo)
{
if (m_appInfo.data() == appinfo) {
return;
}
m_appInfo.reset(appinfo);
m_isValid = appinfo->isValidApp();
m_winIconPreferred = !appinfo;
setPropDesktopFile(appinfo ? appinfo->getFileName(): "");
if (!m_winIconPreferred) {
QString id = m_appInfo->getId();
auto perferredApps = m_taskmanager->getWinIconPreferredApps();
if (perferredApps.contains(id)|| appinfo->getIcon().size() == 0) {
m_winIconPreferred = true;
return;
}
}
}
bool Entry::getIsDocked() const
{
return m_isDocked;
}
void Entry::setIsDocked(bool value)
{
if (value != m_isDocked) {
m_isDocked = value;
Q_EMIT isDockedChanged(value);
}
}
void Entry::setMenu(AppMenu *_menu)
{
_menu->setDirtyStatus(true);
m_appMenu.reset(_menu);
Q_EMIT menuChanged(m_appMenu->getMenuJsonStr());
}
void Entry::updateMenu()
{
qInfo() <<"Entry: updateMenu";
AppMenu *appMenu = new AppMenu();
appMenu->appendItem(getMenuItemLaunch());
for (auto &item :getMenuItemDesktopActions())
appMenu->appendItem(item);
if (hasWindow())
appMenu->appendItem(getMenuItemAllWindows());
// menu item dock or undock
qInfo() << "entry " << m_id << " docked? " << m_isDocked;
appMenu->appendItem(m_isDocked? getMenuItemUndock(): getMenuItemDock());
if (hasWindow()) {
if (m_taskmanager->getForceQuitAppStatus() != ForceQuitAppMode::Disabled) {
appMenu->appendItem(m_appInfo && m_appInfo->getIdentifyMethod() == "Andriod" ?
getMenuItemForceQuitAndroid() : getMenuItemForceQuit());
}
if (getAllowedCloseWindows().size() > 0)
appMenu->appendItem(getMenuItemCloseAll());
}
setMenu(appMenu);
}
void Entry::updateIcon()
{
setPropIcon(getIcon());
}
int Entry::getCurrentMode()
{
// 只要当前应用是已经驻留的应用则让其显示为Normal
if (getIsDocked())
return ENTRY_NORMAL;
// 对于未驻留的应用则做如下处理
if (m_taskmanager->getDisplayMode() == DisplayMode::Efficient) {
// 高效模式下只有存在子窗口的则让其为nornal没有子窗口的一般不让其显示
return hasWindow() ? ENTRY_NORMAL : ENTRY_NONE;
}
// 时尚模式下对未驻留应用做如下处理
// 如果开启了最近打开应用的功能则显示到最近打开区域ENTRY_RECENT
if (DockSettings::instance()->showRecent())
return ENTRY_RECENT;
// 未开启最近使用应用的功能,如果有子窗口,则显示成通用的(ENTRY_NORMAL),如果没有子窗口,则不显示(ENTRY_NONE)
return hasWindow() ? ENTRY_NORMAL : ENTRY_NONE;
}
void Entry::updateMode()
{
int currentMode = getCurrentMode();
if (m_mode != currentMode) {
m_mode = currentMode;
Q_EMIT modeChanged(m_mode);
}
}
void Entry::forceUpdateIcon()
{
m_icon = getIcon();
Q_EMIT iconChanged(m_icon);
}
void Entry::updateIsActive()
{
bool isActive = false;
auto activeWin = m_taskmanager->getActiveWindow();
if (activeWin) {
// 判断活跃窗口是否属于当前应用
isActive = m_windowInfoMap.find(activeWin->getXid()) != m_windowInfoMap.end();
}
setPropIsActive(isActive);
}
WindowInfoBase *Entry::getWindowInfoByPid(int pid)
{
for (const auto &windowInfo : m_windowInfoMap) {
if (windowInfo->getPid() == pid)
return windowInfo;
}
return nullptr;
}
WindowInfoBase *Entry::getWindowInfoByWinId(XWindow windowId)
{
if (m_windowInfoMap.find(windowId) != m_windowInfoMap.end())
return m_windowInfoMap[windowId];
return nullptr;
}
void Entry::setPropIcon(QString value)
{
if (value != m_icon) {
m_icon = value;
Q_EMIT iconChanged(value);
}
}
void Entry::setPropName(QString value)
{
if (value != m_name) {
m_name = value;
Q_EMIT nameChanged(value);
}
}
void Entry::setPropIsActive(bool active)
{
if (m_isActive != active) {
m_isActive = active;
Q_EMIT isActiveChanged(active);
}
}
void Entry::setCurrentWindowInfo(WindowInfoBase *windowInfo)
{
m_current = windowInfo;
setPropCurrentWindow(m_current ? m_current->getXid() : 0);
}
void Entry::setPropCurrentWindow(XWindow value)
{
if (value != m_currentWindow) {
m_currentWindow = value;
Q_EMIT currentWindowChanged(value);
}
}
WindowInfoBase *Entry::getCurrentWindowInfo()
{
return m_current;
}
/**
* @brief Entry::findNextLeader
* @return
*/
WindowInfoBase *Entry::findNextLeader()
{
auto xids = m_windowInfoMap.keys();
std::sort(xids.begin(), xids.end());
XWindow curWinId = m_current->getXid();
int index = xids.indexOf(curWinId);
if (index < 0)
return nullptr;
// 如果当前窗口是最大, 返回xids[0], 否则返回xids[index + 1]
int nextIndex = 0;
if (index < xids.size() - 1)
nextIndex = index + 1;
return m_windowInfoMap[xids[nextIndex]];
}
QString Entry::getExec()
{
if (!m_current)
return "";
ProcessInfo *process = m_current->getProcess();
return process->getExe();
}
QString Entry::getCmdLine()
{
QString ret;
if (!m_current) return ret;
ProcessInfo *process = m_current->getProcess();
for (auto i : process->getCmdLine()) ret += i + " ";
return ret;
}
bool Entry::hasWindow()
{
return m_windowInfoMap.size() > 0;
}
/**
* @brief Entry::updateExportWindowInfos
*/
void Entry::updateExportWindowInfos()
{
WindowInfoMap infos;
for (auto info : m_windowInfoMap) {
WindowInfo winInfo;
XWindow xid = info->getXid();
winInfo.title = info->getTitle();
winInfo.attention = info->isDemandingAttention();
winInfo.uuid = info->uuid();
infos[xid] = winInfo;
}
bool changed = true;
if (infos.size() == m_exportWindowInfos.size()) {
changed = false;
for (auto iter = infos.begin(); iter != infos.end(); iter++) {
XWindow xid = iter.key();
if (infos[xid].title != m_exportWindowInfos[xid].title ||
infos[xid].attention != m_exportWindowInfos[xid].attention ||
infos[xid].uuid != m_exportWindowInfos[xid].uuid) {
changed = true;
break;
}
}
}
if (changed) {
Q_EMIT windowInfosChanged(infos);
}
// 更新导出的窗口信息
m_exportWindowInfos = infos;
}
// 分离窗口, 返回是否需要从任务栏remove
bool Entry::detachWindow(WindowInfoBase *info)
{
info->setEntry(nullptr);
XWindow winId = info->getXid();
if (m_windowInfoMap.contains(winId)) {
m_windowInfoMap.remove(winId);
info->deleteLater();
}
if (m_windowInfoMap.isEmpty()) {
if (!m_isDocked) {
// 既无窗口也非驻留应用,并且不是最近打开,无需在任务栏显示
return true;
}
Q_EMIT windowInfosChanged(WindowInfoMap());
setCurrentWindowInfo(nullptr);
} else {
for (auto window : m_windowInfoMap) {
if (window) { // 选择第一个窗口作为当前窗口
setCurrentWindowInfo(window);
break;
}
}
}
updateExportWindowInfos();
updateIcon();
updateMenu();
return false;
}
bool Entry::isShowOnDock() const
{
// 当前应用显示图标的条件是
// 如果该图标已经固定在任务栏上,则始终显示
if (getIsDocked())
return true;
// 1.时尚模式下,如果开启了显示最近使用,则不管是否有子窗口,都在任务栏上显示
// 如果没有开启显示最近使用,则只显示有子窗口的
if (m_taskmanager->getDisplayMode() == DisplayMode::Fashion)
return (DockSettings::instance()->showRecent() || m_exportWindowInfos.size() > 0);
// 2.高效模式下,只有该应用有打开窗口才显示
return m_exportWindowInfos.size() > 0;
}
bool Entry::attachWindow(WindowInfoBase *info)
{
XWindow winId = info->getXid();
qInfo() << "attatchWindow: window id:" << winId;
info->setEntry(this);
if (m_windowInfoMap.find(winId) != m_windowInfoMap.end()) {
qInfo() << "attachWindow: window " << winId << " is already attached";
return false;
}
bool lastShowOnDock = isShowOnDock();
m_windowInfoMap[winId] = info;
updateExportWindowInfos();
updateIsActive();
if (!m_current) {
// from no window to has window
setCurrentWindowInfo(info);
}
updateIcon();
updateMenu();
if (!lastShowOnDock && isShowOnDock()) {
// 新打开的窗口始终显示到最后
Q_EMIT m_taskmanager->entryAdded(this, -1);
}
return true;
}
void Entry::launchApp(uint32_t timestamp)
{
if (m_appInfo)
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, QStringList());
}
bool Entry::containsWindow(XWindow xid)
{
return m_windowInfoMap.find(xid) != m_windowInfoMap.end();
}
// 处理菜单项
void Entry::handleMenuItem(uint32_t timestamp, QString itemId)
{
m_appMenu->handleAction(timestamp, itemId);
}
// 处理拖拽事件
void Entry::handleDragDrop(uint32_t timestamp, QStringList files)
{
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, files);
}
// 驻留
void Entry::requestDock(bool dockToEnd)
{
if (m_taskmanager->dockEntry(this, dockToEnd)) {
m_taskmanager->saveDockedApps();
}
}
// 取消驻留
void Entry::requestUndock(bool dockToEnd)
{
m_taskmanager->undockEntry(this, dockToEnd);
}
void Entry::newInstance(uint32_t timestamp)
{
QStringList files;
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, files);
}
// 检查应用窗口分离、合并状态
void Entry::check()
{
QList<WindowInfoBase *> windows = m_windowInfoMap.values();
for (WindowInfoBase *window : windows) {
m_taskmanager->attachOrDetachWindow(window);
}
}
// 强制退出
void Entry::forceQuit()
{
QMap<int, QVector<WindowInfoBase*>> pidWinInfoMap;
QList<WindowInfoBase *> windows = m_windowInfoMap.values();
for (WindowInfoBase *window : windows) {
int pid = window->getPid();
if (pid != 0) {
pidWinInfoMap[pid].push_back(window);
} else {
window->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();
}
}
}
// 所有的窗口已经退出后清空m_windowInfoMap内容
m_windowInfoMap.clear();
// 退出所有的进程后,及时更新当前剩余的窗口数量
updateExportWindowInfos();
m_taskmanager->removeEntryFromDock(this);
}
void Entry::presentWindows()
{
QList<uint> windows = m_windowInfoMap.keys();
m_taskmanager->presentWindows(windows);
}
/**
* @brief Entry::active
* @param timestamp
*/
void Entry::active(uint32_t timestamp)
{
if (m_taskmanager->getHideMode() == HideMode::SmartHide) {
m_taskmanager->setPropHideState(HideState::Show);
m_taskmanager->updateHideState(false);
}
// 无窗口则直接启动
if (!hasWindow()) {
launchApp(timestamp);
return;
}
if (!m_current) {
qWarning() << "active: current window is nullptr";
return;
}
WindowInfoBase *winInfo = m_current;
if (m_taskmanager->isWaylandEnv()) {
// wayland环境
if (!m_taskmanager->isActiveWindow(winInfo)) {
winInfo->activate();
} else {
bool showing = m_taskmanager->isShowingDesktop();
if (showing || winInfo->isMinimized()) {
winInfo->activate();
} else if (m_windowInfoMap.size() == 1) {
winInfo->minimize();
} else {
WindowInfoBase *nextWin = findNextLeader();
if (nextWin) {
nextWin->activate();
}
}
}
} else {
// X11环境
XWindow xid = winInfo->getXid();
WindowInfoBase *activeWin = m_taskmanager->getActiveWindow();
if (activeWin && xid != activeWin->getXid()) {
m_taskmanager->doActiveWindow(xid);
} else {
bool found = false;
XWindow hiddenAtom = XCB->getAtom("_NET_WM_STATE_HIDDEN");
for (auto state : XCB->getWMState(xid)) {
if (hiddenAtom == state) {
found = true;
break;
}
}
if (found) {
// 激活隐藏窗口
m_taskmanager->doActiveWindow(xid);
} else if (m_windowInfoMap.size() == 1) {
// 窗口图标化
XCB->minimizeWindow(xid);
} else if (m_taskmanager->getActiveWindow() && m_taskmanager->getActiveWindow()->getXid() == xid) {
WindowInfoBase *nextWin = findNextLeader();
if (nextWin) {
nextWin->activate();
}
}
}
}
}
void Entry::activeWindow(quint32 winId)
{
if (m_taskmanager->isWaylandEnv()) {
if (!m_windowInfoMap.contains(winId))
return;
WindowInfoBase *winInfo = m_windowInfoMap[winId];
if (m_taskmanager->isActiveWindow(winInfo)) {
bool showing = m_taskmanager->isShowingDesktop();
if (showing || winInfo->isMinimized()) {
winInfo->activate();
} else if (m_windowInfoMap.size() == 1) {
winInfo->minimize();
} else {
WindowInfoBase *nextWin = findNextLeader();
if (nextWin) {
nextWin->activate();
}
}
} else {
winInfo->activate();
}
} else {
m_taskmanager->doActiveWindow(winId);
}
}
int Entry::mode()
{
return m_mode;
}
XWindow Entry::getCurrentWindow()
{
return m_currentWindow;
}
QString Entry::getDesktopFile()
{
return m_desktopFile;
}
bool Entry::getIsActive() const
{
return m_isActive;
}
QString Entry::getMenu() const
{
return m_appMenu->getMenuJsonStr();
}
QVector<XWindow> Entry::getAllowedClosedWindowIds()
{
QVector<XWindow> ret;
for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) {
WindowInfoBase *info = iter.value();
if (info && info->allowClose())
ret.push_back(iter.key());
}
return ret;
}
WindowInfoMap Entry::getExportWindowInfos()
{
return m_exportWindowInfos;
}
QVector<WindowInfoBase *> Entry::getAllowedCloseWindows()
{
QVector<WindowInfoBase *> ret;
for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) {
WindowInfoBase *info = iter.value();
if (info && info->allowClose()) {
ret.push_back(info);
}
}
return ret;
}
QVector<AppMenuItem> Entry::getMenuItemDesktopActions()
{
QVector<AppMenuItem> ret;
if (!m_appInfo) {
return ret;
}
for (auto action : m_appInfo->getActions()) {
AppMenuAction fn = [=](uint32_t timestamp) {
qInfo() << "do MenuItem: " << action.name;
m_taskmanager->launchAppAction(m_appInfo->getFileName(), action.section, timestamp);
};
AppMenuItem item;
item.text = action.name;
item.action = fn;
item.isActive = true;
ret.push_back(item);
}
return ret;
}
AppMenuItem Entry::getMenuItemLaunch()
{
QString itemName;
if (hasWindow()) {
itemName = getName();
} else {
itemName = tr("Open");
}
AppMenuAction fn = [this](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 = [this](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);
}
// 关闭窗口后,主动刷新事件
XCB->flush();
};
AppMenuItem item;
item.text = tr("Close All");
item.action = fn;
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemForceQuit()
{
bool active = m_taskmanager->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
AppMenuAction fn = [this](uint32_t) {
qInfo() << "do MenuItem: Force Quit";
forceQuit();
};
AppMenuItem item;
item.text = tr("Force Quit");
item.action = fn;
item.isActive = active;
return item;
}
//dock栏上Android程序的Force Quit功能
AppMenuItem Entry::getMenuItemForceQuitAndroid()
{
bool active = m_taskmanager->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 = tr("Force Quit");
item.action = fn;
item.isActive = active;
return item;
}
AppMenuItem Entry::getMenuItemDock()
{
AppMenuItem item;
item.text = tr("Dock");
item.action = [this](uint32_t) {
qInfo() << "do MenuItem: Dock";
requestDock(true);
};
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemUndock()
{
AppMenuItem item;
item.text = tr("Undock");
item.action = [this](uint32_t) {
qInfo() << "do MenuItem: Undock";
requestUndock(true);
};
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemAllWindows()
{
AppMenuItem item;
item.text = tr("All Windows");
item.action = [this](uint32_t) {
qInfo() << "do MenuItem: All Windows";
presentWindows();
};
item.isActive = true;
item.hint = 1;
return item;
}
bool Entry::killProcess(int pid)
{
return !kill(pid, SIGTERM);
}
bool Entry::setPropDesktopFile(QString value)
{
if (value != m_desktopFile) {
m_desktopFile = value;
Q_EMIT desktopFileChanged(value);
return true;
}
return false;
}

156
frame/taskmanager/entry.h Normal file
View File

@ -0,0 +1,156 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef ENTRY_H
#define ENTRY_H
#include "appinfo.h"
#include "appmenu.h"
#include "windowinfomap.h"
#include "windowinfobase.h"
#include <QMap>
#include <QVector>
#include <QObject>
#include <qscopedpointer.h>
#define ENTRY_NONE 0
#define ENTRY_NORMAL 1
#define ENTRY_RECENT 2
// 单个应用类
class TaskManager;
class DBusAdaptorEntry;
class WindowInfo;
typedef QMap<quint32, WindowInfo> WindowInfoMap;
class Entry: public QObject
{
Q_OBJECT
public:
Entry(TaskManager *_taskmanager, AppInfo *_app, QString _innerId, QObject *parent = nullptr);
~Entry();
void updateName();
void updateMenu();
void updateIcon();
void updateMode();
void updateIsActive();
void forceUpdateIcon();
void updateExportWindowInfos();
void launchApp(uint32_t timestamp);
void setIsDocked(bool value);
void setMenu(AppMenu *_menu);
void setPropIcon(QString value);
void setPropName(QString value);
void setPropIsActive(bool active);
void setInnerId(QString _innerId);
void setAppInfo(AppInfo *appinfo);
void setPropCurrentWindow(XWindow value);
void setCurrentWindowInfo(WindowInfoBase *windowInfo);
void check();
void forceQuit();
void presentWindows();
void active(uint32_t timestamp);
void activeWindow(quint32 winId);
void newInstance(uint32_t timestamp);
void requestDock(bool dockToEnd = false);
void requestUndock(bool dockToEnd = false);
void handleMenuItem(uint32_t timestamp, QString itemId);
void handleDragDrop(uint32_t timestamp, QStringList files);
bool containsWindow(XWindow xid);
bool detachWindow(WindowInfoBase *info);
bool attachWindow(WindowInfoBase *info);
bool getIsDocked() const;
bool getIsActive() const;
QString getId() const;
QString getMenu() const;
bool isValid();
bool hasWindow();
int mode();
QString getName();
QString getIcon();
QString getInnerId();
QString getFileName();
QString getDesktopFile();
QString getExec();
QString getCmdLine();
XWindow getCurrentWindow();
AppInfo *getAppInfo();
WindowInfoBase *findNextLeader();
WindowInfoBase *getCurrentWindowInfo();
WindowInfoBase *getWindowInfoByPid(int pid);
WindowInfoBase *getWindowInfoByWinId(XWindow windowId);
WindowInfoMap getExportWindowInfos();
QVector<XWindow> getAllowedClosedWindowIds();
public Q_SLOTS:
QVector<WindowInfoBase *> getAllowedCloseWindows();
Q_SIGNALS:
void modeChanged(int);
void isActiveChanged(bool);
void isDockedChanged(bool);
void menuChanged(QString);
void iconChanged(QString);
void nameChanged(QString);
void desktopFileChanged(QString);
void currentWindowChanged(uint32_t);
void windowInfosChanged(const WindowInfoMap&);
private:
// 右键菜单项
bool killProcess(int pid);
bool setPropDesktopFile(QString value);
bool isShowOnDock() const;
int getCurrentMode();
AppMenuItem getMenuItemLaunch();
AppMenuItem getMenuItemCloseAll();
AppMenuItem getMenuItemForceQuit();
AppMenuItem getMenuItemDock();
AppMenuItem getMenuItemUndock();
AppMenuItem getMenuItemAllWindows();
AppMenuItem getMenuItemForceQuitAndroid();
QVector<AppMenuItem> getMenuItemDesktopActions();
private:
bool m_isActive;
bool m_isValid;
bool m_isDocked;
bool m_winIconPreferred;
int m_mode;
QString m_id;
QString m_name;
QString m_icon;
QString m_innerId;
QString m_desktopFile;
DBusAdaptorEntry *m_adapterEntry;
TaskManager *m_taskmanager;
WindowInfoMap m_exportWindowInfos; // 该应用导出的窗口属性
WindowInfoBase *m_current; // 当前窗口
XWindow m_currentWindow; //当前窗口Id
QScopedPointer<AppInfo> m_appInfo;
QScopedPointer<AppMenu> m_appMenu;
QMap<XWindow, WindowInfoBase *> m_windowInfoMap; // 该应用所有窗口
};
#endif // ENTRY_H

View File

@ -0,0 +1,214 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "processinfo.h"
#include <string>
#include <fstream>
#include <unistd.h>
#include <QDir>
#include <QDebug>
#include <QFileInfo>
ProcessInfo::ProcessInfo(int pid)
: m_pid(pid)
, m_ppid(0)
{
if (pid == 0)
return;
m_exe = getExe();
m_cwd = getCwd();
m_cmdLine = getCmdLine();
getStatus();
// 部分root进程在/proc文件系统查找不到exe、cwd、cmdline信息
if (m_exe.isEmpty() || m_cwd.isEmpty() || m_cmdLine.size() == 0) {
m_isValid = false;
return;
}
// args
qInfo() << "ProcessInfo: exe=" << m_exe << " cwd=" << m_cwd << " cmdLine=" << (m_cmdLine[0].isEmpty() ? " " : m_cmdLine[0]);
auto verifyExe = [](QString exe, QString cwd, QString firstArg){
if (firstArg.size() == 0) return false;
QFileInfo info(firstArg);
if (info.completeBaseName() == firstArg) return true;
if (!QDir::isAbsolutePath(firstArg))
firstArg = cwd + firstArg;
return exe == firstArg;
};
if (!m_cmdLine[0].isEmpty()) {
if (!verifyExe(m_exe, m_cwd, m_cmdLine[0])) {
auto parts = m_cmdLine[0].split(' ');
// try again
if (verifyExe(m_exe, m_cwd, parts[0])) {
m_args.append(parts.mid(1, parts.size() - 1));
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
}
} else {
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
}
}
}
ProcessInfo::ProcessInfo(QStringList cmd)
: m_hasPid(false)
, m_isValid(true)
{
if (cmd.size() == 0) {
m_isValid = false;
return;
}
m_cmdLine = cmd;
m_exe = cmd[0];
m_args.append(cmd.mid(1, cmd.size() - 1));
}
ProcessInfo::~ProcessInfo()
{
}
QString ProcessInfo::getEnv(const QString &key)
{
if (m_environ.size() == 0) getEnviron();
return m_environ[key];
}
Status ProcessInfo::getStatus()
{
if (!m_status.empty()){
return m_status;
}
QString statusFile = getFile("status");
std::ifstream fs(statusFile.toStdString());
if (!fs.is_open()) {
return m_status;
}
std::string tmp = "";
while (std::getline(fs, tmp)) {
auto pos = tmp.find_first_of(':');
if (pos == std::string::npos) {
continue;
}
QString value;
if (pos + 1 < tmp.length()) {
value = QString::fromStdString(tmp.substr(pos + 1));
}
m_status[QString::fromStdString(tmp.substr(0, pos))] = value;
}
return m_status;
}
QStringList ProcessInfo::getCmdLine()
{
if (m_cmdLine.size() == 0) {
QString cmdlineFile = getFile("cmdline");
m_cmdLine = readFile(cmdlineFile);
}
return m_cmdLine;
}
QStringList ProcessInfo::getArgs()
{
return m_args;
}
int ProcessInfo::getPid()
{
return m_pid;
}
int ProcessInfo::getPpid()
{
if (m_ppid == 0) {
if (m_status.find("PPid") != m_status.end()) {
m_ppid = std::stoi(m_status["PPid"].toStdString());
}
}
return m_ppid;
}
bool ProcessInfo::initWithPid()
{
return m_hasPid;
}
bool ProcessInfo::isValid()
{
return m_isValid;
}
QString ProcessInfo::getExe()
{
if (m_exe.isEmpty()) {
QString cmdLineFile = getFile("exe");
QFileInfo path(cmdLineFile);
m_exe = path.canonicalFilePath();
}
return m_exe;
}
bool ProcessInfo::isExist()
{
QString procDir = "/proc/" + QString(m_pid);
return QFile::exists(procDir);
}
QStringList ProcessInfo::readFile(const QString &filePath)
{
QStringList ret;
std::ifstream fs(filePath.toStdString());
if (!fs.is_open()) {
return ret;
}
std::string tmp;
while (std::getline(fs, tmp, '\0')) {
ret.append(QString::fromStdString(tmp));
}
return ret;
}
QString ProcessInfo::getFile(const QString &file)
{
return QString("/proc/").append(QString::number(m_pid).append('/').append(file));
}
QString ProcessInfo::getCwd()
{
if (m_cwd.isEmpty()) {
QString cwdFile = getFile("cwd");
QFileInfo path(cwdFile);
m_cwd = path.canonicalFilePath();
}
return m_cwd;
}
QMap<QString, QString> ProcessInfo::getEnviron()
{
if (m_environ.size() == 0) {
QString envFile = getFile("environ");
QStringList contents = readFile(envFile);
for (auto line : contents){
int index = line.indexOf('=');
m_environ.insert(line.left(index), line.right(line.size() - index - 1));
}
}
return m_environ;
}

View File

@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef PROCESSINFO_H
#define PROCESSINFO_H
#include <QMap>
#include <QVector>
#include <QStringList>
typedef QMap<QString, QString> Status;
// 进程信息
class ProcessInfo
{
public:
explicit ProcessInfo(int pid);
explicit ProcessInfo(QStringList cmd);
virtual ~ProcessInfo();
bool isValid();
bool initWithPid();
int getPid();
int getPpid();
QString getExe();
QString getCwd();
Status getStatus();
QString getEnv(const QString &key);
QStringList getArgs();
QStringList getCmdLine();
QMap<QString, QString> getEnviron();
private:
bool isExist();
QString getJoinedExeArgs();
QString getFile(const QString &file);
QStringList readFile(const QString &filePath);
private:
int m_pid;
int m_ppid;
bool m_hasPid;
bool m_isValid;
Status m_status;
QString m_exe;
QString m_cwd;
QStringList m_args;
QStringList m_cmdLine;
QVector<int> m_uids;
QMap<QString, QString> m_environ;
};
#endif // PROCESSINFO_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,191 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef DOCK_H
#define DOCK_H
#include "docksettings.h"
#include "entries.h"
#include "org_deepin_dde_kwayland_plasmawindow.h"
#include <QStringList>
#include <QTimer>
#include <QMutex>
#include <QObject>
class WindowIdentify;
class DBusHandler;
class WaylandManager;
class X11Manager;
class WindowInfoK;
class WindowInfoX;
using PlasmaWindow = org::deepin::dde::kwayland1::PlasmaWindow;
// 任务管理
class TaskManager : public QObject
{
Q_OBJECT
public:
static inline TaskManager *instance() {
static TaskManager instance;
return &instance;
}
// 将Entry dock在任务栏上
bool dockEntry(Entry *entry, bool moveToEnd = false);
void undockEntry(Entry *entry, bool moveToEnd = false);
QString allocEntryId();
bool shouldShowOnDock(WindowInfoBase *info);
void setDdeLauncherVisible(bool visible);
QString getWMName();
void setWMName(QString name);
void setPropHideState(HideState state);
void attachWindow(WindowInfoBase *info);
void detachWindow(WindowInfoBase *info);
void launchApp(const QString desktopFile, uint32_t timestamp, QStringList files);
void launchAppAction(const QString desktopFile, QString action, uint32_t timestamp);
bool is3DWM();
bool isWaylandEnv();
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
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);
bool isShowingDesktop();
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
void markAppLaunched(AppInfo *appInfo);
ForceQuitAppMode getForceQuitAppStatus();
QVector<QString> getWinIconPreferredApps();
void handleLauncherItemDeleted(QString itemPath);
void handleLauncherItemUpdated(QString itemPath);
QRect getFrontendWindowRect();
DisplayMode getDisplayMode();
void setDisplayMode(int mode);
QStringList getDockedApps();
QList<Entry*> getEntries();
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);
/******************************** dbus handler ****************************/
PlasmaWindow *createPlasmaWindow(QString objPath);
void listenKWindowSignals(WindowInfoK *windowInfo);
void removePlasmaWindowHandler(PlasmaWindow *window);
void presentWindows(QList<uint> windows);
HideMode getDockHideMode();
bool isActiveWindow(const WindowInfoBase *win);
WindowInfoBase *getActiveWindow();
void doActiveWindow(XWindow xid);
QList<XWindow> getClientList();
void setClientList(QList<XWindow> value);
void closeWindow(XWindow windowId);
void MinimizeWindow(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 setShowMultiWindow(bool visible);
bool showMultiWindow() const;
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 removeEntryFromDock(Entry *entry);
void previewWindow(uint xid);
void cancelPreviewWindow();
Q_SIGNALS:
void serviceRestarted();
void entryAdded(const Entry* entry, int index);
void entryRemoved(QString id);
void hideStateChanged(int);
void frontendWindowRectChanged(const QRect &dockRect);
void showRecentChanged(bool);
void showMultiWindowChanged(bool);
public Q_SLOTS:
void updateHideState(bool delay);
void handleActiveWindowChanged(WindowInfoBase *info);
void smartHideModeTimerExpired();
void attachOrDetachWindow(WindowInfoBase *info);
private:
explicit TaskManager(QObject *parent = nullptr);
~TaskManager();
void initSettings();
void initEntries();
void loadAppInfos();
void initClientList();
WindowInfoX *findWindowByXidX(XWindow xid);
WindowInfoK *findWindowByXidK(XWindow xid);
bool isWindowDockOverlapX(XWindow xid);
bool hasInterSectionX(const Geometry &windowRect, QRect dockRect);
bool isWindowDockOverlapK(WindowInfoBase *info);
bool hasInterSectionK(const DockRect &windowRect, QRect dockRect);
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
bool shouldHideOnSmartHideMode();
QVector<XWindow> getActiveWinGroup(XWindow xid);
void updateRecentApps();
private:
void onShowRecentChanged(bool visible);
void onShowMultiWindowChanged(bool visible);
private:
bool m_isWayland; // 判断是否为wayland环境
bool m_showRecent;
bool m_showMultiWindow;
int m_entriesSum; // 累计打开的应用数量
QString m_wmName; // 窗管名称
HideState m_hideState; // 记录任务栏隐藏状态
QRect m_frontendWindowRect; // 前端任务栏大小, 用于智能隐藏时判断窗口是否重合
ForceQuitAppMode m_forceQuitAppStatus; // 强制退出应用状态
Entries *m_entries; // 所有应用实例
X11Manager *m_x11Manager; // X11窗口管理
WaylandManager *m_waylandManager; // wayland窗口管理
WindowIdentify *m_windowIdentify; // 窗口识别
QTimer *m_smartHideTimer; // 任务栏智能隐藏定时器
DBusHandler *m_dbusHandler; // 处理dbus交互
WindowInfoBase *m_activeWindow;// 记录当前活跃窗口信息
WindowInfoBase *m_activeWindowOld;// 记录前一个活跃窗口信息
QList<XWindow> m_clientList; // 所有窗口
};
#endif // TASKMANAGER_H

View File

@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "waylandmanager.h"
#include "taskmanager.h"
#include "taskmanager/entry.h"
#include "xcbutils.h"
#define XCB XCBUtils::instance()
WaylandManager::WaylandManager(TaskManager *_taskmanager, QObject *parent)
: QObject(parent)
, m_taskmanager(_taskmanager)
, m_mutex(QMutex(QMutex::NonRecursive))
{
}
/**
* @brief WaylandManager::registerWindow
* @param objPath
*/
void WaylandManager::registerWindow(const QString &objPath)
{
qInfo() << "registerWindow: " << objPath;
if (findWindowByObjPath(objPath))
return;
PlasmaWindow *plasmaWindow = m_taskmanager->createPlasmaWindow(objPath);
if (!plasmaWindow) {
qWarning() << "registerWindowWayland: createPlasmaWindow failed";
return;
}
if (!plasmaWindow->IsValid() || !plasmaWindow->isValid()) {
qWarning() << "PlasmaWindow is not valid:" << objPath;
plasmaWindow->deleteLater();
return;
}
QString appId = plasmaWindow->AppId();
QStringList list {"dde-dock", "dde-launcher", "dde-clipboard", "dde-osd", "dde-polkit-agent", "dde-simple-egl", "dmcs", "dde-lock"};
if (list.indexOf(appId) >= 0 || appId.startsWith("No such object path")) {
plasmaWindow->deleteLater();
return;
}
XWindow winId = XCB->allocId(); // XCB中未发现释放XID接口
XWindow realId = plasmaWindow->WindowId();
if (realId)
winId = realId;
WindowInfoK *winInfo = new WindowInfoK(plasmaWindow, winId);
m_taskmanager->listenKWindowSignals(winInfo);
insertWindow(objPath, winInfo);
m_taskmanager->attachOrDetachWindow(winInfo);
if (winId) {
m_windowInfoMap[winId] = winInfo;
}
}
// 取消注册窗口
void WaylandManager::unRegisterWindow(const QString &objPath)
{
qInfo() << "unRegisterWindow: " << objPath;
WindowInfoK *winInfo = findWindowByObjPath(objPath);
if (!winInfo)
return;
m_taskmanager->removePlasmaWindowHandler(winInfo->getPlasmaWindow());
m_taskmanager->detachWindow(winInfo);
deleteWindow(objPath);
}
WindowInfoK *WaylandManager::findWindowById(uint activeWin)
{
QMutexLocker locker(&m_mutex);
for (auto iter = m_kWinInfos.begin(); iter != m_kWinInfos.end(); iter++) {
if (iter.value()->getInnerId() == QString::number(activeWin)) {
return iter.value();
}
}
return nullptr;
}
WindowInfoK *WaylandManager::findWindowByXid(XWindow xid)
{
WindowInfoK *winInfo = nullptr;
for (auto iter = m_kWinInfos.begin(); iter != m_kWinInfos.end(); iter++) {
if (iter.value()->getXid() == xid) {
winInfo = iter.value();
break;
}
}
return winInfo;
}
WindowInfoK *WaylandManager::findWindowByObjPath(QString objPath)
{
if (m_kWinInfos.find(objPath) == m_kWinInfos.end())
return nullptr;
return m_kWinInfos[objPath];
}
void WaylandManager::insertWindow(QString objPath, WindowInfoK *windowInfo)
{
QMutexLocker locker(&m_mutex);
m_kWinInfos[objPath] = windowInfo;
}
void WaylandManager::deleteWindow(QString objPath)
{
m_kWinInfos.remove(objPath);
}

View File

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WAYLANDMANAGER_H
#define WAYLANDMANAGER_H
#include "taskmanager/entry.h"
#include "windowinfok.h"
#include <QObject>
#include <QMap>
#include <QMutex>
class TaskManager;
// 管理wayland窗口
class WaylandManager : public QObject
{
Q_OBJECT
public:
explicit WaylandManager(TaskManager *_taskmanager, QObject *parent = nullptr);
void registerWindow(const QString &objPath);
void unRegisterWindow(const QString &objPath);
WindowInfoK *findWindowById(uint activeWin);
WindowInfoK *findWindowByXid(XWindow xid);
WindowInfoK *findWindowByObjPath(QString objPath);
void insertWindow(QString objPath, WindowInfoK *windowInfo);
void deleteWindow(QString objPath);
private:
TaskManager *m_taskmanager;
QMap<QString, WindowInfoK *> m_kWinInfos; // dbusObjectPath -> kwayland window Info
QMap<XWindow, WindowInfoK *> m_windowInfoMap;
QMutex m_mutex;
};
#endif // WAYLANDMANAGER_H

View File

@ -0,0 +1,246 @@
[
{
"ret": "id=jftp",
"rules": [
[
"exec",
"=:java"
],
[
"arg",
"c:jftp.jar"
]
]
},
{
"ret": "env",
"rules": [
[
"wmi",
"=:dman"
],
[
"wmc",
"=:DManual"
]
]
},
{
"ret": "env",
"rules": [
[
"wmi",
"r:\\.exe$"
],
[
"wmi",
"=!iesetup.exe"
],
[
"wmc",
"=:Wine"
]
]
},
{
"ret": "id=netbeans",
"rules": [
[
"wmc",
"c:netbeans"
],
[
"exec",
"=:java"
],
[
"arg",
"c:netbeans"
]
]
},
{
"ret": "id=jabref",
"rules": [
[
"wmc",
"c:jabref"
],
[
"exec",
"=:java"
],
[
"arg",
"c:jabref"
]
]
},
{
"ret": "env",
"rules": [
[
"wmi",
"=:player"
],
[
"wmc",
"c:genymotion"
]
]
},
{
"ret": "id=xdemineur",
"rules": [
[
"wmi",
"c:xdemineur"
],
[
"exec",
"=:xdemineur"
]
]
},
{
"ret": "id=minecraft",
"rules": [
[
"wmi",
"c:minecraft"
],
[
"wmc",
"c:minecraft"
]
]
},
{
"ret": "id=steam",
"rules": [
[
"hasPid",
"=:f"
],
[
"wmi",
"=:"
],
[
"wmc",
"=:"
],
[
"wmn",
"e:steam"
]
]
},
{
"ret": "id=mintdrivers",
"rules": [
[
"wmi",
"e:mintdrivers.py"
],
[
"wmc",
"e:mintdrivers.py"
]
]
},
{
"ret": "id=google-earth",
"rules": [
[
"wmi",
"c:googleearth"
],
[
"wmc",
"c:googleearth"
]
]
},
{
"ret": "id=the-powder-toy",
"rules": [
[
"wmi",
"e:powder"
],
[
"wmc",
"e:powder"
],
[
"hasPid",
"=:t"
]
]
},
{
"ret": "id=cn.google.chrome",
"rules": [
[
"wmi",
"e:google-chrome"
],
[
"wmc",
"e:google-chrome"
]
]
},
{
"ret": "id=ganttproject",
"rules": [
[
"wmi",
"R:^sun-awt-X11"
],
[
"exec",
"=:java"
],
[
"env.CLASSPATH",
"c:ganttproject"
],
[
"arg",
"c:ganttproject"
]
]
},
{
"ret": "id=gdevelop",
"rules": [
[
"wmi",
"c:gdevelop"
],
[
"wmc",
"c:gdevelop"
],
[
"exec",
"=:gdevelop"
]
]
},
{
"ret": "id=apps.com.wechat.web",
"rules": [
[
"wmi",
"e:wx2.qq.com"
],
[
"wmc",
"e:google-chrome"
]
]
}
]

View File

@ -0,0 +1,531 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "windowidentify.h"
#include "common.h"
#include "appinfo.h"
#include "taskmanager.h"
#include "processinfo.h"
#include "taskmanager/desktopinfo.h"
#include "xcbutils.h"
#include "bamfdesktop.h"
#include <QDebug>
#include <QThread>
#include <qstandardpaths.h>
#define XCB XCBUtils::instance()
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(TaskManager *_taskmanager, QObject *parent)
: QObject(parent)
, m_taskmanager(_taskmanager)
{
m_identifyWindowFuns << qMakePair(QString("Android") , &identifyWindowAndroid);
m_identifyWindowFuns << qMakePair(QString("PidEnv"), &identifyWindowByPidEnv);
m_identifyWindowFuns << qMakePair(QString("CmdlineTurboBooster"), &identifyWindowByCmdlineTurboBooster);
m_identifyWindowFuns << qMakePair(QString("Cmdline-XWalk"), &identifyWindowByCmdlineXWalk);
m_identifyWindowFuns << qMakePair(QString("FlatpakAppID"), &identifyWindowByFlatpakAppID);
m_identifyWindowFuns << qMakePair(QString("CrxId"), &identifyWindowByCrxId);
m_identifyWindowFuns << qMakePair(QString("Rule"), &identifyWindowByRule);
m_identifyWindowFuns << qMakePair(QString("Bamf"), &identifyWindowByBamf);
m_identifyWindowFuns << qMakePair(QString("Pid"), &identifyWindowByPid);
m_identifyWindowFuns << qMakePair(QString("Scratch"), &identifyWindowByScratch);
m_identifyWindowFuns << qMakePair(QString("GtkAppId"), &identifyWindowByGtkAppId);
m_identifyWindowFuns << qMakePair(QString("WmClass"), &identifyWindowByWmClass);
}
AppInfo *WindowIdentify::identifyWindow(WindowInfoBase *winInfo, QString &innerId)
{
if (!winInfo)
return nullptr;
qInfo() << "identifyWindow: window id " << winInfo->getXid() << " innerId " << winInfo->getInnerId();
if (winInfo->getWindowType() == "X11")
return identifyWindowX11(static_cast<WindowInfoX *>(winInfo), innerId);
if (winInfo->getWindowType() == "Wayland")
return identifyWindowWayland(static_cast<WindowInfoK *>(winInfo), innerId);
return nullptr;
}
AppInfo *WindowIdentify::identifyWindowX11(WindowInfoX *winInfo, QString &innerId)
{
AppInfo *appInfo = nullptr;
if (winInfo->getInnerId().isEmpty()) {
qInfo() << "identifyWindowX11: window innerId is empty";
return appInfo;
}
for (auto iter = m_identifyWindowFuns.begin(); iter != m_identifyWindowFuns.end(); iter++) {
QString name = iter->first;
IdentifyFunc func = iter->second;
qInfo() << "identifyWindowX11: try " << name;
appInfo = func(m_taskmanager, 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";
// 如果识别窗口失败则该app的entryInnerId使用当前窗口的innerId
innerId = winInfo->getInnerId();
return appInfo;
}
AppInfo *WindowIdentify::identifyWindowWayland(WindowInfoK *winInfo, QString &innerId)
{
// TODO: 对桌面调起的文管应用做规避处理需要在此处添加因为初始化时appId和title为空
if (winInfo->getAppId() == "dde-desktop" && m_taskmanager->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();
QString desktopFilePath = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
if ((desktopFilePath.endsWith(".desktop"))) {
appInfo = new AppInfo(desktopFilePath);
}
}
// autoStart
if (appInfo->isValidApp()) {
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
if (fixedAppInfo) {
delete appInfo;
appInfo = fixedAppInfo;
appInfo->setIdentifyMethod("FixAutostart");
}
}
if (appInfo)
innerId = appInfo->getInnerId();
return appInfo;
}
AppInfo *WindowIdentify::identifyWindowAndroid(TaskManager *_taskmanager, 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);
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(TaskManager *_taskmanager, 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) {
return ret;
}
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
QString launchedDesktopFilePidStr = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE_PID");
int launchedDesktopFilePid = launchedDesktopFilePidStr.toInt();
qInfo() << "launchedDesktopFilePid=" << launchedDesktopFilePid << " launchedDesktopFile=" << launchedDesktopFile;
if (launchedDesktopFile.isEmpty()) {
return ret;
}
auto pidIsSh = [](int pid) -> bool {
ProcessInfo parentProcess(pid);
auto parentCmdLine = parentProcess.getCmdLine();
if (parentCmdLine.size() <= 0) {
return false;
}
qInfo() << "ppid equal" << "parentCmdLine[0]:" << parentCmdLine[0];
QString cmd0 = parentCmdLine[0];
int pos = cmd0.lastIndexOf('/');
if (pos > 0)
cmd0 = cmd0.remove(0, pos + 1);
if (cmd0 == "sh" || cmd0 == "bash"){
return true;
}
return false;
};
auto processInLinglong = [](ProcessInfo* const process) -> bool {
for (ProcessInfo p(process->getPpid()); p.getPid() != 0; p = ProcessInfo(p.getPpid())) {
if (!p.getCmdLine().size()){
qWarning() << "Failed to get command line of" << p.getPid() << " SKIP it.";
continue;
}
if (p.getCmdLine()[0].indexOf("ll-box") != -1) {
qDebug() << "process ID" << process->getPid() << "is in linglong container,"
<<"ll-box PID" << p.getPid();
return true;
}
}
return false;
};
// 以下几种情况下,才能信任环境变量 GIO_LAUNCHED_DESKTOP_FILE。
if (pid == launchedDesktopFilePid || // 当窗口pid和launchedDesktopFilePid相同时
( process->getPpid() &&
process->getPpid() == launchedDesktopFilePid &&
pidIsSh(process->getPpid())
) || // 当窗口的进程的父进程id即ppid和launchedDesktopFilePid相同并且该父进程是sh或bash时。
processInLinglong(process) // 当窗口pid在玲珑容器中
) {
ret = new AppInfo(launchedDesktopFile);
innerId = ret->getInnerId();
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByCmdlineTurboBooster(TaskManager *_taskmanager, 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 (cmdline[0].startsWith(".desktop")) {
desktopFile = cmdline[0];
} else if (QString(cmdline[0]).contains("/applications/")) {
QFileInfo fileInfo(cmdline[0]);
QString path = fileInfo.path();
QString base = fileInfo.completeBaseName();
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(TaskManager *_taskmanager, 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();
QFileInfo file(exe);
QString exeBase = file.completeBaseName();
auto args = process->getArgs();
if (exe != "xwalk" || args.size() == 0)
break;
QString lastArg = args[args.size() - 1];
file.setFile(lastArg);
if (file.completeBaseName() == "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(TaskManager *_taskmanager, 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(TaskManager *_taskmanager, 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(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
{
static WindowPatterns patterns;
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");
if (!launchedDesktopFile.isEmpty())
ret = new AppInfo(launchedDesktopFile);
}
} else {
qInfo() << "patterns match bad result";
}
if (ret)
innerId = ret->getInnerId();
return ret;
}
AppInfo *WindowIdentify::identifyWindowByBamf(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
{
if (_taskmanager->isWaylandEnv()) {
return nullptr;
}
AppInfo *ret = nullptr;
XWindow xid = winInfo->getXid();
qInfo() << "identifyWindowByBamf: windowId=" << xid;
QString desktopFile;
// 重试 bamf 识别,部分的窗口经常要多次调用才能识别到。
for (int i = 0; i < 3; i++) {
desktopFile = _taskmanager->getDesktopFromWindowByBamf(xid);
if (!desktopFile.isEmpty())
break;
}
if (!desktopFile.isEmpty()) {
ret = new AppInfo(desktopFile);
innerId = ret->getInnerId();
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByPid(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
if (winInfo->getPid() > 10) {
auto entry = _taskmanager->getEntryByWindowId(winInfo->getPid());
if (entry) {
ret = entry->getAppInfo();
innerId = ret->getInnerId();
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByScratch(TaskManager *_taskmanager, 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(TaskManager *_taskmanager, 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(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
{
WMClass wmClass = winInfo->getWMClass();
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 (DesktopInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower()).isValidDesktop()) {
AppInfo *appInfo = new AppInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower());
innerId = appInfo->getInnerId();
return appInfo;
}
if (DesktopInfo(QString::fromStdString(wmClass.instanceName)).isValidDesktop()) {
AppInfo *appInfo = new AppInfo(wmClass.instanceName.c_str());
innerId = appInfo->getInnerId();
return appInfo;
}
}
if (wmClass.className.size() > 0) {
QString filename = QString::fromStdString(wmClass.className);
bool isValid = DesktopInfo(filename).isValidDesktop();
if (!isValid) {
filename = BamfDesktop::instance()->fileName(wmClass.instanceName.c_str());
isValid = DesktopInfo(filename).isValidDesktop();
}
if (isValid) {
AppInfo *appInfo = new AppInfo(filename);
innerId = appInfo->getInnerId();
return appInfo;
}
}
return nullptr;
}
AppInfo *WindowIdentify::fixAutostartAppInfo(QString fileName)
{
QFileInfo file(fileName);
QString filePath = file.absolutePath();
bool isAutoStart = false;
for (auto dir : QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)) {
if (dir.contains(filePath)) {
isAutoStart = true;
break;
}
}
return isAutoStart ? new AppInfo(file.completeBaseName()) : nullptr;
}
int32_t WindowIdentify::getAndroidUengineId(XWindow winId)
{
// TODO 获取AndroidUengineId
return 0;
}
QString WindowIdentify::getAndroidUengineName(XWindow winId)
{
// TODO 获取AndroidUengineName
return "";
}

View File

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWIDENTIFY_H
#define WINDOWIDENTIFY_H
#include "taskmanager/entry.h"
#include "windowpatterns.h"
#include "windowinfok.h"
#include "windowinfox.h"
#include <QObject>
#include <QVector>
#include <QMap>
class AppInfo;
class TaskManager;
typedef AppInfo *(*IdentifyFunc)(TaskManager *, WindowInfoX*, QString &innerId);
// 应用窗口识别类
class WindowIdentify : public QObject
{
Q_OBJECT
public:
explicit WindowIdentify(TaskManager *_taskmanager, QObject *parent = nullptr);
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
AppInfo *identifyWindowX11(WindowInfoX *winInfo, QString &innerId);
AppInfo *identifyWindowWayland(WindowInfoK *winInfo, QString &innerId);
static AppInfo *identifyWindowAndroid(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByPidEnv(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCmdlineTurboBooster(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCmdlineXWalk(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByFlatpakAppID(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCrxId(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByRule(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByBamf(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByPid(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByScratch(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByGtkAppId(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByWmClass(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
private:
AppInfo *fixAutostartAppInfo(QString fileName);
static int32_t getAndroidUengineId(XWindow winId);
static QString getAndroidUengineName(XWindow winId);
private:
TaskManager *m_taskmanager;
QList<QPair<QString, IdentifyFunc>> m_identifyWindowFuns;
};
#endif // IDENTIFYWINDOW_H

View File

@ -0,0 +1,68 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWINFOBASE_H
#define WINDOWINFOBASE_H
#include "processinfo.h"
#include "xcbutils.h"
#include <QString>
#include <QVector>
#include <qobject.h>
#include <qobjectdefs.h>
#include <qscopedpointer.h>
class Entry;
class AppInfo;
class WindowInfoBase : public QObject
{
Q_OBJECT
public:
WindowInfoBase(QObject *parent = nullptr) : QObject(parent), entry(nullptr), app(nullptr), m_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;
virtual QString uuid() = 0;
virtual QString getInnerId() { return innerId; }
XWindow getXid() {return xid;}
void setEntry(Entry *value) { entry = value; }
Entry *getEntry() { return entry; }
QString getEntryInnerId() { return entryInnerId; }
void setEntryInnerId(QString value) { entryInnerId = value; }
AppInfo *getAppInfo() { return app; }
void setAppInfo(AppInfo *value) { app = value; }
int getPid() { return pid; }
ProcessInfo *getProcess() { return m_processInfo.data(); }
bool containAtom(QVector<XCBAtom> supports, XCBAtom ty) {return supports.indexOf(ty) != -1;}
protected:
XWindow xid; // 窗口id
QString title; // 窗口标题
QString icon; // 窗口图标
int pid; // 窗口所属应用进程
QString entryInnerId; // 窗口所属应用对应的innerId
QString innerId; // 窗口对应的innerId
Entry *entry; // 窗口所属应用
AppInfo *app; // 窗口所属应用对应的desktopFile信息
int64_t m_createdTime; // 创建时间
QScopedPointer<ProcessInfo> m_processInfo; // 窗口所属应用的进程信息
};
#endif // WINDOWINFOBASE_H

View File

@ -0,0 +1,210 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "windowinfok.h"
#include "entry.h"
#include "processinfo.h"
#include "appinfo.h"
#include <chrono>
#include <qobject.h>
WindowInfoK::WindowInfoK(PlasmaWindow *window, XWindow _xid, QObject *parent)
: WindowInfoBase (parent)
, m_updateCalled(false)
, m_internalId(0)
, m_demaningAttention(false)
, m_closeable(true)
, m_plasmaWindow(window)
{
xid = _xid;
m_createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
}
WindowInfoK::~WindowInfoK()
{
}
bool WindowInfoK::shouldSkip()
{
if (!m_updateCalled) {
update();
m_updateCalled = true;
}
bool skip = m_plasmaWindow->SkipTaskbar();
// 添加窗口能否最小化判断, 如果窗口不能最小化则隐藏任务栏图标
bool canMinimize = false;
canMinimize = m_plasmaWindow->IsMinimizeable();
if (!canMinimize)
skip = true;
if (skip) {
// 白名单, 过滤类似“欢迎应用”, 没有最小化窗口但是需要在任务栏显示图标
QStringList list { "dde-introduction"};
if (list.indexOf(m_appId) != -1)
skip = false;
}
return skip;
}
QString WindowInfoK::getIcon()
{
return icon;
}
QString WindowInfoK::getTitle()
{
return title;
}
bool WindowInfoK::isDemandingAttention()
{
return m_demaningAttention;
}
bool WindowInfoK::allowClose()
{
return m_closeable;
}
void WindowInfoK::close(uint32_t timestamp)
{
m_plasmaWindow->RequestClose();
}
QString WindowInfoK::getAppId()
{
return m_appId;
}
void WindowInfoK::setAppId(QString _appId)
{
m_appId = _appId;
}
void WindowInfoK::activate()
{
m_plasmaWindow->RequestActivate();
}
void WindowInfoK::minimize()
{
m_plasmaWindow->RequestToggleMinimized();
}
bool WindowInfoK::isMinimized()
{
return m_plasmaWindow->IsMinimized();
}
bool WindowInfoK::changeXid(XWindow _xid)
{
xid = _xid;
return true;
}
PlasmaWindow *WindowInfoK::getPlasmaWindow()
{
return m_plasmaWindow.data();
}
bool WindowInfoK::updateGeometry()
{
DockRect rect = m_plasmaWindow->Geometry();
if (m_geometry == rect)
return false;
m_geometry = rect;
return true;
}
void WindowInfoK::updateTitle()
{
title = m_plasmaWindow->Title();
}
void WindowInfoK::updateDemandingAttention()
{
m_demaningAttention = m_plasmaWindow->IsDemandingAttention();
}
void WindowInfoK::updateIcon()
{
icon = m_plasmaWindow->Icon();
}
void WindowInfoK::updateAppId()
{
m_appId = m_plasmaWindow->AppId();
}
void WindowInfoK::updateInternalId()
{
m_internalId = m_plasmaWindow->InternalId();
}
void WindowInfoK::updateCloseable()
{
m_closeable = m_plasmaWindow->IsCloseable();
}
void WindowInfoK::updateProcessInfo()
{
pid = m_plasmaWindow->Pid();
m_processInfo.reset(new ProcessInfo(pid));
}
/**
* @brief WindowInfoK::getGeometry
* @return
*/
DockRect WindowInfoK::getGeometry()
{
return m_geometry;
}
int64_t WindowInfoK::getCreatedTime()
{
return m_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()
{
}
QString WindowInfoK::uuid()
{
return QString(m_plasmaWindow->uuid());
}
QString WindowInfoK::getInnerId()
{
return QString::number(m_internalId);
}

View File

@ -0,0 +1,68 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWINFOK_H
#define WINDOWINFOK_H
#include "windowinfobase.h"
#include "org_deepin_dde_kwayland_plasmawindow.h"
#include <QString>
#include <qobject.h>
#include <qscopedpointer.h>
using PlasmaWindow = org::deepin::dde::kwayland1::PlasmaWindow;
class Entry;
class ProcessInfo;
// wayland下窗口信息
class WindowInfoK: public WindowInfoBase
{
public:
explicit WindowInfoK(PlasmaWindow *window, XWindow _xid = 0, QObject *parent = nullptr);
virtual ~WindowInfoK() override;
virtual bool shouldSkip() override;
virtual QString getIcon() override;
virtual QString getTitle() override;
virtual bool isDemandingAttention() override;
virtual bool allowClose() override;
virtual void close(uint32_t timestamp) override;
virtual void activate() override;
virtual void minimize() override;
virtual bool isMinimized() override;
virtual int64_t getCreatedTime() override;
virtual QString getDisplayName() override;
virtual QString getWindowType() override;
virtual void update() override;
virtual void killClient() override;
virtual QString uuid() override;
QString getInnerId() override;
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();
DockRect getGeometry();
private:
bool m_updateCalled;
QString m_appId;
uint32_t m_internalId;
bool m_demaningAttention;
bool m_closeable;
DockRect m_geometry;
QScopedPointer<PlasmaWindow> m_plasmaWindow;
};
#endif // WINDOWINFOK_H

View File

@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "windowinfomap.h"
QDebug operator<<(QDebug argument, const WindowInfo &info)
{
argument << '(' << info.title << ',' << info.attention << info.uuid << ')';
return argument;
}
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
{
argument.beginStructure();
argument << info.title << info.attention << info.uuid;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
{
argument.beginStructure();
argument >> info.title >> info.attention >> info.uuid;
argument.endStructure();
return argument;
}
bool WindowInfo::operator==(const WindowInfo &rhs) const
{
return attention == rhs.attention &&
title == rhs.title &&
uuid == rhs.uuid;
}

View File

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWINFOLIST_H
#define WINDOWINFOLIST_H
#include <QDebug>
#include <QList>
#include <QDBusArgument>
class WindowInfo
{
public:
friend QDebug operator<<(QDebug argument, const WindowInfo &info);
friend QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info);
friend const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info);
bool operator==(const WindowInfo &rhs) const;
public:
bool attention;
QString title;
QString uuid;
};
typedef QMap<quint32, WindowInfo> WindowInfoMap;
#endif // WINDOWINFOLIST_H

View File

@ -0,0 +1,470 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "windowinfox.h"
#include "appinfo.h"
#include "xcbutils.h"
#include "common.h"
#include "processinfo.h"
#include <QDebug>
#include <QCryptographicHash>
#include <QTimer>
#include <QImage>
#include <QIcon>
#include <QBuffer>
#include <X11/Xlib.h>
#include <algorithm>
#include <qobject.h>
#include <string>
#define XCB XCBUtils::instance()
WindowInfoX::WindowInfoX(XWindow _xid, QObject *parent)
: WindowInfoBase (parent)
, m_x(0)
, m_y(0)
, m_width(0)
, m_height(0)
, m_hasWMTransientFor(false)
, m_hasXEmbedInfo(false)
, m_updateCalled(false)
{
xid = _xid;
m_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 (!m_updateCalled) {
update();
m_updateCalled = true;
}
if (hasWmStateSkipTaskBar() || isValidModal() || shouldSkipWithWMClass())
return true;
for (auto atom : m_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->changeActiveWindow(xid);
QTimer::singleShot(50, [&] {
XCB->restackWindow(xid);
});
}
void WindowInfoX::minimize()
{
XCB->minimizeWindow(xid);
}
bool WindowInfoX::isMinimized()
{
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_HIDDEN"));
}
int64_t WindowInfoX::getCreatedTime()
{
return m_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 ((m_motifWmHints.flags & MotifHintFunctions) == 0
|| (m_motifWmHints.functions & MotifFunctionAll) != 0
|| (m_motifWmHints.functions & MotifFunctionClose) != 0)
return true;
for (auto action : m_wmAllowedActions) {
if (action == XCB->getAtom("_NET_WM_ACTION_CLOSE")) {
return true;
}
}
return false;
}
QString WindowInfoX::getDisplayName()
{
XWindow winId = xid;
//QString role = wmRole;
QString className(m_wmClass.className.c_str());
QString instance;
if (m_wmClass.instanceName.size() > 0) {
int pos = QString(m_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 = m_wmName;
if (!_wmName.isEmpty()) {
int pos = _wmName.lastIndexOf('-');
if (pos != -1 && !_wmName.startsWith("-")) {
_wmName.truncate(pos);
return _wmName;
}
}
if (m_processInfo) {
QString exe {m_processInfo->getEnv("exe")};
if (!exe.isEmpty())
return exe;
}
return QString("window:%1").arg(winId);
}
void WindowInfoX::killClient()
{
XCB->killClientChecked(xid);
}
QString WindowInfoX::uuid()
{
return QString();
}
QString WindowInfoX::getGtkAppId()
{
return m_gtkAppId;
}
QString WindowInfoX::getFlatpakAppId()
{
return m_flatpakAppId;
}
QString WindowInfoX::getWmRole()
{
return m_wmRole;
}
WMClass WindowInfoX::getWMClass()
{
return m_wmClass;
}
QString WindowInfoX::getWMName()
{
return m_wmName;
}
ConfigureEvent *WindowInfoX::getLastConfigureEvent()
{
return m_lastConfigureNotifyEvent;
}
void WindowInfoX::setLastConfigureEvent(ConfigureEvent *event)
{
m_lastConfigureNotifyEvent = event;
}
bool WindowInfoX::isGeometryChanged(int _x, int _y, int _width, int _height)
{
return !(_x == m_x && _y == m_y && _width == m_width && _height == m_height);
}
void WindowInfoX::setGtkAppId(QString _gtkAppId)
{
m_gtkAppId = _gtkAppId;
}
void WindowInfoX::updateMotifWmHints()
{
// get from XCB
m_motifWmHints = XCB->getWindowMotifWMHints(xid);
}
// XEmbed info
// 一般 tray icon 会带有 _XEMBED_INFO 属性
void WindowInfoX::updateHasXEmbedInfo()
{
m_hasXEmbedInfo = XCB->hasXEmbedInfo(xid);
}
/**
* @brief WindowInfoX::genInnerId innerId
* @param winInfo
* @return
*/
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();
for (auto arg : winInfo->getProcess()->getArgs()) {
if (arg.contains("/") || arg == "." || arg == "..") {
args += "%F ";
} else {
args += arg + " ";
}
}
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()
{
m_wmWindowType.clear();
for (auto ty : XCB->getWMWindoType(xid)) {
m_wmWindowType.push_back(ty);
}
}
// 更新窗口许可动作
void WindowInfoX::updateWmAllowedActions()
{
m_wmAllowedActions.clear();
for (auto action : XCB->getWMAllowedActions(xid)) {
m_wmAllowedActions.push_back(action);
}
}
void WindowInfoX::updateWmState()
{
m_wmState.clear();
for (auto a : XCB->getWMState(xid)) {
m_wmState.push_back(a);
}
}
void WindowInfoX::updateWmClass()
{
m_wmClass = XCB->getWMClass(xid);
}
void WindowInfoX::updateWmName()
{
auto name = XCB->getWMName(xid);
if (!name.empty())
m_wmName = name.c_str();
title = getTitle();
}
void WindowInfoX::updateIcon()
{
icon = getIconFromWindow();
}
void WindowInfoX::updateHasWmTransientFor()
{
if (XCB->getWMTransientFor(xid) == 1)
m_hasWMTransientFor = true;
}
/**
* @brief WindowInfoX::update
*/
void WindowInfoX::update()
{
updateWmClass();
updateWmState();
updateWmWindowType();
updateWmAllowedActions();
updateHasWmTransientFor();
updateProcessInfo();
updateWmName();
innerId = genInnerId(this);
}
QString WindowInfoX::getIconFromWindow()
{
WMIcon icon = XCB->getWMIcon(xid);
// invalid icon
if (icon.width == 0) {
return QString();
}
QImage img = QImage((uchar *)icon.data.data(), icon.width, icon.width, QImage::Format_ARGB32);
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
img.scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation);
img.save(&buffer, "PNG");
// convert to base64
QString encode = buffer.data().toBase64();
QString iconPath = QString("%1,%2").arg("data:image/png:base64").arg(encode);
buffer.close();
return iconPath;
}
bool WindowInfoX::isActionMinimizeAllowed()
{
return containAtom(m_wmAllowedActions, XCB->getAtom("_NET_WM_ACTION_MINIMIZE"));
}
bool WindowInfoX::hasWmStateDemandsAttention()
{
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_DEMANDS_ATTENTION"));
}
bool WindowInfoX::hasWmStateSkipTaskBar()
{
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_SKIP_TASKBAR"));
}
bool WindowInfoX::hasWmStateModal()
{
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_MODAL"));
}
bool WindowInfoX::isValidModal()
{
return hasWmStateModal() && hasWmStateModal();
}
// 通过WMClass判断是否需要隐藏此窗口
bool WindowInfoX::shouldSkipWithWMClass()
{
bool ret = false;
if (m_wmClass.instanceName == "explorer.exe" && m_wmClass.className == "Wine")
ret = true;
else if (m_wmClass.className == "dde-launcher" ||
m_wmClass.className == "dde-dock" ||
m_wmClass.className == "dde-lock") {
ret = true;
}
return ret;
}
void WindowInfoX::updateProcessInfo()
{
XWindow winId = xid;
pid = XCB->getWMPid(winId);
qInfo() << "updateProcessInfo: pid=" << pid;
m_processInfo.reset(new ProcessInfo(pid));
if (!m_processInfo->isValid()) {
// try WM_COMMAND
auto wmComand = XCB->getWMCommand(winId);
if (wmComand.size() > 0) {
QStringList cmds;
std::transform(wmComand.begin(), wmComand.end(), std::back_inserter(cmds), [=] (std::string cmd){ return QString::fromStdString(cmd);});
m_processInfo.reset(new ProcessInfo(cmds));
}
}
qInfo() << "updateProcessInfo: pid is " << pid;
}
bool WindowInfoX::getUpdateCalled()
{
return m_updateCalled;
}
void WindowInfoX::setInnerId(QString _innerId)
{
innerId = _innerId;
}
QString WindowInfoX::getTitle()
{
QString name = m_wmName;
if (name.isEmpty())
name = getDisplayName();
return name;
}
bool WindowInfoX::isDemandingAttention()
{
return hasWmStateDemandsAttention();
}
void WindowInfoX::close(uint32_t timestamp)
{
XCB->requestCloseWindow(xid, timestamp);
}

View File

@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWINFOX_H
#define WINDOWINFOX_H
#include "windowinfobase.h"
#include "xcbutils.h"
#include <QVector>
#include <qobject.h>
#include <qobjectdefs.h>
class AppInfo;
// X11下窗口信息 在明确X11环境下使用
class WindowInfoX: public WindowInfoBase
{
Q_OBJECT
public:
WindowInfoX(XWindow _xid = 0, QObject *parent = nullptr);
virtual ~WindowInfoX() override;
virtual bool shouldSkip() override;
virtual QString getIcon() override;
virtual QString getTitle() override;
virtual bool isDemandingAttention() override;
virtual void close(uint32_t timestamp) override;
virtual void activate() override;
virtual void minimize() override;
virtual bool isMinimized() override;
virtual int64_t getCreatedTime() override;
virtual QString getDisplayName() override;
virtual QString getWindowType() override;
virtual bool allowClose() override;
virtual void update() override;
virtual void killClient() override;
virtual QString uuid() override;
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();
private:
int16_t m_x;
int16_t m_y;
uint16_t m_width;
uint16_t m_height;
QVector<XCBAtom> m_wmState;
QVector<XCBAtom> m_wmWindowType;
QVector<XCBAtom> m_wmAllowedActions;
bool m_hasWMTransientFor;
WMClass m_wmClass;
QString m_wmName;
bool m_hasXEmbedInfo;
// 自定义atom属性
QString m_gtkAppId;
QString m_flatpakAppId;
QString m_wmRole;
MotifWMHints m_motifWmHints;
bool m_updateCalled;
ConfigureEvent *m_lastConfigureNotifyEvent;
};
#endif // WINDOWINFOX_H

View File

@ -0,0 +1,299 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "windowpatterns.h"
#include "processinfo.h"
#include <QJsonDocument>
#include <QStandardPaths>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QVariant>
#include <QVariantMap>
#include <QDebug>
#include <QRegExp>
#include <QFile>
#include <QFileInfo>
const int parsedFlagNegative = 0x001;
const int parsedFlagIgnoreCase = 0x010;
const QString getWindowPatternsFile(){
for (auto dataLocation : QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
QString targetFilePath = dataLocation.append("/dde-dock/window_patterns.json");
if (QFile::exists(targetFilePath)) return targetFilePath;
}
return QString();
}
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);
bool ret = ruleRegex.exactMatch(key);
// 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败暂时做兼容处理
if (!ret && value == "\\.exe$") {
ret = key.endsWith(".exe");
}
return ret;
}
bool regexMatchIgnoreCase(QString key, QString value) {
QRegExp ruleRegex(value, Qt::CaseInsensitive);
bool ret = ruleRegex.exactMatch(key);
// 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败暂时做兼容处理
if (!ret && value == "\\.exe$") {
QString _key = key.toLower();
ret = _key.endsWith(".exe");
}
return ret;
}
RuleValueParse::RuleValueParse()
: negative(false)
, type(0)
, flags(0)
{
}
bool RuleValueParse::match(const WindowInfoX *winInfo)
{
QString parsedKey = parseRuleKey(const_cast<WindowInfoX *>(winInfo), key);
if (!fn)
return false;
bool ret = fn(parsedKey, value);
return negative ? !ret : ret;
}
QString RuleValueParse::parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey)
{
ProcessInfo * process = winInfo->getProcess();
if (ruleKey == "hasPid") {
if (process && process->initWithPid()) {
return "t";
}
return "f";
} else if (ruleKey == "exec") {
if (process) {
// 返回执行文件baseName
auto baseName = QFileInfo(process->getExe()).completeBaseName();
return baseName.isEmpty() ? "" : baseName;
}
} else if (ruleKey == "arg") {
if (process) {
// 返回命令行参数
auto ret = process->getArgs().join("");
return ret.isEmpty() ? "" : ret;
}
} else if (ruleKey == "wmi") {
// 窗口实例
auto wmClass = winInfo->getWMClass();
if (!wmClass.instanceName.empty())
return wmClass.instanceName.c_str();
} else if (ruleKey == "wmc") {
// 窗口类型
auto wmClass = winInfo->getWMClass();
if (!wmClass.className.empty())
return wmClass.className.c_str();
} else if (ruleKey == "wmn") {
// 窗口名称
return winInfo->getWMName();
} else if (ruleKey == "wmrole") {
// 窗口角色
return winInfo->getWmRole();
} else {
const QString envPrefix = "env.";
if (ruleKey.startsWith(envPrefix)) {
QString envName = ruleKey.mid(envPrefix.size());
if (winInfo->getProcess()) {
auto ret = process->getEnv(envName);
return ret.isEmpty() ? "" : ret;
}
}
}
return "";
}
WindowPatterns::WindowPatterns()
{
loadWindowPatterns();
}
/**
* @brief WindowPatterns::match
* @param winInfo
* @return
*/
QString WindowPatterns::match(WindowInfoX *winInfo)
{
for (auto pattern : m_patterns) {
bool patternOk = true;
for (auto rule : pattern.parseRules) {
if (!rule.match(winInfo)) {
patternOk = false;
break;
}
}
if (patternOk) {
// 匹配成功
return pattern.result;
}
}
// 匹配失败
return "";
}
void WindowPatterns::loadWindowPatterns()
{
qInfo() << "---loadWindowPatterns";
QFile file(getWindowPatternsFile());
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;
m_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];
}
m_patterns.push_back(pattern);
}
// 解析patterns
for (auto &pattern : m_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 ':':
break;
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:
break;
}
free(orig);
return ret;
}

View File

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef WINDOWPATTERNS_H
#define WINDOWPATTERNS_H
#include "windowinfox.h"
#include <QString>
#include <QVector>
struct RuleValueParse {
RuleValueParse();
bool match(const WindowInfoX *winInfo);
static QString parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey);
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);
private:
QVector<WindowPattern> m_patterns;
};
#endif // WINDOWPATTERNS_H

View File

@ -0,0 +1,455 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "x11manager.h"
#include "taskmanager.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(TaskManager *_taskmanager, QObject *parent)
: QObject(parent)
, m_taskmanager(_taskmanager)
, m_mutex(QMutex(QMutex::NonRecursive))
, m_listenXEvent(true)
{
m_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 (m_listenXEvent) {
XEvent event;
XNextEvent (dpy, &event);
switch (event.type) {
case DestroyNotify: {
XDestroyWindowEvent *eD = (XDestroyWindowEvent *)(&event);
// qDebug() << "DestroyNotify windowId=" << eD->window;
handleDestroyNotifyEvent(XWindow(eD->window));
break;
}
case MapNotify: {
XMapEvent *eM = (XMapEvent *)(&event);
// qDebug() << "MapNotify windowId=" << eM->window;
handleMapNotifyEvent(XWindow(eM->window));
break;
}
case ConfigureNotify: {
XConfigureEvent *eC = (XConfigureEvent *)(&event);
// qDebug() << "ConfigureNotify windowId=" << eC->window;
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
break;
}
case PropertyNotify: {
XPropertyEvent *eP = (XPropertyEvent *)(&event);
// qDebug() << "PropertyNotify windowId=" << eP->window;
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
break;
}
case UnmapNotify: {
// 当松开鼠标的时候会触发该事件,在松开鼠标的时候,需要检测当前窗口是否符合智能隐藏的条件,因此在此处加上该功能
// 如果不加上该处理,那么就会出现将窗口从任务栏下方移动到屏幕中央的时候,任务栏不隐藏
handleActiveWindowChangedX();
break;
}
default:
qDebug() << "unused event type " << event.type;
break;
}
}
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);
}
*/
}
/**
* @brief X11Manager::registerWindow X11窗口
* @param xid
* @return
*/
WindowInfoX *X11Manager::registerWindow(XWindow xid)
{
qInfo() << "registWindow: windowId=" << xid;
WindowInfoX *ret = nullptr;
do {
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end()) {
ret = m_windowInfoMap[xid];
break;
}
WindowInfoX *winInfo = new WindowInfoX(xid);
if (!winInfo)
break;
listenWindowXEvent(winInfo);
m_windowInfoMap[xid] = winInfo;
ret = winInfo;
} while (0);
return ret;
}
// 取消注册X11窗口
void X11Manager::unregisterWindow(XWindow xid)
{
qInfo() << "unregisterWindow: windowId=" << xid;
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end()) {
m_windowInfoMap.remove(xid);
}
}
WindowInfoX *X11Manager::findWindowByXid(XWindow xid)
{
WindowInfoX *ret = nullptr;
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end())
ret = m_windowInfoMap[xid];
return ret;
}
void X11Manager::handleClientListChanged()
{
QSet<XWindow> newClientList, oldClientList, addClientList, rmClientList;
for (auto atom : XCB->getClientList())
newClientList.insert(atom);
for (auto atom : m_taskmanager->getClientList())
oldClientList.insert(atom);
addClientList = newClientList - oldClientList;
rmClientList = oldClientList - newClientList;
m_taskmanager->setClientList(newClientList.values());
// 处理新增窗口
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) {
if (info) {
Q_EMIT requestAttachOrDetachWindow(info);
}
}
}
// 处理需要移除的窗口
for (auto xid : rmClientList) {
WindowInfoX *info = m_windowInfoMap[xid];
if (info) {
m_taskmanager->detachWindow(info);
unregisterWindow(xid);
} else {
// no window
auto entry = m_taskmanager->getEntryByWindowId(xid);
if (entry && !m_taskmanager->isDocked(entry->getFileName())) {
m_taskmanager->removeAppEntry(entry);
}
}
}
}
void X11Manager::handleActiveWindowChangedX()
{
XWindow active = XCB->getActiveWindow();
WindowInfoX *info = findWindowByXid(active);
if (info) {
Q_EMIT requestHandleActiveWindowChange(info);
}
}
void X11Manager::listenRootWindowXEvent()
{
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
XCB->registerEvents(m_rootWindow, eventMask);
handleActiveWindowChangedX();
handleClientListChanged();
}
/**
* @brief X11Manager::listenWindowXEvent
* @param winInfo
*/
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 requestUpdateHideState(false);
}
}
// destory event
void X11Manager::handleDestroyNotifyEvent(XWindow xid)
{
WindowInfoX *winInfo = findWindowByXid(xid);
if (!winInfo)
return;
m_taskmanager->detachWindow(winInfo);
unregisterWindow(xid);
}
// map event
void X11Manager::handleMapNotifyEvent(XWindow xid)
{
WindowInfoX *winInfo = registerWindow(xid);
if (!winInfo)
return;
// TODO QTimer不能在非主线程执行使用单独线程开发定时器处理非主线程类似定时任务
//QTimer::singleShot(2 * 1000, this, [=] {
qInfo() << "handleMapNotifyEvent: pass 2s, now call idnetifyWindow, windowId=" << winInfo->getXid();
QString innerId;
AppInfo *appInfo = m_taskmanager->identifyWindow(winInfo, innerId);
m_taskmanager->markAppLaunched(appInfo);
//});
}
// config changed event 检测窗口大小调整和重绘应用,触发智能隐藏更新
void X11Manager::handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height)
{
WindowInfoX *winInfo = findWindowByXid(xid);
if (!winInfo || m_taskmanager->getDockHideMode() != HideMode::SmartHide)
return;
WMClass wmClass = winInfo->getWMClass();
if (wmClass.className.c_str() == frontendWindowWmClass)
return; // ignore frontend window ConfigureNotify event
Q_EMIT requestUpdateHideState(winInfo->isGeometryChanged(x, y, width, height));
}
// property changed event
void X11Manager::handlePropertyNotifyEvent(XWindow xid, XCBAtom atom)
{
if (xid == m_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
m_taskmanager->detachWindow(winInfo);
winInfo->setInnerId(newInnerId);
needAttachOrDetach = true;
}
if (needAttachOrDetach && winInfo) {
Q_EMIT requestAttachOrDetachWindow(winInfo);
}
Entry *entry = m_taskmanager->getEntryByWindowId(xid);
if (!entry)
return;
if (atom == XCB->getAtom("_NET_WM_STATE")) {
// entry->updateExportWindowInfos();
} 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->updateExportWindowInfos();
} 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(&m_mutex);
QTimer *timer = new QTimer();
timer->setInterval(configureNotifyDelay);
m_windowLastConfigureEventMap[xid] = QPair(event, timer);
}
QPair<ConfigureEvent *, QTimer *> X11Manager::getWindowLastConfigureEvent(XWindow xid)
{
QPair<ConfigureEvent *, QTimer *> ret;
QMutexLocker locker(&m_mutex);
if (m_windowLastConfigureEventMap.find(xid) != m_windowLastConfigureEventMap.end())
ret = m_windowLastConfigureEventMap[xid];
return ret;
}
void X11Manager::delWindowLastConfigureEvent(XWindow xid)
{
QMutexLocker locker(&m_mutex);
if (m_windowLastConfigureEventMap.find(xid) != m_windowLastConfigureEventMap.end()) {
QPair<ConfigureEvent*, QTimer*> item = m_windowLastConfigureEventMap[xid];
m_windowLastConfigureEventMap.remove(xid);
delete item.first;
item.second->deleteLater();
}
}

View File

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef X11MANAGER_H
#define X11MANAGER_H
#include "windowinfox.h"
#include "xcbutils.h"
#include <QObject>
#include <QMap>
#include <QMutex>
#include <QTimer>
class TaskManager;
class X11Manager : public QObject
{
Q_OBJECT
public:
explicit X11Manager(TaskManager *_taskmanager, 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();
Q_SIGNALS:
void requestUpdateHideState(bool delay);
void requestHandleActiveWindowChange(WindowInfoBase *info);
void requestAttachOrDetachWindow(WindowInfoBase *info);
private:
void addWindowLastConfigureEvent(XWindow xid, ConfigureEvent* event);
QPair<ConfigureEvent*, QTimer*> getWindowLastConfigureEvent(XWindow xid);
void delWindowLastConfigureEvent(XWindow xid);
private:
QMap<XWindow, WindowInfoX *> m_windowInfoMap;
TaskManager *m_taskmanager;
QMap<XWindow, QPair<ConfigureEvent*, QTimer*>> m_windowLastConfigureEventMap; // 手动回收ConfigureEvent和QTimer
QMutex m_mutex;
XWindow m_rootWindow; // 根窗口
bool m_listenXEvent; // 监听X事件
};
#endif // X11MANAGER_H

View File

@ -0,0 +1,760 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "xcbutils.h"
#include <cstdint>
#include <utility>
#include <iostream>
#include <cstring>
#include <memory>
#include <algorithm>
#include <X11/Xlib.h>
#include <X11/extensions/XRes.h>
XCBUtils::XCBUtils()
{
m_connect = xcb_connect(nullptr, &m_screenNum); // nullptr表示默认使用环境变量$DISPLAY获取屏幕
if (xcb_connection_has_error(m_connect)) {
std::cout << "XCBUtils: init xcb_connect error" << std::endl;
return;
}
if (!xcb_ewmh_init_atoms_replies(&m_ewmh,
xcb_ewmh_init_atoms(m_connect, &m_ewmh), // 初始化Atom
nullptr))
std::cout << "XCBUtils: init ewmh error" << std::endl;
}
XCBUtils::~XCBUtils()
{
if (m_connect) {
xcb_disconnect(m_connect); // 关闭连接并释放
m_connect = nullptr;
}
}
XWindow XCBUtils::allocId()
{
return xcb_generate_id(m_connect);
}
void XCBUtils::flush()
{
xcb_flush(m_connect);
}
void XCBUtils::killClientChecked(XWindow xid)
{
xcb_kill_client_checked(m_connect, xid);
}
xcb_get_property_reply_t *XCBUtils::getPropertyValueReply(XWindow xid, XCBAtom property, XCBAtom type)
{
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect,
0,
xid,
property,
type,
0,
MAXLEN);
return xcb_get_property_reply(m_connect, cookie, nullptr);
}
void *XCBUtils::getPropertyValue(XWindow xid, XCBAtom property, XCBAtom type)
{
void *value = nullptr;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, property, type);
if (reply) {
if (xcb_get_property_value_length(reply) > 0) {
value = xcb_get_property_value(reply);
}
free(reply);
}
return value;
}
std::string XCBUtils::getUTF8PropertyStr(XWindow xid, XCBAtom property)
{
std::string ret;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, property, m_ewmh.UTF8_STRING);
if (reply) {
ret = getUTF8StrFromReply(reply);
free(reply);
}
return ret;
}
XCBAtom XCBUtils::getAtom(const char *name)
{
XCBAtom ret = m_atomCache.getVal(name);
if (ret == ATOMNONE) {
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connect, false, strlen(name), name);
std::shared_ptr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(m_connect, cookie, nullptr), [=](xcb_intern_atom_reply_t* reply){
free(reply);}
);
if (reply) {
m_atomCache.store(name, xcb_atom_t(reply->atom));
ret = reply->atom;
}
}
return ret;
}
std::string XCBUtils::getAtomName(XCBAtom atom)
{
std::string ret = m_atomCache.getName(atom);
if (ret.empty()) {
xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(m_connect, atom);
std::shared_ptr<xcb_get_atom_name_reply_t> reply(
xcb_get_atom_name_reply(m_connect, cookie, nullptr),
[=](xcb_get_atom_name_reply_t* reply) {free(reply);});
if (reply) {
char *name = xcb_get_atom_name_name(reply.get());
if (name) {
m_atomCache.store(name, atom);
ret = name;
}
}
}
return ret;
}
Geometry XCBUtils::getWindowGeometry(XWindow xid)
{
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xcb_drawable_t(xid));
std::shared_ptr<xcb_get_geometry_reply_t> reply(
xcb_get_geometry_reply(m_connect, cookie, nullptr),
[=](xcb_get_geometry_reply_t* reply){free(reply);}
);
if (!reply) {
std::cout << xid << " getWindowGeometry err" << std::endl;
return Geometry();
}
Geometry ret;
ret.x = reply->x;
ret.y = reply->y;
ret.width = reply->width;
ret.height = reply->height;
const xcb_setup_t *xcbSetup = xcb_get_setup(m_connect);
if (!xcbSetup)
return Geometry();
xcb_screen_iterator_t xcbScreenIterator = xcb_setup_roots_iterator(xcbSetup);
std::shared_ptr<xcb_translate_coordinates_reply_t> translateReply(
xcb_translate_coordinates_reply(m_connect,
xcb_translate_coordinates(m_connect, xid, xcbScreenIterator.data->root, 0, 0),
nullptr),
[=](xcb_translate_coordinates_reply_t* translateReply){free(translateReply);});
if (translateReply) {
ret.x = translateReply->dst_x;
ret.y = translateReply->dst_y;
}
XWindow dWin = getDecorativeWindow(xid);
reply.reset(xcb_get_geometry_reply(m_connect, xcb_get_geometry(m_connect, xcb_drawable_t(dWin)), nullptr),
[=](xcb_get_geometry_reply_t* reply){free(reply);});
if (!reply)
return ret;
if (reply->x == ret.x && reply->y == ret.y) {
// 无标题的窗口比如deepin-editor, dconf-editor等
WindowFrameExtents windowFrameRect = getWindowFrameExtents(xid);
if (!windowFrameRect.isNull()) {
int x = ret.x + windowFrameRect.Left;
int y = ret.y + windowFrameRect.Top;
int width = ret.width - (windowFrameRect.Left + windowFrameRect.Right);
int height = ret.height - (windowFrameRect.Top + windowFrameRect.Bottom);
ret.x = x;
ret.y = y;
ret.width = width;
ret.height = height;
}
}
return ret;
}
XWindow XCBUtils::getDecorativeWindow(XWindow xid)
{
XWindow winId = xid;
for (int i = 0; i < 10; i++) {
xcb_query_tree_cookie_t cookie = xcb_query_tree(m_connect, winId);
std::shared_ptr<xcb_query_tree_reply_t> reply(
xcb_query_tree_reply(m_connect, cookie, nullptr),
[=](xcb_query_tree_reply_t* reply){free(reply);}
);
if (!reply) return 0;
if (reply->root == reply->parent) return winId;
winId = reply->parent;
}
return 0;
}
WindowFrameExtents XCBUtils::getWindowFrameExtents(XWindow xid)
{
xcb_atom_t perp = getAtom("_NET_FRAME_EXTENTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
std::shared_ptr<xcb_get_property_reply_t> reply(
xcb_get_property_reply(m_connect, cookie, nullptr),
[=](xcb_get_property_reply_t* reply){free(reply);}
);
if (!reply || reply->format == 0) {
perp = getAtom("_GTK_FRAME_EXTENTS");
cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
reply.reset(xcb_get_property_reply(m_connect, cookie, nullptr), [=](xcb_get_property_reply_t* reply){free(reply);});
if (!reply)
return WindowFrameExtents();
}
if (reply->format != 32 || reply->value_len != 4) {
return WindowFrameExtents();
}
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply.get()));
if (!data)
return WindowFrameExtents();
WindowFrameExtents winFrame(data[0], data[1], data[2], data[3]);
return winFrame;
}
XWindow XCBUtils::getActiveWindow()
{
XWindow ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window(&m_ewmh, m_screenNum);
if (!xcb_ewmh_get_active_window_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << "getActiveWindow error" << std::endl;
}
return ret;
}
void XCBUtils::setActiveWindow(XWindow xid)
{
xcb_ewmh_set_active_window(&m_ewmh, m_screenNum, xid);
}
void XCBUtils::changeActiveWindow(XWindow newActiveXid)
{
xcb_ewmh_request_change_active_window(&m_ewmh, m_screenNum, newActiveXid, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER, XCB_CURRENT_TIME, XCB_WINDOW_NONE);
flush();
}
void XCBUtils::restackWindow(XWindow xid)
{
xcb_ewmh_request_restack_window(&m_ewmh, m_screenNum, xid, 0, XCB_STACK_MODE_ABOVE);
}
std::list<XWindow> XCBUtils::getClientList()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list(&m_ewmh, m_screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (xcb_ewmh_get_client_list_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.windows_len; i++) {
ret.push_back(reply.windows[i]);
}
xcb_ewmh_get_windows_reply_wipe(&reply);
} else {
std::cout << "getClientList error" << std::endl;
}
return ret;
}
std::list<XWindow> XCBUtils::getClientListStacking()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list_stacking(&m_ewmh, m_screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (xcb_ewmh_get_client_list_stacking_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.windows_len; i++) {
ret.push_back(reply.windows[i]);
}
xcb_ewmh_get_windows_reply_wipe(&reply);
} else {
std::cout << "getClientListStacking error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMState(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (xcb_ewmh_get_wm_state_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMState error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMWindoType(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (xcb_ewmh_get_wm_window_type_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMWindoType error" << std::endl;
}
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMAllowedActions(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_allowed_actions(&m_ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atoms
if (xcb_ewmh_get_wm_allowed_actions_reply(&m_ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
xcb_ewmh_get_atoms_reply_wipe(&reply);
} else {
std::cout << xid << " getWMAllowedActions error" << std::endl;
}
return ret;
}
void XCBUtils::setWMAllowedActions(XWindow xid, std::vector<XCBAtom> actions)
{
XCBAtom list[MAXALLOWEDACTIONLEN] {0};
for (size_t i = 0; i < actions.size(); i++) {
list[i] = actions[i];
}
xcb_ewmh_set_wm_allowed_actions(&m_ewmh, xid, actions.size(), list);
}
std::string XCBUtils::getWMName(XWindow xid)
{
std::string ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(&m_ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply;
if (xcb_ewmh_get_wm_name_reply(&m_ewmh, cookie, &reply, nullptr)) {
ret.assign(reply.strings, reply.strings_len);
// 释放utf8_strings_reply分配的内存
xcb_ewmh_get_utf8_strings_reply_wipe(&reply);
} else {
std::cout << xid << " getWMName error" << std::endl;
}
return ret;
}
uint32_t XCBUtils::getWMPid(XWindow xid)
{
// NOTE(black_desk): code copy from https://gitlab.gnome.org/GNOME/metacity/-/merge_requests/13/diffs
XResClientIdSpec spec = {
.client = xid,
.mask = XRES_CLIENT_ID_PID_MASK,
};
std::shared_ptr<Display> dpy = {
XOpenDisplay(nullptr),
[](Display *p){ XCloseDisplay(p); },
};
long num_ids;
XResClientIdValue *client_ids;
XResQueryClientIds(dpy.get(),
1,
&spec,
&num_ids,
&client_ids);
pid_t pid = -1;
for (long i = 0; i < num_ids; i++) {
if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK) {
pid = XResGetClientPid(&client_ids[i]);
break;
}
}
XResClientIdsDestroy(num_ids, client_ids);
return pid;
}
std::string XCBUtils::getWMIconName(XWindow xid)
{
std::string ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name(&m_ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply;
if (!xcb_ewmh_get_wm_icon_name_reply(&m_ewmh, cookie, &reply, nullptr)) {
std::cout << xid << " getWMIconName error" << std::endl;
}
ret.assign(reply.strings);
return ret;
}
WMIcon XCBUtils::getWMIcon(XWindow xid)
{
WMIcon wmIcon{};
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon(&m_ewmh, xid);
xcb_ewmh_get_wm_icon_reply_t reply;
xcb_generic_error_t* error;
auto ret = xcb_ewmh_get_wm_icon_reply(&m_ewmh, cookie, &reply, &error);
if (error) {
std::cout << "failed to get wm icon" << error->error_code;
std::free(error);
return wmIcon;
}
if (ret) {
auto fcn = [](xcb_ewmh_wm_icon_iterator_t it) {
// https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm45582154990752
// The first two cardinals are width, height. Data is in rows, left to right and top to bottom
// Two cardinals means width and heighr, not offset.
const auto size = it.width * it.height;
std::vector<uint32_t> ret(size);
// data数据是按行从左至右从上至下排列
uint32_t *data = it.data;
if (!data) {
return ret;
}
std::copy_n(data, size, ret.begin());
return ret;
};
// 获取icon中size最大的图标
xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
xcb_ewmh_wm_icon_iterator_t wmIconIt{0, 0, nullptr};
for (; iter.rem; xcb_ewmh_get_wm_icon_next(&iter)) {
const uint32_t size = iter.width * iter.height;
if (size > 0 && size > wmIconIt.width * wmIconIt.height) {
wmIconIt = iter;
}
}
wmIcon = WMIcon{wmIconIt.width, wmIconIt.height, fcn(wmIconIt)};
xcb_ewmh_get_wm_icon_reply_wipe(&reply); // clear
}
return wmIcon;
}
XWindow XCBUtils::getWMClientLeader(XWindow xid)
{
XWindow ret = 0;
XCBAtom atom = getAtom("WM_CLIENT_LEADER");
void *value = getPropertyValue(xid, atom, XCB_ATOM_INTEGER);
if (value) {
ret = *(XWindow*)(value);
}
return ret;
}
void XCBUtils::requestCloseWindow(XWindow xid, uint32_t timestamp)
{
xcb_ewmh_request_close_window(&m_ewmh, m_screenNum, xid, timestamp, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER);
}
uint32_t XCBUtils::getWMDesktop(XWindow xid)
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_desktop_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMDesktop error" << std::endl;
}
return ret;
}
void XCBUtils::setWMDesktop(XWindow xid, uint32_t desktop)
{
xcb_ewmh_set_wm_desktop(&m_ewmh, xid, desktop);
}
void XCBUtils::setCurrentWMDesktop(uint32_t desktop)
{
xcb_ewmh_set_current_desktop(&m_ewmh, m_screenNum, desktop);
}
void XCBUtils::changeCurrentDesktop(uint32_t newDesktop, uint32_t timestamp)
{
xcb_ewmh_request_change_current_desktop(&m_ewmh, m_screenNum, newDesktop, timestamp);
}
uint32_t XCBUtils::getCurrentWMDesktop()
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop(&m_ewmh, m_screenNum);
if (!xcb_ewmh_get_current_desktop_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << "getCurrentWMDesktop error" << std::endl;
}
return ret;
}
bool XCBUtils::isGoodWindow(XWindow xid)
{
bool ret = false;
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xid);
xcb_generic_error_t **errStore = nullptr;
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, errStore);
if (reply) {
// 正常获取窗口geometry则判定为good
if (!errStore) {
ret = true;
} else {
free(errStore);
}
free(reply);
}
return ret;
}
// TODO XCB下无_MOTIF_WM_HINTS属性
MotifWMHints XCBUtils::getWindowMotifWMHints(XWindow xid)
{
XCBAtom atomWmHints = getAtom("_MOTIF_WM_HINTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, atomWmHints, atomWmHints, 0, 5);
std::unique_ptr<xcb_get_property_reply_t> reply(xcb_get_property_reply(m_connect, cookie, nullptr));
if (!reply || reply->format != 32 || reply->value_len != 5)
return MotifWMHints{0, 0, 0, 0, 0};
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply.get()));
MotifWMHints ret;
ret.flags = data[0];
ret.functions = data[1];
ret.decorations = data[2];
ret.inputMode = data[3];
ret.status = data[4];
return ret;
}
bool XCBUtils::hasXEmbedInfo(XWindow xid)
{
//XCBAtom atom = getAtom("_XEMBED_INFO");
return false;
}
XWindow XCBUtils::getWMTransientFor(XWindow xid)
{
XWindow ret;
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for(m_connect, xid);
if (!xcb_icccm_get_wm_transient_for_reply(m_connect, cookie, &ret, nullptr)) {
std::cout << xid << " getWMTransientFor error" << std::endl;
}
return ret;
}
uint32_t XCBUtils::getWMUserTime(XWindow xid)
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_user_time(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMUserTime error" << std::endl;
}
return ret;
}
int XCBUtils::getWMUserTimeWindow(XWindow xid)
{
XCBAtom ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_user_time_window(&m_ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_window_reply(&m_ewmh, cookie, &ret, nullptr)) {
std::cout << xid << " getWMUserTimeWindow error" << std::endl;
}
return ret;
}
WMClass XCBUtils::getWMClass(XWindow xid)
{
WMClass ret;
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class(m_connect, xid);
xcb_icccm_get_wm_class_reply_t reply;
reply.instance_name = nullptr;
reply.class_name = nullptr;
xcb_icccm_get_wm_class_reply(m_connect, cookie, &reply, nullptr); // 返回值为0不一定表示失败 故不做返回值判断
if (reply.class_name)
ret.className.assign(reply.class_name);
if (reply.instance_name)
ret.instanceName.assign(reply.instance_name);
if (reply.class_name || reply.instance_name) {
xcb_icccm_get_wm_class_reply_wipe(&reply);
}
return ret;
}
void XCBUtils::minimizeWindow(XWindow xid)
{
uint32_t data[2];
data[0] = XCB_ICCCM_WM_STATE_ICONIC;
data[1] = XCB_NONE;
xcb_ewmh_send_client_message(m_connect, xid, getRootWindow(),getAtom("WM_CHANGE_STATE"), 2, data);
flush();
}
void XCBUtils::maxmizeWindow(XWindow xid)
{
xcb_ewmh_request_change_wm_state(&m_ewmh
, m_screenNum
, xid
, XCB_EWMH_WM_STATE_ADD
, getAtom("_NET_WM_STATE_MAXIMIZED_VERT")
, getAtom("_NET_WM_STATE_MAXIMIZED_HORZ")
, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER);
}
// TODO
std::vector<std::string> XCBUtils::getWMCommand(XWindow xid)
{
std::vector<std::string> ret;
xcb_get_property_reply_t *reply = getPropertyValueReply(xid, XCB_ATOM_WM_COMMAND, m_ewmh.UTF8_STRING);
if (reply) {
ret = getUTF8StrsFromReply(reply);
free(reply);
}
return ret;
}
std::string XCBUtils::getUTF8StrFromReply(xcb_get_property_reply_t *reply)
{
std::string ret;
if (!reply || reply->format != 8) {
return ret;
}
char data[12] = {0};
for (uint32_t i=0; i < reply->value_len; i++) {
data[i] = char(reply->pad0[i]);
}
ret.assign(data);
return ret;
}
std::vector<std::string> XCBUtils::getUTF8StrsFromReply(xcb_get_property_reply_t *reply)
{
std::vector<std::string> ret;
if (!reply) {
return ret;
}
if (reply->format != 8) {
return ret;
}
// 字符串拆分
uint32_t start = 0;
for (uint32_t i=0; i < reply->value_len; i++) {
if (reply->pad0[i] == 0) {
char data[12] = {0};
int count = 0;
for (uint32_t j=start; j < i; j++)
data[count++] = char(reply->pad0[j]);
data[count] = 0;
ret.push_back(data);
}
}
return ret;
}
XWindow XCBUtils::getRootWindow()
{
XWindow rootWindow = 0;
/* Get the first screen */
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(m_connect)).data;
if (screen) {
rootWindow = screen->root;
}
std::cout << "getRootWinodw: " << rootWindow << std::endl;
return rootWindow;
}
void XCBUtils::registerEvents(XWindow xid, uint32_t eventMask)
{
uint32_t value[1] = {eventMask};
xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(m_connect,
xid,
XCB_CW_EVENT_MASK,
&value);
flush();
xcb_generic_error_t *error = xcb_request_check(m_connect, cookie);
if (error != nullptr) {
std::cout << "window " << xid << "registerEvents error" << std::endl;
}
}
AtomCache::AtomCache()
{
}
XCBAtom AtomCache::getVal(std::string name)
{
XCBAtom atom = ATOMNONE;
auto search = m_atoms.find(name);
if (search != m_atoms.end()) {
atom = search->second;
}
return atom;
}
std::string AtomCache::getName(XCBAtom atom)
{
std::string ret;
auto search = m_atomNames.find(atom);
if (search != m_atomNames.end()) {
ret = search->second;
}
return ret;
}
void AtomCache::store(std::string name, XCBAtom value)
{
m_atoms[name] = value;
m_atomNames[value] = name;
}

View File

@ -0,0 +1,276 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef XCBUTILS_H
#define XCBUTILS_H
#include <xcb/xproto.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>
#include <list>
#include <string>
#include <vector>
#include <map>
#define MAXLEN 0xffff
#define MAXALLOWEDACTIONLEN 256
#define ATOMNONE 0
typedef xcb_window_t XWindow ;
typedef xcb_atom_t XCBAtom;
typedef xcb_destroy_notify_event_t DestroyEvent;
typedef xcb_map_notify_event_t MapEvent;
typedef xcb_configure_notify_event_t ConfigureEvent;
typedef xcb_property_notify_event_t PropertyEvent;
typedef xcb_event_mask_t EventMask;
typedef struct {
std::string instanceName;
std::string className;
} WMClass;
typedef struct {
int16_t x, y;
uint16_t width, height;
} Geometry;
typedef struct {
uint32_t flags;
uint32_t functions;
uint32_t decorations;
int32_t inputMode;
uint32_t status;
} MotifWMHints;
typedef struct {
uint32_t width; /** Icon width */
uint32_t height; /** Icon height */
std::vector<uint32_t> data; /** Rows, left to right and top to bottom of the CARDINAL ARGB */
} WMIcon;
typedef struct WindowFrameExtents {
uint32_t Left;
uint32_t Right;
uint32_t Top;
uint32_t Bottom;
WindowFrameExtents(int left = 0, int right = 0, int top = 0, int bottom = 0): Left(left), Right(right), Top(top), Bottom(bottom) {}
bool isNull() { return Left == 0 && Right == 0 && Top == 0 && Bottom == 0;}
} WindowFrameExtents;
// 缓存atom减少X访问 TODO 加读写锁
class AtomCache {
public:
AtomCache();
XCBAtom getVal(std::string name);
std::string getName(XCBAtom atom);
void store(std::string name, XCBAtom value);
public:
std::map<std::string, XCBAtom> m_atoms;
std::map<XCBAtom, std::string> m_atomNames;
};
// XCB接口封装 参考getCurrentWMDesktop
class XCBUtils
{
XCBUtils();
XCBUtils(const XCBUtils &other);
XCBUtils & operator= (const XCBUtils &other);
~XCBUtils();
public:
static XCBUtils *instance() {
static XCBUtils instance;
return &instance;
}
/************************* xcb method ***************************/
// 分配XID
XWindow allocId();
// 刷新
void flush();
/************************* xpropto method ***************************/
// 杀掉进程
void killClientChecked(XWindow xid);
// 获取属性reply, 返回值必须free
xcb_get_property_reply_t *getPropertyValueReply(XWindow xid, XCBAtom property, XCBAtom type = XCB_ATOM_ATOM);
// 获取属性
void *getPropertyValue(XWindow xid, XCBAtom property, XCBAtom type = XCB_ATOM_ATOM);
// 获取字符串属性
std::string getUTF8PropertyStr(XWindow xid, XCBAtom property);
// 获取名称对应的Atom
XCBAtom getAtom(const char *name);
// 获取Atom对应的名称
std::string getAtomName(XCBAtom atom);
// 获取窗口矩形
Geometry getWindowGeometry(XWindow xid);
// 判断当前窗口是否正常
bool isGoodWindow(XWindow xid);
// 获取窗口
MotifWMHints getWindowMotifWMHints(XWindow xid);
bool hasXEmbedInfo(XWindow xid);
/************************* ewmh method ***************************/
// 获取活动窗口 _NET_ACTIVE_WINDOW
XWindow getActiveWindow();
// 设置活动窗口 _NET_ACTIVE_WINDOW 属性
void setActiveWindow(XWindow xid);
// 改变活动窗口
void changeActiveWindow(XWindow newActiveXid);
// 重新排列窗口
void restackWindow(XWindow xid);
// 获取窗口列表 _NET_CLIENT_LIST
std::list<XWindow> getClientList();
// 获取窗口列表 _NET_CLIENT_LIST_STACKING
std::list<XWindow> getClientListStacking();
// 获取窗口状态 _NET_WM_STATE
/*
_NET_WM_STATE_MODAL, ATOM
_NET_WM_STATE_STICKY, ATOM
_NET_WM_STATE_MAXIMIZED_VERT, ATOM
_NET_WM_STATE_MAXIMIZED_HORZ, ATOM
_NET_WM_STATE_SHADED, ATOM
_NET_WM_STATE_SKIP_TASKBAR, ATOM
_NET_WM_STATE_SKIP_PAGER, ATOM
_NET_WM_STATE_HIDDEN, ATOM
_NET_WM_STATE_FULLSCREEN, ATOM
_NET_WM_STATE_ABOVE, ATOM
_NET_WM_STATE_BELOW, ATOM
_NET_WM_STATE_DEMANDS_ATTENTION, ATOM
*/
std::vector<XCBAtom> getWMState(XWindow xid);
// 获取窗口类型 _NET_WM_WINDOW_TYPE
// Rationale: This hint is intended to replace the MOTIF hints.
// One of the objections to the MOTIF hints is that they are a purely visual description of the window decoration.
// By describing the function of the window, the Window Manager can apply consistent decoration and behavior to windows of the same type.
// Possible examples of behavior include keeping dock/panels on top or allowing pinnable menus / toolbars to only be hidden
// when another window has focus
/*
_NET_WM_WINDOW_TYPE_DESKTOP, ATOM
_NET_WM_WINDOW_TYPE_DOCK, ATOM
_NET_WM_WINDOW_TYPE_TOOLBAR, ATOM
_NET_WM_WINDOW_TYPE_MENU, ATOM
_NET_WM_WINDOW_TYPE_UTILITY, ATOM
_NET_WM_WINDOW_TYPE_SPLASH, ATOM
_NET_WM_WINDOW_TYPE_DIALOG, ATOM
_NET_WM_WINDOW_TYPE_DROPDOWN_MENU, ATOM
_NET_WM_WINDOW_TYPE_POPUP_MENU, ATOM
_NET_WM_WINDOW_TYPE_TOOLTIP, ATOM
_NET_WM_WINDOW_TYPE_NOTIFICATION, ATOM
_NET_WM_WINDOW_TYPE_COMBO, ATOM
_NET_WM_WINDOW_TYPE_DND, ATOM
_NET_WM_WINDOW_TYPE_NORMAL, ATOM
* */
std::vector<XCBAtom> getWMWindoType(XWindow xid);
// 获取窗口许可动作 _NET_WM_ALLOWED_ACTIONS
std::vector<XCBAtom> getWMAllowedActions(XWindow xid);
// 设置窗口许可动作
void setWMAllowedActions(XWindow xid, std::vector<XCBAtom> actions);
// 获取窗口名称 _NET_WM_NAME
std::string getWMName(XWindow xid);
// 获取窗口所属进程 _NET_WM_PID
uint32_t getWMPid(XWindow xid);
// 获取窗口图标 _NET_WM_ICON_NAME
std::string getWMIconName(XWindow xid);
// 获取窗口图标信息 _NET_WM_ICON
WMIcon getWMIcon(XWindow xid);
// WM_CLIENT_LEADER
XWindow getWMClientLeader(XWindow xid);
// 关闭窗口 _NET_CLOSE_WINDOW
void requestCloseWindow(XWindow xid, uint32_t timestamp);
// 获取窗口对应桌面 _NET_WM_DESKTOP
uint32_t getWMDesktop(XWindow xid);
// 设置窗口当前桌面
void setWMDesktop(XWindow xid, uint32_t desktop);
// 设置当前桌面属性
void setCurrentWMDesktop(uint32_t desktop);
// 请求改变当前桌面
void changeCurrentDesktop(uint32_t newDesktop, uint32_t timestamp);
// 获取当前桌面 _NET_CURRENT_DESKTOP
uint32_t getCurrentWMDesktop();
/************************* icccm method ***************************/
// The WM_TRANSIENT_FOR hint of the ICCCM allows clients to specify that a toplevel window may be closed before the client finishes.
// A typical example of a transient window is a dialog.
// Some dialogs can be open for a long time, while the user continues to work in the main window.
// Other dialogs have to be closed before the user can continue to work in the main window
XWindow getWMTransientFor(XWindow xid);
uint32_t getWMUserTime(XWindow xid);
int getWMUserTimeWindow(XWindow xid);
// 获取窗口类型
WMClass getWMClass(XWindow xid);
// 最小化窗口
void minimizeWindow(XWindow xid);
// 最大化窗口
void maxmizeWindow(XWindow xid);
/************************* other method ***************************/
// 获取窗口command
std::vector<std::string> getWMCommand(XWindow xid);
// 解析属性为UTF8格式字符串
std::string getUTF8StrFromReply(xcb_get_property_reply_t *reply);
// 解析属性为UTF8格式字符串字符数组
std::vector<std::string> getUTF8StrsFromReply(xcb_get_property_reply_t *reply);
// 获取根窗口
XWindow getRootWindow();
// 注册事件
void registerEvents(XWindow xid, uint32_t eventMask);
private:
XWindow getDecorativeWindow(XWindow xid);
WindowFrameExtents getWindowFrameExtents(XWindow xid);
private:
xcb_connection_t *m_connect;
int m_screenNum;
xcb_ewmh_connection_t m_ewmh;
AtomCache m_atomCache; // 和ewmh中Atom类型存在重复部分扩张了自定义类型
};
#endif // XCBUTILS_H

View File

@ -5,12 +5,7 @@
#ifndef DBUSUTIL_H
#define DBUSUTIL_H
#include "dockinterface.h"
#include "entryinterface.h"
using DockInter = org::deepin::dde::daemon::DdeDock;
using DockEntryInter = org::deepin::dde::daemon::dock::DockEntry;
#include <QString>
const QString xEventMonitorService = "org.deepin.dde.XEventMonitor1";
const QString xEventMonitorPath = "/org/deepin/dde/XEventMonitor1";
@ -31,14 +26,4 @@ const QString sessionManagerService = "org.deepin.dde.SessionManager1";
const QString sessionManagerPath = "/org/deepin/dde/SessionManager1";
const QString sessionManagerInterface = "org.deepin.dde.SessionManager1";
inline const QString dockServiceName()
{
return QString("org.deepin.dde.daemon.Dock1");
}
inline const QString dockServicePath()
{
return QString("/org/deepin/dde/daemon/Dock1");
}
#endif // DBUSUTIL_H

View File

@ -28,14 +28,13 @@ void DockSettings::init()
if (m_dockSettings) {
connect(m_dockSettings, &DConfig::valueChanged, this, [&] (const QString &key) {
if (key == keyHideMode) {
Q_EMIT
Q_EMIT hideModeChanged(HideModeHandler(m_dockSettings->value(keyHideMode).toString()).toEnum());
} else if(key == keyDisplayMode) {
Q_EMIT displayModeChanged(DisplayMode(DisplayModeHandler(m_dockSettings->value(key).toString()).toEnum()));
} else if (key == keyPosition) {
Q_EMIT positionModeChanged(Position(PositionModeHandler(m_dockSettings->value(key).toString()).toEnum()));
} else if (key == keyForceQuitApp){
QString mode = m_dockSettings->value(key).toString();
Q_EMIT forceQuitAppChanged(ForceQuitAppModeHandler(mode).toEnum());
Q_EMIT forceQuitAppChanged(ForceQuitAppModeHandler(m_dockSettings->value(key).toString()).toEnum());
} else if (key == keyShowRecent) {
Q_EMIT showRecentChanged(m_dockSettings->value(key).toBool());
} else if (key == keyShowMultiWindow) {
@ -50,8 +49,6 @@ void DockSettings::init()
Q_EMIT windowSizeFashionChanged(m_dockSettings->value(keyWindowSizeFashion).toUInt());
} else if ( key == keyWindowSizeEfficient) {
Q_EMIT windowSizeEfficientChanged(m_dockSettings->value(keyWindowSizeEfficient).toUInt());
} else if ( key == keyOpacity) {
Q_EMIT opacityChanged(m_dockSettings->value(keyOpacity).toDouble());
}
});
}
@ -249,15 +246,6 @@ void DockSettings::setRecentApps(const QStringList &apps)
saveStringList(keyRecentApp, apps);
}
double DockSettings::getOpacity()
{
double opacity = 0.4;
// if (m_appearanceSettings) {
// opacity = m_appearanceSettings->value(keyOpacity).toDouble();
// }
return opacity;
}
QVector<QString> DockSettings::getWinIconPreferredApps()
{
QVector<QString> ret;

View File

@ -205,7 +205,6 @@ public:
void setDockedApps(const QStringList &apps);
QStringList getRecentApps() const;
void setRecentApps(const QStringList &apps);
double getOpacity();
QVector<QString> getWinIconPreferredApps();
void setShowRecent(bool visible);
bool showRecent() const;
@ -257,8 +256,6 @@ Q_SIGNALS:
void windowSizeFashionChanged(uint size);
// 高效模式dock尺寸改变
void windowSizeEfficientChanged(uint size);
// 透明度改变
void opacityChanged(double opacity);
private:
DockSettings(QObject *paret = nullptr);

View File

@ -31,6 +31,7 @@
const QString MonitorsSwitchTime = "monitorsSwitchTime";
const QString OnlyShowPrimary = "onlyShowPrimary";
const double DEFAULTOPACITY = 0.4;
#define DIS_INS DisplayManager::instance()
#define DOCK_SCREEN DockScreen::instance()
@ -306,7 +307,7 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor()
const static int flags = Motion | Button | Key;
const static int monitorHeight = static_cast<int>(15 * qApp->devicePixelRatio());
// 后端认为的任务栏大小(无缩放因素影响)
const int realDockSize = int((m_displayMode == DisplayMode::Fashion ? (int)m_windowFashionSize + 2 * 10 /*上下的边距各10像素*/ : (int)m_windowFashionSize) * qApp->devicePixelRatio());
const int realDockSize = int((m_displayMode == DisplayMode::Fashion ? m_windowFashionSize + 20 : m_windowEfficientSize) * qApp->devicePixelRatio());
// 任务栏唤起区域
m_monitorRectList.clear();
@ -541,6 +542,9 @@ void MultiScreenWorker::initMembers()
m_delayWakeTimer->setSingleShot(true);
m_windowFashionSize = int(DockSettings::instance()->getWindowSizeFashion() * qApp->devicePixelRatio());
m_windowEfficientSize = int(DockSettings::instance()->getWindowSizeEfficient() * qApp->devicePixelRatio());
setStates(LauncherDisplay, m_launcherInter->isValid() ? m_launcherInter->visible() : false);
// init check
@ -553,6 +557,7 @@ void MultiScreenWorker::initConnection()
connect(DIS_INS, &DisplayManager::screenInfoChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo);
connect(m_launcherInter, static_cast<void (DBusLuncher::*)(bool) const>(&DBusLuncher::VisibleChanged), this, [ = ](bool value) { setStates(LauncherDisplay, value); });
connect(m_appearanceInter, &Appearance::OpacityChanged, this, &MultiScreenWorker::onOpacityChanged);
connect(this, &MultiScreenWorker::requestUpdatePosition, this, &MultiScreenWorker::onRequestUpdatePosition);
connect(this, &MultiScreenWorker::requestUpdateMonitorInfo, this, &MultiScreenWorker::onRequestUpdateMonitorInfo);
@ -570,7 +575,7 @@ void MultiScreenWorker::initConnection()
connect(DockSettings::instance(), &DockSettings::positionModeChanged, this, &MultiScreenWorker::onPositionChanged);
connect(DockSettings::instance(), &DockSettings::displayModeChanged, this, &MultiScreenWorker::onDisplayModeChanged);
connect(DockSettings::instance(), &DockSettings::hideModeChanged, this, &MultiScreenWorker::onHideModeChanged);
// connect(DockSettings::instance(), &DockSettings::hideStateChange, this, &MultiScreenWorker::onHideStateChanged);
connect(TaskManager::instance(), &TaskManager::hideStateChanged, this, &MultiScreenWorker::onHideStateChanged);
}
void MultiScreenWorker::initDockMode()
@ -578,8 +583,8 @@ void MultiScreenWorker::initDockMode()
onPositionChanged(DockSettings::instance()->getPositionMode());
onDisplayModeChanged(DockSettings::instance()->getDisplayMode());
onHideModeChanged(DockSettings::instance()->getHideMode());
// onHideStateChanged(m_dockInter->hideState());
onOpacityChanged(DockSettings::instance()->getOpacity());
onHideStateChanged(TaskManager::instance()->getHideState());
onOpacityChanged(m_appearanceInter? m_appearanceInter->opacity(): DEFAULTOPACITY);
DockItem::setDockPosition(m_position);
qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position));
@ -674,7 +679,7 @@ void MultiScreenWorker::resetDockScreen()
bool MultiScreenWorker::isCursorOut(int x, int y)
{
const int realDockSize = int((m_displayMode == DisplayMode::Fashion ? (int)m_windowFashionSize + 2 * 10 /*上下的边距各10像素*/ : (int)m_windowEfficientSize) * qApp->devicePixelRatio());
const int realDockSize = int((m_displayMode == DisplayMode::Fashion ? m_windowFashionSize : m_windowEfficientSize) * qApp->devicePixelRatio());
for (auto s : DIS_INS->screens()) {
// 屏幕此位置不可停靠时,不用监听这块区域
if (!DIS_INS->canDock(s, m_position))

View File

@ -83,7 +83,7 @@ MainPanelControl::MainPanelControl(QWidget *parent)
, m_recentHelper(new RecentAppHelper(m_appAreaSonWidget, m_recentAreaWidget, this))
, m_toolHelper(new ToolAppHelper(m_toolSonAreaWidget, this))
, m_multiHelper(new MultiWindowHelper(m_appAreaSonWidget, m_multiWindowWidget, this))
, m_showRecent(false)
, m_showRecent(DockSettings::instance()->showRecent())
{
initUI();
initConnection();
@ -723,6 +723,8 @@ void MainPanelControl::mousePressEvent(QMouseEvent *e)
void MainPanelControl::startDrag(DockItem *dockItem)
{
// 每次拖动使m_dragIndex==-1, 表明当前item的位置未发生变化
m_dragIndex = -1;
QPointer<DockItem> item = dockItem;
const QPixmap pixmap = item->grab();

View File

@ -186,12 +186,6 @@ TrayGridWidget::TrayGridWidget(QWidget *parent)
{
initMember();
setAttribute(Qt::WA_TranslucentBackground);
connect(DockSettings::instance(), &DockSettings::opacityChanged, this, [=] (double opacity) {
m_maskAlpha = static_cast<int> (opacity);
});
QMetaObject::invokeMethod(this, [=] {
m_maskAlpha = static_cast<int> (DockSettings::instance()->getOpacity());
});
}
void TrayGridWidget::setPosition(const Dock::Position &position)
@ -313,7 +307,7 @@ void TrayGridWidget::initMember()
QColor TrayGridWidget::maskColor() const
{
QColor color = DGuiApplicationHelper::standardPalette(DGuiApplicationHelper::instance()->themeType()).window().color();
color.setAlpha(m_maskAlpha);
color.setAlpha(0);
return color;
}

View File

@ -75,7 +75,6 @@ private:
TrayGridView *m_referGridView;
Dtk::Gui::DRegionMonitor *m_regionInter;
static Dock::Position m_position;
int m_maskAlpha;
};
#endif // EXPANDICONWIDGET_H

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "mainwindow.h"
#include "taskmanager/entry.h"
#include "windowmanager.h"
#include "traymainwindow.h"
#include "multiscreenworker.h"
@ -675,8 +676,7 @@ void WindowManager::onRequestUpdateFrontendGeometry()
}
}
DockInter dockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus());
dockInter.SetFrontendWindowRect(x, y, uint(rect.width()), uint(rect.height()));
TaskManager::instance()->setFrontendWindowRect(x, y, uint(rect.width()), uint(rect.height()));
}
void WindowManager::onRequestNotifyWindowManager()

View File

@ -3,8 +3,6 @@ set(PLUGIN_NAME "onboard")
project(${PLUGIN_NAME})
generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface)
# Sources files
file(GLOB_RECURSE SRCS "*.h"
"*.cpp"
@ -25,8 +23,7 @@ set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../)
target_include_directories(${PLUGIN_NAME} PUBLIC ${Qt5DBus_INCLUDE_DIRS}
../../interfaces
../../frame/qtdbusextended
./dbusinterface/generation_dbus_interface)
../../frame/qtdbusextended)
target_link_libraries(${PLUGIN_NAME} PRIVATE
${DtkWidget_LIBRARIES}

View File

@ -1,38 +0,0 @@
// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "arealist.h"
bool MonitRect::operator ==(const MonitRect &rect)
{
return x1 == rect.x1 && y1 == rect.y1 && x2 == rect.x2 && y2 == rect.y2;
}
QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect)
{
arg.beginStructure();
arg << rect.x1 << rect.y1 << rect.x2 << rect.y2;
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect)
{
arg.beginStructure();
arg >> rect.x1 >> rect.y1 >> rect.x2 >> rect.y2;
arg.endStructure();
return arg;
}
void registerAreaListMetaType()
{
qRegisterMetaType<MonitRect>("MonitRect");
qDBusRegisterMetaType<MonitRect>();
qRegisterMetaType<AreaList>("AreaList");
qDBusRegisterMetaType<AreaList>();
}

View File

@ -1,32 +0,0 @@
// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef AREALIST_H
#define AREALIST_H
#include <QDBusMetaType>
#include <QRect>
#include <QList>
struct MonitRect {
int x1;
int y1;
int x2;
int y2;
bool operator ==(const MonitRect& rect);
};
typedef QList<MonitRect> AreaList;
Q_DECLARE_METATYPE(MonitRect)
Q_DECLARE_METATYPE(AreaList)
QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect);
const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect);
void registerAreaListMetaType();
#endif // AREALIST_H

View File

@ -1,8 +0,0 @@
<interface name="org.deepin.dde.daemon.Dock1.Entry">
<method name="Activate">
<arg type="u" direction="in"></arg>
</method>
<property name="Id" type="s" access="read"></property>
<property name="IsActive" type="b" access="read"></property>
<property name="Name" type="s" access="read"></property>
</interface>

View File

@ -1,3 +0,0 @@
<interface name="org.deepin.dde.daemon.Dock1">
<property name="Entries" type="ao" access="read"/>
</interface>

View File

@ -6,9 +6,6 @@
#include "onboardplugin.h"
#include "../widgets/tipswidget.h"
#include "org_deepin_dde_daemon_dock1.h"
#include "org_deepin_dde_daemon_dock1_entry.h"
#include <DGuiApplicationHelper>
#include <QIcon>
@ -19,12 +16,6 @@
DGUI_USE_NAMESPACE
using DBusDock = org::deepin::dde::daemon::Dock1;
using DockEntryInter = org::deepin::dde::daemon::dock1::Entry;
static const QString serviceName = QString("org.deepin.dde.daemon.Dock1");
static const QString servicePath = QString("/org/deepin/dde/daemon/Dock1");
using namespace Dock;
OnboardPlugin::OnboardPlugin(QObject *parent)
: QObject(parent)
@ -117,15 +108,6 @@ void OnboardPlugin::invokedMenuItem(const QString &itemKey, const QString &menuI
process->start("onboard-settings", QStringList());
}
DBusDock DockInter(serviceName, servicePath, QDBusConnection::sessionBus(), this);
for (auto entry : DockInter.entries()) {
DockEntryInter AppInter(serviceName, entry.path(), QDBusConnection::sessionBus(), this);
if(AppInter.name() == "Onboard-Settings" && !AppInter.isActive()) {
AppInter.Activate(0);
break;
}
}
}
void OnboardPlugin::displayModeChanged(const Dock::DisplayMode displayMode)

View File

@ -40,7 +40,7 @@ public:
DockPluginController::DockPluginController(PluginProxyInterface *proxyInter, QObject *parent)
: QObject(parent)
, m_dbusDaemonInterface(QDBusConnection::sessionBus().interface())
, m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
// , m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
, m_proxyInter(proxyInter)
{
qApp->installEventFilter(this);
@ -48,7 +48,7 @@ DockPluginController::DockPluginController(PluginProxyInterface *proxyInter, QOb
refreshPluginSettings();
connect(DockSettings::instance(), &DockSettings::quickPluginsChanged, this, &DockPluginController::onConfigChanged);
connect(m_dockDaemonInter, &DockInter::PluginSettingsSynced, this, &DockPluginController::refreshPluginSettings, Qt::QueuedConnection);
// connect(m_dockDaemonInter, &DockInter::PluginSettingsSynced, this, &DockPluginController::refreshPluginSettings, Qt::QueuedConnection);
}
DockPluginController::~DockPluginController()
@ -327,7 +327,7 @@ void DockPluginController::savePluginValue(PluginsItemInterface * const itemInte
}
m_pluginSettingsObject.insert(itemInter->pluginName(), localObject);
m_dockDaemonInter->MergePluginSettings(QJsonDocument(remoteObject).toJson(QJsonDocument::JsonFormat::Compact));
DockSettings::instance()->mergePluginSettings(QJsonDocument(remoteObject).toJson(QJsonDocument::JsonFormat::Compact));
}
const QVariant DockPluginController::getPluginValue(PluginsItemInterface * const itemInter, const QString &key, const QVariant &fallback)
@ -353,7 +353,7 @@ void DockPluginController::removePluginValue(PluginsItemInterface * const itemIn
m_pluginSettingsObject.insert(itemInter->pluginName(), localObject);
}
m_dockDaemonInter->RemovePluginSettings(itemInter->pluginName(), keyList);
DockSettings::instance()->removePluginSettings(itemInter->pluginName(), keyList);
}
void DockPluginController::startLoadPlugin(const QStringList &dirs)
@ -576,7 +576,7 @@ void DockPluginController::initPlugin(PluginsItemInterface *interface)
void DockPluginController::refreshPluginSettings()
{
const QString &pluginSettings = m_dockDaemonInter->GetPluginSettings().value();
const QString &pluginSettings = DockSettings::instance()->getPluginSettings();
if (pluginSettings.isEmpty()) {
qDebug() << "Error! get plugin settings from dbus failed!";
return;
@ -604,9 +604,9 @@ void DockPluginController::refreshPluginSettings()
}
// not notify plugins to refresh settings if this update is not emit by dock daemon
if (sender() != m_dockDaemonInter) {
return;
}
// if (sender() != m_dockDaemonInter) {
// return;
// }
// notify all plugins to reload plugin settings
for (PluginsItemInterface *pluginInter : m_pluginsMap.keys()) {

View File

@ -84,7 +84,6 @@ private Q_SLOTS:
private:
QDBusConnectionInterface *m_dbusDaemonInterface;
DockInter *m_dockDaemonInter;
// interface, "pluginloader", PluginLoader指针对象
QMap<PluginsItemInterface *, QMap<QString, QObject *>> m_pluginsMap;