diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.android.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.android.kt new file mode 100644 index 0000000..ae34e0b --- /dev/null +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.android.kt @@ -0,0 +1,8 @@ +package com.artemchep.keyguard.platform.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable +import com.artemchep.keyguard.platform.Platform + +@Composable +actual fun Platform.hasDarkThemeEnabled(): Boolean = isSystemInDarkTheme() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.kt new file mode 100644 index 0000000..acee7b7 --- /dev/null +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.kt @@ -0,0 +1,7 @@ +package com.artemchep.keyguard.platform.theme + +import androidx.compose.runtime.Composable +import com.artemchep.keyguard.platform.Platform + +@Composable +expect fun Platform.hasDarkThemeEnabled(): Boolean diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt index a41ce7b..ece6afc 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt @@ -22,6 +22,8 @@ import com.artemchep.keyguard.common.usecase.GetColors import com.artemchep.keyguard.common.usecase.GetFont import com.artemchep.keyguard.common.usecase.GetTheme import com.artemchep.keyguard.common.usecase.GetThemeUseAmoledDark +import com.artemchep.keyguard.platform.CurrentPlatform +import com.artemchep.keyguard.platform.theme.hasDarkThemeEnabled import com.artemchep.keyguard.res.Res import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.monet.ColorSchemeFactory @@ -275,7 +277,7 @@ fun KeyguardTheme( val isDarkColorScheme = when (theme) { AppTheme.DARK -> true AppTheme.LIGHT -> false - null -> isSystemInDarkTheme() + null -> CurrentPlatform.hasDarkThemeEnabled() } val scheme = kotlin.run { diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.desktop.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.desktop.kt new file mode 100644 index 0000000..04a0f32 --- /dev/null +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/theme/PlatformTheme.desktop.kt @@ -0,0 +1,69 @@ +package com.artemchep.keyguard.platform.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import com.artemchep.keyguard.platform.Platform +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.withContext +import java.util.concurrent.TimeUnit + +@Composable +actual fun Platform.hasDarkThemeEnabled(): Boolean = when (this) { + is Platform.Desktop.Linux -> isLinuxPortalInDarkTheme() + else -> isSystemInDarkTheme() +} + +@Composable +private fun isLinuxPortalInDarkTheme(): Boolean { + val darkThemeDefault = isSystemInDarkTheme() + var darkThemeState by remember { + mutableStateOf(darkThemeDefault) + } + LaunchedEffect(Unit) { + while (true) { + kotlin.runCatching { + darkThemeState = readLinuxPortalInDarkTheme() + }.getOrElse { + // Stop checking for the appearance, just use + // whatever Compose provides. + darkThemeState = darkThemeDefault + return@LaunchedEffect + } + + delay(2000L) + ensureActive() + } + } + return darkThemeState +} + +private suspend fun readLinuxPortalInDarkTheme() = withContext(Dispatchers.IO) { + val command = listOf( + "gdbus", + "call", + "--session", + "--dest=org.freedesktop.portal.Desktop", + "--object-path=/org/freedesktop/portal/desktop", + "--method=org.freedesktop.portal.Settings.Read", + "org.freedesktop.appearance", + "color-scheme", + ) + val pb = ProcessBuilder(command) + .redirectError(ProcessBuilder.Redirect.INHERIT) + val process = pb.start().apply { + waitFor(60, TimeUnit.MINUTES) + } + + val result = process.inputStream.reader().readText() + // 0: No preference + // 1: Prefer dark appearance + // 2: Prefer light appearance + result[10] == '1' +}