Fix HiDPI and improve session

pull/6/head
reionwong 4 years ago
parent bc8d003916
commit 01f815bebf

@ -7,7 +7,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(QT Core Gui Widgets Quick QuickControls2 DBus X11Extras LinguistTools)

@ -20,6 +20,7 @@
#include "application.h"
#include "sessionadaptor.h"
// Qt
#include <QDBusConnection>
#include <QStandardPaths>
#include <QSettings>
@ -27,6 +28,58 @@
#include <QDebug>
#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)
: QApplication(argc, argv)
, m_processManager(new ProcessManager)
@ -38,15 +91,24 @@ Application::Application(int &argc, char **argv)
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Session"), this);
createConfigDirectory();
initEnvironments();
initLanguage();
initScreenScaleFactors();
initFontDpi();
initEnvironments();
if (!syncDBusEnvironment()) {
// Startup error
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);
}
@ -75,7 +137,6 @@ void Application::initEnvironments()
qputenv("QT_QPA_PLATFORMTHEME", "cutefish");
qputenv("QT_PLATFORM_PLUGIN", "cutefish");
qunsetenv("QT_AUTO_SCREEN_SCALE_FACTOR");
qunsetenv("QT_SCALE_FACTOR");
qunsetenv("QT_SCREEN_SCALE_FACTORS");
qunsetenv("QT_ENABLE_HIGHDPI_SCALING");
@ -83,6 +144,8 @@ void Application::initEnvironments()
qunsetenv("QT_FONT_DPI");
qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough");
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
// IM Config
qputenv("GTK_IM_MODULE", "fcitx5");
qputenv("QT4_IM_MODULE", "fcitx5");
@ -91,6 +154,21 @@ void Application::initEnvironments()
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()
{
QSettings settings(QSettings::UserScope, "cutefishos", "language");
@ -125,16 +203,11 @@ void Application::initScreenScaleFactors()
qreal scaleFactor = settings.value("PixelRatio", 1.0).toReal();
qputenv("QT_SCREEN_SCALE_FACTORS", QByteArray::number(scaleFactor));
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray::number(1));
// GDK
if (!isInteger(scaleFactor)) {
qunsetenv("GDK_SCALE");
qputenv("GDK_DPI_SCALE", QByteArray::number(scaleFactor));
} else {
// for Gtk
if (qFloor(scaleFactor) > 1) {
qputenv("GDK_SCALE", QByteArray::number(scaleFactor, 'g', 0));
// Intger scale does not adjust GDK_DPI_SCALE.
// qputenv("GDK_DPI_SCALE", QByteArray::number(scaleFactor, 'g', 3));
qputenv("GDK_DPI_SCALE", QByteArray::number(1.0 / scaleFactor, 'g', 3));
}
}
@ -150,6 +223,31 @@ bool Application::syncDBusEnvironment()
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()
{
const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);

@ -63,9 +63,11 @@ public slots:
private:
void initEnvironments();
void initFontDpi();
void initLanguage();
void initScreenScaleFactors();
bool syncDBusEnvironment();
void importSystemdEnvrionment();
void createConfigDirectory();
int runSync(const QString &program, const QStringList &args, const QStringList &env = {});

@ -21,6 +21,7 @@
#include "themeadaptor.h"
#include <QDBusInterface>
#include <QProcess>
#include <QFile>
#include <QDebug>
@ -158,6 +159,30 @@ qreal ThemeManager::devicePixelRatio()
void ThemeManager::setDevicePixelRatio(qreal ratio)
{
m_settings->setValue(s_devicePixelRatio, ratio);
// Set font dpi
// ref kscreen.
if (qFuzzyCompare(ratio, 1.0)) {
// if dpi is the default (96) remove the entry rather than setting it
QProcess proc;
proc.start(QStringLiteral("xrdb"), {QStringLiteral("-quiet"), QStringLiteral("-remove"), QStringLiteral("-nocpp")});
if (proc.waitForStarted()) {
proc.write(QByteArray("Xft.dpi\n"));
proc.closeWriteChannel();
proc.waitForFinished();
}
m_settings->setValue("forceFontDPI", 0);
} else {
const int scaleDpi = qRound(ratio * 96.0);
QProcess proc;
proc.start(QStringLiteral("xrdb"), {QStringLiteral("-quiet"), QStringLiteral("-merge"), QStringLiteral("-nocpp")});
if (proc.waitForStarted()) {
proc.write(QByteArray("Xft.dpi: " + QString::number(scaleDpi).toLatin1()));
proc.closeWriteChannel();
proc.waitForFinished();
}
m_settings->setValue("forceFontDPI", scaleDpi);
}
}
QString ThemeManager::wallpaper()

Loading…
Cancel
Save