Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/rust_android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@ jobs:
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1
with:
target: aarch64-linux-android
target: aarch64-linux-android, x86_64-linux-android
- name: Install cargo-ndk
run: cargo install cargo-ndk
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- name: Set up cargo cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
if: github.ref != 'refs/heads/main'
with:
shared-key: "rust-android"
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Build Android example
run: cargo ndk -t arm64-v8a build -p android --lib
working-directory: examples/android/AndroidApp
run: ./gradlew buildRelease
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ freya-code-editor = { path = "./crates/freya-code-editor", version = "0.4.0-rc.1
"rust",
] }
freya-android = { path = "./crates/freya-android", version = "0.4.0-rc.19" }
mundy = { version = "0.2.3", default-features = false, features = [
"async-io",
"callback",
"accent-color",
] }

# core
generational-box = "0.7"
Expand Down
28 changes: 24 additions & 4 deletions crates/freya-components/src/theming/themes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,35 @@ fn register_base_component_themes(theme: &mut Theme) {
}

/// Light theme with all built-in component themes registered.
///
/// The primary color tracks the OS-level [`AccentColor`] when available; the
/// secondary and tertiary colors are derived from it (lightened / darkened).
pub fn light_theme() -> Theme {
let mut theme = Theme::new("light", LIGHT_COLORS);
register_base_component_themes(&mut theme);
theme
build_theme("light", LIGHT_COLORS)
}

/// Dark theme with all built-in component themes registered.
///
/// The primary color tracks the OS-level [`AccentColor`] when available; the
/// secondary and tertiary colors are derived from it (lightened / darkened).
pub fn dark_theme() -> Theme {
let mut theme = Theme::new("dark", DARK_COLORS);
build_theme("dark", DARK_COLORS)
}

fn build_theme(name: &'static str, mut colors: ColorsSheet) -> Theme {
if let Some(primary) = current_accent_color() {
colors.primary = primary;
colors.secondary = Color::lerp(primary, Color::WHITE, 0.65);
colors.tertiary = Color::lerp(primary, Color::BLACK, 0.23);
}
let mut theme = Theme::new(name, colors);
register_base_component_themes(&mut theme);
theme
}

fn current_accent_color() -> Option<Color> {
let platform: Platform = try_consume_root_context()?;
let accent = platform.accent_color.read().0?;
let [r, g, b, _] = accent.to_u8_array();
Some(Color::from_rgb(r, g, b))
}
3 changes: 3 additions & 0 deletions crates/freya-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ keyboard-types = { workspace = true }
torin = { workspace = true }
smallvec = "1.15.1"

# OS preferences
mundy = { workspace = true }

# Layers
itertools = { workspace = true }

Expand Down
6 changes: 6 additions & 0 deletions crates/freya-core/src/platform.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::rc::Rc;

pub use mundy::{
AccentColor,
Srgba,
};
use torin::prelude::Size2D;

use crate::{
Expand Down Expand Up @@ -41,6 +45,8 @@ pub struct Platform {
pub navigation_mode: State<NavigationMode>,
/// The OS-level [`PreferredTheme`].
pub preferred_theme: State<PreferredTheme>,
/// The OS-level [`AccentColor`].
pub accent_color: State<AccentColor>,
/// Sender used to dispatch [`UserEvent`]s to the active renderer.
pub sender: Rc<dyn Fn(UserEvent)>,
}
Expand Down
13 changes: 13 additions & 0 deletions crates/freya-core/src/style/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,17 @@ impl Color {
pub fn pretty(&self) -> String {
self.to_rgb_string()
}

/// Linearly interpolates between two colors per channel. `t` is clamped
/// to `0.0..=1.0`; `0.0` returns `start`, `1.0` returns `end`.
pub fn lerp(start: Color, end: Color, t: f32) -> Color {
let t = t.clamp(0.0, 1.0);
let mix = |a: u8, b: u8| (a as f32 + (b as f32 - a as f32) * t).round() as u8;
Color::from_argb(
mix(start.a(), end.a()),
mix(start.r(), end.r()),
mix(start.g(), end.g()),
mix(start.b(), end.b()),
)
}
}
1 change: 1 addition & 0 deletions crates/freya-testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl TestingRunner {
root_size: State::create(size),
navigation_mode: State::create(NavigationMode::NotKeyboard),
preferred_theme: State::create(PreferredTheme::Light),
accent_color: State::create(AccentColor::default()),
sender: Rc::new(move |user_event| {
match user_event {
UserEvent::RequestRedraw => {
Expand Down
3 changes: 3 additions & 0 deletions crates/freya-winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ raw-window-handle = { workspace = true }
winit = { workspace = true }
freya-engine = { workspace = true }

# OS preferences
mundy = { workspace = true }

# Events
ragnarok = { workspace = true }
keyboard-types = { workspace = true }
Expand Down
17 changes: 17 additions & 0 deletions crates/freya-winit/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ pub enum NativeEvent {
#[cfg(feature = "tray")]
Tray(NativeTrayEvent),
Generic(NativeGenericEvent),
Preferences(mundy::Preferences),
}

impl From<accesskit_winit::Event> for NativeEvent {
Expand Down Expand Up @@ -300,6 +301,8 @@ impl ApplicationHandler<NativeEvent> for WinitRenderer {
}
self.resumed = true;

subscribe_preferences(self.proxy.clone());

let _ = self
.proxy
.send_event(NativeEvent::Generic(NativeGenericEvent::PollFutures));
Expand Down Expand Up @@ -353,6 +356,13 @@ impl ApplicationHandler<NativeEvent> for WinitRenderer {
self.futures
.retain_mut(|fut| fut.poll(&mut cx).is_pending());
}
NativeEvent::Preferences(prefs) => {
for app in self.windows.values_mut() {
app.platform
.accent_color
.set_if_modified(prefs.accent_color);
}
}
#[cfg(feature = "tray")]
NativeEvent::Tray(NativeTrayEvent { action }) => {
let renderer_context = RendererContext {
Expand Down Expand Up @@ -1178,3 +1188,10 @@ impl ApplicationHandler<NativeEvent> for WinitRenderer {
}
}
}

fn subscribe_preferences(proxy: EventLoopProxy<NativeEvent>) {
let subscription = mundy::Preferences::subscribe(mundy::Interest::AccentColor, move |prefs| {
let _ = proxy.send_event(NativeEvent::Preferences(prefs));
});
std::mem::forget(subscription);
}
14 changes: 14 additions & 0 deletions crates/freya-winit/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ impl AppWindow {
let mut tree = Tree::default();

let window_size = window.inner_size();
let accent_color_preference = accent_color_preference();
let platform = runner.provide_root_context({
let event_loop_proxy = event_loop_proxy.clone();
let window_id = window.id();
Expand All @@ -200,6 +201,7 @@ impl AppWindow {
)),
navigation_mode: State::create(NavigationMode::NotKeyboard),
preferred_theme: State::create(theme),
accent_color: State::create(accent_color_preference.accent_color),
sender: Rc::new(move |user_event| {
event_loop_proxy
.send_event(NativeEvent::Window(NativeWindowEvent {
Expand Down Expand Up @@ -365,3 +367,15 @@ impl AppWindow {
&mut self.window
}
}

fn accent_color_preference() -> mundy::Preferences {
use std::sync::OnceLock;
static PREFERENCE: OnceLock<mundy::Preferences> = OnceLock::new();
*PREFERENCE.get_or_init(|| {
mundy::Preferences::once_blocking(
mundy::Interest::AccentColor,
std::time::Duration::from_millis(200),
)
.unwrap_or_default()
})
}
4 changes: 4 additions & 0 deletions examples/android/AndroidApp/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ android {

tasks.register<Exec>("buildRustLibrary") {
workingDir("../..")
val androidHome = System.getenv("ANDROID_HOME") ?: System.getenv("ANDROID_SDK_ROOT") ?: ""
environment("ANDROID_HOME", androidHome)
environment("ANDROID_JAR", "$androidHome/platforms/android-36/android.jar")
commandLine("cargo", "ndk",
"-o", "AndroidApp/app/src/main/jniLibs/",
"-t", "arm64-v8a",
"-t", "x86_64-linux-android",
"--platform", "31",
"build", "--lib", "--release")
}

Expand Down
Loading