From e8106a975e5ca1a8d71fd3b341934b828818ddf9 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Thu, 18 Jul 2024 11:43:31 +0200 Subject: [PATCH] feat(displays): pan left and right when dragging displays to edge --- Cargo.toml | 14 +++--- .../src/pages/display/arrangement.rs | 44 +++++++++++++++---- cosmic-settings/src/pages/display/mod.rs | 22 ++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1fb9eb6..a62b96b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,15 @@ tokio = { version = "1.37.0", features = ["macros"] } [workspace.dependencies.libcosmic] git = "https://github.com/pop-os/libcosmic" -features = ["dbus-config", "single-instance", "multi-window", "tokio", "wayland", "wgpu", "xdg-portal"] +features = [ + "dbus-config", + "single-instance", + "multi-window", + "tokio", + "wayland", + "wgpu", + "xdg-portal", +] [workspace.dependencies.cosmic-config] git = "https://github.com/pop-os/libcosmic" @@ -35,10 +43,6 @@ git = "https://github.com/smithay/client-toolkit/" package = "smithay-client-toolkit" rev = "3bed072" -[profile.dev] -opt-level = 2 -lto = false - [profile.release] opt-level = 3 lto = "thin" diff --git a/cosmic-settings/src/pages/display/arrangement.rs b/cosmic-settings/src/pages/display/arrangement.rs index d2d04fa..99778a7 100644 --- a/cosmic-settings/src/pages/display/arrangement.rs +++ b/cosmic-settings/src/pages/display/arrangement.rs @@ -19,6 +19,12 @@ const UNIT_PIXELS: f32 = 12.0; pub type OnPlacementFunc = Box Message>; pub type OnSelectFunc = Box Message>; +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Pan { + Left, + Right, +} + #[must_use] #[derive(derive_setters::Setters)] pub struct Arrangement<'a, Message> { @@ -27,6 +33,8 @@ pub struct Arrangement<'a, Message> { #[setters(skip)] tab_model: &'a SingleSelectModel, #[setters(skip)] + on_pan: Option Message>>, + #[setters(skip)] on_placement: Option>, #[setters(skip)] on_select: Option>, @@ -39,6 +47,7 @@ impl<'a, Message> Arrangement<'a, Message> { Self { list, tab_model, + on_pan: None, on_placement: None, on_select: None, width: Length::Shrink, @@ -46,6 +55,11 @@ impl<'a, Message> Arrangement<'a, Message> { } } + pub fn on_pan(mut self, on_pan: impl Fn(Pan) -> Message + 'static) -> Self { + self.on_pan = Some(Box::new(on_pan)); + self + } + pub fn on_placement( mut self, on_placement: impl Fn(OutputKey, i32, i32) -> Message + 'static, @@ -119,8 +133,8 @@ impl<'a, Message: Clone> Widget for Arrangemen display_area.1 = display_area.1.max(height as i32 + output.position.1); } - let width = (max_dimensions.0 as i32 * 2 + display_area.0) as f32 / UNIT_PIXELS; - let height = (max_dimensions.1 as i32 * 2 + display_area.1) as f32 / UNIT_PIXELS; + let width = ((max_dimensions.0 as f32 * 2.0) as i32 + display_area.0) as f32 / UNIT_PIXELS; + let height = ((max_dimensions.1 as f32 * 2.0) as i32 + display_area.1) as f32 / UNIT_PIXELS; let state = tree.state.downcast_mut::(); state.max_dimensions = ( @@ -146,16 +160,25 @@ impl<'a, Message: Clone> Widget for Arrangemen _renderer: &Renderer, _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, - _viewport: &Rectangle, + viewport: &Rectangle, ) -> event::Status { let bounds = layout.bounds(); match event { - core::Event::Mouse(mouse::Event::CursorMoved { .. }) - | core::Event::Touch(touch::Event::FingerMoved { .. }) => { - if let Some(position) = cursor.position() { - let state = tree.state.downcast_mut::(); - if let Some((output_key, region)) = state.dragging.as_mut() { + core::Event::Mouse(mouse::Event::CursorMoved { position, .. }) + | core::Event::Touch(touch::Event::FingerMoved { position, .. }) => { + let state = tree.state.downcast_mut::(); + + if let Some((output_key, region)) = state.dragging.as_mut() { + if let Some(ref mut on_pan) = self.on_pan { + if bounds.x + viewport.width - 150.0 < position.x { + shell.publish(on_pan(Pan::Right)); + } else if bounds.x + 150.0 > position.x { + shell.publish(on_pan(Pan::Left)); + } + } + + if let Some(inner_position) = cursor.position() { update_dragged_region( self.tab_model, self.list, @@ -163,7 +186,10 @@ impl<'a, Message: Clone> Widget for Arrangemen *output_key, region, state.max_dimensions, - (position.x - state.offset.0, position.y - state.offset.1), + ( + inner_position.x - state.offset.0, + inner_position.y - state.offset.1, + ), ); return event::Status::Captured; diff --git a/cosmic-settings/src/pages/display/mod.rs b/cosmic-settings/src/pages/display/mod.rs index de2621e..05eed5a 100644 --- a/cosmic-settings/src/pages/display/mod.rs +++ b/cosmic-settings/src/pages/display/mod.rs @@ -76,6 +76,8 @@ pub enum Message { // NightLightContext, /// Set the orientation of a display. Orientation(Transform), + /// Pan the displays view + Pan(arrangement::Pan), /// Status of an applied display change. RandrResult(Arc>), /// Request to reload the page. @@ -123,6 +125,8 @@ pub struct Page { cache: ViewCache, // context: Option, display_arrangement_scrollable: widget::Id, + /// Tracks the last pan status. + last_pan: f32, /// The setting to revert to if the next dialog page is cancelled. dialog: Option, /// the instant the setting was changed. @@ -143,6 +147,7 @@ impl Default for Page { cache: ViewCache::default(), // context: None, display_arrangement_scrollable: widget::Id::unique(), + last_pan: 0.5, dialog: None, dialog_countdown: 0, show_display_options: true, @@ -413,6 +418,21 @@ impl Page { // } Message::Orientation(orientation) => return self.set_orientation(orientation), + Message::Pan(pan) => { + match pan { + arrangement::Pan::Left => self.last_pan = 0.0f32.max(self.last_pan - 0.01), + arrangement::Pan::Right => self.last_pan = 1.0f32.min(self.last_pan + 0.01), + } + + return cosmic::iced::widget::scrollable::snap_to( + self.display_arrangement_scrollable.clone(), + RelativeOffset { + x: self.last_pan, + y: 0.0, + }, + ); + } + Message::Position(display, x, y) => return self.set_position(display, x, y), Message::Refresh => { @@ -447,6 +467,7 @@ impl Page { } } + self.last_pan = 0.5; cosmic::iced::widget::scrollable::snap_to( self.display_arrangement_scrollable.clone(), RelativeOffset { x: 0.5, y: 0.5 }, @@ -958,6 +979,7 @@ pub fn display_arrangement() -> Section { .push({ Arrangement::new(&page.list, &page.display_tabs) .on_select(|id| pages::Message::Displays(Message::Display(id))) + .on_pan(|pan| pages::Message::Displays(Message::Pan(pan))) .on_placement(|id, x, y| { pages::Message::Displays(Message::Position(id, x, y)) })