bbcbec7709
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.
130 lines
4.9 KiB
C++
130 lines
4.9 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2019 Weixuan XIAO <veyx.shaw@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
*/
|
|
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QFile>
|
|
#include <QIcon>
|
|
#include <QSettings>
|
|
#include <QStandardPaths>
|
|
|
|
#include <iostream>
|
|
|
|
#include <Windows.h>
|
|
#include <tlhelp32.h>
|
|
#include <winrt/Windows.Foundation.Collections.h>
|
|
#include <winrt/Windows.UI.ViewManagement.h>
|
|
|
|
#include "indicator_debug.h"
|
|
#include "indicatorhelper.h"
|
|
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
|
|
|
|
IndicatorHelper::IndicatorHelper()
|
|
: m_indicatorUrl(QUrl::fromLocalFile(QApplication::applicationDirPath()))
|
|
{
|
|
uiSettings = winrt::Windows::UI::ViewManagement::UISettings();
|
|
}
|
|
|
|
IndicatorHelper::~IndicatorHelper()
|
|
{
|
|
this->terminateProcess(processes::dbus_daemon, m_indicatorUrl);
|
|
this->terminateProcess(processes::kdeconnect_app, m_indicatorUrl);
|
|
this->terminateProcess(processes::kdeconnect_handler, m_indicatorUrl);
|
|
this->terminateProcess(processes::kdeconnect_settings, m_indicatorUrl);
|
|
this->terminateProcess(processes::kdeconnect_sms, m_indicatorUrl);
|
|
this->terminateProcess(processes::kdeconnect_daemon, m_indicatorUrl);
|
|
}
|
|
|
|
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
|
|
const QString iconPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("icons"), QStandardPaths::LocateDirectory);
|
|
if (!iconPath.isNull()) {
|
|
QStringList themeSearchPaths = QIcon::themeSearchPaths();
|
|
themeSearchPaths << iconPath;
|
|
QIcon::setThemeSearchPaths(themeSearchPaths);
|
|
}
|
|
}
|
|
|
|
int IndicatorHelper::startDaemon()
|
|
{
|
|
kdeconnectd.start(processes::kdeconnect_daemon, QStringList());
|
|
return 0;
|
|
}
|
|
|
|
void onThemeChanged(QSystemTrayIcon &systray)
|
|
{
|
|
// Since this is a system tray icon, we care about the system theme and not the app theme
|
|
QSettings registry(QStringLiteral("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"), QSettings::Registry64Format);
|
|
bool isLightTheme = registry.value(QStringLiteral("SystemUsesLightTheme")).toBool();
|
|
if (isLightTheme) {
|
|
systray.setIcon(
|
|
QIcon(QStandardPaths::locate(QStandardPaths::AppLocalDataLocation, QStringLiteral("icons/hicolor/scalable/apps/kdeconnectindicator.svg"))));
|
|
} else {
|
|
systray.setIcon(
|
|
QIcon(QStandardPaths::locate(QStandardPaths::AppLocalDataLocation, QStringLiteral("icons/hicolor/scalable/apps/kdeconnectindicatordark.svg"))));
|
|
}
|
|
}
|
|
|
|
void IndicatorHelper::systrayIconHook(QSystemTrayIcon &systray)
|
|
{
|
|
// Set a callback so we can detect changes to light/dark themes and manually call the callback once the first time
|
|
uiSettings.ColorValuesChanged([&systray](auto &&unused1, auto &&unused2) {
|
|
onThemeChanged(systray);
|
|
});
|
|
onThemeChanged(systray);
|
|
}
|
|
|
|
bool IndicatorHelper::terminateProcess(const QString &processName, const QUrl &indicatorUrl) const
|
|
{
|
|
HANDLE hProcessSnap;
|
|
HANDLE hProcess;
|
|
|
|
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
if (hProcessSnap == INVALID_HANDLE_VALUE) {
|
|
qCWarning(KDECONNECT_INDICATOR) << "Failed to get snapshot of processes.";
|
|
return FALSE;
|
|
}
|
|
|
|
PROCESSENTRY32 pe32;
|
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
if (!Process32First(hProcessSnap, &pe32)) {
|
|
qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the first process.";
|
|
CloseHandle(hProcessSnap);
|
|
return FALSE;
|
|
}
|
|
|
|
do {
|
|
if (QString::fromWCharArray((wchar_t *)pe32.szExeFile) == processName) {
|
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
|
|
|
|
if (hProcess == NULL) {
|
|
qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the process:" << processName;
|
|
return FALSE;
|
|
} else {
|
|
const DWORD processPathSize = 4096;
|
|
CHAR processPathString[processPathSize];
|
|
|
|
BOOL gotProcessPath = QueryFullProcessImageNameA(hProcess, 0, (LPSTR)processPathString, (PDWORD)&processPathSize);
|
|
|
|
if (gotProcessPath) {
|
|
const QUrl processUrl = QUrl::fromLocalFile(QString::fromStdString(processPathString)); // to replace \\ with /
|
|
if (indicatorUrl.isParentOf(processUrl)) {
|
|
BOOL terminateSuccess = TerminateProcess(hProcess, 0);
|
|
if (!terminateSuccess) {
|
|
qCWarning(KDECONNECT_INDICATOR) << "Failed to terminate process:" << processName;
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (Process32Next(hProcessSnap, &pe32));
|
|
|
|
CloseHandle(hProcessSnap);
|
|
return TRUE;
|
|
}
|