Refactor macOS startup code
Moves all the stuff that is needed to start DBus on macOS (which for some reason it needs several steps, involving the use of `launchctl`) into a single `startDBusDaemon()` function. Before, it was spread into `kdeconnectconfig.cpp`, `indicatorhelper_mac.cpp` and `dbushelper.cpp`. It also removes checking for an existing DBus daemon and always starts our own, since in most cases we couldn't connect to it anyway. This, together with removing the sleep in the retries when polling for the DBus daemon from 3s to 100ms, makes the startup much faster, so I removed the loading splash screen.
This commit is contained in:
parent
d73cfa15b2
commit
bbcbec7709
12 changed files with 149 additions and 336 deletions
|
@ -1,11 +1,5 @@
|
||||||
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
|
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
|
||||||
|
|
||||||
set(KDECONNECT_PRIVATE_DBUS_ADDR unix:tmpdir=/tmp)
|
|
||||||
if(WIN32)
|
|
||||||
set(KDECONNECT_PRIVATE_DBUS_ADDR tcp:host=localhost,port=0)
|
|
||||||
endif()
|
|
||||||
set(KDECONNECT_PRIVATE_DBUS_NAME DBusKDEConnectOnly)
|
|
||||||
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
|
|
||||||
|
|
||||||
option(MDNS_ENABLED "Use MDNS for device discovery" ON)
|
option(MDNS_ENABLED "Use MDNS for device discovery" ON)
|
||||||
|
|
||||||
|
|
|
@ -18,28 +18,15 @@
|
||||||
#include "kdeconnectconfig.h"
|
#include "kdeconnectconfig.h"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
#include <KLocalizedString>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QThread>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace DBusHelper
|
namespace DBusHelper
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
class DBusInstancePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DBusInstancePrivate();
|
|
||||||
~DBusInstancePrivate();
|
|
||||||
|
|
||||||
void launchDBusDaemon();
|
|
||||||
void closeDBusDaemon();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QProcess *m_dbusProcess;
|
|
||||||
};
|
|
||||||
|
|
||||||
static DBusInstancePrivate dbusInstance;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void filterNonExportableCharacters(QString &s)
|
void filterNonExportableCharacters(QString &s)
|
||||||
{
|
{
|
||||||
|
@ -48,35 +35,56 @@ void filterNonExportableCharacters(QString &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
void launchDBusDaemon()
|
|
||||||
|
const QString PrivateDbusAddr = QStringLiteral("unix:tmpdir=/tmp");
|
||||||
|
const QString PrivateDBusAddressPath = QStringLiteral("/tmp/private_dbus_address");
|
||||||
|
const QString DBUS_LAUNCHD_SESSION_BUS_SOCKET = QStringLiteral("DBUS_LAUNCHD_SESSION_BUS_SOCKET");
|
||||||
|
|
||||||
|
QProcess *m_dbusProcess = nullptr;
|
||||||
|
|
||||||
|
void setLaunchctlEnv(const QString &env)
|
||||||
{
|
{
|
||||||
dbusInstance.launchDBusDaemon();
|
QProcess setLaunchdDBusEnv;
|
||||||
qAddPostRoutine(closeDBusDaemon);
|
setLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
|
||||||
|
setLaunchdDBusEnv.setArguments({QStringLiteral("setenv"), DBUS_LAUNCHD_SESSION_BUS_SOCKET, env});
|
||||||
|
setLaunchdDBusEnv.start();
|
||||||
|
setLaunchdDBusEnv.waitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeDBusDaemon()
|
void unsetLaunchctlEnv()
|
||||||
{
|
{
|
||||||
dbusInstance.closeDBusDaemon();
|
|
||||||
}
|
|
||||||
|
|
||||||
void macosUnsetLaunchctlEnv()
|
|
||||||
{
|
|
||||||
// Unset Launchd env
|
|
||||||
QProcess unsetLaunchdDBusEnv;
|
QProcess unsetLaunchdDBusEnv;
|
||||||
unsetLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
|
unsetLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
|
||||||
unsetLaunchdDBusEnv.setArguments({QStringLiteral("unsetenv"), QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV)});
|
unsetLaunchdDBusEnv.setArguments({QStringLiteral("unsetenv"), DBUS_LAUNCHD_SESSION_BUS_SOCKET});
|
||||||
unsetLaunchdDBusEnv.start();
|
unsetLaunchdDBusEnv.start();
|
||||||
unsetLaunchdDBusEnv.waitForFinished();
|
unsetLaunchdDBusEnv.waitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBusInstancePrivate::launchDBusDaemon()
|
void stopDBusDaemon()
|
||||||
{
|
{
|
||||||
// Kill old dbus daemon
|
if (m_dbusProcess != nullptr) {
|
||||||
if (m_dbusProcess != nullptr)
|
m_dbusProcess->terminate();
|
||||||
closeDBusDaemon();
|
m_dbusProcess->waitForFinished();
|
||||||
|
delete m_dbusProcess;
|
||||||
|
m_dbusProcess = nullptr;
|
||||||
|
unsetLaunchctlEnv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start dbus daemon
|
int startDBusDaemon()
|
||||||
m_dbusProcess = new QProcess();
|
{
|
||||||
|
if (m_dbusProcess) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qAddPostRoutine(stopDBusDaemon);
|
||||||
|
|
||||||
|
// Unset launchctl env and private dbus addr file, avoid block
|
||||||
|
unsetLaunchctlEnv();
|
||||||
|
QFile privateDBusAddressFile(PrivateDBusAddressPath);
|
||||||
|
if (privateDBusAddressFile.exists()) {
|
||||||
|
privateDBusAddressFile.resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
QString kdeconnectDBusConfiguration;
|
QString kdeconnectDBusConfiguration;
|
||||||
QString dbusDaemonExecutable = QStandardPaths::findExecutable(QStringLiteral("dbus-daemon"), {QCoreApplication::applicationDirPath()});
|
QString dbusDaemonExecutable = QStandardPaths::findExecutable(QStringLiteral("dbus-daemon"), {QCoreApplication::applicationDirPath()});
|
||||||
|
@ -87,60 +95,70 @@ void DBusInstancePrivate::launchDBusDaemon()
|
||||||
dbusDaemonExecutable = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../bin/dbus-daemon");
|
dbusDaemonExecutable = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../bin/dbus-daemon");
|
||||||
kdeconnectDBusConfiguration = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../share/dbus-1/session.conf");
|
kdeconnectDBusConfiguration = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../share/dbus-1/session.conf");
|
||||||
}
|
}
|
||||||
|
m_dbusProcess = new QProcess();
|
||||||
m_dbusProcess->setProgram(dbusDaemonExecutable);
|
m_dbusProcess->setProgram(dbusDaemonExecutable);
|
||||||
m_dbusProcess->setArguments({QStringLiteral("--print-address"),
|
m_dbusProcess->setArguments({QStringLiteral("--print-address"),
|
||||||
QStringLiteral("--nofork"),
|
QStringLiteral("--nofork"),
|
||||||
QStringLiteral("--config-file=") + kdeconnectDBusConfiguration,
|
QStringLiteral("--config-file"),
|
||||||
QStringLiteral("--address=") + QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR)});
|
kdeconnectDBusConfiguration,
|
||||||
|
QStringLiteral("--address"),
|
||||||
|
PrivateDbusAddr});
|
||||||
m_dbusProcess->setWorkingDirectory(QCoreApplication::applicationDirPath());
|
m_dbusProcess->setWorkingDirectory(QCoreApplication::applicationDirPath());
|
||||||
m_dbusProcess->setStandardOutputFile(KdeConnectConfig::instance().privateDBusAddressPath());
|
m_dbusProcess->setStandardOutputFile(PrivateDBusAddressPath);
|
||||||
m_dbusProcess->setStandardErrorFile(QProcess::nullDevice());
|
|
||||||
m_dbusProcess->start();
|
m_dbusProcess->start();
|
||||||
m_dbusProcess->waitForStarted(); // Avoid potential racing condition
|
m_dbusProcess->waitForStarted();
|
||||||
|
|
||||||
|
QFile dbusAddressFile(PrivateDBusAddressPath);
|
||||||
|
|
||||||
|
if (!dbusAddressFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
|
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but error read private dbus address conf";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream in(&dbusAddressFile);
|
||||||
|
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Waiting for private dbus";
|
||||||
|
|
||||||
|
int retry = 0;
|
||||||
|
QString addr = in.readLine();
|
||||||
|
while (addr.length() == 0 && retry < 150) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Retry reading private DBus address";
|
||||||
|
QThread::msleep(100);
|
||||||
|
retry++;
|
||||||
|
addr = in.readLine(); // Read until first not empty line
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr.length() == 0) {
|
||||||
|
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but read private dbus address failed";
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Private dbus address: " << addr;
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
// Set launchctl env
|
|
||||||
QString privateDBusAddress = KdeConnectConfig::instance().privateDBusAddress();
|
|
||||||
QRegularExpressionMatch path;
|
QRegularExpressionMatch path;
|
||||||
if (privateDBusAddress.contains(QRegularExpression(QStringLiteral("path=(?<path>/tmp/dbus-[A-Za-z0-9]+)")), &path)) {
|
if (!addr.contains(QRegularExpression(QStringLiteral("path=(?<path>/tmp/dbus-[A-Za-z0-9]+)")), &path)) {
|
||||||
qCDebug(KDECONNECT_CORE) << "DBus address: " << path.captured(QStringLiteral("path"));
|
qCCritical(KDECONNECT_CORE) << "Fail to parse dbus address";
|
||||||
QProcess setLaunchdDBusEnv;
|
return -3;
|
||||||
setLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
|
|
||||||
setLaunchdDBusEnv.setArguments({QStringLiteral("setenv"), QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV), path.captured(QStringLiteral("path"))});
|
|
||||||
setLaunchdDBusEnv.start();
|
|
||||||
setLaunchdDBusEnv.waitForFinished();
|
|
||||||
} else {
|
|
||||||
qCDebug(KDECONNECT_CORE) << "Cannot get dbus address";
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBusInstancePrivate::closeDBusDaemon()
|
QString dbusAddress = path.captured(QStringLiteral("path"));
|
||||||
{
|
qCDebug(KDECONNECT_CORE) << "DBus address: " << dbusAddress;
|
||||||
if (m_dbusProcess != nullptr) {
|
if (dbusAddress.isEmpty()) {
|
||||||
m_dbusProcess->terminate();
|
qCCritical(KDECONNECT_CORE) << "Fail to extract dbus address";
|
||||||
m_dbusProcess->waitForFinished();
|
return -4;
|
||||||
delete m_dbusProcess;
|
|
||||||
m_dbusProcess = nullptr;
|
|
||||||
|
|
||||||
QFile privateDBusAddressFile(KdeConnectConfig::instance().privateDBusAddressPath());
|
|
||||||
|
|
||||||
if (privateDBusAddressFile.exists())
|
|
||||||
privateDBusAddressFile.resize(0);
|
|
||||||
|
|
||||||
macosUnsetLaunchctlEnv();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLaunchctlEnv(dbusAddress);
|
||||||
|
|
||||||
|
if (!QDBusConnection::sessionBus().isConnected()) {
|
||||||
|
qCCritical(KDECONNECT_CORE) << "Invalid env:" << dbusAddress;
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Private D-Bus daemon launched and connected.";
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBusInstancePrivate::DBusInstancePrivate()
|
#endif // Q_OS_MAC
|
||||||
: m_dbusProcess(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DBusInstancePrivate::~DBusInstancePrivate()
|
} // namespace DBusHelper
|
||||||
{
|
|
||||||
closeDBusDaemon();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
20
core/dbushelper.h
Normal file
20
core/dbushelper.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2024 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "kdeconnectcore_export.h"
|
||||||
|
|
||||||
|
namespace DBusHelper
|
||||||
|
{
|
||||||
|
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString &s);
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
int KDECONNECTCORE_EXPORT startDBusDaemon();
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
/**
|
|
||||||
* SPDX-FileCopyrightText: 2014 Albert Vaca <albertvaka@gmail.com>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef KDECONNECT_DBUSHELPER_H
|
|
||||||
#define KDECONNECT_DBUSHELPER_H
|
|
||||||
#include <QString>
|
|
||||||
#include <QDBusConnection>
|
|
||||||
|
|
||||||
#include "kdeconnectcore_export.h"
|
|
||||||
|
|
||||||
#define KDECONNECT_PRIVATE_DBUS_ADDR "${KDECONNECT_PRIVATE_DBUS_ADDR}"
|
|
||||||
#define KDECONNECT_PRIVATE_DBUS_NAME "${KDECONNECT_PRIVATE_DBUS_NAME}"
|
|
||||||
|
|
||||||
#define KDECONNECT_SESSION_DBUS_LAUNCHD_ENV "DBUS_LAUNCHD_SESSION_BUS_SOCKET"
|
|
||||||
|
|
||||||
namespace DBusHelper {
|
|
||||||
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s);
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
void KDECONNECTCORE_EXPORT launchDBusDaemon();
|
|
||||||
void KDECONNECTCORE_EXPORT closeDBusDaemon();
|
|
||||||
void KDECONNECTCORE_EXPORT macosUnsetLaunchctlEnv();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -35,10 +35,6 @@ struct KdeConnectConfigPrivate {
|
||||||
|
|
||||||
QSettings *m_config;
|
QSettings *m_config;
|
||||||
QSettings *m_trustedDevices;
|
QSettings *m_trustedDevices;
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QString m_privateDBusAddress; // Private DBus Address cache
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static QString getDefaultDeviceName()
|
static QString getDefaultDeviceName()
|
||||||
|
@ -381,48 +377,3 @@ void KdeConnectConfig::generateCertificate(const QString &certPath)
|
||||||
Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath));
|
Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QString KdeConnectConfig::privateDBusAddressPath()
|
|
||||||
{
|
|
||||||
return baseConfigDir().absoluteFilePath(QStringLiteral("private_dbus_address"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString KdeConnectConfig::privateDBusAddress()
|
|
||||||
{
|
|
||||||
if (d->m_privateDBusAddress.length() != 0)
|
|
||||||
return d->m_privateDBusAddress;
|
|
||||||
|
|
||||||
QString dbusAddressPath = privateDBusAddressPath();
|
|
||||||
QFile dbusAddressFile(dbusAddressPath);
|
|
||||||
|
|
||||||
if (!dbusAddressFile.open(QFile::ReadOnly | QFile::Text)) {
|
|
||||||
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but error read private dbus address conf";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream in(&dbusAddressFile);
|
|
||||||
|
|
||||||
qCDebug(KDECONNECT_CORE) << "Waiting for private dbus";
|
|
||||||
|
|
||||||
int retry = 0;
|
|
||||||
QString addr = in.readLine();
|
|
||||||
while (addr.length() == 0 && retry < 5) {
|
|
||||||
qCDebug(KDECONNECT_CORE) << "Retry reading private DBus address after 3s";
|
|
||||||
QThread::sleep(3);
|
|
||||||
retry++;
|
|
||||||
addr = in.readLine(); // Read until first not empty line
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr.length() == 0) {
|
|
||||||
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but read private dbus address failed";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(KDECONNECT_CORE) << "Private dbus address: " << addr;
|
|
||||||
|
|
||||||
d->m_privateDBusAddress = addr;
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -61,13 +61,6 @@ public:
|
||||||
QDir deviceConfigDir(const QString &deviceId);
|
QDir deviceConfigDir(const QString &deviceId);
|
||||||
QDir pluginConfigDir(const QString &deviceId, const QString &pluginName); // Used by KdeConnectPluginConfig
|
QDir pluginConfigDir(const QString &deviceId, const QString &pluginName); // Used by KdeConnectPluginConfig
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
/*
|
|
||||||
* Get private DBus Address when use private DBus
|
|
||||||
*/
|
|
||||||
QString privateDBusAddressPath();
|
|
||||||
QString privateDBusAddress();
|
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
KdeConnectConfig();
|
KdeConnectConfig();
|
||||||
|
|
||||||
|
|
|
@ -86,19 +86,10 @@ int main(int argc, char *argv[])
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
||||||
parser.addOption(replaceOption);
|
parser.addOption(replaceOption);
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QCommandLineOption macosPrivateDBusOption({QStringLiteral("use-private-dbus")},
|
|
||||||
i18n("Launch a private D-Bus daemon with kdeconnectd (macOS test-purpose only)"));
|
|
||||||
parser.addOption(macosPrivateDBusOption);
|
|
||||||
#endif
|
|
||||||
aboutData.setupCommandLine(&parser);
|
aboutData.setupCommandLine(&parser);
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
if (parser.isSet(macosPrivateDBusOption)) {
|
|
||||||
DBusHelper::launchDBusDaemon();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
aboutData.processCommandLine(&parser);
|
aboutData.processCommandLine(&parser);
|
||||||
if (parser.isSet(replaceOption)) {
|
if (parser.isSet(replaceOption)) {
|
||||||
auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"),
|
auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"),
|
||||||
|
|
|
@ -12,23 +12,16 @@
|
||||||
IndicatorHelper::IndicatorHelper()
|
IndicatorHelper::IndicatorHelper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IndicatorHelper::~IndicatorHelper()
|
IndicatorHelper::~IndicatorHelper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorHelper::preInit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::postInit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::iconPathHook()
|
void IndicatorHelper::iconPathHook()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int IndicatorHelper::daemonHook(QProcess & /*kdeconnectd*/)
|
int IndicatorHelper::startDaemon()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
#ifndef INDICATORHELPER_H
|
#ifndef INDICATORHELPER_H
|
||||||
#define INDICATORHELPER_H
|
#define INDICATORHELPER_H
|
||||||
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QSplashScreen>
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#else
|
#else
|
||||||
|
@ -17,6 +14,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QProcess>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
namespace processes
|
namespace processes
|
||||||
{
|
{
|
||||||
|
@ -32,19 +30,12 @@ const QString kdeconnect_sms = QStringLiteral("kdeconnect-sms.exe");
|
||||||
class IndicatorHelper
|
class IndicatorHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
IndicatorHelper(const QUrl &indicatorUrl);
|
|
||||||
#else
|
|
||||||
IndicatorHelper();
|
IndicatorHelper();
|
||||||
#endif
|
|
||||||
~IndicatorHelper();
|
~IndicatorHelper();
|
||||||
|
|
||||||
void preInit();
|
|
||||||
void postInit();
|
|
||||||
|
|
||||||
void iconPathHook();
|
void iconPathHook();
|
||||||
|
|
||||||
int daemonHook(QProcess &kdeconnectd);
|
int startDaemon();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
void systrayIconHook(QSystemTrayIcon &systray);
|
void systrayIconHook(QSystemTrayIcon &systray);
|
||||||
|
@ -53,11 +44,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QSplashScreen *m_splashScreen;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
QProcess kdeconnectd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminate processes of KDE Connect like kdeconnectd.exe and dbus-daemon.exe
|
* Terminate processes of KDE Connect like kdeconnectd.exe and dbus-daemon.exe
|
||||||
*
|
*
|
||||||
|
|
|
@ -4,55 +4,29 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "indicatorhelper.h"
|
||||||
|
|
||||||
|
#include <KLocalizedString>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QProcess>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
|
||||||
|
|
||||||
#include <dbushelper.h>
|
|
||||||
|
|
||||||
#include "indicatorhelper.h"
|
|
||||||
|
|
||||||
#include "serviceregister_mac.h"
|
#include "serviceregister_mac.h"
|
||||||
|
#include <dbushelper.h>
|
||||||
#include <kdeconnectconfig.h>
|
#include <kdeconnectconfig.h>
|
||||||
|
|
||||||
IndicatorHelper::IndicatorHelper()
|
IndicatorHelper::IndicatorHelper()
|
||||||
{
|
{
|
||||||
registerServices();
|
registerServices();
|
||||||
|
|
||||||
// Use a hardcoded QPixmap because QIcon::fromTheme will instantiate a QPlatformTheme theme
|
|
||||||
// which could try to use DBus before we have started it and cache an invalid DBus session
|
|
||||||
// in QDBusConnectionManager
|
|
||||||
const QString iconPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("kdeconnect-icons"), QStandardPaths::LocateDirectory);
|
|
||||||
QPixmap splashPixmap(iconPath + QStringLiteral("/hicolor/scalable/apps/kdeconnect.svg"));
|
|
||||||
m_splashScreen = new QSplashScreen(splashPixmap);
|
|
||||||
|
|
||||||
// Icon is white, set the text color to black
|
|
||||||
m_splashScreen->showMessage(i18n("Launching") + QStringLiteral("\n"), Qt::AlignHCenter | Qt::AlignBottom, Qt::black);
|
|
||||||
m_splashScreen->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IndicatorHelper::~IndicatorHelper()
|
IndicatorHelper::~IndicatorHelper()
|
||||||
{
|
{
|
||||||
if (m_splashScreen != nullptr) {
|
|
||||||
delete m_splashScreen;
|
|
||||||
m_splashScreen = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::preInit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::postInit()
|
|
||||||
{
|
|
||||||
m_splashScreen->finish(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorHelper::iconPathHook()
|
void IndicatorHelper::iconPathHook()
|
||||||
|
@ -65,86 +39,26 @@ void IndicatorHelper::iconPathHook()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IndicatorHelper::daemonHook(QProcess &kdeconnectd)
|
int IndicatorHelper::startDaemon()
|
||||||
{
|
{
|
||||||
// This flag marks whether a session DBus daemon is installed and run
|
int dbusStatus = DBusHelper::startDBusDaemon();
|
||||||
bool hasUsableSessionBus = true;
|
if (dbusStatus) {
|
||||||
// Use another bus instance for detecting, avoid session bus cache in Qt
|
|
||||||
if (!QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("kdeconnect-test-client")).isConnected()) {
|
|
||||||
qDebug() << "Default session bus not detected, will use private D-Bus.";
|
|
||||||
|
|
||||||
// Unset launchctl env and private dbus addr file, avoid block
|
|
||||||
DBusHelper::macosUnsetLaunchctlEnv();
|
|
||||||
QFile privateDBusAddressFile(KdeConnectConfig::instance().privateDBusAddressPath());
|
|
||||||
if (privateDBusAddressFile.exists())
|
|
||||||
privateDBusAddressFile.resize(0);
|
|
||||||
|
|
||||||
// Update session bus usability state
|
|
||||||
hasUsableSessionBus = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start daemon
|
|
||||||
m_splashScreen->showMessage(i18n("Launching daemon") + QStringLiteral("\n"), Qt::AlignHCenter | Qt::AlignBottom, Qt::black);
|
|
||||||
|
|
||||||
// Here we will try to bring our private session D-Bus
|
|
||||||
if (!hasUsableSessionBus) {
|
|
||||||
qDebug() << "Launching private session D-Bus.";
|
|
||||||
DBusHelper::macosUnsetLaunchctlEnv();
|
|
||||||
DBusHelper::launchDBusDaemon();
|
|
||||||
// Wait for dbus daemon env
|
|
||||||
QProcess getLaunchdDBusEnv;
|
|
||||||
m_splashScreen->showMessage(i18n("Waiting D-Bus") + QStringLiteral("\n"), Qt::AlignHCenter | Qt::AlignBottom, Qt::black);
|
|
||||||
getLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
|
|
||||||
getLaunchdDBusEnv.setArguments({QStringLiteral("getenv"), QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV)});
|
|
||||||
getLaunchdDBusEnv.start();
|
|
||||||
getLaunchdDBusEnv.waitForFinished();
|
|
||||||
|
|
||||||
QString launchdDBusEnv = QString::fromLocal8Bit(getLaunchdDBusEnv.readAllStandardOutput());
|
|
||||||
|
|
||||||
if (!launchdDBusEnv.isEmpty() && QDBusConnection::sessionBus().isConnected()) {
|
|
||||||
qDebug() << "Private D-Bus daemon launched and connected.";
|
|
||||||
hasUsableSessionBus = true;
|
|
||||||
} else if (!launchdDBusEnv.isEmpty()) {
|
|
||||||
// Show a warning and exit
|
|
||||||
qCritical() << "Invalid " << KDECONNECT_SESSION_DBUS_LAUNCHD_ENV << "env: \"" << launchdDBusEnv << "\"";
|
|
||||||
|
|
||||||
QMessageBox::critical(nullptr,
|
QMessageBox::critical(nullptr,
|
||||||
i18n("KDE Connect"),
|
i18n("KDE Connect"),
|
||||||
i18n("Cannot connect to DBus\n"
|
i18n("Cannot connect to DBus\n"
|
||||||
"KDE Connect will quit"),
|
"KDE Connect will quit"),
|
||||||
QMessageBox::Abort,
|
QMessageBox::Abort,
|
||||||
QMessageBox::Abort);
|
QMessageBox::Abort);
|
||||||
// End the program
|
QApplication::exit(dbusStatus);
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
// Show a warning and exit
|
|
||||||
qCritical() << "Fail to get launchctl" << KDECONNECT_SESSION_DBUS_LAUNCHD_ENV << "env";
|
|
||||||
|
|
||||||
QMessageBox::critical(nullptr,
|
|
||||||
i18n("KDE Connect"),
|
|
||||||
i18n("Cannot connect to DBus\n"
|
|
||||||
"KDE Connect will quit"),
|
|
||||||
QMessageBox::Abort,
|
|
||||||
QMessageBox::Abort);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// After D-Bus setting up, everything should go fine
|
|
||||||
QIcon kdeconnectIcon = QIcon::fromTheme(QStringLiteral("kdeconnect"));
|
|
||||||
m_splashScreen->setPixmap(QPixmap(kdeconnectIcon.pixmap(256, 256)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start kdeconnectd, the daemon will not duplicate when there is already one
|
// Start kdeconnectd, the daemon will not duplicate when there is already one
|
||||||
if (QString daemon = QCoreApplication::applicationDirPath() + QLatin1String("/kdeconnectd"); QFile::exists(daemon)) {
|
QString daemonPath = QCoreApplication::applicationDirPath() + QLatin1String("/kdeconnectd");
|
||||||
kdeconnectd.setProgram(daemon);
|
if (!QFile::exists(daemonPath)) {
|
||||||
} else {
|
|
||||||
QMessageBox::critical(nullptr, i18n("KDE Connect"), i18n("Cannot find kdeconnectd"), QMessageBox::Abort, QMessageBox::Abort);
|
QMessageBox::critical(nullptr, i18n("KDE Connect"), i18n("Cannot find kdeconnectd"), QMessageBox::Abort, QMessageBox::Abort);
|
||||||
return -1;
|
QApplication::exit(-10);
|
||||||
}
|
}
|
||||||
kdeconnectd.startDetached();
|
QProcess::startDetached(daemonPath);
|
||||||
|
|
||||||
m_splashScreen->showMessage(i18n("Loading modules") + QStringLiteral("\n"), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
@ -14,17 +15,15 @@
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
#include <winrt/Windows.Foundation.Collections.h>
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
#include <winrt/Windows.UI.ViewManagement.h>
|
#include <winrt/Windows.UI.ViewManagement.h>
|
||||||
|
|
||||||
#include "indicator_debug.h"
|
#include "indicator_debug.h"
|
||||||
#include "indicatorhelper.h"
|
#include "indicatorhelper.h"
|
||||||
|
|
||||||
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
|
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
|
||||||
|
|
||||||
IndicatorHelper::IndicatorHelper(const QUrl &indicatorUrl)
|
IndicatorHelper::IndicatorHelper()
|
||||||
: m_indicatorUrl(indicatorUrl)
|
: m_indicatorUrl(QUrl::fromLocalFile(QApplication::applicationDirPath()))
|
||||||
{
|
{
|
||||||
uiSettings = winrt::Windows::UI::ViewManagement::UISettings();
|
uiSettings = winrt::Windows::UI::ViewManagement::UISettings();
|
||||||
}
|
}
|
||||||
|
@ -39,14 +38,6 @@ IndicatorHelper::~IndicatorHelper()
|
||||||
this->terminateProcess(processes::kdeconnect_daemon, m_indicatorUrl);
|
this->terminateProcess(processes::kdeconnect_daemon, m_indicatorUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorHelper::preInit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::postInit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorHelper::iconPathHook()
|
void IndicatorHelper::iconPathHook()
|
||||||
{
|
{
|
||||||
// FIXME: This doesn't seem to be enough for QIcon::fromTheme to find the icons, so we still have to use the full path when setting the icon
|
// FIXME: This doesn't seem to be enough for QIcon::fromTheme to find the icons, so we still have to use the full path when setting the icon
|
||||||
|
@ -58,7 +49,7 @@ void IndicatorHelper::iconPathHook()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IndicatorHelper::daemonHook(QProcess &kdeconnectd)
|
int IndicatorHelper::startDaemon()
|
||||||
{
|
{
|
||||||
kdeconnectd.start(processes::kdeconnect_daemon, QStringList());
|
kdeconnectd.start(processes::kdeconnect_daemon, QStringList());
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -49,6 +49,10 @@ int main(int argc, char **argv)
|
||||||
QIcon::setFallbackThemeName(QStringLiteral("breeze"));
|
QIcon::setFallbackThemeName(QStringLiteral("breeze"));
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
IndicatorHelper helper;
|
||||||
|
helper.startDaemon();
|
||||||
|
|
||||||
KAboutData about(QStringLiteral("kdeconnect-indicator"),
|
KAboutData about(QStringLiteral("kdeconnect-indicator"),
|
||||||
i18n("KDE Connect Indicator"),
|
i18n("KDE Connect Indicator"),
|
||||||
QStringLiteral(KDECONNECT_VERSION_STRING),
|
QStringLiteral(KDECONNECT_VERSION_STRING),
|
||||||
|
@ -62,20 +66,8 @@ int main(int argc, char **argv)
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
KColorSchemeManager manager;
|
KColorSchemeManager manager;
|
||||||
QApplication::setStyle(QStringLiteral("breeze"));
|
QApplication::setStyle(QStringLiteral("breeze"));
|
||||||
IndicatorHelper helper(QUrl::fromLocalFile(qApp->applicationDirPath()));
|
|
||||||
#else
|
|
||||||
IndicatorHelper helper;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
helper.preInit();
|
|
||||||
|
|
||||||
// Run Daemon initialization step
|
|
||||||
// When run from macOS app bundle, D-Bus call should be later than kdeconnectd and D-Bus daemon
|
|
||||||
QProcess kdeconnectd;
|
|
||||||
if (helper.daemonHook(kdeconnectd)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
KDBusService dbusService(KDBusService::Unique);
|
KDBusService dbusService(KDBusService::Unique);
|
||||||
|
|
||||||
// Trigger loading the KIconLoader plugin
|
// Trigger loading the KIconLoader plugin
|
||||||
|
@ -130,7 +122,6 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
// Add quit menu
|
// Add quit menu
|
||||||
#if defined Q_OS_MAC
|
#if defined Q_OS_MAC
|
||||||
|
|
||||||
menu->addAction(i18n("Quit"), []() {
|
menu->addAction(i18n("Quit"), []() {
|
||||||
auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect.daemon"),
|
auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect.daemon"),
|
||||||
QStringLiteral("/MainApplication"),
|
QStringLiteral("/MainApplication"),
|
||||||
|
@ -194,8 +185,5 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
app.setQuitOnLastWindowClosed(false);
|
app.setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
// Finish init
|
|
||||||
helper.postInit();
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue