|
|
|
@ -20,6 +20,7 @@
|
|
|
|
#include "application.h"
|
|
|
|
#include "application.h"
|
|
|
|
#include "sessionadaptor.h"
|
|
|
|
#include "sessionadaptor.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Qt
|
|
|
|
#include <QDBusConnection>
|
|
|
|
#include <QDBusConnection>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <QSettings>
|
|
|
|
@ -27,6 +28,58 @@
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QDir>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <QDBusConnectionInterface>
|
|
|
|
|
|
|
|
#include <QDBusServiceWatcher>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// STL
|
|
|
|
|
|
|
|
#include <optional>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional<QStringList> getSystemdEnvironment()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
QStringList list;
|
|
|
|
|
|
|
|
auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"),
|
|
|
|
|
|
|
|
QStringLiteral("/org/freedesktop/systemd1"),
|
|
|
|
|
|
|
|
QStringLiteral("org.freedesktop.DBus.Properties"),
|
|
|
|
|
|
|
|
QStringLiteral("Get"));
|
|
|
|
|
|
|
|
msg << QStringLiteral("org.freedesktop.systemd1.Manager") << QStringLiteral("Environment");
|
|
|
|
|
|
|
|
auto reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
|
|
|
|
if (reply.type() == QDBusMessage::ErrorMessage) {
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the returned type is correct.
|
|
|
|
|
|
|
|
auto arguments = reply.arguments();
|
|
|
|
|
|
|
|
if (arguments.isEmpty() || arguments[0].userType() != qMetaTypeId<QDBusVariant>()) {
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
auto variant = qdbus_cast<QVariant>(arguments[0]);
|
|
|
|
|
|
|
|
if (variant.type() != QVariant::StringList) {
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return variant.toStringList();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isShellVariable(const QByteArray &name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return name == "_" || name.startsWith("SHLVL");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isSessionVariable(const QByteArray &name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Check is variable is specific to session.
|
|
|
|
|
|
|
|
return name == "DISPLAY" || name == "XAUTHORITY" || //
|
|
|
|
|
|
|
|
name == "WAYLAND_DISPLAY" || name == "WAYLAND_SOCKET" || //
|
|
|
|
|
|
|
|
name.startsWith("XDG_");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void setEnvironmentVariable(const QByteArray &name, const QByteArray &value)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (qgetenv(name) != value) {
|
|
|
|
|
|
|
|
qputenv(name, value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Application::Application(int &argc, char **argv)
|
|
|
|
Application::Application(int &argc, char **argv)
|
|
|
|
: QApplication(argc, argv)
|
|
|
|
: QApplication(argc, argv)
|
|
|
|
, m_processManager(new ProcessManager)
|
|
|
|
, m_processManager(new ProcessManager)
|
|
|
|
@ -38,15 +91,24 @@ Application::Application(int &argc, char **argv)
|
|
|
|
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Session"), this);
|
|
|
|
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Session"), this);
|
|
|
|
|
|
|
|
|
|
|
|
createConfigDirectory();
|
|
|
|
createConfigDirectory();
|
|
|
|
initEnvironments();
|
|
|
|
|
|
|
|
initLanguage();
|
|
|
|
initLanguage();
|
|
|
|
initScreenScaleFactors();
|
|
|
|
initScreenScaleFactors();
|
|
|
|
|
|
|
|
initFontDpi();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initEnvironments();
|
|
|
|
|
|
|
|
|
|
|
|
if (!syncDBusEnvironment()) {
|
|
|
|
if (!syncDBusEnvironment()) {
|
|
|
|
// Startup error
|
|
|
|
// Startup error
|
|
|
|
qDebug() << "Could not sync environment to dbus.";
|
|
|
|
qDebug() << "Could not sync environment to dbus.";
|
|
|
|
|
|
|
|
qApp->exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We import systemd environment after we sync the dbus environment here.
|
|
|
|
|
|
|
|
// Otherwise it may leads to some unwanted order of applying environment
|
|
|
|
|
|
|
|
// variables (e.g. LANG and LC_*)
|
|
|
|
|
|
|
|
// ref plasma
|
|
|
|
|
|
|
|
importSystemdEnvrionment();
|
|
|
|
|
|
|
|
|
|
|
|
QTimer::singleShot(100, m_processManager, &ProcessManager::start);
|
|
|
|
QTimer::singleShot(100, m_processManager, &ProcessManager::start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -75,7 +137,6 @@ void Application::initEnvironments()
|
|
|
|
qputenv("QT_QPA_PLATFORMTHEME", "cutefish");
|
|
|
|
qputenv("QT_QPA_PLATFORMTHEME", "cutefish");
|
|
|
|
qputenv("QT_PLATFORM_PLUGIN", "cutefish");
|
|
|
|
qputenv("QT_PLATFORM_PLUGIN", "cutefish");
|
|
|
|
|
|
|
|
|
|
|
|
qunsetenv("QT_AUTO_SCREEN_SCALE_FACTOR");
|
|
|
|
|
|
|
|
qunsetenv("QT_SCALE_FACTOR");
|
|
|
|
qunsetenv("QT_SCALE_FACTOR");
|
|
|
|
qunsetenv("QT_SCREEN_SCALE_FACTORS");
|
|
|
|
qunsetenv("QT_SCREEN_SCALE_FACTORS");
|
|
|
|
qunsetenv("QT_ENABLE_HIGHDPI_SCALING");
|
|
|
|
qunsetenv("QT_ENABLE_HIGHDPI_SCALING");
|
|
|
|
@ -83,6 +144,8 @@ void Application::initEnvironments()
|
|
|
|
qunsetenv("QT_FONT_DPI");
|
|
|
|
qunsetenv("QT_FONT_DPI");
|
|
|
|
qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough");
|
|
|
|
qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
|
|
|
|
|
|
|
|
|
|
|
// IM Config
|
|
|
|
// IM Config
|
|
|
|
qputenv("GTK_IM_MODULE", "fcitx5");
|
|
|
|
qputenv("GTK_IM_MODULE", "fcitx5");
|
|
|
|
qputenv("QT4_IM_MODULE", "fcitx5");
|
|
|
|
qputenv("QT4_IM_MODULE", "fcitx5");
|
|
|
|
@ -91,6 +154,21 @@ void Application::initEnvironments()
|
|
|
|
qputenv("XMODIFIERS", "@im=fcitx");
|
|
|
|
qputenv("XMODIFIERS", "@im=fcitx");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Application::initFontDpi()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
QSettings settings(QSettings::UserScope, "cutefishos", "theme");
|
|
|
|
|
|
|
|
int fontDpi = settings.value("forceFontDPI", 0).toReal();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO port to c++?
|
|
|
|
|
|
|
|
const QByteArray input = "Xft.dpi: " + QByteArray::number(fontDpi);
|
|
|
|
|
|
|
|
QProcess p;
|
|
|
|
|
|
|
|
p.start(QStringLiteral("xrdb"), {QStringLiteral("-quiet"), QStringLiteral("-merge"), QStringLiteral("-nocpp")});
|
|
|
|
|
|
|
|
p.setProcessChannelMode(QProcess::ForwardedChannels);
|
|
|
|
|
|
|
|
p.write(input);
|
|
|
|
|
|
|
|
p.closeWriteChannel();
|
|
|
|
|
|
|
|
p.waitForFinished(-1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Application::initLanguage()
|
|
|
|
void Application::initLanguage()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
QSettings settings(QSettings::UserScope, "cutefishos", "language");
|
|
|
|
QSettings settings(QSettings::UserScope, "cutefishos", "language");
|
|
|
|
@ -125,16 +203,11 @@ void Application::initScreenScaleFactors()
|
|
|
|
qreal scaleFactor = settings.value("PixelRatio", 1.0).toReal();
|
|
|
|
qreal scaleFactor = settings.value("PixelRatio", 1.0).toReal();
|
|
|
|
|
|
|
|
|
|
|
|
qputenv("QT_SCREEN_SCALE_FACTORS", QByteArray::number(scaleFactor));
|
|
|
|
qputenv("QT_SCREEN_SCALE_FACTORS", QByteArray::number(scaleFactor));
|
|
|
|
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray::number(1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GDK
|
|
|
|
// for Gtk
|
|
|
|
if (!isInteger(scaleFactor)) {
|
|
|
|
if (qFloor(scaleFactor) > 1) {
|
|
|
|
qunsetenv("GDK_SCALE");
|
|
|
|
|
|
|
|
qputenv("GDK_DPI_SCALE", QByteArray::number(scaleFactor));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
qputenv("GDK_SCALE", QByteArray::number(scaleFactor, 'g', 0));
|
|
|
|
qputenv("GDK_SCALE", QByteArray::number(scaleFactor, 'g', 0));
|
|
|
|
// Intger scale does not adjust GDK_DPI_SCALE.
|
|
|
|
qputenv("GDK_DPI_SCALE", QByteArray::number(1.0 / scaleFactor, 'g', 3));
|
|
|
|
// qputenv("GDK_DPI_SCALE", QByteArray::number(scaleFactor, 'g', 3));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -150,6 +223,31 @@ bool Application::syncDBusEnvironment()
|
|
|
|
return exitCode == 0;
|
|
|
|
return exitCode == 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Import systemd user environment.
|
|
|
|
|
|
|
|
// Systemd read ~/.config/environment.d which applies to all systemd user unit.
|
|
|
|
|
|
|
|
// But it won't work if cutefishDE is not started by systemd.
|
|
|
|
|
|
|
|
void Application::importSystemdEnvrionment()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto environment = getSystemdEnvironment();
|
|
|
|
|
|
|
|
if (!environment) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &envString : environment.value()) {
|
|
|
|
|
|
|
|
const auto env = envString.toLocal8Bit();
|
|
|
|
|
|
|
|
const int idx = env.indexOf('=');
|
|
|
|
|
|
|
|
if (Q_UNLIKELY(idx <= 0)) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto name = env.left(idx);
|
|
|
|
|
|
|
|
if (isShellVariable(name) || isSessionVariable(name)) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
setEnvironmentVariable(name, env.mid(idx + 1));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Application::createConfigDirectory()
|
|
|
|
void Application::createConfigDirectory()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
|
|
|
|
const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
|
|
|
|
|