feat: 实现Apps服务、Launcher服务、Dock服务

*重写Apps服务,新服务分为org.deepin.daemon.DFWatcher1和org.deepin.daemon.ALRecorder1两个服务
*重写Launcher服务, 新服务名为org.deepin.dde.daemon.Launcher1
*重写Dock服务, 新服务名为org.deepin.dde.daemon.Dock1
*重写部分go-lib接口,保存在src/lib目录, 后续从项目中提出统一存放至开发库
*使用XCB库实现与XServer交互,存放在src/lib目录
*放弃依赖dde-qt-dbus-factory包, 将xml文件生成的静态编译代码存放在frameworkdbus目录

Log: 实现Apps服务、Launcher服务、Dock服务
Task: https://pms.uniontech.com/task-view-109315.html
Influence: 无
Change-Id: Ia9676060bfe81ce8d02c48972cc3d3cbaf665a31
This commit is contained in:
Li Xi 2022-04-24 14:52:13 +08:00 committed by weizhixiang
parent dd7d4737bf
commit 13a1cabda1
118 changed files with 18347 additions and 3 deletions

7
debian/control vendored
View File

@ -10,6 +10,12 @@ Build-Depends:
qt5-qmake,
qtbase5-dev,
qttools5-dev,
libdtkcore-dev (>=5.4.14),
libdtkcore5-bin (>=5.4.14),
libxcb1-dev,
libxcb-icccm4-dev,
libxcb-ewmh-dev,
libx11-dev,
Standards-Version: 4.1.3
Homepage: https://www.deepin.org
@ -20,3 +26,4 @@ Depends:
${shlibs:Depends},
Description: dde application manager module
Application manager for DDE.

View File

@ -1 +1,3 @@
add_subdirectory(systemd)
add_subdirectory(systemd)
add_subdirectory(dconf)

View File

@ -0,0 +1,7 @@
set(DCONFIG_FILES
com.deepin.dde.launcher.json
com.deepin.dde.dock.json
com.deepin.dde.appearance.json
)
install(FILES ${DCONFIG_FILES} DESTINATION /usr/share/dsg/configs/dde-application-manager)

View File

@ -0,0 +1,145 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"Extra_Picture_Uris": {
"serial": 0,
"flags": ["global"],
"name": "Extra_Picture_Uris",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Font_Standard": {
"value": "Noto Sans",
"serial": 0,
"flags": ["global"],
"name": "Font_Standard",
"name[zh_CN]": "*****",
"description": "The standard font for desktop",
"permissions": "readwrite",
"visibility": "private"
},
"Theme_Auto": {
"value": false,
"serial": 0,
"flags": ["global"],
"name": "Theme_Auto",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Wallpaper_Slideshow": {
"value": "",
"serial": 0,
"flags": ["global"],
"name": "Wallpaper_Slideshow",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Cursor_Theme": {
"value": "bloom",
"serial": 0,
"flags": ["global"],
"name": "Cursor_Theme",
"name[zh_CN]": "*****",
"description": "Cursor theme name. Used only by Xservers that support the Xcursor extension.",
"permissions": "readwrite",
"visibility": "private"
},
"Font_Size": {
"value": 10.5,
"serial": 0,
"flags": ["global"],
"name": "Font_Size",
"name[zh_CN]": "*****",
"description": "The desktop font size",
"permissions": "readwrite",
"visibility": "private"
},
"Wallpaper_Uris": {
"value": "",
"serial": 0,
"flags": ["global"],
"name": "Wallpaper_Uris",
"name[zh_CN]": "*****",
"description": "wallpaper json string",
"permissions": "readwrite",
"visibility": "private"
},
"Icon_Theme": {
"value": "bloom",
"serial": 0,
"flags": ["global"],
"name": "Icon_Theme",
"name[zh_CN]": "*****",
"description": "Icon theme to use for the panel, nautilus etc.",
"permissions": "readwrite",
"visibility": "private"
},
"Opacity": {
"value": 0.40000000000000002,
"serial": 0,
"flags": ["global"],
"name": "Opacity",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Font_Monospace": {
"value": "Noto Mono",
"serial": 0,
"flags": ["global"],
"name": "Font_Monospace",
"name[zh_CN]": "*****",
"description": "The monospace font for desktop",
"permissions": "readwrite",
"visibility": "private"
},
"Excluded_Icon_Themes": {
"value": ["hicolor", "gnome", "Adwaita"],
"serial": 0,
"flags": ["global"],
"name": "Excluded_Icon_Themes",
"name[zh_CN]": "*****",
"description": "Icon theme black list.",
"permissions": "readwrite",
"visibility": "private"
},
"Gtk_Theme": {
"value": "deepin",
"serial": 0,
"flags": ["global"],
"name": "Gtk_Theme",
"name[zh_CN]": "*****",
"description": "Basename of the default theme used by gtk+.",
"permissions": "readwrite",
"visibility": "private"
},
"Sound_Theme": {
"value": "deepin",
"serial": 0,
"flags": ["global"],
"name": "Sound_Theme",
"name[zh_CN]": "*****",
"description": "Set the system sound theme",
"permissions": "readwrite",
"visibility": "private"
},
"Background_Uris": {
"value": ["file:///usr/share/backgrounds/default_background.jpg"],
"serial": 0,
"flags": ["global"],
"name": "Background_Uris",
"name[zh_CN]": "*****",
"description": "Note that the backend only supports local (file://) URIs.",
"permissions": "readwrite",
"visibility": "private"
}
}
}

View File

@ -0,0 +1,146 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"Window_Size_Fashion": {
"value": 48,
"serial": 0,
"flags": ["global"],
"name": "Window_Size_Fashion",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Icon_Size": {
"value": 36,
"serial": 0,
"flags": ["global"],
"name": "Icon_Size",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Position": {
"value": "bottom",
"serial": 0,
"flags": ["global"],
"name": "Position",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Wireless_Scan_Interval": {
"value": 5,
"serial": 0,
"flags": ["global"],
"name": "Wireless_Scan_Interval",
"name[zh_CN]": "*****",
"description": "wireless scan interval",
"permissions": "readwrite",
"visibility": "private"
},
"Hide_Timeout": {
"value": 0,
"serial": 0,
"flags": ["global"],
"name": "Hide_Timeout",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Hide_Mode": {
"value": "keep-showing",
"serial": 0,
"flags": ["global"],
"name": "Hide_Mode",
"name[zh_CN]": "*****",
"description": "The value will influence when the dock is shown or hidden.",
"permissions": "readwrite",
"visibility": "private"
},
"Show_Timeout": {
"value": 100,
"serial": 0,
"flags": ["global"],
"name": "Show_Timeout",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Window_Size_Efficient": {
"value": 40,
"serial": 0,
"flags": ["global"],
"name": "Window_Size_Efficient",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Plugin_Settings": {
"value": "{}",
"serial": 0,
"flags": ["global"],
"name": "Plugin_Settings",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Docked_Apps": {
"value": ["/S@dde-file-manager", "/S@uos-browser", "/S@org.deepin.browser", "/S@deepin-appstore", "/S@deepin-app-store", "/S@com.deepin.store.intranet", "/S@deepin-album", "/S@deepin-music", "/S@deepin-contacts", "/S@dde-calendar", "/S@dde-control-center"],
"serial": 0,
"flags": ["global"],
"name": "Docked_Apps",
"name[zh_CN]": "*****",
"description": "The default apps which is docked when dock is started.",
"permissions": "readwrite",
"visibility": "private"
},
"Win_Icon_Preferred_Apps": {
"value": ["apps.com.qq.im", "deepin.com.qq.im", "apps.com.qq.im.light", "apps.com.qq.b.eim", "apps.com.qq.rtxclient"],
"serial": 0,
"flags": ["global"],
"name": "Win_Icon_Preferred_Apps",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Delay_Plugins_Time": {
"value": 0,
"serial": 0,
"flags": ["global"],
"name": "Delay_Plugins_Time",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Force_Quit_App": {
"value": "enabled",
"serial": 0,
"flags": ["global"],
"name": "Force_Quit_App",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Display_Mode": {
"value": "efficient",
"serial": 0,
"flags": ["global"],
"name": "Display_Mode",
"name[zh_CN]": "*****",
"description": "The dock gets different display mode, for instance, dock looks like win7 taskbar on classic mode.",
"permissions": "readwrite",
"visibility": "private"
}
}
}

View File

@ -0,0 +1,246 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"Apps_Can_Not_Start_Up_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Can_Not_Start_Up_List",
"name[zh_CN]": "*****",
"description": "apps not allowed to start up",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Order_Zh_Cn": {
"value": ["uos-browser", "org.deepin.browser", "dde-file-manager", "deepin-app-store", "deepin-appstore", "deepin-music", "deepin-movie", "deepin-screen-recorder", "deepin-image-viewer", "deepin-album", "deepin-draw", "deepin-reader", "deepin-editor", "deepin-mail", "thunderbird", "deepin-terminal", "terminal", "org.gnome.Terminal", "deepin-contacts", "deepin-voice-note", "downloader", "deepin-manual", "org.deepin.scanner", "org.deepin.scaner", "dde-computer", "dde-trash", "deepin-defender", "dde-control-center", "chineseime-setting", "fcitx-config-gtk3", "chineseime-setting-wizard", "deepin-system-monitor", "deepin-boot-maker", "deepin-devicemanager", "deepin-log-viewer", "dde-printer", "dde-calendar", "deepin-calculator", "deepin-font-manager", "deepin-compressor", "deepin-deb-installer", "deepin-diskmanager", "dde-introduction", "uos-service-support", "uos-remote-assistance", "deepin-camera", "deepin-phone-master", "gparted", "org.gnome.Cheese", "Cheese", "gnome.Cheese"],
"serial": 0,
"flags": ["global"],
"name": "Apps_Order_Zh_Cn",
"name[zh_CN]": "*****",
"description": "launcher apps order, ensure that all lowercase.",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Icon_Ratio": {
"value": 0.5,
"serial": 0,
"flags": ["global"],
"name": "Apps_Icon_Ratio",
"name[zh_CN]": "*****",
"description": "(null)",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Can_Not_Use_Proxy_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Can_Not_Use_Proxy_List",
"name[zh_CN]": "*****",
"description": "apps disable use proxy menu",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Start_Up_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Start_Up_List",
"name[zh_CN]": "*****",
"description": "apps hide function start up",
"permissions": "readwrite",
"visibility": "private"
},
"Fullscreen": {
"value": false,
"serial": 0,
"flags": ["global"],
"name": "Fullscreen",
"name[zh_CN]": "*****",
"description": "(null)",
"permissions": "readwrite",
"visibility": "private"
},
"Mini_Frame_Right_Bar_Hide_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Mini_Frame_Right_Bar_Hide_List",
"name[zh_CN]": "*****",
"description": "icons not allowed to show on mini frame right bar",
"permissions": "readwrite",
"visibility": "private"
},
"Auto_Exit": {
"value": false,
"serial": 0,
"flags": ["global"],
"name": "Auto_Exit",
"name[zh_CN]": "*****",
"description": "(null)",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Order_Zh_Tw": {
"value": ["uos-browser", "org.deepin.browser", "dde-file-manager", "deepin-app-store", "deepin-appstore", "deepin-music", "deepin-movie", "deepin-screen-recorder", "deepin-image-viewer", "deepin-album", "deepin-draw", "deepin-reader", "deepin-editor", "deepin-mail", "thunderbird", "deepin-terminal", "terminal", "org.gnome.Terminal", "deepin-contacts", "deepin-voice-note", "downloader", "deepin-manual", "org.deepin.scanner", "org.deepin.scaner", "dde-computer", "dde-trash", "deepin-defender", "dde-control-center", "chineseime-setting", "fcitx-config-gtk3", "chineseime-setting-wizard", "deepin-system-monitor", "deepin-boot-maker", "deepin-devicemanager", "deepin-log-viewer", "dde-printer", "dde-calendar", "deepin-calculator", "deepin-font-manager", "deepin-compressor", "deepin-deb-installer", "deepin-diskmanager", "dde-introduction", "uos-service-support", "uos-remote-assistance", "deepin-camera", "deepin-phone-master", "gparted", "org.gnome.Cheese", "Cheese", "gnome.Cheese"],
"serial": 0,
"flags": ["global"],
"name": "Apps_Order_Zh_Tw",
"name[zh_CN]": "*****",
"description": "launcher apps order, ensure that all lowercase.",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Can_Not_Send_To_Dock_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Can_Not_Send_To_Dock_List",
"name[zh_CN]": "*****",
"description": "apps not allowed to send to Dock",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Can_Not_Send_To_Desktop_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Can_Not_Send_To_Desktop_List",
"name[zh_CN]": "*****",
"description": "apps not allowed to send to Desktop",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Send_To_Desktop_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Send_To_Desktop_List",
"name[zh_CN]": "*****",
"description": "apps hide function send to desktop",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hold_List": {
"value": ["dde-introduction", "dde-file-manager", "deepin-appstore", "deepin-app-store", "deepin-terminal", "deepin-manual", "dde-computer", "dde-trash", "deepin-defender", "dde-control-center", "fcitx-config-gtk3", "fcitx-configtool", "deepin-system-monitor", "deepin-devicemanager", "dde-printer", "dde-calendar", "uos-service-support", "deepin-toggle-desktop", "deepin-wm-multitaskingview", "kwin-wm-multitaskingview", "com.deepin.store.intranet", "chineseime-setting"],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hold_List",
"name[zh_CN]": "*****",
"description": "apps not allowed to uninstall",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Open_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Open_List",
"name[zh_CN]": "*****",
"description": "apps hide function open",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Can_Not_Open_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Can_Not_Open_List",
"name[zh_CN]": "*****",
"description": "apps not allowed to open",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Use_Proxy": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Use_Proxy",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Search_Package_Name": {
"value": false,
"serial": 0,
"flags": ["global"],
"name": "Search_Package_Name",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Order": {
"value": ["uos-browser", "org.deepin.browser", "dde-file-manager", "deepin-app-store", "deepin-appstore", "deepin-music", "deepin-movie", "deepin-screen-recorder", "deepin-image-viewer", "deepin-album", "deepin-draw", "deepin-reader", "deepin-editor", "deepin-mail", "thunderbird", "deepin-terminal", "terminal", "org.gnome.Terminal", "deepin-contacts", "deepin-voice-note", "downloader", "deepin-manual", "org.deepin.scanner", "org.deepin.scaner", "dde-computer", "dde-trash", "deepin-defender", "dde-control-center", "chineseime-setting", "fcitx-config-gtk3", "chineseime-setting-wizard", "deepin-system-monitor", "deepin-boot-maker", "deepin-devicemanager", "deepin-log-viewer", "dde-printer", "dde-calendar", "deepin-calculator", "deepin-font-manager", "deepin-compressor", "deepin-deb-installer", "deepin-diskmanager", "dde-introduction", "uos-service-support", "uos-remote-assistance", "deepin-camera", "deepin-phone-master", "gparted", "org.gnome.Cheese", "Cheese", "gnome.Cheese"],
"serial": 0,
"flags": ["global"],
"name": "Apps_Order",
"name[zh_CN]": "*****",
"description": "launcher apps order, ensure that all lowercase.",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Use_Proxy_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Use_Proxy_List",
"name[zh_CN]": "*****",
"description": "apps hide use proxy menu",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Disable_Scaling": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Disable_Scaling",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hidden": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hidden",
"name[zh_CN]": "*****",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Send_To_Dock_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Send_To_Dock_List",
"name[zh_CN]": "*****",
"description": "apps hide function send to dock",
"permissions": "readwrite",
"visibility": "private"
},
"Apps_Hide_Uninstall_List": {
"value": [],
"serial": 0,
"flags": ["global"],
"name": "Apps_Hide_Uninstall_List",
"name[zh_CN]": "*****",
"description": "apps hide function uninstall",
"permissions": "readwrite",
"visibility": "private"
},
"Display_Mode": {
"value": "free",
"serial": 0,
"flags": ["global"],
"name": "Display_Mode",
"name[zh_CN]": "*****",
"description": "Launcher display mode.",
"permissions": "readwrite",
"visibility": "private"
}
}
}

View File

@ -0,0 +1,73 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c BamfApplication -p BamfApplication Application.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbusbamfapplication.h"
/*
* Implementation of interface class __BamfApplication
*/
class __BamfApplicationPrivate
{
public:
__BamfApplicationPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__BamfApplication::__BamfApplication(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __BamfApplicationPrivate)
{
if (QMetaType::type("QList<uint>") == QMetaType::UnknownType) {
qRegisterMetaType< QList<uint> >("QList<uint>");
qDBusRegisterMetaType< QList<uint> >();
}
}
__BamfApplication::~__BamfApplication()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __BamfApplication::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, &__BamfApplication::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __BamfApplication::onPendingCallFinished(QDBusPendingCallWatcher *w)
{
w->deleteLater();
const auto callName = d_ptr->m_processingCalls.key(w);
Q_ASSERT(!callName.isEmpty());
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

@ -0,0 +1,134 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c BamfApplication -p BamfApplication Application.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef BAMFAPPLICATION_H
#define BAMFAPPLICATION_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface org.ayatana.bamf.application
*/
class __BamfApplicationPrivate;
class __BamfApplication : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.ayatana.bamf.application"; }
public:
explicit __BamfApplication(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__BamfApplication();
public Q_SLOTS: // METHODS
inline Q_DECL_DEPRECATED QDBusPendingReply<QString, QString> ApplicationMenu()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ApplicationMenu"), argumentList);
}
inline Q_DECL_DEPRECATED QDBusReply<QString> ApplicationMenu(QString &objectpath)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("ApplicationMenu"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
objectpath = qdbus_cast<QString>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<QString> ApplicationType()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ApplicationType"), argumentList);
}
inline QDBusPendingReply<QString> DesktopFile()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("DesktopFile"), argumentList);
}
inline QDBusPendingReply<QString> FocusableChild()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("FocusableChild"), argumentList);
}
inline QDBusPendingReply<bool> ShowStubs()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ShowStubs"), argumentList);
}
inline QDBusPendingReply<QStringList> SupportedMimeTypes()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("SupportedMimeTypes"), argumentList);
}
inline QDBusPendingReply<QList<uint> > Xids()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Xids"), argumentList);
}
Q_SIGNALS: // SIGNALS
void DesktopFileUpdated(const QString &desktop_file);
void SupportedMimeTypesChanged(const QStringList &dnd_mimes);
Q_DECL_DEPRECATED void WindowAdded(const QString &path);
Q_DECL_DEPRECATED void WindowRemoved(const QString &path);
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__BamfApplicationPrivate *d_ptr;
};
namespace org {
namespace ayatana {
namespace bamf {
typedef ::__BamfApplication BamfApplication;
}
}
}
#endif

View File

@ -0,0 +1,75 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c BamfMatcher -p BamfMatcher Matcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbusbamfmatcher.h"
/*
* Implementation of interface class __BamfMatcher
*/
class __BamfMatcherPrivate
{
public:
__BamfMatcherPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__BamfMatcher::__BamfMatcher(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __BamfMatcherPrivate)
{
if (QMetaType::type("QList<uint>") == QMetaType::UnknownType) {
qRegisterMetaType< QList<uint> >("QList<uint>");
qDBusRegisterMetaType< QList<uint> >();
}
}
__BamfMatcher::~__BamfMatcher()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __BamfMatcher::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, &__BamfMatcher::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __BamfMatcher::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

@ -0,0 +1,188 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c BamfMatcher -p BamfMatcher Matcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef BAMFMATCHER_H
#define BAMFMATCHER_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface org.ayatana.bamf.matcher
*/
class __BamfMatcherPrivate;
class __BamfMatcher : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.ayatana.bamf.matcher"; }
public:
explicit __BamfMatcher(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__BamfMatcher();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QString> ActiveApplication()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ActiveApplication"), argumentList);
}
inline QDBusPendingReply<QString> ActiveWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList);
}
inline QDBusPendingReply<QString> ApplicationForXid(uint xid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(xid);
return asyncCallWithArgumentList(QStringLiteral("ApplicationForXid"), argumentList);
}
inline QDBusPendingReply<bool> ApplicationIsRunning(const QString &desktop_file)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktop_file);
return asyncCallWithArgumentList(QStringLiteral("ApplicationIsRunning"), argumentList);
}
inline QDBusPendingReply<QStringList> ApplicationPaths()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ApplicationPaths"), argumentList);
}
inline QDBusPendingReply<QString> PathForApplication(const QString &desktop_file)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktop_file);
return asyncCallWithArgumentList(QStringLiteral("PathForApplication"), argumentList);
}
inline QDBusPendingReply<> RegisterFavorites(const QStringList &favorites)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(favorites);
return asyncCallWithArgumentList(QStringLiteral("RegisterFavorites"), argumentList);
}
inline void RegisterFavoritesQueued(const QStringList &favorites)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(favorites);
CallQueued(QStringLiteral("RegisterFavorites"), argumentList);
}
inline QDBusPendingReply<QStringList> RunningApplications()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RunningApplications"), argumentList);
}
inline QDBusPendingReply<QStringList> RunningApplicationsDesktopFiles()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RunningApplicationsDesktopFiles"), argumentList);
}
inline QDBusPendingReply<QStringList> TabPaths()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("TabPaths"), argumentList);
}
inline QDBusPendingReply<QStringList> WindowPaths()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("WindowPaths"), argumentList);
}
inline QDBusPendingReply<QStringList> WindowStackForMonitor(int monitor_id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(monitor_id);
return asyncCallWithArgumentList(QStringLiteral("WindowStackForMonitor"), argumentList);
}
inline QDBusPendingReply<QList<uint> > XidsForApplication(const QString &desktop_file)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(desktop_file);
return asyncCallWithArgumentList(QStringLiteral("XidsForApplication"), argumentList);
}
Q_SIGNALS: // SIGNALS
void ActiveApplicationChanged(const QString &old_app, const QString &new_app);
void ActiveWindowChanged(const QString &old_win, const QString &new_win);
void RunningApplicationsChanged(const QStringList &opened_desktop_files, const QStringList &closed_desktop_files);
void StackingOrderChanged();
void ViewClosed(const QString &path, const QString &type);
void ViewOpened(const QString &path, const QString &type);
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__BamfMatcherPrivate *d_ptr;
};
namespace org {
namespace ayatana {
namespace bamf {
typedef ::__BamfMatcher BamfMatcher;
}
}
}
#endif

View File

@ -0,0 +1,71 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c OutputManagement -p generated/outputmanagement ../xml/OutputManagement.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuskwaylandoutput.h"
/*
* Implementation of interface class __OutputManagement
*/
class __OutputManagementPrivate
{
public:
__OutputManagementPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__OutputManagement::__OutputManagement(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __OutputManagementPrivate)
{
}
__OutputManagement::~__OutputManagement()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __OutputManagement::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, &__OutputManagement::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __OutputManagement::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

@ -0,0 +1,119 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c OutputManagement -p generated/outputmanagement ../xml/OutputManagement.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef OUTPUTMANAGEMENT_H
#define OUTPUTMANAGEMENT_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface com.deepin.daemon.KWayland.Output
*/
class __OutputManagementPrivate;
class __OutputManagement : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.daemon.KWayland.Output"; }
public:
explicit __OutputManagement(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__OutputManagement();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> Apply(const QString &outputs)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(outputs);
return asyncCallWithArgumentList(QStringLiteral("Apply"), argumentList);
}
inline void ApplyQueued(const QString &outputs)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(outputs);
CallQueued(QStringLiteral("Apply"), argumentList);
}
inline QDBusPendingReply<QString> GetOutput(const QString &uuid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uuid);
return asyncCallWithArgumentList(QStringLiteral("GetOutput"), argumentList);
}
inline QDBusPendingReply<QString> ListOutput()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ListOutput"), argumentList);
}
inline QDBusPendingReply<> WlSimulateKey(int state)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(state);
return asyncCallWithArgumentList(QStringLiteral("WlSimulateKey"), argumentList);
}
inline void WlSimulateKeyQueued(int state)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(state);
CallQueued(QStringLiteral("WlSimulateKey"), argumentList);
}
Q_SIGNALS: // SIGNALS
void OutputAdded(const QString &output);
void OutputChanged(const QString &output);
void OutputRemoved(const QString &output);
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__OutputManagementPrivate *d_ptr;
};
namespace com {
namespace deepin {
namespace daemon {
namespace kwayland {
typedef ::__OutputManagement Output;
}
}
}
}
#endif

View File

@ -0,0 +1,71 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c kwaylandmanager -p kwaylandmanager com.deepin.daemon.KWayland.WindowManager.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuskwaylandwindowmanager.h"
/*
* Implementation of interface class __kwaylandmanager
*/
class __kwaylandmanagerPrivate
{
public:
__kwaylandmanagerPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__KwaylandManager::__KwaylandManager(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __kwaylandmanagerPrivate)
{
}
__KwaylandManager::~__KwaylandManager()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __KwaylandManager::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, &__KwaylandManager::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __KwaylandManager::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

@ -0,0 +1,94 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c kwaylandmanager -p kwaylandmanager com.deepin.daemon.KWayland.WindowManager.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef KWAYLANDMANAGER_H
#define KWAYLANDMANAGER_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface com.deepin.daemon.KWayland.WindowManager
*/
class __kwaylandmanagerPrivate;
class __KwaylandManager : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.daemon.KWayland.WindowManager"; }
public:
explicit __KwaylandManager(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__KwaylandManager();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<uint> ActiveWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList);
}
inline QDBusPendingReply<bool> IsShowingDesktop()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsShowingDesktop"), argumentList);
}
inline QDBusPendingReply<QVariantList> Windows()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Windows"), argumentList);
}
Q_SIGNALS: // SIGNALS
void ActiveWindowChanged();
void WindowCreated(const QString &ObjPath);
void WindowRemove(const QString &ObjPath);
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__kwaylandmanagerPrivate *d_ptr;
};
namespace com {
namespace deepin {
namespace daemon {
namespace kwayland {
typedef ::__KwaylandManager WindowManager;
}
}
}
}
#endif

View File

@ -0,0 +1,129 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Launcherd -p generated/com_deepin_dde_daemon_launcherd ../xml/com.deepin.dde.daemon.Launcherd.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuslauncher.h"
/*
* Implementation of interface class __Launcherd
*/
class __LauncherdPrivate
{
public:
__LauncherdPrivate() = default;
// begin member variables
int DisplayMode;
bool Fullscreen;
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
LauncherBackEnd::LauncherBackEnd(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __LauncherdPrivate)
{
connect(this, &LauncherBackEnd::propertyChanged, this, &LauncherBackEnd::onPropertyChanged);
if (QMetaType::type("LauncherItemInfo") == QMetaType::UnknownType)
registerLauncherItemInfoMetaType();
if (QMetaType::type("LauncherItemInfoList") == QMetaType::UnknownType)
registerLauncherItemInfoListMetaType();
}
LauncherBackEnd::~LauncherBackEnd()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void LauncherBackEnd::onPropertyChanged(const QString &propName, const QVariant &value)
{
if (propName == QStringLiteral("DisplayMode"))
{
const int &DisplayMode = qvariant_cast<int>(value);
if (d_ptr->DisplayMode != DisplayMode)
{
d_ptr->DisplayMode = DisplayMode;
Q_EMIT DisplayModeChanged(d_ptr->DisplayMode);
}
return;
}
if (propName == QStringLiteral("Fullscreen"))
{
const bool &Fullscreen = qvariant_cast<bool>(value);
if (d_ptr->Fullscreen != Fullscreen)
{
d_ptr->Fullscreen = Fullscreen;
Q_EMIT FullscreenChanged(d_ptr->Fullscreen);
}
return;
}
qWarning() << "property not handle: " << propName;
return;
}
int LauncherBackEnd::displayMode()
{
return qvariant_cast<int>(internalPropGet("DisplayMode", &d_ptr->DisplayMode));
}
void LauncherBackEnd::setDisplayMode(int value)
{
internalPropSet("DisplayMode", QVariant::fromValue(value), &d_ptr->DisplayMode);
}
bool LauncherBackEnd::fullscreen()
{
return qvariant_cast<bool>(internalPropGet("Fullscreen", &d_ptr->Fullscreen));
}
void LauncherBackEnd::setFullscreen(bool value)
{
internalPropSet("Fullscreen", QVariant::fromValue(value), &d_ptr->Fullscreen);
}
void LauncherBackEnd::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, &LauncherBackEnd::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void LauncherBackEnd::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

@ -0,0 +1,235 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Launcherd -p generated/com_deepin_dde_daemon_launcherd ../xml/com.deepin.dde.daemon.Launcherd.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef COM_DEEPIN_DDE_DAEMON_LAUNCHERD_H
#define COM_DEEPIN_DDE_DAEMON_LAUNCHERD_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
#include "types/launcheriteminfo.h"
#include "types/launcheriteminfolist.h"
/*
* Proxy class for interface org.deepin.dde.daemon.Launcher1
*/
class __LauncherdPrivate;
class LauncherBackEnd : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.deepin.dde.daemon.Launcher1"; }
public:
explicit LauncherBackEnd(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~LauncherBackEnd();
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
int displayMode();
void setDisplayMode(int value);
Q_PROPERTY(bool Fullscreen READ fullscreen WRITE setFullscreen NOTIFY FullscreenChanged)
bool fullscreen();
void setFullscreen(bool value);
public Q_SLOTS: // METHODS
inline QDBusPendingReply<LauncherItemInfoList> GetAllItemInfos()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetAllItemInfos"), argumentList);
}
inline QDBusPendingReply<QStringList> GetAllNewInstalledApps()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetAllNewInstalledApps"), argumentList);
}
inline QDBusPendingReply<bool> GetDisableScaling(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("GetDisableScaling"), argumentList);
}
inline QDBusPendingReply<LauncherItemInfo> GetItemInfo(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("GetItemInfo"), argumentList);
}
inline QDBusPendingReply<bool> GetUseProxy(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("GetUseProxy"), argumentList);
}
inline QDBusPendingReply<bool> IsItemOnDesktop(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("IsItemOnDesktop"), argumentList);
}
inline QDBusPendingReply<> MarkLaunched(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("MarkLaunched"), argumentList);
}
inline void MarkLaunchedQueued(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
CallQueued(QStringLiteral("MarkLaunched"), argumentList);
}
inline QDBusPendingReply<bool> RequestRemoveFromDesktop(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("RequestRemoveFromDesktop"), argumentList);
}
inline QDBusPendingReply<bool> RequestSendToDesktop(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("RequestSendToDesktop"), argumentList);
}
inline QDBusPendingReply<> RequestUninstall(const QString &id, bool purge)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(purge);
return asyncCallWithArgumentList(QStringLiteral("RequestUninstall"), argumentList);
}
inline void RequestUninstallQueued(const QString &id, bool purge)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(purge);
CallQueued(QStringLiteral("RequestUninstall"), argumentList);
}
inline QDBusPendingReply<> Search(const QString &key)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(key);
return asyncCallWithArgumentList(QStringLiteral("Search"), argumentList);
}
inline void SearchQueued(const QString &key)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(key);
CallQueued(QStringLiteral("Search"), argumentList);
}
inline QDBusPendingReply<> SetDisableScaling(const QString &id, bool value)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(value);
return asyncCallWithArgumentList(QStringLiteral("SetDisableScaling"), argumentList);
}
inline void SetDisableScalingQueued(const QString &id, bool value)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(value);
CallQueued(QStringLiteral("SetDisableScaling"), argumentList);
}
inline QDBusPendingReply<> SetUseProxy(const QString &id, bool value)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(value);
return asyncCallWithArgumentList(QStringLiteral("SetUseProxy"), argumentList);
}
inline void SetUseProxyQueued(const QString &id, bool value)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id) << QVariant::fromValue(value);
CallQueued(QStringLiteral("SetUseProxy"), argumentList);
}
Q_SIGNALS: // SIGNALS
void ItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID);
void NewAppLaunched(const QString &appID);
void SearchDone(const QStringList &apps);
void UninstallFailed(const QString &appId, const QString &errMsg);
void UninstallSuccess(const QString &appID);
// begin property changed signals
void DisplayModeChanged(int value) const;
void FullscreenChanged(bool value) const;
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:
__LauncherdPrivate *d_ptr;
};
namespace com {
namespace deepin {
namespace dde {
namespace daemon {
typedef ::LauncherBackEnd LauncherBackEnd;
}
}
}
}
#endif

View File

@ -0,0 +1,96 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Launcher -p generated/com_deepin_dde_launcher ../xml/com.deepin.dde.Launcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuslauncherfront.h"
/*
* Implementation of interface class __Launcher
*/
class __LauncherPrivate
{
public:
__LauncherPrivate() = default;
// begin member variables
bool Visible;
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
LauncherFront::LauncherFront(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __LauncherPrivate)
{
connect(this, &LauncherFront::propertyChanged, this, &LauncherFront::onPropertyChanged);
}
LauncherFront::~LauncherFront()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void LauncherFront::onPropertyChanged(const QString &propName, const QVariant &value)
{
if (propName == QStringLiteral("Visible"))
{
const bool &Visible = qvariant_cast<bool>(value);
if (d_ptr->Visible != Visible)
{
d_ptr->Visible = Visible;
Q_EMIT VisibleChanged(d_ptr->Visible);
}
return;
}
qWarning() << "property not handle: " << propName;
return;
}
bool LauncherFront::visible()
{
return qvariant_cast<bool>(internalPropGet("Visible", &d_ptr->Visible));
}
void LauncherFront::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, &LauncherFront::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void LauncherFront::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

@ -0,0 +1,169 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Launcher -p generated/com_deepin_dde_launcher ../xml/com.deepin.dde.Launcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef COM_DEEPIN_DDE_LAUNCHER_H
#define COM_DEEPIN_DDE_LAUNCHER_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface org.deepin.dde.Launcher1
*/
class __LauncherPrivate;
class LauncherFront : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.deepin.dde.Launcher1"; }
public:
explicit LauncherFront(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~LauncherFront();
Q_PROPERTY(bool Visible READ visible NOTIFY VisibleChanged)
bool visible();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> Exit()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Exit"), argumentList);
}
inline void ExitQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Exit"), argumentList);
}
inline QDBusPendingReply<> Hide()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Hide"), argumentList);
}
inline void HideQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Hide"), argumentList);
}
inline QDBusPendingReply<bool> IsVisible()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsVisible"), argumentList);
}
inline QDBusPendingReply<> Show()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Show"), argumentList);
}
inline void ShowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Show"), argumentList);
}
inline QDBusPendingReply<> ShowByMode(qlonglong in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("ShowByMode"), argumentList);
}
inline void ShowByModeQueued(qlonglong in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("ShowByMode"), argumentList);
}
inline QDBusPendingReply<> Toggle()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Toggle"), argumentList);
}
inline void ToggleQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Toggle"), argumentList);
}
inline QDBusPendingReply<> UninstallApp(const QString &appKey)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appKey);
return asyncCallWithArgumentList(QStringLiteral("UninstallApp"), argumentList);
}
inline void UninstallAppQueued(const QString &appKey)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appKey);
CallQueued(QStringLiteral("UninstallApp"), argumentList);
}
Q_SIGNALS: // SIGNALS
void Closed();
void Shown();
void VisibleChanged(bool visible);
// begin property changed signals
//void VisibleChanged(bool value) const;
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:
__LauncherPrivate *d_ptr;
};
namespace com {
namespace deepin {
namespace dde {
typedef ::LauncherFront LauncherFront;
}
}
}
#endif

View File

@ -0,0 +1,73 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Window -p generated/window ../xml/Window.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbusplasmawindow.h"
/*
* Implementation of interface class __Window
*/
class __WindowPrivate
{
public:
__WindowPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
PlasmaWindow::PlasmaWindow(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __WindowPrivate)
{
if (QMetaType::type("Rect") == QMetaType::UnknownType)
registerRectMetaType();
}
PlasmaWindow::~PlasmaWindow()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void PlasmaWindow::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, &PlasmaWindow::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void PlasmaWindow::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

@ -0,0 +1,499 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c Window -p generated/window ../xml/Window.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef WINDOW_H
#define WINDOW_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
#include "types/rect.h"
/*
* Proxy class for interface com.deepin.daemon.KWayland.PlasmaWindow
*/
class __WindowPrivate;
class PlasmaWindow : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.daemon.KWayland.PlasmaWindow"; }
public:
explicit PlasmaWindow(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~PlasmaWindow();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QString> AppId()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("AppId"), argumentList);
}
inline QDBusPendingReply<Rect> Geometry()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Geometry"), argumentList);
}
inline QDBusPendingReply<QString> Icon()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Icon"), argumentList);
}
inline QDBusPendingReply<uint> InternalId()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("InternalId"), argumentList);
}
inline QDBusPendingReply<bool> IsActive()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsActive"), argumentList);
}
inline QDBusPendingReply<bool> IsCloseable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsCloseable"), argumentList);
}
inline QDBusPendingReply<bool> IsDemandingAttention()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsDemandingAttention"), argumentList);
}
inline QDBusPendingReply<bool> IsFullscreen()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsFullscreen"), argumentList);
}
inline QDBusPendingReply<bool> IsFullscreenable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsFullscreenable"), argumentList);
}
inline QDBusPendingReply<bool> IsKeepAbove()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsKeepAbove"), argumentList);
}
inline QDBusPendingReply<bool> IsMaximizeable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsMaximizeable"), argumentList);
}
inline QDBusPendingReply<bool> IsMaximized()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsMaximized"), argumentList);
}
inline QDBusPendingReply<bool> IsMinimizeable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsMinimizeable"), argumentList);
}
inline QDBusPendingReply<bool> IsMinimized()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsMinimized"), argumentList);
}
inline QDBusPendingReply<bool> IsMovable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsMovable"), argumentList);
}
inline QDBusPendingReply<bool> IsOnAllDesktops()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsOnAllDesktops"), argumentList);
}
inline QDBusPendingReply<bool> IsResizable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsResizable"), argumentList);
}
inline QDBusPendingReply<bool> IsShadeable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsShadeable"), argumentList);
}
inline QDBusPendingReply<bool> IsShaded()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsShaded"), argumentList);
}
inline QDBusPendingReply<bool> IsValid()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsValid"), argumentList);
}
inline QDBusPendingReply<bool> IsVirtualDesktopChangeable()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("IsVirtualDesktopChangeable"), argumentList);
}
inline QDBusPendingReply<uint> Pid()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Pid"), argumentList);
}
inline QDBusPendingReply<> RequestActivate()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestActivate"), argumentList);
}
inline void RequestActivateQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestActivate"), argumentList);
}
inline QDBusPendingReply<> RequestClose()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestClose"), argumentList);
}
inline void RequestCloseQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestClose"), argumentList);
}
inline QDBusPendingReply<> RequestEnterNewVirtualDesktop()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestEnterNewVirtualDesktop"), argumentList);
}
inline void RequestEnterNewVirtualDesktopQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestEnterNewVirtualDesktop"), argumentList);
}
inline QDBusPendingReply<> RequestEnterVirtualDesktop(const QString &argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
return asyncCallWithArgumentList(QStringLiteral("RequestEnterVirtualDesktop"), argumentList);
}
inline void RequestEnterVirtualDesktopQueued(const QString &argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
CallQueued(QStringLiteral("RequestEnterVirtualDesktop"), argumentList);
}
inline QDBusPendingReply<> RequestLeaveVirtualDesktop(const QString &argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
return asyncCallWithArgumentList(QStringLiteral("RequestLeaveVirtualDesktop"), argumentList);
}
inline void RequestLeaveVirtualDesktopQueued(const QString &argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
CallQueued(QStringLiteral("RequestLeaveVirtualDesktop"), argumentList);
}
inline QDBusPendingReply<> RequestMove()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestMove"), argumentList);
}
inline void RequestMoveQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestMove"), argumentList);
}
inline QDBusPendingReply<> RequestResize()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestResize"), argumentList);
}
inline void RequestResizeQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestResize"), argumentList);
}
inline QDBusPendingReply<> RequestToggleKeepAbove()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestToggleKeepAbove"), argumentList);
}
inline void RequestToggleKeepAboveQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestToggleKeepAbove"), argumentList);
}
inline QDBusPendingReply<> RequestToggleKeepBelow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestToggleKeepBelow"), argumentList);
}
inline void RequestToggleKeepBelowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestToggleKeepBelow"), argumentList);
}
inline QDBusPendingReply<> RequestToggleMaximized()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestToggleMaximized"), argumentList);
}
inline void RequestToggleMaximizedQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestToggleMaximized"), argumentList);
}
inline QDBusPendingReply<> RequestToggleMinimized()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestToggleMinimized"), argumentList);
}
inline void RequestToggleMinimizedQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestToggleMinimized"), argumentList);
}
inline QDBusPendingReply<> RequestToggleShaded()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestToggleShaded"), argumentList);
}
inline void RequestToggleShadedQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestToggleShaded"), argumentList);
}
inline QDBusPendingReply<> RequestVirtualDesktop(uint argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
return asyncCallWithArgumentList(QStringLiteral("RequestVirtualDesktop"), argumentList);
}
inline void RequestVirtualDesktopQueued(uint argin0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(argin0);
CallQueued(QStringLiteral("RequestVirtualDesktop"), argumentList);
}
inline QDBusPendingReply<bool> SkipSwitcher()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("SkipSwitcher"), argumentList);
}
inline QDBusPendingReply<bool> SkipTaskbar()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("SkipTaskbar"), argumentList);
}
inline QDBusPendingReply<QString> Title()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Title"), argumentList);
}
inline QDBusPendingReply<uint> VirtualDesktop()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("VirtualDesktop"), argumentList);
}
inline QDBusPendingReply<uint> WindowId()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("WindowId"), argumentList);
}
Q_SIGNALS: // SIGNALS
void ActiveChanged();
void AppIdChanged();
void CloseableChanged();
void DemandsAttentionChanged();
void FullscreenChanged();
void FullscreenableChanged();
void GeometryChanged();
void IconChanged();
void KeepAboveChanged();
void KeepBelowChanged();
void MaximizeableChanged();
void MaximizedChanged();
void MinimizeableChanged();
void MinimizedChanged();
void MovableChanged();
void OnAllDesktopsChanged();
void ParentWindowChanged();
void ResizableChanged();
void ShadeableChanged();
void ShadedChanged();
void SkipSwitcherChanged();
void SkipTaskbarChanged();
void TitleChanged();
void Unmapped();
void VirtualDesktopChangeableChanged();
void VirtualDesktopChanged();
void WindowIdChanged();
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__WindowPrivate *d_ptr;
};
namespace com {
namespace deepin {
namespace daemon {
namespace kwayland {
typedef ::PlasmaWindow PlasmaWindow;
}
}
}
}
#endif

View File

@ -0,0 +1,209 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c wm -p generated/com_deepin_wm ../xml/com.deepin.wm.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuswm.h"
/*
* Implementation of interface class __wm
*/
class __wmPrivate
{
public:
__wmPrivate() = default;
// begin member variables
bool compositingAllowSwitch;
bool compositingEnabled;
bool compositingPossible;
int cursorSize;
QString cursorTheme;
bool zoneEnabled;
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__wm::__wm(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __wmPrivate)
{
connect(this, &__wm::propertyChanged, this, &__wm::onPropertyChanged);
if (QMetaType::type("QList<uint>") == QMetaType::UnknownType) {
qRegisterMetaType< QList<uint> >("QList<uint>");
qDBusRegisterMetaType< QList<uint> >();
}
}
__wm::~__wm()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __wm::onPropertyChanged(const QString &propName, const QVariant &value)
{
if (propName == QStringLiteral("compositingAllowSwitch"))
{
const bool &compositingAllowSwitch = qvariant_cast<bool>(value);
if (d_ptr->compositingAllowSwitch != compositingAllowSwitch)
{
d_ptr->compositingAllowSwitch = compositingAllowSwitch;
Q_EMIT CompositingAllowSwitchChanged(d_ptr->compositingAllowSwitch);
}
return;
}
if (propName == QStringLiteral("compositingEnabled"))
{
const bool &compositingEnabled = qvariant_cast<bool>(value);
if (d_ptr->compositingEnabled != compositingEnabled)
{
d_ptr->compositingEnabled = compositingEnabled;
Q_EMIT CompositingEnabledChanged(d_ptr->compositingEnabled);
}
return;
}
if (propName == QStringLiteral("compositingPossible"))
{
const bool &compositingPossible = qvariant_cast<bool>(value);
if (d_ptr->compositingPossible != compositingPossible)
{
d_ptr->compositingPossible = compositingPossible;
Q_EMIT CompositingPossibleChanged(d_ptr->compositingPossible);
}
return;
}
if (propName == QStringLiteral("cursorSize"))
{
const int &cursorSize = qvariant_cast<int>(value);
if (d_ptr->cursorSize != cursorSize)
{
d_ptr->cursorSize = cursorSize;
Q_EMIT CursorSizeChanged(d_ptr->cursorSize);
}
return;
}
if (propName == QStringLiteral("cursorTheme"))
{
const QString &cursorTheme = qvariant_cast<QString>(value);
if (d_ptr->cursorTheme != cursorTheme)
{
d_ptr->cursorTheme = cursorTheme;
Q_EMIT CursorThemeChanged(d_ptr->cursorTheme);
}
return;
}
if (propName == QStringLiteral("zoneEnabled"))
{
const bool &zoneEnabled = qvariant_cast<bool>(value);
if (d_ptr->zoneEnabled != zoneEnabled)
{
d_ptr->zoneEnabled = zoneEnabled;
Q_EMIT ZoneEnabledChanged(d_ptr->zoneEnabled);
}
return;
}
qWarning() << "property not handle: " << propName;
return;
}
bool __wm::compositingAllowSwitch()
{
return qvariant_cast<bool>(internalPropGet("compositingAllowSwitch", &d_ptr->compositingAllowSwitch));
}
bool __wm::compositingEnabled()
{
return qvariant_cast<bool>(internalPropGet("compositingEnabled", &d_ptr->compositingEnabled));
}
void __wm::setCompositingEnabled(bool value)
{
internalPropSet("compositingEnabled", QVariant::fromValue(value), &d_ptr->compositingEnabled);
}
bool __wm::compositingPossible()
{
return qvariant_cast<bool>(internalPropGet("compositingPossible", &d_ptr->compositingPossible));
}
int __wm::cursorSize()
{
return qvariant_cast<int>(internalPropGet("cursorSize", &d_ptr->cursorSize));
}
void __wm::setCursorSize(int value)
{
internalPropSet("cursorSize", QVariant::fromValue(value), &d_ptr->cursorSize);
}
QString __wm::cursorTheme()
{
return qvariant_cast<QString>(internalPropGet("cursorTheme", &d_ptr->cursorTheme));
}
void __wm::setCursorTheme(const QString &value)
{
internalPropSet("cursorTheme", QVariant::fromValue(value), &d_ptr->cursorTheme);
}
bool __wm::zoneEnabled()
{
return qvariant_cast<bool>(internalPropGet("zoneEnabled", &d_ptr->zoneEnabled));
}
void __wm::setZoneEnabled(bool value)
{
internalPropSet("zoneEnabled", QVariant::fromValue(value), &d_ptr->zoneEnabled);
}
void __wm::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, &__wm::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __wm::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);
}

708
src/frameworkdbus/dbuswm.h Normal file
View File

@ -0,0 +1,708 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c wm -p generated/com_deepin_wm ../xml/com.deepin.wm.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef COM_DEEPIN_WM_H
#define COM_DEEPIN_WM_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface com.deepin.wm
*/
class __wmPrivate;
class __wm : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.wm"; }
public:
explicit __wm(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__wm();
Q_PROPERTY(bool compositingAllowSwitch READ compositingAllowSwitch NOTIFY CompositingAllowSwitchChanged)
bool compositingAllowSwitch();
Q_PROPERTY(bool compositingEnabled READ compositingEnabled WRITE setCompositingEnabled NOTIFY CompositingEnabledChanged)
bool compositingEnabled();
void setCompositingEnabled(bool value);
Q_PROPERTY(bool compositingPossible READ compositingPossible NOTIFY CompositingPossibleChanged)
bool compositingPossible();
Q_PROPERTY(int cursorSize READ cursorSize WRITE setCursorSize NOTIFY CursorSizeChanged)
int cursorSize();
void setCursorSize(int value);
Q_PROPERTY(QString cursorTheme READ cursorTheme WRITE setCursorTheme NOTIFY CursorThemeChanged)
QString cursorTheme();
void setCursorTheme(const QString &value);
Q_PROPERTY(bool zoneEnabled READ zoneEnabled WRITE setZoneEnabled NOTIFY ZoneEnabledChanged)
bool zoneEnabled();
void setZoneEnabled(bool value);
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> BeginToMoveActiveWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("BeginToMoveActiveWindow"), argumentList);
}
inline void BeginToMoveActiveWindowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("BeginToMoveActiveWindow"), argumentList);
}
inline QDBusPendingReply<> CancelPreviewWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("CancelPreviewWindow"), argumentList);
}
inline void CancelPreviewWindowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("CancelPreviewWindow"), argumentList);
}
inline QDBusPendingReply<> ChangeCurrentWorkspaceBackground(const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri);
return asyncCallWithArgumentList(QStringLiteral("ChangeCurrentWorkspaceBackground"), argumentList);
}
inline void ChangeCurrentWorkspaceBackgroundQueued(const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri);
CallQueued(QStringLiteral("ChangeCurrentWorkspaceBackground"), argumentList);
}
inline QDBusPendingReply<> ClearMoveStatus()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ClearMoveStatus"), argumentList);
}
inline void ClearMoveStatusQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ClearMoveStatus"), argumentList);
}
inline QDBusPendingReply<> EnableZoneDetected(bool enabled)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(enabled);
return asyncCallWithArgumentList(QStringLiteral("EnableZoneDetected"), argumentList);
}
inline void EnableZoneDetectedQueued(bool enabled)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(enabled);
CallQueued(QStringLiteral("EnableZoneDetected"), argumentList);
}
inline QDBusPendingReply<QStringList> GetAccel(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("GetAccel"), argumentList);
}
inline QDBusPendingReply<QString> GetAllAccels()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetAllAccels"), argumentList);
}
inline QDBusPendingReply<bool> GetCurrentDesktopStatus()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetCurrentDesktopStatus"), argumentList);
}
inline QDBusPendingReply<int> GetCurrentWorkspace()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetCurrentWorkspace"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentWorkspaceBackground()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetCurrentWorkspaceBackground"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentWorkspaceBackgroundForMonitor(const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(strMonitorName);
return asyncCallWithArgumentList(QStringLiteral("GetCurrentWorkspaceBackgroundForMonitor"), argumentList);
}
inline QDBusPendingReply<QStringList> GetDefaultAccel(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("GetDefaultAccel"), argumentList);
}
inline QDBusPendingReply<bool> GetIsShowDesktop()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetIsShowDesktop"), argumentList);
}
inline QDBusPendingReply<bool> GetMultiTaskingStatus()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetMultiTaskingStatus"), argumentList);
}
inline QDBusPendingReply<double> GetTouchBorderInterval()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("GetTouchBorderInterval"), argumentList);
}
inline QDBusPendingReply<QString> GetWorkspaceBackground(int index)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index);
return asyncCallWithArgumentList(QStringLiteral("GetWorkspaceBackground"), argumentList);
}
inline QDBusPendingReply<QString> GetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index) << QVariant::fromValue(strMonitorName);
return asyncCallWithArgumentList(QStringLiteral("GetWorkspaceBackgroundForMonitor"), argumentList);
}
inline QDBusPendingReply<> MinimizeActiveWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("MinimizeActiveWindow"), argumentList);
}
inline void MinimizeActiveWindowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("MinimizeActiveWindow"), argumentList);
}
inline QDBusPendingReply<> NextWorkspace()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("NextWorkspace"), argumentList);
}
inline void NextWorkspaceQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("NextWorkspace"), argumentList);
}
inline QDBusPendingReply<> PerformAction(int type)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(type);
return asyncCallWithArgumentList(QStringLiteral("PerformAction"), argumentList);
}
inline void PerformActionQueued(int type)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(type);
CallQueued(QStringLiteral("PerformAction"), argumentList);
}
inline QDBusPendingReply<> PresentWindows(const QList<uint> &xids)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(xids);
return asyncCallWithArgumentList(QStringLiteral("PresentWindows"), argumentList);
}
inline void PresentWindowsQueued(const QList<uint> &xids)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(xids);
CallQueued(QStringLiteral("PresentWindows"), argumentList);
}
inline QDBusPendingReply<> PreviewWindow(uint xid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(xid);
return asyncCallWithArgumentList(QStringLiteral("PreviewWindow"), argumentList);
}
inline void PreviewWindowQueued(uint xid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(xid);
CallQueued(QStringLiteral("PreviewWindow"), argumentList);
}
inline QDBusPendingReply<> PreviousWorkspace()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("PreviousWorkspace"), argumentList);
}
inline void PreviousWorkspaceQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("PreviousWorkspace"), argumentList);
}
inline QDBusPendingReply<> RemoveAccel(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
return asyncCallWithArgumentList(QStringLiteral("RemoveAccel"), argumentList);
}
inline void RemoveAccelQueued(const QString &id)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(id);
CallQueued(QStringLiteral("RemoveAccel"), argumentList);
}
inline QDBusPendingReply<bool> SetAccel(const QString &data)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(data);
return asyncCallWithArgumentList(QStringLiteral("SetAccel"), argumentList);
}
inline QDBusPendingReply<> SetCurrentWorkspace(int index)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index);
return asyncCallWithArgumentList(QStringLiteral("SetCurrentWorkspace"), argumentList);
}
inline void SetCurrentWorkspaceQueued(int index)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index);
CallQueued(QStringLiteral("SetCurrentWorkspace"), argumentList);
}
inline QDBusPendingReply<> SetCurrentWorkspaceBackground(const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri);
return asyncCallWithArgumentList(QStringLiteral("SetCurrentWorkspaceBackground"), argumentList);
}
inline void SetCurrentWorkspaceBackgroundQueued(const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri);
CallQueued(QStringLiteral("SetCurrentWorkspaceBackground"), argumentList);
}
inline QDBusPendingReply<> SetCurrentWorkspaceBackgroundForMonitor(const QString &uri, const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri) << QVariant::fromValue(strMonitorName);
return asyncCallWithArgumentList(QStringLiteral("SetCurrentWorkspaceBackgroundForMonitor"), argumentList);
}
inline void SetCurrentWorkspaceBackgroundForMonitorQueued(const QString &uri, const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri) << QVariant::fromValue(strMonitorName);
CallQueued(QStringLiteral("SetCurrentWorkspaceBackgroundForMonitor"), argumentList);
}
inline QDBusPendingReply<> SetDecorationDeepinTheme(const QString &deepinThemeName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(deepinThemeName);
return asyncCallWithArgumentList(QStringLiteral("SetDecorationDeepinTheme"), argumentList);
}
inline void SetDecorationDeepinThemeQueued(const QString &deepinThemeName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(deepinThemeName);
CallQueued(QStringLiteral("SetDecorationDeepinTheme"), argumentList);
}
inline QDBusPendingReply<> SetDecorationTheme(const QString &themeType, const QString &themeName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(themeType) << QVariant::fromValue(themeName);
return asyncCallWithArgumentList(QStringLiteral("SetDecorationTheme"), argumentList);
}
inline void SetDecorationThemeQueued(const QString &themeType, const QString &themeName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(themeType) << QVariant::fromValue(themeName);
CallQueued(QStringLiteral("SetDecorationTheme"), argumentList);
}
inline QDBusPendingReply<> SetMultiTaskingStatus(bool isActive)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(isActive);
return asyncCallWithArgumentList(QStringLiteral("SetMultiTaskingStatus"), argumentList);
}
inline void SetMultiTaskingStatusQueued(bool isActive)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(isActive);
CallQueued(QStringLiteral("SetMultiTaskingStatus"), argumentList);
}
inline QDBusPendingReply<> SetShowDesktop(bool isShowDesktop)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(isShowDesktop);
return asyncCallWithArgumentList(QStringLiteral("SetShowDesktop"), argumentList);
}
inline void SetShowDesktopQueued(bool isShowDesktop)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(isShowDesktop);
CallQueued(QStringLiteral("SetShowDesktop"), argumentList);
}
inline QDBusPendingReply<> SetTouchBorderInterval(double interval)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(interval);
return asyncCallWithArgumentList(QStringLiteral("SetTouchBorderInterval"), argumentList);
}
inline void SetTouchBorderIntervalQueued(double interval)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(interval);
CallQueued(QStringLiteral("SetTouchBorderInterval"), argumentList);
}
inline QDBusPendingReply<> SetTransientBackground(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return asyncCallWithArgumentList(QStringLiteral("SetTransientBackground"), argumentList);
}
inline void SetTransientBackgroundQueued(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
CallQueued(QStringLiteral("SetTransientBackground"), argumentList);
}
inline QDBusPendingReply<> SetTransientBackgroundForMonitor(const QString &uri, const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri) << QVariant::fromValue(strMonitorName);
return asyncCallWithArgumentList(QStringLiteral("SetTransientBackgroundForMonitor"), argumentList);
}
inline void SetTransientBackgroundForMonitorQueued(const QString &uri, const QString &strMonitorName)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(uri) << QVariant::fromValue(strMonitorName);
CallQueued(QStringLiteral("SetTransientBackgroundForMonitor"), argumentList);
}
inline QDBusPendingReply<> SetWorkspaceBackground(int index, const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index) << QVariant::fromValue(uri);
return asyncCallWithArgumentList(QStringLiteral("SetWorkspaceBackground"), argumentList);
}
inline void SetWorkspaceBackgroundQueued(int index, const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index) << QVariant::fromValue(uri);
CallQueued(QStringLiteral("SetWorkspaceBackground"), argumentList);
}
inline QDBusPendingReply<> SetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName, const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index) << QVariant::fromValue(strMonitorName) << QVariant::fromValue(uri);
return asyncCallWithArgumentList(QStringLiteral("SetWorkspaceBackgroundForMonitor"), argumentList);
}
inline void SetWorkspaceBackgroundForMonitorQueued(int index, const QString &strMonitorName, const QString &uri)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(index) << QVariant::fromValue(strMonitorName) << QVariant::fromValue(uri);
CallQueued(QStringLiteral("SetWorkspaceBackgroundForMonitor"), argumentList);
}
inline QDBusPendingReply<> ShowAllWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ShowAllWindow"), argumentList);
}
inline void ShowAllWindowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ShowAllWindow"), argumentList);
}
inline QDBusPendingReply<> ShowWindow()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ShowWindow"), argumentList);
}
inline void ShowWindowQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ShowWindow"), argumentList);
}
inline QDBusPendingReply<> ShowWorkspace()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ShowWorkspace"), argumentList);
}
inline void ShowWorkspaceQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ShowWorkspace"), argumentList);
}
inline QDBusPendingReply<> SwitchApplication(bool backward)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backward);
return asyncCallWithArgumentList(QStringLiteral("SwitchApplication"), argumentList);
}
inline void SwitchApplicationQueued(bool backward)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backward);
CallQueued(QStringLiteral("SwitchApplication"), argumentList);
}
inline QDBusPendingReply<> SwitchToWorkspace(bool backward)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backward);
return asyncCallWithArgumentList(QStringLiteral("SwitchToWorkspace"), argumentList);
}
inline void SwitchToWorkspaceQueued(bool backward)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backward);
CallQueued(QStringLiteral("SwitchToWorkspace"), argumentList);
}
inline QDBusPendingReply<> TileActiveWindow(uint side)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(side);
return asyncCallWithArgumentList(QStringLiteral("TileActiveWindow"), argumentList);
}
inline void TileActiveWindowQueued(uint side)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(side);
CallQueued(QStringLiteral("TileActiveWindow"), argumentList);
}
inline QDBusPendingReply<> ToggleActiveWindowMaximize()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("ToggleActiveWindowMaximize"), argumentList);
}
inline void ToggleActiveWindowMaximizeQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("ToggleActiveWindowMaximize"), argumentList);
}
inline QDBusPendingReply<> TouchToMove(int x, int y)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y);
return asyncCallWithArgumentList(QStringLiteral("TouchToMove"), argumentList);
}
inline void TouchToMoveQueued(int x, int y)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y);
CallQueued(QStringLiteral("TouchToMove"), argumentList);
}
inline QDBusPendingReply<int> WorkspaceCount()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("WorkspaceCount"), argumentList);
}
Q_SIGNALS: // SIGNALS
void WorkspaceBackgroundChanged(int index, const QString &newUri);
void WorkspaceBackgroundChangedForMonitor(int index, const QString &strMonitorName, const QString &uri);
void WorkspaceSwitched(int from, int to);
void compositingEnabledChanged(bool enabled);
void wmCompositingEnabledChanged(bool enabled);
void workspaceCountChanged(int count);
// begin property changed signals
void CompositingAllowSwitchChanged(bool value) const;
void CompositingEnabledChanged(bool value) const;
void CompositingPossibleChanged(bool value) const;
void CursorSizeChanged(int value) const;
void CursorThemeChanged(const QString & value) const;
void ZoneEnabledChanged(bool value) const;
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:
__wmPrivate *d_ptr;
};
namespace com {
namespace deepin {
typedef ::__wm WM;
}
}
#endif

View File

@ -0,0 +1,71 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c WMSwitcher -p generated/com_deepin_wmswitcher ../xml/com.deepin.WMSwitcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "dbuswmswitcher.h"
/*
* Implementation of interface class __WMSwitcher
*/
class __WMSwitcherPrivate
{
public:
__WMSwitcherPrivate() = default;
// begin member variables
public:
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
QMap<QString, QList<QVariant>> m_waittingCalls;
};
__WMSwitcher::__WMSwitcher(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)
, d_ptr(new __WMSwitcherPrivate)
{
}
__WMSwitcher::~__WMSwitcher()
{
qDeleteAll(d_ptr->m_processingCalls.values());
delete d_ptr;
}
void __WMSwitcher::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, &__WMSwitcher::onPendingCallFinished);
d_ptr->m_processingCalls.insert(callName, watcher);
}
}
void __WMSwitcher::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

@ -0,0 +1,122 @@
/*
* This file was generated by qdbusxml2cpp-fix version 0.8
* Command line was: qdbusxml2cpp-fix -c WMSwitcher -p generated/com_deepin_wmswitcher ../xml/com.deepin.WMSwitcher.xml
*
* qdbusxml2cpp-fix is Copyright (C) 2016 Deepin Technology Co., Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef COM_DEEPIN_WMSWITCHER_H
#define COM_DEEPIN_WMSWITCHER_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface com.deepin.WMSwitcher
*/
class __WMSwitcherPrivate;
class __WMSwitcher : public DBusExtendedAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.deepin.WMSwitcher"; }
public:
explicit __WMSwitcher(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~__WMSwitcher();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<bool> AllowSwitch()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("AllowSwitch"), argumentList);
}
inline QDBusPendingReply<QString> CurrentWM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("CurrentWM"), argumentList);
}
inline QDBusPendingReply<> RequestSwitchWM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RequestSwitchWM"), argumentList);
}
inline void RequestSwitchWMQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RequestSwitchWM"), argumentList);
}
inline QDBusPendingReply<> RestartWM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("RestartWM"), argumentList);
}
inline void RestartWMQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("RestartWM"), argumentList);
}
inline QDBusPendingReply<> Start2DWM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Start2DWM"), argumentList);
}
inline void Start2DWMQueued()
{
QList<QVariant> argumentList;
CallQueued(QStringLiteral("Start2DWM"), argumentList);
}
Q_SIGNALS: // SIGNALS
void WMChanged(const QString &in0);
// begin property changed signals
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);
private Q_SLOTS:
void onPendingCallFinished(QDBusPendingCallWatcher *w);
private:
__WMSwitcherPrivate *d_ptr;
};
namespace com {
namespace deepin {
typedef ::__WMSwitcher WMSwitcher;
}
}
#endif

View File

@ -0,0 +1 @@
#include "dbusextended.h"

View File

@ -0,0 +1 @@
#include "dbusextendedabstractinterface.h"

View File

@ -0,0 +1,35 @@
// -*- c++ -*-
/*!
*
* Copyright (C) 2015 Jolla Ltd.
*
* Contact: Valerio Valerio <valerio.valerio@jolla.com>
* Author: Andres Gomez <andres.gomez@jolla.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QT_DBUS_EXTENDED_H
#define QT_DBUS_EXTENDED_H
#if defined(QT_DBUS_EXTENDED_LIBRARY)
# define QT_DBUS_EXTENDED_EXPORT Q_DECL_EXPORT
#else
# define QT_DBUS_EXTENDED_EXPORT Q_DECL_IMPORT
#endif
#endif /* QT_DBUS_EXTENDED_H */

View File

@ -0,0 +1,525 @@
// -*- c++ -*-
/*!
*
* Copyright (C) 2015 Jolla Ltd.
*
* Contact: Valerio Valerio <valerio.valerio@jolla.com>
* Author: Andres Gomez <andres.gomez@jolla.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbusextendedpendingcallwatcher_p.h"
#include <DBusExtendedAbstractInterface>
#include <QtDBus/QDBusMetaType>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusPendingCall>
#include <QtDBus/QDBusPendingCallWatcher>
#include <QtDBus/QDBusPendingReply>
#include <QtCore/QDebug>
#include <QtCore/QMetaProperty>
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, dBusInterface, ("org.freedesktop.DBus"))
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, dBusPropertiesInterface, ("org.freedesktop.DBus.Properties"))
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, dBusPropertiesChangedSignal, ("PropertiesChanged"))
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, propertyChangedSignature, ("propertyChanged(QString,QVariant)"))
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, propertyInvalidatedSignature, ("propertyInvalidated(QString)"))
DBusExtendedAbstractInterface::DBusExtendedAbstractInterface(const QString &service, const QString &path, const char *interface, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, interface, connection, parent)
, m_sync(true)
, m_useCache(false)
, m_getAllPendingCallWatcher(0)
, m_propertiesChangedConnected(false)
{
const_cast<QDBusConnection&>(connection).connect(QString("org.freedesktop.DBus"), QString("/org/freedesktop/DBus"), QString("org.freedesktop.DBus"), QString("NameOwnerChanged"), this, SLOT(onDBusNameOwnerChanged(QString,QString,QString)));
}
DBusExtendedAbstractInterface::~DBusExtendedAbstractInterface()
{
}
void DBusExtendedAbstractInterface::setSync(bool sync) { setSync(sync, true); }
/*
* Note: After sync is set to false, it will always return a empty value
* if you call the property's get function directly. So you can only get it
* through the changed signal when you get an property, and it's also a good idea
* to save a cache yourself.
*/
/*
* : sync false get ,
* changed , changed
*/
void DBusExtendedAbstractInterface::setSync(bool sync, bool autoStart)
{
m_sync = sync;
// init all properties
if (autoStart && !m_sync && !isValid())
startServiceProcess();
}
void DBusExtendedAbstractInterface::getAllProperties()
{
m_lastExtendedError = QDBusError();
if (!isValid()) {
QString errorMessage = QStringLiteral("This Extended DBus interface is not valid yet.");
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qDebug() << Q_FUNC_INFO << errorMessage;
return;
}
if (!m_sync && m_getAllPendingCallWatcher) {
// Call already in place, not repeating ...
return;
}
QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), *dBusPropertiesInterface(), QStringLiteral("GetAll"));
msg << interface();
if (m_sync) {
QDBusMessage reply = connection().call(msg);
if (reply.type() != QDBusMessage::ReplyMessage) {
m_lastExtendedError = QDBusError(reply);
qWarning() << Q_FUNC_INFO << m_lastExtendedError.message();
return;
}
if (reply.signature() != QLatin1String("a{sv}")) {
QString errorMessage = QStringLiteral("Invalid signature \"%1\" in return from call to %2")
.arg(reply.signature(),
QString(*dBusPropertiesInterface()));
qWarning() << Q_FUNC_INFO << errorMessage;
m_lastExtendedError = QDBusError(QDBusError::InvalidSignature, errorMessage);
return;
}
QVariantMap value = reply.arguments().at(0).toMap();
onPropertiesChanged(interface(), value, QStringList());
} else {
QDBusPendingReply<QVariantMap> async = connection().asyncCall(msg);
m_getAllPendingCallWatcher = new QDBusPendingCallWatcher(async, this);
connect(m_getAllPendingCallWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onAsyncGetAllPropertiesFinished(QDBusPendingCallWatcher*)));
return;
}
}
void DBusExtendedAbstractInterface::connectNotify(const QMetaMethod &signal)
{
if (signal.methodType() == QMetaMethod::Signal
&& (signal.methodSignature() == *propertyChangedSignature()
|| signal.methodSignature() == *propertyInvalidatedSignature())) {
if (!m_propertiesChangedConnected) {
QStringList argumentMatch;
argumentMatch << interface();
connection().connect(service(), path(), *dBusPropertiesInterface(), *dBusPropertiesChangedSignal(),
argumentMatch, QString(),
this, SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
m_propertiesChangedConnected = true;
return;
}
} else {
QDBusAbstractInterface::connectNotify(signal);
}
}
void DBusExtendedAbstractInterface::disconnectNotify(const QMetaMethod &signal)
{
if (signal.methodType() == QMetaMethod::Signal
&& (signal.methodSignature() == *propertyChangedSignature()
|| signal.methodSignature() == *propertyInvalidatedSignature())) {
if (m_propertiesChangedConnected
&& 0 == receivers(propertyChangedSignature()->constData())
&& 0 == receivers(propertyInvalidatedSignature()->constData())) {
QStringList argumentMatch;
argumentMatch << interface();
connection().disconnect(service(), path(), *dBusPropertiesInterface(), *dBusPropertiesChangedSignal(),
argumentMatch, QString(),
this, SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
m_propertiesChangedConnected = false;
return;
}
} else {
QDBusAbstractInterface::disconnectNotify(signal);
}
}
QVariant DBusExtendedAbstractInterface::internalPropGet(const char *propname, void *propertyPtr)
{
m_lastExtendedError = QDBusError();
if (m_useCache) {
int propertyIndex = metaObject()->indexOfProperty(propname);
QMetaProperty metaProperty = metaObject()->property(propertyIndex);
return QVariant(metaProperty.userType(), propertyPtr);
}
if (m_sync) {
QVariant ret = property(propname);
QMetaType::construct(ret.userType(), propertyPtr, ret.constData());
return ret;
} else {
if (!isValid()) {
QString errorMessage = QStringLiteral("This Extended DBus interface is not valid yet.");
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qDebug() << Q_FUNC_INFO << errorMessage;
return QVariant();
}
int propertyIndex = metaObject()->indexOfProperty(propname);
if (-1 == propertyIndex) {
QString errorMessage = QStringLiteral("Got unknown property \"%1\" to read")
.arg(QString::fromLatin1(propname));
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qWarning() << Q_FUNC_INFO << errorMessage;
return QVariant();
}
QMetaProperty metaProperty = metaObject()->property(propertyIndex);
if (!metaProperty.isReadable()) {
QString errorMessage = QStringLiteral("Property \"%1\" is NOT readable")
.arg(QString::fromLatin1(propname));
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qWarning() << Q_FUNC_INFO << errorMessage;
return QVariant();
}
// is this metatype registered?
const char *expectedSignature = "";
if (int(metaProperty.type()) != QMetaType::QVariant) {
expectedSignature = QDBusMetaType::typeToSignature(metaProperty.userType());
if (0 == expectedSignature) {
QString errorMessage =
QStringLiteral("Type %1 must be registered with Qt D-Bus "
"before it can be used to read property "
"%2.%3")
.arg(metaProperty.typeName(),
interface(),
propname);
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qWarning() << Q_FUNC_INFO << errorMessage;
return QVariant();
}
}
asyncProperty(propname);
return QVariant(metaProperty.userType(), propertyPtr);
}
}
void DBusExtendedAbstractInterface::internalPropSet(const char *propname, const QVariant &value, void *propertyPtr)
{
m_lastExtendedError = QDBusError();
if (m_sync) {
setProperty(propname, value);
} else {
if (!isValid()) {
QString errorMessage = QStringLiteral("This interface is not yet valid");
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qDebug() << Q_FUNC_INFO << errorMessage;
return;
}
int propertyIndex = metaObject()->indexOfProperty(propname);
if (-1 == propertyIndex) {
QString errorMessage = QStringLiteral("Got unknown property \"%1\" to write")
.arg(QString::fromLatin1(propname));
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qWarning() << Q_FUNC_INFO << errorMessage;
return;
}
QMetaProperty metaProperty = metaObject()->property(propertyIndex);
if (!metaProperty.isWritable()) {
QString errorMessage = QStringLiteral("Property \"%1\" is NOT writable")
.arg(QString::fromLatin1(propname));
m_lastExtendedError = QDBusMessage::createError(QDBusError::Failed, errorMessage);
qWarning() << Q_FUNC_INFO << errorMessage;
return;
}
QVariant variant = QVariant(metaProperty.type(), propertyPtr);
variant = value;
asyncSetProperty(propname, variant);
}
}
QVariant DBusExtendedAbstractInterface::asyncProperty(const QString &propertyName)
{
QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), *dBusPropertiesInterface(), QStringLiteral("Get"));
msg << interface() << propertyName;
QDBusPendingReply<QVariant> async = connection().asyncCall(msg);
DBusExtendedPendingCallWatcher *watcher = new DBusExtendedPendingCallWatcher(async, propertyName, QVariant(), this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onAsyncPropertyFinished(QDBusPendingCallWatcher*)));
return QVariant();
}
void DBusExtendedAbstractInterface::asyncSetProperty(const QString &propertyName, const QVariant &value)
{
QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), *dBusPropertiesInterface(), QStringLiteral("Set"));
msg << interface() << propertyName << QVariant::fromValue(QDBusVariant(value));
QDBusPendingReply<> async = connection().asyncCall(msg);
DBusExtendedPendingCallWatcher *watcher = new DBusExtendedPendingCallWatcher(async, propertyName, value, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onAsyncSetPropertyFinished(QDBusPendingCallWatcher*)));
}
void DBusExtendedAbstractInterface::startServiceProcess()
{
const QString &servName = service();
if (isValid())
{
qWarning() << "Service" << servName << "is already started.";
return;
}
QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", *dBusInterface(), QStringLiteral("StartServiceByName"));
msg << servName << quint32(0);
QDBusPendingReply<quint32> async = connection().asyncCall(msg);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, &DBusExtendedAbstractInterface::onStartServiceProcessFinished);
}
void DBusExtendedAbstractInterface::onStartServiceProcessFinished(QDBusPendingCallWatcher *w)
{
if (w->isError())
{
m_lastExtendedError = w->error();
} else {
m_lastExtendedError = QDBusError();
}
QDBusPendingReply<quint32> reply = *w;
Q_EMIT serviceStartFinished(reply.value());
w->deleteLater();
}
void DBusExtendedAbstractInterface::onAsyncPropertyFinished(QDBusPendingCallWatcher *w)
{
DBusExtendedPendingCallWatcher *watcher = qobject_cast<DBusExtendedPendingCallWatcher *>(w);
Q_ASSERT(watcher);
QDBusPendingReply<QVariant> reply = *watcher;
if (reply.isError()) {
m_lastExtendedError = reply.error();
} else {
int propertyIndex = metaObject()->indexOfProperty(watcher->asyncProperty().toLatin1().constData());
QVariant value = demarshall(interface(),
metaObject()->property(propertyIndex),
reply.value(),
&m_lastExtendedError);
if (m_lastExtendedError.isValid()) {
Q_EMIT propertyInvalidated(watcher->asyncProperty());
} else {
Q_EMIT propertyChanged(watcher->asyncProperty(), value);
}
}
Q_EMIT asyncPropertyFinished(watcher->asyncProperty());
watcher->deleteLater();
}
void DBusExtendedAbstractInterface::onAsyncSetPropertyFinished(QDBusPendingCallWatcher *w)
{
DBusExtendedPendingCallWatcher *watcher = qobject_cast<DBusExtendedPendingCallWatcher *>(w);
Q_ASSERT(watcher);
QDBusPendingReply<> reply = *watcher;
if (reply.isError()) {
m_lastExtendedError = reply.error();
} else {
m_lastExtendedError = QDBusError();
}
Q_EMIT asyncSetPropertyFinished(watcher->asyncProperty());
// Resetting the property to its previous value after sending the
// finished signal
if (reply.isError()) {
m_lastExtendedError = QDBusError();
Q_EMIT propertyChanged(watcher->asyncProperty(), watcher->previousValue());
}
watcher->deleteLater();
}
void DBusExtendedAbstractInterface::onAsyncGetAllPropertiesFinished(QDBusPendingCallWatcher *watcher)
{
m_getAllPendingCallWatcher = 0;
QDBusPendingReply<QVariantMap> reply = *watcher;
if (reply.isError()) {
m_lastExtendedError = reply.error();
} else {
m_lastExtendedError = QDBusError();
}
Q_EMIT asyncGetAllPropertiesFinished();
if (!reply.isError()) {
onPropertiesChanged(interface(), reply.value(), QStringList());
}
watcher->deleteLater();
}
void DBusExtendedAbstractInterface::onPropertiesChanged(const QString& interfaceName,
const QVariantMap& changedProperties,
const QStringList& invalidatedProperties)
{
if (interfaceName == interface()) {
QVariantMap::const_iterator i = changedProperties.constBegin();
while (i != changedProperties.constEnd()) {
int propertyIndex = metaObject()->indexOfProperty(i.key().toLatin1().constData());
if (-1 == propertyIndex) {
qDebug() << Q_FUNC_INFO << "Got unknown changed property" << i.key();
} else {
QVariant value = demarshall(interface(), metaObject()->property(propertyIndex), i.value(), &m_lastExtendedError);
if (m_lastExtendedError.isValid()) {
Q_EMIT propertyInvalidated(i.key());
} else {
Q_EMIT propertyChanged(i.key(), value);
}
}
++i;
}
QStringList::const_iterator j = invalidatedProperties.constBegin();
while (j != invalidatedProperties.constEnd()) {
if (-1 == metaObject()->indexOfProperty(j->toLatin1().constData())) {
qDebug() << Q_FUNC_INFO << "Got unknown invalidated property" << *j;
} else {
m_lastExtendedError = QDBusError();
Q_EMIT propertyInvalidated(*j);
}
++j;
}
}
}
void DBusExtendedAbstractInterface::onDBusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
if (name == service() && oldOwner.isEmpty())
{
m_dbusOwner = newOwner;
Q_EMIT serviceValidChanged(true);
}
else if (name == m_dbusOwner && newOwner.isEmpty())
{
m_dbusOwner.clear();
Q_EMIT serviceValidChanged(false);
}
}
QVariant DBusExtendedAbstractInterface::demarshall(const QString &interface, const QMetaProperty &metaProperty, const QVariant &value, QDBusError *error)
{
Q_ASSERT(metaProperty.isValid());
Q_ASSERT(error != 0);
if (value.userType() == metaProperty.userType()) {
// No need demarshalling. Passing back straight away ...
*error = QDBusError();
return value;
}
QVariant result = QVariant(metaProperty.userType(), (void*)0);
QString errorMessage;
const char *expectedSignature = QDBusMetaType::typeToSignature(metaProperty.userType());
if (value.userType() == qMetaTypeId<QDBusArgument>()) {
// demarshalling a DBus argument ...
QDBusArgument dbusArg = value.value<QDBusArgument>();
if (expectedSignature == dbusArg.currentSignature().toLatin1()) {
QDBusMetaType::demarshall(dbusArg, metaProperty.userType(), result.data());
if (!result.isValid()) {
errorMessage = QStringLiteral("Unexpected failure demarshalling "
"upon PropertiesChanged signal arrival "
"for property `%3.%4' (expected type `%5' (%6))")
.arg(interface,
QString::fromLatin1(metaProperty.name()),
QString::fromLatin1(metaProperty.typeName()),
expectedSignature);
}
} else {
errorMessage = QStringLiteral("Unexpected `user type' (%2) "
"upon PropertiesChanged signal arrival "
"for property `%3.%4' (expected type `%5' (%6))")
.arg(dbusArg.currentSignature(),
interface,
QString::fromLatin1(metaProperty.name()),
QString::fromLatin1(metaProperty.typeName()),
QString::fromLatin1(expectedSignature));
}
} else {
const char *actualSignature = QDBusMetaType::typeToSignature(value.userType());
errorMessage = QStringLiteral("Unexpected `%1' (%2) "
"upon PropertiesChanged signal arrival "
"for property `%3.%4' (expected type `%5' (%6))")
.arg(QString::fromLatin1(value.typeName()),
QString::fromLatin1(actualSignature),
interface,
QString::fromLatin1(metaProperty.name()),
QString::fromLatin1(metaProperty.typeName()),
QString::fromLatin1(expectedSignature));
}
if (errorMessage.isEmpty()) {
*error = QDBusError();
} else {
*error = QDBusMessage::createError(QDBusError::InvalidSignature, errorMessage);
qDebug() << Q_FUNC_INFO << errorMessage;
}
return result;
}

View File

@ -0,0 +1,103 @@
// -*- c++ -*-
/*!
*
* Copyright (C) 2015 Jolla Ltd.
*
* Contact: Valerio Valerio <valerio.valerio@jolla.com>
* Author: Andres Gomez <andres.gomez@jolla.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DBUSEXTENDEDABSTRACTINTERFACE_H
#define DBUSEXTENDEDABSTRACTINTERFACE_H
#include <DBusExtended>
#include <QDBusAbstractInterface>
#include <QDBusError>
class QDBusPendingCallWatcher;
class DBusExtendedPendingCallWatcher;
class QT_DBUS_EXTENDED_EXPORT DBusExtendedAbstractInterface: public QDBusAbstractInterface
{
Q_OBJECT
public:
virtual ~DBusExtendedAbstractInterface();
Q_PROPERTY(bool sync READ sync WRITE setSync)
inline bool sync() const { return m_sync; }
void setSync(bool sync);
void setSync(bool sync, bool autoStart);
Q_PROPERTY(bool useCache READ useCache WRITE setUseCache)
inline bool useCache() const { return m_useCache; }
inline void setUseCache(bool useCache) { m_useCache = useCache; }
void getAllProperties();
inline QDBusError lastExtendedError() const { return m_lastExtendedError; }
public Q_SLOTS:
void startServiceProcess();
protected:
DBusExtendedAbstractInterface(const QString &service,
const QString &path,
const char *interface,
const QDBusConnection &connection,
QObject *parent);
void connectNotify(const QMetaMethod &signal);
void disconnectNotify(const QMetaMethod &signal);
QVariant internalPropGet(const char *propname, void *propertyPtr);
void internalPropSet(const char *propname, const QVariant &value, void *propertyPtr);
Q_SIGNALS:
void serviceValidChanged(const bool valid) const;
void serviceStartFinished(const quint32 ret) const;
void propertyChanged(const QString &propertyName, const QVariant &value);
void propertyInvalidated(const QString &propertyName);
void asyncPropertyFinished(const QString &propertyName);
void asyncSetPropertyFinished(const QString &propertyName);
void asyncGetAllPropertiesFinished();
private Q_SLOTS:
void onPropertiesChanged(const QString& interfaceName,
const QVariantMap& changedProperties,
const QStringList& invalidatedProperties);
void onDBusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
void onAsyncPropertyFinished(QDBusPendingCallWatcher *w);
void onAsyncSetPropertyFinished(QDBusPendingCallWatcher *w);
void onAsyncGetAllPropertiesFinished(QDBusPendingCallWatcher *watcher);
void onStartServiceProcessFinished(QDBusPendingCallWatcher *w);
private:
QVariant asyncProperty(const QString &propertyName);
void asyncSetProperty(const QString &propertyName, const QVariant &value);
static QVariant demarshall(const QString &interface, const QMetaProperty &metaProperty, const QVariant &value, QDBusError *error);
bool m_sync;
bool m_useCache;
QDBusPendingCallWatcher *m_getAllPendingCallWatcher;
QDBusError m_lastExtendedError;
QString m_dbusOwner;
bool m_propertiesChangedConnected;
};
#endif /* DBUSEXTENDEDABSTRACTINTERFACE_H */

View File

@ -0,0 +1,38 @@
// -*- c++ -*-
/*!
*
* Copyright (C) 2015 Jolla Ltd.
*
* Contact: Valerio Valerio <valerio.valerio@jolla.com>
* Author: Andres Gomez <andres.gomez@jolla.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbusextendedpendingcallwatcher_p.h"
DBusExtendedPendingCallWatcher::DBusExtendedPendingCallWatcher(const QDBusPendingCall &call, const QString &asyncProperty, const QVariant &previousValue, QObject *parent)
: QDBusPendingCallWatcher(call, parent)
, m_asyncProperty(asyncProperty)
, m_previousValue(previousValue)
{
}
DBusExtendedPendingCallWatcher::~DBusExtendedPendingCallWatcher()
{
}

View File

@ -0,0 +1,67 @@
// -*- c++ -*-
/*!
*
* Copyright (C) 2015 Jolla Ltd.
*
* Contact: Valerio Valerio <valerio.valerio@jolla.com>
* Author: Andres Gomez <andres.gomez@jolla.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// W A R N I N G
// -------------
//
// This file is not part of the public API. This header file may
// change from version to version without notice, or even be
// removed.
//
// We mean it.
//
//
#ifndef DBUSEXTENDEDPENDINGCALLWATCHER_P_H
#define DBUSEXTENDEDPENDINGCALLWATCHER_P_H
#include <QDBusPendingCallWatcher>
#include <QDBusError>
class DBusExtendedPendingCallWatcher: public QDBusPendingCallWatcher
{
Q_OBJECT
public:
explicit DBusExtendedPendingCallWatcher(const QDBusPendingCall &call,
const QString &asyncProperty,
const QVariant &previousValue,
QObject *parent = 0);
~DBusExtendedPendingCallWatcher();
Q_PROPERTY(QString AsyncProperty READ asyncProperty)
inline QString asyncProperty() const { return m_asyncProperty; }
Q_PROPERTY(QVariant PreviousValue READ previousValue)
inline QVariant previousValue() const { return m_previousValue; }
private:
QString m_asyncProperty;
QVariant m_previousValue;
};
#endif /* DBUSEXTENDEDPENDINGCALLWATCHER_P_H */

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd.
*
* Author: LiLinling <lilinling_cm@deepin.com>
*
* Maintainer: LiLinling <lilinling_cm@deepin.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 "launcheriteminfo.h"
bool LauncherItemInfo::operator!=(const LauncherItemInfo &itemInfo)
{
return itemInfo.ID != ID;
}
QDBusArgument &operator<<(QDBusArgument &argument, const LauncherItemInfo &itemInfo)
{
argument.beginStructure();
argument << itemInfo.Path << itemInfo.Name << itemInfo.ID << itemInfo.Icon << itemInfo.CategoryID << itemInfo.TimeInstalled;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, LauncherItemInfo &itemInfo)
{
argument.beginStructure();
argument >> itemInfo.Path >> itemInfo.Name >> itemInfo.ID >> itemInfo.Icon >> itemInfo.CategoryID >> itemInfo.TimeInstalled;
argument.endStructure();
return argument;
}
void registerLauncherItemInfoMetaType()
{
qRegisterMetaType<LauncherItemInfo>("ItemInfo");
qDBusRegisterMetaType<LauncherItemInfo>();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd.
*
* Author: LiLinling <lilinling_cm@deepin.com>
*
* Maintainer: LiLinling <lilinling_cm@deepin.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/>.
*/
#pragma once
#include <QtCore/QString>
#include <QtDBus/QtDBus>
#include <QtCore/QList>
#include <QDBusMetaType>
struct LauncherItemInfo {
QString Path;
QString Name;
QString ID;
QString Icon;
qint64 CategoryID;
qint64 TimeInstalled;
bool operator!=(const LauncherItemInfo &versionInfo);
};
Q_DECLARE_METATYPE(LauncherItemInfo)
QDBusArgument &operator<<(QDBusArgument &argument, const LauncherItemInfo &versionInfo);
const QDBusArgument &operator>>(const QDBusArgument &argument, LauncherItemInfo &versionInfo);
void registerLauncherItemInfoMetaType();

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd.
*
* Author: LiLinling <lilinling_cm@deepin.com>
*
* Maintainer: LiLinling <lilinling_cm@deepin.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 "launcheriteminfolist.h"
void registerLauncherItemInfoListMetaType()
{
qRegisterMetaType<LauncherItemInfo>("ItemInfoList");
qDBusRegisterMetaType<LauncherItemInfoList>();
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd.
*
* Author: LiLinling <lilinling_cm@deepin.com>
*
* Maintainer: LiLinling <lilinling_cm@deepin.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/>.
*/
#pragma once
#include "launcheriteminfo.h"
#include <QtCore/QList>
#include <QDBusMetaType>
typedef QList<LauncherItemInfo> LauncherItemInfoList;
Q_DECLARE_METATYPE(LauncherItemInfoList)
void registerLauncherItemInfoListMetaType();

View File

@ -0,0 +1,50 @@
#include "rect.h"
#include <QDebug>
Rect::Rect()
: X(0)
, Y(0)
, Width(0)
, Height(0)
{
}
QDebug operator<<(QDebug debug, const Rect &rect)
{
debug << QString("Rect(%1, %2, %3, %4)").arg(rect.X)
.arg(rect.Y)
.arg(rect.Width)
.arg(rect.Height);
return debug;
}
Rect::operator QRect() const
{
return QRect(X, Y, Width, Height);
}
QDBusArgument &operator<<(QDBusArgument &arg, const Rect &rect)
{
arg.beginStructure();
arg << rect.X << rect.Y << rect.Width << rect.Height;
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>(const QDBusArgument &arg, Rect &rect)
{
arg.beginStructure();
arg >> rect.X >> rect.Y >> rect.Width >> rect.Height;
arg.endStructure();
return arg;
}
void registerRectMetaType()
{
qRegisterMetaType<Rect>("Rect");
qDBusRegisterMetaType<Rect>();
}

View File

@ -0,0 +1,25 @@
#ifndef DOCKRECT_H
#define DOCKRECT_H
#include <QRect>
#include <QDBusMetaType>
struct Rect
{
public:
Rect();
operator QRect() const;
friend QDebug operator<<(QDebug debug, const Rect &rect);
friend const QDBusArgument &operator>>(const QDBusArgument &arg, Rect &rect);
friend QDBusArgument &operator<<(QDBusArgument &arg, const Rect &rect);
private:
qint32 X, Y, Width, Height;
};
Q_DECLARE_METATYPE(Rect)
void registerRectMetaType();
#endif // DOCKRECT_H

169
src/lib/basedir.cpp Normal file
View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "basedir.h"
#include "dfile.h"
#include "dstring.h"
#include <algorithm>
BaseDir::BaseDir()
{
}
std::string BaseDir::homeDir()
{
char *home = getenv("HOME");
if (!home)
return "";
return std::string(home) + "/";
}
std::string BaseDir::uerDataDir()
{
// default $HOME/.local/share
std::string home = homeDir();
std::string defaultDir = home.size() > 0 ? home + ".local/share/" : "";
const char *xdgDataHomePtr = getenv("XDG_DATA_HOME");
if (!xdgDataHomePtr)
return defaultDir;
if (!DFile::isAbs(xdgDataHomePtr))
return defaultDir;
return std::string(xdgDataHomePtr) + "/";
}
std::vector<std::string> BaseDir::sysDataDirs()
{
std::vector<std::string> defaultDirs {"/usr/local/share/", "/usr/share/"};
const char *xdgDataDirsPtr = getenv("XDG_DATA_DIRS");
if (!xdgDataDirsPtr)
return defaultDirs;
std::string xdgDataDirsStr(xdgDataDirsPtr);
std::vector<std::string> xdgDataDirs = DString::splitStr(xdgDataDirsStr, ':');
if (xdgDataDirs.size() == 0)
return defaultDirs;
filterNotAbs(xdgDataDirs);
addSuffixSlash(xdgDataDirs);
return xdgDataDirs;
}
std::string BaseDir::userConfigDir()
{
// default $HOME/.config
std::string defaultDir = homeDir() + ".config/";
const char *xdgConfigHomePtr = getenv("XDG_CONFIG_HOME");
if (!xdgConfigHomePtr)
return defaultDir;
std::string xdgConfigHome(xdgConfigHomePtr);
if (!DFile::isAbs(xdgConfigHome))
return defaultDir;
return xdgConfigHome + "/";
}
std::vector<std::string> BaseDir::sysConfigDirs()
{
std::vector<std::string> defaultDirs {"/etc/xdg/"};
const char *xdgConfigDirsPtr = getenv("XDG_CONFIG_DIRS");
if (!xdgConfigDirsPtr)
return defaultDirs;
std::string xdgConfigDirsStr(xdgConfigDirsPtr);
std::vector<std::string> xdgConfigDirs = DString::splitStr(xdgConfigDirsStr, ':');
if (xdgConfigDirs.size() == 0)
return defaultDirs;
filterNotAbs(xdgConfigDirs);
addSuffixSlash(xdgConfigDirs);
return xdgConfigDirs;
}
std::string BaseDir::userCacheDir()
{
std::string home = homeDir();
std::string defaultDir = home.size() > 0 ? home + ".cache/" : "";
const char *xdgCacheHomePtr = getenv("XDG_CACHE_HOME");
if (!xdgCacheHomePtr)
return defaultDir;
std::string xdgCacheHome(xdgCacheHomePtr);
if (!DFile::isAbs(xdgCacheHome))
return defaultDir;
return xdgCacheHome + "/";
}
std::string BaseDir::userAppDir()
{
std::string dataDir = uerDataDir();
return dataDir.size() > 0 ? dataDir + "appliations/" : "";
}
std::vector<std::string> BaseDir::sysAppDirs()
{
auto dataDirs = sysDataDirs();
std::vector<std::string> sysAppDirs(dataDirs.size());
std::transform(dataDirs.begin(), dataDirs.end(), sysAppDirs.begin(),
[](std::string dir) -> std::string {return dir + "applications/";});
return sysAppDirs;
}
std::vector<std::string> BaseDir::appDirs()
{
std::vector<std::string> appDirs = sysAppDirs();
appDirs.push_back(userAppDir());
return appDirs;
}
std::vector<std::string> BaseDir::autoStartDirs()
{
std::vector<std::string> autoStartDirs = sysConfigDirs();
autoStartDirs.push_back(userConfigDir());
std::transform(autoStartDirs.begin(), autoStartDirs.end(), autoStartDirs.begin(),
[](std::string dir) -> std::string {return dir + "autostart/";});
return autoStartDirs;
}
void BaseDir::filterNotAbs(std::vector<std::string> &dirs)
{
for (auto iter = dirs.begin(); iter != dirs.end();) { // erase element in vector
if (!DFile::isAbs(*iter))
iter = dirs.erase(iter);
else
iter++;
}
}
void BaseDir::addSuffixSlash(std::vector<std::string> &dirs)
{
for (auto &dir : dirs) {
if (!DString::endWith(dir, "/"))
dir += "/";
}
}

50
src/lib/basedir.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BASEDIR_H
#define BASEDIR_H
#include <vector>
#include <string>
// 基础目录类, 目录结尾统一包含斜杠/
class BaseDir
{
public:
BaseDir();
static std::string homeDir();
static std::string uerDataDir();
static std::vector<std::string> sysDataDirs();
static std::string userConfigDir();
static std::vector<std::string> sysConfigDirs();
static std::string userCacheDir();
static std::string userAppDir();
static std::vector<std::string> sysAppDirs();
static std::vector<std::string> appDirs();
static std::vector<std::string> autoStartDirs();
private:
static void filterNotAbs(std::vector<std::string> &dirs);
static void addSuffixSlash(std::vector<std::string> &dirs);
};
#endif // BASEDIR_H

380
src/lib/desktopinfo.cpp Normal file
View File

@ -0,0 +1,380 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "desktopinfo.h"
#include "locale.h"
#include "unistd.h"
#include "dstring.h"
#include "dfile.h"
#include "basedir.h"
#include <algorithm>
#include <stdlib.h>
#include <iostream>
#include <dirent.h>
std::vector<std::string> DesktopInfo::currentDesktops;
DesktopInfo::DesktopInfo(const std::string &_fileName)
: kf(KeyFile())
, fileName(_fileName)
, isValid(true)
{
if (!DString::endWith(fileName, ".desktop"))
fileName += ".desktop";
if (!DFile::isAbs(fileName)) {
// fileName是文件名增加目录
bool isExisted = false;
for (const auto &dir : BaseDir::appDirs()) {
fileName = dir + fileName;
if (DFile::isExisted(fileName)) {
isExisted = true;
break;
}
}
if (!isExisted) {
isValid = false;
return;
}
}
kf.loadFile(fileName);
// check DesktopInfo valid
if (fileName.find(".desktop") == std::string::npos)
isValid = false;
std::vector<std::string> mainKeys = kf.getMainKeys();
if (mainKeys.size() == 0)
isValid = false;
bool found = std::any_of(mainKeys.begin(), mainKeys.end(),
[](const auto &key) {return key == MainSection;});
if (!found)
isValid = false;
if (kf.getStr(MainSection, KeyType) != TypeApplication)
isValid = false;
name = kf.getLocaleStr(MainSection, KeyName, "");
icon = kf.getStr(MainSection, KeyIcon);
id = getId();
}
DesktopInfo::~DesktopInfo()
{
}
std::string DesktopInfo::getFileName()
{
return fileName;
}
bool DesktopInfo::isValidDesktop()
{
return isValid;
}
bool DesktopInfo::shouldShow()
{
if (getNoDisplay() || getIsHidden())
return false;
std::vector<std::string> desktopEnvs;
return getShowIn(desktopEnvs);
}
bool DesktopInfo::getNoDisplay()
{
return kf.getBool(MainSection, KeyNoDisplay);
}
bool DesktopInfo::getIsHidden()
{
return kf.getBool(MainSection, KeyHidden);
}
bool DesktopInfo::getShowIn(std::vector<std::string> desktopEnvs)
{
if (desktopEnvs.size() == 0) {
if (currentDesktops.size() == 0) {
const char *env = getenv(envDesktopEnv.c_str());
const auto &desktop = DString::splitChars(env, ':');
currentDesktops.assign(desktop.begin(), desktop.end());
}
desktopEnvs.assign(currentDesktops.begin(), currentDesktops.end());
}
std::vector<std::string> onlyShowIn = kf.getStrList(MainSection, KeyOnlyShowIn);
std::vector<std::string> notShowIn = kf.getStrList(MainSection, KeyNotShowIn);
for (const auto &desktop : desktopEnvs) {
bool ret = std::any_of(onlyShowIn.begin(), onlyShowIn.end(),
[&desktop](const auto &d) {return d == desktop;});
if (ret)
return true;
ret = std::any_of(notShowIn.begin(), notShowIn.end(),
[&desktop](const auto &d) {return d == desktop;});
if (ret)
return false;
}
return onlyShowIn.size() == 0;
}
std::string DesktopInfo::getExecutable()
{
return kf.getStr(MainSection, KeyExec);
}
bool DesktopInfo::isExecutableOk()
{
// 检查TryExec字段
std::string value = getTryExec();
std::vector<std::string> parts = DString::splitStr(value, ' ');
if (parts.size() > 0 ) {
value.assign(parts[0]);
DString::delQuote(value);
if (strstr(value.c_str(), "/") && DFile::isExisted(value))
return true;
else
return findExecutable(value);
}
// 检查Exec字段
value.assign(getExecutable());
parts.clear();
parts = DString::splitStr(value, ' ');
if (parts.size() > 0) {
value.assign(parts[0]);
DString::delQuote(value);
if (strstr(value.c_str(), "/") && DFile::isExisted(value))
return true;
else
return findExecutable(value);
}
return false;
}
bool DesktopInfo::isInstalled()
{
const char *name = fileName.c_str();
const char *found = strstr(name, "/applications/");
if (!found)
return false;
auto appDirs = BaseDir::appDirs();
return std::any_of(appDirs.begin(), appDirs.end(),
[&name, &found] (std::string dir) -> bool {return strneq(dir.c_str(), name, size_t(found - name));});
}
std::vector<DesktopAction> DesktopInfo::getActions()
{
std::vector<DesktopAction> actions;
for (const auto &mainKey : kf.getMainKeys()) {
if (DString::startWith(mainKey, "Desktop Action")
|| DString::endWith(mainKey, "Shortcut Group")) {
DesktopAction action;
action.name = kf.getLocaleStr(mainKey, KeyName, "");
action.exec = kf.getStr(mainKey, KeyExec);
actions.push_back(action);
}
}
return actions;
}
// 使用appId获取DesktopInfo需检查有效性
DesktopInfo DesktopInfo::getDesktopInfoById(std::string appId)
{
if (!DString::endWith(appId, ".desktop"))
appId += ".desktop";
for (const auto & dir : BaseDir::appDirs()) {
std::string filePath = dir + appId;
//检测文件有效性
if (DFile::isExisted(filePath)) {
return DesktopInfo(filePath);
}
}
return DesktopInfo("");
}
// TryExec is Path to an executable file on disk used to determine if the program is actually installed
std::string DesktopInfo::getTryExec()
{
return kf.getStr(MainSection, KeyTryExec);
}
// 按$PATH路径查找执行文件
bool DesktopInfo::findExecutable(std::string &exec)
{
static const char *path = getenv("PATH");
static std::vector<std::string> paths = DString::splitChars(path, ':');
return std::any_of(paths.begin(), paths.end(), [&exec](std::string path) {return DFile::isExisted(path + "/" +exec);});
}
// filename must has suffix desktopExt
// example:
// /usr/share/applications/a.desktop -> a
// /usr/share/applications/kde4/a.desktop -> kde4/a
// /xxxx/dir/a.desktop -> /xxxx/dir/a
std::string DesktopInfo::getId()
{
if (!id.empty())
return id;
std::string idStr;
auto const suffixPos = fileName.find(".desktop");
if (suffixPos == std::string::npos)
return "";
idStr = fileName.substr(0, fileName.size() - 8); // trim suffix
size_t dirPos = idStr.find("/applications/");
if (dirPos == std::string::npos)
return "";
std::string baseDir(idStr.substr(0, dirPos + 14)); // length of "/applications/" is 14
std::vector<std::string> appDirs = BaseDir::appDirs();
bool installed = std::any_of(appDirs.begin(), appDirs.end(),
[&baseDir](const auto &dir) {return dir == baseDir;});
if (installed) {
id = idStr.substr(baseDir.size(), idStr.size());
}
return id;
}
std::string DesktopInfo::getGenericName()
{
return kf.getLocaleStr(MainSection, KeyGenericName, "");
}
std::string DesktopInfo::getName()
{
return name;
}
std::string DesktopInfo::getIcon()
{
return icon;
}
std::string DesktopInfo::getCommandLine()
{
return kf.getStr(MainSection, KeyExec);
}
std::vector<std::string> DesktopInfo::getKeywords()
{
return kf.getLocaleStrList(MainSection, KeyKeywords, "");
}
std::vector<std::string> DesktopInfo::getCategories()
{
return kf.getStrList(MainSection, KeyCategories);
}
// class AppsDir
AppsDir::AppsDir(const std::string &dirPath)
: path(dirPath)
{
}
AppsDir::~AppsDir()
{
}
std::string AppsDir::getPath()
{
return path;
}
// 获取目录对应的应用名称
std::map<std::string, bool> AppsDir::getAppNames()
{
DIR* dp;
struct dirent* ep;
dp = opendir(path.c_str());
if (dp == nullptr)
{
std::cout << "Couldn't open directory " << path << std::endl;
return appNames;
}
while ((ep = readdir(dp))) {
if (ep->d_type != DT_REG && ep->d_type != DT_LNK)
continue;
if (!DString::endWith(ep->d_name, ".desktop"))
continue;
appNames.insert({ep->d_name, true});
}
closedir(dp);
return appNames;
}
// 获取所有应用信息
std::vector<DesktopInfo> AppsDir::getAllDesktopInfos()
{
std::map<std::string, bool> recoder;
std::vector<DesktopInfo> desktopInfos;
for (auto dir : BaseDir::appDirs()) {
AppsDir appsDir(dir);
std::map<std::string, bool> appNames = appsDir.getAppNames();
if (appNames.size() == 0)
continue;
for (const auto &iter : appNames) {
if (recoder.find(iter.first) != recoder.end())
continue;
std::string filePath = dir + iter.first;
DesktopInfo desktopInfo(filePath);
if (!desktopInfo.isValidDesktop())
continue;
if (!desktopInfo.shouldShow())
continue;
desktopInfos.push_back(std::move(desktopInfo));
recoder[iter.first] = true;
}
}
return desktopInfos;
}

121
src/lib/desktopinfo.h Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DESKTOPINFO_H
#define DESKTOPINFO_H
#include "keyfile.h"
#include <string>
#include <vector>
const std::string MainSection = "Desktop Entry";
const std::string KeyType = "Type";
const std::string KeyVersion = "Version";
const std::string KeyName = "Name";
const std::string KeyGenericName = "GenericName";
const std::string KeyNoDisplay = "NoDisplay";
const std::string KeyComment = "Comment";
const std::string KeyIcon = "Icon";
const std::string KeyHidden = "Hidden";
const std::string KeyOnlyShowIn = "OnlyShowIn";
const std::string KeyNotShowIn = "NotShowIn";
const std::string KeyTryExec = "TryExec";
const std::string KeyExec = "Exec";
const std::string KeyPath = "Path";
const std::string KeyTerminal = "Terminal";
const std::string KeyMimeType = "MimeType";
const std::string KeyCategories = "Categories";
const std::string KeyKeywords = "Keywords";
const std::string KeyStartupNotify = "StartupNotify";
const std::string KeyStartupWMClass = "StartupWMClass";
const std::string KeyURL = "URL";
const std::string KeyActions = "Actions";
const std::string KeyDBusActivatable = "DBusActivatable";
const std::string TypeApplication = "Application";
const std::string TypeLink = "Link";
const std::string TypeDirectory = "Directory";
const std::string envDesktopEnv = "XDG_CURRENT_DESKTOP";
typedef struct DesktopAction {
std::string section;
std::string name;
std::string exec;
} DesktopAction;
// 应用Desktop信息类
class DesktopInfo {
public:
explicit DesktopInfo(const std::string &_fileName);
~DesktopInfo();
std::string getFileName();
std::string getExecutable();
bool isValidDesktop();
bool shouldShow();
bool getNoDisplay();
bool getIsHidden();
bool getShowIn(std::vector<std::string> desktopEnvs);
bool isExecutableOk();
bool isInstalled();
std::vector<DesktopAction> getActions();
static DesktopInfo getDesktopInfoById(std::string appId);
std::string getId();
std::string getGenericName();
std::string getName();
std::string getIcon();
std::string getCommandLine();
std::vector<std::string> getKeywords();
std::vector<std::string> getCategories();
KeyFile kf;
private:
std::string getTryExec();
bool findExecutable(std::string &exec);
std::string fileName;
std::string id;
std::string name;
std::string icon;
std::string overRideExec;
bool isValid;
static std::vector<std::string> currentDesktops;
};
// 应用目录类
class AppsDir {
public:
explicit AppsDir(const std::string &dirPath);
~AppsDir();
std::string getPath();
std::map<std::string, bool> getAppNames();
static std::vector<DesktopInfo> getAllDesktopInfos();
private:
std::string path;
std::map<std::string, bool> appNames;
};
#endif // DESKTOPINFO_H

79
src/lib/dfile.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dfile.h"
#include "macro.h"
#include <unistd.h>
#include <cstring>
DFile::DFile()
{
}
bool DFile::isAbs(std::string file)
{
char resolved_path[MAX_FILEPATH_LEN];
if (realpath(file.c_str(), resolved_path)) {
std::string filePath(resolved_path);
if (filePath == file)
return true;
}
return false;
}
bool DFile::isExisted(std::string file)
{
return !access(file.c_str(), F_OK);
}
std::string DFile::dir(std::string file)
{
std::string ret;
if (isAbs(file)) {
size_t pos = file.find_last_of("/");
if (pos != std::string::npos) {
ret.assign(file, 0, pos + 1); // 包含结尾斜杠/
}
}
return ret;
}
std::string DFile::base(std::string file)
{
std::string ret;
if (strstr(file.c_str(), "/")) { // 包含路径
size_t pos = file.find_last_of("/");
if (pos != std::string::npos) {
ret.assign(file, pos + 1, file.size() - pos); // 去除路径
}
}
size_t pos = file.find_last_of("."); // 去除后缀
if (pos != std::string::npos) {
ret.assign(file, 0, pos + 1);
}
return ret;
}

37
src/lib/dfile.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DFILE_H
#define DFILE_H
#include <string>
class DFile
{
public:
explicit DFile();
static bool isAbs(std::string file);
static bool isExisted(std::string file);
static std::string dir(std::string file);
static std::string base(std::string file);
};
#endif // DFILE_H

210
src/lib/dlocale.cpp Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dlocale.h"
#include "dstring.h"
#include <stdlib.h>
#include <pthread.h>
#define ComponentCodeset 1
#define ComponentTerritory 2
#define ComponentModifier 4
#define MAXLINELEN 256
const char *aliasFile = "/usr/share/locale/locale.alias";
const char charUscore = '_';
const char charDot = '.';
const char charAt = '@';
Locale::Locale()
{
pthread_mutex_init(&languageNames.mutex, nullptr);
// init aliases
FILE *fp = fopen(aliasFile, "r");
if (fp) {
char data[MAXLINELEN] = {0};
std::string line;
std::vector<std::string> parts;
while (fgets(data, MAXLINELEN, fp)) {
char *start = &data[0];
char *end = start;
// 移除行首
while (strneq(start, " ", 1) || strneq(start, "\t", 1))
start++;
// 过滤注释行和空行
if (strneq(start, "#", 1) || strneq(start, "\n", 1))
continue;
while (!strneq(end, "\n", 1))
end++;
// 移除行尾
while (strneq(end, "\n", 1) || strneq(end, "\r", 1)
|| strneq(end, " ", 1) || strneq(end, "\t", 1))
end--;
line.assign(start, ulong(end - start + 1));
parts = DString::splitStr(line, ' ');
// 使用\t分割
if (parts.size() != 2)
parts = DString::splitStr(line, '\t');
if (parts.size() == 2) {
aliases[parts[0]] = parts[1];
}
}
fclose(fp);
}
}
// wayland environment is useful?
// ExplodeLocale Break an X/Open style locale specification into components
Locale::Components Locale::explodeLocale(std::string locale)
{
Components cmp;
std::vector<std::string> parts;
if (locale.find(charAt) != std::string::npos) {
parts = DString::splitStr(locale, charAt);
if (parts.size() == 2) {
cmp.modifier = parts[1];
locale = parts[0];
cmp.mask |= ComponentModifier;
}
}
if (locale.find(charDot) != std::string::npos) {
parts = DString::splitStr(locale, charDot);
if (parts.size() == 2) {
cmp.codeset = parts[1];
locale = locale[0];
cmp.mask |= ComponentCodeset;
}
}
if (locale.find(charUscore) != std::string::npos) {
parts = DString::splitStr(locale, charUscore);
if (parts.size() == 2) {
cmp.territory = parts[1];
locale = parts[0];
cmp.mask |= ComponentTerritory;
}
}
cmp.language = locale;
return cmp;
}
std::string Locale::guessCategoryValue(std::string categoryName)
{
// The highest priority value is the 'LANGUAGE' environment
// variable. This is a GNU extension.
const char *language = getenv("LANGUAGE");
if (language)
return language;
// Setting of LC_ALL overwrites all other.
const char *lcAll = getenv("LC_ALL");
if (lcAll)
return lcAll;
// Next comes the name of the desired category.
const char *name = getenv(categoryName.c_str());
if (name)
return name;
// Last possibility is the LANG environment variable.
const char *lang = getenv("LANG");
if (lang)
return lang;
return "C";
}
std::string Locale::unaliasLang(std::string lang)
{
if (aliases.find(lang) != aliases.end())
return aliases[lang];
else
return lang;
}
// wayland environment is useful?
/*
* Compute all interesting variants for a given locale name -
* by stripping off different components of the value.
*
* For simplicity, we assume that the locale is in
* X/Open format: language[_territory][.codeset][@modifier]
*/
std::vector<std::string> Locale::getLocaleVariants(const std::string &locale)
{
auto cmp = explodeLocale(locale);
uint mask = cmp.mask;
std::vector<std::string> variants;
for (uint i = 0; i <= mask; i++) {
uint j = mask - i;
//if ((j & ^mask) == 0) {
std::string var(cmp.language);
if (j & ComponentTerritory)
var = var + charUscore + cmp.territory;
if (j & ComponentCodeset)
var = var + charDot + cmp.codeset;
if (j & ComponentModifier)
var = var + charAt + cmp.modifier;
variants.push_back(var);
//}
}
return variants;
}
std::vector<std::string> Locale::getLanguageNames()
{
std::vector<std::string> names;
std::string value(guessCategoryValue("LC_MESSAGES"));
if (value.empty()) {
names.push_back(value);
return names;
}
pthread_mutex_lock(&languageNames.mutex);
if (languageNames.language != value) {
languageNames.language = value;
languageNames.names.clear();
std::vector<std::string> langs = DString::splitStr(value, ':');
for (const auto & lang : langs) {
std::vector<std::string> localeVariant = getLocaleVariants(unaliasLang(lang));
for (const auto & var : localeVariant)
languageNames.names.push_back(var);
}
languageNames.names.push_back("C");
}
pthread_mutex_unlock(&languageNames.mutex);
return languageNames.names;
}

66
src/lib/dlocale.h Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOCALE_H
#define LOCALE_H
#include <string>
#include <vector>
#include <map>
// 本地化类
class Locale {
struct LanguageNameCache {
std::string language;
std::vector<std::string> names;
pthread_mutex_t mutex;
};
struct Components {
Components() : mask(0) {} // 数字必须初始化
std::string language;
std::string territory;
std::string codeset;
std::string modifier;
uint mask;
};
public:
std::vector<std::string> getLocaleVariants(const std::string &locale);
std::vector<std::string> getLanguageNames();
static inline Locale *instance() {
static Locale instance;
return &instance;
}
private:
Locale();
Locale(const Locale &);
Locale& operator= (const Locale &);
Components explodeLocale(std::string locale);
std::string guessCategoryValue(std::string categoryName);
std::string unaliasLang(std::string);
std::map<std::string, std::string> aliases;
LanguageNameCache languageNames;
};
#endif

147
src/lib/dstring.cpp Normal file
View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dstring.h"
#include <assert.h>
DString::DString()
{
}
DString::~DString()
{
}
std::vector<std::string> DString::splitChars(const char *cs, char c)
{
assert(cs);
std::vector<std::string> ret;
unsigned long idx = 0;
unsigned long size = strlen(cs);
bool found = false;
std::string sub;
for (unsigned long i=0; i < size; i++) {
if (!strneq(&cs[i], &c, 1))
continue;
sub.assign(cs, found ? idx+1:idx, found ? i-idx-1:i-idx);
if (idx < i && !sub.empty()) {
ret.push_back(sub);
}
idx = i;
found = true;
}
sub.assign(cs, found ? idx+1:idx, found ? size-idx-1:size-idx);
if (idx < size && !sub.empty()) {
ret.push_back(sub);
}
return ret;
}
std::vector<std::string> DString::splitStr(const std::string &str, char c)
{
return splitChars(str.c_str(), c);
}
std::vector<std::string> DString::splitVectorChars(const std::vector<char> &content, size_t length, char c)
{
std::vector<std::string> ret;
size_t pos = 0;
bool hasChar = true;
for (size_t i = 0; i < length; i++) {
if (content[i] == c && i > pos && hasChar) {
std::string str;
for (size_t j = pos; j <= i; j++) {
str += std::string(1, content[j]);
}
ret.push_back(str);
pos = i + 1;
hasChar = false;
} else {
hasChar = true;
}
}
return ret;
}
bool DString::startWith(const char *chars, const char *prefix)
{
assert(chars);
assert(prefix);
size_t len;
len = strlen(prefix);
return strneq(chars, prefix, len);
}
bool DString::startWith(const std::string &str, const std::string &prefix)
{
return startWith(str.c_str(), prefix.c_str());
}
bool DString::endWith(const char *chars, const char *suffix)
{
assert(chars);
assert(suffix);
size_t charsLen = strlen(chars);
size_t suffixLen = strlen(suffix);
if (charsLen == 0 || charsLen < suffixLen)
return false;
return memcmp(chars + charsLen - suffixLen, suffix, suffixLen) == 0;
}
bool DString::endWith(const std::string &str, const std::string &suffix)
{
return endWith(str.c_str(), suffix.c_str());
}
char *DString::delQuote(const char *chars)
{
char *data = nullptr;
if (!chars)
return data;
if (strneq(chars, "\"", 1) && strneq(chars + strlen(chars) - 1, "\"", 1)) {
data = static_cast<char *>(calloc(1, strlen(chars) - 2));
memcpy(data, chars + 1, strlen(chars) - 1);
} else {
data = static_cast<char *>(calloc(1, strlen(chars) + 1));
memcpy(data, chars, strlen(chars) + 1);
}
return data;
}
void DString::delQuote(std::string &str)
{
while (*str.begin() == '\"' && *str.rbegin() == '\"')
str.assign(str.substr(1, str.size() - 2));
}

56
src/lib/dstring.h Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DSTRING_H
#define DSTRING_H
#include <vector>
#include <string>
#include <cstring>
#define streq(a,b) (strcmp((a),(b)) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
// 字符串操作
class DString
{
public:
DString();
~DString();
// 字符串拆分
static std::vector<std::string> splitChars(const char *cs, char c);
static std::vector<std::string> splitStr(const std::string &str, char c);
static std::vector<std::string> splitVectorChars(const std::vector<char> &content, size_t length, char c);
// 字符串前缀判断
static bool startWith(const char *chars, const char *prefix);
static bool startWith(const std::string &str, const std::string &prefix);
// 字符后缀判断
static bool endWith(const char *chars, const char *suffix);
static bool endWith(const std::string &str, const std::string &suffix);
// 去除首尾引用
static char *delQuote(const char *chars);
static void delQuote(std::string &str);
};
#endif // DSTRING_H

289
src/lib/keyfile.cpp Normal file
View File

@ -0,0 +1,289 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "keyfile.h"
#include "dlocale.h"
#include "dstring.h"
#include "macro.h"
#include <cstring>
#include <string>
#include <iostream>
KeyFile::KeyFile(char separtor)
: fp(nullptr)
, modified(false)
, listSeparator(separtor)
{
}
KeyFile::~KeyFile()
{
if (fp) {
fclose(fp);
fp = nullptr;
}
}
bool KeyFile::getBool(const std::string &section, const std::string &key, bool defaultValue)
{
if (mainKeyMap.find(section) == mainKeyMap.end())
return false;
std::string valueStr = mainKeyMap[section][key];
bool value = defaultValue;
if (valueStr == "true")
value = true;
else if (valueStr == "false")
value = false;
return value;
}
// TODO
std::vector<bool> KeyFile::getBoolList(const std::string &section, const std::string &key, bool defaultValue)
{
std::vector<bool> tmp;
return tmp;
}
int KeyFile::getInt(const std::string &section, const std::string &key, int defaultValue)
{
if (mainKeyMap.find(section) == mainKeyMap.end())
return defaultValue;
std::string valueStr = mainKeyMap[section][key];
int value;
try {
value = std::stoi(valueStr);
} catch (std::invalid_argument&) {
value = defaultValue;
}
return value;
}
// TODO
std::vector<int> KeyFile::getIntList(const std::string &section, const std::string &key, int defaultValue)
{
std::vector<int> tmp;
return tmp;
}
// TODO
int64_t KeyFile::getInt64(const std::string &section, const std::string &key, int64_t defaultValue)
{
return int64_t(0);
}
// TODO
float KeyFile::getFloat(const std::string &section, const std::string &key, float defaultValue)
{
return 1.0;
}
std::string KeyFile::getStr(const std::string &section, const std::string &key, std::string defaultValue)
{
if (mainKeyMap.find(section) == mainKeyMap.end())
return defaultValue;
std::string valueStr = mainKeyMap[section][key];
if (valueStr.empty())
valueStr = defaultValue;
return valueStr;
}
bool KeyFile::containKey(const std::string &section, const std::string &key)
{
if (mainKeyMap.find(section) == mainKeyMap.end())
return false;
return mainKeyMap[section].find(key) != mainKeyMap[section].end();
}
std::string KeyFile::getLocaleStr(const std::string &section, const std::string &key, std::string defaultLocale)
{
std::vector<std::string> languages = defaultLocale.empty()
? Locale::instance()->getLanguageNames()
: Locale::instance()->getLocaleVariants(defaultLocale);
std::string translated;
for (const auto &lang : languages) {
translated.assign(getStr(section, key + "[" + lang + "]"));
if (!translated.empty())
return translated;
}
// NOTE: not support key Gettext-Domain
// fallback to default key
return getStr(section, key);
}
std::vector<std::string> KeyFile::getStrList(const std::string &section, const std::string &key)
{
std::string value = getStr(section, key);
return DString::splitStr(value, listSeparator);
}
std::vector<std::string> KeyFile::getLocaleStrList(const std::string &section, const std::string &key, std::string defaultLocale)
{
std::vector<std::string> languages = defaultLocale.empty()
? Locale::instance()->getLanguageNames()
: Locale::instance()->getLocaleVariants(defaultLocale);
std::vector<std::string> translated;
for (const auto &lang : languages) {
translated = getStrList(section, key + "[" + lang + "]");
if (translated.size() > 0)
return translated;
}
//fallback to default key
return getStrList(section, key);
}
// 修改keyfile内容
void KeyFile::setKey(const std::string &section, const std::string &key, const std::string &value)
{
if (mainKeyMap.find(section) == mainKeyMap.end())
mainKeyMap.insert({section, KeyMap()});
mainKeyMap[section].insert({key, value});
}
// 写入文件
bool KeyFile::saveToFile(const std::string &filePath)
{
FILE *sfp = fopen(filePath.data(), "w+");
if (!sfp)
return false;
for (const auto &im : mainKeyMap) {
const auto &keyMap = im.second;
std::string section = "[" + im.first + "]\n";
fputs(section.c_str(), sfp);
for (const auto &ik : keyMap) {
std::string kv = ik.first + "=" + ik.second + "\n";
fputs(kv.c_str(), sfp);
}
}
fclose(sfp);
return true;
}
bool KeyFile::loadFile(const std::string &filePath)
{
mainKeyMap.clear();
if (fp) {
fclose(fp);
fp = nullptr;
}
std::string lastSection;
fp = fopen(filePath.data(), "r");
if (!fp)
return false;
char line[MAX_LINE_LEN] = {0};
while (fgets(line, MAX_LINE_LEN, fp)) {
char *start = &line[0];
char *end = start;
while (!strneq(end, "\0", 1))
end++;
end--; // 返回'\0'前一个字符
// 移除行首
while (strneq(start, " ", 1) || strneq(start, "\t", 1))
start++;
// 过滤注释行
if (strneq(start, "#", 1))
continue;
// 移除行尾
while (strneq(end, "\n", 1) || strneq(end, "\r", 1)
|| strneq(end, " ", 1) || strneq(end, "\t", 1))
end--;
char *lPos = strchr(start, '[');
char *rPos = strchr(start, ']');
if (lPos && rPos && rPos - lPos > 0 && lPos == start && rPos == end) {
// 主键
std::string section(lPos + 1, size_t(rPos - lPos - 1));
mainKeyMap.insert({section, KeyMap()});
lastSection = section;
} else {
char *equal = strchr(start, '=');
if (!equal)
continue;
// 文件格式错误
if (lastSection.empty()) {
std::cout << "failed to load file " << filePath << std::endl;
return false;
}
// 子键
std::string key(start, size_t(equal - start));
std::string value(equal + 1, size_t(end - equal));
for (auto &iter : mainKeyMap) {
if (iter.first != lastSection)
continue;
iter.second[key] = value;
}
}
}
fclose(fp);
fp = nullptr;
return true;
}
std::vector<std::string> KeyFile::getMainKeys()
{
std::vector<std::string> mainKeys;
for (const auto &iter : mainKeyMap)
mainKeys.push_back(iter.first);
return mainKeys;
}
void KeyFile::print()
{
std::cout << "sectionMap: " << std::endl;
for (auto sectionMap : mainKeyMap) {
std::cout << "section=" << sectionMap.first << std::endl;
KeyMap keyMap = sectionMap.second;
for (auto iter : keyMap) {
std::cout << iter.first << "=" << iter.second << std::endl;
}
std::cout << std::endl;
}
}

67
src/lib/keyfile.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEYFILE_H
#define KEYFILE_H
#include <string>
#include <map>
#include <vector>
typedef std::map<std::string, std::string> KeyMap;
typedef std::map<std::string, KeyMap> MainKeyMap;
// 解析ini、desktop文件类
class KeyFile
{
public:
explicit KeyFile(char separtor = ';');
~KeyFile();
bool getBool(const std::string &section, const std::string &key, bool defaultValue = false);
std::vector<bool> getBoolList(const std::string &section, const std::string &key, bool defaultValue = false);
int getInt(const std::string &section, const std::string &key, int defaultValue = 0);
std::vector<int> getIntList(const std::string &section, const std::string &key, int defaultValue = 0);
int64_t getInt64(const std::string &section, const std::string &key, int64_t defaultValue = 0);
float getFloat(const std::string &section, const std::string &key, float defaultValue = 0);
std::string getStr(const std::string &section, const std::string &key, std::string defaultValue = "");
bool containKey(const std::string &section, const std::string &key);
std::string getLocaleStr(const std::string &section, const std::string &key, std::string defaultLocale = "");
std::vector<std::string> getStrList(const std::string &section, const std::string &key);
std::vector<std::string> getLocaleStrList(const std::string &section, const std::string &key, std::string defaultLocale = "");
void setKey(const std::string &section, const std::string &key, const std::string &value);
bool saveToFile(const std::string &filePath);
bool loadFile(const std::string &filePath);
std::vector<std::string> getMainKeys();
// for test
void print();
private:
MainKeyMap mainKeyMap; // section -> key : value
std::string filePath;
FILE *fp;
bool modified;
char listSeparator;
};
#endif // KEYFILE_H

72
src/lib/lang.h Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LANG_H
#define LANG_H
#include "dstring.h"
#include <stdlib.h>
#include <cstring>
#include <string>
#include <vector>
#include <array>
// 返回用户语言,参见man gettext
inline std::vector<std::string> queryLangs() {
std::vector<std::string> ret;
const char *lcAll = getenv("LC_ALL");
const char *lcMessage = getenv("LC_MESSAGE");
const char *language = getenv("LANGUAGE");
const char *lang = getenv("LANG");
auto cutOff = [](std::string str)->std::string {
size_t idx = str.find(".");
if (idx == std::string::npos)
return str;
return std::string(str).substr(0, idx);
};
if (lcAll && std::string(lcAll) != "C"
&& language && std::string(language) != "")
{
std::vector<std::string> splits = DString::splitChars(language, ':');
for (const auto &l : splits) {
ret.push_back(cutOff(l));
}
return ret;
}
if (lcAll && std::string(lcAll) != "")
ret.push_back(cutOff(lcAll));
if (lcMessage && std::string(lcMessage) != "")
ret.push_back(cutOff(lcMessage));
if (lang && std::string(lang) != "")
ret.push_back(cutOff(lang));
return ret;
}
#endif // LANG_H

72
src/lib/lang.hpp Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LANG_H
#define LANG_H
#include "dstring.h"
#include <stdlib.h>
#include <cstring>
#include <string>
#include <vector>
#include <array>
// 返回用户语言,参见man gettext
inline std::vector<std::string> queryLangs() {
std::vector<std::string> ret;
const char *lcAll = getenv("LC_ALL");
const char *lcMessage = getenv("LC_MESSAGE");
const char *language = getenv("LANGUAGE");
const char *lang = getenv("LANG");
auto cutOff = [](std::string str)->std::string {
size_t idx = str.find(".");
if (idx == std::string::npos)
return str;
return std::string(str).substr(0, idx);
};
if (lcAll && std::string(lcAll) != "C"
&& language && std::string(language) != "")
{
std::vector<std::string> splits = DString::splitChars(language, ':');
for (const auto &l : splits) {
ret.push_back(cutOff(l));
}
return ret;
}
if (lcAll && std::string(lcAll) != "")
ret.push_back(cutOff(lcAll));
if (lcMessage && std::string(lcMessage) != "")
ret.push_back(cutOff(lcMessage));
if (lang && std::string(lang) != "")
ret.push_back(cutOff(lang));
return ret;
}
#endif // LANG_H

31
src/lib/macro.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MACRO_H
#define MACRO_H
#define _likely_(x) (__builtin_expect(!!(x), 1))
#define _unlikely_(x) (__builtin_expect(!!(x), 0))
#define MAX_FILEPATH_LEN 256
#define MAX_LINE_LEN 256
#endif // MACRO_H

188
src/lib/process.cpp Normal file
View File

@ -0,0 +1,188 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "process.h"
#include "macro.h"
#include "dstring.h"
#include "dfile.h"
#include <algorithm>
#include <dirent.h>
#include <unistd.h>
#define FILECONTENLEN 2048
Process::Process()
: pid(0)
, ppid(0)
{
}
Process::Process(int _pid)
: pid(_pid)
, ppid(0)
{
}
bool Process::isExist()
{
std::string procDir = "/proc/" + std::to_string(pid);
return DFile::isExisted(procDir);
}
std::vector<std::string> Process::getCmdLine()
{
if (cmdLine.size() == 0) {
std::string cmdlineFile = getFile("cmdline");
cmdLine = readFile(cmdlineFile);
}
return cmdLine;
}
std::string Process::getCwd()
{
if (cwd.empty()) {
std::string cwdFile = getFile("cwd");
char path[MAX_FILEPATH_LEN] = {};
ssize_t len = readlink(cwdFile.c_str(), path, MAX_FILEPATH_LEN);
if (len > 0 && len < MAX_FILEPATH_LEN) {
cwd = std::string(path) + "/";
}
}
return cwd;
}
std::string Process::getExe()
{
if (exe.empty()) {
std::string cmdLineFile = getFile("exe");
char path[MAX_FILEPATH_LEN] = {};
ssize_t len = readlink(cmdLineFile.c_str(), path, MAX_FILEPATH_LEN);
if (len > 0 && len < MAX_FILEPATH_LEN) {
exe = std::string(path);
}
}
return exe;
}
std::vector<std::string> Process::getEnviron()
{
if (environ.size() == 0) {
std::string envFile = getFile("environ");
environ = readFile(envFile);
}
return environ;
}
std::string Process::getEnv(const std::string &key)
{
if (environ.size() == 0)
environ = getEnviron();
std::string keyPrefix = key + "=";
for (auto & env : environ) {
if (DString::startWith(env, keyPrefix)) {
ulong len = keyPrefix.size();
return env.substr(len, env.size() - len);
}
}
return "";
}
Status Process::getStatus()
{
if (status.size() == 0) {
std::string statusFile = getFile("status");
FILE *fp = fopen(statusFile.c_str(), "r");
if (!fp)
return status;
char line[MAX_LINE_LEN] = {0};
while (fgets(line, MAX_LINE_LEN, fp)) {
std::string info(line);
std::vector<std::string> parts = DString::splitStr(info, ':');
if (parts.size() == 2)
status[parts[0]] = parts[1];
}
fclose(fp);
}
return status;
}
std::vector<int> Process::getUids()
{
if (uids.size() == 0) {
if (status.find("Uid") != status.end()) {
std::string uidGroup = status["Uid"];
std::vector<std::string> parts = DString::splitStr(uidGroup, '\t');
uids.reserve(parts.size());
std::transform(parts.begin(), parts.end(), uids.begin(),
[](std::string idStr) -> int {return std::stoi(idStr);});
}
}
return uids;
}
int Process::getPid()
{
return pid;
}
int Process::getPpid()
{
if (ppid == 0) {
if (status.find("PPid") != status.end()) {
ppid = std::stoi(status["PPid"]);
}
}
return ppid;
}
std::string Process::getFile(const std::string &name)
{
return "/proc/" + std::to_string(pid) + "/" + name;
}
// /proc is not real file system
std::vector<std::string> Process::readFile(std::string fileName)
{
std::vector<std::string> ret;
std::FILE *fp = std::fopen(fileName.c_str(), "r");
if (!fp)
return ret;
std::vector<char> content(FILECONTENLEN);
std::size_t len = std::fread(&content[0], 1, FILECONTENLEN, fp);
std::fclose(fp);
ret = DString::splitVectorChars(content, len, '\0');
return ret;
}

62
src/lib/process.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_H
#define PROCESS_H
#include <map>
#include <vector>
#include <string>
typedef std::map<std::string, std::string> Status;
class Process
{
public:
Process();
explicit Process(int _pid);
bool isExist();
std::vector<std::string> getCmdLine();
std::string getCwd();
std::string getExe();
std::vector<std::string> getEnviron();
std::string getEnv(const std::string &key);
Status getStatus();
std::vector<int> getUids();
int getPid();
int getPpid();
private:
std::string getFile(const std::string &name);
std::vector<std::string> readFile(std::string fileName);
int pid;
std::vector<std::string> cmdLine;
std::string cwd;
std::string exe;
std::vector<std::string> environ;
Status status;
std::vector<int> uids;
int ppid;
};
#endif // PROCESS_H

574
src/lib/xcbutils.cpp Normal file
View File

@ -0,0 +1,574 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xcbutils.h"
#include <iostream>
#include <cstring>
XCBUtils::XCBUtils()
{
connect = xcb_connect(nullptr, &screenNum); // nullptr表示默认使用环境变量$DISPLAY获取屏幕
if (xcb_connection_has_error(connect)) {
std::cout << "XCBUtils: init xcb_connect error" << std::endl;
return;
}
if (!xcb_ewmh_init_atoms_replies(&ewmh,
xcb_ewmh_init_atoms(connect, &ewmh), // 初始化Atom
nullptr))
std::cout << "XCBUtils: init ewmh error" << std::endl;
}
XCBUtils::~XCBUtils()
{
if (connect) {
xcb_disconnect(connect); // 关闭连接并释放
connect = nullptr;
}
}
XWindow XCBUtils::allocId()
{
return xcb_generate_id(connect);
}
void XCBUtils::killClientChecked(XWindow xid)
{
xcb_kill_client_checked(connect, xid);
}
xcb_get_property_reply_t *XCBUtils::getPropertyValueReply(XWindow xid, XCBAtom property, XCBAtom type)
{
xcb_get_property_cookie_t cookie = xcb_get_property(connect,
0,
xid,
property,
type,
0,
MAXLEN);
return xcb_get_property_reply(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, ewmh.UTF8_STRING);
if (reply) {
ret = getUTF8StrFromReply(reply);
free(reply);
}
return ret;
}
XCBAtom XCBUtils::getAtom(const char *name)
{
XCBAtom ret = atomCache.getVal(name);
if (ret == ATOMNONE) {
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connect, false, strlen(name), name);
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply (connect,
cookie,
nullptr);
if (reply) {
atomCache.store(name, reply->atom);
ret = reply->atom;
free(reply);
}
}
return ret;
}
std::string XCBUtils::getAtomName(XCBAtom atom)
{
std::string ret = atomCache.getName(atom);
if (ret.empty()) {
xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(connect, atom);
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(connect,
cookie,
nullptr);
if (reply) {
char *name = xcb_get_atom_name_name(reply);
if (name) {
atomCache.store(name, atom);
ret = name;
}
free(reply);
}
}
return ret;
}
Geometry XCBUtils::getWindowGeometry(XWindow xid)
{
Geometry ret;
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(connect, xid);
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(connect, cookie, nullptr);
if (reply) {
ret.x = reply->x;
ret.y = reply->y;
ret.width = reply->width;
ret.height = reply->height;
free(reply);
} else {
std::cout << xid << " getWindowGeometry err" << std::endl;
}
return ret;
}
XWindow XCBUtils::getActiveWindow()
{
XWindow ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window(&ewmh, screenNum);
if (!xcb_ewmh_get_active_window_reply(&ewmh, cookie, &ret, nullptr))
std::cout << "getActiveWindow error" << std::endl;
return ret;
}
void XCBUtils::setActiveWindow(XWindow xid)
{
xcb_ewmh_set_active_window(&ewmh, screenNum, xid);
}
std::list<XWindow> XCBUtils::getClientList()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list(&ewmh, screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (!xcb_ewmh_get_client_list_reply(&ewmh, cookie, &reply, nullptr))
std::cout << "getClientList error" << std::endl;
for (uint32_t i = 0; i < reply.windows_len; i++)
ret.push_back(reply.windows[i]);
return ret;
}
std::list<XWindow> XCBUtils::getClientListStacking()
{
std::list<XWindow> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_client_list_stacking(&ewmh, screenNum);
xcb_ewmh_get_windows_reply_t reply;
if (!xcb_ewmh_get_client_list_stacking_reply(&ewmh, cookie, &reply, nullptr))
std::cout << "getClientListStacking error" << std::endl;
for (uint32_t i = 0; i < reply.windows_len; i++)
ret.push_back(reply.windows[i]);
return ret;
}
std::vector<XCBAtom> XCBUtils::getWMState(XWindow xid)
{
std::vector<XCBAtom> ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state(&ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (xcb_ewmh_get_wm_state_reply(&ewmh, cookie, &reply, nullptr)) {
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
} 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(&ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atom
if (!xcb_ewmh_get_wm_window_type_reply(&ewmh, cookie, &reply, nullptr))
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(&ewmh, xid);
xcb_ewmh_get_atoms_reply_t reply; // a list of Atoms
if (!xcb_ewmh_get_wm_allowed_actions_reply(&ewmh, cookie, &reply, nullptr))
std::cout << xid << " getWMAllowedActions error" << std::endl;
for (uint32_t i = 0; i < reply.atoms_len; i++) {
ret.push_back(reply.atoms[i]);
}
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(&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(&ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply1;
if (!xcb_ewmh_get_wm_name_reply(&ewmh, cookie, &reply1, nullptr))
std::cout << xid << " getWMName error" << std::endl;
ret.assign(reply1.strings);
return ret;
}
uint32_t XCBUtils::getWMPid(XWindow xid)
{
uint32_t ret = 0;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_pid(&ewmh, xid);
if (!xcb_ewmh_get_wm_pid_reply(&ewmh, cookie, &ret, nullptr))
std::cout << xid << " getWMPid error" << std::endl;
return ret;
}
std::string XCBUtils::getWMIconName(XWindow xid)
{
std::string ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name(&ewmh, xid);
xcb_ewmh_get_utf8_strings_reply_t reply;
if (!xcb_ewmh_get_wm_icon_name_reply(&ewmh, cookie, &reply, nullptr))
std::cout << xid << " getWMIconName error" << std::endl;
ret.assign(reply.strings);
return ret;
}
std::vector<WMIcon> XCBUtils::getWMIcon(XWindow xid)
{
std::vector<WMIcon> ret;
/*
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon(&ewmh, xid);
xcb_ewmh_get_wm_icon_reply_t reply;
if (xcb_ewmh_get_wm_icon_reply(&ewmh, cookie, &reply, nullptr)) {
xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
auto fcn = [](xcb_ewmh_wm_icon_iterator_t it) {
std::vector<BYTE> data;
uint32_t *dat = it.data;
int area = it.width * it.height;
for (int i = 0; i < (2 + area) * 4; i++, dat++) { // TODO check data accuracy
data.push_back(*dat);
}
return data;
};
ret.push_back({iter.width, iter.height, fcn(iter)});
while (iter.rem >= 1) {
xcb_ewmh_get_wm_icon_next(&iter);
ret.push_back({iter.width, iter.height, fcn(iter)});
}
xcb_ewmh_get_wm_icon_reply_wipe(&reply); // clear
}
*/
return ret;
}
XWindow XCBUtils::getWMClientLeader(XWindow xid)
{
XWindow ret;
XCBAtom atom = getAtom("WM_CLIENT_LEADER");
void *value = getPropertyValue(xid, atom, XCB_ATOM_INTEGER);
std::cout << "getWMClientLeader:" << (char*)value << std::endl;
return ret;
}
void XCBUtils::requestCloseWindow(XWindow xid, uint32_t timestamp)
{
xcb_ewmh_request_close_window(&ewmh, 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(&ewmh, xid);
if (!xcb_ewmh_get_wm_desktop_reply(&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(&ewmh, xid, desktop);
}
void XCBUtils::setCurrentWMDesktop(uint32_t desktop)
{
xcb_ewmh_set_current_desktop(&ewmh, screenNum, desktop);
}
uint32_t XCBUtils::getCurrentWMDesktop()
{
uint32_t ret;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop(&ewmh, screenNum);
if (!xcb_ewmh_get_current_desktop_reply(&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(connect, xid);
xcb_generic_error_t **errStore = nullptr;
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(connect, cookie, errStore);
if (reply) {
if (!errStore) // 正常获取窗口geometry则判定为good
ret = true;
free(reply);
}
return ret;
}
// TODO XCB下无_MOTIF_WM_HINTS属性
MotifWMHints XCBUtils::getWindowMotifWMHints(XWindow xid)
{
MotifWMHints ret;
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(connect, xid);
if (!xcb_icccm_get_wm_transient_for_reply(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(&ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_reply(&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(&ewmh, xid);
if (!xcb_ewmh_get_wm_user_time_window_reply(&ewmh, cookie, &ret, NULL))
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(connect, xid);
xcb_icccm_get_wm_class_reply_t reply;
if (!xcb_icccm_get_wm_class_reply(connect, cookie, &reply, nullptr)) {
if (reply.class_name)
ret.className.assign(reply.class_name);
if (reply.instance_name)
ret.instanceName.assign(reply.instance_name);
//xcb_icccm_get_wm_class_reply_wipe(&reply);
} else {
std::cout << xid << " getWMClass error" << std::endl;
}
return ret;
}
// TODO
void XCBUtils::minimizeWindow(XWindow xid)
{
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints(connect, xid);
xcb_icccm_wm_hints_t *hints = new xcb_icccm_wm_hints_t; // 分配堆空间
xcb_icccm_get_wm_hints_reply(connect, cookie, hints, nullptr);
xcb_icccm_wm_hints_set_iconic(hints);
xcb_icccm_set_wm_hints(connect, xid, hints);
free(hints);
}
void XCBUtils::maxmizeWindow(XWindow xid)
{
xcb_ewmh_request_change_wm_state(&ewmh
, 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, 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(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(connect,
xid,
XCB_CW_EVENT_MASK,
&value);
xcb_flush(connect);
xcb_generic_error_t *error = xcb_request_check(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 = atoms.find(name);
if (search != atoms.end())
atom = search->second;
return atom;
}
std::string AtomCache::getName(XCBAtom atom)
{
std::string ret;
auto search = atomNames.find(atom);
if (search != atomNames.end())
ret = search->second;
return ret;
}
void AtomCache::store(std::string name, XCBAtom value)
{
atoms[name] = value;
atomNames[value] = name;
}

272
src/lib/xcbutils.h Normal file
View File

@ -0,0 +1,272 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef 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 unsigned char BYTE;
typedef struct {
uint32_t width; /** Icon width */
uint32_t height; /** Icon height */
std::vector<BYTE> data; /** Rows, left to right and top to bottom of the CARDINAL ARGB */
} WMIcon;
// 缓存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> atoms;
std::map<XCBAtom, std::string> 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;
}
// test
xcb_connection_t *getConnect() {return connect;}
/************************* xcb method ***************************/
// 分配XID
XWindow allocId();
/************************* 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);
// 获取窗口列表 _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
std::vector<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);
// 获取当前桌面 _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:
xcb_connection_t *connect;
int screenNum;
xcb_ewmh_connection_t ewmh;
AtomCache atomCache; // 和ewmh中Atom类型存在重复部分扩张了自定义类型
};
#endif // XCBUTILS_H

View File

@ -12,7 +12,6 @@ set(SRCS
../modules/methods/registe.hpp
../modules/util/common.cpp
../modules/util/common.h
../modules/util/debug
../modules/util/filesystem.cpp
../modules/util/filesystem.h
../modules/util/json.h

View File

@ -0,0 +1,257 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "alrecorder.h"
#include "dfwatcher.h"
#include <QDir>
#include <QDBusConnection>
#include <QDBusError>
#include <QtDebug>
#include <QCryptographicHash>
const QString userAppsCfgDir = QDir::homePath() + "/.config/deepin/dde-daemon/apps/";
AlRecorder::AlRecorder(DFWatcher *_watcher, QObject *parent)
: QObject (parent)
, watcher(_watcher)
, mutex(QMutex(QMutex::NonRecursive))
{
QDBusConnection con = QDBusConnection::sessionBus();
if (!con.registerService("org.deepin.daemon.AlRecorder1"))
{
qWarning() << "register service AlRecorder1 error:" << con.lastError().message();
return;
}
if (!con.registerObject("/org/deepin/daemon/AlRecorder1", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals))
{
qWarning() << "register object AlRecorder1 error:" << con.lastError().message();
return;
}
connect(watcher, &DFWatcher::Event, this, &AlRecorder::onDFChanged, Qt::QueuedConnection);
Q_EMIT ServiceRestarted();
}
AlRecorder::~AlRecorder()
{
QDBusConnection::sessionBus().unregisterObject("/org/deepin/daemon/AlRecorder1");
}
// 获取未启动应用列表
QMap<QString, QStringList> AlRecorder::GetNew()
{
QMap<QString, QStringList> ret;
QMutexLocker locker(&mutex);
for (auto is = subRecoders.begin(); is != subRecoders.end(); is++) {
QStringList apps;
for (auto il = is.value().launchedMap.begin(); il != is.value().launchedMap.end(); il++) {
if (!il.value()) // 未启动应用
apps.push_back(il.key());
}
if (apps.size() > 0)
ret[is.key()] = apps;
}
return ret;
}
// 标记应用已启动状态
void AlRecorder::MarkLaunched(const QString &filePath)
{
if (!filePath.endsWith(".desktop"))
return;
QFileInfo info;
QMutexLocker locker(&mutex);
for (auto sri = subRecoders.begin(); sri != subRecoders.end(); sri++) {
if (!filePath.contains(sri.key()))
continue;
info.setFile(filePath);
QString name = info.baseName();
for (auto li = sri.value().launchedMap.begin(); li != sri.value().launchedMap.end(); li++) {
if (li.key() == name && !li.value()) {
li.value() = true;
goto end;
}
}
}
// 根据filePath匹配到唯一应用
end:
if (info.isDir()) {
saveStatusFile(info.absolutePath() + "/");
Q_EMIT Launched(filePath);
}
}
// 记录Launcher服务卸载应用信息, 终端卸载不会调用该函数, desktopFiles为绝对路径
void AlRecorder::UninstallHints(const QStringList &desktopFiles)
{
QMutexLocker locker(&mutex);
for (auto desktop : desktopFiles) {
for (auto sri = subRecoders.begin(); sri != subRecoders.end(); sri++) {
if (!desktop.contains(sri.key()))
continue;
QFileInfo info(desktop);
sri.value().uninstallMap[info.baseName()] = true;
}
}
}
// 监控目录
void AlRecorder::WatchDirs(const QStringList &dataDirs)
{
for (auto dirPath : dataDirs) {
if (subRecoders.contains(dirPath))
continue;
QDir dir(dirPath);
QStringList files = dir.entryList(QDir::Files);
for (auto &file : files)
file = dirPath + file;
// 监听目录和文件
watcher->addDir(dirPath);
if (files.size() > 0)
watcher->addPaths(files);
// 初始化对应目录和应用信息
initSubRecoder(dirPath);
}
}
// 初始化应用目录记录
void AlRecorder::initSubRecoder(const QString &dirPath)
{
subRecorder sub;
QByteArray encryText = QCryptographicHash::hash(dirPath.toLatin1(), QCryptographicHash::Md5);
QString statusFile = userAppsCfgDir + "launched-" + encryText.toHex() + ".csv";
// 读取App状态记录
QMap<QString, bool> launchedApp;
QFile file(statusFile);
if (file.open(QIODevice::ReadWrite | QIODevice::Text)) {
while (!file.atEnd()){
QString line(file.readLine());
QStringList strs = line.split(",");
if (strs.length() != 2)
continue;
if (strs[1].size() > 0 && strs[1][0] == 't')
launchedApp[strs[0]] = true;
else
launchedApp[strs[0]] = false;
}
file.close();
} else {
// 读取app desktop
QDir dir(dirPath);
QStringList files = dir.entryList(QDir::Files);
QStringList apps;
for (QString file : files) {
if (!file.endsWith(".desktop"))
continue;
int index = file.lastIndexOf(".");
file.truncate(index);
qInfo() << "entry =" << file;
apps.push_back(file);
}
// fallback 都打开过
for (auto app : apps)
launchedApp[app] = true;
}
sub.statusFile = statusFile;
sub.launchedMap = launchedApp;
subRecoders[dirPath] = sub;
}
void AlRecorder::onDFChanged(const QString &filePath, uint32_t op)
{
QFileInfo info(filePath);
QString dirPath = info.absolutePath() + "/";
QString name = info.baseName();
subRecorder &sub = subRecoders[dirPath];
QMap<QString, bool> &launchedMap = sub.launchedMap;
// 过滤文件, 仅保留.desktop类型
if (!filePath.endsWith(".desktop"))
return;
switch (op) {
case DFWatcher::event::Add:
qInfo() << "AlRecorder: Add " << filePath;
if (!launchedMap.contains(name)) {
bool launched = false;
if (sub.removedLaunchedMap.find(name) != sub.removedLaunchedMap.end()) {
launched = sub.removedLaunchedMap[name];
sub.removedLaunchedMap.remove(name);
}
launchedMap[name] = launched;
}
sub.uninstallMap.remove(name);
saveStatusFile(dirPath); // 刷新状态文件
break;
case DFWatcher::event::Del:
qInfo() << "AlRecorder: Del" << filePath;
if (launchedMap.contains(name)) {
if (!sub.uninstallMap.contains(name))
sub.removedLaunchedMap[name] = launchedMap[name];
launchedMap.remove(name);
}
saveStatusFile(dirPath); //刷新状态文件
break;
case DFWatcher::event::Mod:
break;
}
}
void AlRecorder::saveStatusFile(const QString &dirPath)
{
subRecorder sub = subRecoders[dirPath];
QString tmpFile = sub.statusFile + "_tmp";
QFile fp(tmpFile);
bool ok = false;
qInfo() << "saveStatusFile=" << dirPath << "create file=" << tmpFile;
if (fp.open(QIODevice::ReadWrite | QIODevice::Text)) {
QTextStream out(&fp);
out << "# " << dirPath << endl;
for (auto rl = sub.launchedMap.begin(); rl != sub.launchedMap.end(); rl++) {
out << rl.key() << "," << ((rl.value() == true) ? "t" : "f") << endl;
}
ok = true;
fp.close();
}
// 覆盖原文件
QFile::remove(sub.statusFile);
QFile::rename(tmpFile, sub.statusFile);
Q_EMIT StatusSaved(dirPath, sub.statusFile, ok);
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ALRECORDER_H
#define ALRECORDER_H
#include <QObject>
#include <QMap>
#include <QMutex>
class DFWatcher;
// 记录应用状态信息
class AlRecorder: public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.deepin.daemon.AlRecorder1")
public:
struct subRecorder {
QString statusFile; // 应用目录状态文件
QMap<QString, bool> launchedMap; // 应用启动记录
QMap<QString, bool> removedLaunchedMap; // desktop文件卸载记录
QMap<QString, bool> uninstallMap; // 记录应用将被卸载状态
};
AlRecorder(DFWatcher *_watcher, QObject *parent = nullptr);
~AlRecorder();
Q_SIGNALS:
void Launched(const QString &file);
void StatusSaved(const QString &root, const QString &file, bool ok);
void ServiceRestarted();
private Q_SLOTS:
void onDFChanged(const QString &filePath, uint32_t op);
public Q_SLOTS:
QMap<QString, QStringList> GetNew();
void MarkLaunched(const QString &filePath);
void UninstallHints(const QStringList &desktopFiles);
void WatchDirs(const QStringList &dataDirs);
private:
void initSubRecoder(const QString &dirPath);
void saveStatusFile(const QString &dirPath);
QMap<QString,subRecorder> subRecoders; // 记录不同应用目录的文件状态
DFWatcher *watcher;
QMutex mutex;
};
#endif // ALRECODER_H

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "appmanager.h"
#include "dfwatcher.h"
#include "alrecorder.h"
#include "basedir.h"
#include <QDebug>
#include <QDir>
AppManager::AppManager(QObject *parent)
: QObject(parent)
, watcher(new DFWatcher(this))
, recorder(new AlRecorder(watcher, this))
{
QStringList dataDirs;
dataDirs << BaseDir::userAppDir().c_str();
for (auto &dir : BaseDir::sysAppDirs())
dataDirs << dir.c_str();
recorder->WatchDirs(dataDirs); // 监控应用desktop
}
AppManager::~AppManager()
{
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APPMANAGER_H
#define APPMANAGER_H
#include <QObject>
class DFWatcher;
class AlRecorder;
class AppManager: public QObject
{
Q_OBJECT
public:
explicit AppManager(QObject *parent = nullptr);
~AppManager();
private:
DFWatcher *watcher;
AlRecorder *recorder;
};
#endif // APPMANAGER_H

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dfwatcher.h"
#include <QDir>
#include <QDBusConnection>
#include <QDBusError>
#include <QtDebug>
const QString dfSuffix = ".desktop";
const QString configSuffix = ".json";
DFWatcher::DFWatcher(QObject *parent)
: QObject (parent)
, watcher(new QFileSystemWatcher(this))
{
QDBusConnection con = QDBusConnection::sessionBus();
if (!con.registerService("org.deepin.daemon.DFWatcher1"))
{
qInfo() << "register service app1 error:" << con.lastError().message();
return;
}
if (!con.registerObject("/org/deepin/daemon/DFWatcher1", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals))
{
qInfo() << "register object DFWatcher error:" << con.lastError().message();
return;
}
connect(watcher, &QFileSystemWatcher::fileChanged, this, &DFWatcher::fileUpdated, Qt::QueuedConnection);
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &DFWatcher::directoryUpdated, Qt::QueuedConnection);
}
DFWatcher::~DFWatcher()
{
QDBusConnection::sessionBus().unregisterObject("/org/deepin/daemon/DFWatcher1");
}
void DFWatcher::addDir(const QString &path)
{
// 记录当前目录内容
qInfo() << "addDir :" << path;
const QDir dir(path);
dirContentMap[path] = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
watcher->addPath(path);
}
void DFWatcher::addPaths(const QStringList &paths)
{
watcher->addPaths(paths);
}
QStringList DFWatcher::files()
{
return watcher->files();
}
void DFWatcher::removePath(const QString &filepath)
{
watcher->removePath(filepath);
}
void DFWatcher::fileUpdated(const QString &filePath)
{
qInfo() << "event: modify filepath=" << filePath;
if (filePath.endsWith(dfSuffix) || filePath.endsWith(configSuffix))
Q_EMIT Event(filePath, int(event::Mod));
}
void DFWatcher::directoryUpdated(const QString &dirPath)
{
QStringList recoderedContent = dirContentMap[dirPath];
const QDir dir(dirPath);
QStringList newEntries = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
QSet<QString> newDirSet = QSet<QString>::fromList(newEntries);
QSet<QString> currentDirSet = QSet<QString>::fromList(recoderedContent);
// 添加的文件
QSet<QString> newFiles = newDirSet - currentDirSet;
QStringList newFile = newFiles.toList();
// 移除的文件
QSet<QString> deletedFiles = currentDirSet - newDirSet;
QStringList deleteFile = deletedFiles.toList();
// 更新目录记录
dirContentMap[dirPath] = newEntries;
// 新增文件
if (newFile.size() > 0) {
for (auto &file : newFile) {
//qInfo() << "event: add filepath=" << file;
if (file.endsWith(dfSuffix)) {
Q_EMIT Event(dirPath + file, event::Add);
}
}
}
// 移除文件
if (deleteFile.size() > 0) {
for (auto &file : deleteFile) {
//qInfo() << "event: del filepath=" << file;
if (file.endsWith(dfSuffix)) {
Q_EMIT Event(dirPath + file, event::Del);
}
}
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DFWATCHER_H
#define DFWATCHER_H
#include <QObject>
#include <QMap>
#include <QFileSystemWatcher>
class DFWatcher: public QObject {
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.deepin.daemon.DFWatcher1")
public:
enum event{
Add,
Del,
Mod,
};
explicit DFWatcher(QObject *parent = nullptr);
~DFWatcher();
void addDir(const QString & path);
void addPaths(const QStringList &paths);
QStringList files();
void removePath(const QString &filepath);
Q_SIGNALS:
void Event(const QString &filepath, int op);
private Q_SLOTS:
void fileUpdated(const QString &filePath);
void directoryUpdated(const QString &dirPath);
private:
QFileSystemWatcher *watcher;
QMap<QString, QStringList> dirContentMap; // 监控的目录内容列表
};
#endif

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "appinfo.h"
#include "common.h"
#include <QDebug>
#include <QString>
#include <QCryptographicHash>
AppInfo::AppInfo(DesktopInfo &info)
: isValid(true)
{
init(info);
}
AppInfo::AppInfo(const QString &_fileName)
: isValid(true)
{
DesktopInfo info(_fileName.toStdString());
init(info);
}
void AppInfo::init(DesktopInfo &info)
{
if (!info.isValidDesktop()) {
isValid = false;
return;
}
std::string xDeepinVendor= info.kf.getStr(MainSection, "X-Deepin-Vendor");
if (xDeepinVendor == "deepin") {
name = info.getGenericName().c_str();
if (name.isEmpty())
name = info.getName().c_str();
} else {
name = info.getName().c_str();
}
innerId = genInnerIdWithDesktopInfo(info);
fileName = info.getFileName().c_str();
id = info.getId().c_str();
icon = info.getIcon().c_str();
installed = info.isInstalled();
for (const auto & action : info.getActions()) {
actions.push_back(action);
}
}
QString AppInfo::genInnerIdWithDesktopInfo(DesktopInfo &info)
{
std::string cmdline = info.getCommandLine();
QByteArray encryText = QCryptographicHash::hash(QString(cmdline.c_str()).toLatin1(), QCryptographicHash::Md5);
QString innerId = desktopHashPrefix + encryText.toHex();
qInfo() << "app " << info.getId().c_str() << " generate innerId :" << innerId;
return innerId;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APPINFO_H
#define APPINFO_H
#include "desktopinfo.h"
#include<QVector>
// 应用信息类
class AppInfo
{
public:
explicit AppInfo(DesktopInfo &info);
explicit AppInfo(const QString &_fileName);
void init(DesktopInfo &info);
QString getFileName() {return fileName;}
QString getIcon() {return icon;}
QString getId() {return id;}
QString getInnerId() {return innerId;}
QString getName() {return name;}
QVector<DesktopAction> getActions() {return actions;}
QString getIdentifyMethod() {return identifyMethod;}
void setIdentifyMethod(QString method) {identifyMethod = method;}
bool isInstalled() {return installed;}
bool isValidApp() {return isValid;}
private:
QString genInnerIdWithDesktopInfo(DesktopInfo &info);
QString fileName;
QString id;
QString icon;
QString identifyMethod;
QString innerId;
QString name;
QVector<DesktopAction> actions;
bool installed;
bool isValid;
};
#endif // APPINFO_H

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "appmenu.h"
#include <QJsonArray>
#include <QJsonDocument>
AppMenu::AppMenu()
: checkableMenu(false)
, singleCheck(false)
, itemcount(0)
, dirty(false)
{
}
// 增加菜单选项
void AppMenu::appendItem(AppMenuItem item)
{
if (!item.text.isEmpty()) {
item.id = allocateId();
items.push_back(item);
}
}
void AppMenu::handleAction(uint32_t timestamp, QString itemId)
{
for (auto &item : items) {
if (item.id == itemId) {
item.action(timestamp);
break;
}
}
}
void AppMenu::setDirtyStatus(bool isDirty)
{
dirty = isDirty;
}
QString AppMenu::getMenuJsonStr()
{
QJsonObject obj;
QJsonArray array;
for (auto item : items) {
QJsonObject objItem;
objItem["itemId"] = item.id;
objItem["itemText"] = item.text;
objItem["isActive"] = item.isActive;
objItem["isCheckable"] = item.isCheckable;
objItem["checked"] = item.checked;
objItem["itemIcon"] = item.icon;
objItem["itemIconHover"] = item.iconHover;
objItem["itemIconInactive"] = item.iconInactive;
objItem["showCheckMark"] = item.showCheckMark;
objItem["itemSubMenu"] = item.subMenu ? item.subMenu->getMenuJsonStr() : "";
array.push_back(QJsonValue(objItem));
}
obj["items"] = QJsonValue(array);
obj["checkableMenu"] = checkableMenu;
obj["singleCheck"] = singleCheck;
QString ret = QJsonDocument(obj).toJson();
return ret;
}
QString AppMenu::allocateId()
{
return QString::number(itemcount++);
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APPMENU_H
#define APPMENU_H
#include <QString>
#include <QJsonObject>
#include <QVector>
#include <memory>
#include <vector>
#include <functional>
typedef std::function<void(uint32_t)> AppMenuAction;
class AppMenu;
// 应用菜单选项
struct AppMenuItem {
QString id;
QString text;
bool isActive;
QString isCheckable;
QString checked;
QString icon;
QString iconHover;
QString iconInactive;
QString showCheckMark;
std::shared_ptr<AppMenu> subMenu;
int hint;
AppMenuAction action;
};
// 应用菜单类
class AppMenu
{
public:
AppMenu();
void appendItem(AppMenuItem item);
void handleAction(uint32_t timestamp, QString itemId);
void setDirtyStatus(bool isDirty);
QString getMenuJsonStr();
private:
QString allocateId();
QVector<AppMenuItem> items; // json:"items"
bool checkableMenu; // json:"checkableMenu"
bool singleCheck; // json:"singleCheck"
int itemcount;
bool dirty;
};
#endif // APPMENU_H

103
src/modules/dock/common.h Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMON_H
#define COMMON_H
#include <QString>
#include <QMap>
#include <QDir>
const QString configDock = "com.deepin.dde.dock";
const QString configAppearance = "com.deepin.dde.appearance";
const QString keyHideMode = "Hide_Mode";
const QString keyDisplayMode = "Display_Mode";
const QString keyPosition = "Position";
const QString keyIconSize = "Icon_Size";
const QString keyDockedApps = "Docked_Apps";
const QString keyShowTimeout = "Show_Timeout";
const QString keyHideTimeout = "Hide_Timeout";
const QString keyWindowSizeFashion = "Window_Size_Fashion";
const QString keyWindowSizeEfficient = "Window_Size_Efficient";
const QString keyWinIconPreferredApps = "Win_Icon_Preferred_Apps";
const QString keyOpacity = "Opacity";
const QString keyPluginSettings = "Plugin_Settings";
const QString keyForceQuitApp = "Force_Quit_App";
const QString scratchDir = QDir::homePath() + "/.local/dock/scratch/";
const QMap<QString, QString> pathDirCodeMap {
{"/usr/share/applications/", "/S@"},
{"/usr/local/share/applications/", "/L@"},
{QDir::homePath() + "/.local/share/applications", "/H@"},
{QDir::homePath() + "/.local/dock/scratch", "/D@"},
};
const QMap<QString, QString> pathCodeDirMap {
{"/S@", "/usr/share/applications/"},
{"/L@", "/usr/local/share/applications/"},
{"/H@", QDir::homePath() + "/.local/share/applications"},
{"/D@", QDir::homePath() + "/.local/dock/scratch"},
};
// DBus服务、路径
const QString dbusService = "org.deepin.dde.daemon.Dock1";
const QString dbusPath = "/org/deepin/dde/daemon/Dock1";
const QString dbusInterface = dbusService;
const QString windowPatternsFile = "/usr/share/dde/data/window_patterns.json";
const QString desktopHashPrefix = "d:";
const QString windowHashPrefix = "w:";
const QString entryDBusObjPathPrefix = dbusPath + "/entries/";
const QString entryDBusInterface = dbusInterface + ".Entry";
// 驻留应用desktop file模板
const QString dockedItemTemplate = R"([Desktop Entry]
Name=%1
Exec=%2
Icon=%3
Type=Application
Terminal=false
StartupNotify=false
)";
const QString frontendWindowWmClass = "dde-dock";
const int configureNotifyDelay = 100;
const int smartHideTimerDelay = 400;
const int bestIconSize = 48;
const int menuItemHintShowAllWindows = 1;
const int MotifHintFunctions = 1;
const int MotifHintDecorations = 2;
const int MotifHintInputMode = 4;
const int MotifHintStatus = 8;
const int MotifFunctionNone = 0;
const int MotifFunctionAll = 1;
const int MotifFunctionResize = 2;
const int MotifFunctionMove = 4;
const int MotifFunctionMinimize = 8;
const int MotifFunctionMaximize = 16;
const int MotifFunctionClose = 32;
const QString ddeLauncherWMClass = "dde-launcher";
#endif // COMMON_H

View File

@ -0,0 +1,229 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dbusadaptordock.h"
DBusAdaptorDock::DBusAdaptorDock(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
// constructor
setAutoRelaySignals(true);
Dock *dock = static_cast<Dock *>(QObject::parent());
if (dock) {
connect(dock, &Dock::serviceRestarted, this, [&] {
Q_EMIT ServiceRestarted();});
connect(dock, &Dock::entryAdded, this, [&](QString entryObjPath, int32_t index){
Q_EMIT EntryAdded(QDBusObjectPath(entryObjPath), index);});
connect(dock, &Dock::entryRemoved, this, &DBusAdaptorDock::EntryRemoved);
connect(dock, &Dock::hideStateChanged, this, &DBusAdaptorDock::HideStateChanged);
connect(dock, &Dock::frontendWindowRectChanged, this, &DBusAdaptorDock::FrontendWindowRectChanged);
}
}
DBusAdaptorDock::~DBusAdaptorDock()
{
// destructor
}
int DBusAdaptorDock::displayMode() const
{
return parent()->getDisplayMode();
}
void DBusAdaptorDock::setDisplayMode(int value)
{
if (displayMode() != value) {
parent()->setDisplayMode(value);
Q_EMIT DisplayModeChanged();
}
}
QStringList DBusAdaptorDock::dockedApps() const
{
return parent()->getDockedApps();
}
QList<QDBusObjectPath> DBusAdaptorDock::entries() const
{
QList<QDBusObjectPath> ret;
for (auto path : parent()->getEntryPaths())
ret.push_back(QDBusObjectPath(path));
return ret;
}
int DBusAdaptorDock::hideMode() const
{
return int(parent()->getHideMode());
}
void DBusAdaptorDock::setHideMode(int value)
{
if (hideMode() != value) {
parent()->setHideMode(HideMode(value));
Q_EMIT HideModeChanged();
}
}
int DBusAdaptorDock::hideState() const
{
return int(parent()->getHideState());
}
uint DBusAdaptorDock::hideTimeout() const
{
return parent()->getHideTimeout();
}
void DBusAdaptorDock::setHideTimeout(uint value)
{
if (hideTimeout() != value) {
parent()->setHideTimeout(value);
Q_EMIT HideTimeoutChanged();
}
}
uint DBusAdaptorDock::windowSizeEfficient() const
{
return parent()->getWindowSizeEfficient();
}
void DBusAdaptorDock::setWindowSizeEfficient(uint value)
{
if (windowSizeEfficient() != value) {
parent()->setWindowSizeEfficient(value);
Q_EMIT WindowSizeEfficientChanged();
}
}
uint DBusAdaptorDock::windowSizeFashion() const
{
return parent()->getWindowSizeFashion();
}
void DBusAdaptorDock::setWindowSizeFashion(uint value)
{
if (windowSizeFashion() != value) {
parent()->setWindowSizeFashion(value);
Q_EMIT WindowSizeFashionChanged();
}
}
QRect DBusAdaptorDock::frontendWindowRect() const
{
return parent()->getFrontendWindowRect();
}
double DBusAdaptorDock::opacity() const
{
return parent()->getOpacity();
}
uint DBusAdaptorDock::iconSize() const
{
return parent()->getIconSize();
}
void DBusAdaptorDock::setIconSize(uint value)
{
if (iconSize() != value) {
parent()->setIconSize(value);
Q_EMIT IconSizeChanged();
}
}
int DBusAdaptorDock::position() const
{
return parent()->getPosition();
}
void DBusAdaptorDock::setPosition(int value)
{
if (position() != value) {
parent()->setPosition(value);
Q_EMIT PositionChanged();
}
}
uint DBusAdaptorDock::showTimeout() const
{
return parent()->getShowTimeout();
}
void DBusAdaptorDock::setShowTimeout(uint value)
{
if (showTimeout() != value) {
parent()->setShowTimeout(value);
Q_EMIT ShowTimeoutChanged();
}
}
Dock *DBusAdaptorDock::parent() const
{
return static_cast<Dock *>(QObject::parent());
}
void DBusAdaptorDock::CloseWindow(uint win)
{
parent()->closeWindow(win);
}
// for debug
QStringList DBusAdaptorDock::GetEntryIDs()
{
return parent()->getEntryIDs();
}
bool DBusAdaptorDock::IsDocked(const QString &desktopFile)
{
return parent()->isDocked(desktopFile);
}
bool DBusAdaptorDock::IsOnDock(const QString &desktopFile)
{
return parent()->isOnDock(desktopFile);
}
void DBusAdaptorDock::MoveEntry(int index, int newIndex)
{
parent()->moveEntry(index, newIndex);
}
QString DBusAdaptorDock::QueryWindowIdentifyMethod(uint win)
{
return parent()->queryWindowIdentifyMethod(win);
}
bool DBusAdaptorDock::RequestDock(const QString &desktopFile, int index)
{
return parent()->requestDock(desktopFile, index);
}
bool DBusAdaptorDock::RequestUndock(const QString &desktopFile)
{
return parent()->requestUndock(desktopFile);
}
void DBusAdaptorDock::SetFrontendWindowRect(int x, int y, uint width, uint height)
{
parent()->setFrontendWindowRect(x, y, width, height);
}

View File

@ -0,0 +1,193 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DBUSADAPTORDOCK_H
#define DBUSADAPTORDOCK_H
#include "dock.h"
#include <QtCore/QObject>
#include <QtCore/QMetaObject>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QRect>
/*
* Adaptor class for interface org.deepin.dde.daemon.Dock1
*/
class DBusAdaptorDock: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Dock1")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"org.deepin.dde.daemon.Dock1\">\n"
" <method name=\"CloseWindow\">\n"
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
" </method>\n"
" <method name=\"GetEntryIDs\">\n"
" <arg direction=\"out\" type=\"as\" name=\"list\"/>\n"
" </method>\n"
" <method name=\"IsDocked\">\n"
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
" </method>\n"
" <method name=\"IsOnDock\">\n"
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
" </method>\n"
" <method name=\"MoveEntry\">\n"
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"newIndex\"/>\n"
" </method>\n"
" <method name=\"QueryWindowIdentifyMethod\">\n"
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
" <arg direction=\"out\" type=\"s\" name=\"identifyMethod\"/>\n"
" </method>\n"
" <method name=\"RequestDock\">\n"
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
" </method>\n"
" <method name=\"RequestUndock\">\n"
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
" </method>\n"
" <method name=\"SetFrontendWindowRect\">\n"
" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
" <arg direction=\"in\" type=\"u\" name=\"width\"/>\n"
" <arg direction=\"in\" type=\"u\" name=\"height\"/>\n"
" </method>\n"
" <signal name=\"ServiceRestarted\"/>\n"
" <signal name=\"EntryAdded\">\n"
" <arg type=\"o\" name=\"path\"/>\n"
" <arg type=\"i\" name=\"index\"/>\n"
" </signal>\n"
" <signal name=\"EntryRemoved\">\n"
" <arg type=\"s\" name=\"entryId\"/>\n"
" </signal>\n"
" <property access=\"readwrite\" type=\"u\" name=\"ShowTimeout\"/>\n"
" <property access=\"readwrite\" type=\"u\" name=\"HideTimeout\"/>\n"
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeEfficient\"/>\n"
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeFashion\"/>\n"
" <property access=\"read\" type=\"iiii\" name=\"FrontendWindowRect\"/>\n"
" <property access=\"read\" type=\"d\" name=\"Opacity\"/>\n"
" <property access=\"read\" type=\"ao\" name=\"Entries\"/>\n"
" <property access=\"readwrite\" type=\"i\" name=\"HideMode\"/>\n"
" <property access=\"readwrite\" type=\"i\" name=\"DisplayMode\"/>\n"
" <property access=\"read\" type=\"i\" name=\"HideState\"/>\n"
" <property access=\"readwrite\" type=\"i\" name=\"Position\"/>\n"
" <property access=\"readwrite\" type=\"u\" name=\"IconSize\"/>\n"
" <property access=\"read\" type=\"as\" name=\"DockedApps\"/>\n"
" </interface>\n"
"")
public:
DBusAdaptorDock(QObject *parent);
virtual ~DBusAdaptorDock();
public: // PROPERTIES
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
int displayMode() const;
void setDisplayMode(int value);
Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged)
QStringList dockedApps() const;
Q_PROPERTY(QList<QDBusObjectPath> Entries READ entries NOTIFY EntriesChanged)
QList<QDBusObjectPath> entries() const;
Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged)
int hideMode() const;
void setHideMode(int value);
Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged)
int hideState() const;
Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged)
uint hideTimeout() const;
void setHideTimeout(uint value);
Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged)
uint windowSizeEfficient() const;
void setWindowSizeEfficient(uint value);
Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged)
uint windowSizeFashion() const;
void setWindowSizeFashion(uint value);
Q_PROPERTY(QRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged)
QRect frontendWindowRect() const;
Q_PROPERTY(double Opacity READ opacity NOTIFY OpacityChanged)
double opacity() const;
Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged)
uint iconSize() const;
void setIconSize(uint value);
Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged)
int position() const;
void setPosition(int value);
Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged)
uint showTimeout() const;
void setShowTimeout(uint value);
Dock *parent() const;
public Q_SLOTS: // METHODS
void CloseWindow(uint win);
QStringList GetEntryIDs();
bool IsDocked(const QString &desktopFile);
bool IsOnDock(const QString &desktopFile);
void MoveEntry(int index, int newIndex);
QString QueryWindowIdentifyMethod(uint win);
bool RequestDock(const QString &desktopFile, int index);
bool RequestUndock(const QString &desktopFile);
void SetFrontendWindowRect(int x, int y, uint width, uint height);
Q_SIGNALS: // SIGNALS
void ServiceRestarted();
void EntryAdded(const QDBusObjectPath &path, int index);
void EntryRemoved(const QString &entryId);
void DisplayModeChanged();
void DockedAppsChanged();
void OpacityChanged();
void EntriesChanged();
void HideModeChanged();
void WindowSizeEfficientChanged();
void WindowSizeFashionChanged();
void HideStateChanged();
void FrontendWindowRectChanged();
void HideTimeoutChanged();
void IconSizeChanged();
void PositionChanged();
void ShowTimeoutChanged();
};
#endif

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dbusadaptorentry.h"
DBusAdaptorEntry::DBusAdaptorEntry(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
// constructor
setAutoRelaySignals(true);
//qDBusRegisterMetaType<ExportWindowInfo>();
Entry *entry = static_cast<Entry *>(QObject::parent());
if (entry) {
connect(entry, &Entry::isActiveChanged, this, &DBusAdaptorEntry::IsActiveChanged);
connect(entry, &Entry::isDockedChanged, this, &DBusAdaptorEntry::IsDockedChanged);
connect(entry, &Entry::menuChanged, this, &DBusAdaptorEntry::MenuChanged);
connect(entry, &Entry::iconChanged, this, &DBusAdaptorEntry::IconChanged);
connect(entry, &Entry::nameChanged, this, &DBusAdaptorEntry::NameChanged);
connect(entry, &Entry::desktopFileChanged, this, &DBusAdaptorEntry::DesktopFileChanged);
connect(entry, &Entry::currentWindowChanged, this, &DBusAdaptorEntry::CurrentWindowChanged);
}
}
DBusAdaptorEntry::~DBusAdaptorEntry()
{
// destructor
}
uint DBusAdaptorEntry::currentWindow() const
{
return parent()->getCurrentWindow();
}
QString DBusAdaptorEntry::desktopFile() const
{
return parent()->getDesktopFile();
}
QString DBusAdaptorEntry::icon() const
{
return parent()->getIcon();
}
QString DBusAdaptorEntry::id() const
{
return parent()->getId();
}
bool DBusAdaptorEntry::isActive() const
{
return parent()->getIsActive();
}
bool DBusAdaptorEntry::isDocked() const
{
return parent()->getIsDocked();
}
QString DBusAdaptorEntry::menu() const
{
return parent()->getMenu();
}
QString DBusAdaptorEntry::name() const
{
return parent()->getName();
}
/*
QList<ExportWindowInfo> DBusAdaptorEntry::windowInfos()
{
return parent()->getExportWindowInfos();
}
*/
Entry *DBusAdaptorEntry::parent() const
{
return static_cast<Entry *>(QObject::parent());
}
void DBusAdaptorEntry::Activate(uint timestamp)
{
parent()->active(timestamp);
}
void DBusAdaptorEntry::Check()
{
parent()->check();
}
void DBusAdaptorEntry::ForceQuit()
{
parent()->forceQuit();
}
QList<QVariant> DBusAdaptorEntry::GetAllowedCloseWindows()
{
auto ids = parent()->getAllowedClosedWindowIds();
QList<QVariant> ret;
for (auto id : ids)
ret.push_back(id);
return ret;
}
void DBusAdaptorEntry::HandleDragDrop(uint timestamp, const QStringList &files)
{
parent()->handleDragDrop(timestamp, files);
}
void DBusAdaptorEntry::HandleMenuItem(uint timestamp, const QString &id)
{
parent()->handleMenuItem(timestamp, id);
}
void DBusAdaptorEntry::NewInstance(uint timestamp)
{
parent()->newInstance(timestamp);
}
void DBusAdaptorEntry::PresentWindows()
{
parent()->presentWindows();
}
void DBusAdaptorEntry::RequestDock()
{
parent()->requestDock();
}
void DBusAdaptorEntry::RequestUndock()
{
parent()->requestUndock();
}
QDBusArgument &operator <<(QDBusArgument &argument, const ExportWindowInfo &info)
{
argument.beginStructure();
argument << info.xid << info.title << info.flash;
argument.endStructure();
return argument;
}
const QDBusArgument &operator >>(const QDBusArgument &argument, ExportWindowInfo &info)
{
argument.beginStructure();
argument >> info.xid >> info.title >> info.flash;
argument.endStructure();
return argument;
}
QDebug operator<<(QDebug deg, const ExportWindowInfo &info)
{
qDebug() << "xid: " << info.xid << " title:" << info.title << " flash:" << info.flash;
return deg;
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DBUSADAPTORENTRY_H
#define DBUSADAPTORENTRY_H
#include "entry.h"
#include <QtCore/QObject>
#include <QtCore/QMetaObject>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <DBusExtendedAbstractInterface>
Q_DECLARE_METATYPE(ExportWindowInfo)
QDBusArgument &operator <<(QDBusArgument &argument, const ExportWindowInfo &info);
const QDBusArgument &operator >>(const QDBusArgument &argument, ExportWindowInfo &info);
QDebug operator<<(QDebug deg, const ExportWindowInfo &info);
/*
* Adaptor class for interface org.deepin.dde.daemon.Dock1.Entry
*/
class DBusAdaptorEntry: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Dock1.Entry")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"org.deepin.dde.daemon.Dock1.Entry\">\n"
" <method name=\"Activate\">\n"
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
" </method>\n"
" <method name=\"Check\"/>\n"
" <method name=\"ForceQuit\"/>\n"
" <method name=\"GetAllowedCloseWindows\">\n"
" <arg direction=\"out\" type=\"au\" name=\"windows\"/>\n"
" </method>\n"
" <method name=\"HandleDragDrop\">\n"
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
" <arg direction=\"in\" type=\"as\" name=\"files\"/>\n"
" </method>\n"
" <method name=\"HandleMenuItem\">\n"
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
" </method>\n"
" <method name=\"NewInstance\">\n"
" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
" </method>\n"
" <method name=\"PresentWindows\"/>\n"
" <method name=\"RequestDock\"/>\n"
" <method name=\"RequestUndock\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Name\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Icon\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Id\"/>\n"
" <property access=\"read\" type=\"b\" name=\"IsActive\"/>\n"
" <property access=\"read\" type=\"u\" name=\"CurrentWindow\"/>\n"
" <property access=\"read\" type=\"b\" name=\"IsDocked\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Menu\"/>\n"
" <property access=\"read\" type=\"s\" name=\"DesktopFile\"/>\n"
" <property access=\"read\" type=\"a(usb)\" name=\"WindowInfos\"/>\n"
" </interface>\n"
"")
public:
DBusAdaptorEntry(QObject *parent);
virtual ~DBusAdaptorEntry();
public: // PROPERTIES
Q_PROPERTY(uint CurrentWindow READ currentWindow NOTIFY CurrentWindowChanged)
uint currentWindow() const;
Q_PROPERTY(QString DesktopFile READ desktopFile NOTIFY DesktopFileChanged)
QString desktopFile() const;
Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged)
QString icon() const;
Q_PROPERTY(QString Id READ id)
QString id() const;
Q_PROPERTY(bool IsActive READ isActive NOTIFY IsActiveChanged)
bool isActive() const;
Q_PROPERTY(bool IsDocked READ isDocked NOTIFY IsDockedChanged)
bool isDocked() const;
Q_PROPERTY(QString Menu READ menu NOTIFY MenuChanged)
QString menu() const;
Q_PROPERTY(QString Name READ name NOTIFY NameChanged)
QString name() const;
//Q_PROPERTY(QString WindowInfos READ windowInfos)
//QList<ExportWindowInfo> windowInfos();
Entry *parent() const;
public Q_SLOTS: // METHODS
void Activate(uint timestamp);
void Check();
void ForceQuit();
QList<QVariant> GetAllowedCloseWindows();
void HandleDragDrop(uint timestamp, const QStringList &files);
void HandleMenuItem(uint timestamp, const QString &id);
void NewInstance(uint timestamp);
void PresentWindows();
void RequestDock();
void RequestUndock();
Q_SIGNALS: // SIGNALS
void IsActiveChanged(bool value);
void IsDockedChanged(bool value);
void MenuChanged(QString value);
void IconChanged(QString value);
void NameChanged(QString value);
void DesktopFileChanged(QString value);
void CurrentWindowChanged(uint32_t value);
};
#endif

View File

@ -0,0 +1,214 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dbushandler.h"
#include "dock.h"
#include "windowinfok.h"
#include "dbusbamfapplication.h"
DBusHandler::DBusHandler(Dock *_dock, QObject *parent)
: QObject(parent)
, dock(_dock)
, session(QDBusConnection::sessionBus())
, launcherEnd(new LauncherBackEnd("org.deepin.dde.daemon.Launcher1", "/org/deepin/dde/daemon/Launcher1", session, this))
, launcherFront(new LauncherFront("org.deepin.dde.Launcher1", "/org/deepin/dde/Launcher1", session, this))
, wm(new com::deepin::WM("com.deepin.wm", "/com/deepin/wm", session, this))
, wmSwitcher(new com::deepin::WMSwitcher("com.deepin.wmWMSwitcher", "/com/deepin/WMSwitcher", session, this))
, kwaylandManager(nullptr)
, bamfMatcher(new org::ayatana::bamf::BamfMatcher("org.ayatana.bamf.matcher", "/org/ayatana/bamf/matcher", session, this))
{
// 关联org.deepin.dde.daemon.Launcher1事件 ItemChanged
connect(launcherEnd, &LauncherBackEnd::ItemChanged, this, &DBusHandler::handleLauncherItemChanged);
// 关联org.deepin.dde.Launcher1事件 VisibleChanged
connect(launcherFront, &LauncherFront::VisibleChanged, this, [&](bool visible) {
dock->setDdeLauncherVisible(visible);
dock->updateHideState(false);
});
// 关联com.deepin.WMSwitcher事件 WMChanged
connect(wmSwitcher, &__WMSwitcher::WMChanged, this, [&](QString name) {dock->setWMName(name);});
}
// 关联com.deepin.daemon.KWayland.WindowManager事件
void DBusHandler::listenWaylandWMSignals()
{
kwaylandManager = new com::deepin::daemon::kwayland::WindowManager("com.deepin.daemon.KWayland", "/com/deepin/daemon/KWayland/WindowManager", session, this);
// ActiveWindowchanged
connect(kwaylandManager, &__KwaylandManager::ActiveWindowChanged, this, &DBusHandler::handleWlActiveWindowchange);
// WindowCreated
connect(kwaylandManager, &__KwaylandManager::WindowCreated, this, [&] (const QString &ObjPath) {
dock->registerWindowWayland(ObjPath);
});
// WindowRemove
connect(kwaylandManager, &__KwaylandManager::WindowRemove, this, [&] (const QString &ObjPath) {
dock->unRegisterWindowWayland(ObjPath);
});
}
void DBusHandler::handleLauncherItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID)
{
qInfo() << "handleLauncherItemChanged status:" << status << " Name:" << itemInfo.Name << " ID:" << itemInfo.ID;
if (status == "deleted") {
dock->handleLauncherItemDeleted(itemInfo.Path);
} else if (status == "created") {
// don't need to download to dock when app reinstall
} else if (status == "updated") {
dock->handleLauncherItemUpdated(itemInfo.Path);
}
}
QString DBusHandler::getCurrentWM()
{
return wmSwitcher->CurrentWM().value();
}
// TODO 扩展ApplicationManager Run接口允许带参数启动应用暂时调用StartManager接口
void DBusHandler::launchApp(uint32_t timestamp, QStringList files)
{
QDBusInterface interface = QDBusInterface("com.deepin.StartManager", "/com/deepin/StartManager", "com.deepin.StartManager");
interface.call("LaunchApp", files, timestamp);
}
void DBusHandler::launchAppAction(uint32_t timestamp, QString file, QString section)
{
QDBusInterface interface = QDBusInterface("com.deepin.StartManager", "/com/deepin/StartManager", "com.deepin.StartManager");
interface.call("LaunchAppAction", file, section, timestamp);
}
void DBusHandler::markAppLaunched(const QString &filePath)
{
QDBusInterface interface = QDBusInterface("org.deepin.daemon.AlRecorder1", "/org/deepin/daemon/AlRecorder1", "org.deepin.daemon.AlRecorder1");
interface.call("MarkLaunched", filePath);
}
bool DBusHandler::wlShowingDesktop()
{
bool ret = false;
if (kwaylandManager)
ret = kwaylandManager->IsShowingDesktop().value();
return ret;
}
uint DBusHandler::wlActiveWindow()
{
uint ret = 0;
if (kwaylandManager)
ret = kwaylandManager->ActiveWindow().value();
return ret;
}
void DBusHandler::handleWlActiveWindowchange()
{
uint activeWinInternalId = wlActiveWindow();
if (activeWinInternalId == 0)
return;
WindowInfoK *info = dock->handleActiveWindowChangedK(activeWinInternalId);
if (info->getXid() != 0) {
dock->handleActiveWindowChanged(info);
} else {
dock->updateHideState(false);
}
}
void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo)
{
PlasmaWindow *window = windowInfo->getPlasmaWindow();
if (!window)
return;
// Title changed
connect(window, &PlasmaWindow::TitleChanged, this, [&] {
windowInfo->updateTitle();
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
if (!entry)
return;
if (entry->getCurrentWindowInfo() == windowInfo)
entry->updateName();
entry->updateWindowInfos();
});
// Icon changed
connect(window, &PlasmaWindow::IconChanged, this, [&] {
windowInfo->updateIcon();
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
if (!entry)
return;
entry->updateIcon();
});
// DemandingAttention changed
connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [&] {
windowInfo->updateDemandingAttention();
auto entry = dock->getEntryByWindowId(windowInfo->getXid());
if (!entry)
return;
entry->updateWindowInfos();
});
// Geometry changed
connect(window, &PlasmaWindow::GeometryChanged, this, [&] {
if (!windowInfo->updateGeometry())
return;
dock->handleWindowGeometryChanged();
});
}
PlasmaWindow *DBusHandler::createPlasmaWindow(QString objPath)
{
return new PlasmaWindow("com.deepin.daemon.KWayland.PlasmaWindow", objPath, session, this);
}
// 取消关联信号
void DBusHandler::removePlasmaWindowHandler(PlasmaWindow *window)
{
}
void DBusHandler::presentWindows(QList<uint> windows)
{
wm->PresentWindows(windows);
}
QString DBusHandler::getDesktopFromWindowByBamf(XWindow windowId)
{
QDBusPendingReply<QString> reply = bamfMatcher->ApplicationForXid(windowId);
if (!reply.isValid())
return "";
QString appObjPath = reply.value();
org::ayatana::bamf::BamfApplication bamfApp("org.ayatana.bamf.application", appObjPath, session, this);
if (bamfApp.isValid())
return bamfApp.DesktopFile();
return "";
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DBUSHANDLER_H
#define DBUSHANDLER_H
#include "dbuslauncher.h"
#include "dbuslauncherfront.h"
#include "dbuswm.h"
#include "dbuswmswitcher.h"
#include "dbuskwaylandwindowmanager.h"
#include "windowinfok.h"
#include "dbusplasmawindow.h"
#include "dbusbamfmatcher.h"
#include <QObject>
#include <QDBusConnection>
#include <QDBusMessage>
class Dock;
// 处理DBus交互
class DBusHandler : public QObject
{
Q_OBJECT
public:
explicit DBusHandler(Dock *_dock, QObject *parent = nullptr);
/************************* KWayland/WindowManager ***************************/
void listenWaylandWMSignals();
bool wlShowingDesktop();
uint wlActiveWindow();
/************************* daemon.Launcher1 ***************************/
void handleLauncherItemChanged(const QString &status, LauncherItemInfo itemInfo, qlonglong categoryID);
/************************* WMSwitcher ***************************/
QString getCurrentWM();
/************************* StartManager ***************************/
void launchApp(uint32_t timestamp, QStringList files);
void launchAppAction(uint32_t timestamp, QString file, QString section);
/************************* AlRecorder1 ***************************/
void markAppLaunched(const QString &filePath);
/************************* KWayland.PlasmaWindow ***************************/
void listenKWindowSignals(WindowInfoK *windowInfo);
PlasmaWindow *createPlasmaWindow(QString objPath);
void removePlasmaWindowHandler(PlasmaWindow *window);
/************************* WM ***************************/
void presentWindows(QList<uint> windows);
/************************* bamf ***************************/
// XWindow -> desktopFile
QString getDesktopFromWindowByBamf(XWindow windowId);
private Q_SLOTS:
void handleWlActiveWindowchange();
private:
Dock *dock;
QDBusConnection session;
LauncherBackEnd *launcherEnd;
LauncherFront *launcherFront;
com::deepin::WM *wm;
com::deepin::WMSwitcher *wmSwitcher;
com::deepin::daemon::kwayland::WindowManager *kwaylandManager;
org::ayatana::bamf::BamfMatcher *bamfMatcher;
};
#endif // DBUSHANDLER_H

1045
src/modules/dock/dock.cpp Normal file

File diff suppressed because it is too large Load Diff

191
src/modules/dock/dock.h Normal file
View File

@ -0,0 +1,191 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOCK_H
#define DOCK_H
#include "synmodule.h"
#include "docksettings.h"
#include "entries.h"
#include "dbusplasmawindow.h"
#include <QStringList>
#include <QTimer>
#include <QMutex>
class WindowIdentify;
class DBusHandler;
class WaylandManager;
class X11Manager;
class WindowInfoK;
class WindowInfoX;
// 任务栏
class Dock : public SynModule
{
Q_OBJECT
enum class HideState
{
Unknown,
Show,
Hide,
};
public:
explicit Dock(QObject *parent = nullptr);
~Dock();
bool dockEntry(Entry *entry);
void undockEntry(Entry *entry);
QString allocEntryId();
bool shouldShowOnDock(WindowInfoBase *info);
void setDdeLauncherVisible(bool visible);
QString getWMName();
void setWMName(QString name);
void setPropHideMode(HideState state);
void attachOrDetachWindow(WindowInfoBase *info);
void attachWindow(WindowInfoBase *info);
void detachWindow(WindowInfoBase *info);
void markAppLaunched(const QString &filePath);
void launchApp(uint32_t timestamp, QStringList files);
void launchAppAction(uint32_t timestamp, QString file, QString section);
bool is3DWM();
bool isWaylandEnv();
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
void handleActiveWindowChanged(WindowInfoBase *info);
void saveDockedApps();
void removeAppEntry(Entry *entry);
void handleWindowGeometryChanged();
Entry *getEntryByWindowId(XWindow windowId);
QString getDesktopFromWindowByBamf(XWindow windowId);
void registerWindowWayland(const QString &objPath);
void unRegisterWindowWayland(const QString &objPath);
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
void markAppLaunched(AppInfo *appInfo);
void deleteWindow(XWindow xid);
ForceQuitAppMode getForceQuitAppStatus();
QVector<QString> getWinIconPreferredApps();
void handleLauncherItemDeleted(QString itemPath);
void handleLauncherItemUpdated(QString itemPath);
double getOpacity();
QRect getFrontendWindowRect();
int getDisplayMode();
void setDisplayMode(int mode);
QStringList getDockedApps();
QStringList getEntryPaths();
HideMode getHideMode();
void setHideMode(HideMode mode);
HideState getHideState();
void setHideState(HideState state);
uint getHideTimeout();
void setHideTimeout(uint timeout);
uint getIconSize();
void setIconSize(uint size);
int getPosition();
void setPosition(int position);
uint getShowTimeout();
void setShowTimeout(uint timeout);
uint getWindowSizeEfficient();
void setWindowSizeEfficient(uint size);
uint getWindowSizeFashion();
void setWindowSizeFashion(uint size);
// 设置配置
void setSynConfig(QByteArray ba);
QByteArray getSyncConfig();
/******************************** dbus handler ****************************/
PlasmaWindow *createPlasmaWindow(QString objPath);
void listenKWindowSignals(WindowInfoK *windowInfo);
void removePlasmaWindowHandler(PlasmaWindow *window);
void presentWindows(QList<uint> windows);
HideMode getDockHideMode();
WindowInfoBase *getActiveWindow();
QList<XWindow> getClientList();
void closeWindow(XWindow windowId);
QStringList getEntryIDs();
void setFrontendWindowRect(int32_t x, int32_t y, uint width, uint height);
bool isDocked(const QString desktopFile);
bool requestDock(QString desktopFile, int index);
bool requestUndock(QString desktopFile);
void moveEntry(int oldIndex, int newIndex);
bool isOnDock(QString desktopFile);
QString queryWindowIdentifyMethod(XWindow windowId);
QStringList getDockedAppsDesktopFiles();
QString getPluginSettings();
void setPluginSettings(QString jsonStr);
void mergePluginSettings(QString jsonStr);
void removePluginSettings(QString pluginName, QStringList settingkeys);
void updateHideState(bool delay);
Q_SIGNALS:
void serviceRestarted();
void entryAdded(QString entryObjPath, int32_t index);
void entryRemoved(QString id);
void hideStateChanged();
void frontendWindowRectChanged();
private Q_SLOTS:
void smartHideModeTimerExpired();
private:
void initSettings();
void updateMenu();
void initEntries();
void initDockedApps();
void initClientList();
WindowInfoX *findWindowByXidX(XWindow xid);
WindowInfoK *findWindowByXidK(XWindow xid);
bool isWindowDockOverlapX(XWindow xid);
bool isWindowDockOverlapK(WindowInfoBase *info);
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
bool shouldHideOnSmartHideMode();
QVector<XWindow> getActiveWinGroup(XWindow xid);
WindowIdentify *windowIdentify; // 窗口识别
Entries *entries; // 所有应用实例
int entriesSum; // 累计打开的应用数量
bool ddeLauncherVisible; // 前端启动器是否可见
QString wmName; // 窗管名称
WaylandManager *waylandManager; // wayland窗口管理
X11Manager *x11Manager; // X11窗口管理
QList<XWindow> clientList; // 所有窗口
QRect frontendWindowRect; // 前端任务栏大小, 用于智能隐藏时判断窗口是否重合
HideState hideState; // 记录任务栏隐藏状态
QTimer *smartHideTimer; // 任务栏智能隐藏定时器
WindowInfoBase *activeWindow;// 记录当前活跃窗口信息
WindowInfoBase *activeWindowOld;// 记录前一个活跃窗口信息
bool isWayland; // 判断是否为wayland环境
ForceQuitAppMode forceQuitAppStatus; // 强制退出应用状态
DBusHandler *dbusHandler; // 处理dbus交互
QMutex windowOperateMutex; // 窗口合并或拆分锁
};
#endif // DOCK_H

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dockmanager.h"
#include "dock.h"
#include <QDBusConnection>
#include <QDebug>
#include <QDBusError>
DockManager::DockManager(QObject *parent)
: QObject(parent)
, dock(new Dock(this))
{
adaptor = new DBusAdaptorDock(dock);
QDBusConnection con = QDBusConnection::sessionBus();
if (!con.registerService(dbusService)) {
qWarning() << "register service Dock1 error:" << con.lastError().message();
return;
}
if (!con.registerObject(dbusPath, dock, QDBusConnection::ExportAdaptors))
{
qWarning() << "register object Dock1 error:" << con.lastError().message();
return;
}
}
DockManager::~DockManager()
{
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOCKMANAGER_H
#define DOCKMANAGER_H
#include "dbusadaptordock.h"
#include <QObject>
class Dock;
// 任务栏管理类
class DockManager : public QObject
{
Q_OBJECT
public:
explicit DockManager(QObject *parent = nullptr);
~DockManager();
Q_SIGNALS:
public Q_SLOTS:
private:
Dock *dock;
DBusAdaptorDock *adaptor;
};
#endif // DOCKMANAGER_H

View File

@ -0,0 +1,354 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "docksettings.h"
#include "settings.h"
#include <DConfig>
#include <QDebug>
#include <QJsonObject>
#include <QJsonDocument>
DCORE_USE_NAMESPACE
static DConfig *dockSettings = Settings::ConfigPtr(configDock);
static DConfig *appearanceSettings = Settings::ConfigPtr(configAppearance);
DockSettings::DockSettings(QObject *parent)
: QObject (parent)
{
init();
}
void DockSettings::init()
{
// 绑定属性
if (dockSettings) {
connect(dockSettings, &DConfig::valueChanged, this, [&] (const QString &key) {
if (key == keyHideMode) {
Q_EMIT hideModeChanged(HideMode(dockSettings->value(key).toInt()));
} else if(key == keyDisplayMode) {
Q_EMIT displayModeChanged(DisplayMode(dockSettings->value(key).toInt()));
} else if (key == keyPosition) {
Q_EMIT positionModeChanged(PositonMode(dockSettings->value(key).toInt()));
} else if (key == keyForceQuitApp){
Q_EMIT forceQuitAppChanged(dockSettings->value(key).toBool());
}
});
}
}
HideMode DockSettings::getHideMode()
{
HideMode ret = HideMode::Unknown;
if (dockSettings) {
QString mode = dockSettings->value(keyHideMode).toString();
HideModeHandler handler(mode);
ret = handler.toEnum();
}
return ret;
}
void DockSettings::setHideMode(HideMode mode)
{
if (dockSettings) {
dockSettings->setValue(keyHideMode, HideModeHandler(mode).toString());
}
}
DisplayMode DockSettings::getDisplayMode()
{
DisplayMode ret = DisplayMode::Unknown;
if (dockSettings) {
QString mode = dockSettings->value(keyDisplayMode).toString();
DisplayModeHandler handler(mode);
ret = handler.toEnum();
}
return ret;
}
void DockSettings::setDisplayMode(DisplayMode mode)
{
if (dockSettings) {
dockSettings->setValue(keyHideMode, DisplayModeHandler(mode).toString());
}
}
PositonMode DockSettings::getPositionMode()
{
PositonMode ret = PositonMode::Unknown;
if (dockSettings) {
QString mode = dockSettings->value(keyPosition).toString();
PositonModeHandler handler(mode);
ret = handler.toEnum();
}
return ret;
}
void DockSettings::setPositionMode(PositonMode mode)
{
if (dockSettings) {
dockSettings->setValue(keyPosition, PositonModeHandler(mode).toString());
}
}
ForceQuitAppMode DockSettings::getForceQuitAppMode()
{
ForceQuitAppMode ret = ForceQuitAppMode::Unknown;
if (dockSettings) {
QString mode = dockSettings->value(keyForceQuitApp).toString();
ForceQuitAppModeHandler handler(mode);
ret = handler.toEnum();
}
return ret;
}
void DockSettings::setForceQuitAppMode(ForceQuitAppMode mode)
{
if (dockSettings) {
dockSettings->setValue(keyForceQuitApp, ForceQuitAppModeHandler(mode).toString());
}
}
uint DockSettings::getIconSize()
{
uint size = 36;
if (dockSettings) {
size = dockSettings->value(keyIconSize).toUInt();
}
return size;
}
void DockSettings::setIconSize(uint size)
{
if (dockSettings) {
dockSettings->setValue(keyIconSize, size);
}
}
uint DockSettings::getShowTimeout()
{
uint time = 100;
if (dockSettings) {
time = dockSettings->value(keyShowTimeout).toUInt();
}
return time;
}
void DockSettings::setShowTimeout(uint time)
{
if (dockSettings) {
dockSettings->setValue(keyShowTimeout, time);
}
}
uint DockSettings::getHideTimeout()
{
uint time = 0;
if (dockSettings) {
time = dockSettings->value(keyHideTimeout).toUInt();
}
return time;
}
void DockSettings::setHideTimeout(uint time)
{
if (dockSettings) {
dockSettings->setValue(keyHideTimeout, time);
}
}
uint DockSettings::getWindowSizeEfficient()
{
uint size = 40;
if (dockSettings) {
size = dockSettings->value(keyWindowSizeEfficient).toUInt();
}
return size;
}
void DockSettings::setWindowSizeEfficient(uint size)
{
if (dockSettings) {
dockSettings->setValue(keyWindowSizeEfficient, size);
}
}
uint DockSettings::getWindowSizeFashion()
{
uint size = 48;
if (dockSettings) {
size = dockSettings->value(keyWindowSizeFashion).toUInt();
}
return size;
}
void DockSettings::setWindowSizeFashion(uint size)
{
if (dockSettings) {
dockSettings->setValue(keyWindowSizeFashion, size);
}
}
QStringList DockSettings::getDockedApps()
{
QStringList ret;
if (!dockSettings)
return ret;
for(const auto &var : dockSettings->value(keyDockedApps).toList()) {
if (var.isValid())
ret.push_back(var.toString());
}
return ret;
}
void DockSettings::setDockedApps(QList<QString> &apps)
{
if (!dockSettings)
return;
qDebug() << "docked apps:" << apps;
QVariantList list;
for (auto app : apps) {
list << QVariant(app);
}
dockSettings->setValue(keyDockedApps, list);
}
double DockSettings::getOpacity()
{
double opacity = 0.4;
if (appearanceSettings) {
opacity = appearanceSettings->value(keyOpacity).toDouble();
}
return opacity;
}
QVector<QString> DockSettings::getWinIconPreferredApps()
{
QVector<QString> ret;
if (dockSettings) {
for(const auto &var : dockSettings->value(keyWinIconPreferredApps).toList()) {
if (var.isValid())
ret.push_back(var.toString());
}
}
return ret;
}
QString DockSettings::getPluginSettings()
{
QString ret;
if (dockSettings) {
ret = dockSettings->value(keyPluginSettings).toString();
}
qInfo() << "getpluginsettings:" << ret;
return ret;
}
void DockSettings::setPluginSettings(QString jsonStr)
{
if (jsonStr.isEmpty())
return;
if (dockSettings) {
dockSettings->setValue(keyPluginSettings, jsonStr);
}
}
void DockSettings::mergePluginSettings(QString jsonStr)
{
QString origin = getPluginSettings();
QJsonObject originSettings = plguinSettingsStrToObj(origin);
QJsonObject needMergeSettings = plguinSettingsStrToObj(jsonStr);
for (auto pluginsIt = needMergeSettings.begin(); pluginsIt != needMergeSettings.end(); pluginsIt++) {
const QString &pluginName = pluginsIt.key();
const QJsonObject &needMergeSettingsObj = pluginsIt.value().toObject();
QJsonObject originSettingsObj = originSettings.value(pluginName).toObject();
for (auto settingsIt = needMergeSettingsObj.begin(); settingsIt != needMergeSettingsObj.end(); settingsIt++) {
originSettingsObj.insert(settingsIt.key(), settingsIt.value());
}
// 重写plugin对应的设置
originSettings.remove(pluginName);
originSettings.insert(pluginName, originSettingsObj);
}
setPluginSettings(QJsonDocument(originSettings).toJson(QJsonDocument::JsonFormat::Compact));
}
void DockSettings::removePluginSettings(QString pluginName, QStringList settingkeys)
{
if (pluginName.isEmpty())
return;
QString origin = getPluginSettings();
QJsonObject originSettings = plguinSettingsStrToObj(origin);
if (settingkeys.size() == 0) {
originSettings.remove(pluginName);
} else {
for (auto pluginsIt = originSettings.begin(); pluginsIt != originSettings.end(); pluginsIt++) {
const QString &pluginName = pluginsIt.key();
if (pluginName != pluginName)
continue;
QJsonObject originSettingsObj = originSettings.value(pluginName).toObject();
for (const auto &key : settingkeys) {
originSettingsObj.remove(key);
}
// 重写plugin对应的设置
originSettings.remove(pluginName);
originSettings.insert(pluginName, originSettingsObj);
}
}
setPluginSettings(QJsonDocument(originSettings).toJson(QJsonDocument::JsonFormat::Compact));
}
// 借鉴自dde-dock
QJsonObject DockSettings::plguinSettingsStrToObj(QString jsonStr)
{
QJsonObject ret;
const QJsonObject &pluginSettingsObject = QJsonDocument::fromJson(jsonStr.toLocal8Bit()).object();
if (pluginSettingsObject.isEmpty()) {
return ret;
}
for (auto pluginsIt = pluginSettingsObject.constBegin(); pluginsIt != pluginSettingsObject.constEnd(); ++pluginsIt) {
const QString &pluginName = pluginsIt.key();
const QJsonObject &settingsObject = pluginsIt.value().toObject();
QJsonObject newSettingsObject = ret.value(pluginName).toObject();
for (auto settingsIt = settingsObject.constBegin(); settingsIt != settingsObject.constEnd(); ++settingsIt) {
newSettingsObject.insert(settingsIt.key(), settingsIt.value());
}
// TODO: remove not exists key-values
ret.insert(pluginName, newSettingsObject);
}
return ret;
}

View File

@ -0,0 +1,275 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOCKSETTINGS_H
#define DOCKSETTINGS_H
#include "common.h"
#include <QObject>
// 隐藏模式
enum class HideMode {
KeepShowing,
KeepHidden,
SmartHide,
Unknown,
};
class HideModeHandler {
HideMode modeEnum;
QString modeStr;
public:
HideModeHandler(HideMode mode) : modeEnum(mode), modeStr("") {}
HideModeHandler(QString mode) : modeEnum(HideMode::Unknown), modeStr(mode) {}
bool equal(HideModeHandler hideMode) {
return toString() == hideMode.toString() || toEnum() == hideMode.toEnum();
}
QString toString() {
switch (modeEnum) {
case HideMode::KeepShowing:
return "keep-showing";
case HideMode::KeepHidden:
return "keep-hidden";
case HideMode::SmartHide:
return "smart-hide";
case HideMode::Unknown:
default:
return "unknown";
}
}
HideMode toEnum() {
if (modeStr == "keep-showing")
return HideMode::KeepHidden;
else if (modeStr == "keep-hidden")
return HideMode::KeepHidden;
else if (modeStr == "smart-hide")
return HideMode::SmartHide;
else
return HideMode::Unknown;
}
};
// 显示样式
enum class DisplayMode {
Fashion,
Efficient,
Unknown,
};
class DisplayModeHandler {
DisplayMode modeEnum;
QString modeStr;
public:
DisplayModeHandler(DisplayMode mode) : modeEnum(mode), modeStr("") {}
DisplayModeHandler(QString mode) : modeEnum(DisplayMode::Unknown), modeStr(mode) {}
bool equal(DisplayModeHandler displayMode) {
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
}
QString toString() {
switch (modeEnum) {
case DisplayMode::Fashion:
return "fashion";
case DisplayMode::Efficient:
return "efficient";
case DisplayMode::Unknown:
default:
return "unknown";
}
}
DisplayMode toEnum() {
if (modeStr == "fashion")
return DisplayMode::Fashion;
else if (modeStr == "efficient")
return DisplayMode::Efficient;
else
return DisplayMode::Unknown;
}
};
// 显示位置
enum class PositonMode {
TOP,
Right,
Bottom,
Left,
Unknown,
};
class PositonModeHandler {
PositonMode modeEnum;
QString modeStr;
public:
PositonModeHandler(PositonMode mode) : modeEnum(mode), modeStr("") {}
PositonModeHandler(QString mode) : modeEnum(PositonMode::Unknown), modeStr(mode) {}
bool equal(PositonModeHandler displayMode) {
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
}
QString toString() {
switch (modeEnum) {
case PositonMode::TOP:
return "top";
case PositonMode::Right:
return "right";
case PositonMode::Bottom:
return "bottom";
case PositonMode::Left:
return "left";
case PositonMode::Unknown:
default:
return "unknown";
}
}
PositonMode toEnum() {
if (modeStr == "top")
return PositonMode::TOP;
else if (modeStr == "right")
return PositonMode::Right;
else if (modeStr == "bottom")
return PositonMode::Bottom;
else if (modeStr == "left")
return PositonMode::Left;
else
return PositonMode::Unknown;
}
};
// 强制退出应用菜单状态
enum class ForceQuitAppMode {
Enabled, // 开启
Disabled, // 关闭
Deactivated, // 置灰
Unknown
};
class ForceQuitAppModeHandler {
ForceQuitAppMode modeEnum;
QString modeStr;
public:
ForceQuitAppModeHandler(ForceQuitAppMode mode) : modeEnum(mode), modeStr("") {}
ForceQuitAppModeHandler(QString mode) : modeEnum(ForceQuitAppMode::Unknown), modeStr(mode) {}
bool equal(ForceQuitAppModeHandler displayMode) {
return toString() == displayMode.toString() || toEnum() == displayMode.toEnum();
}
QString toString() {
switch (modeEnum) {
case ForceQuitAppMode::Enabled:
return "enabled";
case ForceQuitAppMode::Disabled:
return "disabled";
case ForceQuitAppMode::Deactivated:
return "deactivated";
case ForceQuitAppMode::Unknown:
default:
return "unknown";
}
}
ForceQuitAppMode toEnum() {
if (modeStr == "enabled")
return ForceQuitAppMode::Enabled;
else if (modeStr == "disabled")
return ForceQuitAppMode::Disabled;
else if (modeStr == "deactivated")
return ForceQuitAppMode::Deactivated;
else
return ForceQuitAppMode::Unknown;
}
};
class Settings;
// 任务栏组策略配置类
class DockSettings: public QObject
{
Q_OBJECT
public:
static inline DockSettings *instance() {
static DockSettings instance;
return &instance;
}
void init();
HideMode getHideMode();
void setHideMode(HideMode mode);
DisplayMode getDisplayMode();
void setDisplayMode(DisplayMode mode);
PositonMode getPositionMode();
void setPositionMode(PositonMode mode);
ForceQuitAppMode getForceQuitAppMode();
void setForceQuitAppMode(ForceQuitAppMode mode);
uint getIconSize();
void setIconSize(uint size);
uint getShowTimeout();
void setShowTimeout(uint time);
uint getHideTimeout();
void setHideTimeout(uint time);
uint getWindowSizeEfficient();
void setWindowSizeEfficient(uint size);
uint getWindowSizeFashion();
void setWindowSizeFashion(uint size);
QStringList getDockedApps();
void setDockedApps(QList<QString> &apps);
double getOpacity();
QVector<QString> getWinIconPreferredApps();
// plugin settings
QString getPluginSettings();
void setPluginSettings(QString jsonStr);
void mergePluginSettings(QString jsonStr);
void removePluginSettings(QString pluginName, QStringList settingkeys);
QJsonObject plguinSettingsStrToObj(QString jsonStr);
Q_SIGNALS:
// 隐藏模式改变
void hideModeChanged(HideMode mode);
// 显示样式改变
void displayModeChanged(DisplayMode mode);
// 显示位置改变
void positionModeChanged(PositonMode mode);
// 强制退出应用开关改变
void forceQuitAppChanged(bool forced);
private:
DockSettings(QObject *paret = nullptr);
DockSettings(const DockSettings &);
DockSettings& operator= (const DockSettings &);
};
#endif // DOCKSETTINGS_H

View File

@ -0,0 +1,215 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entries.h"
#include "dock.h"
Entries::Entries(Dock *_dock)
: dock(_dock)
{
}
QVector<Entry *> Entries::filterDockedEntries()
{
QVector<Entry *> ret;
for (auto &entry : items) {
if (entry->isValid() && entry->getIsDocked())
ret.push_back(entry);
}
return ret;
}
Entry *Entries::getByInnerId(QString innerId)
{
Entry *ret = nullptr;
for (auto &entry : items) {
if (entry->getInnerId() == innerId)
ret = entry;
}
return ret;
}
void Entries::append(Entry *entry)
{
insert(entry, -1);
}
void Entries::insert(Entry *entry, int index)
{
if (index < 0 || index >= items.size()) {
// append
items.push_back(entry);
} else {
// insert
items.insert(index, entry);
}
insertCb(entry, index);
}
void Entries::remove(Entry *entry)
{
for (auto iter = items.begin(); iter != items.end(); iter++) {
if ((*iter)->getId() == entry->getId()) {
items.erase(iter);
removeCb(entry);
delete entry;
}
}
}
void Entries::move(int oldIndex, int newIndex)
{
if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= items.size() || newIndex >= items.size())
return;
items.swap(oldIndex, newIndex);
}
Entry *Entries::getByWindowPid(int pid)
{
Entry *ret = nullptr;
for (auto &entry : items) {
if (entry->getWindowInfoByPid(pid)) {
ret = entry;
break;
}
}
return ret;
}
Entry *Entries::getByWindowId(XWindow windowId)
{
Entry *ret = nullptr;
for (auto &entry : items) {
if (entry->getWindowInfoByWinId(windowId)) {
ret = entry;
break;
}
}
return ret;
}
Entry *Entries::getByDesktopFilePath(QString filePath)
{
Entry *ret = nullptr;
for (auto &entry : items) {
if (entry->getFileName() == filePath) {
ret = entry;
break;
}
}
return ret;
}
QStringList Entries::getEntryIDs()
{
QStringList list;
for (auto item : items)
list.push_back(item->getId());
return list;
}
Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile)
{
Entry *ret = nullptr;
for (auto entry : filterDockedEntries()) {
if (!entry->isValid())
continue;
if (desktopFile == entry->getFileName()) {
ret = entry;
break;
}
}
return ret;
}
QString Entries::queryWindowIdentifyMethod(XWindow windowId)
{
QString ret;
for (auto entry : items) {
auto window = entry->getWindowInfoByWinId(windowId);
if (window) {
auto app = window->getAppInfo();
if (app) {
ret = app->getIdentifyMethod();
} else {
ret = "Failed";
}
break;
}
}
return ret;
}
void Entries::handleActiveWindowChanged(XWindow activeWindId)
{
for (auto entry : items) {
auto windowInfo = entry->getWindowInfoByWinId(activeWindId);
if (windowInfo) {
entry->setPropIsActive(true);
entry->setCurrentWindowInfo(windowInfo);
entry->updateName();
entry->updateIcon();
} else {
entry->setPropIsActive(false);
}
}
}
void Entries::deleteWindow(XWindow xid)
{
for (auto entry : items) {
if (entry->containsWindow(xid)) {
entry->deleteWindow(xid);
break;
}
}
}
void Entries::updateEntriesMenu()
{
for (auto entry : items) {
entry->updateMenu();
}
}
void Entries::insertCb(Entry *entry, int index)
{
QString objPath = entryDBusObjPathPrefix + entry->getId();
Q_EMIT dock->entryAdded(objPath, index);
}
void Entries::removeCb(Entry *entry)
{
Q_EMIT dock->entryRemoved(entry->getId());
entry->stopExport();
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTRIES_H
#define ENTRIES_H
#include "entry.h"
#include <QVector>
#include <QWeakPointer>
class Dock;
// 所有应用管理类
class Entries
{
public:
Entries(Dock *_dock);
QVector<Entry *> filterDockedEntries();
Entry *getByInnerId(QString innerId);
void append(Entry *entry);
void insert(Entry *entry, int index);
void remove(Entry *entry);
void move(int oldIndex, int newIndex);
Entry *getByWindowPid(int pid);
Entry *getByWindowId(XWindow windowId);
Entry *getByDesktopFilePath(QString filePath);
QStringList getEntryIDs();
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
QString queryWindowIdentifyMethod(XWindow windowId);
void handleActiveWindowChanged(XWindow activeWindId);
void deleteWindow(XWindow xid);
void updateEntriesMenu();
void insertCb(Entry *entry, int index);
void removeCb(Entry *entry);
private:
QList<Entry *> items;
Dock *dock;
};
#endif // ENTRIES_H

787
src/modules/dock/entry.cpp Normal file
View File

@ -0,0 +1,787 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entry.h"
#include "dock.h"
#include "processinfo.h"
#include "dbusadaptorentry.h"
#include <QDebug>
#include <QDBusInterface>
#include<signal.h>
Entry::Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent)
: QObject(parent)
, dock(_dock)
, app(nullptr)
, menu(nullptr)
, isActive(false)
, isDocked(false)
, innerId(_innerId)
, current(nullptr)
, currentWindow(0)
, winIconPreferred(false)
{
setApp(_app);
id = dock->allocEntryId();
name = getName();
icon = getIcon();
}
Entry::~Entry()
{
for (auto winInfo : windowInfos) {
if (winInfo)
delete winInfo;
}
windowInfos.clear();
if (app) {
delete app;
app = nullptr;
}
if (menu) {
delete menu;
menu = nullptr;
}
}
bool Entry::isValid()
{
bool valid = false;
if (app)
valid = app->isValidApp();
return valid;
}
QString Entry::getId()
{
return id;
}
QString Entry::getName()
{
QString ret;
if (app)
ret = app->getName();
if (ret.isEmpty() && !!current)
ret = current->getDisplayName();
return ret;
}
void Entry::updateName()
{
setPropName(getName());
}
QString Entry::getIcon()
{
QString ret;
if (hasWindow()) {
if (!current)
return ret;
// has window && current not nullptr
if (winIconPreferred) {
// try current window icon first
ret = current->getIcon();
if (ret.size() > 0)
return ret;
}
if (app) {
icon = app->getIcon();
if (icon.size() > 0)
return ret;
}
ret = current->getIcon();
} else if (app) {
// no window
ret = app->getIcon();
}
return ret;
}
QString Entry::getInnerId()
{
return innerId;
}
void Entry::setInnerId(QString _innerId)
{
innerId = _innerId;
}
QString Entry::getFileName()
{
QString fileName;
if (app)
fileName = app->getFileName();
return fileName;
}
AppInfo *Entry::getApp()
{
return app;
}
void Entry::setApp(AppInfo *appinfo)
{
if (app == appinfo)
return;
if (app)
delete app;
app = appinfo;
if (!appinfo) {
winIconPreferred = true;
setPropDesktopFile("");
} else {
winIconPreferred = false;
setPropDesktopFile(appinfo->getFileName());
QString id = app->getId();
auto perferredApps = dock->getWinIconPreferredApps();
if (perferredApps.contains(id)) {
winIconPreferred = true;
return;
}
if (appinfo->getIcon().size() == 0) {
winIconPreferred = true;
}
}
}
bool Entry::getIsDocked()
{
return isDocked;
}
void Entry::setIsDocked(bool value)
{
if (value != isDocked) {
isDocked = value;
Q_EMIT isDockedChanged(value);
}
}
// 导出Dbus服务
void Entry::startExport()
{
if (getId().isEmpty()) {
qWarning() << "startExport Entry " << getName() << " id is Empty";
return;
}
new DBusAdaptorEntry(this); // export dbus by Adaptor
QDBusConnection con = QDBusConnection::sessionBus();
if (!con.registerService(dbusService)) {
qWarning() << "register service Dock1 error:" << con.lastError().message();
return;
}
objctPath = entryDBusObjPathPrefix + getId();
if (!con.registerObject(objctPath, this))
{
qWarning() << "register object Dock1 error:" << con.lastError().message();
return;
}
}
// 停止导出Dbus服务
void Entry::stopExport()
{
if (getId().isEmpty()) {
qWarning() << "stopExport Entry " << getName() << " id is Empty";
return;
}
QDBusConnection con = QDBusConnection::sessionBus();
objctPath.clear();
con.unregisterObject(entryDBusObjPathPrefix + getId());
}
void Entry::setMenu(AppMenu *_menu)
{
_menu->setDirtyStatus(true);
if (menu)
delete menu;
menu = _menu;
Q_EMIT menuChanged(menu->getMenuJsonStr());
}
void Entry::updateMenu()
{
qInfo() <<"Entry: updateMenu";
AppMenu *appMenu = new AppMenu();
appMenu->appendItem(getMenuItemLaunch());
for (auto &item :getMenuItemDesktopActions())
appMenu->appendItem(item);
bool hasWin = hasWindow();
if (hasWin)
appMenu->appendItem(getMenuItemAllWindows());
// menu item dock or undock
qInfo() << "entry " << id << " docked? " << isDocked;
if (isDocked)
appMenu->appendItem(getMenuItemUndock());
else
appMenu->appendItem(getMenuItemDock());
if (hasWindow()) {
if (dock->getForceQuitAppStatus() != ForceQuitAppMode::Disabled) {
if (app && app->getIdentifyMethod() == "Andriod")
appMenu->appendItem(getMenuItemForceQuitAndroid());
else
appMenu->appendItem(getMenuItemForceQuit());
}
if (getAllowedCloseWindows().size() > 0)
appMenu->appendItem(getMenuItemCloseAll());
}
setMenu(appMenu);
}
void Entry::updateIcon()
{
setPropIcon(getIcon());
}
void Entry::forceUpdateIcon()
{
icon = getIcon();
Q_EMIT iconChanged(icon);
}
void Entry::updateIsActive()
{
bool isActive = false;
auto activeWin = dock->getActiveWindow();
if (activeWin)
isActive = windowInfos.find(activeWin->getXid()) != windowInfos.end();
setPropIsActive(isActive);
}
WindowInfoBase *Entry::getWindowInfoByPid(int pid)
{
WindowInfoBase *ret = nullptr;
for (const auto &windowInfo : windowInfos) {
if (windowInfo->getPid() == pid) {
ret = windowInfo;
break;
}
}
return ret;
}
WindowInfoBase *Entry::getWindowInfoByWinId(XWindow windowId)
{
WindowInfoBase *ret = nullptr;
if (windowInfos.find(windowId) != windowInfos.end()) {
ret = windowInfos[windowId];
}
return ret;
}
void Entry::setPropIsDocked(bool docked)
{
if (isDocked != docked) {
isDocked = docked;
Q_EMIT isDockedChanged(docked);
}
}
void Entry::setPropIcon(QString value)
{
if (value != icon) {
icon = value;
Q_EMIT iconChanged(value);
}
}
void Entry::setPropName(QString value)
{
if (value != name) {
name = value;
Q_EMIT nameChanged(value);
}
}
void Entry::setPropIsActive(bool active)
{
if (isActive != active) {
isActive = active;
Q_EMIT isActiveChanged(active);
}
}
void Entry::setCurrentWindowInfo(WindowInfoBase *windowInfo)
{
current = windowInfo;
setPropCurrentWindow(current ? current->getXid() : 0);
}
void Entry::setPropCurrentWindow(XWindow value)
{
if (value != currentWindow) {
currentWindow = value;
Q_EMIT currentWindowChanged(value);
}
}
WindowInfoBase *Entry::getCurrentWindowInfo()
{
return current;
}
QString Entry::getExec(bool oneLine)
{
QString ret;
if (!current)
return ret;
ProcessInfo *process = current->getProcess();
if (process) {
if (oneLine)
ret = process->getOneCommandLine().c_str();
else
ret = process->getShellScriptLines().c_str();
}
return ret;
}
bool Entry::hasWindow()
{
return windowInfos.size() > 0;
}
void Entry::updateWindowInfos()
{
QList<ExportWindowInfo> infos;
bool changed = false;
for (auto info : windowInfos) {
XWindow xid = info->getXid();
QString title = info->getTitle();
bool flash = info->isDemandingAttention();
infos.push_back({xid, title, flash});
if (!changed) {
for (auto info : exportWindowInfos) {
if (info.title != title || info.flash != flash)
changed = true;
}
}
}
if (changed) {
exportWindowInfos = infos;
}
}
// 分离窗口, 返回是否需要从任务栏remove
bool Entry::detachWindow(WindowInfoBase *info)
{
info->setEntry(nullptr);
XWindow winId = info->getXid();
deleteWindow(winId);
if (windowInfos.size() == 0) {
if (!isDocked) // 既无窗口也非驻留应用,无需在任务栏显示
return true;
setCurrentWindowInfo(nullptr);
} else {
for (auto window : windowInfos) {
if (window) { // 选择第一个窗口作为当前窗口
setCurrentWindowInfo(window);
break;
}
}
}
updateWindowInfos();
updateIcon();
updateIsActive();
updateMenu();
return false;
}
bool Entry::attachWindow(WindowInfoBase *info)
{
XWindow winId = info->getXid();
qInfo() << "attatchWindow: window id:" << winId;
info->setEntry(this);
if (windowInfos.find(winId) != windowInfos.end()) {
qInfo() << "attachWindow: window " << winId << " is already attached";
return false;
}
windowInfos[winId] = info;
updateWindowInfos();
updateIsActive();
if (!current) {
// from no window to has window
setCurrentWindowInfo(info);
}
updateIcon();
updateMenu();
return true;
}
void Entry::launchApp(uint32_t timestamp)
{
dock->launchApp(timestamp, QStringList() << app->getFileName());
}
bool Entry::containsWindow(XWindow xid)
{
return windowInfos.find(xid) != windowInfos.end();
}
void Entry::deleteWindow(XWindow xid)
{
WindowInfoBase *info = windowInfos[xid];
windowInfos.remove(xid);
for (int i = 0; i < exportWindowInfos.size(); i++) {
if (exportWindowInfos[i].xid == xid) {
exportWindowInfos.removeAt(i);
break;
}
}
if (info) {
delete info;
}
}
// 处理菜单项
void Entry::handleMenuItem(uint32_t timestamp, QString itemId)
{
menu->handleAction(timestamp, itemId);
}
// 处理拖拽事件
void Entry::handleDragDrop(uint32_t timestamp, QStringList files)
{
dock->launchApp(timestamp, files);
}
// 驻留
void Entry::requestDock()
{
if (dock->dockEntry(this)) {
dock->saveDockedApps();
}
}
// 取消驻留
void Entry::requestUndock()
{
dock->undockEntry(this);
}
void Entry::newInstance(uint32_t timestamp)
{
QStringList files;
dock->launchApp(timestamp, files);
}
// 检查应用窗口分离、合并状态
void Entry::check()
{
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
dock->attachOrDetachWindow(iter.value());
}
}
// 强制退出
void Entry::forceQuit()
{
QMap<int, QVector<WindowInfoBase*>> pidWinInfoMap;
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
int pid = iter.value()->getPid();
if (pid != 0) {
pidWinInfoMap[pid].push_back(iter.value());
} else {
iter.value()->killClient();
}
for (auto iter = pidWinInfoMap.begin(); iter != pidWinInfoMap.end(); iter++) {
if (!killProcess(iter.key())) { // kill pid
for (auto &info : iter.value()) { // kill window
info->killClient();
}
}
}
}
}
void Entry::presentWindows()
{
QList<uint> windows;
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++)
windows.push_back(iter.key());
dock->presentWindows(windows);
}
void Entry::active(uint32_t timestamp)
{
}
XWindow Entry::getCurrentWindow()
{
return currentWindow;
}
QString Entry::getDesktopFile()
{
return desktopFile;
}
bool Entry::getIsActive()
{
return isActive;
}
QString Entry::getMenu()
{
return menu->getMenuJsonStr();
}
QVector<XWindow> Entry::getAllowedClosedWindowIds()
{
QVector<XWindow> ret;
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
WindowInfoBase *info = iter.value();
if (info && info->allowClose())
ret.push_back(iter.key());
}
return ret;
}
QList<ExportWindowInfo> Entry::getExportWindowInfos()
{
return exportWindowInfos;
}
QVector<WindowInfoBase *> Entry::getAllowedCloseWindows()
{
QVector<WindowInfoBase *> ret;
for (auto iter = windowInfos.begin(); iter != windowInfos.end(); iter++) {
WindowInfoBase *info = iter.value();
if (info && info->allowClose())
ret.push_back(info);
}
return ret;
}
QVector<AppMenuItem> Entry::getMenuItemDesktopActions()
{
QVector<AppMenuItem> ret;
if (!app)
return ret;
for (auto action : app->getActions()) {
AppMenuAction fn = [&](uint32_t timestamp) {
qInfo() << "do MenuItem: " << action.name.c_str();
dock->launchAppAction(timestamp, app->getFileName(), action.section.c_str());
};
AppMenuItem item;
item.text = action.name.c_str();
item.action = fn;
item.isActive = true;
ret.push_back(item);
}
return ret;
}
AppMenuItem Entry::getMenuItemLaunch()
{
QString itemName;
if (hasWindow())
itemName = getName();
else
itemName = "Open";
AppMenuAction fn = [&](uint32_t timestamp) {
qInfo() << "do MenuItem: Open";
this->launchApp(timestamp);
};
AppMenuItem item;
item.text = itemName;
item.action = fn;
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemCloseAll()
{
AppMenuAction fn = [&](uint32_t timestamp) {
qInfo() << "do MenuItem: Close All";
auto winInfos = getAllowedCloseWindows();
// 从大到小排序, 方便后面关闭窗口
for (int i = 0; i < winInfos.size() - 1; i++) {
for (int j = i + 1; j < winInfos.size(); j++) {
if (winInfos[i]->getCreatedTime() < winInfos[j]->getCreatedTime()) {
auto info = winInfos[i];
winInfos[i] = winInfos[j];
winInfos[j] = info;
}
}
}
for (auto info : winInfos) {
qInfo() << "close WindowId " << info->getXid();
info->close(timestamp);
}
};
AppMenuItem item;
item.text = "Close All";
item.action = fn;
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemForceQuit()
{
bool active = dock->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
AppMenuAction fn = [&](uint32_t) {
qInfo() << "do MenuItem: Force Quit";
forceQuit();
};
AppMenuItem item;
item.text = "Force Quit";
item.action = fn;
item.isActive = active;
return item;
}
//dock栏上Android程序的Force Quit功能
AppMenuItem Entry::getMenuItemForceQuitAndroid()
{
bool active = dock->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
auto allowedCloseWindows = getAllowedCloseWindows();
AppMenuAction fn = [](uint32_t){};
if (allowedCloseWindows.size() > 0) {
qInfo() << "do MenuItem: Force Quit";
AppMenuAction fn = [&](uint32_t timestamp) {
for (auto info : allowedCloseWindows) {
info->close(timestamp);
}
};
}
AppMenuItem item;
item.text = "Force Quit";
item.action = fn;
item.isActive = active;
return item;
}
AppMenuItem Entry::getMenuItemDock()
{
AppMenuItem item;
item.text = "Dock";
item.action = [&](uint32_t) {
qInfo() << "do MenuItem: Dock";
requestDock();
};
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemUndock()
{
AppMenuItem item;
item.text = "Undock";
item.action = [&](uint32_t) {
qInfo() << "do MenuItem: Undock";
requestUndock();
};
item.isActive = true;
return item;
}
AppMenuItem Entry::getMenuItemAllWindows()
{
AppMenuItem item;
item.text = "All Windows";
item.action = [&](uint32_t) {
qInfo() << "do MenuItem: All Windows";
presentWindows();
};
item.isActive = true;
item.hint = menuItemHintShowAllWindows;
return item;
}
bool Entry::killProcess(int pid)
{
bool ret = true;
Process p(pid);
if (p.isExist()) {
ret = !kill(pid, SIGTERM);
}
return ret;
}
bool Entry::setPropDesktopFile(QString value)
{
bool ret = false;
if (value != desktopFile) {
desktopFile = value;
ret = true;
Q_EMIT desktopFileChanged(value);
}
return ret;
}

149
src/modules/dock/entry.h Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTRY_H
#define ENTRY_H
#include "appinfo.h"
#include "appmenu.h"
#include "windowinfobase.h"
#include <QMap>
#include <QVector>
#include <QObject>
struct ExportWindowInfo {
XWindow xid;
QString title;
bool flash;
};
// 单个应用类
class Dock;
class Entry: public QObject
{
Q_OBJECT
public:
Entry(Dock *_dock, AppInfo *_app, QString _innerId, QObject *parent = nullptr);
~Entry();
bool isValid();
QString getId();
QString getName();
void updateName();
QString getIcon();
QString getInnerId();
void setInnerId(QString _innerId);
QString getFileName();
AppInfo *getApp();
void setApp(AppInfo *appinfo);
bool getIsDocked();
void setIsDocked(bool value);
void startExport();
void stopExport();
void setMenu(AppMenu *_menu);
void updateMenu();
void updateIcon();
void forceUpdateIcon();
void updateIsActive();
WindowInfoBase *getWindowInfoByPid(int pid);
WindowInfoBase *getWindowInfoByWinId(XWindow windowId);
void setPropIsDocked(bool docked);
void setPropIcon(QString value);
void setPropName(QString value);
void setPropIsActive(bool active);
void setPropCurrentWindow(XWindow value);
void setCurrentWindowInfo(WindowInfoBase *windowInfo);
WindowInfoBase *getCurrentWindowInfo();
QString getExec(bool oneLine);
bool hasWindow();
void updateWindowInfos();
bool detachWindow(WindowInfoBase *info);
bool attachWindow(WindowInfoBase *info);
void launchApp(uint32_t timestamp);
bool containsWindow(XWindow xid);
void deleteWindow(XWindow xid);
void handleMenuItem(uint32_t timestamp, QString itemId);
void handleDragDrop(uint32_t timestamp, QStringList files);
void requestDock();
void requestUndock();
void newInstance(uint32_t timestamp);
void check();
void forceQuit();
void presentWindows();
void active(uint32_t timestamp);
XWindow getCurrentWindow();
QString getDesktopFile();
bool getIsActive();
QString getMenu();
QVector<XWindow> getAllowedClosedWindowIds();
QList<ExportWindowInfo> getExportWindowInfos();
public Q_SLOTS:
QVector<WindowInfoBase *> getAllowedCloseWindows();
Q_SIGNALS:
void isActiveChanged(bool value);
void isDockedChanged(bool value);
void menuChanged(QString value);
void iconChanged(QString value);
void nameChanged(QString value);
void desktopFileChanged(QString value);
void currentWindowChanged(uint32_t value);
private:
// 右键菜单项
QVector<AppMenuItem> getMenuItemDesktopActions();
AppMenuItem getMenuItemLaunch();
AppMenuItem getMenuItemCloseAll();
AppMenuItem getMenuItemForceQuit();
AppMenuItem getMenuItemForceQuitAndroid();
AppMenuItem getMenuItemDock();
AppMenuItem getMenuItemUndock();
AppMenuItem getMenuItemAllWindows();
bool killProcess(int pid);
bool setPropDesktopFile(QString value);
Dock *dock;
AppInfo *app;
AppMenu *menu;
bool isActive;
bool isDocked;
QString id;
QString name;
QString icon;
QString innerId;
QString desktopFile;
// Dbus属性直接放到interface上
QMap<XWindow, WindowInfoBase *> windowInfos; // 该应用所有窗口
QList<ExportWindowInfo> exportWindowInfos;
WindowInfoBase *current; // 当前窗口
XWindow currentWindow; //当前窗口Id
bool winIconPreferred;
QString objctPath;
};
#endif // ENTRY_H

View File

@ -0,0 +1,141 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "processinfo.h"
#include "dstring.h"
#include "dfile.h"
ProcessInfo::ProcessInfo(int pid)
: hasPid(true)
, process(Process(pid))
{
if (pid == 0)
return;
// exe
exe = process.getExe();
// cwd
cwd = process.getCwd();
// cmdline
cmdLine = process.getCmdLine();
// ppid
Status pstatus = process.getStatus();
if (pstatus.size() > 0) {
int ppid = process.getPpid();
}
// args
auto verifyExe = [](std::string exe, std::string cwd, std::string firstArg){
if (DFile::base(firstArg) == firstArg)
return true;
if (!DFile::isAbs(firstArg))
firstArg = cwd + firstArg;
return exe == firstArg;
};
if (!verifyExe(exe, cwd, cmdLine[0])) {
auto parts = DString::splitStr(cmdLine[0], ' ');
// try again
if (verifyExe(exe, cwd, parts[0])) {
for (int j = 1; j < parts.size(); j++) {
args.push_back(parts[j]);
}
for (int i = 1; i < cmdLine.size(); i++) {
args.push_back(cmdLine[i]);
}
}
} else {
for (int i = 1; i < cmdLine.size(); i++) {
args.push_back(cmdLine[i]);
}
}
}
ProcessInfo::ProcessInfo(std::vector<std::string> &cmd)
: hasPid(false)
, process(Process())
{
if (cmd.size() == 0)
return;
cmdLine = cmd;
exe = cmd[0];
for (ulong i=0; i < cmd.size(); i++) {
if (i > 0) {
args.push_back(cmd[i]);
}
}
}
std::string ProcessInfo::getEnv(std::string key)
{
return process.getEnv(key);
}
std::vector<std::string> ProcessInfo::getCmdLine()
{
return cmdLine;
}
std::vector<std::string> ProcessInfo::getArgs()
{
return args;
}
int ProcessInfo::getPid()
{
return process.getPid();
}
int ProcessInfo::getPpid()
{
return process.getPpid();
}
std::string ProcessInfo::getExe()
{
return exe;
}
std::string ProcessInfo::getOneCommandLine()
{
std::string cmdline = getJoinedExeArgs();
return "sh -c 'cd " + cwd + "; exec " + cmdline + ";'";
}
std::string ProcessInfo::getShellScriptLines()
{
std::string cmdline = getJoinedExeArgs();
return "#!/bin/sh\n cd " + cwd + "\n exec " + cmdline + "\n";
}
std::string ProcessInfo::getJoinedExeArgs()
{
std::string ret = "\"" + exe + "\"";
for (auto arg : args) {
ret += " \"" + arg + "\"";
}
ret += " $@";
return ret;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESSINFO_H
#define PROCESSINFO_H
#include "process.h"
#include <string>
#include <vector>
// 进程信息
class ProcessInfo
{
public:
ProcessInfo(int pid);
ProcessInfo(std::vector<std::string> &cmd);
std::string getEnv(std::string key);
std::vector<std::string> getCmdLine();
std::vector<std::string> getArgs();
int getPid();
int getPpid();
std::string getExe();
std::string getOneCommandLine();
std::string getShellScriptLines();
private:
std::string getJoinedExeArgs();
std::vector<std::string> cmdLine;
std::vector<std::string> args;
std::string exe;
std::string cwd;
bool hasPid;
Process process;
};
#endif // PROCESSINFO_H

View File

@ -0,0 +1,127 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "waylandmanager.h"
#include "dock.h"
#include "xcbutils.h"
#define XCB XCBUtils::instance()
WaylandManager::WaylandManager(Dock *_dock, QObject *parent)
: QObject(parent)
, dock(_dock)
, mutex(QMutex(QMutex::NonRecursive))
{
}
// 注册窗口
void WaylandManager::registerWindow(const QString &objPath)
{
qInfo() << "registerWindow: " << objPath;
if (findWindowByObjPath(objPath))
return;
PlasmaWindow *plasmaWindow = dock->createPlasmaWindow(objPath);
if (!plasmaWindow) {
qWarning() << "registerWindowWayland: createPlasmaWindow failed";
return;
}
QString appId = plasmaWindow->AppId();
QStringList list {"dde-dock", "dde-launcher", "dde-clipboard", "dde-osd", "dde-polkit-agent", "dde-simple-egl", "dmcs"};
if (list.indexOf(appId))
return;
XWindow winId = XCB->allocId(); // XCB中未发现释放XID接口
XWindow realId = plasmaWindow->WindowId();
if (!realId)
winId = realId;
WindowInfoK *winInfo = new WindowInfoK(plasmaWindow, winId);
dock->listenKWindowSignals(winInfo);
insertWindow(objPath, winInfo);
dock->attachOrDetachWindow(winInfo);
if (realId) {
windowInfoMap[realId] = winInfo;
}
}
// 取消注册窗口
void WaylandManager::unRegisterWindow(const QString &objPath)
{
qInfo() << "unRegisterWindow: " << objPath;
WindowInfoK *winInfo = findWindowByObjPath(objPath);
if (!winInfo)
return;
dock->removePlasmaWindowHandler(winInfo->getPlasmaWindow());
dock->detachWindow(winInfo);
deleteWindow(objPath);
}
WindowInfoK *WaylandManager::handleActiveWindowChangedK(uint activeWin)
{
WindowInfoK *winInfo = nullptr;
QMutexLocker locker(&mutex);
for (auto iter = kWinInfos.begin(); iter != kWinInfos.end(); iter++) {
if (iter.value()->getInnerId() == activeWin) {
winInfo = iter.value();
break;
}
}
return winInfo;
}
WindowInfoK *WaylandManager::findWindowByXid(XWindow xid)
{
WindowInfoK *winInfo = nullptr;
for (auto iter = kWinInfos.begin(); iter != kWinInfos.end(); iter++) {
if (iter.value()->getXid() == xid) {
winInfo = iter.value();
break;
}
}
return winInfo;
}
WindowInfoK *WaylandManager::findWindowByObjPath(QString objPath)
{
if (kWinInfos.find(objPath) == kWinInfos.end())
return nullptr;
return kWinInfos[objPath];
}
void WaylandManager::insertWindow(QString objPath, WindowInfoK *windowInfo)
{
QMutexLocker locker(&mutex);
kWinInfos[objPath] = windowInfo;
}
void WaylandManager::deleteWindow(QString objPath)
{
kWinInfos.remove(objPath);
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WAYLANDMANAGER_H
#define WAYLANDMANAGER_H
#include "windowinfok.h"
#include <QObject>
#include <QMap>
#include <QMutex>
class Dock;
// 管理wayland窗口
class WaylandManager : public QObject
{
Q_OBJECT
public:
explicit WaylandManager(Dock *_dock, QObject *parent = nullptr);
void registerWindow(const QString &objPath);
void unRegisterWindow(const QString &objPath);
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
WindowInfoK *findWindowByXid(XWindow xid);
WindowInfoK *findWindowByObjPath(QString objPath);
void insertWindow(QString objPath, WindowInfoK *windowInfo);
void deleteWindow(QString objPath);
private:
Dock *dock;
QMap<QString, WindowInfoK *> kWinInfos; // dbusObjectPath -> kwayland window Info
QMap<XWindow, WindowInfoK *> windowInfoMap;
QMutex mutex;
};
#endif // WAYLANDMANAGER_H

View File

@ -0,0 +1,545 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "windowidentify.h"
#include "common.h"
#include "appinfo.h"
#include "dock.h"
#include "processinfo.h"
#include "dstring.h"
#include "basedir.h"
#include "dfile.h"
#include "xcbutils.h"
#include <QDebug>
#include <QThread>
#define XCB XCBUtils::instance()
WindowPatterns WindowIdentify::patterns;
static QMap<QString, QString> crxAppIdMap = {
{"crx_onfalgmmmaighfmjgegnamdjmhpjpgpi", "apps.com.aiqiyi"},
{"crx_gfhkopakpiiaeocgofdpcpjpdiglpkjl", "apps.cn.kugou.hd"},
{"crx_gaoopbnflngfkoobibfgbhobdeiipcgh", "apps.cn.kuwo.kwmusic"},
{"crx_jajaphleehpmpblokgighfjneejapnok", "apps.com.evernote"},
{"crx_ebhffdbfjilfhahiinoijchmlceailfn", "apps.com.letv"},
{"crx_almpoflgiciaanepplakjdkiaijmklld", "apps.com.tongyong.xxbox"},
{"crx_heaphplipeblmpflpdcedfllmbehonfo", "apps.com.peashooter"},
{"crx_dbngidmdhcooejaggjiochbafiaefndn", "apps.com.rovio.angrybirdsseasons"},
{"crx_chfeacahlaknlmjhiagghobhkollfhip", "apps.com.sina.weibo"},
{"crx_cpbmecbkmjjfemjiekledmejoakfkpec", "apps.com.openapp"},
{"crx_lalomppgkdieklbppclocckjpibnlpjc", "apps.com.baidutieba"},
{"crx_gejbkhjjmicgnhcdpgpggboldigfhgli", "apps.com.zhuishushenqi"},
{"crx_gglenfcpioacendmikabbkecnfpanegk", "apps.com.duokan"},
{"crx_nkmmgdfgabhefacpfdabadjfnpffhpio", "apps.com.zhihu.daily"},
{"crx_ajkogonhhcighbinfgcgnjiadodpdicb", "apps.com.netease.newsreader"},
{"crx_hgggjnaaklhemplabjhgpodlcnndhppo", "apps.com.baidu.music.pad"},
{"crx_ebmgfebnlgilhandilnbmgadajhkkmob", "apps.cn.ibuka"},
{"crx_nolebplcbgieabkblgiaacdpgehlopag", "apps.com.tianqitong"},
{"crx_maghncnmccfbmkekccpmkjjfcmdnnlip", "apps.com.youjoy.strugglelandlord"},
{"crx_heliimhfjgfabpgfecgdhackhelmocic", "apps.cn.emoney"},
{"crx_jkgmneeafmgjillhgmjbaipnakfiidpm", "apps.com.instagram"},
{"crx_cdbkhmfmikobpndfhiphdbkjklbmnakg", "apps.com.easymindmap"},
{"crx_djflcciklfljleibeinjmjdnmenkciab", "apps.com.lgj.thunderbattle"},
{"crx_ffdgbolnndgeflkapnmoefhjhkeilfff", "apps.com.qianlong"},
{"crx_fmpniepgiofckbfgahajldgoelogdoap", "apps.com.windhd"},
{"crx_dokjmallmkihbgefmladclcdcinjlnpj", "apps.com.youdao.hanyu"},
{"crx_dicimeimfmbfcklbjdpnlmjgegcfilhm", "apps.com.ibookstar"},
{"crx_cokkcjnpjfffianjbpjbcgjefningkjm", "apps.com.yidianzixun"},
{"crx_ehflkacdpmeehailmcknlnkmjalehdah", "apps.com.xplane"},
{"crx_iedokjbbjejfinokgifgecmboncmkbhb", "apps.com.wedevote"},
{"crx_eaefcagiihjpndconigdpdmcbpcamaok", "apps.com.tongwei.blockbreaker"},
{"crx_mkjjfibpccammnliaalefmlekiiikikj", "apps.com.dayima"},
{"crx_gflkpppiigdigkemnjlonilmglokliol", "apps.com.cookpad"},
{"crx_jfhpkchgedddadekfeganigbenbfaohe", "apps.com.issuu"},
{"crx_ggkmfnbkldhmkehabgcbnmlccfbnoldo", "apps.bible.cbol"},
{"crx_phlhkholfcljapmcidanddmhpcphlfng", "apps.com.kanjian.radio"},
{"crx_bjgfcighhaahojkibojkdmpdihhcehfm", "apps.de.danoeh.antennapod"},
{"crx_kldipknjommdfkifomkmcpbcnpmcnbfi", "apps.com.asoftmurmur"},
{"crx_jfhlegimcipljdcionjbipealofoncmd", "apps.com.tencentnews"},
{"crx_aikgmfkpmmclmpooohngmcdimgcocoaj", "apps.com.tonghuashun"},
{"crx_ifimglalpdeoaffjmmihoofapmpflkad", "apps.com.letv.lecloud.disk"},
{"crx_pllcekmbablpiogkinogefpdjkmgicbp", "apps.com.hwadzanebook"},
{"crx_ohcknkkbjmgdfcejpbmhjbohnepcagkc", "apps.com.douban.radio"},
};
WindowIdentify::WindowIdentify(Dock *_dock, QObject *parent)
: QObject(parent)
, dock(_dock)
{
identifyWindowFuns["Android"] = identifyWindowAndroid;
identifyWindowFuns["PidEnv"] = identifyWindowByPidEnv;
identifyWindowFuns["CmdlineTurboBooster"] = identifyWindowByCmdlineTurboBooster;
identifyWindowFuns["Cmdline-XWalk"] = identifyWindowByCmdlineXWalk;
identifyWindowFuns["FlatpakAppID"] = identifyWindowByFlatpakAppID;
identifyWindowFuns["CrxId"] = identifyWindowByCrxId;
identifyWindowFuns["Rule"] = identifyWindowByRule;
identifyWindowFuns["Bamf"] = identifyWindowByBamf;
identifyWindowFuns["Pid"] = identifyWindowByPid;
identifyWindowFuns["Scratch"] = identifyWindowByScratch;
identifyWindowFuns["GtkAppId"] = identifyWindowByGtkAppId;
identifyWindowFuns["WmClass"] = identifyWindowByWmClass;
}
AppInfo *WindowIdentify::identifyWindow(WindowInfoBase *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
//qInfo() << "identifyWindow: window id " << winInfo->getXid() << " innerId " << winInfo->getInnerId();
if (winInfo->getWindowType() == "X11")
ret = identifyWindowX11(static_cast<WindowInfoX *>(winInfo), innerId);
else if (winInfo->getWindowType() == "Wayland")
ret = identifyWindowWayland(static_cast<WindowInfoK *>(winInfo), innerId);
return ret;
}
AppInfo *WindowIdentify::identifyWindowX11(WindowInfoX *winInfo, QString &innerId)
{
AppInfo *appInfo = nullptr;
if (winInfo->getInnerId() == "") {
qInfo() << "identify WindowX11: innerId is empty";
return appInfo;
}
for (auto iter = identifyWindowFuns.begin(); iter != identifyWindowFuns.end(); iter++) {
QString name = iter.key();
IdentifyFunc func = iter.value();
qInfo() << "identifyWindowX11: try " << name;
appInfo = func(dock, winInfo, innerId);
if (appInfo) { // TODO: if name == "Pid", appInfo may by nullptr
// 识别成功
qInfo() << "identify Window by " << name << " innerId " << appInfo->getInnerId() << " success!";
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
if (fixedAppInfo) {
delete appInfo;
appInfo = fixedAppInfo;
appInfo->setIdentifyMethod(name + "+FixAutostart");
innerId = appInfo->getInnerId();
} else {
appInfo->setIdentifyMethod(name);
}
return appInfo;
}
}
qInfo() << "identifyWindowX11: failed";
return appInfo;
}
AppInfo *WindowIdentify::identifyWindowWayland(WindowInfoK *winInfo, QString &innerId)
{
// TODO: 对桌面调起的文管应用做规避处理需要在此处添加因为初始化时appId和title为空
if (winInfo->getAppId() == "dde-desktop" && dock->shouldShowOnDock(winInfo)) {
winInfo->setAppId("dde-file-manager");
}
QString appId = winInfo->getAppId();
if (appId.isEmpty()) {
QString title = winInfo->getTitle();
// TODO: 对于appId为空的情况使用title过滤此项修改针对浏览器下载窗口
}
// 先使用appId获取appInfo,如果不能成功获取再使用GIO_LAUNCHED_DESKTOP_FILE环境变量获取
AppInfo *appInfo = new AppInfo(appId);
if (!appInfo->isValidApp() && winInfo->getProcess()) {
ProcessInfo *process = winInfo->getProcess();
std::string desktopFilePath = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
if (DString::endWith(desktopFilePath, ".desktop")) {
appInfo = new AppInfo(desktopFilePath.c_str());
}
}
// autoStart
if (appInfo->isValidApp()) {
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
if (fixedAppInfo) {
delete appInfo;
appInfo = fixedAppInfo;
appInfo->setIdentifyMethod("FixAutostart");
}
} else {
// bamf
XWindow winId = winInfo->getXid();
QString desktop = dock->getDesktopFromWindowByBamf(winId);
if (!desktop.isEmpty()) {
appInfo = new AppInfo(desktop);
}
WMClass wmClass = XCB->getWMClass(winId);
if (wmClass.instanceName.size() > 0) {
QString instance(wmClass.instanceName.c_str());
appInfo = new AppInfo("org.deepin.flatdeb." + instance);
if (appInfo)
return appInfo;
appInfo = new AppInfo(instance);
if (appInfo)
return appInfo;
if (wmClass.className.size() > 0) {
appInfo = new AppInfo(wmClass.className.c_str());
if (appInfo)
return appInfo;
}
}
}
if (appInfo)
innerId = appInfo->getInnerId();
return appInfo;
}
AppInfo *WindowIdentify::identifyWindowAndroid(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
int32_t androidId = getAndroidUengineId(winInfo->getXid());
QString androidName = getAndroidUengineName(winInfo->getXid());
if (androidId != -1 && androidName != "") {
QString desktopPath = "/usr/share/applications/uengine." + androidName + ".desktop";
DesktopInfo desktopInfo(desktopPath.toStdString());
if (!desktopInfo.isValidDesktop()) {
qInfo() << "identifyWindowAndroid: not exist DesktopFile " << desktopPath;
return ret;
}
ret = new AppInfo(desktopInfo);
ret->setIdentifyMethod("Android");
innerId = ret->getInnerId();
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByPidEnv(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
int pid = winInfo->getPid();
auto process = winInfo->getProcess();
qInfo() << "identifyWindowByPidEnv: pid=" << pid << " WindowId=" << winInfo->getXid();
if (pid != 0 && process) {
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE").c_str();
QString launchedDesktopFilePidStr = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE_PID").c_str();
int launchedDesktopFilePid = launchedDesktopFilePidStr.toInt();
qInfo() << "launchedDesktopFilePid=" << launchedDesktopFilePid << " launchedDesktopFile=" << launchedDesktopFile;
// 以下 2 种情况下,才能信任环境变量 GIO_LAUNCHED_DESKTOP_FILE。
// 1. 当窗口 pid 和 launchedDesktopFilePid 相同时;
// 2. 当窗口的进程的父进程 id即 ppid和 launchedDesktopFilePid 相同,
// 并且该父进程是 sh 或 bash 时。
bool needTry = false;
if (pid == launchedDesktopFilePid) {
needTry = true;
} else if (process->getPpid() && process->getPpid() == launchedDesktopFilePid) {
Process parentProcess(launchedDesktopFilePid);
auto parentCmdLine = parentProcess.getCmdLine();
if (parentCmdLine.size() > 0) {
qInfo() << "ppid equal " << "parentCmdLine[0]:" << parentCmdLine[0].c_str();
QString cmd0 = parentCmdLine[0].c_str();
int pos = cmd0.lastIndexOf('/');
if (pos > 0)
cmd0 = cmd0.remove(0, pos + 1);
if (cmd0 == "sh" || cmd0 == "bash")
needTry = true;
}
}
if (needTry) {
ret = new AppInfo(launchedDesktopFile);
innerId = ret->getInnerId();
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByCmdlineTurboBooster(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
int pid = winInfo->getPid();
ProcessInfo *process = winInfo->getProcess();
if (pid != 0 && process) {
auto cmdline = process->getCmdLine();
if (cmdline.size() > 0) {
QString desktopFile;
if (DString::endWith(cmdline[0], ".desktop")) {
desktopFile = cmdline[0].c_str();
} else if (QString(cmdline[0].c_str()).contains("/applications/")) {
QFileInfo fileInfo(cmdline[0].c_str());
QString path = fileInfo.path();
QString base = fileInfo.baseName();
QDir dir(path);
QStringList files = dir.entryList(QDir::Files);
for (auto f : files) {
if (f.contains(path + "/" + base + ".desktop")) {
desktopFile = f;
break;
}
}
qInfo() << "identifyWindowByCmdlineTurboBooster: desktopFile is " << desktopFile;
if (!desktopFile.isEmpty()) {
ret = new AppInfo(desktopFile);
innerId = ret->getInnerId();
}
}
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByCmdlineXWalk(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
qInfo() << "identifyWindowByCmdlineXWalk: windowId=" << winInfo->getXid();
AppInfo *ret = nullptr;
do {
auto process = winInfo->getProcess();
if (!process || !winInfo->getPid())
break;
QString exe = process->getExe().c_str();
QFileInfo file(exe);
QString exeBase = file.baseName();
auto args = process->getArgs();
if (exe != "xwalk" || args.size() == 0)
break;
QString lastArg = args[args.size() - 1].c_str();
file.setFile(lastArg);
if (file.baseName() == "manifest.json") {
auto strs = lastArg.split("/");
if (strs.size() > 3 && strs[strs.size() - 2].size() > 0) { // appId为 strs倒数第二个字符串
ret = new AppInfo(strs[strs.size() - 2]);
innerId = ret->getInnerId();
break;
}
}
qInfo() << "identifyWindowByCmdlineXWalk: failed";
} while (0);
return ret;
}
AppInfo *WindowIdentify::identifyWindowByFlatpakAppID(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
QString flatpak = winInfo->getFlatpakAppId();
qInfo() << "identifyWindowByFlatpakAppID: flatpak:" << flatpak;
if (flatpak.startsWith("app/")) {
auto parts = flatpak.split("/");
if (parts.size() > 0) {
QString appId = parts[1];
ret = new AppInfo(appId);
innerId = ret->getInnerId();
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByCrxId(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
WMClass wmClass = XCB->getWMClass(winInfo->getXid());
QString className, instanceName;
className.append(wmClass.className.c_str());
instanceName.append(wmClass.instanceName.c_str());
if (className.toLower() == "chromium-browser" && instanceName.toLower().startsWith("crx_")) {
if (crxAppIdMap.find(instanceName.toLower()) != crxAppIdMap.end()) {
QString appId = crxAppIdMap[instanceName.toLower()];
qInfo() << "identifyWindowByCrxId: appId " << appId;
ret = new AppInfo(appId);
innerId = ret->getInnerId();
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByRule(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
qInfo() << "identifyWindowByRule: windowId=" << winInfo->getXid();
AppInfo *ret = nullptr;
QString matchStr = patterns.match(winInfo);
if (matchStr.isEmpty())
return ret;
if (matchStr.size() > 4 && matchStr.startsWith("id=")) {
matchStr.remove(0, 3);
ret = new AppInfo(matchStr);
} else if (matchStr == "env") {
auto process = winInfo->getProcess();
if (process) {
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE").c_str();
if (!launchedDesktopFile.isEmpty())
ret = new AppInfo(launchedDesktopFile);
}
} else {
qInfo() << "patterns match bad result";
}
if (ret)
innerId = ret->getInnerId();
return ret;
}
AppInfo *WindowIdentify::identifyWindowByBamf(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
XWindow xid = winInfo->getXid();
qInfo() << "identifyWindowByBamf: windowId=" << xid;
QString desktopFile;
// 重试 bamf 识别yozo office 的窗口经常要第二次时才能识别到。
for (int i=0; i<3; i++) {
desktopFile = _dock->getDesktopFromWindowByBamf(xid);
if (!desktopFile.isEmpty())
break;
QThread::msleep(100);
}
if (!desktopFile.isEmpty()) {
ret = new AppInfo(desktopFile);
innerId = ret->getInnerId();
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByPid(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
if (winInfo->getPid() > 10) {
auto entry = _dock->getEntryByWindowId(winInfo->getPid());
if (entry) {
ret = entry->getApp();
innerId = ret->getInnerId();
}
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByScratch(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
QString desktopFile = scratchDir + winInfo->getInnerId() + ".desktop";
qInfo() << "identifyWindowByScratch: xid " << winInfo->getXid() << " desktopFile" << desktopFile;
QFile file(desktopFile);
if (file.exists()) {
ret = new AppInfo(desktopFile);
innerId = ret->getInnerId();
}
return ret;
}
AppInfo *WindowIdentify::identifyWindowByGtkAppId(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
QString gtkAppId = winInfo->getGtkAppId();
if (!gtkAppId.isEmpty()) {
ret = new AppInfo(gtkAppId);
innerId = ret->getInnerId();
}
qInfo() << "identifyWindowByGtkAppId: gtkAppId:" << gtkAppId;
return ret;
}
AppInfo *WindowIdentify::identifyWindowByWmClass(Dock *_dock, WindowInfoX *winInfo, QString &innerId)
{
AppInfo *ret = nullptr;
WMClass wmClass = winInfo->getWMClass();
do {
if (wmClass.instanceName.size() > 0) {
// example:
// WM_CLASS(STRING) = "Brackets", "Brackets"
// wm class instance is Brackets
// try app id org.deepin.flatdeb.brackets
ret = new AppInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower());
if (ret)
break;
ret = new AppInfo(wmClass.instanceName.c_str());
if (ret)
break;
}
if (wmClass.className.size() > 0) {
ret = new AppInfo(wmClass.className.c_str());
if (ret)
break;
}
} while (0);
if (ret)
innerId = ret->getInnerId();
return ret;
}
AppInfo *WindowIdentify::fixAutostartAppInfo(QString fileName)
{
QFileInfo file(fileName);
QString filePath = file.absolutePath();
bool isAutoStart = false;
for (auto &dir : BaseDir::autoStartDirs()) {
if (QString(dir.c_str()).contains(filePath)) {
isAutoStart = true;
break;
}
}
return isAutoStart ? new AppInfo(file.baseName()) : nullptr;
}
int32_t WindowIdentify::getAndroidUengineId(XWindow winId)
{
// TODO 获取AndroidUengineId
return 0;
}
QString WindowIdentify::getAndroidUengineName(XWindow winId)
{
// TODO 获取AndroidUengineName
return "";
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WINDOWIDENTIFY_H
#define WINDOWIDENTIFY_H
#include "windowpatterns.h"
#include "windowinfok.h"
#include "windowinfox.h"
#include <QObject>
#include <QVector>
#include <QMap>
class AppInfo;
class Dock;
typedef AppInfo *(*IdentifyFunc)(Dock *, WindowInfoX*, QString &innerId);
// 应用窗口识别类
class WindowIdentify : public QObject
{
Q_OBJECT
public:
explicit WindowIdentify(Dock *_dock, QObject *parent = nullptr);
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
AppInfo *identifyWindowX11(WindowInfoX *winInfo, QString &innerId);
AppInfo *identifyWindowWayland(WindowInfoK *winInfo, QString &innerId);
static AppInfo *identifyWindowAndroid(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByPidEnv(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCmdlineTurboBooster(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCmdlineXWalk(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByFlatpakAppID(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByCrxId(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByRule(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByBamf(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByPid(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByScratch(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByGtkAppId(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
static AppInfo *identifyWindowByWmClass(Dock *_dock, WindowInfoX *winInfo, QString &innerId);
public Q_SLOTS:
private:
AppInfo *fixAutostartAppInfo(QString fileName);
static int32_t getAndroidUengineId(XWindow winId);
static QString getAndroidUengineName(XWindow winId);
static WindowPatterns patterns; // 根据rule识别
Dock *dock;
QMap<QString, IdentifyFunc> identifyWindowFuns;
};
#endif // IDENTIFYWINDOW_H

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WINDOWINFOBASE_H
#define WINDOWINFOBASE_H
#include "xcbutils.h"
#include <QString>
#include <QVector>
class Entry;
class AppInfo;
class ProcessInfo;
class WindowInfoBase
{
public:
WindowInfoBase() : entry(nullptr), app(nullptr), processInfo(nullptr) {}
virtual ~WindowInfoBase() {}
virtual bool shouldSkip() = 0;
virtual QString getIcon() = 0;
virtual QString getTitle() = 0;
virtual bool isDemandingAttention() = 0;
virtual void close(uint32_t timestamp) = 0;
virtual void activate() = 0;
virtual void minimize() = 0;
virtual bool isMinimized() = 0;
virtual int64_t getCreatedTime() = 0;
virtual QString getWindowType() = 0;
virtual QString getDisplayName() = 0;
virtual bool allowClose() = 0;
virtual void update() = 0;
virtual void killClient() = 0;
XWindow getXid() {return xid;}
void setEntry(Entry *value) {entry = value;}
Entry *getEntry() {return entry;}
QString getEntryInnerId() {return entryInnerId;}
QString getInnerId() {return innerId;}
void setEntryInnerId(QString value) {entryInnerId = value;}
AppInfo *getAppInfo() {return app;}
void setAppInfo(AppInfo *value) {app = value;}
int getPid() {return pid;}
ProcessInfo *getProcess() {return processInfo;}
bool containAtom(QVector<XCBAtom> supports, XCBAtom ty) {return supports.indexOf(ty) != -1;}
protected:
XWindow xid;
QString title;
QString icon;
int pid;
QString entryInnerId;
QString innerId;
Entry *entry;
AppInfo *app;
ProcessInfo *processInfo;
int64_t createdTime;
};
#endif // WINDOWINFOBASE_H

View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "windowinfok.h"
#include "entry.h"
#include "processinfo.h"
#include "appinfo.h"
#include <chrono>
WindowInfoK::WindowInfoK(PlasmaWindow *window, XWindow _xid)
: WindowInfoBase ()
, updateCalled(false)
, internalId(0)
, demaningAttention(false)
, closeable(true)
, minimized(true)
, plasmaWindow(window)
{
xid = _xid;
createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
}
WindowInfoK::~WindowInfoK()
{
}
bool WindowInfoK::shouldSkip()
{
if (!updateCalled) {
update();
updateCalled = true;
}
bool skip = plasmaWindow->SkipTaskbar();
// 添加窗口能否最小化判断, 如果窗口不能最小化则隐藏任务栏图标
bool canMinimize = false;
canMinimize = plasmaWindow->IsMinimizeable();
if (!canMinimize)
skip = true;
if (skip) {
// 白名单, 过滤类似“欢迎应用”, 没有最小化窗口但是需要在任务栏显示图标
QStringList list { "dde-introduction"};
if (list.indexOf(appId) != -1)
skip = false;
}
return skip;
}
QString WindowInfoK::getIcon()
{
return icon;
}
QString WindowInfoK::getTitle()
{
return title;
}
bool WindowInfoK::isDemandingAttention()
{
return demaningAttention;
}
bool WindowInfoK::allowClose()
{
return closeable;
}
void WindowInfoK::close(uint32_t timestamp)
{
plasmaWindow->RequestClose();
}
QString WindowInfoK::getAppId()
{
return appId;
}
void WindowInfoK::setAppId(QString _appId)
{
appId = _appId;
}
void WindowInfoK::activate()
{
plasmaWindow->RequestActivate();
}
void WindowInfoK::minimize()
{
plasmaWindow->RequestToggleMinimized();
}
bool WindowInfoK::isMinimized()
{
return minimized;
}
bool WindowInfoK::changeXid(XWindow _xid)
{
xid = _xid;
return true;
}
PlasmaWindow *WindowInfoK::getPlasmaWindow()
{
return plasmaWindow;
}
bool WindowInfoK::updateGeometry()
{
Rect rect = plasmaWindow->Geometry();
if (geometry == rect)
return false;
geometry = rect;
return true;
}
void WindowInfoK::updateTitle()
{
title = plasmaWindow->Title();
}
void WindowInfoK::updateDemandingAttention()
{
demaningAttention = plasmaWindow->IsDemandingAttention();
}
void WindowInfoK::updateIcon()
{
icon = plasmaWindow->Icon();
}
void WindowInfoK::updateAppId()
{
appId = plasmaWindow->AppId();
}
void WindowInfoK::updateInternalId()
{
internalId = plasmaWindow->InternalId();
}
void WindowInfoK::updateCloseable()
{
closeable = plasmaWindow->IsCloseable();
}
void WindowInfoK::updateProcessInfo()
{
pid = plasmaWindow->Pid();
processInfo = new ProcessInfo(pid);
}
int64_t WindowInfoK::getCreatedTime()
{
return createdTime;
}
// 主要是为兼容X11
QString WindowInfoK::getDisplayName()
{
return "";
}
QString WindowInfoK::getWindowType()
{
return "Wayland";
}
void WindowInfoK::update()
{
updateInternalId();
updateAppId();
updateIcon();
updateTitle();
updateGeometry();
updateDemandingAttention();
updateCloseable();
updateProcessInfo();
}
void WindowInfoK::killClient()
{
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WINDOWINFOK_H
#define WINDOWINFOK_H
#include "windowinfobase.h"
#include "dbusplasmawindow.h"
#include <QString>
class Entry;
class ProcessInfo;
// wayland下窗口信息
class WindowInfoK: public WindowInfoBase
{
public:
WindowInfoK(PlasmaWindow *window, XWindow _xid = 0);
virtual ~WindowInfoK();
virtual bool shouldSkip();
virtual QString getIcon();
virtual QString getTitle();
virtual bool isDemandingAttention();
virtual bool allowClose();
virtual void close(uint32_t timestamp);
virtual void activate();
virtual void minimize();
virtual bool isMinimized();
virtual int64_t getCreatedTime();
virtual QString getDisplayName();
virtual QString getWindowType();
virtual void update();
virtual void killClient();
QString getAppId();
void setAppId(QString _appId);
bool changeXid(XWindow _xid);
PlasmaWindow *getPlasmaWindow();
bool updateGeometry();
void updateTitle();
void updateDemandingAttention();
void updateIcon();
void updateAppId();
void updateInternalId();
void updateCloseable();
void updateProcessInfo();
private:
bool updateCalled;
QString appId;
uint32_t internalId;
bool demaningAttention;
bool closeable;
bool minimized;
PlasmaWindow *plasmaWindow;
Rect geometry;
};
#endif // WINDOWINFOK_H

View File

@ -0,0 +1,447 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "windowinfox.h"
#include "appinfo.h"
#include "xcbutils.h"
#include "dstring.h"
#include "common.h"
#include "processinfo.h"
#include <QDebug>
#include <QCryptographicHash>
#define XCB XCBUtils::instance()
WindowInfoX::WindowInfoX(XWindow _xid)
: WindowInfoBase ()
, x(0)
, y(0)
, width(0)
, height(0)
, hasWMTransientFor(false)
, hasXEmbedInfo(false)
, updateCalled(false)
{
xid = _xid;
createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
}
WindowInfoX::~WindowInfoX()
{
}
bool WindowInfoX::shouldSkip()
{
qInfo() << "window " << xid << " shouldSkip?";
if (!updateCalled) {
update();
updateCalled = true;
}
if (hasWmStateSkipTaskBar() || isValidModal() || shouldSkipWithWMClass())
return true;
for (auto atom : wmWindowType) {
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DIALOG") && !isActionMinimizeAllowed())
return true;
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_UTILITY")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_COMBO")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DESKTOP")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DND")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DOCK")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_MENU")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_POPUP_MENU")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_SPLASH")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLBAR")
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"))
return true;
}
return false;
}
QString WindowInfoX::getIcon()
{
if (icon.isEmpty())
icon = getIconFromWindow();
return icon;
}
void WindowInfoX::activate()
{
XCB->setActiveWindow(xid);
}
void WindowInfoX::minimize()
{
XCB->minimizeWindow(xid);
}
bool WindowInfoX::isMinimized()
{
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_HIDDEN"));
}
int64_t WindowInfoX::getCreatedTime()
{
return createdTime;
}
QString WindowInfoX::getWindowType()
{
return "X11";
}
bool WindowInfoX::allowClose()
{
// 允许关闭的条件:
// 1. 不设置 functions 字段即MotifHintFunctions 标志位;
// 2. 或者设置了 functions 字段并且 设置了 MotifFunctionAll 标志位;
// 3. 或者设置了 functions 字段并且 设置了 MotifFunctionClose 标志位。
// 相关定义在 motif-2.3.8/lib/Xm/MwmUtil.h 。
if ((motifWmHints.flags & MotifHintFunctions) == 0
|| (motifWmHints.functions & MotifFunctionAll) != 0
|| (motifWmHints.functions & MotifFunctionClose) != 0)
return true;
for (auto action : wmAllowedActions) {
if (action == XCB->getAtom("_NET_WM_ACTION_CLOSE")) {
return true;
}
}
return false;
}
QString WindowInfoX::getDisplayName()
{
XWindow winId = xid;
//QString role = wmRole;
QString className(wmClass.className.c_str());
QString instance;
if (wmClass.instanceName.size() > 0) {
int pos = QString(wmClass.instanceName.c_str()).lastIndexOf('/');
if (pos != -1)
instance.remove(0, pos + 1);
}
qInfo() << "getDisplayName class:" << className << " ,instance:" << instance;
//if (!role.isEmpty() && !className.isEmpty())
// return className + " " + role;
if (!className.isEmpty())
return className;
if (!instance.isEmpty())
return instance;
QString _wmName = wmName;
if (!_wmName.isEmpty()) {
int pos = _wmName.lastIndexOf('-');
if (pos != -1 && !_wmName.startsWith("-")) {
_wmName.truncate(pos);
return _wmName;
}
}
if (processInfo) {
QString exe {processInfo->getEnv("exe").c_str()};
if (!exe.isEmpty())
return exe;
}
return QString("window:%1").arg(winId);
}
void WindowInfoX::killClient()
{
XCB->killClientChecked(xid);
}
QString WindowInfoX::getGtkAppId()
{
return gtkAppId;
}
QString WindowInfoX::getFlatpakAppId()
{
return flatpakAppId;
}
QString WindowInfoX::getWmRole()
{
return wmRole;
}
WMClass WindowInfoX::getWMClass()
{
return wmClass;
}
QString WindowInfoX::getWMName()
{
return wmName;
}
ConfigureEvent *WindowInfoX::getLastConfigureEvent()
{
return lastConfigureNotifyEvent;
}
void WindowInfoX::setLastConfigureEvent(ConfigureEvent *event)
{
lastConfigureNotifyEvent = event;
}
bool WindowInfoX::isGeometryChanged(int _x, int _y, int _width, int _height)
{
return !(_x == x && _y == y && _width == width && _height == height);
}
void WindowInfoX::setGtkAppId(QString _gtkAppId)
{
gtkAppId = _gtkAppId;
}
void WindowInfoX::updateMotifWmHints()
{
// get from XCB
motifWmHints = XCB->getWindowMotifWMHints(xid);
}
// XEmbed info
// 一般 tray icon 会带有 _XEMBED_INFO 属性
void WindowInfoX::updateHasXEmbedInfo()
{
hasXEmbedInfo = XCB->hasXEmbedInfo(xid);
}
QString WindowInfoX::genInnerId(WindowInfoX *winInfo)
{
XWindow winId = winInfo->getXid();
QString wmClassName, wmInstance;
WMClass wmClass = winInfo->getWMClass();
if (wmClass.className.size() > 0)
wmClassName = wmClass.className.c_str();
if (wmClass.instanceName.size() > 0) {
QString instanceName(wmClass.instanceName.c_str());
instanceName.remove(0, instanceName.lastIndexOf('/') + 1);
wmInstance = instanceName;
}
QString exe, args;
if (winInfo->getProcess()) {
exe = winInfo->getProcess()->getExe().c_str();
for (auto arg : winInfo->getProcess()->getArgs()) {
QString argStr(arg.c_str());
if (argStr.contains("/") || argStr == "." || argStr == "..") {
args += "%F ";
} else {
args += argStr + " ";
}
}
if (args.size() > 0)
args.remove(args.size() - 2, 1);
}
bool hasPid = winInfo->getPid() != 0;
QString str;
// NOTE: 不要使用 wmRole有些程序总会改变这个值比如 GVim
if (wmInstance.isEmpty() && wmClassName.isEmpty() && exe.isEmpty() && winInfo->getGtkAppId().isEmpty()) {
if (!winInfo->getWMName().isEmpty())
str = QString("wmName:%1").arg(winInfo->getWMName());
else
str = QString("windowId:%1").arg(winInfo->getXid());
} else {
str = QString("wmInstance:%1,wmClass:%2,exe:%3,args:%4,hasPid:%5,gtkAppId:%6").arg(wmInstance).arg(wmClassName).arg(exe).arg(args).arg(hasPid).arg(winInfo->getGtkAppId());
}
QByteArray encryText = QCryptographicHash::hash(str.toLatin1(), QCryptographicHash::Md5);
QString innerId = windowHashPrefix + encryText.toHex();
qInfo() << "genInnerId window " << winId << " innerId :" << innerId;
return innerId;
}
// 更新窗口类型
void WindowInfoX::updateWmWindowType()
{
wmWindowType.clear();
for (auto ty : XCB->getWMWindoType(xid)) {
wmWindowType.push_back(ty);
}
}
// 更新窗口许可动作
void WindowInfoX::updateWmAllowedActions()
{
wmAllowedActions.clear();
for (auto action : XCB->getWMAllowedActions(xid)) {
wmAllowedActions.push_back(action);
}
}
void WindowInfoX::updateWmState()
{
wmState.clear();
for (auto a : XCB->getWMState(xid)) {
wmState.push_back(a);
}
}
void WindowInfoX::updateWmClass()
{
wmClass = XCB->getWMClass(xid);
}
void WindowInfoX::updateWmName()
{
auto name = XCB->getWMName(xid);
if (!name.empty())
wmName = name.c_str();
title = getTitle();
}
void WindowInfoX::updateIcon()
{
icon = getIconFromWindow();
}
void WindowInfoX::updateHasWmTransientFor()
{
if (XCB->getWMTransientFor(xid) == 1)
hasWMTransientFor = true;
}
void WindowInfoX::update()
{
updateWmClass();
updateWmState();
updateWmWindowType();
updateWmAllowedActions();
updateHasWmTransientFor();
updateProcessInfo();
updateWmName();
innerId = genInnerId(this);
}
// TODO 从窗口中获取图标, 并设置best size be used in Entry
QString WindowInfoX::getIconFromWindow()
{
QString ret;
return ret;
}
bool WindowInfoX::isActionMinimizeAllowed()
{
return containAtom(wmAllowedActions, XCB->getAtom("_NET_WM_ACTION_MINIMIZE"));
}
bool WindowInfoX::hasWmStateDemandsAttention()
{
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_DEMANDS_ATTENTION"));
}
bool WindowInfoX::hasWmStateSkipTaskBar()
{
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_SKIP_TASKBAR"));
}
bool WindowInfoX::hasWmStateModal()
{
return containAtom(wmState, XCB->getAtom("_NET_WM_STATE_MODAL"));
}
bool WindowInfoX::isValidModal()
{
return hasWmStateModal() && hasWmStateModal();
}
// 通过WMClass判断是否需要隐藏此窗口
bool WindowInfoX::shouldSkipWithWMClass()
{
bool ret = false;
if (wmClass.instanceName == "explorer.exe" && wmClass.className == "Wine")
ret = true;
else if (wmClass.className == "dde-launcher")
ret = true;
return ret;
}
void WindowInfoX::updateProcessInfo()
{
XWindow winId = xid;
pid = XCB->getWMPid(winId);
if (processInfo)
delete processInfo;
processInfo = new ProcessInfo(pid);
if (!processInfo) {
// try WM_COMMAND
auto wmComand = XCB->getWMCommand(winId);
if (wmComand.size() > 0)
processInfo = new ProcessInfo(wmComand);
}
qInfo() << "updateProcessInfo: pid is " << pid;
}
bool WindowInfoX::getUpdateCalled()
{
return updateCalled;
}
void WindowInfoX::setInnerId(QString _innerId)
{
innerId = _innerId;
}
QString WindowInfoX::getTitle()
{
QString name = wmName;
if (name.isEmpty())
name = getDisplayName();
return name;
}
bool WindowInfoX::isDemandingAttention()
{
return hasWmStateDemandsAttention();
}
void WindowInfoX::close(uint32_t timestamp)
{
XCB->requestCloseWindow(xid, timestamp);
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WINDOWINFOX_H
#define WINDOWINFOX_H
#include "windowinfobase.h"
#include "xcbutils.h"
#include <QVector>
class AppInfo;
// X11下窗口信息 在明确X11环境下使用
class WindowInfoX: public WindowInfoBase
{
public:
WindowInfoX(XWindow _xid = 0);
virtual ~WindowInfoX();
virtual bool shouldSkip();
virtual QString getIcon();
virtual QString getTitle();
virtual bool isDemandingAttention();
virtual void close(uint32_t timestamp);
virtual void activate();
virtual void minimize();
virtual bool isMinimized();
virtual int64_t getCreatedTime();
virtual QString getDisplayName();
virtual QString getWindowType();
virtual bool allowClose();
virtual void update();
virtual void killClient();
QString genInnerId(WindowInfoX *winInfo);
QString getGtkAppId();
QString getFlatpakAppId();
QString getWmRole();
WMClass getWMClass();
QString getWMName();
void updateProcessInfo();
bool getUpdateCalled();
void setInnerId(QString _innerId);
ConfigureEvent *getLastConfigureEvent();
void setLastConfigureEvent(ConfigureEvent *event);
bool isGeometryChanged(int _x, int _y, int _width, int _height);
void setGtkAppId(QString _gtkAppId);
/************************更新XCB窗口属性*********************/
void updateWmWindowType();
void updateWmAllowedActions();
void updateWmState();
void updateWmClass();
void updateMotifWmHints();
void updateWmName();
void updateIcon();
void updateHasXEmbedInfo();
void updateHasWmTransientFor();
private:
QString getIconFromWindow();
bool isActionMinimizeAllowed();
bool hasWmStateDemandsAttention();
bool hasWmStateSkipTaskBar();
bool hasWmStateModal();
bool isValidModal();
bool shouldSkipWithWMClass();
int16_t x, y;
uint16_t width, height;
QVector<XCBAtom> wmState;
QVector<XCBAtom> wmWindowType;
QVector<XCBAtom> wmAllowedActions;
bool hasWMTransientFor;
WMClass wmClass;
QString wmName;
bool hasXEmbedInfo;
// 自定义atom属性
QString gtkAppId;
QString flatpakAppId;
QString wmRole;
MotifWMHints motifWmHints;
bool updateCalled;
ConfigureEvent *lastConfigureNotifyEvent;
};
#endif // WINDOWINFOX_H

View File

@ -0,0 +1,229 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "windowpatterns.h"
#include "common.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QVariant>
#include <QVariantMap>
#include <QDebug>
#include <dstring.h>
#include <QRegExp>
#include <QFile>
const int parsedFlagNegative = 0x001;
const int parsedFlagIgnoreCase = 0x010;
bool contains(QString key, QString value) {
return key.contains(value);
}
bool containsIgnoreCase(QString key, QString value) {
QString _key = key.toLower();
QString _value = value.toLower();
return _key.contains(_value);
}
bool equal(QString key, QString value) {
return key == value;
}
bool equalIgnoreCase(QString key, QString value) {
return key.toLower() == value.toLower();
}
bool regexMatch(QString key, QString value) {
QRegExp ruleRegex(value);
return ruleRegex.exactMatch(key);
}
bool regexMatchIgnoreCase(QString key, QString value) {
QRegExp ruleRegex(value, Qt::CaseInsensitive);
return ruleRegex.exactMatch(key);
}
RuleValueParse::RuleValueParse()
: negative(0)
, type(0)
, flags(0)
{
}
bool RuleValueParse::parse(QString parsedKey)
{
if (!fn)
return false;
return negative ? fn(parsedKey, value) : !fn(parsedKey, value);
}
bool RuleValueParse::match(const WindowInfoX *winInfo)
{
QString parsedKey;
return parse(parsedKey);
}
WindowPatterns::WindowPatterns()
{
}
QString WindowPatterns::match(WindowInfoX *winInfo)
{
return "";
}
void WindowPatterns::loadWindowPatterns()
{
qInfo() << "---loadWindowPatterns";
QFile file(windowPatternsFile);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();
if (!doc.isArray())
return;
QJsonArray arr = doc.array();
if (arr.size() == 0)
return;
patterns.clear();
for (auto iterp = arr.begin(); iterp != arr.end(); iterp++) {
// 过滤非Object
if (!(*iterp).isObject())
continue;
QJsonObject patternObj = (*iterp).toObject();
QVariantMap patternMap = patternObj.toVariantMap();
WindowPattern pattern;
for (auto infoIter = patternMap.begin(); infoIter != patternMap.end(); infoIter++) {
QString ret = infoIter.key();
QVariant value = infoIter.value();
if (ret == "ret") {
pattern.result = value.toString();
} else if (ret == "rules") {
for (auto &item : value.toList()) {
if (!item.isValid())
continue;
if (item.toList().size() != 2)
continue;
pattern.rules.push_back({item.toList()[0].toString(), item.toList()[1].toString()});
}
}
}
qInfo() << pattern.result;
for (const auto &item : pattern.rules) {
qInfo() << item[0] << " " << item[1];
}
patterns.push_back(pattern);
}
// 解析patterns
for (auto &pattern : patterns) {
for (int i=0; i < pattern.rules.size(); i++) {
RuleValueParse ruleValue = parseRule(pattern.rules[i]);
pattern.parseRules.push_back(ruleValue);
}
}
}
// "=:XXX" equal XXX
// "=!XXX" not equal XXX
// "c:XXX" contains XXX
// "c!XXX" not contains XXX
// "r:XXX" match regexp XXX
// "r!XXX" not match regexp XXX
// e c r ignore case
// = E C R not ignore case
// 解析窗口类型规则
RuleValueParse WindowPatterns::parseRule(QVector<QString> rule)
{
RuleValueParse ret;
ret.key = rule[0];
ret.original = rule[1];
if (rule[1].size() < 2)
return ret;
int len = ret.original.size() + 1;
char *orig = static_cast<char *>(calloc(1, size_t(len)));
if (!orig)
return ret;
strncpy(orig, ret.original.toStdString().c_str(), size_t(len));
switch (orig[1]) {
case ':':
case '!':
ret.flags |= parsedFlagNegative;
ret.negative = true;
break;
default:
return ret;
}
ret.value = QString(&orig[2]);
ret.type = uint8_t(orig[0]);
switch (orig[0]) {
case 'C':
ret.fn = contains;
break;
case 'c':
ret.flags |= parsedFlagIgnoreCase;
ret.fn = containsIgnoreCase;
break;
case '=':
case 'E':
ret.fn = equal;
break;
case 'e':
ret.flags |= parsedFlagIgnoreCase;
ret.fn = equalIgnoreCase;
break;
case 'R':
ret.fn = regexMatch;
break;
case 'r':
ret.flags |= parsedFlagIgnoreCase;
ret.fn = regexMatchIgnoreCase;
break;
default:
return ret;
}
return ret;
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WINDOWPATTERNS_H
#define WINDOWPATTERNS_H
#include "windowinfox.h"
#include <QString>
#include <QVector>
struct RuleValueParse {
RuleValueParse();
bool parse(QString parsedKey);
bool match(const WindowInfoX *winInfo);
QString key;
bool negative;
bool (*fn)(QString, QString);
uint8_t type;
uint flags;
QString original;
QString value;
};
class WindowPatterns
{
// 窗口类型匹配
struct WindowPattern {
QVector<QVector<QString>> rules; // rules
QString result; // ret
QVector< RuleValueParse> parseRules;
};
public:
WindowPatterns();
QString match(WindowInfoX *winInfo);
private:
void loadWindowPatterns();
RuleValueParse parseRule(QVector<QString> rule);
QVector<WindowPattern> patterns;
};
#endif // WINDOWPATTERNS_H

View File

@ -0,0 +1,438 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "x11manager.h"
#include "dock.h"
#include "common.h"
#include <QDebug>
#include <QTimer>
/*
* 使Xlib监听X Events
* 使XCB接口与X进行交互
* */
#include <ctype.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#define XCB XCBUtils::instance()
X11Manager::X11Manager(Dock *_dock, QObject *parent)
: QObject(parent)
, dock(_dock)
, mutex(QMutex(QMutex::NonRecursive))
, listenXEvent(true)
{
rootWindow = XCB->getRootWindow();
}
void X11Manager::listenXEventUseXlib()
{
Display *dpy;
int screen;
char *displayname = nullptr;
Window w;
XSetWindowAttributes attr;
XWindowAttributes wattr;
dpy = XOpenDisplay (displayname);
if (!dpy) {
exit (1);
}
screen = DefaultScreen (dpy);
w = RootWindow(dpy, screen);
const struct {
const char *name;
long mask;
} events[] = {
{ "keyboard", KeyPressMask | KeyReleaseMask | KeymapStateMask },
{ "mouse", ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
LeaveWindowMask | PointerMotionMask | Button1MotionMask |
Button2MotionMask | Button3MotionMask | Button4MotionMask |
Button5MotionMask | ButtonMotionMask },
{ "button", ButtonPressMask | ButtonReleaseMask },
{ "expose", ExposureMask },
{ "visibility", VisibilityChangeMask },
{ "structure", StructureNotifyMask },
{ "substructure", SubstructureNotifyMask | SubstructureRedirectMask },
{ "focus", FocusChangeMask },
{ "property", PropertyChangeMask },
{ "colormap", ColormapChangeMask },
{ "owner_grab_button", OwnerGrabButtonMask },
{ nullptr, 0 }
};
long mask = 0;
for (int i = 0; events[i].name; i++)
mask |= events[i].mask;
attr.event_mask = mask;
XGetWindowAttributes(dpy, w, &wattr);
attr.event_mask &= ~SubstructureRedirectMask;
XSelectInput(dpy, w, attr.event_mask);
while (listenXEvent) {
XEvent event;
XNextEvent (dpy, &event);
if (event.type == DestroyNotify) {
XDestroyWindowEvent *eD = (XDestroyWindowEvent *) (&event);
//qInfo() << "DestroyNotify windowId=" << eD->window;
handleDestroyNotifyEvent(XWindow(eD->window));
} else if (event.type == MapNotify) {
XMapEvent *eM = (XMapEvent *)(&event);
//qInfo() << "MapNotify windowId=" << eM->window;
handleMapNotifyEvent(XWindow(eM->window));
} else if (event.type == ConfigureNotify ) {
XConfigureEvent *eC = (XConfigureEvent *) (&event);
//qInfo() << "ConfigureNotify windowId=" << eC->window;
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
} else if (event.type == PropertyNotify) {
XPropertyEvent *eP = (XPropertyEvent *) (&event);
//qInfo() << "PropertyNotify windowId=" << eP->window;
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
} else {
//qInfo() << "Unknown event type " << event.type;
}
}
XCloseDisplay (dpy);
}
void X11Manager::listenXEventUseXCB()
{
/*
xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(XCB->getConnect(), XCB->getRootWindow());
xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(XCB->getConnect(), cookie, NULL);
if (reply) {
uint32_t valueMask = reply->your_event_mask;
valueMask &= ~XCB_CW_OVERRIDE_REDIRECT;
uint32_t mask[2] = {0};
mask[0] = valueMask;
//xcb_change_window_attributes(XCB->getConnect(), XCB->getRootWindow(), valueMask, mask);
free(reply);
}
xcb_generic_event_t *event;
while ( (event = xcb_wait_for_event (XCB->getConnect())) ) {
eventHandler(event->response_type & ~0x80, event);
}
*/
}
// 注册X11窗口
WindowInfoX *X11Manager::registerWindow(XWindow xid)
{
qInfo() << "registWindow: windowId=" << xid;
WindowInfoX *ret = nullptr;
do {
if (windowInfoMap.find(xid) != windowInfoMap.end()) {
ret = windowInfoMap[xid];
break;
}
WindowInfoX *winInfo = new WindowInfoX(xid);
if (!winInfo)
break;
listenWindowXEvent(winInfo);
windowInfoMap[xid] = winInfo;
ret = winInfo;
} while (0);
return ret;
}
// 取消注册X11窗口
void X11Manager::unregisterWindow(XWindow xid)
{
qInfo() << "unregisterWindow: windowId=" << xid;
if (windowInfoMap.find(xid) != windowInfoMap.end()) {
windowInfoMap.remove(xid);
}
}
WindowInfoX *X11Manager::findWindowByXid(XWindow xid)
{
WindowInfoX *ret = nullptr;
if (windowInfoMap.find(xid) != windowInfoMap.end())
ret = windowInfoMap[xid];
return ret;
}
void X11Manager::handleClientListChanged()
{
QSet<XWindow> newClientList, oldClientList, addClientList, rmClientList;
for (auto atom : XCB->getClientList())
newClientList.insert(atom);
for (auto atom : dock->getClientList())
oldClientList.insert(atom);
addClientList = newClientList - oldClientList;
rmClientList = oldClientList - newClientList;
for (auto xid : addClientList) {
WindowInfoX *info = registerWindow(xid);
if (!XCB->isGoodWindow(xid))
continue;
uint32_t pid = XCB->getWMPid(xid);
WMClass wmClass = XCB->getWMClass(xid);
QString wmName(XCB->getWMName(xid).c_str());
if (pid != 0 || (wmClass.className.size() > 0 && wmClass.instanceName.size() > 0)
|| wmName.size() > 0 || XCB->getWMCommand(xid).size() > 0)
dock->attachWindow(info);
}
for (auto xid : rmClientList) {
WindowInfoX *info = windowInfoMap[xid];
if (info) {
dock->detachWindow(info);
unregisterWindow(xid);
} else {
// no window
auto entry = dock->getEntryByWindowId(xid);
if (entry && !dock->isDocked(entry->getFileName())) {
dock->removeAppEntry(entry);
}
}
}
}
void X11Manager::handleActiveWindowChangedX()
{
XWindow active = XCB->getActiveWindow();
WindowInfoX *info = findWindowByXid(active);
dock->handleActiveWindowChanged(info);
}
void X11Manager::listenRootWindowXEvent()
{
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
XCB->registerEvents(rootWindow, eventMask);
handleActiveWindowChangedX();
handleClientListChanged();
}
void X11Manager::listenWindowXEvent(WindowInfoX *winInfo)
{
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | EventMask::XCB_EVENT_MASK_STRUCTURE_NOTIFY | EventMask::XCB_EVENT_MASK_VISIBILITY_CHANGE;
XCB->registerEvents(winInfo->getXid(), eventMask);
}
void X11Manager::handleRootWindowPropertyNotifyEvent(XCBAtom atom)
{
if (atom == XCB->getAtom("_NET_CLIENT_LIST"))
handleClientListChanged();
else if (atom == XCB->getAtom("_NET_ACTIVE_WINDOW"))
handleActiveWindowChangedX();
else if (atom == XCB->getAtom("_NET_SHOWING_DESKTOP"))
Q_EMIT needUpdateHideState(false);
}
// destory event
void X11Manager::handleDestroyNotifyEvent(XWindow xid)
{
WindowInfoX *winInfo = findWindowByXid(xid);
if (!winInfo)
return;
dock->detachWindow(winInfo);
unregisterWindow(xid);
}
// map event
void X11Manager::handleMapNotifyEvent(XWindow xid)
{
WindowInfoX *winInfo = registerWindow(xid);
if (!winInfo)
return;
QTimer::singleShot(2 * 1000, this, [&] {
qInfo() << "handleMapNotifyEvent: pass 2s, now call idnetifyWindow, windowId=" << winInfo->getXid();
QString innerId;
AppInfo *appInfo = dock->identifyWindow(winInfo, innerId);
dock->markAppLaunched(appInfo);
});
}
// config changed event 检测窗口大小调整和重绘应用
void X11Manager::handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height)
{
WindowInfoX *winInfo = findWindowByXid(xid);
if (!winInfo || dock->getDockHideMode() != HideMode::SmartHide)
return;
WMClass wmClass = winInfo->getWMClass();
if (wmClass.className.c_str() == frontendWindowWmClass)
return; // ignore frontend window ConfigureNotify event
Q_EMIT needUpdateHideState(winInfo->isGeometryChanged(x, y, width, height));
}
// property changed event
void X11Manager::handlePropertyNotifyEvent(XWindow xid, XCBAtom atom)
{
if (xid == rootWindow) {
handleRootWindowPropertyNotifyEvent(atom);
return;
}
WindowInfoX *winInfo = findWindowByXid(xid);
if (!winInfo)
return;
QString newInnerId;
bool needAttachOrDetach = false;
if (atom == XCB->getAtom("_NET_WM_STATE")) {
winInfo->updateWmState();
needAttachOrDetach = true;
} else if (atom == XCB->getAtom("_GTK_APPLICATION_ID")) {
QString gtkAppId;
winInfo->setGtkAppId(gtkAppId);
newInnerId = winInfo->genInnerId(winInfo);
} else if (atom == XCB->getAtom("_NET_WM_PID")) {
winInfo->updateProcessInfo();
newInnerId = winInfo->genInnerId(winInfo);
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
winInfo->updateWmName();
newInnerId = winInfo->genInnerId(winInfo);
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
winInfo->updateIcon();
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
winInfo->updateWmAllowedActions();
} else if (atom == XCB->getAtom("_MOTIF_WM_HINTS")) {
winInfo->updateMotifWmHints();
} else if (atom == XCB_ATOM_WM_CLASS) {
winInfo->updateWmClass();
newInnerId = winInfo->genInnerId(winInfo);
needAttachOrDetach = true;
} else if (atom == XCB->getAtom("_XEMBED_INFO")) {
winInfo->updateHasXEmbedInfo();
needAttachOrDetach = true;
} else if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE")) {
winInfo->updateWmWindowType();
needAttachOrDetach = true;
} else if (atom == XCB_ATOM_WM_TRANSIENT_FOR) {
winInfo->updateHasWmTransientFor();
needAttachOrDetach = true;
}
if (!newInnerId.isEmpty() && winInfo->getUpdateCalled() && winInfo->getInnerId() != newInnerId) {
// winInfo.innerId changed
dock->detachWindow(winInfo);
winInfo->setInnerId(newInnerId);
needAttachOrDetach = true;
}
if (needAttachOrDetach)
dock->attachWindow(winInfo);
Entry *entry = dock->getEntryByWindowId(xid);
if (!entry)
return;
if (atom == XCB->getAtom("_NET_WM_STATE")) {
entry->updateWindowInfos();
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
if (entry->getCurrentWindowInfo() == winInfo) {
entry->updateIcon();
}
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
if (entry->getCurrentWindowInfo() == winInfo) {
entry->updateName();
}
entry->updateWindowInfos();
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
entry->updateMenu();
}
}
void X11Manager::eventHandler(uint8_t type, void *event)
{
qInfo() << "eventHandler" << "type = " << type;
switch (type) {
case XCB_MAP_NOTIFY: // 17 注册新窗口
qInfo() << "eventHandler: XCB_MAP_NOTIFY";
break;
case XCB_DESTROY_NOTIFY: // 19 销毁窗口
qInfo() << "eventHandler: XCB_DESTROY_NOTIFY";
break;
case XCB_CONFIGURE_NOTIFY: // 22 窗口变化
qInfo() << "eventHandler: XCB_CONFIGURE_NOTIFY";
break;
case XCB_PROPERTY_NOTIFY: // 28 窗口属性改变
qInfo() << "eventHandler: XCB_PROPERTY_NOTIFY";
break;
}
}
void X11Manager::addWindowLastConfigureEvent(XWindow xid, ConfigureEvent *event)
{
delWindowLastConfigureEvent(xid);
QMutexLocker locker(&mutex);
QTimer *timer = new QTimer();
timer->setInterval(configureNotifyDelay);
windowLastConfigureEventMap[xid] = QPair(event, timer);
}
QPair<ConfigureEvent *, QTimer *> X11Manager::getWindowLastConfigureEvent(XWindow xid)
{
QPair<ConfigureEvent *, QTimer *> ret;
QMutexLocker locker(&mutex);
if (windowLastConfigureEventMap.find(xid) != windowLastConfigureEventMap.end())
ret = windowLastConfigureEventMap[xid];
return ret;
}
void X11Manager::delWindowLastConfigureEvent(XWindow xid)
{
QMutexLocker locker(&mutex);
if (windowLastConfigureEventMap.find(xid) != windowLastConfigureEventMap.end()) {
QPair<ConfigureEvent*, QTimer*> item = windowLastConfigureEventMap[xid];
windowLastConfigureEventMap.remove(xid);
delete item.first;
item.second->deleteLater();
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef X11MANAGER_H
#define X11MANAGER_H
#include "windowinfox.h"
#include "xcbutils.h"
#include <QObject>
#include <QMap>
#include <QMutex>
#include <QTimer>
class Dock;
class X11Manager : public QObject
{
Q_OBJECT
public:
explicit X11Manager(Dock *_dock, QObject *parent = nullptr);
WindowInfoX *findWindowByXid(XWindow xid);
WindowInfoX *registerWindow(XWindow xid);
void unregisterWindow(XWindow xid);
void handleClientListChanged();
void handleActiveWindowChangedX();
void listenRootWindowXEvent();
void listenWindowXEvent(WindowInfoX *winInfo);
void handleRootWindowPropertyNotifyEvent(XCBAtom atom);
void handleDestroyNotifyEvent(XWindow xid);
void handleMapNotifyEvent(XWindow xid);
void handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height);
void handlePropertyNotifyEvent(XWindow xid, XCBAtom atom);
void eventHandler(uint8_t type, void *event);
void listenWindowEvent(WindowInfoX *winInfo);
void listenXEventUseXlib();
void listenXEventUseXCB();
signals:
void needUpdateHideState(bool delay);
private:
void addWindowLastConfigureEvent(XWindow xid, ConfigureEvent* event);
QPair<ConfigureEvent*, QTimer*> getWindowLastConfigureEvent(XWindow xid);
void delWindowLastConfigureEvent(XWindow xid);
QMap<XWindow, WindowInfoX *> windowInfoMap;
Dock *dock;
QMap<XWindow, QPair<ConfigureEvent*, QTimer*>> windowLastConfigureEventMap; // 手动回收ConfigureEvent和QTimer
QMutex mutex;
XWindow rootWindow; // 根窗口
bool listenXEvent; // 监听X事件
};
#endif // X11MANAGER_H

View File

@ -0,0 +1,291 @@
/*
* Copyright (C) 2022 ~ 2023 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "category.h"
Category::Category()
{
}
Category::~Category()
{
}
QString Category::getStr(Categorytype ty) {
QMap<Categorytype, QString> ty2str = {
{Categorytype::CategoryInternet, "Internet"},
{Categorytype::CategoryChat, "Chat"},
{Categorytype::CategoryMusic, "Music"},
{Categorytype::CategoryVideo, "Video"},
{Categorytype::CategoryGraphics, "Graphics"},
{Categorytype::CategoryOffice, "Office"},
{Categorytype::CategoryGame, "Game"},
{Categorytype::CategoryReading, "Reading"},
{Categorytype::CategoryDevelopment, "Development"},
{Categorytype::CategorySystem, "System"},
{Categorytype::CategoryOthers, "Others"},
};
return ty2str.find(ty) != ty2str.end() ? ty2str[ty] : "Others";
}
QString Category::pinYin(Categorytype ty) {
QMap<Categorytype, QString> ty2py = {
{Categorytype::CategoryInternet, "wangluo"},
{Categorytype::CategoryChat, "shejiaogoutong"},
{Categorytype::CategoryMusic, "yinyuexinshang"},
{Categorytype::CategoryVideo, "shipinbofang"},
{Categorytype::CategoryGraphics, "tuxintuxiang"},
{Categorytype::CategoryOffice, "bangongxuexi"},
{Categorytype::CategoryGame, "youxiyule"},
{Categorytype::CategoryReading, "yuedufanyi"},
{Categorytype::CategoryDevelopment, "bianchengkaifai"},
{Categorytype::CategorySystem, "xitongguanli"},
{Categorytype::CategoryOthers, "qita"},
};
return ty2py.find(ty) != ty2py.end() ? ty2py[ty] : "qita";
}
Categorytype Category::parseCategoryString(QString str) {
QMap<QString, Categorytype> name2ty {
{"internet", Categorytype::CategoryInternet},
{"chat", Categorytype::CategoryChat},
{"music", Categorytype::CategoryMusic},
{"video", Categorytype::CategoryVideo},
{"graphics", Categorytype::CategoryGraphics},
{"office", Categorytype::CategoryOffice},
{"game", Categorytype::CategoryGame},
{"reading", Categorytype::CategoryReading},
{"development", Categorytype::CategoryDevelopment},
{"system", Categorytype::CategorySystem},
{"others", Categorytype::CategoryOthers},
};
return name2ty.find(str) != name2ty.end() ? name2ty[str] : Categorytype::CategoryErr;
}
QList<Categorytype> Category::parseXCategoryString(QString str) {
QMultiMap<QString, Categorytype> xname2ty {
{"2dgraphics", Categorytype::CategoryGraphics},
{"3dgraphics", Categorytype::CategoryGraphics},
{"accessibility", Categorytype::CategorySystem},
{"accessories", Categorytype::CategoryOthers},
{"actiongame", Categorytype::CategoryGame},
{"advancedsettings", Categorytype::CategorySystem},
{"adventuregame", Categorytype::CategoryGame},
{"amusement", Categorytype::CategoryGame},
{"applet", Categorytype::CategoryOthers},
{"arcadegame", Categorytype::CategoryGame},
{"archiving", Categorytype::CategorySystem},
{"art", Categorytype::CategoryOffice},
{"artificialintelligence", Categorytype::CategoryOffice},
{"astronomy", Categorytype::CategoryOffice},
{"audio", Categorytype::CategoryMusic},
{"audiovideo", Categorytype::CategoryMusic},
{"audiovideo", Categorytype::CategoryVideo},
{"audiovideoediting", Categorytype::CategoryMusic},
{"audiovideoediting", Categorytype::CategoryVideo},
{"biology", Categorytype::CategoryOffice},
{"blocksgame", Categorytype::CategoryGame},
{"boardgame", Categorytype::CategoryGame},
{"building", Categorytype::CategoryDevelopment},
{"calculator", Categorytype::CategorySystem},
{"calendar", Categorytype::CategorySystem},
{"cardgame", Categorytype::CategoryGame},
{"cd", Categorytype::CategoryMusic},
{"chart", Categorytype::CategoryOffice},
{"chat", Categorytype::CategoryChat},
{"chemistry", Categorytype::CategoryOffice},
{"clock", Categorytype::CategorySystem},
{"compiz", Categorytype::CategorySystem},
{"compression", Categorytype::CategorySystem},
{"computerscience", Categorytype::CategoryOffice},
{"consoleonly", Categorytype::CategoryOthers},
{"contactmanagement", Categorytype::CategoryChat},
{"core", Categorytype::CategoryOthers},
{"debugger", Categorytype::CategoryDevelopment},
{"desktopsettings", Categorytype::CategorySystem},
{"desktoputility", Categorytype::CategorySystem},
{"development", Categorytype::CategoryDevelopment},
{"dialup", Categorytype::CategorySystem},
{"dictionary", Categorytype::CategoryOffice},
{"discburning", Categorytype::CategorySystem},
{"documentation", Categorytype::CategoryOffice},
{"editors", Categorytype::CategoryOthers},
{"education", Categorytype::CategoryOffice},
{"electricity", Categorytype::CategoryOffice},
{"electronics", Categorytype::CategoryOffice},
{"email", Categorytype::CategoryInternet},
{"emulator", Categorytype::CategoryGame},
{"engineering", Categorytype::CategorySystem},
{"favorites", Categorytype::CategoryOthers},
{"filemanager", Categorytype::CategorySystem},
{"filesystem", Categorytype::CategorySystem},
{"filetools", Categorytype::CategorySystem},
{"filetransfer", Categorytype::CategoryInternet},
{"finance", Categorytype::CategoryOffice},
{"game", Categorytype::CategoryGame},
{"geography", Categorytype::CategoryOffice},
{"geology", Categorytype::CategoryOffice},
{"geoscience", Categorytype::CategoryOthers},
{"gnome", Categorytype::CategorySystem},
{"gpe", Categorytype::CategoryOthers},
{"graphics", Categorytype::CategoryGraphics},
{"guidesigner", Categorytype::CategoryDevelopment},
{"hamradio", Categorytype::CategoryOffice},
{"hardwaresettings", Categorytype::CategorySystem},
{"ide", Categorytype::CategoryDevelopment},
{"imageprocessing", Categorytype::CategoryGraphics},
{"instantmessaging", Categorytype::CategoryChat},
{"internet", Categorytype::CategoryInternet},
{"ircclient", Categorytype::CategoryChat},
{"kde", Categorytype::CategorySystem},
{"kidsgame", Categorytype::CategoryGame},
{"literature", Categorytype::CategoryOffice},
{"logicgame", Categorytype::CategoryGame},
{"math", Categorytype::CategoryOffice},
{"medicalsoftware", Categorytype::CategoryOffice},
{"meteorology", Categorytype::CategoryOthers},
{"midi", Categorytype::CategoryMusic},
{"mixer", Categorytype::CategoryMusic},
{"monitor", Categorytype::CategorySystem},
{"motif", Categorytype::CategoryOthers},
{"multimedia", Categorytype::CategoryVideo},
{"music", Categorytype::CategoryMusic},
{"network", Categorytype::CategoryInternet},
{"news", Categorytype::CategoryReading},
{"numericalanalysis", Categorytype::CategoryOffice},
{"ocr", Categorytype::CategoryGraphics},
{"office", Categorytype::CategoryOffice},
{"p2p", Categorytype::CategoryInternet},
{"packagemanager", Categorytype::CategorySystem},
{"panel", Categorytype::CategorySystem},
{"pda", Categorytype::CategorySystem},
{"photography", Categorytype::CategoryGraphics},
{"physics", Categorytype::CategoryOffice},
{"pim", Categorytype::CategoryOthers},
{"player", Categorytype::CategoryMusic},
{"player", Categorytype::CategoryVideo},
{"playonlinux", Categorytype::CategoryOthers},
{"presentation", Categorytype::CategoryOffice},
{"printing", Categorytype::CategoryOffice},
{"profiling", Categorytype::CategoryDevelopment},
{"projectmanagement", Categorytype::CategoryOffice},
{"publishing", Categorytype::CategoryOffice},
{"puzzlegame", Categorytype::CategoryGame},
{"rastergraphics", Categorytype::CategoryGraphics},
{"recorder", Categorytype::CategoryMusic},
{"recorder", Categorytype::CategoryVideo},
{"remoteaccess", Categorytype::CategorySystem},
{"revisioncontrol", Categorytype::CategoryDevelopment},
{"robotics", Categorytype::CategoryOffice},
{"roleplaying", Categorytype::CategoryGame},
{"scanning", Categorytype::CategoryOffice},
{"science", Categorytype::CategoryOffice},
{"screensaver", Categorytype::CategoryOthers},
{"sequencer", Categorytype::CategoryMusic},
{"settings", Categorytype::CategorySystem},
{"security", Categorytype::CategorySystem},
{"simulation", Categorytype::CategoryGame},
{"sportsgame", Categorytype::CategoryGame},
{"spreadsheet", Categorytype::CategoryOffice},
{"strategygame", Categorytype::CategoryGame},
{"system", Categorytype::CategorySystem},
{"systemsettings", Categorytype::CategorySystem},
{"technical", Categorytype::CategoryOthers},
{"telephony", Categorytype::CategorySystem},
{"telephonytools", Categorytype::CategorySystem},
{"terminalemulator", Categorytype::CategorySystem},
{"texteditor", Categorytype::CategoryOffice},
{"texttools", Categorytype::CategoryOffice},
{"transiation", Categorytype::CategoryDevelopment},
{"translation", Categorytype::CategoryReading},
{"trayicon", Categorytype::CategorySystem},
{"tuner", Categorytype::CategoryMusic},
{"tv", Categorytype::CategoryVideo},
{"utility", Categorytype::CategorySystem},
{"vectorgraphics", Categorytype::CategoryGraphics},
{"video", Categorytype::CategoryVideo},
{"videoconference", Categorytype::CategoryInternet},
{"viewer", Categorytype::CategoryGraphics},
{"webbrowser", Categorytype::CategoryInternet},
{"webdevelopment", Categorytype::CategoryDevelopment},
{"wine", Categorytype::CategoryOthers},
{"wine-programs-accessories", Categorytype::CategoryOthers},
{"wordprocessor", Categorytype::CategoryOffice},
{"x-alsa", Categorytype::CategoryMusic},
{"x-bible", Categorytype::CategoryReading},
{"x-bluetooth", Categorytype::CategorySystem},
{"x-debian-applications-emulators", Categorytype::CategoryGame},
{"x-digital_processing", Categorytype::CategorySystem},
{"x-enlightenment", Categorytype::CategorySystem},
{"x-geeqie", Categorytype::CategoryGraphics},
{"x-gnome-networksettings", Categorytype::CategorySystem},
{"x-gnome-personalsettings", Categorytype::CategorySystem},
{"x-gnome-settings-panel", Categorytype::CategorySystem},
{"x-gnome-systemsettings", Categorytype::CategorySystem},
{"x-gnustep", Categorytype::CategorySystem},
{"x-islamic-software", Categorytype::CategoryReading},
{"x-jack", Categorytype::CategoryMusic},
{"x-kde-edu-misc", Categorytype::CategoryReading},
{"x-kde-internet", Categorytype::CategorySystem},
{"x-kde-more", Categorytype::CategorySystem},
{"x-kde-utilities-desktop", Categorytype::CategorySystem},
{"x-kde-utilities-file", Categorytype::CategorySystem},
{"x-kde-utilities-peripherals", Categorytype::CategorySystem},
{"x-kde-utilities-pim", Categorytype::CategorySystem},
{"x-lxde-settings", Categorytype::CategorySystem},
{"x-mandriva-office-publishing", Categorytype::CategoryOthers},
{"x-mandrivalinux-internet-other", Categorytype::CategorySystem},
{"x-mandrivalinux-office-other", Categorytype::CategoryOffice},
{"x-mandrivalinux-system-archiving-backup", Categorytype::CategorySystem},
{"x-midi", Categorytype::CategoryMusic},
{"x-misc", Categorytype::CategorySystem},
{"x-multitrack", Categorytype::CategoryMusic},
{"x-novell-main", Categorytype::CategorySystem},
{"x-quran", Categorytype::CategoryReading},
{"x-red-hat-base", Categorytype::CategorySystem},
{"x-red-hat-base-only", Categorytype::CategorySystem},
{"x-red-hat-extra", Categorytype::CategorySystem},
{"x-red-hat-serverconfig", Categorytype::CategorySystem},
{"x-religion", Categorytype::CategoryReading},
{"x-sequencers", Categorytype::CategoryMusic},
{"x-sound", Categorytype::CategoryMusic},
{"x-sun-supported", Categorytype::CategorySystem},
{"x-suse-backup", Categorytype::CategorySystem},
{"x-suse-controlcenter-lookandfeel", Categorytype::CategorySystem},
{"x-suse-controlcenter-system", Categorytype::CategorySystem},
{"x-suse-core", Categorytype::CategorySystem},
{"x-suse-core-game", Categorytype::CategoryGame},
{"x-suse-core-office", Categorytype::CategoryOffice},
{"x-suse-sequencer", Categorytype::CategoryMusic},
{"x-suse-yast", Categorytype::CategorySystem},
{"x-suse-yast-high_availability", Categorytype::CategorySystem},
{"x-synthesis", Categorytype::CategorySystem},
{"x-turbolinux-office", Categorytype::CategoryOffice},
{"x-xfce", Categorytype::CategorySystem},
{"x-xfce-toplevel", Categorytype::CategorySystem},
{"x-xfcesettingsdialog", Categorytype::CategorySystem},
{"x-ximian-main", Categorytype::CategorySystem},
};
return {xname2ty.values(str)};
}

Some files were not shown because too many files have changed in this diff Show More