/* * SPDX-FileCopyrightText: 2019 Weixuan XIAO * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL */ #include #include #include #include #include #include #include #include #include #include #include "indicator_debug.h" #include "indicatorhelper.h" winrt::Windows::UI::ViewManagement::UISettings uiSettings; IndicatorHelper::IndicatorHelper(const QUrl &indicatorUrl) : m_indicatorUrl(indicatorUrl) { 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::preInit() { } void IndicatorHelper::postInit() { } 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::daemonHook(QProcess &kdeconnectd) { kdeconnectd.start(processes::kdeconnect_daemon); 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; }