File indexing completed on 2024-05-12 05:29:27
0001 // SPDX-FileCopyrightText: 2019, 2022 Mikhail Zolotukhin <zomial@protonmail.com> 0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 0004 #include "xsettings.h" 0005 0006 #include <unistd.h> 0007 0008 #include <QDir> 0009 #include <QProcess> 0010 #include <QRegularExpression> 0011 #include <QStandardPaths> 0012 0013 #include <csignal> 0014 #include <glib.h> 0015 0016 #include "config_editor/utils.h" 0017 0018 namespace 0019 { 0020 constinit unsigned s_applyId = 0; 0021 0022 void replaceValueInXSettingsdContents(QString &xSettingsdContents, const QString ¶mName, const QVariant ¶mValue) 0023 { 0024 const QRegularExpression regExp(paramName + QStringLiteral(" [^\n]*($|\n)")); 0025 0026 QString newConfigString; 0027 if (paramValue.type() == QVariant::Type::String) { 0028 newConfigString = QStringLiteral("%1 \"%2\"\n").arg(paramName, paramValue.toString()); 0029 } else if (paramValue.type() == QVariant::Type::Bool) { 0030 // XSettigsd does not support 'true' and 'false' as values 0031 newConfigString = QStringLiteral("%1 %2\n").arg(paramName, QString::number(paramValue.toInt())); 0032 } else { 0033 newConfigString = QStringLiteral("%1 %2\n").arg(paramName, paramValue.toString()); 0034 } 0035 0036 if (paramValue.isNull()) { 0037 // unset value 0038 xSettingsdContents.replace(regExp, QString()); 0039 } else if (xSettingsdContents.contains(regExp)) { 0040 xSettingsdContents.replace(regExp, newConfigString); 0041 } else { 0042 xSettingsdContents = newConfigString + xSettingsdContents; 0043 } 0044 } 0045 0046 pid_t pidOfXSettingsd() 0047 { 0048 QProcess pgrep; 0049 pgrep.start(QStringLiteral("pgrep"), 0050 QStringList{ 0051 QStringLiteral("-u"), 0052 QString::number(getuid()), 0053 QStringLiteral("-n"), // select most recently started 0054 QStringLiteral("xsettingsd"), 0055 }); 0056 pgrep.waitForFinished(); 0057 QString xsettingsdPid = QString(pgrep.readAllStandardOutput()).remove('\n'); 0058 return xsettingsdPid.toInt(); 0059 } 0060 0061 #if GLIB_CHECK_VERSION(2, 74, 0) 0062 void reloadXSettingsd(void *) 0063 #else 0064 int reloadXSettingsd(void *) 0065 #endif 0066 { 0067 pid_t xSettingsdPid = pidOfXSettingsd(); 0068 if (xSettingsdPid == 0) { 0069 QProcess::startDetached(QStandardPaths::findExecutable(QStringLiteral("xsettingsd")), QStringList()); 0070 } else { 0071 kill(xSettingsdPid, SIGHUP); 0072 } 0073 0074 s_applyId = 0; 0075 #if !GLIB_CHECK_VERSION(2, 74, 0) 0076 return G_SOURCE_REMOVE; 0077 #endif 0078 } 0079 0080 } 0081 0082 namespace XSettingsEditor 0083 { 0084 0085 void setValue(const QString ¶mName, const QVariant ¶mValue) 0086 { 0087 QString configLocation = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); 0088 0089 QDir xsettingsdPath = configLocation + QStringLiteral("/xsettingsd"); 0090 if (!xsettingsdPath.exists()) { 0091 xsettingsdPath.mkpath(QStringLiteral(".")); 0092 } 0093 0094 QString xSettingsdConfigPath = xsettingsdPath.path() + QStringLiteral("/xsettingsd.conf"); 0095 0096 QFile xSettingsdConfig(xSettingsdConfigPath); 0097 QString xSettingsdConfigContents = Utils::readFileContents(xSettingsdConfig); 0098 replaceValueInXSettingsdContents(xSettingsdConfigContents, paramName, paramValue); 0099 xSettingsdConfig.remove(); 0100 xSettingsdConfig.open(QIODevice::WriteOnly | QIODevice::Text); 0101 xSettingsdConfig.write(xSettingsdConfigContents.toUtf8()); 0102 0103 if (s_applyId == 0) { 0104 #if GLIB_CHECK_VERSION(2, 74, 0) 0105 s_applyId = g_timeout_add_once(100, reloadXSettingsd, nullptr); 0106 #else 0107 s_applyId = g_timeout_add(100, reloadXSettingsd, nullptr); 0108 #endif 0109 } 0110 } 0111 0112 void unsetValue(const QString ¶mName) 0113 { 0114 setValue(paramName, QVariant()); 0115 } 0116 }