chore: updates after iced rebase

This commit is contained in:
Ashley Wulber 2026-03-03 13:53:45 -05:00 committed by Ashley Wulber
parent 45e01aa6e6
commit d4becdd6c5
15 changed files with 1329 additions and 1118 deletions

View file

@ -30,7 +30,7 @@ use cosmic::{
},
},
};
use std::{cell::RefCell, collections::HashMap, sync::Arc, thread};
use std::{cell::RefCell, collections::HashMap, hash::Hash, sync::Arc, thread};
mod buffer;
use buffer::Buffer;
@ -48,7 +48,20 @@ mod workspace;
use super::{CaptureFilter, CaptureImage, Cmd, Event};
pub fn subscription(conn: Connection) -> iced::Subscription<Event> {
iced::Subscription::run_with_id("wayland-sub", async { start(conn) }.flatten_stream())
#[derive(Clone)]
struct WaylandSubscription(Connection);
impl Hash for WaylandSubscription {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.backend().display_id().hash(state);
}
}
iced::Subscription::run_with(
WaylandSubscription(conn.clone()),
|WaylandSubscription(conn)| {
let conn = conn.clone();
async { start(conn) }.flatten_stream()
},
)
}
pub struct AppData {

View file

@ -1,4 +1,5 @@
use cosmic::iced::{self, futures::StreamExt};
use std::{any::TypeId, hash::Hash};
use tokio::sync::broadcast;
use tokio_stream::wrappers::BroadcastStream;
@ -65,9 +66,23 @@ impl Interface {
}
pub fn subscription(&self) -> iced::Subscription<Event> {
iced::Subscription::run_with_id(
"workspaces-dbus-sun",
BroadcastStream::new(self.event_sender.subscribe()).filter_map(|x| async { x.ok() }),
#[derive(Clone)]
struct Wrapper {
event_sender: broadcast::Sender<Event>,
}
impl Hash for Wrapper {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
TypeId::of::<Wrapper>().hash(state);
}
}
iced::Subscription::run_with(
Wrapper {
event_sender: self.event_sender.clone(),
},
|Wrapper { event_sender }| {
BroadcastStream::new(event_sender.subscribe()).filter_map(|x| async { x.ok() })
},
)
}
}

View file

@ -289,7 +289,7 @@ fn workspace_item(
};
let workspace_footer = row![
widget::horizontal_space().width(Length::Fixed(32.0)),
widget::space::horizontal().width(Length::Fixed(32.0)),
widget::text::body(fl!("workspace", number = workspace.info.name.as_str()))
.ellipsize(Ellipsize::Middle(EllipsizeHeightLimit::Lines(1)))
.apply(widget::container)
@ -346,14 +346,18 @@ fn workspace_drag_placeholder(
other_workspace.handle().clone(),
other_output.clone(),
);
let placeholder = widget::button::custom(widget::Space::new(Length::Fill, Length::Fill))
.class(cosmic::theme::Button::Custom {
active: Box::new(|_, _| unreachable!()),
disabled: Box::new(|theme| workspace_item_appearance(theme, true, true)),
hovered: Box::new(|_, _| unreachable!()),
pressed: Box::new(|_, _| unreachable!()),
})
.padding(8);
let placeholder = widget::button::custom(
widget::Space::new()
.width(Length::Fill)
.height(Length::Fill),
)
.class(cosmic::theme::Button::Custom {
active: Box::new(|_, _| unreachable!()),
disabled: Box::new(|theme| workspace_item_appearance(theme, true, true)),
hovered: Box::new(|_, _| unreachable!()),
pressed: Box::new(|_, _| unreachable!()),
})
.padding(8);
let placeholder = crate::widgets::match_size(
workspace_item(other_workspace, other_output, layout, true, true),
placeholder,
@ -439,7 +443,10 @@ fn workspaces_sidebar<'a>(
DragWorkspace {},
DragSurface::Workspace(workspace.handle().clone()),
Some(workspace.dnd_source_id.clone()),
widget::Space::new(Length::Shrink, Length::Shrink).into(),
widget::Space::new()
.width(Length::Shrink)
.height(Length::Shrink)
.into(),
move || workspace_item(&workspace_clone, &output_clone, layout, false, true),
);
sidebar_entries.push(source);
@ -502,6 +509,7 @@ fn workspaces_sidebar<'a>(
..Default::default()
},
shadow: Shadow::default(),
snap: true,
}
})),
)

View file

@ -41,19 +41,6 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for ImageBg<'_, Msg> {
fn children(&self) -> Vec<Tree>;
fn size(&self) -> Size<Length>;
fn size_hint(&self) -> Size<Length>;
fn layout(
&self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node;
fn operate(
&self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
fn mouse_interaction(
&self,
tree: &Tree,
@ -66,24 +53,38 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for ImageBg<'_, Msg> {
to self.content.as_widget_mut() {
fn diff(&mut self, tree: &mut Tree);
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status;
);
fn overlay<'b>(
&'b mut self,
tree: &'b mut Tree,
layout: Layout<'_>,
layout: Layout<'b>,
renderer: &cosmic::Renderer,
viewport: &Rectangle,
translation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
fn layout(
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node;
fn operate(
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
}
}

View file

@ -41,32 +41,32 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MatchSize<'_, Msg> {
}
fn operate(
&self,
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
) {
self.matched
.as_widget()
.as_widget_mut()
.operate(&mut tree.children[0], layout, renderer, operation);
self.shown
.as_widget()
.as_widget_mut()
.operate(&mut tree.children[1], layout, renderer, operation);
}
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status {
self.shown.as_widget_mut().on_event(
) {
self.shown.as_widget_mut().update(
&mut tree.children[1],
event,
layout,
@ -96,14 +96,14 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MatchSize<'_, Msg> {
}
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node {
// TODO?
self.matched
.as_widget()
.as_widget_mut()
.layout(&mut tree.children[0], renderer, limits)
}

View file

@ -39,13 +39,12 @@ pub struct LayoutWrapper<'a, Msg> {
impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for LayoutWrapper<'_, Msg> {
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node {
dbg!(limits);
dbg!(self.content.as_widget().layout(tree, renderer, limits))
self.content.as_widget_mut().layout(tree, renderer, limits)
}
delegate::delegate! {
@ -55,13 +54,6 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for LayoutWrapper<'_, Msg
fn children(&self) -> Vec<Tree>;
fn size(&self) -> Size<Length>;
fn size_hint(&self) -> Size<Length>;
fn operate(
&self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
fn draw(
&self,
state: &Tree,
@ -85,25 +77,33 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for LayoutWrapper<'_, Msg
to self.content.as_widget_mut() {
fn diff(&mut self, tree: &mut Tree);
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status;
);
fn overlay<'b>(
&'b mut self,
tree: &'b mut Tree,
layout: Layout<'_>,
layout: Layout<'b>,
renderer: &cosmic::Renderer,
viewport: &Rectangle,
transation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
fn set_id(&mut self, id: Id);
fn operate(
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
}
}
}

View file

@ -34,19 +34,6 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MouseInteractionWrapp
fn children(&self) -> Vec<Tree>;
fn size(&self) -> Size<Length>;
fn size_hint(&self) -> Size<Length>;
fn layout(
&self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node;
fn operate(
&self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
fn draw(
&self,
state: &Tree,
@ -62,25 +49,39 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for MouseInteractionWrapp
to self.content.as_widget_mut() {
fn diff(&mut self, tree: &mut Tree);
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status;
);
fn overlay<'b>(
&'b mut self,
tree: &'b mut Tree,
layout: Layout<'_>,
layout: Layout<'b>,
renderer: &cosmic::Renderer,
viewport: &Rectangle,
translation: Vector,
) -> Option<overlay::Element<'b, Msg, cosmic::Theme, cosmic::Renderer>>;
fn set_id(&mut self, id: Id);
fn layout(
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node;
fn operate(
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
);
}
}

View file

@ -75,7 +75,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for SizeCrossNth<'_, Msg>
}
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
@ -87,7 +87,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for SizeCrossNth<'_, Msg>
// Get layout of main widget, to set overall cross axis size
let (max_width, max_height) = self.axis.pack(max_main, max_cross);
let child_limits = layout::Limits::new(Size::ZERO, Size::new(max_width, max_height));
let layout = self.children[self.index].as_widget().layout(
let layout = self.children[self.index].as_widget_mut().layout(
&mut tree.children[self.index],
renderer,
&child_limits,
@ -100,13 +100,13 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for SizeCrossNth<'_, Msg>
let mut total_main = 0.0;
let nodes = self
.children
.iter()
.iter_mut()
.zip(tree.children.iter_mut())
.map(|(child, tree)| {
let (max_width, max_height) = self.axis.pack(max_main - total_main, max_cross);
let child_limits =
layout::Limits::new(Size::ZERO, Size::new(max_width, max_height));
let mut layout = child.as_widget().layout(tree, renderer, &child_limits);
let mut layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
// Center on cross axis
let cross = ((max_cross - self.axis.cross(layout.size())) / 2.).max(0.);
let (x, y) = self.axis.pack(total_main, cross);
@ -122,53 +122,47 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for SizeCrossNth<'_, Msg>
}
fn operate(
&self,
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
operation.container(None, layout.bounds());
operation.traverse(&mut |operation| {
self.children
.iter()
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.for_each(|((child, state), layout)| {
child
.as_widget()
.as_widget_mut()
.operate(state, layout, renderer, operation);
});
});
}
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status {
self.children
) {
for ((child, state), layout) in self
.children
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.map(|((child, state), layout)| {
child.as_widget_mut().on_event(
state,
event.clone(),
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
)
})
.fold(event::Status::Ignored, event::Status::merge)
{
child.as_widget_mut().update(
state, event, layout, cursor, renderer, clipboard, shell, viewport,
)
}
}
fn mouse_interaction(

View file

@ -34,7 +34,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for Toplevels<'_, Msg> {
}
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
@ -42,10 +42,10 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for Toplevels<'_, Msg> {
// Call `.layout()` on each child with full limits to determine "preferred" sizes
let layout_toplevels = self
.children
.iter()
.iter_mut()
.zip(tree.children.iter_mut())
.map(|(child, tree)| {
let preferred_size = child.as_widget().layout(tree, renderer, limits).size();
let preferred_size = child.as_widget_mut().layout(tree, renderer, limits).size();
LayoutToplevel {
preferred_size,
_phantom_data: PhantomData,
@ -58,12 +58,12 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for Toplevels<'_, Msg> {
let nodes = self
.children
.iter()
.iter_mut()
.zip(tree.children.iter_mut())
.zip(assigned_rects)
.map(|((child, tree), assigned_rect)| {
let child_limits = layout::Limits::new(Size::ZERO, assigned_rect.size());
let layout = child.as_widget().layout(tree, renderer, &child_limits);
let layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
// Center on both axes, if child didn't consume full size allocation
let centering_offset = Vector::new(
@ -78,53 +78,47 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for Toplevels<'_, Msg> {
}
fn operate(
&self,
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
operation.container(None, layout.bounds());
operation.traverse(&mut |operation| {
self.children
.iter()
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.for_each(|((child, state), layout)| {
child
.as_widget()
.as_widget_mut()
.operate(state, layout, renderer, operation);
});
});
}
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status {
self.children
) {
for ((child, state), layout) in self
.children
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.map(|((child, state), layout)| {
child.as_widget_mut().on_event(
state,
event.clone(),
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
)
})
.fold(event::Status::Ignored, event::Status::merge)
{
child.as_widget_mut().update(
state, event, layout, cursor, renderer, clipboard, shell, viewport,
);
}
}
fn mouse_interaction(

View file

@ -100,6 +100,7 @@ impl<T: AxisToplevelLayout> ToplevelLayout for T {
&*toplevels,
)
};
let inner = self
.layout(max_limit, toplevels_slice)
.map(|rect| rect.pack(self.axis()));

View file

@ -55,12 +55,17 @@ impl AxisToplevelLayout for TwoRowColToplevelLayout {
// Better layout
if two_row_scale_factor > scale_factor {
// TODO padding
let row1 = self.0.layout(half_max_limit, &toplevels[..split_point]);
let spacing = self.0.spacing as f32;
let row1 = self
.0
.layout(half_max_limit, &toplevels[..split_point])
.collect::<Vec<_>>()
.into_iter();
let row2 = self
.0
.layout(half_max_limit, &toplevels[split_point..])
.map(move |mut rect| {
rect.origin.cross += half_max_limit.cross + self.0.spacing as f32;
rect.origin.cross += half_max_limit.cross + spacing;
rect
});
return itertools::Either::Left(row1.chain(row2));

View file

@ -37,29 +37,29 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for VisibilityWrapper<'_,
}
fn operate(
&self,
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
) {
self.content
.as_widget()
.as_widget_mut()
.operate(&mut tree.children[0], layout, renderer, operation);
}
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status {
self.content.as_widget_mut().on_event(
) {
self.content.as_widget_mut().update(
&mut tree.children[0],
event,
layout,
@ -68,7 +68,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for VisibilityWrapper<'_,
clipboard,
shell,
viewport,
)
);
}
fn mouse_interaction(
@ -89,13 +89,13 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for VisibilityWrapper<'_,
}
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
) -> layout::Node {
self.content
.as_widget()
.as_widget_mut()
.layout(&mut tree.children[0], renderer, limits)
}

View file

@ -67,7 +67,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'_, Msg>
}
fn layout(
&self,
&mut self,
tree: &mut Tree,
renderer: &cosmic::Renderer,
limits: &layout::Limits,
@ -84,16 +84,17 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'_, Msg>
let max_cross = self.axis.cross(limits.max());
let mut total_main = 0.0;
let mut max_child_cross = 0.0;
let children_len = self.children.len();
let nodes = self
.children
.iter()
.iter_mut()
.zip(tree.children.iter_mut())
.enumerate()
.map(|(i, (child, tree))| {
let (max_width, max_height) = self.axis.pack(max_main, max_cross);
let child_limits =
layout::Limits::new(Size::ZERO, Size::new(max_width, max_height));
let mut layout = child.as_widget().layout(tree, renderer, &child_limits);
let mut layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
let child_size = layout.size();
let (x, y) = self.axis.pack(total_main, 0.0);
layout = layout.move_to(Point::new(x, y));
@ -102,7 +103,7 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'_, Msg>
// XXX Don't add spacing for 0 length `dnd_source` placeholder widget
if main != 0.0 {
total_main += main;
if i < self.children.len() - 1 {
if i < children_len - 1 {
total_main += spacing;
}
}
@ -116,53 +117,47 @@ impl<Msg> Widget<Msg, cosmic::Theme, cosmic::Renderer> for WorkspaceBar<'_, Msg>
}
fn operate(
&self,
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &cosmic::Renderer,
operation: &mut dyn Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
operation.container(None, layout.bounds());
operation.traverse(&mut |operation| {
self.children
.iter()
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.for_each(|((child, state), layout)| {
child
.as_widget()
.as_widget_mut()
.operate(state, layout, renderer, operation);
});
});
}
fn on_event(
fn update(
&mut self,
tree: &mut Tree,
event: Event,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &cosmic::Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Msg>,
viewport: &Rectangle,
) -> event::Status {
self.children
) {
for ((child, state), layout) in self
.children
.iter_mut()
.zip(&mut tree.children)
.zip(layout.children())
.map(|((child, state), layout)| {
child.as_widget_mut().on_event(
state,
event.clone(),
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
)
})
.fold(event::Status::Ignored, event::Status::merge)
{
child.as_widget_mut().update(
state, event, layout, cursor, renderer, clipboard, shell, viewport,
);
}
}
fn mouse_interaction(