From 42aaafe586c44b5250d157701dba3336f7a4bac4 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 25 Oct 2023 19:24:51 +0200 Subject: [PATCH] utils: New geometry spaces local/global --- src/backend/render/mod.rs | 20 +- src/input/mod.rs | 229 +++++++++++----------- src/shell/element/mod.rs | 23 +-- src/shell/element/stack.rs | 10 +- src/shell/element/surface.rs | 7 +- src/shell/element/window.rs | 4 +- src/shell/grabs/moving.rs | 99 +++++----- src/shell/layout/floating/grabs/resize.rs | 22 ++- src/shell/layout/floating/mod.rs | 2 +- src/shell/layout/tiling/mod.rs | 125 +++++++----- src/shell/mod.rs | 32 +-- src/shell/workspace.rs | 23 ++- src/utils/geometry.rs | 149 ++++++++++++++ src/utils/mod.rs | 1 + src/utils/prelude.rs | 8 +- src/wayland/handlers/screencopy.rs | 4 +- src/wayland/handlers/xdg_shell/popup.rs | 37 ++-- src/xwayland.rs | 21 +- 18 files changed, 516 insertions(+), 300 deletions(-) create mode 100644 src/utils/geometry.rs diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index 75cead8a..97437b1c 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -17,7 +17,7 @@ use crate::{ CosmicMapped, CosmicMappedRenderElement, OverviewMode, Trigger, WorkspaceRenderElement, }, state::{Common, Fps}, - utils::prelude::{OutputExt, SeatExt}, + utils::prelude::*, wayland::{ handlers::{ data_device::get_dnd_icon, @@ -160,7 +160,7 @@ impl IndicatorShader { pub fn focus_element( renderer: &R, key: impl Into, - mut element_geo: Rectangle, + mut element_geo: Rectangle, thickness: u8, scale: f64, alpha: f32, @@ -184,7 +184,7 @@ impl IndicatorShader { pub fn element( renderer: &R, key: impl Into, - geo: Rectangle, + geo: Rectangle, thickness: u8, radius: u8, alpha: f32, @@ -223,7 +223,7 @@ impl IndicatorShader { let elem = PixelShaderElement::new( shader, - geo, + geo.as_logical(), None, //TODO alpha, vec![ @@ -240,8 +240,8 @@ impl IndicatorShader { } let elem = &mut cache.get_mut(&key).unwrap().1; - if elem.geometry(1.0.into()).to_logical(1) != geo { - elem.resize(geo, None); + if elem.geometry(1.0.into()).to_logical(1) != geo.as_logical() { + elem.resize(geo.as_logical(), None); } elem.clone() } @@ -271,7 +271,7 @@ impl BackdropShader { pub fn element( renderer: &R, key: impl Into, - geo: Rectangle, + geo: Rectangle, radius: f32, alpha: f32, color: [f32; 3], @@ -304,7 +304,7 @@ impl BackdropShader { let elem = PixelShaderElement::new( shader, - geo, + geo.as_logical(), None, // TODO alpha, vec![ @@ -320,8 +320,8 @@ impl BackdropShader { } let elem = &mut cache.get_mut(&key).unwrap().1; - if elem.geometry(1.0.into()).to_logical(1) != geo { - elem.resize(geo, None); + if elem.geometry(1.0.into()).to_logical(1) != geo.as_logical() { + elem.resize(geo.as_logical(), None); } elem.clone() } diff --git a/src/input/mod.rs b/src/input/mod.rs index 41e1a864..0c4265b1 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -553,24 +553,18 @@ impl State { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { let current_output = seat.active_output(); - let mut position = seat.get_pointer().unwrap().current_location(); + let mut position = seat.get_pointer().unwrap().current_location().as_global(); - let relative_pos = self - .common - .shell - .map_global_to_space(position, ¤t_output); let overview = self.common.shell.overview_mode(); - let output_geometry = current_output.geometry(); let workspace = self.common.shell.workspaces.active_mut(¤t_output); let under = State::surface_under( position, - relative_pos, ¤t_output, - output_geometry, &self.common.shell.override_redirect_windows, overview.0.clone(), workspace, - ); + ) + .map(|(target, pos)| (target, pos.as_logical())); let ptr = seat.get_pointer().unwrap(); @@ -618,7 +612,7 @@ impl State { return; } - position += event.delta(); + position += event.delta().as_global(); let output = self .common @@ -627,18 +621,17 @@ impl State { .find(|output| output.geometry().to_f64().contains(position)) .cloned() .unwrap_or(current_output.clone()); + let output_geometry = output.geometry(); let workspace = self.common.shell.workspaces.active_mut(&output); - let output_geometry = output.geometry(); let new_under = State::surface_under( position, - relative_pos, &output, - output_geometry, &self.common.shell.override_redirect_windows, overview.0, workspace, - ); + ) + .map(|(target, pos)| (target, pos.as_logical())); position.x = position.x.clamp( output_geometry.loc.x as f64, @@ -660,13 +653,17 @@ impl State { } if let PointerFocusTarget::Element(element) = surface { //if !element.is_in_input_region(&(position.to_i32_round() - *surface_loc).to_f64()) { - if !element.is_in_input_region(&(position - surface_loc.to_f64())) { + if !element.is_in_input_region( + &(position.as_logical() - surface_loc.to_f64()), + ) { ptr.frame(self); return; } } if let Some(region) = confine_region { - if !region.contains(position.to_i32_round() - *surface_loc) { + if !region + .contains(position.as_logical().to_i32_round() - *surface_loc) + { ptr.frame(self); return; } @@ -679,7 +676,7 @@ impl State { self, under, &MotionEvent { - location: position, + location: position.as_logical(), serial, time: event.time_msec(), }, @@ -720,17 +717,16 @@ impl State { for session in sessions_for_output(&self.common, &output) { if let Some((geometry, offset)) = seat.cursor_geometry( - position.to_buffer( + position.as_logical().to_buffer( output.current_scale().fractional_scale(), output.current_transform(), - &output.geometry().size.to_f64(), + &output_geometry.size.to_f64().as_logical(), ), self.common.clock.now(), ) { session.cursor_info(&seat, InputType::Pointer, geometry, offset); } } - #[cfg(feature = "debug")] if self.common.seats().position(|x| x == &seat).unwrap() == 0 { let location = if let Some(output) = self.common.shell.outputs.first() { @@ -752,28 +748,27 @@ impl State { let position = geometry.loc.to_f64() + smithay::backend::input::AbsolutePositionEvent::position_transformed( &event, - geometry.size, - ); - let relative_pos = self.common.shell.map_global_to_space(position, &output); + geometry.size.as_logical(), + ) + .as_global(); let overview = self.common.shell.overview_mode(); let workspace = self.common.shell.workspaces.active_mut(&output); let serial = SERIAL_COUNTER.next_serial(); let under = State::surface_under( position, - relative_pos, &output, - geometry, &self.common.shell.override_redirect_windows, overview.0, workspace, - ); + ) + .map(|(target, pos)| (target, pos.as_logical())); for session in sessions_for_output(&self.common, &output) { if let Some((geometry, offset)) = seat.cursor_geometry( - position.to_buffer( + position.as_logical().to_buffer( output.current_scale().fractional_scale(), output.current_transform(), - &output.geometry().size.to_f64(), + &geometry.size.to_f64().as_logical(), ), self.common.clock.now(), ) { @@ -785,7 +780,7 @@ impl State { self, under, &MotionEvent { - location: position, + location: position.as_logical(), serial, time: event.time_msec(), }, @@ -835,22 +830,22 @@ impl State { && !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false) { let output = seat.active_output(); - let pos = seat.get_pointer().unwrap().current_location(); - let relative_pos = self.common.shell.map_global_to_space(pos, &output); + let pos = seat.get_pointer().unwrap().current_location().as_global(); + let relative_pos = pos.to_local(&output); let overview = self.common.shell.overview_mode(); let workspace = self.common.shell.active_space_mut(&output); let mut under = None; - if let Some(window) = workspace.get_fullscreen(&output) { + if let Some(window) = workspace.get_fullscreen() { let layers = layer_map_for_output(&output); if let Some(layer) = - layers.layer_under(WlrLayer::Overlay, relative_pos) + layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; if layer.can_receive_keyboard_focus() && layer .surface_under( - relative_pos - layer_loc.to_f64(), + relative_pos.as_logical() - layer_loc.to_f64(), WindowSurfaceType::ALL, ) .is_some() @@ -864,14 +859,19 @@ impl State { let done = { let layers = layer_map_for_output(&output); if let Some(layer) = layers - .layer_under(WlrLayer::Overlay, relative_pos) - .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos)) + .layer_under(WlrLayer::Overlay, relative_pos.as_logical()) + .or_else(|| { + layers.layer_under( + WlrLayer::Top, + relative_pos.as_logical(), + ) + }) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; if layer.can_receive_keyboard_focus() && layer .surface_under( - relative_pos - layer_loc.to_f64(), + relative_pos.as_logical() - layer_loc.to_f64(), WindowSurfaceType::ALL, ) .is_some() @@ -884,35 +884,38 @@ impl State { } }; if !done { - if let Some(surface) = workspace.get_maximized(&output) { - under = Some(surface.clone().into()); + if let Some((target, _)) = + workspace.element_under(pos, overview.0) + { + under = Some(target); } else { - if let Some((target, _)) = - workspace.element_under(relative_pos, overview.0) + let layers = layer_map_for_output(&output); + if let Some(layer) = layers + .layer_under( + WlrLayer::Bottom, + relative_pos.as_logical(), + ) + .or_else(|| { + layers.layer_under( + WlrLayer::Background, + relative_pos.as_logical(), + ) + }) { - under = Some(target); - } else { - let layers = layer_map_for_output(&output); - if let Some(layer) = layers - .layer_under(WlrLayer::Bottom, pos) - .or_else(|| { - layers.layer_under(WlrLayer::Background, pos) - }) + let layer_loc = + layers.layer_geometry(layer).unwrap().loc; + if layer.can_receive_keyboard_focus() + && layer + .surface_under( + relative_pos.as_logical() + - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) + .is_some() { - let layer_loc = - layers.layer_geometry(layer).unwrap().loc; - if layer.can_receive_keyboard_focus() - && layer - .surface_under( - relative_pos - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - under = Some(layer.clone().into()); - } - }; - } + under = Some(layer.clone().into()); + } + }; } } } @@ -1349,7 +1352,7 @@ impl State { self, None, &MotionEvent { - location: new_pos.to_f64(), + location: new_pos.to_f64().as_logical(), serial, time, }, @@ -1386,7 +1389,7 @@ impl State { self, None, &MotionEvent { - location: new_pos.to_f64(), + location: new_pos.to_f64().as_logical(), serial, time, }, @@ -1426,7 +1429,7 @@ impl State { self, None, &MotionEvent { - location: new_pos.to_f64(), + location: new_pos.to_f64().as_logical(), serial, time, }, @@ -1462,7 +1465,7 @@ impl State { self, None, &MotionEvent { - location: new_pos.to_f64(), + location: new_pos.to_f64().as_logical(), serial, time, }, @@ -1705,77 +1708,83 @@ impl State { } pub fn surface_under( - global_pos: Point, - relative_pos: Point, + global_pos: Point, output: &Output, - output_geo: Rectangle, override_redirect_windows: &[X11Surface], overview: OverviewMode, workspace: &mut Workspace, - ) -> Option<(PointerFocusTarget, Point)> { - if let Some(window) = workspace.get_fullscreen(output) { + ) -> Option<(PointerFocusTarget, Point)> { + let relative_pos = global_pos.to_local(output); + let output_geo = output.geometry(); + + if let Some(window) = workspace.get_fullscreen() { let layers = layer_map_for_output(output); - if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos) { + if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; if layer - .surface_under(relative_pos - layer_loc.to_f64(), WindowSurfaceType::ALL) + .surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) .is_some() { - return Some((layer.clone().into(), output_geo.loc + layer_loc)); + return Some((layer.clone().into(), output_geo.loc + layer_loc.as_global())); } } - if let Some(or) = override_redirect_windows - .iter() - .find(|or| or.is_in_input_region(&(global_pos - or.geometry().loc.to_f64()))) - { - return Some((or.clone().into(), or.geometry().loc)); + if let Some(or) = override_redirect_windows.iter().find(|or| { + or.is_in_input_region(&(global_pos.as_logical() - or.geometry().loc.to_f64())) + }) { + return Some((or.clone().into(), or.geometry().loc.as_global())); } Some((window.clone().into(), output_geo.loc)) } else { { let layers = layer_map_for_output(output); if let Some(layer) = layers - .layer_under(WlrLayer::Overlay, relative_pos) - .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos)) + .layer_under(WlrLayer::Overlay, relative_pos.as_logical()) + .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos.as_logical())) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; if layer - .surface_under(relative_pos - layer_loc.to_f64(), WindowSurfaceType::ALL) + .surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) .is_some() { - return Some((layer.clone().into(), output_geo.loc + layer_loc)); + return Some(( + layer.clone().into(), + output_geo.loc + layer_loc.as_global(), + )); } } } - if let Some(or) = override_redirect_windows - .iter() - .find(|or| or.is_in_input_region(&(global_pos - or.geometry().loc.to_f64()))) - { - return Some((or.clone().into(), or.geometry().loc)); + if let Some(or) = override_redirect_windows.iter().find(|or| { + or.is_in_input_region(&(global_pos.as_logical() - or.geometry().loc.to_f64())) + }) { + return Some((or.clone().into(), or.geometry().loc.as_global())); } - if let Some(surface) = workspace.get_maximized(output) { - let offset = layer_map_for_output(output).non_exclusive_zone().loc; - return Some((surface.clone().into(), output_geo.loc + offset)); - } else { - if let Some((target, loc)) = workspace.element_under(relative_pos, overview) { - return Some((target, loc + (global_pos - relative_pos).to_i32_round())); - } + if let Some((target, loc)) = workspace.element_under(global_pos, overview) { + return Some((target, loc)); + } + { + let layers = layer_map_for_output(output); + if let Some(layer) = layers + .layer_under(WlrLayer::Bottom, relative_pos.as_logical()) + .or_else(|| layers.layer_under(WlrLayer::Background, relative_pos.as_logical())) { - let layers = layer_map_for_output(output); - if let Some(layer) = layers - .layer_under(WlrLayer::Bottom, relative_pos) - .or_else(|| layers.layer_under(WlrLayer::Background, relative_pos)) + let layer_loc = layers.layer_geometry(layer).unwrap().loc; + if layer + .surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) + .is_some() { - let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - return Some((layer.clone().into(), output_geo.loc + layer_loc)); - } + return Some(( + layer.clone().into(), + output_geo.loc + layer_loc.as_global(), + )); } } } diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 12157b2a..dbaf8f16 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -4,7 +4,7 @@ use crate::{ GlMultiError, GlMultiFrame, GlMultiRenderer, }, state::State, - utils::prelude::SeatExt, + utils::prelude::*, }; use calloop::LoopHandle; use id_tree::NodeId; @@ -94,8 +94,8 @@ pub struct CosmicMapped { //tiling pub tiling_node_id: Arc>>, //floating - pub(super) last_geometry: Arc>>>, pub(super) resize_state: Arc>>, + pub last_geometry: Arc>>>, #[cfg(feature = "debug")] debug: Arc>>, @@ -108,6 +108,7 @@ impl fmt::Debug for CosmicMapped { .field("last_cursor_position", &self.last_cursor_position) .field("tiling_node_id", &self.tiling_node_id) .field("resize_state", &self.resize_state) + .field("last_geometry", &self.last_geometry) .finish() } } @@ -361,7 +362,7 @@ impl CosmicMapped { window.is_activated(pending) } - pub fn set_geometry(&self, geo: Rectangle) { + pub fn set_geometry(&self, geo: Rectangle) { match &self.element { CosmicMappedInternal::Stack(s) => s.set_geometry(geo), CosmicMappedInternal::Window(w) => w.set_geometry(geo), @@ -501,11 +502,9 @@ impl CosmicMapped { let stack = CosmicStack::new(std::iter::once(surface), handle); if let Some(geo) = self.last_geometry.lock().unwrap().clone() { - stack.set_geometry(geo); - } - for (output, overlap) in outputs { - stack.output_enter(output, overlap); + stack.set_geometry(geo.to_global(&output)); } + stack.output_enter(output, overlap); stack.set_activate(activated); stack.active().send_configure(); stack.refresh(); @@ -527,11 +526,9 @@ impl CosmicMapped { let window = CosmicWindow::new(surface, handle); if let Some(geo) = self.last_geometry.lock().unwrap().clone() { - window.set_geometry(geo); - } - for (output, overlap) in outputs { - window.output_enter(output, overlap); + window.set_geometry(geo.to_global(&output)); } + window.output_enter(output, overlap); window.set_activate(self.is_activated(true)); window.surface().send_configure(); window.refresh(); @@ -1068,8 +1065,8 @@ impl From for CosmicMapped { element: CosmicMappedInternal::Window(w), last_cursor_position: Arc::new(Mutex::new(HashMap::new())), tiling_node_id: Arc::new(Mutex::new(None)), - last_geometry: Arc::new(Mutex::new(None)), resize_state: Arc::new(Mutex::new(None)), + last_geometry: Arc::new(Mutex::new(None)), #[cfg(feature = "debug")] debug: Arc::new(Mutex::new(None)), } @@ -1082,8 +1079,8 @@ impl From for CosmicMapped { element: CosmicMappedInternal::Stack(s), last_cursor_position: Arc::new(Mutex::new(HashMap::new())), tiling_node_id: Arc::new(Mutex::new(None)), - last_geometry: Arc::new(Mutex::new(None)), resize_state: Arc::new(Mutex::new(None)), + last_geometry: Arc::new(Mutex::new(None)), #[cfg(feature = "debug")] debug: Arc::new(Mutex::new(None)), } diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 04e333ec..54478b3a 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -5,7 +5,7 @@ use crate::{ }, state::State, utils::iced::{IcedElement, Program}, - utils::prelude::SeatExt, + utils::prelude::*, wayland::handlers::screencopy::ScreencopySessions, }; use calloop::LoopHandle; @@ -91,7 +91,7 @@ pub struct CosmicStackInternal { override_alive: Arc, last_seat: Arc, Serial)>>>, last_location: Arc, Serial, u32)>>>, - geometry: Arc>>>, + geometry: Arc>>>, mask: Arc>>, } @@ -406,7 +406,7 @@ impl CosmicStack { Point::from((0, TAB_HEIGHT)) } - pub fn set_geometry(&self, geo: Rectangle) { + pub fn set_geometry(&self, geo: Rectangle) { self.0.with_program(|p| { let loc = (geo.loc.x, geo.loc.y + TAB_HEIGHT); let size = (geo.size.w, geo.size.h - TAB_HEIGHT); @@ -1047,11 +1047,11 @@ impl PointerTarget for CosmicStack { if let Some(workspace) = data.common.shell.space_for(stack_mapped) { // TODO: Unify this somehow with Shell::move_request/Workspace::move_request let button = 0x110; // BTN_LEFT - let pos = event.location; + let pos = event.location.as_global(); let start_data = PointerGrabStartData { focus: None, button, - location: pos, + location: pos.as_logical(), }; let mapped = CosmicMapped::from(CosmicWindow::new( surface, diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index 67b88b1b..c427f1b9 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -51,6 +51,7 @@ use smithay::{ use crate::{ state::{State, SurfaceDmabufFeedback}, + utils::prelude::*, wayland::handlers::decoration::PreferredDecorationMode, }; @@ -122,13 +123,13 @@ impl CosmicSurface { } } - pub fn set_geometry(&self, geo: Rectangle) { + pub fn set_geometry(&self, geo: Rectangle) { match self { CosmicSurface::Wayland(window) => window .toplevel() - .with_pending_state(|state| state.size = Some(geo.size)), + .with_pending_state(|state| state.size = Some(geo.size.as_logical())), CosmicSurface::X11(surface) => { - let _ = surface.configure(geo); + let _ = surface.configure(geo.as_logical()); } _ => {} } diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 67856dd1..92588f29 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -3,7 +3,7 @@ use crate::{ state::State, utils::{ iced::{IcedElement, Program}, - prelude::SeatExt, + prelude::*, }, wayland::handlers::screencopy::ScreencopySessions, }; @@ -132,7 +132,7 @@ impl CosmicWindow { )) } - pub fn set_geometry(&self, geo: Rectangle) { + pub fn set_geometry(&self, geo: Rectangle) { self.0.with_program(|p| { let loc = ( geo.loc.x, diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index e8233b55..e044e4fc 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -82,15 +82,21 @@ impl MoveGrabState { let mut window_geo = self.window.geometry(); window_geo.loc += cursor_at.to_i32_round() + self.window_offset; - if !output.geometry().intersection(window_geo).is_some() { + if !output + .geometry() + .as_logical() + .intersection(window_geo) + .is_some() + { return Vec::new(); } let output_scale: Scale = output.current_scale().fractional_scale().into(); let scaling_offset = self.window_offset - self.window_offset.to_f64().upscale(scale).to_i32_round(); - let render_location = - cursor_at.to_i32_round() - output.geometry().loc + self.window_offset - scaling_offset; + let render_location = cursor_at.to_i32_round() - output.geometry().loc.as_logical() + + self.window_offset + - scaling_offset; let focus_element = if self.indicator_thickness > 0 { Some( @@ -105,7 +111,8 @@ impl MoveGrabState { .to_f64() .upscale(scale) .to_i32_round(), - ), + ) + .as_local(), self.indicator_thickness, output_scale.x, 1.0, @@ -208,6 +215,7 @@ impl PointerGrab for MoveGrab { .find(|output| { output .geometry() + .as_logical() .contains(handle.current_location().to_i32_round()) }) .cloned() @@ -233,8 +241,8 @@ impl PointerGrab for MoveGrab { if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) { let mut window_geo = self.window.geometry(); window_geo.loc += event.location.to_i32_round() + grab_state.window_offset; - for output in &state.common.shell.outputs { - if let Some(overlap) = output.geometry().intersection(window_geo) { + for output in state.common.shell.outputs() { + if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) { if self.window_outputs.insert(output.clone()) { self.window.output_enter(output, overlap); if let Some(indicator) = @@ -261,11 +269,20 @@ impl PointerGrab for MoveGrab { if indicator_location.is_some() != grab_state.stacking_indicator.is_some() { grab_state.stacking_indicator = indicator_location.map(|geo| { - let element = stack_hover(state.common.event_loop_handle.clone(), geo.size); + let element = stack_hover( + state.common.event_loop_handle.clone(), + geo.size.as_logical(), + ); for output in &self.window_outputs { - element.output_enter(output, output.geometry()); + element.output_enter( + output, + Rectangle::from_loc_and_size( + (0, 0), + output.geometry().size.as_logical(), + ), + ); } - (element, geo.loc) + (element, geo.loc.as_logical()) }); } } @@ -397,8 +414,8 @@ impl MoveGrab { start_data: PointerGrabStartData, window: CosmicMapped, seat: &Seat, - initial_cursor_location: Point, - initial_window_location: Point, + initial_cursor_location: Point, + initial_window_location: Point, indicator_thickness: u8, was_tiled: bool, ) -> MoveGrab { @@ -409,7 +426,8 @@ impl MoveGrab { let grab_state = MoveGrabState { window: window.clone(), - window_offset: initial_window_location - initial_cursor_location.to_i32_round(), + window_offset: (initial_window_location - initial_cursor_location.to_i32_round()) + .as_logical(), indicator_thickness, start: Instant::now(), stacking_indicator: None, @@ -451,16 +469,16 @@ impl MoveGrab { // No more buttons are pressed, release the grab. let output = self.seat.active_output(); - let position = if let Some(grab_state) = self + let position: Option<(CosmicMapped, Point)> = if let Some(grab_state) = self .seat .user_data() .get::() .and_then(|s| s.borrow_mut().take()) { if grab_state.window.alive() { - let window_location = handle.current_location().to_i32_round() - - output.geometry().loc - + grab_state.window_offset; + let window_location = (handle.current_location().to_i32_round() + + grab_state.window_offset) + .as_global(); let workspace_handle = state.common.shell.active_space(&output).handle; for old_output in self.window_outputs.iter().filter(|o| *o != &output) { @@ -480,41 +498,26 @@ impl MoveGrab { } if self.tiling { - Some( - state - .common - .shell - .active_space_mut(&output) - .tiling_layer - .drop_window(grab_state.window, &output, handle.current_location()), - ) - } else { - let offset = state - .common - .shell - .active_space(&output) - .floating_layer - .space - .output_geometry(&output) - .unwrap() - .loc; - grab_state.window.set_geometry(Rectangle::from_loc_and_size( - window_location + offset, - grab_state.window.geometry().size, - )); - state + let (window, location) = state .common .shell .active_space_mut(&output) - .floating_layer - .map_internal(grab_state.window, &output, Some(window_location + offset)); + .tiling_layer + .drop_window(grab_state.window); + Some((window, location.to_global(&output))) + } else { + grab_state.window.set_geometry(Rectangle::from_loc_and_size( + window_location, + grab_state.window.geometry().size.as_global(), + )); + let workspace = state.common.shell.active_space_mut(&output); + workspace.floating_layer.map_internal( + grab_state.window, + Some(window_location.to_local(&workspace.output)), + None, + ); - let pointer_pos = handle.current_location(); - let relative_pos = state.common.shell.map_global_to_space(pointer_pos, &output); - Some(( - self.window.clone(), - window_location + offset + (pointer_pos - relative_pos).to_i32_round(), - )) + Some((self.window.clone(), window_location)) } } else { None @@ -535,7 +538,7 @@ impl MoveGrab { state, Some(( PointerFocusTarget::from(mapped.clone()), - position - self.window.geometry().loc, + position.as_logical() - self.window.geometry().loc, )), &MotionEvent { location: handle.current_location(), diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index 530c9a86..89b9ef54 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -101,10 +101,10 @@ impl PointerGrab for ResizeSurfaceGrab { self.window.set_resizing(true); self.window.set_geometry(Rectangle::from_loc_and_size( match self.window.active_window() { - CosmicSurface::X11(s) => s.geometry().loc, + CosmicSurface::X11(s) => s.geometry().loc.as_global(), _ => (0, 0).into(), }, - self.last_window_size, + self.last_window_size.as_global(), )); self.window.configure(); } @@ -139,10 +139,10 @@ impl PointerGrab for ResizeSurfaceGrab { self.window.set_resizing(false); self.window.set_geometry(Rectangle::from_loc_and_size( match self.window.active_window() { - CosmicSurface::X11(s) => s.geometry().loc, + CosmicSurface::X11(s) => s.geometry().loc.as_global(), _ => (0, 0).into(), }, - self.last_window_size, + self.last_window_size.as_global(), )); self.window.configure(); @@ -271,7 +271,13 @@ impl ResizeSurfaceGrab { } pub fn apply_resize_to_location(window: CosmicMapped, space: &mut Workspace) { - if let Some(location) = space.floating_layer.space.element_location(&window) { + if let Some(location) = space + .floating_layer + .space + .element_location(&window) + .map(PointExt::as_local) + .map(|p| p.to_global(space.output())) + { let mut new_location = None; let mut resize_state = window.resize_state.lock().unwrap(); @@ -316,13 +322,13 @@ impl ResizeSurfaceGrab { CosmicSurface::Wayland(window) => { update_reactive_popups( &window, - new_location + offset, + new_location + offset.as_global(), space.floating_layer.space.outputs(), ); } CosmicSurface::X11(surface) => { let mut geometry = surface.geometry(); - geometry.loc += location - new_location; + geometry.loc += (location - new_location).as_logical(); let _ = surface.configure(geometry); } _ => unreachable!(), @@ -331,7 +337,7 @@ impl ResizeSurfaceGrab { space .floating_layer .space - .map_element(window, new_location, false); + .map_element(window, new_location.as_logical(), false); } } } diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 8595ea9b..8955acfe 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -471,7 +471,7 @@ impl FloatingLayout { }) .then_some(pos); - self.map_internal(mapped.clone(), &output, position); + self.map_internal(mapped.clone(), position.map(PointExt::as_local), None); return MoveResult::ShiftFocus(KeyboardFocusTarget::Element(mapped)); } StackMoveResult::Default => {} diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 7e4c4d78..cdb6de1d 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -116,7 +116,7 @@ pub struct NodeDesc { enum TargetZone { Initial, InitialPlaceholder(NodeId), - WindowStack(NodeId, Rectangle), + WindowStack(NodeId, Rectangle), WindowSplit(NodeId, Direction), GroupEdge(NodeId, Direction), GroupInterior(NodeId, usize), @@ -171,22 +171,22 @@ pub enum Data { Group { orientation: Orientation, sizes: Vec, - last_geometry: Rectangle, + last_geometry: Rectangle, alive: Arc<()>, pill_indicator: Option, }, Mapped { mapped: CosmicMapped, - last_geometry: Rectangle, + last_geometry: Rectangle, }, Placeholder { - last_geometry: Rectangle, + last_geometry: Rectangle, initial_placeholder: bool, }, } impl Data { - fn new_group(orientation: Orientation, geo: Rectangle) -> Data { + fn new_group(orientation: Orientation, geo: Rectangle) -> Data { Data::Group { orientation, sizes: vec![ @@ -296,7 +296,7 @@ impl Data { } } - fn geometry(&self) -> &Rectangle { + fn geometry(&self) -> &Rectangle { match self { Data::Group { last_geometry, .. } => last_geometry, Data::Mapped { last_geometry, .. } => last_geometry, @@ -304,7 +304,7 @@ impl Data { } } - fn update_geometry(&mut self, geo: Rectangle) { + fn update_geometry(&mut self, geo: Rectangle) { match self { Data::Group { orientation, @@ -2816,7 +2816,9 @@ impl TilingLayout { let mut configures = Vec::new(); let (outer, inner) = gaps; - let mut geo = layer_map_for_output(&output).non_exclusive_zone(); + let mut geo = layer_map_for_output(&output) + .non_exclusive_zone() + .as_local(); geo.loc.x += outer; geo.loc.y += outer; geo.size.w -= outer * 2; @@ -3861,8 +3863,8 @@ fn swap_factor(size: Size) -> f64 { fn swap_geometry( size: Size, - relative_to: Rectangle, -) -> Rectangle { + relative_to: Rectangle, +) -> Rectangle { let factor = swap_factor(size); let new_size = Size::from(( @@ -3881,7 +3883,7 @@ fn swap_geometry( fn geometries_for_groupview<'a, R>( tree: &Tree, renderer: impl Into>, - non_exclusive_zone: Rectangle, + non_exclusive_zone: Rectangle, seat: Option<&Seat>, alpha: f32, transition: f32, @@ -3891,7 +3893,7 @@ fn geometries_for_groupview<'a, R>( swap_desc: Option, swap_tree: Option<&Tree>, ) -> ( - HashMap>, + HashMap>, Vec>, ) where @@ -3921,7 +3923,7 @@ where } let mut elements = Vec::new(); - let mut geometries: HashMap> = HashMap::new(); + let mut geometries: HashMap> = HashMap::new(); let alpha = alpha * transition; let focused = seat @@ -4268,7 +4270,7 @@ where ); } let swap_geo = swap_geometry( - geo.size, + geo.size.as_logical(), focused_geo.unwrap_or({ let mut geo = non_exclusive_zone; geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into(); @@ -4469,7 +4471,7 @@ where if matches!(swap_desc, Some(ref desc) if &desc.node == &node_id && desc.stack_window.is_none()) { let swap_geo = swap_geometry( - geo.size, + geo.size.as_logical(), focused_geo.unwrap_or({ let mut geo = non_exclusive_zone; geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into(); @@ -4523,7 +4525,7 @@ fn render_old_tree( reference_tree: &Tree, target_tree: &Tree, renderer: &mut R, - geometries: Option>>, + geometries: Option>>, output_scale: f64, percentage: f32, is_swap_mode: bool, @@ -4585,7 +4587,10 @@ where .unwrap_or(*original_geo); let crop_rect = geo.clone(); - let original_location = original_geo.loc.to_physical_precise_round(output_scale) + let original_location = original_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale) - mapped .geometry() .loc @@ -4605,7 +4610,9 @@ where let cropped = CropRenderElement::from_element( elem, output_scale, - crop_rect.to_physical_precise_round(output_scale), + crop_rect + .as_logical() + .to_physical_precise_round(output_scale), )?; let rescaled = RescaleRenderElement::from_element( cropped, @@ -4615,6 +4622,7 @@ where let relocated = RelocateRenderElement::from_element( rescaled, (geo.loc - original_geo.loc) + .as_logical() .to_physical_precise_round(output_scale), Relocate::Relative, ); @@ -4626,7 +4634,9 @@ where let cropped = CropRenderElement::from_element( elem, output_scale, - crop_rect.to_physical_precise_round(output_scale), + crop_rect + .as_logical() + .to_physical_precise_round(output_scale), )?; let rescaled = RescaleRenderElement::from_element( cropped, @@ -4636,6 +4646,7 @@ where let relocated = RelocateRenderElement::from_element( rescaled, (geo.loc - original_geo.loc) + .as_logical() .to_physical_precise_round(output_scale), Relocate::Relative, ); @@ -4655,9 +4666,9 @@ fn render_new_tree( target_tree: &Tree, reference_tree: Option<&Tree>, renderer: &mut R, - non_exclusive_zone: Rectangle, - geometries: Option>>, - old_geometries: Option>>, + non_exclusive_zone: Rectangle, + geometries: Option>>, + old_geometries: Option>>, is_overview: bool, seat: Option<&Seat>, output: &Output, @@ -4685,13 +4696,7 @@ where seat.get_keyboard() .unwrap() .current_focus() - .and_then(|target| { - TilingLayout::currently_focused_node( - &target_tree, - &seat.active_output(), - target, - ) - }) + .and_then(|target| TilingLayout::currently_focused_node(&target_tree, target)) }) .map(|(id, _)| id); let focused_geo = if let Some(focused) = focused.as_ref() { @@ -4778,7 +4783,8 @@ where transition.unwrap_or(1.0), )); - let render_loc = (swap_geo.loc - window_geo.loc).to_physical_precise_round(output_scale); + let render_loc = + (swap_geo.loc.as_logical() - window_geo.loc).to_physical_precise_round(output_scale); swap_elements.extend( window @@ -4792,7 +4798,10 @@ where .map(|window| { CosmicMappedRenderElement::GrabbedWindow(RescaleRenderElement::from_element( window, - swap_geo.loc.to_physical_precise_round(output_scale), + swap_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale), ease( Linear, 1.0, @@ -4985,12 +4994,12 @@ where .unwrap_or(false)) { if let Some(swap) = swap_indicator.as_ref() { - swap.resize(geo.size); - swap.output_enter(output, output_geo); + swap.resize(geo.size.as_logical()); + swap.output_enter(output, output_geo.as_logical()); swap_elements.extend( swap.render_elements::>( renderer, - geo.loc.to_physical_precise_round(output_scale), + geo.loc.as_logical().to_physical_precise_round(output_scale), output_scale.into(), alpha * overview.0.alpha().unwrap_or(1.0), ) @@ -5006,8 +5015,8 @@ where geo.loc -= (18, 18).into(); geo.size += (36, 36).into(); - resize.resize(geo.size); - resize.output_enter(output, output_geo); + resize.resize(geo.size.as_logical()); + resize.output_enter(output, output_geo.as_logical()); let possible_edges = TilingLayout::possible_resizes(target_tree, node_id.clone()); if !possible_edges.is_empty() { @@ -5026,7 +5035,7 @@ where resize .render_elements::>( renderer, - geo.loc.to_physical_precise_round(output_scale), + geo.loc.as_logical().to_physical_precise_round(output_scale), output_scale.into(), alpha * mode.alpha().unwrap_or(1.0), ) @@ -5039,7 +5048,7 @@ where } if let Data::Mapped { mapped, .. } = data { - let original_location = (original_geo.loc - mapped.geometry().loc) + let original_location = (original_geo.loc.as_logical() - mapped.geometry().loc) .to_physical_precise_round(output_scale); let (mut w_elements, p_elements) = mapped @@ -5069,7 +5078,7 @@ where }) .unwrap_or(false) { - let mut geo = mapped.active_window_geometry(); + let mut geo = mapped.active_window_geometry().as_local(); geo.loc += original_geo.loc; w_elements.insert( 0, @@ -5090,16 +5099,22 @@ where let cropped = CropRenderElement::from_element( elem, output_scale, - crop_rect.to_physical_precise_round(output_scale), + crop_rect + .as_logical() + .to_physical_precise_round(output_scale), )?; let rescaled = RescaleRenderElement::from_element( cropped, - original_geo.loc.to_physical_precise_round(output_scale), + original_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale), scale, ); let relocated = RelocateRenderElement::from_element( rescaled, (geo.loc - original_geo.loc) + .as_logical() .to_physical_precise_round(output_scale), Relocate::Relative, ); @@ -5111,16 +5126,22 @@ where let cropped = CropRenderElement::from_element( elem, output_scale, - crop_rect.to_physical_precise_round(output_scale), + crop_rect + .as_logical() + .to_physical_precise_round(output_scale), )?; let rescaled = RescaleRenderElement::from_element( cropped, - original_geo.loc.to_physical_precise_round(output_scale), + original_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale), scale, ); let relocated = RelocateRenderElement::from_element( rescaled, (geo.loc - original_geo.loc) + .as_logical() .to_physical_precise_round(output_scale), Relocate::Relative, ); @@ -5132,16 +5153,22 @@ where let cropped = CropRenderElement::from_element( elem, output_scale, - crop_rect.to_physical_precise_round(output_scale), + crop_rect + .as_logical() + .to_physical_precise_round(output_scale), )?; let rescaled = RescaleRenderElement::from_element( cropped, - original_geo.loc.to_physical_precise_round(output_scale), + original_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale), scale, ); let relocated = RelocateRenderElement::from_element( rescaled, (geo.loc - original_geo.loc) + .as_logical() .to_physical_precise_round(output_scale), Relocate::Relative, ); @@ -5187,10 +5214,10 @@ where (window_elements, popup_elements) } -fn scale_to_center( - old_geo: &Rectangle, - new_geo: &Rectangle, -) -> (f64, Point) { +fn scale_to_center( + old_geo: &Rectangle, + new_geo: &Rectangle, +) -> (f64, Point) { let scale_w = new_geo.size.w as f64 / old_geo.size.w as f64; let scale_h = new_geo.size.h as f64 / old_geo.size.h as f64; diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 3640353f..e4a8263d 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1073,7 +1073,10 @@ impl Shell { .filter(|o| { self.override_redirect_windows.iter().any(|or| { if or.wl_surface().as_ref() == Some(surface) { - or.geometry().intersection(o.geometry()).is_some() + or.geometry() + .as_global() + .intersection(o.geometry()) + .is_some() } else { false } @@ -1393,13 +1396,12 @@ impl Shell { pub fn map_override_redirect(state: &mut State, window: X11Surface) { let geo = window.geometry(); - for (output, overlap) in state - .common - .shell - .outputs() - .cloned() - .filter_map(|o| o.geometry().intersection(geo).map(|overlap| (o, overlap))) - { + for (output, overlap) in state.common.shell.outputs().cloned().filter_map(|o| { + o.geometry() + .as_logical() + .intersection(geo) + .map(|overlap| (o, overlap)) + }) { window.output_enter(&output, overlap); } @@ -1444,7 +1446,7 @@ impl Shell { to: (&Output, Option), follow: bool, direction: Option, - ) -> Result>, InvalidWorkspaceIndex> { + ) -> Result>, InvalidWorkspaceIndex> { let (to_output, to_idx) = to; let to_idx = to_idx.unwrap_or(state.common.shell.workspaces.active_num(to_output).1); if state @@ -1578,14 +1580,18 @@ impl Shell { pub fn update_reactive_popups(&self, mapped: &CosmicMapped) { if let Some(workspace) = self.space_for(mapped) { - let element_loc = workspace.element_geometry(mapped).unwrap().loc; + let element_loc = workspace + .element_geometry(mapped) + .unwrap() + .loc + .to_global(&workspace.output); for (toplevel, offset) in mapped.windows() { if let CosmicSurface::Wayland(toplevel) = toplevel { - let window_geo_offset = toplevel.geometry().loc; + let window_geo_offset = toplevel.geometry().loc.as_global(); update_reactive_popups( &toplevel, - element_loc + offset + window_geo_offset, - self.outputs.iter(), + element_loc + offset.as_global() + window_geo_offset, + self.outputs(), ); } } diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 39486bae..369f1a4b 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -935,20 +935,28 @@ impl Workspace { let mut window_elements = Vec::new(); let mut popup_elements = Vec::new(); - let output_scale = output.current_scale().fractional_scale(); - let layer_map = layer_map_for_output(output); - let zone = layer_map.non_exclusive_zone(); + let output_scale = self.output.current_scale().fractional_scale(); + let zone = { + let layer_map = layer_map_for_output(&self.output); + layer_map.non_exclusive_zone().as_local() + }; // OR windows above all popup_elements.extend( override_redirect_windows .iter() - .filter(|or| (*or).geometry().intersection(output.geometry()).is_some()) + .filter(|or| { + (*or) + .geometry() + .as_global() + .intersection(self.output.geometry()) + .is_some() + }) .flat_map(|or| { AsRenderElements::::render_elements::>( or, renderer, - (or.geometry().loc - output.geometry().loc) + (or.geometry().loc - self.output.geometry().loc.as_logical()) .to_physical_precise_round(output_scale), Scale::from(output_scale), 1.0, @@ -1027,7 +1035,10 @@ impl Workspace { (None, None) => (full_geo, 1.0), }; - let render_loc = target_geo.loc.to_physical_precise_round(output_scale); + let render_loc = target_geo + .loc + .as_logical() + .to_physical_precise_round(output_scale); let scale = Scale { x: target_geo.size.w as f64 / bbox.size.w as f64, y: target_geo.size.h as f64 / bbox.size.h as f64, diff --git a/src/utils/geometry.rs b/src/utils/geometry.rs new file mode 100644 index 00000000..19e6f6ed --- /dev/null +++ b/src/utils/geometry.rs @@ -0,0 +1,149 @@ +use smithay::{ + output::Output, + utils::{Coordinate, Logical, Point, Rectangle, Size}, +}; + +use super::prelude::OutputExt; + +/// Marker type for coordinates in global space +#[derive(Debug)] +pub struct Global; + +/// Marker type for coordinates in workspace local space +#[derive(Debug)] +pub struct Local; + +pub trait PointExt { + fn as_global(self) -> Point; + fn as_local(self) -> Point; +} + +pub trait PointGlobalExt { + fn to_local(self, output: &Output) -> Point; + fn as_logical(self) -> Point; +} + +pub trait PointLocalExt { + fn to_global(self, output: &Output) -> Point; + fn as_logical(self) -> Point; +} + +pub trait SizeExt { + fn as_logical(self) -> Size; + fn as_local(self) -> Size; + fn as_global(self) -> Size; +} + +pub trait RectExt { + fn as_global(self) -> Rectangle; + fn as_local(self) -> Rectangle; +} + +pub trait RectGlobalExt { + fn to_local(self, output: &Output) -> Rectangle; + fn as_logical(self) -> Rectangle; +} + +pub trait RectLocalExt { + fn to_global(self, output: &Output) -> Rectangle; + fn as_logical(self) -> Rectangle; +} + +impl PointExt for Point { + fn as_global(self) -> Point { + (self.x, self.y).into() + } + + fn as_local(self) -> Point { + (self.x, self.y).into() + } +} + +impl PointGlobalExt for Point { + fn to_local(self, output: &Output) -> Point { + let point = (self.to_f64() - output.geometry().loc.to_f64()).as_logical(); + (C::from_f64(point.x), C::from_f64(point.y)).into() + } + + fn as_logical(self) -> Point { + (self.x, self.y).into() + } +} + +impl PointLocalExt for Point { + fn to_global(self, output: &Output) -> Point { + let point = + (self.to_f64().as_logical() + output.geometry().loc.to_f64().as_logical()).as_global(); + (C::from_f64(point.x), C::from_f64(point.y)).into() + } + + fn as_logical(self) -> Point { + (self.x, self.y).into() + } +} + +impl SizeExt for Size { + fn as_logical(self) -> Size { + (self.w, self.h).into() + } + fn as_global(self) -> Size { + self + } + fn as_local(self) -> Size { + (self.w, self.h).into() + } +} + +impl SizeExt for Size { + fn as_logical(self) -> Size { + (self.w, self.h).into() + } + fn as_global(self) -> Size { + (self.w, self.h).into() + } + fn as_local(self) -> Size { + self + } +} + +impl SizeExt for Size { + fn as_logical(self) -> Size { + self + } + fn as_global(self) -> Size { + (self.w, self.h).into() + } + fn as_local(self) -> Size { + (self.w, self.h).into() + } +} + +impl RectExt for Rectangle { + fn as_global(self) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.as_global(), (self.size.w, self.size.h)) + } + + fn as_local(self) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.as_local(), (self.size.w, self.size.h)) + } +} + +impl RectGlobalExt for Rectangle { + fn to_local(self, output: &Output) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.to_local(output), (self.size.w, self.size.h)) + } + + fn as_logical(self) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.as_logical(), self.size.as_logical()) + } +} + +impl RectLocalExt for Rectangle { + fn to_global(self, output: &Output) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.to_global(output), (self.size.w, self.size.h)) + } + + fn as_logical(self) -> Rectangle { + Rectangle::from_loc_and_size(self.loc.as_logical(), self.size.as_logical()) + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index ff39a61d..6531f067 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,6 +2,7 @@ mod ids; pub(crate) use self::ids::id_gen; +pub mod geometry; pub mod iced; pub mod prelude; pub mod tween; diff --git a/src/utils/prelude.rs b/src/utils/prelude.rs index d5e8f42b..bbedcba4 100644 --- a/src/utils/prelude.rs +++ b/src/utils/prelude.rs @@ -11,20 +11,21 @@ use smithay::{ Seat, }, output::Output, - utils::{Buffer, IsAlive, Logical, Monotonic, Point, Rectangle, Time, Transform}, + utils::{Buffer, IsAlive, Monotonic, Point, Rectangle, Time, Transform}, wayland::compositor::with_states, }; +pub use super::geometry::*; pub use crate::shell::{Shell, Workspace}; pub use crate::state::{Common, State}; pub use crate::wayland::handlers::xdg_shell::popup::update_reactive_popups; pub trait OutputExt { - fn geometry(&self) -> Rectangle; + fn geometry(&self) -> Rectangle; } impl OutputExt for Output { - fn geometry(&self) -> Rectangle { + fn geometry(&self) -> Rectangle { Rectangle::from_loc_and_size(self.current_location(), { Transform::from(self.current_transform()) .transform_size( @@ -36,6 +37,7 @@ impl OutputExt for Output { .to_logical(self.current_scale().fractional_scale()) .to_i32_round() }) + .as_global() } } diff --git a/src/wayland/handlers/screencopy.rs b/src/wayland/handlers/screencopy.rs index dd775448..f8a8cfdb 100644 --- a/src/wayland/handlers/screencopy.rs +++ b/src/wayland/handlers/screencopy.rs @@ -47,7 +47,7 @@ use crate::{ }, shell::{CosmicMappedRenderElement, CosmicSurface, WorkspaceRenderElement}, state::{BackendData, ClientState, Common, State}, - utils::prelude::OutputExt, + utils::prelude::{OutputExt, PointExt}, wayland::protocols::{ screencopy::{ delegate_screencopy, BufferInfo, BufferParams, CursorMode as ScreencopyCursorMode, @@ -106,7 +106,7 @@ impl ScreencopyHandler for State { if let Some(pointer) = seat.get_pointer() { if output .geometry() - .contains(pointer.current_location().to_i32_round()) + .contains(pointer.current_location().to_i32_round().as_global()) { session.cursor_enter(seat, InputType::Pointer); } diff --git a/src/wayland/handlers/xdg_shell/popup.rs b/src/wayland/handlers/xdg_shell/popup.rs index 99842a3a..225968f7 100644 --- a/src/wayland/handlers/xdg_shell/popup.rs +++ b/src/wayland/handlers/xdg_shell/popup.rs @@ -27,27 +27,28 @@ use std::sync::Mutex; use tracing::{trace, warn}; impl Shell { - pub fn unconstrain_popup(&self, surface: &PopupSurface, positioner: &PositionerState) { + pub fn unconstrain_popup(&self, surface: &PopupSurface) { if let Some(parent) = get_popup_toplevel(&surface) { if let Some(elem) = self.element_for_wl_surface(&parent) { let workspace = self.space_for(elem).unwrap(); - let mut element_geo = workspace.element_geometry(elem).unwrap(); + let mut element_geo = workspace + .element_geometry(elem) + .unwrap() + .to_global(workspace.output()); let (window, offset) = elem .windows() .find(|(w, _)| w.wl_surface().as_ref() == Some(&parent)) .unwrap(); let window_geo_offset = window.geometry().loc; - let window_loc = element_geo.loc + offset + window_geo_offset; - let anchor_point = get_anchor_point(&positioner) + window_loc; + let window_loc: Point = + element_geo.loc + offset.as_global() + window_geo_offset.as_global(); if workspace.is_tiled(elem) { - element_geo.loc = (0, 0).into(); //-= window_loc; - if !unconstrain_xdg_popup_tile(surface, element_geo) { - if let Some(output) = workspace.output_under(anchor_point) { - unconstrain_xdg_popup(surface, window_loc, output.geometry()); - } + element_geo.loc = (0, 0).into(); + if !unconstrain_xdg_popup_tile(surface, element_geo.as_logical()) { + unconstrain_xdg_popup(surface, window_loc, workspace.output().geometry()); } - } else if let Some(output) = workspace.output_under(anchor_point) { - unconstrain_xdg_popup(surface, window_loc, output.geometry()); + } else { + unconstrain_xdg_popup(surface, window_loc, workspace.output().geometry()); } } else if let Some((output, layer_surface)) = self.outputs().find_map(|o| { let map = layer_map_for_output(o); @@ -62,7 +63,7 @@ impl Shell { pub fn update_reactive_popups<'a>( window: &Window, - loc: Point, + loc: Point, outputs: impl Iterator, ) { let output_geo = outputs.map(|o| o.geometry()).collect::>(); @@ -79,7 +80,7 @@ pub fn update_reactive_popups<'a>( attributes.current.positioner.clone() }); if positioner.reactive { - let anchor_point = get_anchor_point(&positioner) + loc; + let anchor_point = loc + get_anchor_point(&positioner).as_global(); if let Some(rect) = output_geo .iter() .find(|geo| geo.contains(anchor_point)) @@ -116,11 +117,11 @@ fn unconstrain_xdg_popup_tile(surface: &PopupSurface, rect: Rectangle, - rect: Rectangle, + window_loc: Point, + mut rect: Rectangle, ) { - let mut relative = rect; - relative.loc -= window_loc; + rect.loc -= window_loc; + let relative = rect.as_logical(); let geometry = surface.with_pending_state(|state| state.positioner.get_geometry()); let offset = check_constrained(geometry, relative); @@ -139,7 +140,7 @@ fn unconstrain_layer_popup(surface: &PopupSurface, output: &Output, layer_surfac let layer_geo = map.layer_geometry(layer_surface).unwrap(); // the output_rect represented relative to the parents coordinate system - let mut relative = Rectangle::from_loc_and_size((0, 0), output.geometry().size); + let mut relative = Rectangle::from_loc_and_size((0, 0), output.geometry().size).as_logical(); relative.loc -= layer_geo.loc; let geometry = surface.with_pending_state(|state| state.positioner.get_geometry()); let offset = check_constrained(geometry, relative); diff --git a/src/xwayland.rs b/src/xwayland.rs index 541c2960..b5dce66b 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -277,13 +277,16 @@ impl XwmHandler for State { { let space = self.common.shell.space_for(mapped).unwrap(); if space.is_floating(mapped) { - mapped.set_geometry(Rectangle::from_loc_and_size( - current_geo.loc, - ( - w.map(|w| w as i32).unwrap_or(current_geo.size.w), - h.map(|h| h as i32).unwrap_or(current_geo.size.h), - ), - )) + mapped.set_geometry( + Rectangle::from_loc_and_size( + current_geo.loc, + ( + w.map(|w| w as i32).unwrap_or(current_geo.size.w), + h.map(|h| h as i32).unwrap_or(current_geo.size.h), + ), + ) + .as_global(), + ) } } else { if let Some(x) = x { @@ -325,13 +328,13 @@ impl XwmHandler for State { } } - let geo = window.geometry(); + let geo = window.geometry().as_global(); for (output, overlap) in self.common.shell.outputs().cloned().map(|o| { let intersection = o.geometry().intersection(geo); (o, intersection) }) { if let Some(overlap) = overlap { - window.output_enter(&output, overlap); + window.output_enter(&output, overlap.as_logical()); } else { window.output_leave(&output); }