Support opacity

This commit is contained in:
Jeremy Soller 2024-02-12 12:36:30 -07:00
parent c93032ab9d
commit 72c97fd5fc
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
4 changed files with 86 additions and 24 deletions

View file

@ -22,6 +22,7 @@ light = Light
syntax-dark = Color scheme dark
syntax-light = Color scheme light
default-zoom-step = Zoom steps
opacity = Background opacity
### Font
font = Font

View file

@ -70,6 +70,7 @@ pub struct Config {
pub bold_font_weight: u16,
pub font_stretch: u16,
pub font_size_zoom_step_mul_100: u16,
pub opacity: u8,
pub profiles: BTreeMap<ProfileId, Profile>,
pub show_headerbar: bool,
pub use_bright_bold: bool,
@ -90,6 +91,7 @@ impl Default for Config {
font_size_zoom_step_mul_100: 100,
font_stretch: Stretch::Normal.to_number(),
font_weight: Weight::NORMAL.0,
opacity: 100,
profiles: BTreeMap::new(),
show_headerbar: true,
syntax_theme_dark: "COSMIC Dark".to_string(),
@ -114,6 +116,10 @@ impl Config {
Metrics::new(font_size, line_height)
}
pub fn opacity_ratio(&self) -> f32 {
(self.opacity as f32) / 100.0
}
// Get a sorted and adjusted for duplicates list of profiles names and ids
pub fn profile_names(&self) -> Vec<(String, ProfileId)> {
let mut profile_names = Vec::<(String, ProfileId)>::with_capacity(self.profiles.len());

View file

@ -23,6 +23,7 @@ use cosmic::{
use cosmic_text::{fontdb::FaceInfo, Family, Stretch, Weight};
use std::{
any::TypeId,
cmp,
collections::{BTreeMap, BTreeSet, HashMap},
env, process,
sync::{atomic::Ordering, Mutex},
@ -266,6 +267,7 @@ pub enum Message {
PaneResized(pane_grid::ResizeEvent),
Modifiers(Modifiers),
MouseEnter(pane_grid::Pane),
Opacity(u8),
Paste(Option<segmented_button::Entity>),
PasteValue(Option<segmented_button::Entity>, String),
ProfileCollapse(ProfileId),
@ -728,8 +730,14 @@ impl App {
Message::DefaultZoomStep(index)
}),
),
)
.add(
widget::settings::item::builder(fl!("opacity"))
.description(format!("{}%", self.config.opacity))
.control(widget::slider(0..=100, self.config.opacity, |opacity| {
Message::Opacity(opacity)
})),
);
//TODO: background opacity
let mut font_section = widget::settings::view_section(fl!("font"))
.add(
@ -934,6 +942,7 @@ impl Application for App {
/// Creates the application, and optionally emits command on initialize.
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
core.window.content_container = false;
core.window.show_headerbar = flags.config.show_headerbar;
// Update font name from config
@ -1106,6 +1115,33 @@ impl Application for App {
/// Handle application events here.
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
// Helper for updating config values efficiently
macro_rules! config_set {
($name: ident, $value: expr) => {
match &self.config_handler {
Some(config_handler) => {
match paste::paste! { self.config.[<set_ $name>](config_handler, $value) } {
Ok(_) => {}
Err(err) => {
log::warn!(
"failed to save config {:?}: {}",
stringify!($name),
err
);
}
}
}
None => {
self.config.$name = $value;
log::warn!(
"failed to save config {:?}: no config handler",
stringify!($name)
);
}
}
};
}
match message {
Message::AppTheme(app_theme) => {
self.config.app_theme = app_theme;
@ -1291,6 +1327,9 @@ impl Application for App {
self.pane_model.focus = pane;
return self.update_focus();
}
Message::Opacity(opacity) => {
config_set!(opacity, cmp::min(100, opacity));
}
Message::PaneClicked(pane) => {
self.pane_model.focus = pane;
return self.update_title(Some(pane));
@ -1443,10 +1482,7 @@ impl Application for App {
}
}
Message::FocusFollowMouse(focus_follow_mouse) => {
if focus_follow_mouse != self.config.focus_follow_mouse {
self.config.focus_follow_mouse = focus_follow_mouse;
return self.save_config();
}
config_set!(focus_follow_mouse, focus_follow_mouse);
}
Message::SystemThemeChange => {
return self.update_config();
@ -1751,10 +1787,11 @@ impl Application for App {
fn view(&self) -> Element<Self::Message> {
let cosmic_theme = self.core().system_theme().cosmic();
let cosmic_theme::Spacing { space_xxs, .. } = cosmic_theme.spacing;
{
// Update terminal window color
//TODO: do this only when theme changes?
let color = Color::from(cosmic_theme.bg_color());
let color = Color::from(cosmic_theme.background.base);
let bytes = color.into_rgba8();
let data = (bytes[2] as u32)
| ((bytes[1] as u32) << 8)
@ -1773,6 +1810,7 @@ impl Application for App {
}
}
}
let pane_grid = PaneGrid::new(&self.pane_model.panes, |pane, tab_model, _is_maximized| {
let mut tab_column = widget::column::with_capacity(1);
@ -1798,9 +1836,13 @@ impl Application for App {
.unwrap_or_else(widget::Id::unique);
match tab_model.data::<Mutex<Terminal>>(entity) {
Some(terminal) => {
let mut terminal_box = terminal_box(terminal).id(terminal_id).on_context_menu(
move |position_opt| Message::TabContextMenu(pane, position_opt),
);
let mut terminal_box = terminal_box(terminal)
.id(terminal_id)
.on_context_menu(move |position_opt| {
Message::TabContextMenu(pane, position_opt)
})
.opacity(self.config.opacity_ratio())
.padding(space_xxs);
if self.config.focus_follow_mouse {
terminal_box =
@ -1891,11 +1933,11 @@ impl Application for App {
})
.width(Length::Fill)
.height(Length::Fill)
.spacing(space_xxs)
.on_click(Message::PaneClicked)
.on_resize(space_xxs, Message::PaneResized)
.on_drag(Message::PaneDragged);
//TODO: apply window border radius xs at bottom of window
pane_grid.into()
}

View file

@ -44,11 +44,13 @@ use crate::{terminal::Metadata, Terminal, TerminalScroll};
pub struct TerminalBox<'a, Message> {
terminal: &'a Mutex<Terminal>,
id: Option<Id>,
border: Border,
padding: Padding,
click_timing: Duration,
context_menu: Option<Point>,
on_context_menu: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
on_mouse_enter: Option<Box<dyn Fn() -> Message + 'a>>,
opacity: Option<f32>,
mouse_inside_boundary: Option<bool>,
}
@ -60,11 +62,13 @@ where
Self {
terminal,
id: None,
border: Border::default(),
padding: Padding::new(0.0),
click_timing: Duration::from_millis(500),
context_menu: None,
on_context_menu: None,
on_mouse_enter: None,
opacity: None,
mouse_inside_boundary: None,
}
}
@ -74,6 +78,11 @@ where
self
}
pub fn border<B: Into<Border>>(mut self, border: B) -> Self {
self.border = border.into();
self
}
pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
self.padding = padding.into();
self
@ -101,6 +110,11 @@ where
self.on_mouse_enter = Some(Box::new(on_mouse_enter));
self
}
pub fn opacity(mut self, opacity: f32) -> Self {
self.opacity = Some(opacity);
self
}
}
pub fn terminal_box<Message>(terminal: &Mutex<Terminal>) -> TerminalBox<'_, Message>
@ -248,17 +262,18 @@ where
renderer.fill_quad(
Quad {
bounds: Rectangle::new(
view_position,
Size::new(view_w as f32 + scrollbar_w, view_h as f32),
),
bounds: layout.bounds(),
border: self.border,
..Default::default()
},
Color::new(
background_color.r() as f32 / 255.0,
background_color.g() as f32 / 255.0,
background_color.b() as f32 / 255.0,
background_color.a() as f32 / 255.0,
match self.opacity {
Some(opacity) => opacity,
None => background_color.a() as f32 / 255.0,
},
),
);
}
@ -301,10 +316,6 @@ where
renderer: &mut Renderer,
is_focused: bool,
) {
if self.metadata == self.default_metadata {
return;
}
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
Color::new(
color.r() as f32 / 255.0,
@ -339,11 +350,13 @@ where
}
let metadata = &self.metadata_set[self.metadata];
let color = shade(metadata.bg, is_focused);
renderer.fill_quad(
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
cosmic_text_to_iced_color(color),
);
if metadata.bg != self.metadata_set[self.default_metadata].bg {
let color = shade(metadata.bg, is_focused);
renderer.fill_quad(
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
cosmic_text_to_iced_color(color),
);
}
if !metadata.flags.is_empty() {
let style_line_height =