chore: update iced/libcosmic

This commit is contained in:
Vukašin Vojinović 2024-10-24 00:15:05 +02:00 committed by Victoria Brekenfeld
parent 0d0b89d538
commit 7de52054ff
12 changed files with 502 additions and 549 deletions

603
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,10 @@ use crate::{
use calloop::LoopHandle; use calloop::LoopHandle;
use cosmic::{ use cosmic::{
iced::widget::{column, container, horizontal_space, row, vertical_space}, iced::{
widget::{column, container, horizontal_space, row, vertical_space},
Alignment,
},
iced_core::{Background, Border, Color, Length}, iced_core::{Background, Border, Color, Length},
theme, theme,
widget::{icon::from_name, text}, widget::{icon::from_name, text},
@ -66,7 +69,7 @@ impl Program for ResizeIndicatorInternal {
fn view(&self) -> cosmic::Element<'_, Self::Message> { fn view(&self) -> cosmic::Element<'_, Self::Message> {
let edges = self.edges.lock().unwrap(); let edges = self.edges.lock().unwrap();
let icon_container_style = || { let icon_container_style = || {
theme::Container::custom(|theme| container::Appearance { theme::Container::custom(|theme| container::Style {
icon_color: Some(Color::from(theme.cosmic().accent.on)), icon_color: Some(Color::from(theme.cosmic().accent.on)),
text_color: Some(Color::from(theme.cosmic().accent.on)), text_color: Some(Color::from(theme.cosmic().accent.on)),
background: Some(Background::Color(theme.cosmic().accent_color().into())), background: Some(Background::Color(theme.cosmic().accent_color().into())),
@ -90,14 +93,13 @@ impl Program for ResizeIndicatorInternal {
.prefer_svg(true) .prefer_svg(true)
.apply(container) .apply(container)
.padding(8) .padding(8)
.style(icon_container_style()) .class(icon_container_style())
.width(Length::Shrink) .width(Length::Shrink)
.apply(container) .apply(container)
.center_x() .center_x(Length::Fill)
.width(Length::Fill)
.into() .into()
} else { } else {
vertical_space(36).into() vertical_space().height(36).into()
}, },
row(vec![ row(vec![
if edges.contains(ResizeEdge::LEFT) { if edges.contains(ResizeEdge::LEFT) {
@ -110,35 +112,32 @@ impl Program for ResizeIndicatorInternal {
.prefer_svg(true) .prefer_svg(true)
.apply(container) .apply(container)
.padding(8) .padding(8)
.style(icon_container_style()) .class(icon_container_style())
.width(Length::Shrink) .width(Length::Shrink)
.apply(container) .apply(container)
.center_y() .center_y(Length::Fill)
.height(Length::Fill)
.into() .into()
} else { } else {
horizontal_space(36).into() horizontal_space().width(36).into()
}, },
row(vec![ row(vec![
text::heading(&self.shortcut1).into(), text::heading(&self.shortcut1).into(),
text::body(fl!("grow-window")).into(), text::body(fl!("grow-window")).into(),
horizontal_space(40).into(), horizontal_space().width(40).into(),
text::heading(&self.shortcut2).into(), text::heading(&self.shortcut2).into(),
text::body(fl!("shrink-window")).into(), text::body(fl!("shrink-window")).into(),
]) ])
.apply(container) .apply(container)
.center_x() .align_x(Alignment::Center)
.center_y() .align_y(Alignment::Center)
.padding(16) .padding(16)
.apply(container) .apply(container)
.style(icon_container_style()) .class(icon_container_style())
.width(Length::Shrink) .width(Length::Shrink)
.height(Length::Shrink) .height(Length::Shrink)
.apply(container) .apply(container)
.height(Length::Fill) .center_x(Length::Fill)
.width(Length::Fill) .center_y(Length::Fill)
.center_x()
.center_y()
.into(), .into(),
if edges.contains(ResizeEdge::RIGHT) { if edges.contains(ResizeEdge::RIGHT) {
from_name(if self.direction == ResizeDirection::Outwards { from_name(if self.direction == ResizeDirection::Outwards {
@ -150,14 +149,13 @@ impl Program for ResizeIndicatorInternal {
.prefer_svg(true) .prefer_svg(true)
.apply(container) .apply(container)
.padding(8) .padding(8)
.style(icon_container_style()) .class(icon_container_style())
.height(Length::Shrink) .height(Length::Shrink)
.apply(container) .apply(container)
.center_y() .center_y(Length::Fill)
.height(Length::Fill)
.into() .into()
} else { } else {
horizontal_space(36).into() horizontal_space().width(36).into()
}, },
]) ])
.width(Length::Fill) .width(Length::Fill)
@ -173,14 +171,13 @@ impl Program for ResizeIndicatorInternal {
.prefer_svg(true) .prefer_svg(true)
.apply(container) .apply(container)
.padding(8) .padding(8)
.style(icon_container_style()) .class(icon_container_style())
.width(Length::Shrink) .width(Length::Shrink)
.apply(container) .apply(container)
.center_x() .center_x(Length::Fill)
.width(Length::Fill)
.into() .into()
} else { } else {
vertical_space(36).into() vertical_space().height(36).into()
}, },
]) ])
.into() .into()

View file

@ -14,9 +14,9 @@ use crate::{
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
use cosmic::{ use cosmic::{
iced::{id::Id, widget as iced_widget}, iced::{id::Id, widget as iced_widget, Alignment},
iced_core::{border::Radius, Background, Border, Color, Length}, iced_core::{border::Radius, Background, Border, Color, Length},
iced_runtime::Command, iced_runtime::Task,
iced_widget::scrollable::AbsoluteOffset, iced_widget::scrollable::AbsoluteOffset,
theme, widget as cosmic_widget, Apply, Element as CosmicElement, Theme, theme, widget as cosmic_widget, Apply, Element as CosmicElement, Theme,
}; };
@ -712,7 +712,7 @@ impl Program for CosmicStackInternal {
&mut self, &mut self,
message: Self::Message, message: Self::Message,
loop_handle: &LoopHandle<'static, crate::state::State>, loop_handle: &LoopHandle<'static, crate::state::State>,
) -> Command<Self::Message> { ) -> Task<Self::Message> {
match message { match message {
Message::DragStart => { Message::DragStart => {
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() { if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
@ -874,7 +874,7 @@ impl Program for CosmicStackInternal {
} }
_ => unreachable!(), _ => unreachable!(),
} }
Command::none() Task::none()
} }
fn view(&self) -> CosmicElement<'_, Self::Message> { fn view(&self) -> CosmicElement<'_, Self::Message> {
@ -890,8 +890,8 @@ impl Program for CosmicStackInternal {
.size(16) .size(16)
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.style(if group_focused { .class(if group_focused {
theme::Svg::custom(|theme| iced_widget::svg::Appearance { theme::Svg::custom(|theme| iced_widget::svg::Style {
color: Some(if theme.cosmic().is_dark { color: Some(if theme.cosmic().is_dark {
Color::BLACK Color::BLACK
} else { } else {
@ -903,7 +903,7 @@ impl Program for CosmicStackInternal {
}) })
.apply(iced_widget::container) .apply(iced_widget::container)
.padding([4, 24]) .padding([4, 24])
.center_y() .align_y(Alignment::Center)
.apply(iced_widget::mouse_area) .apply(iced_widget::mouse_area)
.on_press(Message::DragStart) .on_press(Message::DragStart)
.on_right_press(Message::Menu) .on_right_press(Message::Menu)
@ -935,7 +935,8 @@ impl Program for CosmicStackInternal {
.height(Length::Fill) .height(Length::Fill)
.width(Length::Fill), .width(Length::Fill),
), ),
iced_widget::horizontal_space(0) iced_widget::horizontal_space()
.width(Length::Fixed(0.0))
.apply(iced_widget::container) .apply(iced_widget::container)
.padding([64, 24]) .padding([64, 24])
.apply(iced_widget::mouse_area) .apply(iced_widget::mouse_area)
@ -953,10 +954,10 @@ impl Program for CosmicStackInternal {
iced_widget::row(elements) iced_widget::row(elements)
.height(TAB_HEIGHT as u16) .height(TAB_HEIGHT as u16)
.width(Length::Fill) //width as u16) .width(Length::Fill)
.apply(iced_widget::container) .apply(iced_widget::container)
.center_y() .align_y(Alignment::Center)
.style(theme::Container::custom(move |theme| { .class(theme::Container::custom(move |theme| {
let background = if group_focused { let background = if group_focused {
Some(Background::Color(theme.cosmic().accent_color().into())) Some(Background::Color(theme.cosmic().accent_color().into()))
} else { } else {
@ -965,7 +966,7 @@ impl Program for CosmicStackInternal {
))) )))
}; };
iced_widget::container::Appearance { iced_widget::container::Style {
icon_color: Some(Color::from(theme.cosmic().background.on)), icon_color: Some(Color::from(theme.cosmic().background.on)),
text_color: Some(Color::from(theme.cosmic().background.on)), text_color: Some(Color::from(theme.cosmic().background.on)),
background, background,

View file

@ -5,11 +5,7 @@ use cosmic::{
alignment, event, alignment, event,
layout::{Layout, Limits, Node}, layout::{Layout, Limits, Node},
mouse, overlay, renderer, mouse, overlay, renderer,
widget::{ widget::{operation::Operation, tree::Tree, Id, Widget},
operation::{Operation, OperationOutputWrapper},
tree::Tree,
Id, Widget,
},
Border, Clipboard, Color, Length, Rectangle, Shell, Size, Border, Clipboard, Color, Length, Rectangle, Shell, Size,
}, },
iced_widget::scrollable::AbsoluteOffset, iced_widget::scrollable::AbsoluteOffset,
@ -54,19 +50,19 @@ pub(super) enum TabRuleTheme {
impl From<TabRuleTheme> for theme::Rule { impl From<TabRuleTheme> for theme::Rule {
fn from(theme: TabRuleTheme) -> Self { fn from(theme: TabRuleTheme) -> Self {
match theme { match theme {
TabRuleTheme::ActiveActivated => Self::custom(|theme| widget::rule::Appearance { TabRuleTheme::ActiveActivated => Self::custom(|theme| widget::rule::Style {
color: theme.cosmic().accent_color().into(), color: theme.cosmic().accent_color().into(),
width: 4, width: 4,
radius: 0.0.into(), radius: 0.0.into(),
fill_mode: FillMode::Full, fill_mode: FillMode::Full,
}), }),
TabRuleTheme::ActiveDeactivated => Self::custom(|theme| widget::rule::Appearance { TabRuleTheme::ActiveDeactivated => Self::custom(|theme| widget::rule::Style {
color: theme.cosmic().palette.neutral_5.into(), color: theme.cosmic().palette.neutral_5.into(),
width: 4, width: 4,
radius: 0.0.into(), radius: 0.0.into(),
fill_mode: FillMode::Full, fill_mode: FillMode::Full,
}), }),
TabRuleTheme::Default => Self::custom(|theme| widget::rule::Appearance { TabRuleTheme::Default => Self::custom(|theme| widget::rule::Style {
color: theme.cosmic().palette.neutral_5.into(), color: theme.cosmic().palette.neutral_5.into(),
width: 4, width: 4,
radius: 8.0.into(), radius: 8.0.into(),
@ -96,11 +92,11 @@ impl TabBackgroundTheme {
} }
} }
impl From<TabBackgroundTheme> for theme::Container { impl From<TabBackgroundTheme> for theme::Container<'_> {
fn from(background_theme: TabBackgroundTheme) -> Self { fn from(background_theme: TabBackgroundTheme) -> Self {
match background_theme { match background_theme {
TabBackgroundTheme::ActiveActivated => { TabBackgroundTheme::ActiveActivated => {
Self::custom(move |theme| widget::container::Appearance { Self::custom(move |theme| widget::container::Style {
icon_color: Some(Color::from(theme.cosmic().accent_text_color())), icon_color: Some(Color::from(theme.cosmic().accent_text_color())),
text_color: Some(Color::from(theme.cosmic().accent_text_color())), text_color: Some(Color::from(theme.cosmic().accent_text_color())),
background: Some(background_theme.background_color(theme).into()), background: Some(background_theme.background_color(theme).into()),
@ -113,7 +109,7 @@ impl From<TabBackgroundTheme> for theme::Container {
}) })
} }
TabBackgroundTheme::ActiveDeactivated => { TabBackgroundTheme::ActiveDeactivated => {
Self::custom(move |theme| widget::container::Appearance { Self::custom(move |theme| widget::container::Style {
icon_color: None, icon_color: None,
text_color: None, text_color: None,
background: Some(background_theme.background_color(theme).into()), background: Some(background_theme.background_color(theme).into()),
@ -215,20 +211,19 @@ impl<Message: TabMessage + 'static> Tab<Message> {
.icon() .icon()
.apply(widget::button) .apply(widget::button)
.padding(0) .padding(0)
.style(theme::iced::Button::Text); .class(theme::iced::Button::Text);
if let Some(close_message) = self.close_message { if let Some(close_message) = self.close_message {
close_button = close_button.on_press(close_message); close_button = close_button.on_press(close_message);
} }
let items = vec![ let items = vec![
widget::vertical_rule(4).style(self.rule_theme).into(), widget::vertical_rule(4).class(self.rule_theme).into(),
self.app_icon self.app_icon
.clone() .clone()
.apply(widget::container) .apply(widget::container)
.height(Length::Fill)
.width(Length::Shrink) .width(Length::Shrink)
.padding([2, 4]) .padding([2, 4])
.center_y() .center_y(Length::Fill)
.into(), .into(),
tab_text(self.title, self.active) tab_text(self.title, self.active)
.font(self.font) .font(self.font)
@ -238,10 +233,9 @@ impl<Message: TabMessage + 'static> Tab<Message> {
.into(), .into(),
close_button close_button
.apply(widget::container) .apply(widget::container)
.height(Length::Fill)
.width(Length::Shrink) .width(Length::Shrink)
.padding([2, 4]) .padding([2, 4])
.center_y() .center_y(Length::Fill)
.align_x(alignment::Horizontal::Right) .align_x(alignment::Horizontal::Right)
.into(), .into(),
]; ];
@ -269,7 +263,7 @@ pub(super) struct TabInternal<'a, Message: TabMessage> {
id: Id, id: Id,
idx: usize, idx: usize,
active: bool, active: bool,
background: theme::Container, background: theme::Container<'a>,
elements: Vec<cosmic::Element<'a, Message>>, elements: Vec<cosmic::Element<'a, Message>>,
press_message: Option<Message>, press_message: Option<Message>,
right_click_message: Option<Message>, right_click_message: Option<Message>,
@ -347,7 +341,7 @@ where
tree: &mut Tree, tree: &mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Message>>, operation: &mut dyn Operation<()>,
) { ) {
operation.container(None, layout.bounds(), &mut |operation| { operation.container(None, layout.bounds(), &mut |operation| {
self.elements self.elements
@ -454,8 +448,8 @@ where
cursor: mouse::Cursor, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
use cosmic::widget::container::StyleSheet; use cosmic::widget::container::Catalog;
let style = theme.appearance(&self.background); let style = theme.style(&self.background);
draw_background(renderer, &style, layout.bounds()); draw_background(renderer, &style, layout.bounds());
@ -486,7 +480,8 @@ where
tree: &'b mut Tree, tree: &'b mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
translation: cosmic::iced::Vector,
) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> { ) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> {
overlay::from_children(&mut self.elements, tree, layout, renderer) overlay::from_children(&mut self.elements, tree, layout, renderer, translation)
} }
} }

View file

@ -84,7 +84,7 @@ impl TabText {
vertical_alignment: alignment::Vertical::Center, vertical_alignment: alignment::Vertical::Center,
shaping: Shaping::Advanced, shaping: Shaping::Advanced,
line_height: LineHeight::default(), line_height: LineHeight::default(),
wrap: cosmic::iced::advanced::text::Wrap::None, wrapping: cosmic::iced::advanced::text::Wrapping::None,
}) })
} }
} }

View file

@ -8,7 +8,7 @@ use cosmic::{
widget::{ widget::{
operation::{ operation::{
scrollable::{AbsoluteOffset, RelativeOffset}, scrollable::{AbsoluteOffset, RelativeOffset},
Operation, OperationOutputWrapper, Scrollable, Operation, Scrollable,
}, },
tree::{self, Tree}, tree::{self, Tree},
Widget, Widget,
@ -16,10 +16,9 @@ use cosmic::{
Background, Border, Clipboard, Color, Length, Point, Rectangle, Renderer, Shell, Size, Background, Border, Clipboard, Color, Length, Point, Rectangle, Renderer, Shell, Size,
Vector, Vector,
}, },
iced_style::container::StyleSheet as ContainerStyleSheet,
iced_widget::container::draw_background, iced_widget::container::draw_background,
theme, theme,
widget::icon::from_name, widget::{container::Catalog, icon::from_name},
Apply, Apply,
}; };
use keyframe::{ use keyframe::{
@ -45,6 +44,7 @@ struct ScrollAnimationState {
start_time: Instant, start_time: Instant,
start: Offset, start: Offset,
end: Offset, end: Offset,
extra: Offset,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -75,9 +75,24 @@ impl Scrollable for State {
start_time: Instant::now(), start_time: Instant::now(),
start: self.offset_x, start: self.offset_x,
end: new_offset, end: new_offset,
extra: Offset::Absolute(0.),
}); });
self.offset_x = new_offset; self.offset_x = new_offset;
} }
fn scroll_by(
&mut self,
offset: AbsoluteOffset,
_bounds: Rectangle,
_content_bounds: Rectangle,
) {
self.scroll_animation = Some(ScrollAnimationState {
start_time: Instant::now(),
start: self.offset_x,
end: self.offset_x,
extra: Offset::Absolute(offset.x.max(0.0)),
});
}
} }
impl Default for State { impl Default for State {
@ -145,7 +160,7 @@ where
Element::new(tab.internal(i)) Element::new(tab.internal(i))
}); });
let tabs_rule = widget::vertical_rule(4).style(if tabs.len() - 1 == active { let tabs_rule = widget::vertical_rule(4).class(if tabs.len() - 1 == active {
if activated { if activated {
TabRuleTheme::ActiveActivated TabRuleTheme::ActiveActivated
} else { } else {
@ -166,7 +181,7 @@ where
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.apply(widget::button) .apply(widget::button)
.style(theme::iced::Button::Text) .class(theme::iced::Button::Text)
.on_press(Message::scroll_back()); .on_press(Message::scroll_back());
let next_button = from_name("go-next-symbolic") let next_button = from_name("go-next-symbolic")
@ -174,17 +189,17 @@ where
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.apply(widget::button) .apply(widget::button)
.style(theme::iced::Button::Text) .class(theme::iced::Button::Text)
.on_press(Message::scroll_further()); .on_press(Message::scroll_further());
let mut elements = Vec::with_capacity(tabs.len() + 5); let mut elements = Vec::with_capacity(tabs.len() + 5);
elements.push(widget::vertical_rule(4).style(rule_style).into()); elements.push(widget::vertical_rule(4).class(rule_style).into());
elements.push(prev_button.into()); elements.push(prev_button.into());
elements.extend(tabs); elements.extend(tabs);
elements.push(tabs_rule.into()); elements.push(tabs_rule.into());
elements.push(next_button.into()); elements.push(next_button.into());
elements.push(widget::vertical_rule(4).style(rule_style).into()); elements.push(widget::vertical_rule(4).class(rule_style).into());
Tabs { Tabs {
elements, elements,
@ -239,6 +254,7 @@ impl State {
Vector::new( Vector::new(
animation.start.absolute(bounds.width, content_bounds.width) animation.start.absolute(bounds.width, content_bounds.width)
+ animation.extra.absolute(bounds.width, content_bounds.width) * percentage
+ (animation.end.absolute(bounds.width, content_bounds.width) + (animation.end.absolute(bounds.width, content_bounds.width)
- animation.start.absolute(bounds.width, content_bounds.width)) - animation.start.absolute(bounds.width, content_bounds.width))
* percentage, * percentage,
@ -490,9 +506,9 @@ where
height: b.bounds().height, height: b.bounds().height,
}); });
let background_style = ContainerStyleSheet::appearance( let background_style = Catalog::style(
theme, theme,
&theme::Container::custom(|theme| widget::container::Appearance { &theme::Container::custom(|theme| widget::container::Style {
icon_color: None, icon_color: None,
text_color: None, text_color: None,
background: Some(Background::Color(super::tab::primary_container_color( background: Some(Background::Color(super::tab::primary_container_color(
@ -666,10 +682,12 @@ where
tree: &mut Tree, tree: &mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Message>>, operation: &mut dyn Operation<()>,
) { ) {
let state = tree.state.downcast_mut::<State>(); let state = tree.state.downcast_mut::<State>();
let bounds = layout.bounds(); let bounds = layout.bounds();
let content_layout = layout.children().next().unwrap();
let content_bounds = content_layout.bounds();
state.cleanup_old_animations(); state.cleanup_old_animations();
@ -677,6 +695,7 @@ where
state, state,
self.id.as_ref(), self.id.as_ref(),
bounds, bounds,
content_bounds,
Vector { x: 0.0, y: 0.0 }, /* seemingly unused */ Vector { x: 0.0, y: 0.0 }, /* seemingly unused */
); );
@ -819,6 +838,7 @@ where
start_time: Instant::now(), start_time: Instant::now(),
start: Offset::Absolute(offset.x), start: Offset::Absolute(offset.x),
end: Offset::Absolute(new_offset.x), end: Offset::Absolute(new_offset.x),
extra: Offset::Absolute(0.),
}); });
state.offset_x = Offset::Absolute(new_offset.x); state.offset_x = Offset::Absolute(new_offset.x);
} }
@ -993,7 +1013,8 @@ where
tree: &'b mut Tree, tree: &'b mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
translation: cosmic::iced::Vector,
) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> { ) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> {
overlay::from_children(&mut self.elements, tree, layout, renderer) overlay::from_children(&mut self.elements, tree, layout, renderer, translation)
} }
} }

View file

@ -38,16 +38,16 @@ impl Program for StackHoverInternal {
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.into(), .into(),
horizontal_space(16).into(), horizontal_space().width(16).into(),
text::title3(fl!("stack-windows")).into(), text::title3(fl!("stack-windows")).into(),
]) ])
.align_items(Alignment::Center) .align_y(Alignment::Center)
.apply(container) .apply(container)
.center_x() .align_x(Alignment::Center)
.center_y() .align_y(Alignment::Center)
.padding(16) .padding(16)
.apply(container) .apply(container)
.style(theme::Container::custom(|theme| container::Appearance { .class(theme::Container::custom(|theme| container::Style {
icon_color: Some(Color::from(theme.cosmic().accent.on)), icon_color: Some(Color::from(theme.cosmic().accent.on)),
text_color: Some(Color::from(theme.cosmic().accent.on)), text_color: Some(Color::from(theme.cosmic().accent.on)),
background: Some(Background::Color(theme.cosmic().accent_color().into())), background: Some(Background::Color(theme.cosmic().accent_color().into())),
@ -61,10 +61,8 @@ impl Program for StackHoverInternal {
.width(Length::Shrink) .width(Length::Shrink)
.height(Length::Shrink) .height(Length::Shrink)
.apply(container) .apply(container)
.width(Length::Fill) .center_x(Length::Fill)
.height(Length::Fill) .center_y(Length::Fill)
.center_x()
.center_y()
.into() .into()
} }
} }

View file

@ -34,16 +34,16 @@ impl Program for SwapIndicatorInternal {
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.into(), .into(),
horizontal_space(16).into(), horizontal_space().width(16).into(),
text::title3(fl!("swap-windows")).into(), text::title3(fl!("swap-windows")).into(),
]) ])
.align_items(Alignment::Center) .align_y(Alignment::Center)
.apply(container) .apply(container)
.center_x() .align_x(Alignment::Center)
.center_y() .align_y(Alignment::Center)
.padding(16) .padding(16)
.apply(container) .apply(container)
.style(theme::Container::custom(|theme| container::Appearance { .class(theme::Container::custom(|theme| container::Style {
icon_color: Some(Color::from(theme.cosmic().accent.on)), icon_color: Some(Color::from(theme.cosmic().accent.on)),
text_color: Some(Color::from(theme.cosmic().accent.on)), text_color: Some(Color::from(theme.cosmic().accent.on)),
background: Some(Background::Color(theme.cosmic().accent_color().into())), background: Some(Background::Color(theme.cosmic().accent_color().into())),
@ -57,10 +57,8 @@ impl Program for SwapIndicatorInternal {
.width(Length::Shrink) .width(Length::Shrink)
.height(Length::Shrink) .height(Length::Shrink)
.apply(container) .apply(container)
.height(Length::Fill) .center_x(Length::Fill)
.width(Length::Fill) .center_y(Length::Fill)
.center_x()
.center_y()
.into() .into()
} }
} }

View file

@ -11,7 +11,7 @@ use crate::{
}, },
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
use cosmic::iced::{Color, Command}; use cosmic::iced::{Color, Task};
use smithay::{ use smithay::{
backend::{ backend::{
input::KeyState, input::KeyState,
@ -404,7 +404,7 @@ impl Program for CosmicWindowInternal {
&mut self, &mut self,
message: Self::Message, message: Self::Message,
loop_handle: &LoopHandle<'static, crate::state::State>, loop_handle: &LoopHandle<'static, crate::state::State>,
) -> Command<Self::Message> { ) -> Task<Self::Message> {
match message { match message {
Message::DragStart => { Message::DragStart => {
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() { if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
@ -504,7 +504,7 @@ impl Program for CosmicWindowInternal {
} }
} }
} }
Command::none() Task::none()
} }
fn background_color(&self, theme: &cosmic::Theme) -> Color { fn background_color(&self, theme: &cosmic::Theme) -> Color {
@ -517,7 +517,7 @@ impl Program for CosmicWindowInternal {
fn view(&self) -> cosmic::Element<'_, Self::Message> { fn view(&self) -> cosmic::Element<'_, Self::Message> {
let mut header = cosmic::widget::header_bar() let mut header = cosmic::widget::header_bar()
.start(cosmic::widget::horizontal_space(32)) .start(cosmic::widget::horizontal_space().width(32))
.title(self.last_title.lock().unwrap().clone()) .title(self.last_title.lock().unwrap().clone())
.on_drag(Message::DragStart) .on_drag(Message::DragStart)
.on_close(Message::Close) .on_close(Message::Close)
@ -528,12 +528,12 @@ impl Program for CosmicWindowInternal {
if cosmic::config::show_minimize() { if cosmic::config::show_minimize() {
header = header header = header
.on_minimize(Message::Minimize) .on_minimize(Message::Minimize)
.start(cosmic::widget::horizontal_space(40)); // 32 + 8 spacing .start(cosmic::widget::horizontal_space().width(40)); // 32 + 8 spacing
} }
if cosmic::config::show_maximize() { if cosmic::config::show_maximize() {
header = header header = header
.on_maximize(Message::Maximize) .on_maximize(Message::Maximize)
.start(cosmic::widget::horizontal_space(40)); // 32 + 8 spacing .start(cosmic::widget::horizontal_space().width(40)); // 32 + 8 spacing
} }
header.into() header.into()

View file

@ -3,17 +3,17 @@ use cosmic::{
iced_core::{ iced_core::{
event, layout, mouse, overlay, event, layout, mouse, overlay,
renderer::{Quad, Style}, renderer::{Quad, Style},
widget::{tree, Id, OperationOutputWrapper, Tree, Widget}, widget::{tree, Id, Tree, Widget},
Background, Border, Clipboard, Color, Event, Layout, Length, Rectangle, Background, Border, Clipboard, Color, Event, Layout, Length, Rectangle,
Renderer as IcedRenderer, Shell, Size, Renderer as IcedRenderer, Shell, Size,
}, },
widget::button::StyleSheet, widget::button::Catalog,
}; };
pub struct SubmenuItem<'a, Message> { pub struct SubmenuItem<'a, Message> {
elem: cosmic::Element<'a, Message>, elem: cosmic::Element<'a, Message>,
idx: usize, idx: usize,
styling: <cosmic::Theme as StyleSheet>::Style, styling: <cosmic::Theme as Catalog>::Class,
} }
impl<'a, Message> SubmenuItem<'a, Message> { impl<'a, Message> SubmenuItem<'a, Message> {
@ -25,7 +25,7 @@ impl<'a, Message> SubmenuItem<'a, Message> {
} }
} }
pub fn style(mut self, style: <cosmic::Theme as StyleSheet>::Style) -> Self { pub fn style(mut self, style: <cosmic::Theme as Catalog>::Class) -> Self {
self.styling = style; self.styling = style;
self self
} }
@ -133,7 +133,7 @@ where
state: &mut Tree, state: &mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
operation: &mut dyn cosmic::widget::Operation<OperationOutputWrapper<Message>>, operation: &mut dyn cosmic::widget::Operation<()>,
) { ) {
let state = &mut state.children[0]; let state = &mut state.children[0];
let layout = layout.children().next().unwrap(); let layout = layout.children().next().unwrap();
@ -206,10 +206,13 @@ where
state: &'b mut Tree, state: &'b mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &cosmic::Renderer, renderer: &cosmic::Renderer,
translation: cosmic::iced::Vector,
) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> { ) -> Option<overlay::Element<'b, Message, cosmic::Theme, cosmic::Renderer>> {
let state = &mut state.children[0]; let state = &mut state.children[0];
let layout = layout.children().next().unwrap(); let layout = layout.children().next().unwrap();
self.elem.as_widget_mut().overlay(state, layout, renderer) self.elem
.as_widget_mut()
.overlay(state, layout, renderer, translation)
} }
} }

View file

@ -7,10 +7,10 @@ use calloop::LoopHandle;
use cosmic::{ use cosmic::{
iced::{Alignment, Background}, iced::{Alignment, Background},
iced_core::{alignment::Horizontal, Border, Length, Rectangle as IcedRectangle}, iced_core::{alignment::Horizontal, Border, Length, Rectangle as IcedRectangle},
iced_widget::{self, text::Appearance as TextAppearance, Column, Row}, iced_widget::{self, text::Style as TextStyle, Column, Row},
theme, theme,
widget::{button, divider, horizontal_space, icon::from_name, text}, widget::{button, divider, horizontal_space, icon::from_name, text},
Apply as _, Command, Apply as _, Task,
}; };
use smithay::{ use smithay::{
backend::{ backend::{
@ -202,7 +202,7 @@ impl Program for ContextMenu {
&mut self, &mut self,
message: Self::Message, message: Self::Message,
loop_handle: &LoopHandle<'static, crate::state::State>, loop_handle: &LoopHandle<'static, crate::state::State>,
) -> Command<Self::Message> { ) -> Task<Self::Message> {
match message { match message {
Message::ItemPressed(idx) => { Message::ItemPressed(idx) => {
if let Some(Item::Entry { on_press, .. }) = self.items.get_mut(idx) { if let Some(Item::Entry { on_press, .. }) = self.items.get_mut(idx) {
@ -331,7 +331,7 @@ impl Program for ContextMenu {
} }
}; };
Command::none() Task::none()
} }
fn view(&self) -> cosmic::Element<'_, Self::Message> { fn view(&self) -> cosmic::Element<'_, Self::Message> {
@ -350,7 +350,7 @@ impl Program for ContextMenu {
match item { match item {
Item::Separator => divider::horizontal::light().into(), Item::Separator => divider::horizontal::light().into(),
Item::Submenu { title, .. } => Row::with_children(vec![ Item::Submenu { title, .. } => Row::with_children(vec![
horizontal_space(16).into(), horizontal_space().width(16).into(),
text::body(title).width(mode).into(), text::body(title).width(mode).into(),
from_name("go-next-symbolic") from_name("go-next-symbolic")
.size(16) .size(16)
@ -361,7 +361,7 @@ impl Program for ContextMenu {
.spacing(8) .spacing(8)
.width(width) .width(width)
.padding([8, 16]) .padding([8, 16])
.align_items(Alignment::Center) .align_y(Alignment::Center)
.apply(|row| item::SubmenuItem::new(row, idx)) .apply(|row| item::SubmenuItem::new(row, idx))
.style(theme::Button::MenuItem) .style(theme::Button::MenuItem)
.into(), .into(),
@ -378,20 +378,20 @@ impl Program for ContextMenu {
.size(16) .size(16)
.prefer_svg(true) .prefer_svg(true)
.icon() .icon()
.style(theme::Svg::custom(|theme| iced_widget::svg::Appearance { .class(theme::Svg::custom(|theme| iced_widget::svg::Style {
color: Some(theme.cosmic().accent.base.into()), color: Some(theme.cosmic().accent.base.into()),
})) }))
.into() .into()
} else { } else {
horizontal_space(16).into() horizontal_space().width(16).into()
}, },
text::body(title) text::body(title)
.width(mode) .width(mode)
.style(if *disabled { .class(if *disabled {
theme::Text::Custom(|theme| { theme::Text::Custom(|theme| {
let mut color = theme.cosmic().background.component.on; let mut color = theme.cosmic().background.component.on;
color.alpha *= 0.5; color.alpha *= 0.5;
TextAppearance { TextStyle {
color: Some(color.into()), color: Some(color.into()),
} }
}) })
@ -399,17 +399,17 @@ impl Program for ContextMenu {
theme::Text::Default theme::Text::Default
}) })
.into(), .into(),
horizontal_space(16).into(), horizontal_space().width(16).into(),
]; ];
if let Some(shortcut) = shortcut.as_ref() { if let Some(shortcut) = shortcut.as_ref() {
components.push( components.push(
text::body(shortcut) text::body(shortcut)
.horizontal_alignment(Horizontal::Right) .align_x(Horizontal::Right)
.width(Length::Shrink) .width(Length::Shrink)
.style(theme::Text::Custom(|theme| { .class(theme::Text::Custom(|theme| {
let mut color = theme.cosmic().background.component.on; let mut color = theme.cosmic().background.component.on;
color.alpha *= 0.75; color.alpha *= 0.75;
TextAppearance { TextStyle {
color: Some(color.into()), color: Some(color.into()),
} }
})) }))
@ -420,12 +420,12 @@ impl Program for ContextMenu {
Row::with_children(components) Row::with_children(components)
.spacing(8) .spacing(8)
.width(mode) .width(mode)
.align_items(Alignment::Center) .align_y(Alignment::Center)
.apply(button::custom) .apply(button::custom)
.width(width) .width(width)
.padding([8, 16]) .padding([8, 16])
.on_press_maybe((!disabled).then_some(Message::ItemPressed(idx))) .on_press_maybe((!disabled).then_some(Message::ItemPressed(idx)))
.style(theme::Button::MenuItem) .class(theme::Button::MenuItem)
.into() .into()
} }
} }
@ -433,10 +433,10 @@ impl Program for ContextMenu {
.width(Length::Shrink) .width(Length::Shrink)
.apply(iced_widget::container) .apply(iced_widget::container)
.padding(1) .padding(1)
.style(theme::Container::custom(|theme| { .class(theme::Container::custom(|theme| {
let cosmic = theme.cosmic(); let cosmic = theme.cosmic();
let component = &cosmic.background.component; let component = &cosmic.background.component;
iced_widget::container::Appearance { iced_widget::container::Style {
icon_color: Some(cosmic.accent.base.into()), icon_color: Some(cosmic.accent.base.into()),
text_color: Some(component.on.into()), text_color: Some(component.on.into()),
background: Some(Background::Color(component.base.into())), background: Some(Background::Color(component.base.into())),

View file

@ -10,26 +10,24 @@ use cosmic::{
iced::{ iced::{
advanced::widget::Tree, advanced::widget::Tree,
event::Event, event::Event,
futures::{FutureExt, StreamExt},
keyboard::{Event as KeyboardEvent, Modifiers as IcedModifiers}, keyboard::{Event as KeyboardEvent, Modifiers as IcedModifiers},
mouse::{Button as MouseButton, Cursor, Event as MouseEvent, ScrollDelta}, mouse::{Button as MouseButton, Cursor, Event as MouseEvent, ScrollDelta},
touch::{Event as TouchEvent, Finger}, touch::{Event as TouchEvent, Finger},
window::{Event as WindowEvent, Id}, window::Event as WindowEvent,
Command, Limits, Point as IcedPoint, Rectangle as IcedRectangle, Size as IcedSize, Limits, Point as IcedPoint, Size as IcedSize, Task,
}, },
iced_core::{clipboard::Null as NullClipboard, renderer::Style, Color, Length, Pixels}, iced_core::{clipboard::Null as NullClipboard, id::Id, renderer::Style, Color, Length, Pixels},
iced_renderer::graphics::Renderer as IcedGraphicsRenderer,
iced_runtime::{ iced_runtime::{
command::Action,
program::{Program as IcedProgram, State}, program::{Program as IcedProgram, State},
Debug, task::into_stream,
Action, Debug,
}, },
Theme, Theme,
}; };
use iced_tiny_skia::{ use iced_tiny_skia::{graphics::Viewport, Primitive};
graphics::{damage, Viewport},
Backend, Primitive,
};
use once_cell::sync::Lazy;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use smithay::{ use smithay::{
backend::{ backend::{
@ -67,6 +65,8 @@ use smithay::{
}, },
}; };
static ID: Lazy<Id> = Lazy::new(|| Id::new("Program"));
pub struct IcedElement<P: Program + Send + 'static>(pub(crate) Arc<Mutex<IcedElementInternal<P>>>); pub struct IcedElement<P: Program + Send + 'static>(pub(crate) Arc<Mutex<IcedElementInternal<P>>>);
impl<P: Program + Send + 'static> fmt::Debug for IcedElement<P> { impl<P: Program + Send + 'static> fmt::Debug for IcedElement<P> {
@ -104,9 +104,9 @@ pub trait Program {
&mut self, &mut self,
message: Self::Message, message: Self::Message,
loop_handle: &LoopHandle<'static, crate::state::State>, loop_handle: &LoopHandle<'static, crate::state::State>,
) -> Command<Self::Message> { ) -> Task<Self::Message> {
let _ = (message, loop_handle); let _ = (message, loop_handle);
Command::none() Task::none()
} }
fn view(&self) -> cosmic::Element<'_, Self::Message>; fn view(&self) -> cosmic::Element<'_, Self::Message>;
@ -131,7 +131,7 @@ impl<P: Program> IcedProgram for ProgramWrapper<P> {
type Renderer = cosmic::Renderer; type Renderer = cosmic::Renderer;
type Theme = cosmic::Theme; type Theme = cosmic::Theme;
fn update(&mut self, message: Self::Message) -> Command<Self::Message> { fn update(&mut self, message: Self::Message) -> Task<Self::Message> {
self.0.update(message, &self.1) self.0.update(message, &self.1)
} }
@ -159,9 +159,9 @@ pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
// futures // futures
handle: LoopHandle<'static, crate::state::State>, handle: LoopHandle<'static, crate::state::State>,
scheduler: Scheduler<<P as Program>::Message>, scheduler: Scheduler<Option<<P as Program>::Message>>,
executor_token: Option<RegistrationToken>, executor_token: Option<RegistrationToken>,
rx: Receiver<<P as Program>::Message>, rx: Receiver<Option<<P as Program>::Message>>,
} }
impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> { impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
@ -178,14 +178,10 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
if !self.state.is_queue_empty() { if !self.state.is_queue_empty() {
tracing::warn!("Missing force_update call"); tracing::warn!("Missing force_update call");
} }
let mut renderer = cosmic::Renderer::TinySkia(IcedGraphicsRenderer::new( let mut renderer = cosmic::Renderer::new(cosmic::font::default(), Pixels(16.0));
Backend::new(),
cosmic::font::default(),
Pixels(16.0),
));
let mut debug = Debug::new(); let mut debug = Debug::new();
let state = State::new( let state = State::new(
Id::MAIN, ID.clone(),
ProgramWrapper(self.state.program().0.clone(), handle.clone()), ProgramWrapper(self.state.program().0.clone(), handle.clone()),
IcedSize::new(self.size.w as f32, self.size.h as f32), IcedSize::new(self.size.w as f32, self.size.h as f32),
&mut renderer, &mut renderer,
@ -244,15 +240,11 @@ impl<P: Program + Send + 'static> IcedElement<P> {
theme: cosmic::Theme, theme: cosmic::Theme,
) -> IcedElement<P> { ) -> IcedElement<P> {
let size = size.into(); let size = size.into();
let mut renderer = cosmic::Renderer::TinySkia(IcedGraphicsRenderer::new( let mut renderer = cosmic::Renderer::new(cosmic::font::default(), Pixels(16.0));
Backend::new(),
cosmic::font::default(),
Pixels(16.0),
));
let mut debug = Debug::new(); let mut debug = Debug::new();
let state = State::new( let state = State::new(
Id::MAIN, ID.clone(),
ProgramWrapper(program, handle.clone()), ProgramWrapper(program, handle.clone()),
IcedSize::new(size.w as f32, size.h as f32), IcedSize::new(size.w as f32, size.h as f32),
&mut renderer, &mut renderer,
@ -368,8 +360,8 @@ impl<P: Program + Send + 'static + Clone> IcedElement<P> {
impl<P: Program + Send + 'static> IcedElementInternal<P> { impl<P: Program + Send + 'static> IcedElementInternal<P> {
#[profiling::function] #[profiling::function]
fn update(&mut self, mut force: bool) -> Vec<Action<<P as Program>::Message>> { fn update(&mut self, mut force: bool) -> Vec<Task<<P as Program>::Message>> {
while let Ok(message) = self.rx.try_recv() { while let Ok(Some(message)) = self.rx.try_recv() {
self.state.queue_message(message); self.state.queue_message(message);
force = true; force = true;
} }
@ -383,17 +375,16 @@ impl<P: Program + Send + 'static> IcedElementInternal<P> {
.map(|p| IcedPoint::new(p.x as f32, p.y as f32)) .map(|p| IcedPoint::new(p.x as f32, p.y as f32))
.map(Cursor::Available) .map(Cursor::Available)
.unwrap_or(Cursor::Unavailable); .unwrap_or(Cursor::Unavailable);
let actions = self let actions = self
.state .state
.update( .update(
Id::MAIN, ID.clone(),
IcedSize::new(self.size.w as f32, self.size.h as f32), IcedSize::new(self.size.w as f32, self.size.h as f32),
cursor, cursor,
&mut self.renderer, &mut self.renderer,
&self.theme, &self.theme,
&Style { &Style {
scale_factor: 1.0, //TODO: why is this scale_factor: 1.0, // TODO: why is this
icon_color: self.theme.cosmic().on_bg_color().into(), icon_color: self.theme.cosmic().on_bg_color().into(),
text_color: self.theme.cosmic().on_bg_color().into(), text_color: self.theme.cosmic().on_bg_color().into(),
}, },
@ -402,17 +393,15 @@ impl<P: Program + Send + 'static> IcedElementInternal<P> {
) )
.1; .1;
actions if let Some(action) = actions {
.into_iter() if let Some(t) = into_stream(action) {
.filter_map(|action| { let _ = self.scheduler.schedule(t.into_future().map(|f| match f.0 {
if let Action::Future(future) = action { Some(Action::Output(msg)) => Some(msg),
let _ = self.scheduler.schedule(future); _ => None,
None }));
} else { }
Some(action) }
} Vec::new()
})
.collect::<Vec<_>>()
} }
} }
@ -751,14 +740,11 @@ impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
fn set_activate(&self, activated: bool) { fn set_activate(&self, activated: bool) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal.state.queue_event(Event::Window( internal.state.queue_event(Event::Window(if activated {
Id::MAIN, WindowEvent::Focused
if activated { } else {
WindowEvent::Focused WindowEvent::Unfocused
} else { }));
WindowEvent::Unfocused
},
));
let _ = internal.update(true); // TODO let _ = internal.update(true); // TODO
} }
@ -860,83 +846,62 @@ where
} else { } else {
false false
}; };
if force {
internal_ref.pending_update = None;
}
let _ = internal_ref.update(force); let _ = internal_ref.update(force);
if let Some((buffer, _)) = internal_ref.buffers.get_mut(&OrderedFloat(scale.x)) {
if let Some((buffer, ref mut old_primitives)) =
internal_ref.buffers.get_mut(&OrderedFloat(scale.x))
{
let size: Size<i32, BufferCoords> = internal_ref let size: Size<i32, BufferCoords> = internal_ref
.size .size
.to_f64() .to_f64()
.to_buffer(scale.x, Transform::Normal) .to_buffer(scale.x, Transform::Normal)
.to_i32_round(); .to_i32_round();
if size.w > 0 && size.h > 0 { if size.w > 0 && size.h > 0 {
let cosmic::Renderer::TinySkia(renderer) = &mut internal_ref.renderer;
let state_ref = &internal_ref.state; let state_ref = &internal_ref.state;
let mut clip_mask = tiny_skia::Mask::new(size.w as u32, size.h as u32).unwrap(); let mut clip_mask = tiny_skia::Mask::new(size.w as u32, size.h as u32).unwrap();
let overlay = internal_ref.debug.overlay(); let overlay = internal_ref.debug.overlay();
let theme = &internal_ref.theme; let theme = &internal_ref.theme;
buffer _ = buffer.render().draw(|buf| {
.render() let mut pixels =
.draw(move |buf| { tiny_skia::PixmapMut::from_bytes(buf, size.w as u32, size.h as u32)
let mut pixels = .expect("Failed to create pixel map");
tiny_skia::PixmapMut::from_bytes(buf, size.w as u32, size.h as u32)
.expect("Failed to create pixel map");
renderer.with_primitives(|backend, primitives| { let background_color = state_ref.program().0.background_color(theme);
let background_color = state_ref.program().0.background_color(theme); let bounds = IcedSize::new(size.w as u32, size.h as u32);
let bounds = IcedSize::new(size.w as u32, size.h as u32); let viewport = Viewport::with_physical_size(bounds, scale.x);
let viewport = Viewport::with_physical_size(bounds, scale.x);
let mut damage = old_primitives let damage = vec![cosmic::iced::Rectangle::new(
.as_ref() cosmic::iced::Point::default(),
.and_then(|(last_primitives, last_color)| { viewport.logical_size(),
(last_color == &background_color) )];
.then(|| damage::list(last_primitives, primitives))
})
.unwrap_or_else(|| {
vec![IcedRectangle::with_size(viewport.logical_size())]
});
damage = damage::group(damage, scale.x as f32, bounds);
if !damage.is_empty() { internal_ref.renderer.draw(
backend.draw( &mut pixels,
&mut pixels, &mut clip_mask,
&mut clip_mask, &viewport,
primitives, &damage,
&viewport, background_color,
&damage, &overlay,
background_color, );
&overlay,
);
*old_primitives = Some((primitives.to_vec(), background_color)); let damage = damage
} .into_iter()
.filter_map(|x| x.snap())
let damage = damage .map(|damage_rect| {
.into_iter() Rectangle::from_loc_and_size(
.map(|x| x.snap()) (damage_rect.x as i32, damage_rect.y as i32),
.map(|damage_rect| { (damage_rect.width as i32, damage_rect.height as i32),
Rectangle::from_loc_and_size( )
(damage_rect.x as i32, damage_rect.y as i32),
(damage_rect.width as i32, damage_rect.height as i32),
)
})
.collect::<Vec<_>>();
state_ref.program().0.foreground(
&mut pixels,
&damage,
scale.x as f32,
theme,
);
Result::<_, ()>::Ok(damage)
}) })
}) .collect::<Vec<_>>();
.unwrap(); state_ref
.program()
.0
.foreground(&mut pixels, &damage, scale.x as f32, theme);
Result::<_, ()>::Ok(damage)
});
} }
if let Ok(buffer) = MemoryRenderBufferRenderElement::from_buffer( if let Ok(buffer) = MemoryRenderBufferRenderElement::from_buffer(
@ -946,9 +911,11 @@ where
Some(alpha), Some(alpha),
Some(Rectangle::from_loc_and_size( Some(Rectangle::from_loc_and_size(
(0., 0.), (0., 0.),
size.to_f64().to_logical(1.0, Transform::Normal), size.to_f64()
.to_logical(1., Transform::Normal)
.to_i32_round(),
)), )),
Some(internal_ref.size), Some(size.to_logical(1, Transform::Normal)),
Kind::Unspecified, Kind::Unspecified,
) { ) {
return vec![C::from(buffer)]; return vec![C::from(buffer)];