grabs: Snap Window Edges to Close Output Edges

This commit is contained in:
Daniel 2025-02-14 21:58:09 +11:00 committed by GitHub
parent 2678cf41b2
commit 2553810621
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 148 additions and 13 deletions

View file

@ -288,7 +288,12 @@ pub fn window_items(
let _ = handle.insert_idle(move |state| {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::TOP);
let res = shell.menu_resize_request(
&resize_clone,
&seat,
ResizeEdge::TOP,
state.common.config.cosmic_conf.edge_snap_threshold,
);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
@ -318,7 +323,12 @@ pub fn window_items(
let _ = handle.insert_idle(move |state| {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::LEFT);
let res = shell.menu_resize_request(
&resize_clone,
&seat,
ResizeEdge::LEFT,
state.common.config.cosmic_conf.edge_snap_threshold,
);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
@ -348,8 +358,12 @@ pub fn window_items(
let _ = handle.insert_idle(move |state| {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res =
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::RIGHT);
let res = shell.menu_resize_request(
&resize_clone,
&seat,
ResizeEdge::RIGHT,
state.common.config.cosmic_conf.edge_snap_threshold,
);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
@ -379,8 +393,12 @@ pub fn window_items(
let _ = handle.insert_idle(move |state| {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res =
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::BOTTOM);
let res = shell.menu_resize_request(
&resize_clone,
&seat,
ResizeEdge::BOTTOM,
state.common.config.cosmic_conf.edge_snap_threshold,
);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {

View file

@ -342,6 +342,7 @@ pub struct MoveGrab {
window_outputs: HashSet<Output>,
previous: ManagedLayer,
release: ReleaseMode,
window_snap_threshold: f64,
// SAFETY: This is only used on drop which will always be on the main thread
evlh: NotSend<LoopHandle<'static, State>>,
}
@ -383,6 +384,40 @@ impl MoveGrab {
let mut window_geo = self.window.geometry();
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
if matches!(self.previous, ManagedLayer::Floating | ManagedLayer::Sticky) {
let loc = (grab_state.window_offset.to_f64() + grab_state.location).as_local();
let size = window_geo.size.to_f64().as_local();
let output_geom = self
.cursor_output
.geometry()
.to_f64()
.to_local(&self.cursor_output);
let output_loc = output_geom.loc;
let output_size = output_geom.size;
grab_state.location.x = if (loc.x - output_loc.x).abs() < self.window_snap_threshold
{
output_loc.x - grab_state.window_offset.x as f64
} else if ((loc.x + size.w) - (output_loc.x + output_size.w)).abs()
< self.window_snap_threshold
{
output_loc.x + output_size.w - grab_state.window_offset.x as f64 - size.w
} else {
grab_state.location.x
};
grab_state.location.y = if (loc.y - output_loc.y).abs() < self.window_snap_threshold
{
output_loc.y - grab_state.window_offset.y as f64
} else if ((loc.y + size.h) - (output_loc.y + output_size.h)).abs()
< self.window_snap_threshold
{
output_loc.y + output_size.h - grab_state.window_offset.y as f64 - size.h
} else {
grab_state.location.y
};
}
for output in shell.outputs() {
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
if self.window_outputs.insert(output.clone()) {
@ -681,6 +716,7 @@ impl MoveGrab {
initial_window_location: Point<i32, Global>,
cursor_output: Output,
indicator_thickness: u8,
window_snap_threshold: f64,
previous_layer: ManagedLayer,
release: ReleaseMode,
evlh: LoopHandle<'static, State>,
@ -720,10 +756,11 @@ impl MoveGrab {
window,
start_data,
seat: seat.clone(),
window_outputs: outputs,
cursor_output,
window_outputs: outputs,
previous: previous_layer,
release,
window_snap_threshold,
evlh: NotSend(evlh),
}
}