Skip to content

Commit

Permalink
adding a spacer widget for the status bar
Browse files Browse the repository at this point in the history
  • Loading branch information
sminez committed Jun 2, 2024
1 parent b4b511c commit fbcde44
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 7 deletions.
16 changes: 13 additions & 3 deletions crates/penrose_ui/src/bar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,15 @@ impl<X: XConn> StatusBar<X> {
let mut extents = Vec::with_capacity(self.widgets.len());
let mut greedy_indices = vec![];

for (i, w) in self.widgets.iter_mut().enumerate() {
for (j, w) in self
.widgets
.iter_mut()
.filter(|w| w.required_for_screen(i))
.enumerate()
{
extents.push(w.current_extent(&mut ctx, self.h)?);
if w.is_greedy() {
greedy_indices.push(i)
greedy_indices.push(j)
}
}

Expand All @@ -152,7 +157,12 @@ impl<X: XConn> StatusBar<X> {
}

let mut x = 0;
for (wd, (w, _)) in self.widgets.iter_mut().zip(extents) {
for (wd, (w, _)) in self
.widgets
.iter_mut()
.filter(|w| w.required_for_screen(i))
.zip(extents)
{
wd.draw(&mut ctx, self.active_screen, screen_has_focus, w, self.h)?;
x += w;
ctx.flush();
Expand Down
72 changes: 72 additions & 0 deletions crates/penrose_ui/src/bar/widgets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ where
/// space will be split evenly between all widgets.
fn is_greedy(&self) -> bool;

/// Whether or not this widget should be displayed on the given screen index.
///
/// By default all widgets are displayed on all screens but this allows widgets to
/// conditionally render on a subset of screens (e.g. a systray widget only displaying
/// on the primary screen).
#[allow(unused_variables)]
fn required_for_screen(&self, idx: usize) -> bool {
true
}

#[allow(unused_variables)]
/// A startup hook to be run in order to initialise this Widget
fn on_startup(&mut self, state: &mut State<X>, x: &X) -> Result<()> {
Expand Down Expand Up @@ -380,3 +390,65 @@ impl<X: XConn> Widget<X> for IntervalText {
Widget::<X>::require_draw(&*inner)
}
}

/// A simple percentage based spacer widget that can be conditionally applied to
/// specific screens.
#[derive(Debug)]
pub struct Spacer {
screen_indices: Vec<usize>,
perc: f32,
w: u32,
}

impl Spacer {
/// Construct a new spacer for rendering on the specified screens.
///
/// It will consume `perc`% of the width of any screen it is rendered on.
///
/// # Panics
/// This method will panic if `perc` is not in the range `0.0..=1.0`.
pub fn new(screen_indices: Vec<usize>, perc: f32) -> Self {
if !(0.0..=1.0).contains(&perc) {
panic!("{perc} is an invalid percentage");
}

Self {
screen_indices,
perc,
w: 0,
}
}
}

impl<X: XConn> Widget<X> for Spacer {
fn draw(&mut self, ctx: &mut Context<'_>, _: usize, _: bool, w: u32, h: u32) -> Result<()> {
ctx.fill_bg(Rect::new(0, 0, w, h))
}

fn current_extent(&mut self, _: &mut Context<'_>, h: u32) -> Result<(u32, u32)> {
Ok((self.w, h))
}

fn is_greedy(&self) -> bool {
false
}

fn require_draw(&self) -> bool {
false
}

fn required_for_screen(&self, idx: usize) -> bool {
self.screen_indices.contains(&idx)
}

fn on_startup(&mut self, state: &mut State<X>, _: &X) -> Result<()> {
self.w = state
.client_set
.screens()
.next()
.map(|s| (s.geometry().w as f32 * self.perc) as u32)
.unwrap();

Ok(())
}
}
2 changes: 1 addition & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ where
pub fn extension<E: Any>(&self) -> Result<Arc<RefCell<E>>> {
self.extensions
.get()
.map(Arc::clone)
.cloned()
.ok_or(Error::UnknownStateExtension {
type_id: TypeId::of::<E>(),
})
Expand Down
8 changes: 6 additions & 2 deletions src/extensions/hooks/window_swallowing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ struct WindowSwallowingState {
impl WindowSwallowingState {
fn stash_state<X: XConn>(&mut self, state: &mut State<X>) -> Result<bool> {
self.stack_before_close = state.client_set.current_stack().cloned();
self.floating_before_close = state.client_set.floating.clone();
self.floating_before_close
.clone_from(&state.client_set.floating);

Ok(true)
}
Expand Down Expand Up @@ -65,7 +66,10 @@ impl WindowSwallowingState {

info!(%parent, %child, "restoring swallowed parent in place of child");
transfer_floating_state(child, parent, &mut self.floating_before_close);
state.client_set.floating = self.floating_before_close.clone();
state
.client_set
.floating
.clone_from(&self.floating_before_close);
old_stack.focus = parent;
state.client_set.modify_occupied(|_| old_stack);
x.refresh(state)?;
Expand Down
2 changes: 1 addition & 1 deletion src/pure/stack_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ pub mod tests {
// This state is technically invalid for us to get in to but the point is
// to check that we definitely leave the previous tag alone during this
// operation and don't end up with it anywhere it shouldn't be.
s.previous_tag = "PREVIOUS".to_owned();
"PREVIOUS".clone_into(&mut s.previous_tag);

assert_eq!(s.screens.focus.workspace.tag, "3");
assert_eq!(s.previous_tag, "PREVIOUS");
Expand Down

0 comments on commit fbcde44

Please sign in to comment.