update upstream code (将yangtze分支代码合进upstream分支)

This commit is contained in:
杜长峰 2023-04-24 17:09:43 +08:00
commit 9932d35118
24 changed files with 484 additions and 187 deletions

View File

@ -2,6 +2,11 @@
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/com/kylin/ProcessManager">
<interface name="com.kylin.ProcessManager">
<method name="InitCGroup">
<arg name="rootPath" type="s" direction="in"/>
<arg name="result" type="a{sv}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMap&lt;QString,QVariant>"/>
</method>
<method name="CreateProcessCGroup">
<arg name="appId" type="s" direction="in"/>
<arg name="pids" type="ai" direction="in"/>

View File

@ -10,14 +10,16 @@
{
"resource": "CPU",
"adjs": [300, 200, 100],
"cpu.weight": [20, 40, 60]
"cpu.weight": [20, 40, 60],
"cpu.max": [20000, 40000, 60000]
},
{
"resource": "IO",
"adjs": [300, 200, 100],
"io.weight": [20, 40, 60]
"io.weight": [20, 40, 60],
"cgroup.freeze": [1, 0, 0]
}
]
},
"statusSwitchInterval": 10
}
"statusSwitchInterval": 1800
}

View File

@ -0,0 +1,2 @@
# kylin-app-manager

View File

@ -20,31 +20,21 @@
#include "dbusservices/appmanagerservice.h"
#include "dbusservices/applauncher.h"
#include "dbusservices/whitelistmanager.h"
#include "memorymonitor.h"
#include "dbusservices/applauncher.h"
#include "core/eventwatcher.h"
AppManager::AppManager(QObject *parent)
: QObject(parent)
, m_service(new AppManagerService(this))
, m_appLauncher(new AppLauncher(this))
, m_whiteListManager(new WhiteListManager(this))
#if 0
, m_memMonitor(new MemoryMonitor(this))
#endif
, m_eventWatcher(new EventWatcher(this))
{
QDBusConnection connection = QDBusConnection::sessionBus();
if (!connection.registerService("com.kylin.AppManager") ||
!connection.registerObject("/com/kylin/AppManager", this)) {
qWarning() << "register dbus service failed" << connection.lastError();
}
// 当白名单添加应用时更新该应用的cgroup状态
connect(m_whiteListManager, &WhiteListManager::addedToWhitelist,
m_appLauncher, &AppLauncher::updateWhitelistCGroupStatus);
connect(m_appLauncher, &AppLauncher::appLaunched,
m_service, &AppManagerService::appLaunched);
#if 0
connect(m_memMonitor, &MemoryMonitor::lowMemoryWaining,
m_appLauncher, &AppLauncher::killCachedApp);
#endif
initConnections();
}
bool AppManager::LaunchApp(const QString &desktopFile)
@ -69,17 +59,17 @@ bool AppManager::LaunchDefaultAppWithUrl(const QString &url)
void AppManager::SetPowerSavingModeEnable(bool enable)
{
m_appLauncher->setPowerSavingModeEnable(enable);
// m_appLauncher->setPowerSavingModeEnable(enable);
}
bool AppManager::AddToWhiteList(const QString &desktopFile, const QString &option)
{
return m_whiteListManager->addToWhiteList(desktopFile, option);
return m_whiteListManager.addToWhiteList(desktopFile, option);
}
bool AppManager::RemoveFromWhiteList(const QString &desktopFile, const QString &option)
{
return m_whiteListManager->removeFromWhiteList(desktopFile, option);
return m_whiteListManager.removeFromWhiteList(desktopFile, option);
}
bool AppManager::ActiveProcessByWid(const uint &wid)
@ -87,14 +77,19 @@ bool AppManager::ActiveProcessByWid(const uint &wid)
return m_appLauncher->ActiveProcessByWid(wid);
}
bool AppManager::ActiveProcessByPid(const int &pid)
{
return m_appLauncher->ActiveProcessByPid(pid);
}
QStringList AppManager::WhiteListsOfApp(const QString &desktopFile)
{
return m_whiteListManager->whiteListsOfApp(desktopFile);
return m_whiteListManager.whiteListsOfApp(desktopFile);
}
QStringList AppManager::AppWhiteList(const QString &option)
{
return m_whiteListManager->appWhiteList(option);
return m_whiteListManager.appWhiteList(option);
}
QVector<QStringList> AppManager::RecommendAppLists(const QString &fileName)
@ -112,14 +107,61 @@ QString AppManager::AppDesktopFileNameByWid(qint64 wid)
return m_appLauncher->AppDesktopFileNameByWid(wid);
}
QString AppManager::Inhibit(const QString &desktopFile,
uint pid,
const QString &reason,
uint flags)
{
return m_appInfoManager.inhibit(desktopFile, pid, reason, flags);
}
void AppManager::UnInhibit(const QString &cookie)
{
m_appInfoManager.unInhibit(cookie);
}
bool AppManager::ThawApps()
{
return m_appInfoManager.ThawApps();
}
void AppManager::setEnvValue(const QByteArray &envValue)
{
return m_appLauncher->setEnvValue(envValue);
}
#if 0
QList<uint> AppManager::RunningApplications()
void AppManager::initConnections()
{
return m_appLauncher->RunningApplications();
connect(&m_appInfoManager, &AppInfoManager::appLaunched,
m_service, &AppManagerService::appLaunched);
connect(&m_appInfoManager, &AppInfoManager::appFinished,
m_service, &AppManagerService::appFinished);
connect(m_eventWatcher, &EventWatcher::activeWindowChanged,
&m_appInfoManager, &AppInfoManager::onActiveWindowChanged);
connect(m_eventWatcher, &EventWatcher::windowAdded,
&m_appInfoManager, &AppInfoManager::onWindowAdded);
connect(m_eventWatcher, &EventWatcher::windowRemoved,
&m_appInfoManager, &AppInfoManager::onWindowRemoved);
connect(m_eventWatcher, &EventWatcher::mprisDbusAdded,
&m_appInfoManager, &AppInfoManager::onMprisDbusAdded);
connect(m_eventWatcher, &EventWatcher::tabletModeChanged,
&m_appInfoManager, &AppInfoManager::onTabletModeChanged);
connect(m_eventWatcher, &EventWatcher::resourceThresholdWarning,
&m_appInfoManager, &AppInfoManager::onResourceThresholdWarning);
connect(m_eventWatcher, &EventWatcher::aboutToQuitApp,
&m_appInfoManager, &AppInfoManager::onAboutToQuitApp);
connect(m_eventWatcher, &EventWatcher::ChildPidFinished,
&m_appInfoManager, &AppInfoManager::onChildPidFinished);
connect(&m_appInfoManager, &AppInfoManager::launchHoverButton,
m_appLauncher, &AppLauncher::wakeupHoverButton);
}
#endif

View File

@ -18,12 +18,17 @@
#define APPMANAGER_H
#include <QObject>
#include <KWindowSystem>
#include <QVector>
#include "common.h"
#include "core/appinfomanager.h"
#include "dbusservices/whitelistmanager.h"
class AppManagerService;
class AppLauncher;
class WhiteListManager;
class MemoryMonitor;
class EventWatcher;
class AppStatusManager;
class AppManager : public QObject
{
Q_OBJECT
@ -38,24 +43,32 @@ public:
Q_INVOKABLE bool AddToWhiteList(const QString &desktopFile, const QString &option);
Q_INVOKABLE bool RemoveFromWhiteList(const QString &desktopFile, const QString &option);
Q_INVOKABLE bool ActiveProcessByWid(const uint &wid);
Q_INVOKABLE bool ActiveProcessByPid(const int &pid);
Q_INVOKABLE QStringList WhiteListsOfApp(const QString &desktopFile);
Q_INVOKABLE QStringList AppWhiteList(const QString &option);
Q_INVOKABLE QVector<QStringList> RecommendAppLists(const QString &fileName);
Q_INVOKABLE QString AppDesktopFileNameByPid(qint64 pid);
Q_INVOKABLE QString AppDesktopFileNameByWid(qint64 wid);
Q_INVOKABLE void setEnvValue(const QByteArray &envValue);
Q_INVOKABLE QString Inhibit(const QString &desktopFile,
uint pid,
const QString &reason,
uint flags);
Q_INVOKABLE void UnInhibit(const QString &cookie);
#if 0
Q_INVOKABLE QList<uint> RunningApplications();
#endif
Q_INVOKABLE bool ThawApps();
void setEnvValue(const QByteArray &envValue);
private:
void initConnections();
private:
AppManagerService *m_service;
AppLauncher *m_appLauncher;
WhiteListManager *m_whiteListManager;
#if 0
MemoryMonitor *m_memMonitor;
#endif
EventWatcher *m_eventWatcher;
WhiteListManager &m_whiteListManager = common::Singleton<WhiteListManager>::GetInstance();
AppInfoManager &m_appInfoManager = common::Singleton<AppInfoManager>::GetInstance();
};
#endif // APPMANAGER_H

View File

@ -24,7 +24,7 @@ AppCGroup::AppCGroup(QObject *parent)
, m_processManagerInterface(new com::kylin::ProcessManager("com.kylin.ProcessManager",
"/com/kylin/ProcessManager", QDBusConnection::systemBus()))
{
initCGroup();
}
QString AppCGroup::createProcessCGroup(const QString &appId, const QList<int> &pids)
@ -78,7 +78,7 @@ QString AppCGroup::cgroupNameWithPid(int pid)
auto reply = m_processManagerInterface->CGroupNameWithPid(pid);
while (!reply.isFinished()) {
qApp->processEvents();
sleep(1);
usleep(1);
}
if (reply.isError()) {
qWarning() << __FUNCTION__ << "error, " << reply.error();
@ -86,3 +86,27 @@ QString AppCGroup::cgroupNameWithPid(int pid)
}
return reply.value().value(kDbusResult).toString();
}
void AppCGroup::initCGroup()
{
QProcess p;
p.start("id", QStringList() << "-u");
p.waitForFinished();
auto userId = p.readAll().toUInt();
auto rootPath = QString("user.slice/user-%1.slice/kylin-app-manager").arg(userId);
auto reply = m_processManagerInterface->InitCGroup(rootPath);
while (!reply.isFinished()) {
qApp->processEvents();
usleep(1);
}
if (reply.isError()) {
qWarning() << __FUNCTION__ << "error, " << reply.error();
return;
}
if (!reply.value().value(kDbusResult).toBool()) {
qWarning() << "Init CGroup failed, "
<< reply.value().value(kDbusErrMsg).toString()
<< "the root path is " << rootPath;
}
qDebug() << reply.value().value(kDbusResult) << rootPath;
}

View File

@ -37,6 +37,7 @@ public:
QString cgroupNameWithPid(int pid);
private:
void initCGroup();
private:
com::kylin::ProcessManager *m_processManagerInterface;

View File

@ -15,6 +15,8 @@
*/
#include "appinfo.h"
#include <QCryptographicHash>
#include <QDateTime>
#include <KWindowSystem>
#include <windowmanager/windowmanager.h>
#include "common.h"
@ -93,7 +95,7 @@ QStringList AppInfo::cgroupNames(Policy::AppStatus status) const
{
QStringList cgroupNames;
for (auto const &instance : qAsConst(m_instances)) {
if (instance.appStatus >= status) {
if (instance.appStatus == status) {
cgroupNames.push_back(instance.cgroupName);
}
}
@ -192,10 +194,9 @@ bool AppInfo::appInstanceIsHidden(const QString &instName) const
}
for (auto const &wid : inst.wids) {
// todo: return hidden state
if (Policy::isWaylandPlatform()) {
auto windowInfo = kdk::WindowManager::getwindowInfo(wid);
return true;
return windowInfo.isMinimized();
}
KWindowInfo windowInfo(wid, NET::WMState | NET::XAWMState);
if (!windowInfo.hasState(NET::Hidden)) {

View File

@ -52,7 +52,7 @@ QString AppInfoManager::newAppInstance(const QString &desktopFile,
return QString();
}
QString cgroupName = (type == appinfo::Normal) ?
QString cgroupName = (type == appinfo::Normal && !kNoCgroupApps.contains(desktopFileName(desktopFile))) ?
m_appStatusManager->newAppInstance(appId, pids) : "";
appinfo::AppInstance appInstance;
appInstance.pids = pids;
@ -217,7 +217,8 @@ std::tuple<appinfo::RunningStatus, QString, bool> AppInfoManager::runningStatus(
bool launchingTimeout = false;
QString launchingInstName;
auto appInfo = appInfos.value(appId);
for (const auto &instance : appInfo.instances()) {
auto instances = appInfo.instances();
for (const auto &instance : qAsConst(instances)) {
if (args.isEmpty()) {
if (instance.appRunningStaus == appinfo::RunningStatus::Running) {
return std::make_tuple(appinfo::RunningStatus::Running, instance.instName, false);
@ -286,6 +287,73 @@ void AppInfoManager::updateWakeupHoverButtonStatus(const bool &isWakeupBtn)
m_isWakeupHoverButton = isWakeupBtn;
}
QString AppInfoManager::inhibit(const QString &desktopFile,
uint pid,
const QString &reason,
uint flags)
{
QString appId = appIdByDesktopFile(desktopFile);
if (appId.isEmpty()) {
return QString();
}
if (flags & inhibitor::FrozenInhibitor) {
thawApp((int)pid);
QByteArray srcData = QString(appId +
QString::number(QDateTime::currentMSecsSinceEpoch()) + QString::number(pid)).toLocal8Bit();
QString cookie = QCryptographicHash::hash(srcData, QCryptographicHash::Md5).toHex().constData();
qInfo() << "Add frozen inhibitor," << desktopFile << pid << reason;
m_inhibitors.push_back({ appId, cookie, (int)pid, inhibitor::FrozenInhibitor });
return cookie;
}
return QString();
}
void AppInfoManager::unInhibit(const QString &cookie)
{
QString appId;
appinfo::AppInstance appInstance;
for (int i=0; i<m_inhibitors.count(); ++i) {
if (m_inhibitors.at(i).cookie == cookie) {
appId = m_inhibitors.at(i).appId;
appInstance = appInstanceWithPid(m_inhibitors.at(i).pid);
m_inhibitors.removeAt(i);
break;
}
}
if (appId.isEmpty()) {
return;
}
m_appStatusManager->appStatusTimeOutCallback({ appId, appInstance.instName, appInstance.appStatus });
}
bool AppInfoManager::isInhibited(const QString &appId, const QString &instName)
{
for (auto &inhibitor : qAsConst(m_inhibitors)) {
if (appId != inhibitor.appId) {
continue;
}
int pid = inhibitor.pid;
auto ret = iterateThroughAppInstances([pid](const appinfo::AppInstance &instance)->bool {
return instance.pids.contains(pid);
});
if (ret.first.isEmpty()) {
continue;
}
if (ret.second.instName == instName) {
return true;
}
}
return false;
}
bool AppInfoManager::ThawApps()
{
return m_appStatusManager->ThawApps();
}
void AppInfoManager::onActiveWindowChanged(quint32 currentWid,
int currentPid,
quint32 preWid,
@ -306,9 +374,6 @@ void AppInfoManager::onActiveWindowChanged(quint32 currentWid,
if (currentApp.second == preApp.second) {
return;
}
qDebug() << current_func << currentApp.second << preApp.second;
bool preAppIsHidden = appInfos.value(preApp.first).appInstanceIsHidden(preApp.second);
m_appStatusManager->activeAppChanged(currentApp.first, currentApp.second,
preApp.first, preApp.second,
@ -328,14 +393,17 @@ void AppInfoManager::onWindowAdded(quint32 wid, int pid)
QString appCmdline = cmdline(pid);
if (appCmdline.startsWith(kKmreAppMainWindow)) {
QString androidAppName = findAndroidNameByWid(wid);
QString fullDesktopName = desktopFullFilename(androidAppName);
QString appId = appIdByDesktopFile(fullDesktopName);
// appInfos 包含kmre应用
if (appInfos.contains(appId)) {
updateAppInfomations(fullDesktopName, wid, pid);
if (androidAppName.isEmpty()) {
androidAppName = findAndroidNameByPid(pid);
}
if (androidAppName.isEmpty()) {
qWarning() << current_func << "androidAppName is empty!" << wid << pid;
return;
}
// appInfos 不包含kmre应用
QString fullDesktopName = desktopFullFilename(androidAppName);
QString appId = appIdByDesktopFile(fullDesktopName);
// kmre应用主进程被gio拉起来后就finish掉了只留下kmre窗口进程
addAppInfomations(fullDesktopName, appCmdline, wid, pid);
return;
}
@ -351,8 +419,10 @@ void AppInfoManager::onWindowAdded(quint32 wid, int pid)
QString cgroupName = m_appStatusManager->cgroupWithPid(pid);
if (!cgroupName.isEmpty()) {
appIdInstance = appInstanceInfoWithInstName(cgroupName);
updateInstanceInfos(appIdInstance, wid, pid);
return;
if (!appIdInstance.first.isEmpty()) {
updateInstanceInfos(appIdInstance, wid, pid);
return;
}
}
// 匹配cmdline
@ -364,7 +434,7 @@ void AppInfoManager::onWindowAdded(quint32 wid, int pid)
// 匹配全局desktop
QString desktopFile = findGlobalDesktopFile(appCmdline);
if (desktopFile.isEmpty()) {
if (!desktopFile.isEmpty()) {
addAppInfomations(desktopFile, appCmdline, wid, pid);
return;
}
@ -387,6 +457,7 @@ void AppInfoManager::onWindowAdded(quint32 wid, int pid)
void AppInfoManager::onWindowRemoved(quint32 wid)
{
qWarning() << current_func << wid;
if (wid == 0) {
qWarning() << current_func << "wid or pid is inValid!" << wid;
return;
@ -508,7 +579,8 @@ QString AppInfoManager::appIdByDesktopFile(const QString &desktopFile) const
qWarning() << current_func << "desktopFile is empty!";
return QString();
}
QFile file(desktopFile);
QString desktopFileName = desktopFullFilename(desktopFile);
QFile file(desktopFileName);
if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
qWarning() << "file open error!" << desktopFile;
file.close();
@ -524,6 +596,24 @@ QString AppInfoManager::appIdByDesktopFile(const QString &desktopFile) const
return QString(hashData.toHex().constData());
}
QString AppInfoManager::desktopFileName(const QString &desktopFile)
{
if (!desktopFile.endsWith(".desktop")) {
return QString();
}
if (!QFile::exists(desktopFile)) {
return desktopFile;
}
auto items = desktopFile.split("/");
if (items.isEmpty()) {
return desktopFile;
}
return items.last();
}
QPair<QString, QStringList> AppInfoManager::desktopFileExec(const QString &desktopFileName)
{
if (desktopFileName.isEmpty()) {
@ -550,7 +640,7 @@ QPair<QString, QStringList> AppInfoManager::desktopFileExec(const QString &deskt
return { exec, execArgs };
}
QString AppInfoManager::desktopFullFilename(const QString &desktopFileName)
QString AppInfoManager::desktopFullFilename(const QString &desktopFileName) const
{
QFile desktopFile(desktopFileName);
if (desktopFile.exists()) {
@ -591,6 +681,14 @@ AppInfoManager::AppIdInstanceName AppInfoManager::appInstanceInfoWithInstName(co
return { ret.first, ret.second.instName };
}
appinfo::AppInstance AppInfoManager::appInstanceWithPid(int pid)
{
auto ret = iterateThroughAppInstances([pid] (const appinfo::AppInstance &instance)->bool {
return instance.pids.contains(pid);
});
return ret.second;
}
QString AppInfoManager::findAndroidNameByWid(const quint32 &wid)
{
if (wid <= 0) {
@ -866,7 +964,7 @@ QList<int> AppInfoManager::findChildrenPids(const int &pid)
}
void AppInfoManager::updateAppInfomations(const QString &fullDesktopName, const quint32 &wid, const int &pid)
{
{
if (fullDesktopName.isEmpty() || wid <= 0 || pid <= 0) {
qWarning() << current_func << "fullDesktopName wid or pid is inValid!" << fullDesktopName << wid << pid;
return;
@ -957,6 +1055,28 @@ void AppInfoManager::updateInstanceInfos(const AppIdInstanceName &appIdInstance,
}
}
QString AppInfoManager::findAndroidNameByPid(const quint32 &pid)
{
if (pid <= 0) {
qWarning() << current_func << "pid is inValid!";
return QString();
}
QString appCmdline = cmdline(pid);
QString startStr = "-p";
QString endStr = "-f";
int startIndex = appCmdline.indexOf(startStr);
int endIndex = appCmdline.indexOf(endStr);
if (startIndex == -1 || endIndex == -1 || startIndex+2 > appCmdline.size() || endIndex-startIndex-2 > appCmdline.size()) {
qWarning() << current_func << "appCmdline index is inValid!" << pid << appCmdline;
return QString();
}
QString androidName = appCmdline.mid(startIndex + 2, endIndex - startIndex - 2).trimmed().split("/").last();
if (!androidName.endsWith(".desktop")) {
androidName.push_back(".desktop");
}
return androidName;
}
QPair<QString, appinfo::AppInstance> AppInfoManager::iterateThroughAppInstances(
const std::function<bool (const appinfo::AppInstance &)> &callback)
{

View File

@ -99,9 +99,21 @@ public:
*/
bool isWakeupHoverButton();
void updateWakeupHoverButtonStatus(const bool &isWakeupBtn);
QString inhibit(const QString &desktopFile,
uint pid,
const QString &reason,
uint flags);
void unInhibit(const QString &cookie);
bool isInhibited(const QString &appId, const QString &instName);
/**
* @brief ThawApps session关机时调用
* @return true
*/
bool ThawApps();
public Q_SLOTS:
void onActiveWindowChanged(quint32 currentWid, int currentPid, quint32 preWid, int prePid);
void onWindowAdded(quint32 wid, int pid);
@ -141,6 +153,8 @@ private:
*/
QString appIdByDesktopFile(const QString &desktopFile) const;
QString desktopFileName(const QString &desktopFile);
/**
* @brief desktopFileExec desktop文件中Exec字段
* @param desktopFileName desktop名称
@ -153,7 +167,7 @@ private:
* @param desktopFileName desktop名称
* @return desktop名称
*/
QString desktopFullFilename(const QString &desktopFileName);
QString desktopFullFilename(const QString &desktopFileName) const;
/**
* @brief appInstanceInfoWithWindowId appId和instName
@ -163,6 +177,7 @@ private:
AppIdInstanceName appInstanceInfoWithWindowId(quint32 wid);
AppIdInstanceName appInstanceInfoWithPid(int pid);
AppIdInstanceName appInstanceInfoWithInstName(const QString &instName);
appinfo::AppInstance appInstanceWithPid(int pid);
/**
* @brief findAndroidNameByWid kmre接口通过wid找到对应移动android包名
@ -235,12 +250,22 @@ private:
*/
void updateInstanceInfos(const AppIdInstanceName &appIdInstance, const quint32 &wid, const int &pid);
QString findAndroidNameByPid(const quint32 &pid);
// <appid, app instance>
QPair<QString, appinfo::AppInstance> iterateThroughAppInstances(
const std::function<bool(const appinfo::AppInstance &instance)> &callback);
private:
typedef QMap<QString, appinfo::AppInfo> AppInformation;
struct Inhibitor
{
QString appId;
QString cookie;
int pid;
inhibitor::Inhibitor type;
};
AppInformation appInfos;
QMap<int, QString> m_tmpMprisDbus;
AppStatusManager *m_appStatusManager;
@ -251,6 +276,7 @@ private:
const QString m_hoverAppJsonFile;
QJsonObject m_hoverAppsJsonObj;
bool m_isWakeupHoverButton;
QList<Inhibitor> m_inhibitors;
const QString kKmreAppMainWindow = "/usr/bin/kylin-kmre-window";
const QStringList hoverAppLists = {
"wps-office-prometheus.desktop",
@ -261,6 +287,8 @@ private:
"wps-office-wpp.desktop",
"qaxbrowser-safe.desktop"
};
const QStringList kNoCgroupApps = {
};
};
#endif // APPINFOMANAGER_H

View File

@ -20,10 +20,6 @@
#include "eventwatcher.h"
#include <unistd.h>
#define CGROUP_FREEZE "cgroup.freeze"
#define CPU_WEIGHT "cpu.weight"
#define IO_WEIGHT "io.weight"
AppStatusManager::AppStatusManager(AppInfoManager *parent)
: QObject(parent)
, m_timerWheel(new timerwheel::TimerWheel(this))
@ -46,7 +42,8 @@ bool AppStatusManager::deleteAppCGroup(const QString &cgroupName)
m_cgroupInfo.remove(cgroupName);
auto it = m_appInfoManager->appInfos.constBegin();
while (it != m_appInfoManager->appInfos.constEnd()) {
for (auto const &instance : it.value().instances()) {
auto instances = it.value().instances();
for (auto const &instance : qAsConst(instances)) {
if (instance.cgroupName == cgroupName) {
m_timerWheel->deleteTimer(instance.timerId);
m_appInfoManager->appInfos[it.key()].setInstanceTimerId(cgroupName, 0);
@ -79,7 +76,7 @@ void AppStatusManager::activeAppChanged(const QString &currentAppId,
m_timerWheel->deleteTimer(currentAppInfo.instanceTimerId(currentInstName));
auto currentAppStatus = currentAppInfo.instanceStatus(currentInstName);
if (currentAppStatus == m_policy->suspendStatus() || currentAppStatus == m_policy->frozenStatus()) {
setProcessResourceValue(currentAppInfo.desktopFile(), currentInstName, CGROUP_FREEZE, 0);
setProcessResourceValue(currentAppId, currentAppInfo.desktopFile(), currentInstName, CGROUP_FREEZE, 0);
}
if (m_cgroupInfo.contains(currentInstName)) {
@ -88,7 +85,8 @@ void AppStatusManager::activeAppChanged(const QString &currentAppId,
while (it != values.constEnd()) {
int defaultValue = m_policy->defaultCGroupVale(it.key());
if (it.value() != defaultValue) {
setProcessResourceValue(currentAppInfo.desktopFile(),
setProcessResourceValue(currentAppId,
currentAppInfo.desktopFile(),
currentInstName,
it.key(), defaultValue);
m_cgroupInfo[currentInstName][it.key()] = defaultValue;
@ -103,7 +101,7 @@ void AppStatusManager::activeAppChanged(const QString &currentAppId,
bool isTabletMode = EventWatcher::isTabletMode();
auto &preAppInfo = m_appInfoManager->appInfos[preAppId];
auto preAppStatus = m_policy->appStatus(false, preAppMinimized);
preAppInfo.setInstanceStatus(currentInstName, preAppStatus);
preAppInfo.setInstanceStatus(preInstName, preAppStatus);
timerwheel::AppData appData { preAppId, preInstName, m_policy->nextAppStatus(preAppStatus) };
auto timerId = m_timerWheel->addTimer(m_policy->statusSwitchInterval(), appData,
std::bind(&AppStatusManager::appStatusTimeOutCallback,
@ -130,7 +128,7 @@ void AppStatusManager::appStatusTimeOutCallback(timerwheel::AppData appData)
{
qDebug() << current_func << appData.appId << appData.dstStatus << appData.instName;
if (!m_appInfoManager->appInfos.contains(appData.appId)) {
qWarning() << current_func << " Does not contain the app info, app id " << appData.appId;
qWarning() << current_func << "Does not contain the app info, app id " << appData.appId;
return;
}
@ -138,7 +136,7 @@ void AppStatusManager::appStatusTimeOutCallback(timerwheel::AppData appData)
bool isTabletMode = EventWatcher::isTabletMode();
appInfo.setInstanceStatus(appData.instName, appData.dstStatus);
if (isTabletMode && appData.dstStatus == m_policy->frozenStatus()) {
setProcessResourceValue(appInfo.desktopFile(), appData.instName, CGROUP_FREEZE, 1);
setProcessResourceValue(appData.appId, appInfo.desktopFile(), appData.instName, CGROUP_FREEZE, 1);
}
if (appData.dstStatus != m_policy->lastStatus()) {
@ -154,9 +152,11 @@ void AppStatusManager::tabletModeChanged(bool isTablet)
{
int freeze = isTablet ? 1 : 0;
for (auto &appInfo : m_appInfoManager->appInfos) {
for (auto const &instance : appInfo.instances()) {
auto instances = appInfo.instances();
for (auto const &instance : qAsConst(instances)) {
if (instance.appStatus == m_policy->frozenStatus()) {
setProcessResourceValue(appInfo.desktopFile(), instance.cgroupName, CGROUP_FREEZE, freeze);
setProcessResourceValue(appInfo.appId(), appInfo.desktopFile(),
instance.cgroupName, CGROUP_FREEZE, freeze);
}
}
}
@ -170,7 +170,7 @@ QString AppStatusManager::cgroupWithPid(int pid)
bool AppStatusManager::thawApp(const QString &appId, const QString &cgroupName)
{
if (!m_appInfoManager->appInfos.contains(appId)) {
qWarning() << current_func << "appInfos is not contains " << appId << cgroupName;
qWarning() << current_func << "appInfos dose not contains " << appId << cgroupName;
return false;
}
QString desktopFile = m_appInfoManager->appInfos.value(appId).desktopFile();
@ -179,7 +179,7 @@ bool AppStatusManager::thawApp(const QString &appId, const QString &cgroupName)
if (m_whiteListManager.isExists(desktop, "AppManager")) {
return true;
}
return setProcessResourceValue(desktopFile, cgroupName, CGROUP_FREEZE, 0);
return setProcessResourceValue(appId, desktopFile, cgroupName, CGROUP_FREEZE, 0);
}
void AppStatusManager::aboutToQuitApp()
@ -190,7 +190,8 @@ void AppStatusManager::aboutToQuitApp()
while (it != m_appInfoManager->appInfos.constEnd()) {
for (auto &instance : it.value().instances()) {
if (instance.appStatus == Policy::CachedAppAdj && isTabletMode) {
setProcessResourceValue(it->desktopFile(), instance.cgroupName,
setProcessResourceValue(it->appId(), it->desktopFile(),
instance.cgroupName,
CGROUP_FREEZE, 0);
}
}
@ -204,6 +205,23 @@ void AppStatusManager::initConnections()
this, &AppStatusManager::updateWhitelistAppStatus);
}
bool AppStatusManager::ThawApps()
{
qWarning() << "shut down and unfreeze all apps";
auto it = m_appInfoManager->appInfos.constBegin();
while (it != m_appInfoManager->appInfos.constEnd()) {
for (auto &instance : it.value().instances()) {
if (instance.appStatus == Policy::CachedAppAdj || instance.appStatus == Policy::SuspendedAppAdj) {
setProcessResourceValue(it->appId(), it->desktopFile(),
instance.cgroupName,
CGROUP_FREEZE, 0);
}
}
++ it;
}
return true;
}
void AppStatusManager::updateWhitelistAppStatus(QString desktopName)
{
if (desktopName.isEmpty()) {
@ -217,52 +235,57 @@ void AppStatusManager::updateWhitelistAppStatus(QString desktopName)
return;
}
auto const &appInfo = m_appInfoManager->appInfos.value(appId);
for (auto const &it : appInfo.instances()) {
setProcessResourceValue(appInfo.desktopFile(), it.cgroupName, CGROUP_FREEZE, m_policy->defaultCGroupVale(CGROUP_FREEZE));
setProcessResourceValue(appInfo.desktopFile(), it.cgroupName, CPU_WEIGHT, m_policy->defaultCGroupVale(CPU_WEIGHT));
setProcessResourceValue(appInfo.desktopFile(), it.cgroupName, IO_WEIGHT, m_policy->defaultCGroupVale(IO_WEIGHT));
auto instances = appInfo.instances();
for (auto const &instance : qAsConst(instances)) {
setProcessResourceValue(appId, appInfo.desktopFile(), instance.cgroupName, CGROUP_FREEZE, m_policy->defaultCGroupVale(CGROUP_FREEZE));
setProcessResourceValue(appId, appInfo.desktopFile(), instance.cgroupName, CPU_WEIGHT, m_policy->defaultCGroupVale(CPU_WEIGHT));
setProcessResourceValue(appId, appInfo.desktopFile(), instance.cgroupName, IO_WEIGHT, m_policy->defaultCGroupVale(IO_WEIGHT));
}
}
void AppStatusManager::resourceThresholdWarning(Policy::Feature resource, Policy::ResourceUrgency level)
{
qDebug() << "resourceThresholdWarning1" << resource << level;
auto actions = m_policy->actions(resource, level);
if (actions.first == -1) {
qDebug() << "resourceThresholdWarning1" << resource << level << actions;
if (actions.isEmpty()) {
qWarning() << "Cat not find any actions when the system resource warning.";
return;
}
qDebug() << actions.first << actions.second;
for (auto &action : qAsConst(actions)) {
if (!action.contains("adjs")) {
qWarning() << current_func << "Get action error when resource threshold warning." << actions;
continue;
}
Policy::AppStatus appStatus = (Policy::AppStatus)actions.first;
auto setProcessValue = [this, appStatus, resource, actions](appinfo::AppInfo &appInfo) {
auto cgroups = appInfo.cgroupNames(appStatus);
auto cgroupValues = actions.second;
for (auto const &cgroup : qAsConst(cgroups)) {
auto it = cgroupValues.constBegin();
while (it != cgroupValues.constEnd()) {
if (it.key() == "adjs") {
Policy::AppStatus appStatus = static_cast<Policy::AppStatus>(action.value("adjs"));
for (auto &appInfo : m_appInfoManager->appInfos) {
auto cgroups = appInfo.cgroupNames(appStatus);
if (cgroups.isEmpty()) {
continue;
}
auto cgroupValues = action;
for (auto &cgroup : qAsConst(cgroups)) {
auto it = cgroupValues.constBegin();
while (it != cgroupValues.constEnd()) {
if (it.key() == "adjs") {
++ it;
continue;
}
qDebug() << cgroup << it.key() << it.value();
bool ret = setProcessResourceValue(appInfo.appId(), appInfo.desktopFile(), cgroup,
it.key(), it.value());
if (ret) {
m_cgroupInfo[cgroup].insert(it.key(), it.value());
}
if (resource == Policy::Memory) {
appInfo.setInstanceStatus(cgroup, m_policy->suspendStatus());
m_appCGroup->reclaimProcesses(cgroup);
}
++ it;
continue;
}
qDebug() << cgroup << it.key() << it.value();
bool ret = setProcessResourceValue(appInfo.desktopFile(), cgroup,
it.key(), it.value());
if (ret) {
m_cgroupInfo[cgroup].insert(it.key(), it.value());
}
if (resource == Policy::Memory) {
appInfo.setInstanceStatus(cgroup, m_policy->suspendStatus());
m_appCGroup->reclaimProcesses(cgroup);
}
++ it;
}
}
};
for (auto &appInfo : m_appInfoManager->appInfos) {
setProcessValue(appInfo);
}
}
@ -313,12 +336,17 @@ void AppStatusManager::callMprisDbus(const QString &dbusService)
}
}
bool AppStatusManager::setProcessResourceValue(const QString &desktopFile,
bool AppStatusManager::setProcessResourceValue(const QString &appId,
const QString &desktopFile,
const QString &cgroupName,
const QString &attrName,
int value)
{
qDebug() << current_func << desktopFile << cgroupName;
if (m_appInfoManager->isInhibited(appId, cgroupName) &&
attrName == CGROUP_FREEZE && value == 1) {
return false;
}
QStringList strList = desktopFile.split("/");
QString desktop = strList.isEmpty() ? desktopFile : strList.constLast();
if (m_whiteListManager.isExists(desktop, "AppManager")) {

View File

@ -77,12 +77,15 @@ public:
void initConnections();
bool ThawApps();
private Q_SLOTS:
void updateWhitelistAppStatus(QString desktopName);
private:
void callMprisDbus(const QString &dbusService);
bool setProcessResourceValue(const QString &desktopFile,
bool setProcessResourceValue(const QString &appId,
const QString &desktopFile,
const QString &cgroupName,
const QString &attrName,
int value);

View File

@ -95,22 +95,31 @@ Policy::AppStatus Policy::suspendStatus() const
return SuspendedAppAdj;
}
QPair<int, QMap<QString, int>> Policy::actions(Feature feat, ResourceUrgency urgency)
QList<QMap<QString, int>> Policy::actions(Feature feat, ResourceUrgency urgency)
{
if (!m_actions.contains(feat)) {
return QPair<int, QMap<QString, int>> { -1, QMap<QString, int>() };
return QList<QMap<QString, int>>();
}
auto appStatus = m_actions.value(feat).value(urgency).value("adjs");
return QPair<int, QMap<QString, int>> { (int)appStatus, m_actions.value(feat).value(urgency) };
QList<QMap<QString, int>> actions;
int nUrg = urgency;
do {
actions.push_back(m_actions.value(feat).value((ResourceUrgency)nUrg));
} while(--nUrg >= 0);
return actions;
}
int Policy::defaultCGroupVale(const QString &name)
{
if (name == "cgroup.freeze") {
if (name == CGROUP_FREEZE) {
return 0;
}
if (name == CPU_MAX) {
return 100000;
}
if (name.endsWith("weight")) {
return 100;
}

View File

@ -26,6 +26,17 @@
#include <QMap>
#endif
#define CGROUP_FREEZE "cgroup.freeze"
#define CPU_WEIGHT "cpu.weight"
#define CPU_MAX "cpu.max"
#define IO_WEIGHT "io.weight"
namespace inhibitor {
enum Inhibitor {
FrozenInhibitor = 1,
};
}
class QFileSystemWatcher;
class Policy : public QObject
{
@ -107,7 +118,7 @@ public:
AppStatus suspendStatus() const;
// <appstatus, >
QPair<int, QMap<QString, int>> actions(Feature feat, ResourceUrgency urgency);
QList<QMap<QString, int>> actions(Feature feat, ResourceUrgency urgency);
int defaultCGroupVale(const QString &name);

View File

@ -1,18 +1,12 @@
/*
* Copyright (C) 2020 The Qt Company Ltd.
* Copyright 2023 KylinSoft Co., Ltd.
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.CGroup.xml -p cgroupinterface -c CGroupInterface
*
* 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 (at your option) any later
* version.
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "cgroupinterface.h"

View File

@ -1,18 +1,12 @@
/*
* Copyright (C) 2020 The Qt Company Ltd.
* Copyright 2023 KylinSoft Co., Ltd.
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp org.ukui.KWin.xml -p kwininterface -c KWinInterface
*
* 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 (at your option) any later
* version.
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "kwininterface.h"

View File

@ -1,17 +1,12 @@
/*
* Copyright 2023 KylinSoft Co., Ltd.
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.statusmanager.interface.xml -p statusmanagerinterface -c StatusManagerInterface
*
* 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 (at your option) any later
* version.
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "statusmanagerinterface.h"

View File

@ -31,9 +31,15 @@ extern "C" {
#include <gio/gappinfo.h>
}
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#define KWIN_SERVICE "org.ukui.KWin"
#else
#define KWIN_SERVICE "org.kde.KWin"
#endif
AppLauncher::AppLauncher(QObject *parent)
: QObject(parent)
, m_kwinInterface(new org::ukui::KWin("org.ukui.KWin", "/KWin",
, m_kwinInterface(new org::ukui::KWin(KWIN_SERVICE, "/KWin",
QDBusConnection::sessionBus(), this))
, m_isWayland(false)
{
@ -290,30 +296,6 @@ QPair<QString, QStringList> AppLauncher::desktopFileExec(const QString &desktopF
}
}
bool AppLauncher::isDesktopFileNoDisplay(const QString &desktopFileName)
{
if (desktopFileName.isEmpty()) {
qWarning() << __FUNCTION__ << "desktopFileName is NULL";
return false;
}
QString fullDesktopName = desktopFullFilename(desktopFileName);
KDesktopFile desktop(fullDesktopName);
QString exec = desktop.entryMap("Desktop Entry").value("NoDisplay");
if (exec.isEmpty()) {
qWarning() << __FUNCTION__ << "NoDisplay is empty!";
return false;
}
exec.remove(QRegExp("%."));
exec.remove(QRegExp("^\""));
exec.remove(QRegExp(" *$"));
exec.remove(QRegExp("\""));
if (exec == "true") {
return true;
}
return false;
}
bool AppLauncher::hasWindow(const QString &desktopFile)
{
QString fullDesktopName = desktopFullFilename(desktopFile);
@ -432,7 +414,7 @@ bool AppLauncher::doLaunchApp(const QString &desktopFile, const QStringList &arg
appinfo::RunningStatus runningStatus;
QString instName;
bool timeout;
std::tie(runningStatus, instName, timeout) = m_appInfoManager.runningStatus(fullDesktopName, startUpArgs);
std::tie(runningStatus, instName, timeout) = m_appInfoManager.runningStatus(fullDesktopName, args);
switch (runningStatus) {
case appinfo::None: {
launchResult = launchDesktopApp(fullDesktopName, args, exec, startUpArgs);
@ -461,6 +443,7 @@ bool AppLauncher::doLaunchApp(const QString &desktopFile, const QStringList &arg
}
auto wids = m_appInfoManager.wids(fullDesktopName, instName);
auto pids = m_appInfoManager.pids(fullDesktopName, instName);
qDebug() << "---> " << "app is running " << wids << pids;
if (wids.isEmpty() || pids.isEmpty() || !activeAppWindow(wids.last(), pids)) {
launchResult = launchDesktopApp(fullDesktopName, args, exec, startUpArgs);
} else {
@ -488,8 +471,9 @@ bool AppLauncher::activeAppWindow(quint32 wid, QList<int> pids)
return true;
}
for (auto pid : qAsConst(pids)) {
for (auto &pid : qAsConst(pids)) {
bool ret = m_kwinInterface->activeWindowByPid(pid);
qDebug() << "avtive window ret " <<ret;
if (!ret) {
return false;
}

View File

@ -83,13 +83,6 @@ public:
*/
void setEnvValue(const QByteArray &envValue);
/**
* @brief isDesktopFileNoDisplay desktop文件中的NoDisplay字段
* @param desktopFileName desktop名称
* @return true返回true
*/
bool isDesktopFileNoDisplay(const QString &desktopFileName);
public Q_SLOTS:
void wakeupHoverButton(const QString &name, const QString &binary, const QStringList &args);

View File

@ -95,9 +95,6 @@ AppLauncherDaemon::AppLauncherDaemon(QObject *parent)
void AppLauncherDaemon::chldSignalHandler(int unused)
{
Q_UNUSED(unused)
#ifdef QT_DEBUG
qDebug() << "handle linux signal: " << unused;
#endif
char a = 1;
::write(s_sigChldFd[0], &a, sizeof(a));
}

View File

@ -87,6 +87,14 @@ QStringList AppManagerService::AppWhiteList(const QString &option)
return appLists;
}
QString AppManagerService::Inhibit(const QString &desktopFile, uint pid, const QString &reason, uint flags)
{
// handle method call com.kylin.AppManager.Inhibit
QString cookie;
QMetaObject::invokeMethod(parent(), "Inhibit", Q_RETURN_ARG(QString, cookie), Q_ARG(QString, desktopFile), Q_ARG(uint, pid), Q_ARG(QString, reason), Q_ARG(uint, flags));
return cookie;
}
bool AppManagerService::LaunchApp(const QString &desktopFile)
{
// handle method call com.kylin.AppManager.LaunchApp
@ -141,6 +149,20 @@ void AppManagerService::SetPowerSavingModeEnable(bool enable)
QMetaObject::invokeMethod(parent(), "SetPowerSavingModeEnable", Q_ARG(bool, enable));
}
bool AppManagerService::ThawApps()
{
// handle method call com.kylin.AppManager.ThawApps
bool succeed;
QMetaObject::invokeMethod(parent(), "ThawApps", Q_RETURN_ARG(bool, succeed));
return succeed;
}
void AppManagerService::UnInhibit(const QString &cookie)
{
// handle method call com.kylin.AppManager.UnInhibit
QMetaObject::invokeMethod(parent(), "UnInhibit", Q_ARG(QString, cookie));
}
QStringList AppManagerService::WhiteListsOfApp(const QString &desktopFile)
{
// handle method call com.kylin.AppManager.WhiteListsOfApp

View File

@ -96,6 +96,19 @@ class AppManagerService: public QDBusAbstractAdaptor
" <arg direction=\"in\" type=\"s\" name=\"fileName\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"succeed\"/>\n"
" </method>\n"
" <method name=\"Inhibit\">\n"
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
" <arg direction=\"in\" type=\"u\" name=\"pid\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"reason\"/>\n"
" <arg direction=\"in\" type=\"u\" name=\"flags\"/>\n"
" <arg direction=\"out\" type=\"s\" name=\"cookie\"/>\n"
" </method>\n"
" <method name=\"UnInhibit\">\n"
" <arg direction=\"in\" type=\"s\" name=\"cookie\"/>\n"
" </method>\n"
" <method name=\"ThawApps\">\n"
" <arg direction=\"out\" type=\"b\" name=\"succeed\"/>\n"
" </method>\n"
" <signal name=\"appLaunched\">\n"
" <arg type=\"s\" name=\"desktopNmae\"/>\n"
" <arg type=\"x\" name=\"pid\"/>\n"
@ -120,6 +133,7 @@ public Q_SLOTS: // METHODS
QString AppDesktopFileNameByPid(qlonglong pid);
QString AppDesktopFileNameByWid(qlonglong wid);
QStringList AppWhiteList(const QString &option);
QString Inhibit(const QString &desktopFile, uint pid, const QString &reason, uint flags);
bool LaunchApp(const QString &desktopFile);
bool LaunchAppWithArguments(const QString &desktopFile, const QStringList &args);
bool LaunchDefaultAppWithUrl(const QString &url);
@ -127,6 +141,8 @@ public Q_SLOTS: // METHODS
QVector <QStringList> RecommendAppLists(const QString &fileName);
bool RemoveFromWhiteList(const QString &desktopFile, const QString &option);
void SetPowerSavingModeEnable(bool enable);
bool ThawApps();
void UnInhibit(const QString &cookie);
QStringList WhiteListsOfApp(const QString &desktopFile);
Q_SIGNALS: // SIGNALS
void appFinished(const QString &desktopNmae, qlonglong pid, uint wid);

View File

@ -60,6 +60,19 @@
<method name="Open">
<arg name="fileName" type="s" direction="in"></arg>
<arg name="succeed" type="b" direction="out"></arg>
</method>
<method name="Inhibit">
<arg name="desktopFile" type="s" direction="in"></arg>
<arg name="pid" type="u" direction="in"></arg>
<arg name="reason" type="s" direction="in"></arg>
<arg name="flags" type="u" direction="in"></arg>
<arg name="cookie" type="s" direction="out"></arg>
</method>
<method name="UnInhibit">
<arg name="cookie" type="s" direction="in"></arg>
</method>
<method name="ThawApps">
<arg name="succeed" type="b" direction="out"></arg>
</method>
<signal name= "appLaunched">
<arg name="desktopNmae" type="s" />

View File

@ -24,7 +24,7 @@
#include "ukui-log4qt.h"
#endif
int mzain(int argc, char *argv[])
int main(int argc, char *argv[])
{
QByteArray sessionEnvValue = qgetenv("SESSION_MANAGER");
qunsetenv("SESSION_MANAGER");