1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-07-01 10:41:03 +02:00

Merge pull request #372 from JakeStanger/feat/auto-hide

feat: bar auto-hide options
This commit is contained in:
Jake Stanger 2023-12-11 21:37:55 +00:00 committed by GitHub
commit 9a7ee6babc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 27 deletions

View file

@ -271,22 +271,24 @@ Check [here](config) for an example config file for a fully configured bar in ea
The following table lists each of the top-level bar config options: The following table lists each of the top-level bar config options:
| Name | Type | Default | Description | | Name | Type | Default | Description |
|--------------------|----------------------------------------|-----------|-----------------------------------------------------------------------------------------------------------------| |--------------------|----------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` | `bar-<n>` | A unique identifier for the bar, used for controlling it over IPC. If not set, uses a generated integer suffix. | | `name` | `string` | `bar-<n>` | A unique identifier for the bar, used for controlling it over IPC. If not set, uses a generated integer suffix. |
| `position` | `top` or `bottom` or `left` or `right` | `bottom` | The bar's position on screen. | | `position` | `top` or `bottom` or `left` or `right` | `bottom` | The bar's position on screen. |
| `anchor_to_edges` | `boolean` | `false` | Whether to anchor the bar to the edges of the screen. Setting to false centres the bar. | | `anchor_to_edges` | `boolean` | `false` | Whether to anchor the bar to the edges of the screen. Setting to false centres the bar. |
| `height` | `integer` | `42` | The bar's height in pixels. | | `height` | `integer` | `42` | The bar's height in pixels. |
| `popup_gap` | `integer` | `5` | The gap between the bar and popup window. | | `popup_gap` | `integer` | `5` | The gap between the bar and popup window. |
| `margin.top` | `integer` | `0` | The margin on the top of the bar | | `margin.top` | `integer` | `0` | The margin on the top of the bar |
| `margin.bottom` | `integer` | `0` | The margin on the bottom of the bar | | `margin.bottom` | `integer` | `0` | The margin on the bottom of the bar |
| `margin.left` | `integer` | `0` | The margin on the left of the bar | | `margin.left` | `integer` | `0` | The margin on the left of the bar |
| `margin.right` | `integer` | `0` | The margin on the right of the bar | | `margin.right` | `integer` | `0` | The margin on the right of the bar |
| `icon_theme` | `string` | `null` | Name of the GTK icon theme to use. Leave blank to use default. | | `icon_theme` | `string` | `null` | Name of the GTK icon theme to use. Leave blank to use default. |
| `ironvar_defaults` | `Map<string, string>` | `{}` | Map of [ironvar](ironvars) keys against their default values. | | `ironvar_defaults` | `Map<string, string>` | `{}` | Map of [ironvar](ironvars) keys against their default values. |
| `start` | `Module[]` | `[]` | Array of left or top modules. | | `start_hidden` | `boolean` | `false`, or `true` if `autohide` set | Whether the bar should be hidden when the application starts. Enabled by default when `autohide` is set. |
| `center` | `Module[]` | `[]` | Array of center modules. | | `autohide` | `integer` | `null` | The duration in milliseconds before the bar is hidden after the cursor leaves. Leave unset to disable auto-hide behaviour. |
| `end` | `Module[]` | `[]` | Array of right or bottom modules. | | `start` | `Module[]` | `[]` | Array of left or top modules. |
| `center` | `Module[]` | `[]` | Array of center modules. |
| `end` | `Module[]` | `[]` | Array of right or bottom modules. |
### 3.2 Module-level options ### 3.2 Module-level options

View file

@ -7,9 +7,10 @@ use crate::{Config, Ironbar};
use color_eyre::Result; use color_eyre::Result;
use gtk::gdk::Monitor; use gtk::gdk::Monitor;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, IconTheme, Orientation}; use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType};
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration;
use tracing::{debug, info}; use tracing::{debug, info};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -37,7 +38,11 @@ pub struct Bar {
impl Bar { impl Bar {
pub fn new(app: &Application, monitor_name: String, config: Config) -> Self { pub fn new(app: &Application, monitor_name: String, config: Config) -> Self {
let window = ApplicationWindow::builder().application(app).build(); let window = ApplicationWindow::builder()
.application(app)
.type_(WindowType::Toplevel)
.build();
let name = config let name = config
.name .name
.clone() .clone()
@ -108,11 +113,36 @@ impl Bar {
self.name, self.monitor_name self.name, self.monitor_name
); );
self.setup_layer_shell(config.anchor_to_edges, config.margin, monitor); self.setup_layer_shell(
&self.window,
true,
config.anchor_to_edges,
config.margin,
monitor,
);
let start_hidden = config.start_hidden.unwrap_or(config.autohide.is_some());
if let Some(autohide) = config.autohide {
let hotspot_window = Window::new(WindowType::Toplevel);
Self::setup_autohide(&self.window, &hotspot_window, autohide);
self.setup_layer_shell(
&hotspot_window,
false,
config.anchor_to_edges,
config.margin,
monitor,
);
if start_hidden {
hotspot_window.show();
}
}
let load_result = self.load_modules(config, monitor)?; let load_result = self.load_modules(config, monitor)?;
self.show(); self.show(!start_hidden);
self.inner = Inner::Loaded { self.inner = Inner::Loaded {
popup: load_result.popup, popup: load_result.popup,
@ -121,16 +151,25 @@ impl Bar {
} }
/// Sets up GTK layer shell for a provided application window. /// Sets up GTK layer shell for a provided application window.
fn setup_layer_shell(&self, anchor_to_edges: bool, margin: MarginConfig, monitor: &Monitor) { fn setup_layer_shell(
let win = &self.window; &self,
win: &impl IsA<Window>,
exclusive_zone: bool,
anchor_to_edges: bool,
margin: MarginConfig,
monitor: &Monitor,
) {
let position = self.position; let position = self.position;
gtk_layer_shell::init_for_window(win); gtk_layer_shell::init_for_window(win);
gtk_layer_shell::set_monitor(win, monitor); gtk_layer_shell::set_monitor(win, monitor);
gtk_layer_shell::set_layer(win, gtk_layer_shell::Layer::Top); gtk_layer_shell::set_layer(win, gtk_layer_shell::Layer::Top);
gtk_layer_shell::auto_exclusive_zone_enable(win);
gtk_layer_shell::set_namespace(win, env!("CARGO_PKG_NAME")); gtk_layer_shell::set_namespace(win, env!("CARGO_PKG_NAME"));
if exclusive_zone {
gtk_layer_shell::auto_exclusive_zone_enable(win);
}
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Top, margin.top); gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Top, margin.top);
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Bottom, margin.bottom); gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Bottom, margin.bottom);
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Left, margin.left); gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Left, margin.left);
@ -164,6 +203,40 @@ impl Bar {
); );
} }
fn setup_autohide(window: &ApplicationWindow, hotspot_window: &Window, timeout: u64) {
hotspot_window.hide();
hotspot_window.set_opacity(0.0);
hotspot_window.set_decorated(false);
hotspot_window.set_size_request(0, 1);
{
let hotspot_window = hotspot_window.clone();
window.connect_leave_notify_event(move |win, _| {
let win = win.clone();
let hotspot_window = hotspot_window.clone();
glib::timeout_add_local_once(Duration::from_millis(timeout), move || {
win.hide();
hotspot_window.show();
});
Inhibit(false)
});
}
{
let win = window.clone();
hotspot_window.connect_enter_notify_event(move |hotspot_win, _| {
hotspot_win.hide();
win.show();
Inhibit(false)
});
}
}
/// Loads the configured modules onto a bar. /// Loads the configured modules onto a bar.
fn load_modules(&self, config: Config, monitor: &Monitor) -> Result<BarLoadResult> { fn load_modules(&self, config: Config, monitor: &Monitor) -> Result<BarLoadResult> {
let icon_theme = IconTheme::new(); let icon_theme = IconTheme::new();
@ -210,7 +283,7 @@ impl Bar {
Ok(result) Ok(result)
} }
fn show(&self) { fn show(&self, include_window: bool) {
debug!("Showing bar: {}", self.name); debug!("Showing bar: {}", self.name);
// show each box but do not use `show_all`. // show each box but do not use `show_all`.
@ -219,7 +292,10 @@ impl Bar {
self.center.show(); self.center.show();
self.end.show(); self.end.show();
self.content.show(); self.content.show();
self.window.show();
if include_window {
self.window.show();
}
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {

View file

@ -99,6 +99,11 @@ pub struct Config {
pub popup_gap: i32, pub popup_gap: i32,
pub name: Option<String>, pub name: Option<String>,
#[serde(default)]
pub start_hidden: Option<bool>,
#[serde(default)]
pub autohide: Option<u64>,
/// GTK icon theme to use. /// GTK icon theme to use.
pub icon_theme: Option<String>, pub icon_theme: Option<String>,
@ -127,6 +132,8 @@ impl Default for Config {
height: default_bar_height(), height: default_bar_height(),
margin: MarginConfig::default(), margin: MarginConfig::default(),
name: None, name: None,
start_hidden: None,
autohide: None,
popup_gap: default_popup_gap(), popup_gap: default_popup_gap(),
icon_theme: None, icon_theme: None,
ironvar_defaults: None, ironvar_defaults: None,

View file

@ -21,7 +21,6 @@ use glib::PropertySet;
use gtk::gdk::Display; use gtk::gdk::Display;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::Application; use gtk::Application;
use lazy_static::lazy_static;
use tokio::runtime::Handle; use tokio::runtime::Handle;
use tokio::task::{block_in_place, spawn_blocking}; use tokio::task::{block_in_place, spawn_blocking};
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
@ -93,7 +92,7 @@ async fn run_with_args() {
static COUNTER: AtomicUsize = AtomicUsize::new(1); static COUNTER: AtomicUsize = AtomicUsize::new(1);
#[cfg(feature = "ipc")] #[cfg(feature = "ipc")]
lazy_static! { lazy_static::lazy_static! {
static ref VARIABLE_MANAGER: Arc<RwLock<VariableManager>> = arc_rw!(VariableManager::new()); static ref VARIABLE_MANAGER: Arc<RwLock<VariableManager>> = arc_rw!(VariableManager::new());
} }