From f2cbe005e3fbb23f1b21ddd0f90dfa9fd9dd9ae5 Mon Sep 17 00:00:00 2001 From: UltimatePlayer97 Date: Tue, 3 Dec 2024 19:21:43 +1100 Subject: [PATCH 1/2] Add KDE Plasma dark mode support --- .../additiveinstaller/darkModeDetector.kt | 115 +++++++++++------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt b/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt index 017fc8f..88f526a 100644 --- a/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt +++ b/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt @@ -1,55 +1,82 @@ package io.github.gaming32.additiveinstaller -import io.github.oshai.kotlinlogging.KotlinLogging import java.io.BufferedReader import java.io.IOException -// Ported to Kotlin from https://github.com/IrisShaders/Iris-Installer/blob/main/src/main/java/net/hypercubemc/iris_installer/DarkModeDetector.java - -private val logger = KotlinLogging.logger {} - private const val REGQUERY_UTIL = "reg query " private const val REGDWORD_TOKEN = "REG_DWORD" private const val DARK_THEME_CMD = "$REGQUERY_UTIL\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\" /v AppsUseLightTheme" private val DARK_THEME_PATTERN = Regex(".*dark.*", RegexOption.IGNORE_CASE) -fun isDarkMode() = when (operatingSystem) { - OperatingSystem.WINDOWS -> isWindowsDarkMode() - OperatingSystem.MACOS -> isMacOsDarkMode() - OperatingSystem.LINUX -> isGnome() && isGnomeDarkMode() - else -> false -} - -private fun isMacOsDarkMode() = query("defaults read -g AppleInterfaceStyle") == "Dark" - -private fun isWindowsDarkMode() = try { - query(DARK_THEME_CMD) - .substringAfter(REGDWORD_TOKEN) - .ifEmpty { null } - ?.trim() - ?.substring(2) - ?.toInt(16) == 0 -} catch (e: Exception) { - false -} - -private fun isGnomeDarkMode() = query("gsettings get org.gnome.desktop.interface gtk-theme") matches DARK_THEME_PATTERN - -private fun isGnome() = operatingSystem == OperatingSystem.LINUX && ( - queryResultContains("echo \$XDG_CURRENT_DESKTOP", "gnome") || - queryResultContains("echo \$XDG_DATA_DIRS | grep -Eo 'gnome'", "gnome") || - queryResultContains("ps -e | grep -E -i \"gnome\"", "gnome") -) - -private fun queryResultContains(cmd: String, subResult: String) = query(cmd).contains(subResult, ignoreCase = true) - -private fun query(cmd: String) = try { - Runtime.getRuntime() - .exec(cmd) - .inputStream - .bufferedReader() - .use(BufferedReader::readText) -} catch (e: IOException) { - logger.error(e) { "Exception caught while querying the OS" } - "" +fun isDarkMode(): Boolean { + return when (operatingSystem) { + OperatingSystem.WINDOWS -> isWindowsDarkMode() + OperatingSystem.MACOS -> isMacOsDarkMode() + OperatingSystem.LINUX -> (isGnome() && isGnomeDarkMode()) || (isKde() && isKdeDarkMode()) + else -> false + } +} + +private fun isMacOsDarkMode(): Boolean { + val result = query("defaults read -g AppleInterfaceStyle") + return result == "Dark" +} + +private fun isWindowsDarkMode(): Boolean { + return try { + val result = query(DARK_THEME_CMD) + result.substringAfter(REGDWORD_TOKEN) + .ifEmpty { null } + ?.trim() + ?.substring(2) + ?.toInt(16) == 0 + } catch (e: Exception) { + false + } +} + +private fun isGnomeDarkMode(): Boolean { + val result = query("gsettings get org.gnome.desktop.interface gtk-theme") + return result matches DARK_THEME_PATTERN +} + +private fun isGnome(): Boolean { + return operatingSystem == OperatingSystem.LINUX && ( + queryResultContains("echo \$XDG_CURRENT_DESKTOP", "gnome") || + queryResultContains("echo \$XDG_DATA_DIRS | grep -Eo 'gnome'", "gnome") || + queryResultContains("ps -e | grep -E -i \"gnome\"", "gnome") + ) +} + +private fun isKdeDarkMode(): Boolean { + val currentLookAndFeel = query("lookandfeeltool --current") + if (currentLookAndFeel.isEmpty()) { + val alternativeLookAndFeel = query("kreadconfig5 --group KDE --key LookAndFeelPackage") + return alternativeLookAndFeel.contains("dark", ignoreCase = true) + } + return currentLookAndFeel.contains("dark", ignoreCase = true) +} + +private fun isKde(): Boolean { + return operatingSystem == OperatingSystem.LINUX && ( + queryResultContains("echo \$XDG_CURRENT_DESKTOP", "KDE") || + queryResultContains("echo \$XDG_DATA_DIRS | grep -Eo 'kde'", "kde") || + queryResultContains("ps -e | grep -E -i \"kde\"", "kde") + ) +} + +private fun queryResultContains(cmd: String, subResult: String): Boolean { + return query(cmd).contains(subResult, ignoreCase = true) +} + +private fun query(cmd: String): String { + return try { + Runtime.getRuntime() + .exec(cmd) + .inputStream + .bufferedReader() + .use(BufferedReader::readText) + } catch (e: IOException) { + "" + } } From 1a48f488eed4ee61dd109511c87470bf2923f00a Mon Sep 17 00:00:00 2001 From: UltimatePlayer97 Date: Tue, 3 Dec 2024 19:29:05 +1100 Subject: [PATCH 2/2] Add back logging --- .../github/gaming32/additiveinstaller/darkModeDetector.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt b/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt index 88f526a..70dbda9 100644 --- a/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt +++ b/src/main/kotlin/io/github/gaming32/additiveinstaller/darkModeDetector.kt @@ -1,8 +1,13 @@ package io.github.gaming32.additiveinstaller +import io.github.oshai.kotlinlogging.KotlinLogging import java.io.BufferedReader import java.io.IOException +// Ported to Kotlin from https://github.com/IrisShaders/Iris-Installer/blob/main/src/main/java/net/hypercubemc/iris_installer/DarkModeDetector.java + +private val logger = KotlinLogging.logger {} + private const val REGQUERY_UTIL = "reg query " private const val REGDWORD_TOKEN = "REG_DWORD" private const val DARK_THEME_CMD = "$REGQUERY_UTIL\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\" /v AppsUseLightTheme" @@ -77,6 +82,7 @@ private fun query(cmd: String): String { .bufferedReader() .use(BufferedReader::readText) } catch (e: IOException) { + logger.error { "Exception caught while querying the OS" } "" } }