diff --git a/src/input/mod.rs b/src/input/mod.rs index 1c35a97f..48db97db 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -337,7 +337,7 @@ impl State { // Constraint does not apply if not within region if !constraint.region().is_none_or(|x| { x.contains( - (ptr.current_location() - *surface_loc).to_i32_round(), + (ptr.current_location() - *surface_loc).to_i32_floor(), ) }) { return; @@ -382,14 +382,25 @@ impl State { .unwrap_or(current_output.clone()); drop(shell); let output_geometry = output.geometry(); - position.x = position.x.clamp( - output_geometry.loc.x as f64, - (output_geometry.loc.x + output_geometry.size.w - 1) as f64, - ); - position.y = position.y.clamp( - output_geometry.loc.y as f64, - (output_geometry.loc.y + output_geometry.size.h - 1) as f64, - ); + + let scale = output.current_scale().fractional_scale(); + let physical = output + .current_mode() + .map(|mode| output.current_transform().transform_size(mode.size)) + .unwrap_or_default(); + let logical = physical.to_f64().to_logical(scale); + let output_geometry_loc = output_geometry.loc.to_f64(); + // output_geometry.size is a rounded value and may undershoot/overshoot the accurate logical size + // We constrain the position with: + // - output_geometry.size so that we don't send leave events to a fullscreen app + // - logical size so that the position doesn't end up outside the actual size of the output + // See https://github.com/pop-os/cosmic-comp/pull/2568 + let max_x = output_geometry_loc.x + + logical.w.min(output_geometry.size.w as f64).next_down(); + let max_y = output_geometry_loc.y + + logical.h.min(output_geometry.size.h as f64).next_down(); + position.x = position.x.clamp(output_geometry_loc.x, max_x); + position.y = position.y.clamp(output_geometry_loc.y, max_y); if ptr.is_grabbed() { if seat @@ -543,7 +554,7 @@ impl State { if let Some(region) = &confine_region && !region - .contains((pos.as_logical() - *surface_loc).to_i32_round()) + .contains((pos.as_logical() - *surface_loc).to_i32_floor()) { return (false, None); } @@ -614,7 +625,7 @@ impl State { PointerConstraint::Confined(confined) => confined.region(), }; let point = - (ptr.current_location() - surface_location).to_i32_round(); + (ptr.current_location() - surface_location).to_i32_floor(); if region.is_none_or(|region| region.contains(point)) { constraint.activate(); } @@ -2210,7 +2221,7 @@ impl State { if Rectangle::new(offset.as_local(), output_geo.size) .intersection(output_geo) .is_some_and(|geometry| { - geometry.contains(global_pos.to_local(output).to_i32_round()) + geometry.contains(global_pos.to_local(output).to_i32_floor()) }) && let Some(element) = workspace.popup_element_under(location, seat) { @@ -2224,7 +2235,7 @@ impl State { if Rectangle::new(offset.as_local(), output_geo.size) .intersection(output_geo) .is_some_and(|geometry| { - geometry.contains(global_pos.to_local(output).to_i32_round()) + geometry.contains(global_pos.to_local(output).to_i32_floor()) }) && let Some(element) = workspace.toplevel_element_under(location, seat) { @@ -2427,7 +2438,7 @@ impl State { if let Some(constraint) = constraint && let Some(region) = constraint.region() { - let point_in_surface = (p - surface_offset.to_f64()).to_i32_round(); + let point_in_surface = (p - surface_offset.to_f64()).to_i32_floor(); return region.contains(point_in_surface); } true diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index fabb87bd..d466f4e0 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -530,7 +530,7 @@ impl CosmicStack { let geo = p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry(); if surface_type.contains(WindowSurfaceType::TOPLEVEL) { - let point_i32 = relative_pos.to_i32_round::(); + let point_i32 = relative_pos.to_i32_floor::(); if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) || (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0) || (point_i32.x - geo.loc.x >= geo.size.w diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 324299e0..86c2ce7f 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -113,7 +113,7 @@ impl Focus { location: Point, ) -> Option { let geo = surface.geometry(); - let loc = location.to_i32_round::() - geo.loc; + let loc = location.to_i32_floor::() - geo.loc; if loc.y < 0 && loc.x < 0 { Some(Focus::ResizeTopLeft) } else if loc.y < 0 && loc.x >= geo.size.w { @@ -292,7 +292,7 @@ impl CosmicWindow { { let geo = p.window.geometry(); - let point_i32 = relative_pos.to_i32_round::(); + let point_i32 = relative_pos.to_i32_floor::(); let ssd_height = if has_ssd { SSD_HEIGHT } else { 0 }; if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) diff --git a/src/shell/grabs/menu/mod.rs b/src/shell/grabs/menu/mod.rs index 46639631..72ea065b 100644 --- a/src/shell/grabs/menu/mod.rs +++ b/src/shell/grabs/menu/mod.rs @@ -548,7 +548,7 @@ impl PointerGrab for MenuGrab { let mut bbox = elem.iced.bbox(); bbox.loc = elem.position.as_logical(); - bbox.contains(event_location.to_i32_round()) + bbox.contains(event_location.to_i32_floor()) }) { let element = &mut elements[i]; @@ -753,7 +753,7 @@ impl TouchGrab for MenuGrab { let mut bbox = elem.iced.bbox(); bbox.loc = elem.position.as_logical(); - bbox.contains(event_location.to_i32_round()) + bbox.contains(event_location.to_i32_floor()) }) { let element = &mut elements[i]; diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 65e901cb..2d95cd27 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -3150,7 +3150,7 @@ impl TilingLayout { location_f64: Point, seat: &Seat, ) -> Option { - let location = location_f64.to_i32_round(); + let location = location_f64.to_i32_floor(); for (mapped, geo) in self.mapped() { if !mapped.bbox().contains((location - geo.loc).as_logical()) { @@ -3177,7 +3177,7 @@ impl TilingLayout { location_f64: Point, seat: &Seat, ) -> Option { - let location = location_f64.to_i32_round(); + let location = location_f64.to_i32_floor(); for (mapped, geo) in self.mapped() { // Tiled windows are rendered cropped to their tile (`geo`), so input must be bound to the tile as well @@ -3209,7 +3209,7 @@ impl TilingLayout { overview: OverviewMode, seat: &Seat, ) -> Option<(PointerFocusTarget, Point)> { - let location = location_f64.to_i32_round(); + let location = location_f64.to_i32_floor(); if matches!(overview, OverviewMode::None) { for (mapped, geo) in self.mapped() { @@ -3244,7 +3244,7 @@ impl TilingLayout { ) -> Option<(PointerFocusTarget, Point)> { let tree = &self.queue.trees.back().unwrap().0; let root = tree.root_node_id()?; - let location = location_f64.to_i32_round(); + let location = location_f64.to_i32_floor(); if matches!(overview, OverviewMode::None) { for (mapped, geo) in self.mapped() { @@ -3305,7 +3305,7 @@ impl TilingLayout { .. }, )) => { - let test_point = (location.to_f64() - last_geometry.loc.to_f64() + let test_point = (location_f64 - last_geometry.loc.to_f64() + mapped.geometry().loc.to_f64().as_local()) .as_logical(); mapped @@ -3410,7 +3410,7 @@ impl TilingLayout { } let location_f64 = location_f64.unwrap(); - let location = location_f64.to_i32_round(); + let location = location_f64.to_i32_floor(); if matches!( overview.active_trigger(), @@ -3660,7 +3660,7 @@ impl TilingLayout { TargetZone::WindowStack(id, last_geometry) } else { let left_right = { - let relative_loc = (location.x - last_geometry.loc.x) as f64; + let relative_loc = location_f64.x - last_geometry.loc.x as f64; if relative_loc < last_geometry.size.w as f64 / 2.0 { (Direction::Left, relative_loc / last_geometry.size.w as f64) } else { @@ -3671,7 +3671,7 @@ impl TilingLayout { } }; let up_down = { - let relative_loc = (location.y - last_geometry.loc.y) as f64; + let relative_loc = location_f64.y - last_geometry.loc.y as f64; if relative_loc < last_geometry.size.h as f64 / 2.0 { (Direction::Up, relative_loc / last_geometry.size.h as f64) } else { diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 0cc0a407..84a020ff 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -785,7 +785,7 @@ impl Workspace { location: Point, seat: &Seat, ) -> Option { - if !self.output.geometry().contains(location.to_i32_round()) { + if !self.output.geometry().contains(location.to_i32_floor()) { return None; } let location = location.to_local(&self.output); @@ -834,7 +834,7 @@ impl Workspace { location: Point, seat: &Seat, ) -> Option { - if !self.output.geometry().contains(location.to_i32_round()) { + if !self.output.geometry().contains(location.to_i32_floor()) { return None; } let location = location.to_local(&self.output); @@ -884,7 +884,7 @@ impl Workspace { overview: OverviewMode, seat: &Seat, ) -> Option<(PointerFocusTarget, Point)> { - if !self.output.geometry().contains(location.to_i32_round()) { + if !self.output.geometry().contains(location.to_i32_floor()) { return None; } let location = location.to_local(&self.output); @@ -934,7 +934,7 @@ impl Workspace { overview: OverviewMode, seat: &Seat, ) -> Option<(PointerFocusTarget, Point)> { - if !self.output.geometry().contains(location.to_i32_round()) { + if !self.output.geometry().contains(location.to_i32_floor()) { return None; } let location = location.to_local(&self.output); diff --git a/src/wayland/handlers/pointer_constraints.rs b/src/wayland/handlers/pointer_constraints.rs index e17c1961..9ce5f63a 100644 --- a/src/wayland/handlers/pointer_constraints.rs +++ b/src/wayland/handlers/pointer_constraints.rs @@ -63,7 +63,7 @@ impl PointerConstraintsHandler for State { if let Some(region) = constraint.region() { if let Some(surface_location) = surface_location && let position = pointer.current_location() - && let point = (position - surface_location.as_logical()).to_i32_round() + && let point = (position - surface_location.as_logical()).to_i32_floor() && region.contains(point) { constraint.activate();