Override widget colors with accent
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="local_colors_extraction_class" translatable="false">app.lawnchair.AccentColorExtractor</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR condITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package app.lawnchair;
|
||||
|
||||
import android.app.WallpaperColors;
|
||||
import android.content.Context;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.util.SparseIntArray;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.launcher3.widget.LocalColorExtractor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import app.lawnchair.theme.ThemeProvider;
|
||||
import dev.kdrag0n.colorkt.Color;
|
||||
import dev.kdrag0n.colorkt.rgb.Srgb;
|
||||
import dev.kdrag0n.monet.theme.ColorScheme;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.S)
|
||||
public class AccentColorExtractor extends LocalColorExtractor implements ThemeProvider.ColorSchemeChangeListener {
|
||||
|
||||
private final ThemeProvider mThemeProvider;
|
||||
private final RectF mTmpRect = new RectF();
|
||||
private Listener mListener;
|
||||
|
||||
@Keep
|
||||
public AccentColorExtractor(Context context) {
|
||||
mThemeProvider = ThemeProvider.INSTANCE.get(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(@Nullable Listener listener) {
|
||||
mListener = listener;
|
||||
notifyListener(mTmpRect, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLocation(List<RectF> locations) {
|
||||
mThemeProvider.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLocations() {
|
||||
mThemeProvider.removeListener(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected SparseIntArray generateColorsOverride(ColorScheme colorScheme) {
|
||||
SparseIntArray colorRes = new SparseIntArray(5 * 13);
|
||||
|
||||
addColorsToArray(colorScheme.getAccent1(), ACCENT1_RES, colorRes);
|
||||
addColorsToArray(colorScheme.getAccent2(), ACCENT2_RES, colorRes);
|
||||
addColorsToArray(colorScheme.getAccent3(), ACCENT3_RES, colorRes);
|
||||
addColorsToArray(colorScheme.getNeutral1(), NEUTRAL1_RES, colorRes);
|
||||
addColorsToArray(colorScheme.getNeutral2(), NEUTRAL2_RES, colorRes);
|
||||
|
||||
return colorRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyColorsOverride(Context base, WallpaperColors colors) {
|
||||
RemoteViews.ColorResources res =
|
||||
RemoteViews.ColorResources.create(base, generateColorsOverride(colors));
|
||||
if (res != null) {
|
||||
res.apply(base);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorSchemeChanged() {
|
||||
notifyListener(mTmpRect, null);
|
||||
}
|
||||
|
||||
protected void notifyListener(RectF area, WallpaperColors colors) {
|
||||
if (mListener != null) {
|
||||
mListener.onColorsChanged(area, generateColorsOverride(mThemeProvider.getColorScheme()));
|
||||
}
|
||||
}
|
||||
|
||||
// Shade number -> color resource ID maps
|
||||
private static final SparseIntArray ACCENT1_RES = new SparseIntArray(13);
|
||||
private static final SparseIntArray ACCENT2_RES = new SparseIntArray(13);
|
||||
private static final SparseIntArray ACCENT3_RES = new SparseIntArray(13);
|
||||
private static final SparseIntArray NEUTRAL1_RES = new SparseIntArray(13);
|
||||
private static final SparseIntArray NEUTRAL2_RES = new SparseIntArray(13);
|
||||
|
||||
static {
|
||||
ACCENT1_RES.put( 0, android.R.color.system_accent1_0);
|
||||
ACCENT1_RES.put( 10, android.R.color.system_accent1_10);
|
||||
ACCENT1_RES.put( 50, android.R.color.system_accent1_50);
|
||||
ACCENT1_RES.put( 100, android.R.color.system_accent1_100);
|
||||
ACCENT1_RES.put( 200, android.R.color.system_accent1_200);
|
||||
ACCENT1_RES.put( 300, android.R.color.system_accent1_300);
|
||||
ACCENT1_RES.put( 400, android.R.color.system_accent1_400);
|
||||
ACCENT1_RES.put( 500, android.R.color.system_accent1_500);
|
||||
ACCENT1_RES.put( 600, android.R.color.system_accent1_600);
|
||||
ACCENT1_RES.put( 700, android.R.color.system_accent1_700);
|
||||
ACCENT1_RES.put( 800, android.R.color.system_accent1_800);
|
||||
ACCENT1_RES.put( 900, android.R.color.system_accent1_900);
|
||||
ACCENT1_RES.put(1000, android.R.color.system_accent1_1000);
|
||||
|
||||
ACCENT2_RES.put( 0, android.R.color.system_accent2_0);
|
||||
ACCENT2_RES.put( 10, android.R.color.system_accent2_10);
|
||||
ACCENT2_RES.put( 50, android.R.color.system_accent2_50);
|
||||
ACCENT2_RES.put( 100, android.R.color.system_accent2_100);
|
||||
ACCENT2_RES.put( 200, android.R.color.system_accent2_200);
|
||||
ACCENT2_RES.put( 300, android.R.color.system_accent2_300);
|
||||
ACCENT2_RES.put( 400, android.R.color.system_accent2_400);
|
||||
ACCENT2_RES.put( 500, android.R.color.system_accent2_500);
|
||||
ACCENT2_RES.put( 600, android.R.color.system_accent2_600);
|
||||
ACCENT2_RES.put( 700, android.R.color.system_accent2_700);
|
||||
ACCENT2_RES.put( 800, android.R.color.system_accent2_800);
|
||||
ACCENT2_RES.put( 900, android.R.color.system_accent2_900);
|
||||
ACCENT2_RES.put(1000, android.R.color.system_accent2_1000);
|
||||
|
||||
ACCENT3_RES.put( 0, android.R.color.system_accent3_0);
|
||||
ACCENT3_RES.put( 10, android.R.color.system_accent3_10);
|
||||
ACCENT3_RES.put( 50, android.R.color.system_accent3_50);
|
||||
ACCENT3_RES.put( 100, android.R.color.system_accent3_100);
|
||||
ACCENT3_RES.put( 200, android.R.color.system_accent3_200);
|
||||
ACCENT3_RES.put( 300, android.R.color.system_accent3_300);
|
||||
ACCENT3_RES.put( 400, android.R.color.system_accent3_400);
|
||||
ACCENT3_RES.put( 500, android.R.color.system_accent3_500);
|
||||
ACCENT3_RES.put( 600, android.R.color.system_accent3_600);
|
||||
ACCENT3_RES.put( 700, android.R.color.system_accent3_700);
|
||||
ACCENT3_RES.put( 800, android.R.color.system_accent3_800);
|
||||
ACCENT3_RES.put( 900, android.R.color.system_accent3_900);
|
||||
ACCENT3_RES.put(1000, android.R.color.system_accent3_1000);
|
||||
|
||||
NEUTRAL1_RES.put( 0, android.R.color.system_neutral1_0);
|
||||
NEUTRAL1_RES.put( 10, android.R.color.system_neutral1_10);
|
||||
NEUTRAL1_RES.put( 50, android.R.color.system_neutral1_50);
|
||||
NEUTRAL1_RES.put( 100, android.R.color.system_neutral1_100);
|
||||
NEUTRAL1_RES.put( 200, android.R.color.system_neutral1_200);
|
||||
NEUTRAL1_RES.put( 300, android.R.color.system_neutral1_300);
|
||||
NEUTRAL1_RES.put( 400, android.R.color.system_neutral1_400);
|
||||
NEUTRAL1_RES.put( 500, android.R.color.system_neutral1_500);
|
||||
NEUTRAL1_RES.put( 600, android.R.color.system_neutral1_600);
|
||||
NEUTRAL1_RES.put( 700, android.R.color.system_neutral1_700);
|
||||
NEUTRAL1_RES.put( 800, android.R.color.system_neutral1_800);
|
||||
NEUTRAL1_RES.put( 900, android.R.color.system_neutral1_900);
|
||||
NEUTRAL1_RES.put(1000, android.R.color.system_neutral1_1000);
|
||||
|
||||
NEUTRAL2_RES.put( 0, android.R.color.system_neutral2_0);
|
||||
NEUTRAL2_RES.put( 10, android.R.color.system_neutral2_10);
|
||||
NEUTRAL2_RES.put( 50, android.R.color.system_neutral2_50);
|
||||
NEUTRAL2_RES.put( 100, android.R.color.system_neutral2_100);
|
||||
NEUTRAL2_RES.put( 200, android.R.color.system_neutral2_200);
|
||||
NEUTRAL2_RES.put( 300, android.R.color.system_neutral2_300);
|
||||
NEUTRAL2_RES.put( 400, android.R.color.system_neutral2_400);
|
||||
NEUTRAL2_RES.put( 500, android.R.color.system_neutral2_500);
|
||||
NEUTRAL2_RES.put( 600, android.R.color.system_neutral2_600);
|
||||
NEUTRAL2_RES.put( 700, android.R.color.system_neutral2_700);
|
||||
NEUTRAL2_RES.put( 800, android.R.color.system_neutral2_800);
|
||||
NEUTRAL2_RES.put( 900, android.R.color.system_neutral2_900);
|
||||
NEUTRAL2_RES.put(1000, android.R.color.system_neutral2_1000);
|
||||
}
|
||||
|
||||
private static void addColorsToArray(Map<Integer, Color> swatch,
|
||||
SparseIntArray resMap, SparseIntArray array) {
|
||||
for (Map.Entry<Integer, Color> entry : swatch.entrySet()) {
|
||||
int shade = entry.getKey();
|
||||
int resId = resMap.get(shade, -1);
|
||||
if (resId != -1) {
|
||||
Srgb color = (Srgb) entry.getValue();
|
||||
array.put(resId, 0xff000000 | color.toRgb8());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import android.os.Looper
|
||||
import android.os.PatternMatcher
|
||||
import android.util.SparseArray
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import app.lawnchair.preferences.PreferenceChangeListener
|
||||
import app.lawnchair.preferences.PreferenceManager
|
||||
import app.lawnchair.theme.color.AndroidColor
|
||||
import app.lawnchair.theme.color.ColorOption
|
||||
@@ -32,17 +33,31 @@ import dev.kdrag0n.monet.theme.MaterialYouTargets
|
||||
|
||||
class ThemeProvider(private val context: Context) {
|
||||
private val prefs = PreferenceManager.getInstance(context)
|
||||
private val wallpaperManager = WallpaperManagerCompat.INSTANCE.get(context)
|
||||
private val accentColor by prefs.accentColor
|
||||
private val enableColorfulTheme by prefs.enableColorfulTheme
|
||||
|
||||
private val targets = MaterialYouTargets(1.0, false, viewingCondition)
|
||||
private val colorSchemeMap = SparseArray<ColorScheme>()
|
||||
private val listeners = mutableListOf<ColorSchemeChangeListener>()
|
||||
|
||||
init {
|
||||
if (Utilities.ATLEAST_S) {
|
||||
colorSchemeMap.append(0, SystemColorScheme(context))
|
||||
registerOverlayChangedListener()
|
||||
}
|
||||
wallpaperManager.addOnChangeListener(object : WallpaperManagerCompat.OnColorsChangedListener {
|
||||
override fun onColorsChanged() {
|
||||
if (accentColor is ColorOption.WallpaperPrimary) {
|
||||
notifyColorSchemeChanged()
|
||||
}
|
||||
}
|
||||
})
|
||||
prefs.accentColor.addListener(object : PreferenceChangeListener {
|
||||
override fun onPreferenceChange() {
|
||||
notifyColorSchemeChanged()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun registerOverlayChangedListener() {
|
||||
@@ -53,6 +68,9 @@ class ThemeProvider(private val context: Context) {
|
||||
object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
colorSchemeMap.append(0, SystemColorScheme(context))
|
||||
if (accentColor is ColorOption.SystemAccent) {
|
||||
notifyColorSchemeChanged()
|
||||
}
|
||||
}
|
||||
},
|
||||
packageFilter,
|
||||
@@ -64,7 +82,6 @@ class ThemeProvider(private val context: Context) {
|
||||
val colorScheme get() = when (val accentColor = this.accentColor) {
|
||||
is ColorOption.SystemAccent -> systemColorScheme
|
||||
is ColorOption.WallpaperPrimary -> {
|
||||
val wallpaperManager = WallpaperManagerCompat.INSTANCE.get(context)
|
||||
val wallpaperPrimary = wallpaperManager.wallpaperColors?.primaryColor
|
||||
getColorScheme(wallpaperPrimary ?: ColorOption.LawnchairBlue.color)
|
||||
}
|
||||
@@ -86,6 +103,19 @@ class ThemeProvider(private val context: Context) {
|
||||
return colorScheme
|
||||
}
|
||||
|
||||
fun addListener(listener: ColorSchemeChangeListener) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
|
||||
fun removeListener(listener: ColorSchemeChangeListener) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
private fun notifyColorSchemeChanged() {
|
||||
ArrayList(listeners)
|
||||
.forEach(ColorSchemeChangeListener::onColorSchemeChanged)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val INSTANCE = MainThreadInitializedObject(::ThemeProvider)
|
||||
@@ -97,6 +127,10 @@ class ThemeProvider(private val context: Context) {
|
||||
Illuminants.D65.toAbs(CieXyzAbs.DEFAULT_SDR_WHITE_LUMINANCE)
|
||||
)
|
||||
}
|
||||
|
||||
interface ColorSchemeChangeListener {
|
||||
fun onColorSchemeChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun Color.toAndroidColor(): Int {
|
||||
|
||||
Reference in New Issue
Block a user