From 09d170eb2242ae134fe1c8a8aac6ac3702b0cbf8 Mon Sep 17 00:00:00 2001 From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Date: Sun, 1 Nov 2026 01:41:42 -0400 Subject: [PATCH] fix: performance HUD cycles colors with the Inner Gamer theme (#1932) --- .../launcher/hud/DroidDeckHudView.kt | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/droiddeck/launcher/hud/DroidDeckHudView.kt b/app/src/main/java/com/droiddeck/launcher/hud/DroidDeckHudView.kt index ca2a3d228..c92ac6c87 100644 --- a/app/src/main/java/com/droiddeck/launcher/hud/DroidDeckHudView.kt +++ b/app/src/main/java/com/droiddeck/launcher/hud/DroidDeckHudView.kt @@ -22,12 +22,16 @@ import android.graphics.Paint import android.graphics.Path import android.graphics.RectF import android.graphics.Typeface +import android.os.SystemClock import android.text.format.DateFormat import android.view.GestureDetector import android.view.MotionEvent import android.view.View import androidx.annotation.VisibleForTesting import androidx.compose.ui.graphics.toArgb +import com.droiddeck.launcher.session.SessionPrefs +import com.droiddeck.launcher.ui.Motion +import com.droiddeck.launcher.ui.Palette import com.droiddeck.launcher.ui.Themes import java.util.Date import java.util.Locale @@ -43,6 +47,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -75,6 +80,7 @@ class DroidDeckHudView(context: Context) : View(context) { private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) private var updateJob: Job? = null + private var hueJob: Job? = null private val metrics = HudMetrics(context) private val density = resources.displayMetrics.density @@ -370,9 +376,11 @@ class DroidDeckHudView(context: Context) : View(context) { private fun stopUpdates() { updateJob?.cancel(); updateJob = null + hueJob?.cancel(); hueJob = null } private fun startUpdates() { + startHueCycle() if (updateJob?.isActive == true) return updateJob = scope.launch { while (isActive) { @@ -399,13 +407,50 @@ class DroidDeckHudView(context: Context) : View(context) { var onRefresh: Runnable? = null private fun applyTheme() { - val palette = Themes.current(context) + applyPalette(Themes.current(context)) + if (isAttachedToWindow && isShown) startHueCycle() + } + + private fun applyPalette(palette: Palette) { accent = palette.primary.toArgb() surfaceRgb = palette.surface.toArgb() and 0xFFFFFF colFps = accent colGraph = lighten(accent, 0.3f) } + /** + * Inner Gamer turns the colour wheel inside the app's Compose UI, which is not running while the drawer is + * closed, so the HUD turns it here and shares the hue so the drawer picks up where the HUD is. + */ + private fun startHueCycle() { + if (hueJob?.isActive == true) return + if (SessionPrefs.theme(context) != Themes.INNER_GAMER) return + hueJob = scope.launch { + var hue = Themes.rgbHue + var shown = Float.NaN + var last = SystemClock.uptimeMillis() + while (isActive && SessionPrefs.theme(context) == Themes.INNER_GAMER) { + val now = SystemClock.uptimeMillis() + val cycle = Themes.rgbCycleMillis(Themes.rgbSpeed).toFloat() + if (Motion.scale == 0f) { + last = now + delay(HUE_IDLE_MS) + continue + } + hue = (hue + (now - last) / cycle * 360f) % 360f + last = now + val stepped = (hue / Themes.RGB_HUE_STEP).toInt() * Themes.RGB_HUE_STEP + if (stepped != shown) { + shown = stepped + Themes.moveRgbHue(stepped) + applyPalette(Themes.innerGamer(stepped)) + rebuildAndInvalidate() + } + delay((cycle * Themes.RGB_HUE_STEP / 360f).toLong().coerceAtLeast(16L)) + } + } + } + private fun lighten(color: Int, amount: Float): Int = Color.rgb( (Color.red(color) + (255 - Color.red(color)) * amount).roundToInt(), (Color.green(color) + (255 - Color.green(color)) * amount).roundToInt(), @@ -1557,6 +1602,7 @@ class DroidDeckHudView(context: Context) : View(context) { private companion object { const val REFRESH_MS = 500L + private const val HUE_IDLE_MS = 500L const val MIN_SCALE = 0.5f const val MAX_SCALE = 2f const val GRAPH_CLIP_MS = 49.9f