summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bar.rs5
-rw-r--r--src/button_manager.rs10
-rw-r--r--src/wm_info_provider.rs4
-rw-r--r--src/wm_info_provider/hyprland.rs43
-rw-r--r--src/wm_info_provider/river.rs58
5 files changed, 99 insertions, 21 deletions
diff --git a/src/bar.rs b/src/bar.rs
index 18be97e..afb221d 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -123,7 +123,10 @@ impl Bar {
) -> anyhow::Result<()> {
if let Some(tag_id) = self.tags_btns.click(x) {
ss.wm_info_provider
- .click_on_tag(conn, self.output.wl, seat, *tag_id, button);
+ .click_on_tag(conn, &self.output, seat, Some(*tag_id), button);
+ } else if self.tags_btns.is_between(x) {
+ ss.wm_info_provider
+ .click_on_tag(conn, &self.output, seat, None, button);
} else if let Some((name, instance)) = self.blocks_btns.click(x) {
if let Some(cmd) = &mut ss.status_cmd {
cmd.send_click_event(&i3bar_protocol::Event {
diff --git a/src/button_manager.rs b/src/button_manager.rs
index 9981229..13f9124 100644
--- a/src/button_manager.rs
+++ b/src/button_manager.rs
@@ -16,4 +16,14 @@ impl<T> ButtonManager<T> {
.find(|(x_off, w, _)| x >= *x_off && x <= *x_off + *w)
.map(|(_, _, e)| e)
}
+
+ pub fn is_between(&self, x: f64) -> bool {
+ let mut left = false;
+ let mut right = false;
+ for &(x_off, w, _) in &self.0 {
+ left |= x_off <= x;
+ right |= x_off + w >= x;
+ }
+ left && right
+ }
}
diff --git a/src/wm_info_provider.rs b/src/wm_info_provider.rs
index 80f4f35..a8ee3be 100644
--- a/src/wm_info_provider.rs
+++ b/src/wm_info_provider.rs
@@ -38,9 +38,9 @@ pub trait WmInfoProvider {
fn click_on_tag(
&mut self,
_conn: &mut Connection<State>,
- _output: WlOutput,
+ _output: &Output,
_seat: WlSeat,
- _tag_id: u32,
+ _tag_id: Option<u32>,
_btn: PointerBtn,
) {
}
diff --git a/src/wm_info_provider/hyprland.rs b/src/wm_info_provider/hyprland.rs
index 29b86b3..a59a68f 100644
--- a/src/wm_info_provider/hyprland.rs
+++ b/src/wm_info_provider/hyprland.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::collapsible_else_if)]
+
use std::io::{self, Write};
use std::os::fd::AsRawFd;
use std::os::unix::net::UnixStream;
@@ -25,6 +27,10 @@ impl HyprlandInfoProvider {
ipc,
})
}
+
+ fn set_workspace(&self, id: u32) {
+ let _ = self.ipc.exec(&format!("/dispatch workspace {id}"));
+ }
}
impl WmInfoProvider for HyprlandInfoProvider {
@@ -57,13 +63,42 @@ impl WmInfoProvider for HyprlandInfoProvider {
fn click_on_tag(
&mut self,
_: &mut Connection<State>,
- _: WlOutput,
+ output: &Output,
_: WlSeat,
- tag_id: u32,
+ tag_id: Option<u32>,
btn: PointerBtn,
) {
- if btn == PointerBtn::Left {
- let _ = self.ipc.exec(&format!("/dispatch workspace {tag_id}"));
+ match btn {
+ PointerBtn::Left => {
+ if let Some(tag_id) = tag_id {
+ self.set_workspace(tag_id);
+ }
+ }
+ PointerBtn::WheelUp | PointerBtn::WheelDown => {
+ if let Some(active_i) = self
+ .workspaces
+ .iter()
+ .position(|ws| ws.monitor == output.name && self.active_id == ws.id)
+ {
+ if btn == PointerBtn::WheelUp {
+ if let Some(prev) = self.workspaces[..active_i]
+ .iter()
+ .rfind(|ws| ws.monitor == output.name)
+ {
+ self.set_workspace(prev.id);
+ }
+ } else {
+ if let Some(next) = self.workspaces[active_i..]
+ .iter()
+ .skip(1)
+ .find(|ws| ws.monitor == output.name)
+ {
+ self.set_workspace(next.id);
+ }
+ }
+ }
+ }
+ _ => (),
}
}
diff --git a/src/wm_info_provider/river.rs b/src/wm_info_provider/river.rs
index 4763f9f..f50eefe 100644
--- a/src/wm_info_provider/river.rs
+++ b/src/wm_info_provider/river.rs
@@ -52,6 +52,15 @@ impl RiverInfoProvider {
},
})
}
+
+ fn set_focused_tags(&self, seat: WlSeat, conn: &mut Connection<State>, tags: u32) {
+ self.control
+ .add_argument(conn, c"set-focused-tags".to_owned());
+ self.control
+ .add_argument(conn, CString::new(tags.to_string()).unwrap());
+ self.control
+ .run_command_with_cb(conn, seat, river_command_cb);
+ }
}
impl WmInfoProvider for RiverInfoProvider {
@@ -109,23 +118,44 @@ impl WmInfoProvider for RiverInfoProvider {
fn click_on_tag(
&mut self,
conn: &mut Connection<State>,
- _output: WlOutput,
+ output: &Output,
seat: WlSeat,
- tag_id: u32,
+ tag_id: Option<u32>,
btn: PointerBtn,
) {
- let cmd = match btn {
- PointerBtn::Left => c"set-focused-tags",
- PointerBtn::Right => c"toggle-focused-tags",
- _ => return,
- };
- self.control.add_argument(conn, cmd.to_owned());
- self.control.add_argument(
- conn,
- CString::new((1u32 << (tag_id - 1)).to_string()).unwrap(),
- );
- self.control
- .run_command_with_cb(conn, seat, river_command_cb);
+ match btn {
+ PointerBtn::Left => {
+ if let Some(tag_id) = tag_id {
+ self.set_focused_tags(seat, conn, 1u32 << (tag_id - 1));
+ }
+ }
+ PointerBtn::Right => {
+ if let Some(tag_id) = tag_id {
+ self.control
+ .add_argument(conn, c"toggle-focused-tags".to_owned());
+ self.control.add_argument(
+ conn,
+ CString::new((1u32 << (tag_id - 1)).to_string()).unwrap(),
+ );
+ self.control
+ .run_command_with_cb(conn, seat, river_command_cb);
+ }
+ }
+ PointerBtn::WheelUp | PointerBtn::WheelDown => {
+ if let Some(status) = self.output_statuses.iter().find(|s| s.output == output.wl) {
+ let mut new_tags = if btn == PointerBtn::WheelUp {
+ status.focused_tags >> 1
+ } else {
+ status.focused_tags << 1
+ };
+ if new_tags == 0 {
+ new_tags |= status.focused_tags & 0x8000_0001;
+ }
+ self.set_focused_tags(seat, conn, new_tags);
+ }
+ }
+ _ => (),
+ }
}
fn as_any(&mut self) -> &mut dyn Any {