diff options
| author | MaxVerevkin <maxxverrr@gmail.com> | 2022-08-08 23:12:23 +0300 |
|---|---|---|
| committer | MaxVerevkin <maxxverrr@gmail.com> | 2022-08-08 23:59:59 +0300 |
| commit | 1851c56e407cac72ca104cc5e75692cd9c648986 (patch) | |
| tree | 31473532e01ee6ee1571974a6abf59463e3265ed /src/river_protocols | |
| parent | 9ddde2d2ee9833412e39afbd1ed907cdea22f08f (diff) | |
| download | i3bar-mango-1851c56e407cac72ca104cc5e75692cd9c648986.tar.gz | |
rewrite using latest walayd libs & implement HiDPI
Diffstat (limited to 'src/river_protocols')
| -rw-r--r-- | src/river_protocols/control.rs | 89 | ||||
| -rw-r--r-- | src/river_protocols/control/dispatch.rs | 70 | ||||
| -rw-r--r-- | src/river_protocols/status.rs | 134 | ||||
| -rw-r--r-- | src/river_protocols/status/dispatch.rs | 86 |
4 files changed, 379 insertions, 0 deletions
diff --git a/src/river_protocols/control.rs b/src/river_protocols/control.rs new file mode 100644 index 0000000..0e7d7e4 --- /dev/null +++ b/src/river_protocols/control.rs @@ -0,0 +1,89 @@ +pub mod protocol { + use smithay_client_toolkit::reexports::client as wayland_client; + use smithay_client_toolkit::reexports::client::protocol::*; + + pub mod __interfaces { + use smithay_client_toolkit::reexports::client::protocol::__interfaces::*; + wayland_scanner::generate_interfaces!("protocols/river-control-unstable-v1.xml"); + } + use self::__interfaces::*; + + wayland_scanner::generate_client_code!("protocols/river-control-unstable-v1.xml"); +} + +mod dispatch; + +use std::sync::Arc; + +use smithay_client_toolkit::globals::GlobalData; +use wayland_client::{protocol::wl_seat, Connection, Dispatch, QueueHandle}; + +use protocol::{zriver_command_callback_v1, zriver_control_v1}; + +use smithay_client_toolkit::error::GlobalError; +use smithay_client_toolkit::registry::GlobalProxy; + +#[derive(Debug, Clone)] +pub struct RiverControlState { + control: Arc<GlobalProxy<zriver_control_v1::ZriverControlV1>>, +} + +impl RiverControlState { + pub fn new() -> Self { + Self { + control: Arc::new(GlobalProxy::NotReady), + } + } + + pub fn is_available(&self) -> bool { + self.control.get().is_ok() + } + + pub fn control(&self) -> Result<&zriver_control_v1::ZriverControlV1, GlobalError> { + self.control.get() + } + + pub fn run_command<D, Args, Arg>( + &self, + qh: &QueueHandle<D>, + seat: &wl_seat::WlSeat, + args: Args, + ) -> Result<(), GlobalError> + where + D: Dispatch<zriver_control_v1::ZriverControlV1, GlobalData> + + Dispatch<zriver_command_callback_v1::ZriverCommandCallbackV1, RiverCommandCallbackData> + + 'static, + Args: IntoIterator<Item = Arg>, + Arg: Into<String>, + { + let control = self.control()?; + for arg in args { + control.add_argument(arg.into()); + } + control.run_command(seat, qh, RiverCommandCallbackData {})?; + Ok(()) + } +} + +pub trait RiverControlHandler: Sized { + fn river_control_state(&mut self) -> &mut RiverControlState; + + fn command_failure(&mut self, conn: &Connection, qh: &QueueHandle<Self>, message: String); + + fn command_success(&mut self, conn: &Connection, qh: &QueueHandle<Self>, message: String); +} + +#[derive(Debug)] +pub struct RiverCommandCallbackData { + // This is empty right now, but may be populated in the future. +} + +#[macro_export] +macro_rules! delegate_river_control { + ($ty: ty) => { + ::smithay_client_toolkit::reexports::client::delegate_dispatch!($ty: [ + $crate::river_protocols::control::protocol::zriver_control_v1::ZriverControlV1: ::smithay_client_toolkit::globals::GlobalData, + $crate::river_protocols::control::protocol::zriver_command_callback_v1::ZriverCommandCallbackV1: $crate::river_protocols::control::RiverCommandCallbackData, + ] => $crate::river_protocols::control::RiverControlState); + }; +} diff --git a/src/river_protocols/control/dispatch.rs b/src/river_protocols/control/dispatch.rs new file mode 100644 index 0000000..14759e7 --- /dev/null +++ b/src/river_protocols/control/dispatch.rs @@ -0,0 +1,70 @@ +use std::sync::Arc; + +use super::protocol::{zriver_command_callback_v1, zriver_control_v1}; +use wayland_client::{Connection, Dispatch, QueueHandle}; + +use smithay_client_toolkit::{ + error::GlobalError, + globals::{GlobalData, ProvidesBoundGlobal}, + registry::{ProvidesRegistryState, RegistryHandler}, +}; + +use super::{RiverCommandCallbackData, RiverControlHandler, RiverControlState}; + +impl<D> RegistryHandler<D> for RiverControlState +where + D: Dispatch<zriver_control_v1::ZriverControlV1, GlobalData> + + RiverControlHandler + + ProvidesRegistryState + + 'static, +{ + fn ready(data: &mut D, _conn: &Connection, qh: &QueueHandle<D>) { + data.river_control_state().control = + Arc::new(data.registry().bind_one(qh, 1..=1, GlobalData).into()); + } +} + +impl ProvidesBoundGlobal<zriver_control_v1::ZriverControlV1, 1> for RiverControlState { + fn bound_global(&self) -> Result<zriver_control_v1::ZriverControlV1, GlobalError> { + self.control.get().cloned() + } +} + +impl<D> Dispatch<zriver_control_v1::ZriverControlV1, GlobalData, D> for RiverControlState +where + D: Dispatch<zriver_control_v1::ZriverControlV1, GlobalData> + RiverControlHandler + 'static, +{ + fn event( + _: &mut D, + _: &zriver_control_v1::ZriverControlV1, + _: zriver_control_v1::Event, + _: &GlobalData, + _: &Connection, + _: &QueueHandle<D>, + ) { + unreachable!("zriver_control_v1 has no events") + } +} + +impl<D> Dispatch<zriver_command_callback_v1::ZriverCommandCallbackV1, RiverCommandCallbackData, D> + for RiverControlState +where + D: Dispatch<zriver_command_callback_v1::ZriverCommandCallbackV1, RiverCommandCallbackData> + + RiverControlHandler + + 'static, +{ + fn event( + data: &mut D, + _callback: &zriver_command_callback_v1::ZriverCommandCallbackV1, + event: zriver_command_callback_v1::Event, + _udata: &RiverCommandCallbackData, + conn: &Connection, + qh: &QueueHandle<D>, + ) { + use zriver_command_callback_v1::Event; + match event { + Event::Success { output } => data.command_success(conn, qh, output), + Event::Failure { failure_message } => data.command_success(conn, qh, failure_message), + } + } +} diff --git a/src/river_protocols/status.rs b/src/river_protocols/status.rs new file mode 100644 index 0000000..50c85e0 --- /dev/null +++ b/src/river_protocols/status.rs @@ -0,0 +1,134 @@ +pub mod protocol { + use smithay_client_toolkit::reexports::client as wayland_client; + use smithay_client_toolkit::reexports::client::protocol::*; + + pub mod __interfaces { + use smithay_client_toolkit::reexports::client::protocol::__interfaces::*; + wayland_scanner::generate_interfaces!("protocols/river-status-unstable-v1.xml"); + } + use self::__interfaces::*; + + wayland_scanner::generate_client_code!("protocols/river-status-unstable-v1.xml"); +} + +mod dispatch; + +use std::sync::{Arc, Weak}; + +use smithay_client_toolkit::globals::GlobalData; +use wayland_client::{protocol::wl_output, Connection, Dispatch, QueueHandle}; + +use protocol::{zriver_output_status_v1, zriver_status_manager_v1}; + +use smithay_client_toolkit::error::GlobalError; +use smithay_client_toolkit::registry::GlobalProxy; + +#[derive(Debug)] +pub struct RiverStatusState { + status_manager: GlobalProxy<zriver_status_manager_v1::ZriverStatusManagerV1>, + output_statuses: Vec<Weak<OutputStatusInner>>, +} + +impl RiverStatusState { + pub fn new() -> Self { + Self { + status_manager: GlobalProxy::NotReady, + output_statuses: Vec::new(), + } + } + + pub fn status_manager( + &self, + ) -> Result<&zriver_status_manager_v1::ZriverStatusManagerV1, GlobalError> { + self.status_manager.get() + } + + pub fn get_output_status( + &self, + status: &zriver_output_status_v1::ZriverOutputStatusV1, + ) -> Option<RiverOutputStatus> { + self.output_statuses + .iter() + .filter_map(Weak::upgrade) + .find(|inner| &inner.status == status) + .map(RiverOutputStatus) + } + + #[must_use = "The output status is destroyed if dropped"] + pub fn new_output_status<D>( + &mut self, + qh: &QueueHandle<D>, + output: &wl_output::WlOutput, + ) -> Result<RiverOutputStatus, GlobalError> + where + D: Dispatch<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalData> + + Dispatch<zriver_output_status_v1::ZriverOutputStatusV1, RiverStatusData> + + 'static, + { + let manager = self.status_manager()?; + let output_status = manager.get_river_output_status(output, qh, RiverStatusData {})?; + + let output_status = RiverOutputStatus(Arc::new(OutputStatusInner { + status: output_status, + })); + + self.output_statuses.push(Arc::downgrade(&output_status.0)); + + Ok(output_status) + } +} + +pub trait RiverStatusHandler: Sized { + fn river_status_state(&mut self) -> &mut RiverStatusState; + + fn focused_tags_updated( + &mut self, + conn: &Connection, + qh: &QueueHandle<Self>, + output_status: &RiverOutputStatus, + focused: u32, + ); + + fn urgent_tags_updated( + &mut self, + conn: &Connection, + qh: &QueueHandle<Self>, + output_status: &RiverOutputStatus, + urgent: u32, + ); +} + +#[derive(Debug, Clone)] +pub struct RiverOutputStatus(Arc<OutputStatusInner>); + +impl PartialEq for RiverOutputStatus { + fn eq(&self, other: &Self) -> bool { + Arc::ptr_eq(&self.0, &other.0) + } +} + +#[derive(Debug)] +pub struct RiverStatusData { + // This is empty right now, but may be populated in the future. +} + +#[macro_export] +macro_rules! delegate_river_status { + ($ty: ty) => { + ::smithay_client_toolkit::reexports::client::delegate_dispatch!($ty: [ + $crate::river_protocols::status::protocol::zriver_status_manager_v1::ZriverStatusManagerV1: ::smithay_client_toolkit::globals::GlobalData, + $crate::river_protocols::status::protocol::zriver_output_status_v1::ZriverOutputStatusV1: $crate::river_protocols::status::RiverStatusData, + ] => $crate::river_protocols::status::RiverStatusState); + }; +} + +#[derive(Debug)] +struct OutputStatusInner { + status: zriver_output_status_v1::ZriverOutputStatusV1, +} + +impl Drop for OutputStatusInner { + fn drop(&mut self) { + self.status.destroy(); + } +} diff --git a/src/river_protocols/status/dispatch.rs b/src/river_protocols/status/dispatch.rs new file mode 100644 index 0000000..d38037d --- /dev/null +++ b/src/river_protocols/status/dispatch.rs @@ -0,0 +1,86 @@ +use super::protocol::{zriver_output_status_v1, zriver_status_manager_v1}; +use wayland_client::{Connection, Dispatch, QueueHandle}; + +use smithay_client_toolkit::{ + error::GlobalError, + globals::{GlobalData, ProvidesBoundGlobal}, + registry::{ProvidesRegistryState, RegistryHandler}, +}; + +use super::{RiverStatusData, RiverStatusHandler, RiverStatusState}; + +impl<D> RegistryHandler<D> for RiverStatusState +where + D: Dispatch<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalData> + + RiverStatusHandler + + ProvidesRegistryState + + 'static, +{ + fn ready(data: &mut D, _conn: &Connection, qh: &QueueHandle<D>) { + data.river_status_state().status_manager = + data.registry().bind_one(qh, 1..=2, GlobalData).into(); + } +} + +impl ProvidesBoundGlobal<zriver_status_manager_v1::ZriverStatusManagerV1, 1> for RiverStatusState { + fn bound_global(&self) -> Result<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalError> { + self.status_manager.get().cloned() + } +} + +impl ProvidesBoundGlobal<zriver_status_manager_v1::ZriverStatusManagerV1, 2> for RiverStatusState { + fn bound_global(&self) -> Result<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalError> { + self.status_manager.get().cloned() + } +} + +impl<D> Dispatch<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalData, D> + for RiverStatusState +where + D: Dispatch<zriver_status_manager_v1::ZriverStatusManagerV1, GlobalData> + + RiverStatusHandler + + 'static, +{ + fn event( + _: &mut D, + _: &zriver_status_manager_v1::ZriverStatusManagerV1, + _: zriver_status_manager_v1::Event, + _: &GlobalData, + _: &Connection, + _: &QueueHandle<D>, + ) { + unreachable!("zriver_status_manager_v1 has no events") + } +} + +impl<D> Dispatch<zriver_output_status_v1::ZriverOutputStatusV1, RiverStatusData, D> + for RiverStatusState +where + D: Dispatch<zriver_output_status_v1::ZriverOutputStatusV1, RiverStatusData> + + RiverStatusHandler + + 'static, +{ + fn event( + data: &mut D, + status: &zriver_output_status_v1::ZriverOutputStatusV1, + event: zriver_output_status_v1::Event, + _udata: &RiverStatusData, + conn: &Connection, + qh: &QueueHandle<D>, + ) { + use zriver_output_status_v1::Event; + + // Remove any statuses that have been dropped + data.river_status_state() + .output_statuses + .retain(|status| status.upgrade().is_some()); + + if let Some(status) = data.river_status_state().get_output_status(status) { + match event { + Event::FocusedTags { tags } => data.focused_tags_updated(conn, qh, &status, tags), + Event::UrgentTags { tags } => data.urgent_tags_updated(conn, qh, &status, tags), + Event::ViewTags { tags: _ } => (), + } + } + } +} |
