summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxVerevkin <maxxverrr@gmail.com>2023-04-12 12:05:08 +0300
committerMaxVerevkin <maxxverrr@gmail.com>2023-06-01 13:34:44 +0300
commit2da90fc625725c6d3465c920826e2718579cfb40 (patch)
tree71e24548972604aaf741e52e6e7a6ba74a95b716 /src
parent84b8dfe8cd190de33221f465a7059be6a30769f5 (diff)
downloadi3bar-mango-2da90fc625725c6d3465c920826e2718579cfb40.tar.gz
WIP: hyprland support
Diffstat (limited to 'src')
-rw-r--r--src/protocol.rs1
-rw-r--r--src/wm_info_provider.rs27
-rw-r--r--src/wm_info_provider/ext_workspace_unstable.rs203
3 files changed, 224 insertions, 7 deletions
diff --git a/src/protocol.rs b/src/protocol.rs
index 5b30463..c393850 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -4,3 +4,4 @@ pub use wayrs_protocols::viewporter::*;
pub use wayrs_protocols::wlr_layer_shell_unstable_v1::*;
wayrs_client::scanner::generate!("protocols/river-status-unstable-v1.xml");
wayrs_client::scanner::generate!("protocols/river-control-unstable-v1.xml");
+wayrs_client::scanner::generate!("protocols/ext-workspace-unstable-v1.xml");
diff --git a/src/wm_info_provider.rs b/src/wm_info_provider.rs
index 12e4fb8..7f2d941 100644
--- a/src/wm_info_provider.rs
+++ b/src/wm_info_provider.rs
@@ -1,3 +1,4 @@
+mod ext_workspace_unstable;
mod river;
use wayrs_client::connection::Connection;
@@ -6,10 +7,13 @@ use wayrs_client::global::*;
use crate::pointer_btn::PointerBtn;
use crate::protocol::*;
use crate::state::State;
+use ext_workspace_unstable::*;
+use river::*;
pub enum WmInfoProvider {
None,
- River(river::RiverInfoProvider),
+ River(RiverInfoProvider),
+ EWU(ExtWorkspaceUnstable),
}
pub type WmInfoCallback = fn(&mut Connection<State>, &mut State, WlOutput, WmInfo);
@@ -20,21 +24,28 @@ impl WmInfoProvider {
globals: &Globals,
callback: WmInfoCallback,
) -> WmInfoProvider {
- let Some(river) = river::RiverInfoProvider::bind(conn, globals, callback) else { return Self::None };
- Self::River(river)
+ if let Some(river) = RiverInfoProvider::bind(conn, globals, callback) {
+ Self::River(river)
+ } else if let Some(ext_wp_u) = ExtWorkspaceUnstable::bind(conn, globals, callback) {
+ Self::EWU(ext_wp_u)
+ } else {
+ Self::None
+ }
}
pub fn new_ouput(&mut self, conn: &mut Connection<State>, output: WlOutput) {
match self {
Self::None => (),
- Self::River(river) => river.new_output(conn, output),
+ Self::River(x) => x.new_output(conn, output),
+ Self::EWU(x) => x.new_ouput(conn, output),
}
}
pub fn output_removed(&mut self, conn: &mut Connection<State>, output: WlOutput) {
match self {
Self::None => (),
- Self::River(river) => river.output_removed(conn, output),
+ Self::River(x) => x.output_removed(conn, output),
+ Self::EWU(x) => x.output_removed(conn, output),
}
}
@@ -48,17 +59,19 @@ impl WmInfoProvider {
) {
match self {
Self::None => (),
- Self::River(river) => river.click_on_tag(conn, output, seat, tag, btn),
+ Self::River(x) => x.click_on_tag(conn, output, seat, tag, btn),
+ Self::EWU(x) => x.click_on_tag(conn, output, seat, tag, btn),
}
}
}
-#[derive(Default)]
+#[derive(Default, Debug)]
pub struct WmInfo {
pub layout_name: Option<String>,
pub tags: Vec<Tag>,
}
+#[derive(Debug)]
pub struct Tag {
pub name: String,
pub is_focused: bool,
diff --git a/src/wm_info_provider/ext_workspace_unstable.rs b/src/wm_info_provider/ext_workspace_unstable.rs
new file mode 100644
index 0000000..68238d0
--- /dev/null
+++ b/src/wm_info_provider/ext_workspace_unstable.rs
@@ -0,0 +1,203 @@
+use wayrs_client::connection::Connection;
+use wayrs_client::global::*;
+use wayrs_client::object::ObjectId;
+use wayrs_client::proxy::Proxy;
+
+use super::*;
+use crate::protocol::*;
+use crate::state::State;
+
+pub struct ExtWorkspaceUnstable {
+ groups: Vec<Group>,
+ known_outputs: Vec<WlOutput>,
+ callback: WmInfoCallback,
+}
+
+#[derive(Debug)]
+struct Group {
+ group_handle: ZextWorkspaceGroupHandleV1,
+ workspaces: Vec<Workspace>,
+ outputs: Vec<ObjectId>,
+}
+
+#[derive(Debug)]
+struct Workspace {
+ workspace_handle: ZextWorkspaceHandleV1,
+ name: Option<String>,
+ is_focused: bool,
+ is_urgent: bool,
+}
+
+impl ExtWorkspaceUnstable {
+ pub fn bind(
+ conn: &mut Connection<State>,
+ globals: &Globals,
+ callback: WmInfoCallback,
+ ) -> Option<Self> {
+ let _: ZextWorkspaceManagerV1 = globals.bind_with_cb(conn, 1..=1, manager_cb).ok()?;
+ Some(Self {
+ groups: Vec::new(),
+ known_outputs: Vec::new(),
+ callback,
+ })
+ }
+}
+
+impl ExtWorkspaceUnstable {
+ pub fn new_ouput(&mut self, _: &mut Connection<State>, output: WlOutput) {
+ self.known_outputs.push(output);
+ }
+
+ pub fn output_removed(&mut self, _: &mut Connection<State>, output: WlOutput) {
+ self.known_outputs.retain(|&o| o != output);
+ for group in &mut self.groups {
+ group.outputs.retain(|&id| id != output.id());
+ }
+ }
+
+ pub fn click_on_tag(
+ &mut self,
+ _: &mut Connection<State>,
+ _: WlOutput,
+ _: WlSeat,
+ _: &str,
+ _: PointerBtn,
+ ) {
+ }
+}
+
+fn manager_cb(
+ conn: &mut Connection<State>,
+ s: &mut State,
+ _: ZextWorkspaceManagerV1,
+ event: zext_workspace_manager_v1::Event,
+) {
+ let WmInfoProvider::EWU(state) = &mut s.shared_state.wm_info_provider else { unreachable!() };
+
+ match event {
+ zext_workspace_manager_v1::Event::WorkspaceGroup(group_handle) => {
+ conn.set_callback_for(group_handle, group_cb);
+ state.groups.push(Group {
+ group_handle,
+ workspaces: Vec::new(),
+ outputs: Vec::new(),
+ });
+ }
+ zext_workspace_manager_v1::Event::Done => {
+ let mut events = Vec::new();
+ for &output in &state.known_outputs {
+ if let Some(group) = state
+ .groups
+ .iter()
+ .find(|g| g.outputs.contains(&output.id()))
+ {
+ let mut tags: Vec<_> = group
+ .workspaces
+ .iter()
+ .flat_map(|w| {
+ let name = w.name.clone()?;
+ Some(Tag {
+ name,
+ is_focused: w.is_focused,
+ is_active: true,
+ is_urgent: w.is_urgent,
+ })
+ })
+ .collect();
+ tags.sort_unstable_by(|a, b| a.name.cmp(&b.name));
+ events.push((output, tags));
+ }
+ }
+
+ let cb = state.callback;
+ for (output, tags) in events {
+ let info = WmInfo {
+ layout_name: None,
+ tags,
+ };
+ (cb)(conn, s, output, info);
+ }
+ }
+ zext_workspace_manager_v1::Event::Finished => unreachable!(),
+ }
+}
+
+fn group_cb(
+ conn: &mut Connection<State>,
+ state: &mut State,
+ group_handle: ZextWorkspaceGroupHandleV1,
+ event: zext_workspace_group_handle_v1::Event,
+) {
+ let WmInfoProvider::EWU(state) = &mut state.shared_state.wm_info_provider else { unreachable!() };
+ let group = state
+ .groups
+ .iter_mut()
+ .find(|g| g.group_handle == group_handle)
+ .unwrap();
+
+ match event {
+ zext_workspace_group_handle_v1::Event::OutputEnter(output) => {
+ group.outputs.push(output);
+ }
+ zext_workspace_group_handle_v1::Event::OutputLeave(_) => todo!(),
+ zext_workspace_group_handle_v1::Event::Workspace(workspace_handle) => {
+ conn.set_callback_for(workspace_handle, workspace_cb);
+ group.workspaces.push(Workspace {
+ workspace_handle,
+ name: None,
+ is_focused: false,
+ is_urgent: false,
+ });
+ }
+ zext_workspace_group_handle_v1::Event::Remove => {
+ todo!();
+ }
+ }
+}
+
+fn workspace_cb(
+ conn: &mut Connection<State>,
+ state: &mut State,
+ workspace_handle: ZextWorkspaceHandleV1,
+ event: zext_workspace_handle_v1::Event,
+) {
+ let WmInfoProvider::EWU(state) = &mut state.shared_state.wm_info_provider else { unreachable!() };
+ let group = state
+ .groups
+ .iter_mut()
+ .find(|g| {
+ g.workspaces
+ .iter()
+ .any(|w| w.workspace_handle == workspace_handle)
+ })
+ .unwrap();
+ let workspace = group
+ .workspaces
+ .iter_mut()
+ .find(|w| w.workspace_handle == workspace_handle)
+ .unwrap();
+
+ match event {
+ zext_workspace_handle_v1::Event::Name(name) => {
+ workspace.name = Some(name.to_string_lossy().into_owned());
+ }
+ zext_workspace_handle_v1::Event::Coordinates(_) => (),
+ zext_workspace_handle_v1::Event::State(state) => {
+ workspace.is_focused = false;
+ workspace.is_urgent = false;
+ for state in state
+ .chunks_exact(4)
+ .map(|b| u32::from_ne_bytes(b.try_into().unwrap()))
+ {
+ workspace.is_focused |= state == zext_workspace_handle_v1::State::Active as u32;
+ workspace.is_urgent |= state == zext_workspace_handle_v1::State::Urgent as u32;
+ }
+ }
+ zext_workspace_handle_v1::Event::Remove => {
+ group
+ .workspaces
+ .retain(|w| w.workspace_handle != workspace_handle);
+ workspace_handle.destroy(conn);
+ }
+ }
+}