fix: stop tracking rects when dragging
subscription counter changes also ensure that when a window is dropped, it gets a new rectangle.
This commit is contained in:
parent
01b5836a97
commit
28a2bfedad
2 changed files with 85 additions and 30 deletions
88
src/main.rs
88
src/main.rs
|
|
@ -156,6 +156,7 @@ struct Toplevel {
|
||||||
info: ToplevelInfo,
|
info: ToplevelInfo,
|
||||||
img: Option<backend::CaptureImage>,
|
img: Option<backend::CaptureImage>,
|
||||||
icon: Option<PathBuf>,
|
icon: Option<PathBuf>,
|
||||||
|
pub pending_move: Option<ExtWorkspaceHandleV1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -210,6 +211,7 @@ struct App {
|
||||||
action_on_typing_activated: bool,
|
action_on_typing_activated: bool,
|
||||||
rectangle_tracker: Option<RectangleTracker<RectId>>,
|
rectangle_tracker: Option<RectangleTracker<RectId>>,
|
||||||
rects: HashMap<RectId, Rectangle>,
|
rects: HashMap<RectId, Rectangle>,
|
||||||
|
sub_ctr: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -614,6 +616,7 @@ impl Application for App {
|
||||||
if self.layer_surfaces.remove(&id).is_none() {
|
if self.layer_surfaces.remove(&id).is_none() {
|
||||||
log::error!("removing non-existant layer shell id {}?", id);
|
log::error!("removing non-existant layer shell id {}?", id);
|
||||||
}
|
}
|
||||||
|
self.sub_ctr += 1;
|
||||||
self.rects.retain(|k, _| k.id != id);
|
self.rects.retain(|k, _| k.id != id);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -668,6 +671,7 @@ impl Application for App {
|
||||||
handle,
|
handle,
|
||||||
info,
|
info,
|
||||||
img: None,
|
img: None,
|
||||||
|
pending_move: None,
|
||||||
});
|
});
|
||||||
// Close workspaces view if a window spawns while open
|
// Close workspaces view if a window spawns while open
|
||||||
#[cfg(not(feature = "mock-backend"))]
|
#[cfg(not(feature = "mock-backend"))]
|
||||||
|
|
@ -692,19 +696,30 @@ impl Application for App {
|
||||||
// XX must clean up rectangles after the window has moved
|
// XX must clean up rectangles after the window has moved
|
||||||
t_w = Some((handle.id(), info.workspace.clone()));
|
t_w = Some((handle.id(), info.workspace.clone()));
|
||||||
|
|
||||||
|
if toplevel
|
||||||
|
.pending_move
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|w| info.workspace.contains(&w.id()))
|
||||||
|
{
|
||||||
|
toplevel.pending_move = None;
|
||||||
|
}
|
||||||
toplevel.info = info;
|
toplevel.info = info;
|
||||||
|
|
||||||
tasks.push(task);
|
tasks.push(task);
|
||||||
}
|
}
|
||||||
if let Some((t, w)) = t_w {
|
if let Some((t, w)) = t_w {
|
||||||
for w in w {
|
for w in w {
|
||||||
|
let old_len = self.rects.len();
|
||||||
self.rects.retain(|id, _| {
|
self.rects.retain(|id, _| {
|
||||||
!(id.toplevel_id.as_ref().is_some_and(|old| *old == t)
|
id.toplevel_id.as_ref().is_none_or(|old| *old != t)
|
||||||
&& id
|
|| id
|
||||||
.workspaces_id
|
.workspaces_id
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|old| !old.contains(&w.id())))
|
.is_some_and(|old| old.contains(&w.id()))
|
||||||
});
|
});
|
||||||
|
if old_len != self.rects.len() {
|
||||||
|
self.sub_ctr += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.visible {
|
if self.visible {
|
||||||
|
|
@ -803,7 +818,19 @@ impl Application for App {
|
||||||
self.send_wayland_cmd(backend::Cmd::CloseToplevel(toplevel_handle));
|
self.send_wayland_cmd(backend::Cmd::CloseToplevel(toplevel_handle));
|
||||||
}
|
}
|
||||||
Msg::StartDrag(drag_surface) => {
|
Msg::StartDrag(drag_surface) => {
|
||||||
|
// if let DragSurface::Toplevel(t) = &drag_surface {}
|
||||||
self.drag_surface = Some((drag_surface, Default::default()));
|
self.drag_surface = Some((drag_surface, Default::default()));
|
||||||
|
let to_update: Vec<_> = self
|
||||||
|
.workspaces
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.filter_map(|w| w.is_active().then(|| w.handle().id()))
|
||||||
|
.collect();
|
||||||
|
return Task::batch(
|
||||||
|
to_update
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|w| self.update_active_workspace(w)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Msg::DndEnter(drop_target, _x, _y, _mimes) => {
|
Msg::DndEnter(drop_target, _x, _y, _mimes) => {
|
||||||
self.drop_target = Some(drop_target);
|
self.drop_target = Some(drop_target);
|
||||||
|
|
@ -814,6 +841,21 @@ impl Application for App {
|
||||||
if self.drop_target == Some(drop_target) {
|
if self.drop_target == Some(drop_target) {
|
||||||
self.drop_target = None;
|
self.drop_target = None;
|
||||||
}
|
}
|
||||||
|
self.sub_ctr += 1;
|
||||||
|
|
||||||
|
if self.visible {
|
||||||
|
let to_update: Vec<_> = self
|
||||||
|
.workspaces
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.filter_map(|w| w.is_active().then(|| w.handle().id()))
|
||||||
|
.collect();
|
||||||
|
return Task::batch(
|
||||||
|
to_update
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|w| self.update_active_workspace(w)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Msg::DndToplevelDrop(_toplevel) => {
|
Msg::DndToplevelDrop(_toplevel) => {
|
||||||
if let Some((DragSurface::Toplevel(handle), _)) = &self.drag_surface {
|
if let Some((DragSurface::Toplevel(handle), _)) = &self.drag_surface {
|
||||||
|
|
@ -822,26 +864,34 @@ impl Application for App {
|
||||||
DropTarget::WorkspaceSidebarEntry(workspace, output)
|
DropTarget::WorkspaceSidebarEntry(workspace, output)
|
||||||
| DropTarget::OutputToplevels(workspace, output),
|
| DropTarget::OutputToplevels(workspace, output),
|
||||||
) => {
|
) => {
|
||||||
let mut w = None;
|
if let Some(t) = self.toplevels.for_handle_mut(handle)
|
||||||
self.rects.retain(|id, _| {
|
&& !t.info.workspace.contains(&workspace.id())
|
||||||
id.toplevel_id.as_ref().is_none_or(|t| {
|
{
|
||||||
let keep = *t != handle.id();
|
self.rects.retain(|r, _| {
|
||||||
if !keep {
|
r.toplevel_id.as_ref().is_none_or(|o| *o != handle.id())
|
||||||
w.clone_from(&id.workspaces_id);
|
});
|
||||||
}
|
self.sub_ctr += 1;
|
||||||
keep
|
|
||||||
})
|
t.pending_move = Some(workspace.clone());
|
||||||
});
|
}
|
||||||
self.send_wayland_cmd(backend::Cmd::MoveToplevelToWorkspace(
|
self.send_wayland_cmd(backend::Cmd::MoveToplevelToWorkspace(
|
||||||
handle.clone(),
|
handle.clone(),
|
||||||
workspace,
|
workspace,
|
||||||
output,
|
output,
|
||||||
));
|
));
|
||||||
if let Some(w) = w {
|
self.drag_surface = None;
|
||||||
return Task::batch(w.into_iter().map(|w| {
|
|
||||||
self.update_active_workspace(w).unwrap_or(Task::none())
|
let to_update: Vec<_> = self
|
||||||
}));
|
.workspaces
|
||||||
}
|
.0
|
||||||
|
.iter()
|
||||||
|
.filter_map(|w| w.is_active().then(|| w.handle().id()))
|
||||||
|
.collect();
|
||||||
|
return Task::batch(
|
||||||
|
to_update
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|w| self.update_active_workspace(w)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Some(
|
Some(
|
||||||
DropTarget::WorkspacesBar(_)
|
DropTarget::WorkspacesBar(_)
|
||||||
|
|
@ -1068,7 +1118,7 @@ impl Application for App {
|
||||||
config_subscription,
|
config_subscription,
|
||||||
comp_config_subscription,
|
comp_config_subscription,
|
||||||
bg_subscription,
|
bg_subscription,
|
||||||
rectangle_tracker_subscription(0).map(|update| Msg::Rectangle(update.1)),
|
rectangle_tracker_subscription(self.sub_ctr).map(|update| Msg::Rectangle(update.1)),
|
||||||
];
|
];
|
||||||
if let Some(conn) = self.conn.clone() {
|
if let Some(conn) = self.conn.clone() {
|
||||||
subscriptions.push(backend::subscription(conn).map(Msg::Wayland));
|
subscriptions.push(backend::subscription(conn).map(Msg::Wayland));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use cosmic::Apply;
|
|
||||||
use cosmic::cctk::cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1;
|
use cosmic::cctk::cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1;
|
||||||
use cosmic::cctk::cosmic_protocols::workspace::v2::client::zcosmic_workspace_handle_v2;
|
use cosmic::cctk::cosmic_protocols::workspace::v2::client::zcosmic_workspace_handle_v2;
|
||||||
use cosmic::cctk::wayland_client::Proxy;
|
use cosmic::cctk::wayland_client::Proxy;
|
||||||
|
|
@ -12,6 +11,7 @@ use cosmic::iced::platform_specific::shell::subsurface_widget::Subsurface;
|
||||||
use cosmic::iced::widget::{column, row};
|
use cosmic::iced::widget::{column, row};
|
||||||
use cosmic::iced::{self, Alignment, Border, Length};
|
use cosmic::iced::{self, Alignment, Border, Length};
|
||||||
use cosmic::widget::{self, Widget, rectangle_tracker};
|
use cosmic::widget::{self, Widget, rectangle_tracker};
|
||||||
|
use cosmic::{Apply, Element};
|
||||||
use cosmic_comp_config::workspace::WorkspaceLayout;
|
use cosmic_comp_config::workspace::WorkspaceLayout;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
|
@ -579,17 +579,22 @@ fn toplevel_preview(
|
||||||
.spacing(8)
|
.spacing(8)
|
||||||
.padding([0, 0, 2, 0])
|
.padding([0, 0, 2, 0])
|
||||||
.align_y(Alignment::Center);
|
.align_y(Alignment::Center);
|
||||||
|
|
||||||
let alpha = if is_being_dragged { 0.5 } else { 1.0 };
|
let alpha = if is_being_dragged { 0.5 } else { 1.0 };
|
||||||
let preview = widget::button::custom(rectangle_track.container(
|
let content = capture_image(toplevel.img.as_ref(), alpha);
|
||||||
RectId {
|
|
||||||
id: window_id,
|
let preview = widget::button::custom(if toplevel.pending_move.is_some() || is_being_dragged {
|
||||||
toplevel_id: Some(toplevel.handle.id()),
|
Element::from(content)
|
||||||
widget_id: None,
|
} else {
|
||||||
workspaces_id: Some(toplevel.info.workspace.iter().map(|h| h.id()).collect()),
|
Element::from(rectangle_track.container(
|
||||||
},
|
RectId {
|
||||||
capture_image(toplevel.img.as_ref(), alpha),
|
id: window_id,
|
||||||
))
|
toplevel_id: Some(toplevel.handle.id()),
|
||||||
|
widget_id: None,
|
||||||
|
workspaces_id: Some(toplevel.info.workspace.iter().map(|h| h.id()).collect()),
|
||||||
|
},
|
||||||
|
content,
|
||||||
|
))
|
||||||
|
})
|
||||||
.selected(
|
.selected(
|
||||||
toplevel
|
toplevel
|
||||||
.info
|
.info
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue