fix: cleanup rectangles on workspace swap
This commit is contained in:
parent
127b966e3e
commit
fa4d8d68a4
2 changed files with 118 additions and 32 deletions
100
src/main.rs
100
src/main.rs
|
|
@ -184,6 +184,7 @@ struct Conf {
|
|||
pub struct RectId {
|
||||
id: window::Id,
|
||||
toplevel_id: Option<ObjectId>,
|
||||
workspaces_id: Option<Vec<ObjectId>>,
|
||||
widget_id: Option<widget::Id>,
|
||||
}
|
||||
|
||||
|
|
@ -444,6 +445,55 @@ impl App {
|
|||
}
|
||||
regions
|
||||
}
|
||||
|
||||
fn update_active_workspace(
|
||||
&mut self,
|
||||
workspace_handle: ExtWorkspaceHandleV1,
|
||||
) -> Option<Task<cosmic::Action<Msg>>> {
|
||||
if let Some((cur_window, _)) = self.layer_surfaces.iter().find(|(_, layer_surface)| {
|
||||
self.workspaces
|
||||
.for_output(&layer_surface.output)
|
||||
.any(|w| *w.handle() == workspace_handle)
|
||||
}) {
|
||||
self.rects.retain(|id, r| {
|
||||
id.toplevel_id == None
|
||||
|| (id.id == *cur_window
|
||||
&& id
|
||||
.workspaces_id
|
||||
.as_ref()
|
||||
.is_some_and(|l| l.iter().any(|o| *o == workspace_handle.id())))
|
||||
});
|
||||
let active = cosmic::theme::active();
|
||||
let rad = active
|
||||
.cosmic()
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x } else { x + 8.0 });
|
||||
let strips: Vec<Rectangle> = self
|
||||
.rects
|
||||
.iter()
|
||||
.map(|(id, rect)| {
|
||||
let rad = CornerRadius {
|
||||
top_left: rad[0] as u32,
|
||||
top_right: rad[1] as u32,
|
||||
bottom_left: rad[3] as u32,
|
||||
bottom_right: rad[2] as u32,
|
||||
};
|
||||
|
||||
cosmic::surface::corner_radius::rounded_rect_strips(*rect, rad)
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
return Some(
|
||||
cosmic::iced::platform_specific::shell::commands::blur::blur(
|
||||
*cur_window,
|
||||
Some(strips),
|
||||
)
|
||||
.discard(),
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Application for App {
|
||||
|
|
@ -470,18 +520,20 @@ impl Application for App {
|
|||
match message {
|
||||
Msg::Rectangle(u) => match u {
|
||||
RectangleUpdate::Rectangle(r) => {
|
||||
// TODO should we reuse previously tracked rectangles on surface creation
|
||||
self.rects.insert(r.0.clone(), r.1);
|
||||
let active = cosmic::theme::active();
|
||||
let rad = active
|
||||
.cosmic()
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x } else { x + 8.0 });
|
||||
let strips = self
|
||||
let mut rects = Vec::new();
|
||||
let mut strips: Vec<Rectangle> = self
|
||||
.rects
|
||||
.iter()
|
||||
.filter(|(id, _)| r.0.id == id.id)
|
||||
.map(|(id, r)| {
|
||||
.filter_map(|(id, rect)| {
|
||||
if r.0.id != id.id {
|
||||
return None;
|
||||
}
|
||||
let rad = if id.toplevel_id.is_none() {
|
||||
CornerRadius {
|
||||
top_left: rad[0] as u32,
|
||||
|
|
@ -490,16 +542,21 @@ impl Application for App {
|
|||
bottom_right: rad[2] as u32,
|
||||
}
|
||||
} else {
|
||||
CornerRadius::default()
|
||||
rects.push(*rect);
|
||||
return None;
|
||||
};
|
||||
|
||||
cosmic::surface::corner_radius::rounded_rect_strips(*r, rad)
|
||||
Some(cosmic::surface::corner_radius::rounded_rect_strips(
|
||||
*rect, rad,
|
||||
))
|
||||
})
|
||||
.flatten();
|
||||
.flatten()
|
||||
.collect();
|
||||
strips.append(&mut rects);
|
||||
|
||||
return cosmic::iced::platform_specific::shell::commands::blur::blur(
|
||||
r.0.id,
|
||||
Some(strips.collect()),
|
||||
Some(strips),
|
||||
)
|
||||
.discard();
|
||||
}
|
||||
|
|
@ -576,6 +633,12 @@ impl Application for App {
|
|||
backend::Event::Workspaces(mut workspaces) => {
|
||||
workspaces.sort_by(|(_, w1), (_, w2)| w1.coordinates.cmp(&w2.coordinates));
|
||||
let old_workspaces = mem::take(&mut self.workspaces);
|
||||
let old_active: HashSet<_> = old_workspaces
|
||||
.0
|
||||
.iter()
|
||||
.filter_map(|w| w.is_active().then(|| w.handle().clone()))
|
||||
.collect();
|
||||
let mut new_active = Vec::new();
|
||||
for (outputs, workspace) in workspaces {
|
||||
// XXX efficiency
|
||||
let old_workspace = old_workspaces.for_handle(&workspace.handle);
|
||||
|
|
@ -584,15 +647,26 @@ impl Application for App {
|
|||
let dnd_source_id = old_workspace
|
||||
.map_or_else(iced::id::Id::unique, |w| w.dnd_source_id.clone());
|
||||
|
||||
self.workspaces.0.push(Workspace {
|
||||
let w = Workspace {
|
||||
info: workspace,
|
||||
outputs,
|
||||
img,
|
||||
has_cursor,
|
||||
dnd_source_id,
|
||||
});
|
||||
};
|
||||
if w.is_active() {
|
||||
new_active.push(w.handle().clone());
|
||||
}
|
||||
self.workspaces.0.push(w);
|
||||
}
|
||||
self.update_capture_filter();
|
||||
return Task::batch(new_active.into_iter().map(|new| {
|
||||
if old_active.contains(&new) {
|
||||
Task::none()
|
||||
} else {
|
||||
self.update_active_workspace(new).unwrap_or(Task::none())
|
||||
}
|
||||
}));
|
||||
}
|
||||
backend::Event::NewToplevel(handle, info) => {
|
||||
log::debug!("New toplevel: {info:?}");
|
||||
|
|
@ -668,7 +742,11 @@ impl Application for App {
|
|||
{
|
||||
return self.hide();
|
||||
}
|
||||
self.send_wayland_cmd(backend::Cmd::ActivateWorkspace(workspace_handle));
|
||||
|
||||
self.send_wayland_cmd(backend::Cmd::ActivateWorkspace(workspace_handle.clone()));
|
||||
if let Some(value) = self.update_active_workspace(workspace_handle) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Msg::ActivateToplevel(toplevel_handle) => {
|
||||
self.send_wayland_cmd(backend::Cmd::ActivateToplevel(toplevel_handle));
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ fn workspaces_sidebar<'a>(
|
|||
id: window_id,
|
||||
toplevel_id: None,
|
||||
widget_id: None,
|
||||
workspaces_id: None,
|
||||
},
|
||||
widget::container(sidebar_entries_container)
|
||||
.width(width)
|
||||
|
|
@ -527,7 +528,12 @@ fn workspaces_sidebar<'a>(
|
|||
.into()
|
||||
}
|
||||
|
||||
fn toplevel_preview(toplevel: &Toplevel, is_being_dragged: bool) -> cosmic::Element<'static, Msg> {
|
||||
fn toplevel_preview(
|
||||
toplevel: &Toplevel,
|
||||
is_being_dragged: bool,
|
||||
window_id: window::Id,
|
||||
rectangle_track: &rectangle_tracker::RectangleTracker<RectId>,
|
||||
) -> cosmic::Element<'static, Msg> {
|
||||
let cosmic::cosmic_theme::Spacing {
|
||||
space_xxs, space_s, ..
|
||||
} = cosmic::theme::active().cosmic().spacing;
|
||||
|
|
@ -575,7 +581,15 @@ fn toplevel_preview(toplevel: &Toplevel, is_being_dragged: bool) -> cosmic::Elem
|
|||
.align_y(Alignment::Center);
|
||||
|
||||
let alpha = if is_being_dragged { 0.5 } else { 1.0 };
|
||||
let preview = widget::button::custom(capture_image(toplevel.img.as_ref(), alpha))
|
||||
let preview = widget::button::custom(rectangle_track.container(
|
||||
RectId {
|
||||
id: window_id,
|
||||
toplevel_id: Some(toplevel.handle.id()),
|
||||
widget_id: None,
|
||||
workspaces_id: Some(toplevel.info.workspace.iter().map(|h| h.id()).collect()),
|
||||
},
|
||||
capture_image(toplevel.img.as_ref(), alpha),
|
||||
))
|
||||
.selected(
|
||||
toplevel
|
||||
.info
|
||||
|
|
@ -602,24 +616,18 @@ fn toplevel_previews_entry<'a>(
|
|||
) -> cosmic::Element<'a, Msg> {
|
||||
// Dragged window still takes up space until moved, but isn't rendered while drag surface is
|
||||
// shown.
|
||||
let preview = rectangle_track.container(
|
||||
RectId {
|
||||
id: window_id,
|
||||
toplevel_id: Some(toplevel.handle.id()),
|
||||
widget_id: None,
|
||||
},
|
||||
crate::widgets::visibility_wrapper(
|
||||
toplevel_preview(toplevel, is_being_dragged),
|
||||
let preview = crate::widgets::visibility_wrapper(
|
||||
toplevel_preview(toplevel, is_being_dragged, window_id, rectangle_track),
|
||||
!is_being_dragged,
|
||||
),
|
||||
);
|
||||
let toplevel2 = toplevel.clone();
|
||||
let track = rectangle_track.clone();
|
||||
dnd_source_with_drag_surface(
|
||||
DragToplevel {},
|
||||
DragSurface::Toplevel(toplevel.handle.clone()),
|
||||
None,
|
||||
preview.into(),
|
||||
move || toplevel_preview(&toplevel2, true),
|
||||
move || toplevel_preview(&toplevel2, true, window_id, &track),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue