feat(displays): pan left and right when dragging displays to edge
This commit is contained in:
parent
48fedb6e75
commit
e8106a975e
3 changed files with 66 additions and 14 deletions
14
Cargo.toml
14
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"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ const UNIT_PIXELS: f32 = 12.0;
|
|||
pub type OnPlacementFunc<Message> = Box<dyn Fn(OutputKey, i32, i32) -> Message>;
|
||||
pub type OnSelectFunc<Message> = Box<dyn Fn(segmented_button::Entity) -> 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<Box<dyn Fn(Pan) -> Message>>,
|
||||
#[setters(skip)]
|
||||
on_placement: Option<OnPlacementFunc<Message>>,
|
||||
#[setters(skip)]
|
||||
on_select: Option<OnSelectFunc<Message>>,
|
||||
|
|
@ -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<Message, cosmic::Theme, Renderer> 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>();
|
||||
state.max_dimensions = (
|
||||
|
|
@ -146,16 +160,25 @@ impl<'a, Message: Clone> Widget<Message, cosmic::Theme, Renderer> 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::<State>();
|
||||
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::<State>();
|
||||
|
||||
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<Message, cosmic::Theme, Renderer> 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;
|
||||
|
|
|
|||
|
|
@ -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<std::io::Result<ExitStatus>>),
|
||||
/// Request to reload the page.
|
||||
|
|
@ -123,6 +125,8 @@ pub struct Page {
|
|||
cache: ViewCache,
|
||||
// context: Option<ContextDrawer>,
|
||||
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<Randr>,
|
||||
/// 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<crate::pages::Message> {
|
|||
.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))
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue