1
0
Fork 0
forked from wry/wry

config: allow disabling the built-in bar

This commit is contained in:
Julian Orth 2025-07-17 22:31:16 +02:00
parent 224f5380fe
commit 08e7e01d0e
16 changed files with 156 additions and 14 deletions

View file

@ -950,6 +950,16 @@ impl ConfigClient {
above above
} }
pub fn set_show_bar(&self, show: bool) {
self.send(&ClientMessage::SetShowBar { show });
}
pub fn get_show_bar(&self) -> bool {
let res = self.send_with_response(&ClientMessage::GetShowBar);
get_response!(res, true, GetShowBar { show });
show
}
pub fn set_show_float_pin_icon(&self, show: bool) { pub fn set_show_float_pin_icon(&self, show: bool) {
self.send(&ClientMessage::SetShowFloatPinIcon { show }); self.send(&ClientMessage::SetShowFloatPinIcon { show });
} }

View file

@ -721,6 +721,10 @@ pub enum ClientMessage<'a> {
GetContentType { GetContentType {
window: Window, window: Window,
}, },
SetShowBar {
show: bool,
},
GetShowBar,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -950,6 +954,9 @@ pub enum Response {
GetContentType { GetContentType {
kind: ContentType, kind: ContentType,
}, },
GetShowBar {
show: bool,
},
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]

View file

@ -316,6 +316,24 @@ pub fn set_show_float_pin_icon(show: bool) {
get!().set_show_float_pin_icon(show); get!().set_show_float_pin_icon(show);
} }
/// Sets whether the built-in bar is shown.
///
/// The default is `true`.
pub fn set_show_bar(show: bool) {
get!().set_show_bar(show)
}
/// Returns whether the built-in bar is shown.
pub fn get_show_bar() -> bool {
get!(true).get_show_bar()
}
/// Toggles whether the built-in bar is shown.
pub fn toggle_show_bar() {
let get = get!();
get.set_show_bar(!get.get_show_bar());
}
/// Sets a callback to run when this config is unloaded. /// Sets a callback to run when this config is unloaded.
/// ///
/// Only one callback can be set at a time. If another callback is already set, it will be /// Only one callback can be set at a time. If another callback is already set, it will be

View file

@ -351,6 +351,7 @@ fn start_compositor2(
head_names: Default::default(), head_names: Default::default(),
head_managers: Default::default(), head_managers: Default::default(),
head_managers_async: Default::default(), head_managers_async: Default::default(),
show_bar: Cell::new(true),
}); });
state.tracker.register(ClientId::from_raw(0)); state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state); create_dummy_output(&state);

View file

@ -1330,6 +1330,19 @@ impl ConfigProxyHandler {
}); });
} }
fn handle_set_show_bar(&self, show: bool) {
self.state.show_bar.set(show);
for output in self.state.root.outputs.lock().values() {
output.on_spaces_changed();
}
}
fn handle_get_show_bar(&self) {
self.respond(Response::GetShowBar {
show: self.state.show_bar.get(),
});
}
fn handle_set_show_float_pin_icon(&self, show: bool) { fn handle_set_show_float_pin_icon(&self, show: bool) {
self.state.show_pin_icon.set(show); self.state.show_pin_icon.set(show);
for stacked in self.state.root.stacked.iter() { for stacked in self.state.root.stacked.iter() {
@ -2982,6 +2995,8 @@ impl ConfigProxyHandler {
ClientMessage::GetContentType { window } => self ClientMessage::GetContentType { window } => self
.handle_get_content_type(window) .handle_get_content_type(window)
.wrn("get_content_type")?, .wrn("get_content_type")?,
ClientMessage::SetShowBar { show } => self.handle_set_show_bar(show),
ClientMessage::GetShowBar => self.handle_get_show_bar(),
} }
Ok(()) Ok(())
} }

View file

@ -87,8 +87,8 @@ impl Renderer<'_> {
render_layer!(output.layers[0]); render_layer!(output.layers[0]);
render_layer!(output.layers[1]); render_layer!(output.layers[1]);
let non_exclusive_rect = output.non_exclusive_rect_rel.get(); let non_exclusive_rect = output.non_exclusive_rect_rel.get();
let (x, y) = non_exclusive_rect.translate_inv(x, y); let (x, mut y) = non_exclusive_rect.translate_inv(x, y);
{ if self.state.show_bar.get() {
let bar_bg = Rect::new_sized(0, 0, non_exclusive_rect.width(), th).unwrap(); let bar_bg = Rect::new_sized(0, 0, non_exclusive_rect.width(), th).unwrap();
let bar_bg = self.base.scale_rect(bar_bg); let bar_bg = self.base.scale_rect(bar_bg);
let bar_bg_abs = { let bar_bg_abs = {
@ -166,9 +166,10 @@ impl Renderer<'_> {
self.render_surface(&data.surface, rect.x1(), rect.y1(), Some(&bounds)); self.render_surface(&data.surface, rect.x1(), rect.y1(), Some(&bounds));
} }
} }
y += th + 1;
} }
if let Some(ws) = output.workspace.get() { if let Some(ws) = output.workspace.get() {
self.render_workspace(&ws, x, y + th + 1); self.render_workspace(&ws, x, y);
} }
} }
macro_rules! render_stacked { macro_rules! render_stacked {

View file

@ -271,6 +271,7 @@ pub struct State {
pub head_managers: pub head_managers:
CopyHashMap<(ClientId, JayHeadManagerSessionV1Id), Rc<JayHeadManagerSessionV1>>, CopyHashMap<(ClientId, JayHeadManagerSessionV1Id), Rc<JayHeadManagerSessionV1>>,
pub head_managers_async: AsyncQueue<HeadManagerEvent>, pub head_managers_async: AsyncQueue<HeadManagerEvent>,
pub show_bar: Cell<bool>,
} }
// impl Drop for State { // impl Drop for State {
@ -1474,6 +1475,9 @@ impl State {
} }
pub fn tray_icon_size(&self) -> i32 { pub fn tray_icon_size(&self) -> i32 {
if !self.show_bar.get() {
return 0;
}
(self.theme.sizes.title_height.get() - 2).max(0) (self.theme.sizes.title_height.get() - 2).max(0)
} }

View file

@ -814,8 +814,13 @@ impl ContainerNode {
let abs_y = self.abs_y1.get(); let abs_y = self.abs_y1.get();
for (i, child) in self.children.iter().enumerate() { for (i, child) in self.children.iter().enumerate() {
let rect = child.title_rect.get(); let rect = child.title_rect.get();
if self.toplevel_data.visible.get() { if self.toplevel_data.visible.get() && !mono && split != ContainerSplit::Horizontal {
self.state.damage(rect.move_(abs_x, abs_y)); self.state.damage(Rect::new_sized_unchecked(
abs_x,
abs_y + rect.y1(),
cwidth,
rect.height() + 1,
));
} }
if i > 0 { if i > 0 {
let rect = if mono { let rect = if mono {
@ -852,6 +857,10 @@ impl ContainerNode {
rd.underline_rects rd.underline_rects
.push(Rect::new_sized(0, th, cwidth, 1).unwrap()); .push(Rect::new_sized(0, th, cwidth, 1).unwrap());
} }
if self.toplevel_data.visible.get() && (mono || split == ContainerSplit::Horizontal) {
self.state
.damage(Rect::new_sized_unchecked(abs_x, abs_y, cwidth, th + 1));
}
rd.titles.remove_if(|_, v| v.is_empty()); rd.titles.remove_if(|_, v| v.is_empty());
} }

View file

@ -496,6 +496,9 @@ impl OutputNode {
fn update_render_data_phase1(self: &Rc<Self>) -> Rc<AsyncEvent> { fn update_render_data_phase1(self: &Rc<Self>) -> Rc<AsyncEvent> {
let on_completed = Rc::new(OnDropEvent::default()); let on_completed = Rc::new(OnDropEvent::default());
if !self.state.show_bar.get() {
return on_completed.event();
}
let Some(ctx) = self.state.render_ctx.get() else { let Some(ctx) = self.state.render_ctx.get() else {
return on_completed.event(); return on_completed.event();
}; };
@ -556,6 +559,10 @@ impl OutputNode {
rd.attention_requested_workspaces.clear(); rd.attention_requested_workspaces.clear();
rd.captured_inactive_workspaces.clear(); rd.captured_inactive_workspaces.clear();
rd.active_workspace = None; rd.active_workspace = None;
if !self.state.show_bar.get() {
self.state.damage(rd.full_area);
return;
}
let mut pos = 0; let mut pos = 0;
let theme = &self.state.theme; let theme = &self.state.theme;
let th = theme.sizes.title_height.get(); let th = theme.sizes.title_height.get();
@ -766,7 +773,10 @@ impl OutputNode {
width, width,
height, height,
)); ));
let y1 = y1 + th + 1; let mut y1 = y1;
if self.state.show_bar.get() {
y1 += th + 1;
}
let height = (y2 - y1).max(0); let height = (y2 - y1).max(0);
self.workspace_rect self.workspace_rect
.set(Rect::new_sized_unchecked(x1, y1, width, height)); .set(Rect::new_sized_unchecked(x1, y1, width, height));
@ -1068,6 +1078,9 @@ impl OutputNode {
} }
fn button(self: Rc<Self>, id: PointerType) { fn button(self: Rc<Self>, id: PointerType) {
if !self.state.show_bar.get() {
return;
}
let (x, y) = match self.pointer_positions.get(&id) { let (x, y) = match self.pointer_positions.get(&id) {
Some(p) => p, Some(p) => p,
_ => return, _ => return,
@ -1208,8 +1221,9 @@ impl OutputNode {
if ws.fullscreen.is_some() { if ws.fullscreen.is_some() {
return None; return None;
} }
let show_bar = self.state.show_bar.get();
let th = self.state.theme.sizes.title_height.get(); let th = self.state.theme.sizes.title_height.get();
if y_abs < rect.y1() + th + 1 { if show_bar && y_abs < rect.y1() + th + 1 {
let rd = &*self.render_data.borrow(); let rd = &*self.render_data.borrow();
let (x, _) = rect.translate(x_abs, y_abs); let (x, _) = rect.translate(x_abs, y_abs);
let mut last_x2 = 0; let mut last_x2 = 0;
@ -1236,8 +1250,11 @@ impl OutputNode {
}, },
}); });
} }
let thp1 = self.state.theme.sizes.title_height.get() + 1; let bar_height = match show_bar {
let rect = Rect::new(rect.x1(), rect.y1() + thp1, rect.x2(), rect.y2())?; true => th + 1,
false => 0,
};
let rect = Rect::new(rect.x1(), rect.y1() + bar_height, rect.x2(), rect.y2())?;
if !rect.contains(x_abs, y_abs) { if !rect.contains(x_abs, y_abs) {
return None; return None;
} }
@ -1256,6 +1273,9 @@ impl OutputNode {
x_abs: i32, x_abs: i32,
y_abs: i32, y_abs: i32,
) -> Option<WorkspaceDragDestination> { ) -> Option<WorkspaceDragDestination> {
if !self.state.show_bar.get() {
return None;
}
let rect = self.non_exclusive_rect.get(); let rect = self.non_exclusive_rect.get();
if !rect.contains(x_abs, y_abs) { if !rect.contains(x_abs, y_abs) {
return None; return None;
@ -1478,7 +1498,10 @@ impl Node for OutputNode {
} }
return FindTreeResult::AcceptsInput; return FindTreeResult::AcceptsInput;
} }
let bar_height = self.state.theme.sizes.title_height.get() + 1; let bar_height = match self.state.show_bar.get() {
true => self.state.theme.sizes.title_height.get() + 1,
false => 0,
};
if usecase == FindTreeUsecase::SelectWorkspace { if usecase == FindTreeUsecase::SelectWorkspace {
if y >= bar_height { if y >= bar_height {
y -= bar_height; y -= bar_height;

View file

@ -68,6 +68,8 @@ pub enum SimpleCommand {
SetFloatPinned(bool), SetFloatPinned(bool),
ToggleFloatPinned, ToggleFloatPinned,
KillClient, KillClient,
ShowBar(bool),
ToggleBar,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -483,6 +485,7 @@ pub struct Config {
pub window_rules: Vec<WindowRule>, pub window_rules: Vec<WindowRule>,
pub pointer_revert_key: Option<KeySym>, pub pointer_revert_key: Option<KeySym>,
pub use_hardware_cursor: Option<bool>, pub use_hardware_cursor: Option<bool>,
pub show_bar: Option<bool>,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]

View file

@ -133,6 +133,9 @@ impl ActionParser<'_> {
"unpin-float" => SetFloatPinned(false), "unpin-float" => SetFloatPinned(false),
"toggle-float-pinned" => ToggleFloatPinned, "toggle-float-pinned" => ToggleFloatPinned,
"kill-client" => KillClient, "kill-client" => KillClient,
"show-bar" => ShowBar(true),
"hide-bar" => ShowBar(false),
"toggle-bar" => ToggleBar,
_ => { _ => {
return Err( return Err(
ActionParserError::UnknownSimpleAction(string.to_string()).spanned(span) ActionParserError::UnknownSimpleAction(string.to_string()).spanned(span)

View file

@ -132,6 +132,7 @@ impl Parser for ConfigParser<'_> {
window_rules_val, window_rules_val,
pointer_revert_key_str, pointer_revert_key_str,
use_hardware_cursor, use_hardware_cursor,
show_bar,
), ),
) = ext.extract(( ) = ext.extract((
( (
@ -179,6 +180,7 @@ impl Parser for ConfigParser<'_> {
opt(val("windows")), opt(val("windows")),
recover(opt(str("pointer-revert-key"))), recover(opt(str("pointer-revert-key"))),
recover(opt(bol("use-hardware-cursor"))), recover(opt(bol("use-hardware-cursor"))),
recover(opt(bol("show-bar"))),
), ),
))?; ))?;
let mut keymap = None; let mut keymap = None;
@ -494,6 +496,7 @@ impl Parser for ConfigParser<'_> {
window_rules, window_rules,
pointer_revert_key, pointer_revert_key,
use_hardware_cursor: use_hardware_cursor.despan(), use_hardware_cursor: use_hardware_cursor.despan(),
show_bar: show_bar.despan(),
}) })
} }
} }

View file

@ -35,12 +35,12 @@ use {
logging::set_log_level, logging::set_log_level,
on_devices_enumerated, on_idle, on_unload, quit, reload, set_color_management_enabled, on_devices_enumerated, on_idle, on_unload, quit, reload, set_color_management_enabled,
set_default_workspace_capture, set_explicit_sync_enabled, set_float_above_fullscreen, set_default_workspace_capture, set_explicit_sync_enabled, set_float_above_fullscreen,
set_idle, set_idle_grace_period, set_show_float_pin_icon, set_ui_drag_enabled, set_idle, set_idle_grace_period, set_show_bar, set_show_float_pin_icon,
set_ui_drag_threshold, set_ui_drag_enabled, set_ui_drag_threshold,
status::{set_i3bar_separator, set_status, set_status_command, unset_status_command}, status::{set_i3bar_separator, set_status, set_status_command, unset_status_command},
switch_to_vt, switch_to_vt,
theme::{reset_colors, reset_font, reset_sizes, set_font}, theme::{reset_colors, reset_font, reset_sizes, set_font},
toggle_float_above_fullscreen, toggle_float_above_fullscreen, toggle_show_bar,
video::{ video::{
ColorSpace, Connector, DrmDevice, TransferFunction, connectors, drm_devices, ColorSpace, Connector, DrmDevice, TransferFunction, connectors, drm_devices,
on_connector_connected, on_connector_disconnected, on_graphics_initialized, on_connector_connected, on_connector_disconnected, on_graphics_initialized,
@ -154,6 +154,8 @@ impl Action {
} }
SimpleCommand::ToggleFloatPinned => window_or_seat!(s, s.toggle_float_pinned()), SimpleCommand::ToggleFloatPinned => window_or_seat!(s, s.toggle_float_pinned()),
SimpleCommand::KillClient => client_action!(c, c.kill()), SimpleCommand::KillClient => client_action!(c, c.kill()),
SimpleCommand::ShowBar(show) => B::new(move || set_show_bar(show)),
SimpleCommand::ToggleBar => B::new(toggle_show_bar),
}, },
Action::Multi { actions } => { Action::Multi { actions } => {
let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect(); let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect();
@ -1247,6 +1249,9 @@ fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
if let Some(v) = config.use_hardware_cursor { if let Some(v) = config.use_hardware_cursor {
persistent.seat.use_hardware_cursor(v); persistent.seat.use_hardware_cursor(v);
} }
if let Some(v) = config.show_bar {
set_show_bar(v);
}
} }
fn create_command(exec: &Exec) -> Command { fn create_command(exec: &Exec) -> Command {

View file

@ -883,6 +883,10 @@
"use-hardware-cursor": { "use-hardware-cursor": {
"type": "boolean", "type": "boolean",
"description": "Configures whether the default seat uses hardware cursors.\n\nThe default is `true`.\n" "description": "Configures whether the default seat uses hardware cursors.\n\nThe default is `true`.\n"
},
"show-bar": {
"type": "boolean",
"description": "Configures whether the built-in bar is shown.\n\nThe default is `true`.\n"
} }
}, },
"required": [] "required": []
@ -1586,7 +1590,10 @@
"pin-float", "pin-float",
"unpin-float", "unpin-float",
"toggle-float-pinned", "toggle-float-pinned",
"kill-client" "kill-client",
"show-bar",
"hide-bar",
"toggle-bar"
] ]
}, },
"Status": { "Status": {

View file

@ -1794,6 +1794,14 @@ The table has the following fields:
The value of this field should be a boolean. The value of this field should be a boolean.
- `show-bar` (optional):
Configures whether the built-in bar is shown.
The default is `true`.
The value of this field should be a boolean.
<a name="types-Connector"></a> <a name="types-Connector"></a>
### `Connector` ### `Connector`
@ -3597,6 +3605,18 @@ The string should have one of the following values:
Within a window rule, it applies to the client of the window. Within a client rule Within a window rule, it applies to the client of the window. Within a client rule
it applies to the matched client. Has no effect otherwise. it applies to the matched client. Has no effect otherwise.
- `show-bar`:
Shows the built-in bar.
- `hide-bar`:
Hides the built-in bar.
- `toggle-bar`:
Toggles the built-in bar.
<a name="types-Status"></a> <a name="types-Status"></a>

View file

@ -854,6 +854,12 @@ SimpleActionName:
Within a window rule, it applies to the client of the window. Within a client rule Within a window rule, it applies to the client of the window. Within a client rule
it applies to the matched client. Has no effect otherwise. it applies to the matched client. Has no effect otherwise.
- value: show-bar
description: Shows the built-in bar.
- value: hide-bar
description: Hides the built-in bar.
- value: toggle-bar
description: Toggles the built-in bar.
Color: Color:
@ -2614,6 +2620,13 @@ Config:
Configures whether the default seat uses hardware cursors. Configures whether the default seat uses hardware cursors.
The default is `true`. The default is `true`.
show-bar:
kind: boolean
required: false
description: |
Configures whether the built-in bar is shown.
The default is `true`.
Idle: Idle: