Skip to content

Commit 2b552dc

Browse files
committed
Add semi_focused tags
I use multiple outputs, and as such often need to remember which output is currently focused. Fortunately, river tells us which output is currently in focus. Therefore, I added the `is_semi_focused` flag to a `Tag`, to signify that it is a focused Tag on its output, but that it is _not_ actually focused, because the whole output is not focused. For users that do not need or want this extra differentiation, setting `tag_semi_focused_{fg,bg}` to the `tag_focused_{fg,bg}` values, will result in the previous behaviour. I am not familiar enough with niri or hyprland to know if they can support something like this too. As such, both of their information providers set `is_semi_focused` unconditionally to `false`.
1 parent c9cee90 commit 2b552dc

7 files changed

Lines changed: 56 additions & 6 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ tag_fg = "#d79921ff"
5555
tag_bg = "#282828ff"
5656
tag_focused_fg = "#1d2021ff"
5757
tag_focused_bg = "#689d68ff"
58+
tag_semi_focused_fg = "#1da021ff"
59+
tag_semi_focused_bg = "#689d68ff"
5860
tag_urgent_fg = "#282828ff"
5961
tag_urgent_bg = "#cc241dff"
6062
tag_inactive_fg = "#d79921ff"

src/bar.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ impl Bar {
216216
(ss.config.tag_urgent_bg, ss.config.tag_urgent_fg)
217217
} else if tag.is_focused {
218218
(ss.config.tag_focused_bg, ss.config.tag_focused_fg)
219+
} else if tag.is_semi_focused {
220+
(ss.config.tag_semi_focused_bg, ss.config.tag_semi_focused_fg)
219221
} else if tag.is_active {
220222
(ss.config.tag_bg, ss.config.tag_fg)
221223
} else if !ss.config.hide_inactive_tags {

src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub struct Config {
2222
pub tag_bg: Color,
2323
pub tag_focused_fg: Color,
2424
pub tag_focused_bg: Color,
25+
pub tag_semi_focused_fg: Color,
26+
pub tag_semi_focused_bg: Color,
2527
pub tag_urgent_fg: Color,
2628
pub tag_urgent_bg: Color,
2729
pub tag_inactive_fg: Color,
@@ -68,6 +70,8 @@ impl Default for Config {
6870
tag_bg: Color::from_rgba_hex(0x282828ff),
6971
tag_focused_fg: Color::from_rgba_hex(0x1d2021ff),
7072
tag_focused_bg: Color::from_rgba_hex(0x689d68ff),
73+
tag_semi_focused_fg: Color::from_rgba_hex(0x1da021ff),
74+
tag_semi_focused_bg: Color::from_rgba_hex(0x689d68ff),
7175
tag_urgent_fg: Color::from_rgba_hex(0x282828ff),
7276
tag_urgent_bg: Color::from_rgba_hex(0xcc241dff),
7377
tag_inactive_fg: Color::from_rgba_hex(0xd79921ff),

src/wm_info_provider.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,16 @@ pub fn bind(conn: &mut Connection<State>, config: &WmConfig) -> Box<dyn WmInfoPr
6868
pub struct Tag {
6969
pub id: u32,
7070
pub name: String,
71+
72+
/// The tag is focused and on the currently focused output.
7173
pub is_focused: bool,
74+
75+
/// The tag is focused, but not on the currently focused output.
76+
pub is_semi_focused: bool,
77+
78+
/// The tag contains views.
7279
pub is_active: bool,
80+
81+
/// The tag contains views marked as “urgent”.
7382
pub is_urgent: bool,
7483
}

src/wm_info_provider/hyprland.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl WmInfoProvider for HyprlandInfoProvider {
5959
is_focused: ws.name == self.active_name,
6060
is_active: true,
6161
is_urgent: false,
62+
is_semi_focused: false,
6263
})
6364
.collect()
6465
}

src/wm_info_provider/niri.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl WmInfoProvider for NiriInfoProvider {
6969
is_focused: ws.is_active,
7070
is_active: i < output_workspaces.len() - 1 || ws.is_focused,
7171
is_urgent: false,
72+
is_semi_focused: false,
7273
})
7374
.collect()
7475
}

src/wm_info_provider/river.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct OutputStatus {
2020
urgent_tags: u32,
2121
active_tags: u32,
2222
layout_name: Option<String>,
23+
is_focused: bool,
2324
}
2425

2526
impl RiverInfoProvider {
@@ -62,6 +63,7 @@ impl WmInfoProvider for RiverInfoProvider {
6263
urgent_tags: 0,
6364
active_tags: 0,
6465
layout_name: None,
66+
is_focused: true,
6567
});
6668
}
6769

@@ -79,11 +81,13 @@ impl WmInfoProvider for RiverInfoProvider {
7981
let Some(status) = self.output_statuses.iter().find(|s| s.output == output.wl) else {
8082
return Vec::new();
8183
};
84+
8285
(1..=u8::min(self.max_tag, 32))
8386
.map(|tag| Tag {
8487
id: tag as u32,
8588
name: tag.to_string(),
86-
is_focused: status.focused_tags & (1 << (tag - 1)) != 0,
89+
is_focused: status.focused_tags & (1 << (tag - 1)) != 0 && status.is_focused,
90+
is_semi_focused: status.focused_tags & (1 << (tag - 1)) != 0 && !status.is_focused,
8791
is_active: status.active_tags & (1 << (tag - 1)) != 0,
8892
is_urgent: status.urgent_tags & (1 << (tag - 1)) != 0,
8993
})
@@ -184,11 +188,38 @@ fn output_status_cb(ctx: EventCtx<State, ZriverOutputStatusV1>) {
184188
}
185189

186190
fn seat_status_cb(ctx: EventCtx<State, ZriverSeatStatusV1>) {
187-
if let zriver_seat_status_v1::Event::Mode(mode) = ctx.event {
188-
let river = ctx.state.shared_state.get_river().unwrap();
189-
let mode = mode.to_string_lossy().into_owned();
190-
river.mode = (mode != "normal").then_some(mode);
191-
ctx.state.mode_name_updated(ctx.conn, None);
191+
match ctx.event {
192+
zriver_seat_status_v1::Event::Mode(mode) => {
193+
let river = ctx.state.shared_state.get_river().unwrap();
194+
let mode = mode.to_string_lossy().into_owned();
195+
river.mode = (mode != "normal").then_some(mode);
196+
ctx.state.mode_name_updated(ctx.conn, None);
197+
}
198+
zriver_seat_status_v1::Event::FocusedOutput(output) => {
199+
let river = ctx.state.shared_state.get_river().unwrap();
200+
let Some(status) = river
201+
.output_statuses
202+
.iter_mut()
203+
.find(|s| s.output == output)
204+
else {
205+
return;
206+
};
207+
status.is_focused = true;
208+
ctx.state.tags_updated(ctx.conn, None);
209+
}
210+
zriver_seat_status_v1::Event::UnfocusedOutput(output) => {
211+
let river = ctx.state.shared_state.get_river().unwrap();
212+
let Some(status) = river
213+
.output_statuses
214+
.iter_mut()
215+
.find(|s| s.output == output)
216+
else {
217+
return;
218+
};
219+
status.is_focused = false;
220+
ctx.state.tags_updated(ctx.conn, None);
221+
}
222+
_ => {}
192223
}
193224
}
194225

0 commit comments

Comments
 (0)