From 57ea51fb40bdcfedcce9706f2c4f419c646f5703 Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 2 Jan 2023 18:53:58 -0500 Subject: [PATCH] feat(wayland): recommended_state --- src/wayland/panel_item.rs | 22 ++++++++++++++-- src/wayland/xdg_shell.rs | 53 +++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index 1adc75b..b10a658 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -58,7 +58,7 @@ lazy_static! { "close", ], aliased_local_methods: vec![], - aliased_remote_signals: vec!["commit_toplevel", "set_cursor",], + aliased_remote_signals: vec!["commit_toplevel", "recommend_toplevel_state", "set_cursor"], ui: Default::default(), items: Registry::new(), acceptors: Registry::new(), @@ -96,6 +96,16 @@ impl Default for ToplevelState { } } +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "type", content = "content")] +pub enum RecommendedState { + Maximize(bool), + Fullscreen(bool), + Minimize, + Move, + Resize(u32), +} + pub struct PanelItem { node: Weak, client_credentials: Option, @@ -498,7 +508,7 @@ impl PanelItem { let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; let Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) }; - #[derive(Deserialize)] + #[derive(Debug, Deserialize)] struct ConfigureToplevelInfo { size: Option>, states: Vec, @@ -547,6 +557,14 @@ impl PanelItem { let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap()); } + pub fn recommend_toplevel_state(&self, state: RecommendedState) { + let Some(node) = self.node.upgrade() else { return }; + dbg!(&state); + let data = serialize(state).unwrap(); + + let _ = node.send_remote_signal("recommend_toplevel_state", &data); + } + pub fn set_cursor(&self, surface: Option<&WlSurface>, hotspot_x: i32, hotspot_y: i32) { let Some(node) = self.node.upgrade() else { return }; let mut data = serialize(()).unwrap(); diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 38f1d2f..2f7e688 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use super::{ - panel_item::{PanelItem, ToplevelState}, + panel_item::{PanelItem, RecommendedState, ToplevelState}, state::WaylandState, }; use mint::Vector2; @@ -280,6 +280,14 @@ pub struct XdgToplevelData { pub state: Arc>, pub xdg_surface_data: XdgSurfaceData, } +impl XdgToplevelData { + fn panel_item(&self) -> Option> { + let wl_surface = self.xdg_surface_data.wl_surface.upgrade().ok()?; + compositor::with_states(&wl_surface, |data| { + data.data_map.get::>().cloned() + }) + } +} impl Dispatch for WaylandState { fn request( _state: &mut WaylandState, @@ -312,12 +320,19 @@ impl Dispatch for WaylandState { x: _, y: _, } => (), - xdg_toplevel::Request::Move { seat: _, serial: _ } => (), + xdg_toplevel::Request::Move { seat: _, serial: _ } => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Move); + } xdg_toplevel::Request::Resize { seat: _, serial: _, - edges: _, - } => (), + edges, + } => { + let WEnum::Value(edges) = edges else { return }; + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Resize(edges as u32)); + } xdg_toplevel::Request::SetMaxSize { width, height } => { let mut state = data.state.lock(); let queued_state = state.queued_state.as_mut().unwrap(); @@ -330,16 +345,28 @@ impl Dispatch for WaylandState { queued_state.min_size = (width > 1 || height > 1) .then_some(Vector2::from([width as u32, height as u32])); } - xdg_toplevel::Request::SetMaximized => (), - xdg_toplevel::Request::UnsetMaximized => (), - xdg_toplevel::Request::SetFullscreen { output: _ } => (), - xdg_toplevel::Request::UnsetFullscreen => (), - xdg_toplevel::Request::SetMinimized => (), + xdg_toplevel::Request::SetMaximized => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Maximize(true)); + } + xdg_toplevel::Request::UnsetMaximized => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Maximize(false)); + } + xdg_toplevel::Request::SetFullscreen { output: _ } => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true)); + } + xdg_toplevel::Request::UnsetFullscreen => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true)); + } + xdg_toplevel::Request::SetMinimized => { + let Some(panel_item) = data.panel_item() else { return }; + panel_item.recommend_toplevel_state(RecommendedState::Minimize); + } xdg_toplevel::Request::Destroy => { - let Ok(wl_surface) = data.xdg_surface_data.wl_surface.upgrade() else { return }; - let Some(panel_item) = compositor::with_states(&wl_surface, |data| { - data.data_map.get::>().cloned() - }) else { return }; + let Some(panel_item) = data.panel_item() else { return }; panel_item.on_drop(); } _ => unreachable!(),