Keep selected document text readable
This commit is contained in:
1 parent
d4c59706d8
commit
e42f580510
2 files changed
+90
-1
No files matched your search
@@ -46,7 +46,9 @@ impl Render for LokView {
|
||||
let focus = self.focus.clone();
|
||||
let colors = &cx.theme().colors;
|
||||
let paper = super::paper();
|
||||
let (selection_color, caret_color) = (colors.selection, colors.focus);
|
||||
// Opaque overlays hide glyphs already painted in the tiles.
|
||||
let selection_color = colors.selection.alpha(colors.selection.a.min(0.3));
|
||||
let caret_color = colors.focus;
|
||||
let canvas_color = colors.sunken;
|
||||
let caret_width = cx.theme().caret_width().to_pixels(window.rem_size());
|
||||
self.handle_size = cx.theme().handle_hit().to_pixels(window.rem_size());
|
||||
|
||||
@@ -83,6 +83,93 @@ fn a_dark_app_paints_the_page_white() {
|
||||
assert!(light > 240, "the view paints the page white: {light}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selection_keeps_document_text_readable_across_themes() {
|
||||
use ely_gpui_component::{
|
||||
devtools::{contrast, over},
|
||||
theme::{ActiveTheme, Mode, Palette, Theme},
|
||||
};
|
||||
|
||||
let Some(install) = crate::client::tests::install() else {
|
||||
eprintln!("SKIP: no pinned LOK build");
|
||||
return;
|
||||
};
|
||||
let mut cx = TestAppContext::single();
|
||||
cx.update(ely_gpui_component::init_for_tests);
|
||||
let (view, worker) = cx.update(|app| live_view(app, &install));
|
||||
let doc = cx.update(|app| view.read(app).doc.clone());
|
||||
let shown = view.clone();
|
||||
let window = cx.add_window(move |_, _| Host(shown));
|
||||
worker
|
||||
.lock()
|
||||
.expect("the worker")
|
||||
.run(&doc, "edit.select_all", &[])
|
||||
.expect("select all");
|
||||
assert!(
|
||||
settle(&cx, |app| !view.read(app).selection.is_empty()),
|
||||
"the selection arrives"
|
||||
);
|
||||
|
||||
let mut themes = vec![
|
||||
("dark".to_string(), Mode::Dark, None),
|
||||
("light".to_string(), Mode::Light, None),
|
||||
];
|
||||
for (name, mode, color) in [
|
||||
("omarchy dark", Mode::Dark, 0x292e42),
|
||||
("omarchy light", Mode::Light, 0xccd0da),
|
||||
] {
|
||||
let mut palette = match mode {
|
||||
Mode::Dark => Palette::dark(false),
|
||||
Mode::Light => Palette::light(false),
|
||||
};
|
||||
palette.selection = gpui::rgb(color).into();
|
||||
themes.push((name.to_string(), mode, Some(palette)));
|
||||
}
|
||||
let mut translucent = Palette::dark(false);
|
||||
translucent.selection = gpui::rgb(0x292e42).into();
|
||||
translucent.selection.a = 0.15;
|
||||
themes.push(("translucent".to_string(), Mode::Dark, Some(translucent)));
|
||||
|
||||
for (name, mode, palette) in themes {
|
||||
cx.update(|app| {
|
||||
Theme::set_palette(mode, palette, app);
|
||||
Theme::set_mode_now(mode, app);
|
||||
});
|
||||
cx.update_window(window.into(), |_, window, app| {
|
||||
window.draw(app).clear(app);
|
||||
let source = app.theme().colors.selection;
|
||||
let selected: Vec<_> = window
|
||||
.painted_quads()
|
||||
.into_iter()
|
||||
.filter_map(|quad| quad.background.as_solid())
|
||||
.filter(|color| color.alpha(1.0) == source.alpha(1.0))
|
||||
.collect();
|
||||
assert!(!selected.is_empty(), "{name}: the selection is painted");
|
||||
for color in selected {
|
||||
for (text, background) in [(gpui::black(), paper()), (gpui::white(), gpui::black())]
|
||||
{
|
||||
let ratio = contrast(over(color, text), over(color, background));
|
||||
assert!(
|
||||
ratio >= 4.5,
|
||||
"{name}: selected text stays readable: {ratio}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
color.a > 0.0 && color.a <= source.a,
|
||||
"{name}: the theme's opacity is respected"
|
||||
);
|
||||
if source.a < 0.3 {
|
||||
assert_eq!(
|
||||
color.a, source.a,
|
||||
"{name}: a translucent theme stays unchanged"
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect("the window lives");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_failed_tile_reports_and_retries_on_a_move() {
|
||||
let Some(install) = crate::client::tests::install() else {
|
||||
|
||||
Reference in new issue
Block a user