summaryrefslogtreecommitdiff
path: root/src/river_protocols
diff options
context:
space:
mode:
authorMaxVerevkin <maxxverrr@gmail.com>2022-08-08 23:12:23 +0300
committerMaxVerevkin <maxxverrr@gmail.com>2022-08-08 23:59:59 +0300
commit1851c56e407cac72ca104cc5e75692cd9c648986 (patch)
tree31473532e01ee6ee1571974a6abf59463e3265ed /src/river_protocols
parent9ddde2d2ee9833412e39afbd1ed907cdea22f08f (diff)
downloadi3bar-mango-1851c56e407cac72ca104cc5e75692cd9c648986.tar.gz
rewrite using latest walayd libs & implement HiDPI
Diffstat (limited to 'src/river_protocols')
-rw-r--r--src/river_protocols/control.rs89
-rw-r--r--src/river_protocols/control/dispatch.rs70
-rw-r--r--src/river_protocols/status.rs134
-rw-r--r--src/river_protocols/status/dispatch.rs86
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: _ } => (),
+ }
+ }
+ }
+}