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)]
struct Workspace {
name: String,
info: cctk::workspace::Workspace,
// img_for_output: HashMap<wl_output::WlOutput, backend::CaptureImage>,
img: Option<backend::CaptureImage>,
handle: ExtWorkspaceHandleV1,
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)]
@ -171,14 +181,14 @@ struct App {
impl App {
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(
&mut self,
handle: &ExtWorkspaceHandleV1,
) -> 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`
@ -284,8 +294,8 @@ impl App {
capture_filter.toplevels_on_workspaces = self
.workspaces
.iter()
.filter(|x| x.is_active)
.map(|x| x.handle.clone())
.filter(|x| x.is_active())
.map(|x| x.handle().clone())
.collect();
}
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);
self.workspaces = Vec::new();
for (outputs, workspace) in workspaces {
let is_active = workspace
.state
.contains(ext_workspace_handle_v1::State::Active);
// XXX efficiency
#[allow(clippy::mutable_key_type)]
let img = old_workspaces
.iter()
.find(|i| i.handle == workspace.handle)
.find(|i| *i.handle() == workspace.handle)
.map(|i| i.img.clone())
.unwrap_or_default();
self.workspaces.push(Workspace {
name: workspace.name,
handle: workspace.handle,
info: workspace,
outputs,
img,
is_active,
});
}
self.update_capture_filter();
@ -466,7 +470,7 @@ impl Application for App {
}
Msg::ActivateWorkspace(workspace_handle) => {
if let Some(workspace) = self.workspace_for_handle(&workspace_handle) {
if workspace.is_active {
if workspace.is_active() {
return self.hide();
}
}
@ -601,7 +605,7 @@ impl Application for App {
// TODO assumes only one active workspace per output
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 {
// Next workspace on output
ScrollDirection::Next => workspaces[workspace_idx + 1..].iter().next(),
@ -610,7 +614,7 @@ impl Application for App {
};
if let Some(workspace) = workspace {
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| {
app.workspace_for_handle(workspace)
.map_or(false, |x| x.is_active)
.map_or(false, |x| x.is_active())
})
}),
layout,
@ -83,10 +83,10 @@ pub(crate) fn layer_surface<'a>(
// TODO multiple active workspaces? Not currently supported by cosmic.
let first_active_workspace = app
.workspaces_for_output(&surface.output)
.find(|w| w.is_active);
.find(|w| w.is_active());
let toplevels = if let Some(workspace) = first_active_workspace {
dnd_destination_for_target(
DropTarget::OutputToplevels(workspace.handle.clone(), surface.output.clone()),
DropTarget::OutputToplevels(workspace.handle().clone(), surface.output.clone()),
toplevels,
Msg::DndToplevelDrop,
)
@ -189,7 +189,7 @@ fn workspace_item<'a>(
let workspace_name = widget::text::body(fl!(
"workspace",
HashMap::from([("number", &workspace.name)])
HashMap::from([("number", &workspace.info.name)])
));
// 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
};
let is_active = workspace.is_active;
let is_active = workspace.is_active();
// TODO editable name?
widget::button::custom(content)
.selected(workspace.is_active)
.selected(workspace.is_active())
.class(cosmic::theme::Button::Custom {
active: Box::new(move |_focused, theme| {
workspace_item_appearance(theme, is_active, is_drop_target)
@ -221,7 +221,7 @@ fn workspace_item<'a>(
workspace_item_appearance(theme, is_active, true)
}),
})
.on_press(Msg::ActivateWorkspace(workspace.handle.clone()))
.on_press(Msg::ActivateWorkspace(workspace.handle().clone()))
.padding(8)
.into()
}
@ -263,7 +263,7 @@ fn workspace_sidebar_entry<'a>(
//crate::widgets::mouse_interaction_wrapper(
// mouse_interaction,
dnd_destination_for_target(
DropTarget::WorkspaceSidebarEntry(workspace.handle.clone(), output.clone()),
DropTarget::WorkspaceSidebarEntry(workspace.handle().clone(), output.clone()),
item,
Msg::DndToplevelDrop,
)
@ -276,7 +276,7 @@ fn workspaces_sidebar<'a>(
drop_target: Option<&backend::ExtWorkspaceHandleV1>,
) -> cosmic::Element<'a, Msg> {
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();
let (axis, width, height) = match layout {
WorkspaceLayout::Vertical => (Axis::Vertical, Length::Shrink, Length::Fill),