From e8c64f46d9a8e79afb13874813fa6a739025d28c Mon Sep 17 00:00:00 2001 From: MaxVerevkin Date: Tue, 31 Jan 2023 23:39:16 +0200 Subject: abstract over tag and layout name provider --- src/wm_info_provider/river.rs | 164 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/wm_info_provider/river.rs (limited to 'src/wm_info_provider') diff --git a/src/wm_info_provider/river.rs b/src/wm_info_provider/river.rs new file mode 100644 index 0000000..dc42d71 --- /dev/null +++ b/src/wm_info_provider/river.rs @@ -0,0 +1,164 @@ +use std::any::Any; +use std::ffi::CString; + +use wayrs_client::connection::Connection; +use wayrs_client::global::*; + +use super::*; +use crate::protocol::*; +use crate::state::State; + +pub(super) struct RiverInfoProvider { + status_manager: ZriverStatusManagerV1, + control: ZriverControlV1, + output_statuses: Vec, + callback: WmInfoCallback, +} + +struct OutputStatus { + output: WlOutput, + status: ZriverOutputStatusV1, + focused_tags: u32, + urgent_tags: u32, + active_tags: u32, + layout_name: Option, +} + +impl RiverInfoProvider { + pub(super) fn bind( + conn: &mut Connection, + globals: &Globals, + callback: WmInfoCallback, + ) -> Option { + Some(Self { + status_manager: globals.bind(conn, 1..=4).ok()?, + control: globals.bind(conn, 1..=1).ok()?, + output_statuses: Vec::new(), + callback, + }) + } +} + +impl WmInfoProvider for RiverInfoProvider { + fn as_any(&mut self) -> &mut dyn Any { + self + } + + fn new_outut(&mut self, conn: &mut Connection, output: WlOutput) { + let status = + self.status_manager + .get_river_output_status_with_cb(conn, output, output_status_cb); + self.output_statuses.push(OutputStatus { + output, + status, + focused_tags: 0, + urgent_tags: 0, + active_tags: 0, + layout_name: None, + }); + } + + fn output_removed(&mut self, conn: &mut Connection, output: WlOutput) { + let index = self + .output_statuses + .iter() + .position(|s| s.output == output) + .unwrap(); + let output_status = self.output_statuses.swap_remove(index); + output_status.status.destroy(conn); + } + + fn left_click_on_tag( + &mut self, + conn: &mut Connection, + _: WlOutput, + seat: WlSeat, + tag: &str, + ) { + let tag: u32 = tag.parse().unwrap(); + self.control + .add_argument(conn, CString::new("set-focused-tags").unwrap()); + self.control + .add_argument(conn, CString::new((1u32 << (tag - 1)).to_string()).unwrap()); + self.control + .run_command_with_cb(conn, seat, river_command_cb); + } + + fn middle_click_on_tag( + &mut self, + conn: &mut Connection, + _: WlOutput, + seat: WlSeat, + tag: &str, + ) { + let tag: u32 = tag.parse().unwrap(); + self.control + .add_argument(conn, CString::new("toggle-focused-tags").unwrap()); + self.control + .add_argument(conn, CString::new((1u32 << (tag - 1)).to_string()).unwrap()); + self.control + .run_command_with_cb(conn, seat, river_command_cb); + } +} + +fn output_status_cb( + conn: &mut Connection, + state: &mut State, + output_status: ZriverOutputStatusV1, + event: zriver_output_status_v1::Event, +) { + let river: &mut RiverInfoProvider = state + .shared_state + .wm_info_provider + .as_mut() + .unwrap() + .as_any() + .downcast_mut() + .unwrap(); + + let status = river + .output_statuses + .iter_mut() + .find(|s| s.status == output_status) + .unwrap(); + + use zriver_output_status_v1::Event; + match event { + Event::FocusedTags(tags) => status.focused_tags = tags, + Event::ViewTags(tags) => { + status.active_tags = tags + .chunks_exact(4) + .map(|bytes| u32::from_ne_bytes(bytes.try_into().unwrap())) + .fold(0, |a, b| a | b); + } + Event::UrgentTags(tags) => status.urgent_tags = tags, + Event::LayoutName(ln) => status.layout_name = Some(ln.to_string_lossy().into()), + Event::LayoutNameClear => status.layout_name = None, + } + + let info = WmInfo { + layout_name: status.layout_name.clone(), + tags: (1..10) + .map(|tag| Tag { + name: tag.to_string(), + is_focused: status.focused_tags & (1 << (tag - 1)) != 0, + is_active: status.active_tags & (1 << (tag - 1)) != 0, + is_urgent: status.urgent_tags & (1 << (tag - 1)) != 0, + }) + .collect(), + }; + + let output = status.output; + (river.callback)(conn, state, output, info); +} + +fn river_command_cb( + conn: &mut Connection, + state: &mut State, + _: ZriverCommandCallbackV1, + event: zriver_command_callback_v1::Event, +) { + if let zriver_command_callback_v1::Event::Failure(msg) = event { + state.set_error(conn, msg.to_string_lossy()) + } +} -- cgit v1.3.1