Store cctk::workspace::Workspace in struct Workspace

Instead of adding more fields to this struct that need to be copied from
the cctk type, just wrap it. Can add methods where that's convenient.
This commit is contained in:
Ian Douglas Scott 2025-04-21 10:36:44 -07:00
parent bcb68ab054
commit 62fbd056bf
2 changed files with 31 additions and 27 deletions

View file

@ -115,12 +115,22 @@ enum Msg {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Workspace { struct Workspace {
name: String, info: cctk::workspace::Workspace,
// img_for_output: HashMap<wl_output::WlOutput, backend::CaptureImage>, // img_for_output: HashMap<wl_output::WlOutput, backend::CaptureImage>,
img: Option<backend::CaptureImage>, img: Option<backend::CaptureImage>,
handle: ExtWorkspaceHandleV1,
outputs: HashSet<wl_output::WlOutput>, outputs: HashSet<wl_output::WlOutput>,
is_active: bool, }
impl Workspace {
fn handle(&self) -> &ExtWorkspaceHandleV1 {
&self.info.handle
}
fn is_active(&self) -> bool {
self.info
.state
.contains(ext_workspace_handle_v1::State::Active)
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -171,14 +181,14 @@ struct App {
impl App { impl App {
fn workspace_for_handle(&self, handle: &ExtWorkspaceHandleV1) -> Option<&Workspace> { fn workspace_for_handle(&self, handle: &ExtWorkspaceHandleV1) -> Option<&Workspace> {
self.workspaces.iter().find(|i| &i.handle == handle) self.workspaces.iter().find(|i| i.handle() == handle)
} }
fn workspace_for_handle_mut( fn workspace_for_handle_mut(
&mut self, &mut self,
handle: &ExtWorkspaceHandleV1, handle: &ExtWorkspaceHandleV1,
) -> Option<&mut Workspace> { ) -> Option<&mut Workspace> {
self.workspaces.iter_mut().find(|i| &i.handle == handle) self.workspaces.iter_mut().find(|i| i.handle() == handle)
} }
// TODO iterate in order based on `coordinates` // TODO iterate in order based on `coordinates`
@ -284,8 +294,8 @@ impl App {
capture_filter.toplevels_on_workspaces = self capture_filter.toplevels_on_workspaces = self
.workspaces .workspaces
.iter() .iter()
.filter(|x| x.is_active) .filter(|x| x.is_active())
.map(|x| x.handle.clone()) .map(|x| x.handle().clone())
.collect(); .collect();
} }
self.send_wayland_cmd(backend::Cmd::CaptureFilter(capture_filter)); self.send_wayland_cmd(backend::Cmd::CaptureFilter(capture_filter));
@ -382,24 +392,18 @@ impl Application for App {
let old_workspaces = mem::take(&mut self.workspaces); let old_workspaces = mem::take(&mut self.workspaces);
self.workspaces = Vec::new(); self.workspaces = Vec::new();
for (outputs, workspace) in workspaces { for (outputs, workspace) in workspaces {
let is_active = workspace
.state
.contains(ext_workspace_handle_v1::State::Active);
// XXX efficiency // XXX efficiency
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
let img = old_workspaces let img = old_workspaces
.iter() .iter()
.find(|i| i.handle == workspace.handle) .find(|i| *i.handle() == workspace.handle)
.map(|i| i.img.clone()) .map(|i| i.img.clone())
.unwrap_or_default(); .unwrap_or_default();
self.workspaces.push(Workspace { self.workspaces.push(Workspace {
name: workspace.name, info: workspace,
handle: workspace.handle,
outputs, outputs,
img, img,
is_active,
}); });
} }
self.update_capture_filter(); self.update_capture_filter();
@ -466,7 +470,7 @@ impl Application for App {
} }
Msg::ActivateWorkspace(workspace_handle) => { Msg::ActivateWorkspace(workspace_handle) => {
if let Some(workspace) = self.workspace_for_handle(&workspace_handle) { if let Some(workspace) = self.workspace_for_handle(&workspace_handle) {
if workspace.is_active { if workspace.is_active() {
return self.hide(); return self.hide();
} }
} }
@ -601,7 +605,7 @@ impl Application for App {
// TODO assumes only one active workspace per output // TODO assumes only one active workspace per output
let workspaces = self.workspaces_for_output(&output).collect::<Vec<_>>(); let workspaces = self.workspaces_for_output(&output).collect::<Vec<_>>();
if let Some(workspace_idx) = workspaces.iter().position(|i| i.is_active) { if let Some(workspace_idx) = workspaces.iter().position(|i| i.is_active()) {
let workspace = match direction { let workspace = match direction {
// Next workspace on output // Next workspace on output
ScrollDirection::Next => workspaces[workspace_idx + 1..].iter().next(), ScrollDirection::Next => workspaces[workspace_idx + 1..].iter().next(),
@ -610,7 +614,7 @@ impl Application for App {
}; };
if let Some(workspace) = workspace { if let Some(workspace) = workspace {
self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( self.send_wayland_cmd(backend::Cmd::ActivateWorkspace(
workspace.handle.clone(), workspace.handle().clone(),
)); ));
} }
} }

View file

@ -74,7 +74,7 @@ pub(crate) fn layer_surface<'a>(
i.info.workspace.iter().any(|workspace| { i.info.workspace.iter().any(|workspace| {
app.workspace_for_handle(workspace) app.workspace_for_handle(workspace)
.map_or(false, |x| x.is_active) .map_or(false, |x| x.is_active())
}) })
}), }),
layout, layout,
@ -83,10 +83,10 @@ pub(crate) fn layer_surface<'a>(
// TODO multiple active workspaces? Not currently supported by cosmic. // TODO multiple active workspaces? Not currently supported by cosmic.
let first_active_workspace = app let first_active_workspace = app
.workspaces_for_output(&surface.output) .workspaces_for_output(&surface.output)
.find(|w| w.is_active); .find(|w| w.is_active());
let toplevels = if let Some(workspace) = first_active_workspace { let toplevels = if let Some(workspace) = first_active_workspace {
dnd_destination_for_target( dnd_destination_for_target(
DropTarget::OutputToplevels(workspace.handle.clone(), surface.output.clone()), DropTarget::OutputToplevels(workspace.handle().clone(), surface.output.clone()),
toplevels, toplevels,
Msg::DndToplevelDrop, Msg::DndToplevelDrop,
) )
@ -189,7 +189,7 @@ fn workspace_item<'a>(
let workspace_name = widget::text::body(fl!( let workspace_name = widget::text::body(fl!(
"workspace", "workspace",
HashMap::from([("number", &workspace.name)]) HashMap::from([("number", &workspace.info.name)])
)); ));
// Needed to prevent text getting pushed out when scaling on Vertical layout // Needed to prevent text getting pushed out when scaling on Vertical layout
@ -205,10 +205,10 @@ fn workspace_item<'a>(
.max_height(image_height + 21.0 + 4.0), // text height + spacing .max_height(image_height + 21.0 + 4.0), // text height + spacing
}; };
let is_active = workspace.is_active; let is_active = workspace.is_active();
// TODO editable name? // TODO editable name?
widget::button::custom(content) widget::button::custom(content)
.selected(workspace.is_active) .selected(workspace.is_active())
.class(cosmic::theme::Button::Custom { .class(cosmic::theme::Button::Custom {
active: Box::new(move |_focused, theme| { active: Box::new(move |_focused, theme| {
workspace_item_appearance(theme, is_active, is_drop_target) workspace_item_appearance(theme, is_active, is_drop_target)
@ -221,7 +221,7 @@ fn workspace_item<'a>(
workspace_item_appearance(theme, is_active, true) workspace_item_appearance(theme, is_active, true)
}), }),
}) })
.on_press(Msg::ActivateWorkspace(workspace.handle.clone())) .on_press(Msg::ActivateWorkspace(workspace.handle().clone()))
.padding(8) .padding(8)
.into() .into()
} }
@ -263,7 +263,7 @@ fn workspace_sidebar_entry<'a>(
//crate::widgets::mouse_interaction_wrapper( //crate::widgets::mouse_interaction_wrapper(
// mouse_interaction, // mouse_interaction,
dnd_destination_for_target( dnd_destination_for_target(
DropTarget::WorkspaceSidebarEntry(workspace.handle.clone(), output.clone()), DropTarget::WorkspaceSidebarEntry(workspace.handle().clone(), output.clone()),
item, item,
Msg::DndToplevelDrop, Msg::DndToplevelDrop,
) )
@ -276,7 +276,7 @@ fn workspaces_sidebar<'a>(
drop_target: Option<&backend::ExtWorkspaceHandleV1>, drop_target: Option<&backend::ExtWorkspaceHandleV1>,
) -> cosmic::Element<'a, Msg> { ) -> cosmic::Element<'a, Msg> {
let sidebar_entries = workspaces let sidebar_entries = workspaces
.map(|w| workspace_sidebar_entry(w, output, layout, drop_target == Some(&w.handle))) .map(|w| workspace_sidebar_entry(w, output, layout, drop_target == Some(w.handle())))
.collect(); .collect();
let (axis, width, height) = match layout { let (axis, width, height) = match layout {
WorkspaceLayout::Vertical => (Axis::Vertical, Length::Shrink, Length::Fill), WorkspaceLayout::Vertical => (Axis::Vertical, Length::Shrink, Length::Fill),