feat(theme): themes as files (theme crate: toml subset + ints, contrast check, wire); whimsy dark + light; display reads themes/, serves THEME/THEME_NAME, init SET_THEME -> THEME_CHANGED to all windows, bar themed; k-ui follows; settings appearance; init keeps choice in sealed users/<id>/settings/, reapplies at sign-in + display restart
This commit is contained in:
@@ -61,7 +61,7 @@ impl Host for FakeHost {
|
||||
type Srv = DisplayServer<GridFramebuffer<W, H>, FakeHost>;
|
||||
|
||||
fn server() -> Srv {
|
||||
DisplayServer::new(GridFramebuffer::new(), FakeHost::default())
|
||||
DisplayServer::new(GridFramebuffer::new(), FakeHost::default(), crate::themes::Themes::new())
|
||||
}
|
||||
|
||||
/// Opens a window through launcher `opener`: its badge.
|
||||
@@ -187,3 +187,48 @@ fn a_present_outside_the_window_is_clipped() {
|
||||
assert_eq!(s.framebuffer().pixel(31, H - 1), Some(RED));
|
||||
assert_ne!(s.framebuffer().pixel(29, H - 1), Some(RED), "left of the rectangle is untouched");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn init_switches_the_theme_and_every_window_hears_of_it() {
|
||||
let light = include_str!("../../../../../disk/themes/whimsy-light.toml");
|
||||
let mut themes = crate::themes::Themes::new();
|
||||
themes.add(light).unwrap();
|
||||
let mut s = DisplayServer::new(GridFramebuffer::new(), FakeHost::default(), themes);
|
||||
let t = open(&mut s, 1, b"Terminal");
|
||||
let snake = open(&mut s, 2, b"Snake");
|
||||
let (n1, n2) = (CapSlot::new(9).unwrap(), CapSlot::new(10).unwrap());
|
||||
s.handle_call(t, [w::SUBSCRIBE, 0, 0, 0], Some(n1));
|
||||
s.handle_call(snake, [w::SUBSCRIBE, 0, 0, 0], Some(n2));
|
||||
let names: Vec<_> = (0..)
|
||||
.map_while(|i| match s.handle_call(t, [w::THEME_NAME, i, 0, 0], None).0 {
|
||||
[w::OK, a, b, c] => {
|
||||
let (n, len) = w::unpack_name([a, b, c]);
|
||||
Some(n[..len].to_vec())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(names, [b"Whimsy Dark".to_vec(), b"Whimsy Light".to_vec()]);
|
||||
|
||||
let read = |s: &mut Srv| -> (usize, theme::Theme) {
|
||||
let mut words = [0; w::THEME_WORDS];
|
||||
let mut head = 0;
|
||||
for part in 0..w::THEME_WORDS / 2 {
|
||||
let r = s.handle_call(snake, [w::THEME, part, 0, 0], None).0;
|
||||
assert_eq!(r[0], w::OK);
|
||||
head = r[1];
|
||||
words[part * 2..part * 2 + 2].copy_from_slice(&r[2..]);
|
||||
}
|
||||
(head >> 32, theme::wire::decode(words))
|
||||
};
|
||||
assert_eq!(read(&mut s).0, 0);
|
||||
let n = w::pack_name(b"Whimsy Light");
|
||||
assert_eq!(s.handle_call(5, [w::SET_THEME, n[0], n[1], n[2]], None).0[0], MALFORMED, "init's alone");
|
||||
assert_eq!(s.handle_call(0, [w::SET_THEME, n[0], n[1], n[2]], None).0[0], w::OK);
|
||||
let (index, t2) = read(&mut s);
|
||||
assert_eq!((index, t2.background), (1, theme::parse(light).unwrap().background));
|
||||
assert!(s.host().signalled.contains(&n1) && s.host().signalled.contains(&n2), "behind or in front");
|
||||
assert_eq!(s.handle_call(t, [w::POLL, 0, 0, 0], None).0[0], w::THEME_CHANGED);
|
||||
let bogus = w::pack_name(b"Nope");
|
||||
assert_eq!(s.handle_call(0, [w::SET_THEME, bogus[0], bogus[1], bogus[2]], None).0[0], MALFORMED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user