diff --git a/docs/Configuration guide.md b/docs/Configuration guide.md index e8be7db..a5b77ce 100644 --- a/docs/Configuration guide.md +++ b/docs/Configuration guide.md @@ -289,9 +289,10 @@ For details on available modules and each of their config options, check the sid For information on the `Script` type, and embedding scripts in strings, see [here](script). +#### Events + | Name | Type | Default | Description | |-------------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------| -| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. | | `on_click_left` | `Script [oneshot]` | `null` | Runs the script when the module is left clicked. | | `on_click_middle` | `Script [oneshot]` | `null` | Runs the script when the module is middle clicked. | | `on_click_right` | `Script [oneshot]` | `null` | Runs the script when the module is right clicked. | @@ -299,4 +300,19 @@ For information on the `Script` type, and embedding scripts in strings, see [her | `on_scroll_down` | `Script [oneshot]` | `null` | Runs the script when the module is scrolled down on. | | `on_mouse_enter` | `Script [oneshot]` | `null` | Runs the script when the module is hovered over. | | `on_mouse_exit` | `Script [oneshot]` | `null` | Runs the script when the module is no longer hovered over. | -| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. | + +#### Visibility + + +| Name | Type | Default | Description | +|-----------------------|-------------------------------------------------------|---------------|--------------------------------------------------------------------------------------------------------------------| +| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. | +| `transition_type` | `slide_start` or `slide_end` or `crossfade` or `none` | `slide_start` | The transition animation to use when showing/hiding the widget. | +| `transition_duration` | `Integer` | `250` | The length of the transition animation to use when showing/hiding the widget. | + +#### Other + + +| Name | Type | Default | Description | +|-------------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------| +| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. | \ No newline at end of file diff --git a/docs/modules/Clipboard.md b/docs/modules/Clipboard.md index 9ad724a..876f296 100644 --- a/docs/modules/Clipboard.md +++ b/docs/modules/Clipboard.md @@ -12,6 +12,7 @@ Supports plain text and images. | Name | Type | Default | Description | |-----------------------|---------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| | `icon` | `string/image` | `󰨸` | Icon to show on the widget button. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | | `max_items` | `integer` | `10` | Maximum number of items to show in the popup. | | `truncate` | `start` or `middle` or `end` or `Map` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | | `truncate.mode` | `start` or `middle` or `end` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | diff --git a/docs/modules/Custom.md b/docs/modules/Custom.md index 9a04381..6d33749 100644 --- a/docs/modules/Custom.md +++ b/docs/modules/Custom.md @@ -15,7 +15,8 @@ It is well worth looking at the examples. There are many widget types, each with their own config options. You can think of these like HTML elements and their attributes. -Every widget has the following options available; `type` is mandatory. +Every widget has the following options available; `type` is mandatory. +You can also add common [module-level options](https://github.com/JakeStanger/ironbar/wiki/configuration-guide#32-module-level-options) on a widget. | Name | Type | Default | Description | |---------|-------------------------------------------------------------------|---------|-------------------------------| @@ -75,16 +76,17 @@ A draggable slider. Note that `on_change` will provide the **floating point** value as an argument. If your input program requires an integer, you will need to round it. -| Name | Type | Default | Description | -|---------------|----------------------------------------------------|--------------|------------------------------------------------------------------------------| -| `src` | `image` | `null` | Image source. See [here](images) for information on images. | -| `size` | `integer` | `null` | Width/height of the image. Aspect ratio is preserved. | -| `orientation` | `horizontal` or `vertical` (shorthand: `h` or `v`) | `horizontal` | Orientation of the slider. | -| `value` | `Script` | `null` | Script to run to get the slider value. Output must be a valid number. | -| `on_change` | `string [command]` | `null` | Command to execute when the slider changes. More on this [below](#commands). | -| `min` | `float` | `0` | Minimum slider value. | -| `max` | `float` | `100` | Maximum slider value. | -| `length` | `integer` | `null` | Slider length. GTK will automatically size if left unset. | +| Name | Type | Default | Description | +|---------------|----------------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------| +| `src` | `image` | `null` | Image source. See [here](images) for information on images. | +| `size` | `integer` | `null` | Width/height of the image. Aspect ratio is preserved. | +| `orientation` | `horizontal` or `vertical` (shorthand: `h` or `v`) | `horizontal` | Orientation of the slider. | +| `value` | `Script` | `null` | Script to run to get the slider value. Output must be a valid number. | +| `on_change` | `string [command]` | `null` | Command to execute when the slider changes. More on this [below](#commands). | +| `min` | `float` | `0` | Minimum slider value. | +| `max` | `float` | `100` | Maximum slider value. | +| `step` | `float` | - | The increment to change when scrolling with the mouse wheel. If left blank, will use the default determined by the environment. | +| `length` | `integer` | `null` | Slider length. GTK will automatically size if left unset. | The example slider widget below shows a volume control for MPC, which updates the server when changed, and polls the server for volume changes to keep the slider in sync. diff --git a/docs/modules/Launcher.md b/docs/modules/Launcher.md index 881e178..8b0421e 100644 --- a/docs/modules/Launcher.md +++ b/docs/modules/Launcher.md @@ -14,6 +14,7 @@ Optionally displays a launchable set of favourites. | `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher | | `show_names` | `boolean` | `false` | Whether to show app names on the button label. Names will still show on tooltips when set to false. | | `show_icons` | `boolean` | `true` | Whether to show app icons on the button. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). |
JSON diff --git a/docs/modules/Music.md b/docs/modules/Music.md index 044c816..e0579ac 100644 --- a/docs/modules/Music.md +++ b/docs/modules/Music.md @@ -27,6 +27,8 @@ in MPRIS mode, the widget will listen to all players and automatically detect/di | `icons.track` | `string/image` | `` | Icon to show next to track title. | | `icons.album` | `string/image` | `` | Icon to show next to album name. | | `icons.artist` | `string/image` | `ﴁ` | Icon to show next to artist name. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | +| `cover_image_size` | `integer` | `128` | Size to render album art image at inside popup. | | `host` | `string/image` | `localhost:6600` | [MPD Only] TCP or Unix socket for the MPD server. | | `music_dir` | `string/image` | `$HOME/Music` | [MPD Only] Path to MPD server's music directory on disc. Required for album art. | diff --git a/docs/modules/Workspaces.md b/docs/modules/Workspaces.md index 0caac3a..7509e66 100644 --- a/docs/modules/Workspaces.md +++ b/docs/modules/Workspaces.md @@ -11,6 +11,7 @@ Shows all current workspaces. Clicking a workspace changes focus to it. | Name | Type | Default | Description | |----------------|-----------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name_map` | `Map` | `{}` | A map of actual workspace names to their display labels/images. Workspaces use their actual name if not present in the map. See [here](images) for information on images. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | | `all_monitors` | `boolean` | `false` | Whether to display workspaces from all monitors. When `false`, only shows workspaces on the current monitor. | | `sort` | `added` or `alphanumeric` | `alphanumeric` | The method used for sorting workspaces. `added` always appends to the end, `alphanumeric` sorts by number/name. | diff --git a/flake.nix b/flake.nix index 43c12d6..3ce3dee 100644 --- a/flake.nix +++ b/flake.nix @@ -57,6 +57,18 @@ default = self.packages.${system}.ironbar; } ); + apps = genSystems (system: let + pkgs = pkgsFor system; + in { + default = { + type = "app"; + program = "${pkgs.ironbar}/bin/ironbar"; + }; + ironbar = { + type = "app"; + program = "${pkgs.ironbar}/bin/ironbar"; + }; + }); devShells = genSystems (system: let pkgs = pkgsFor system; rust = mkRustToolchain pkgs; diff --git a/nix/default.nix b/nix/default.nix index aacfea7..21c2f2a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -59,6 +59,6 @@ rustPlatform.buildRustPackage rec { description = "Customisable gtk-layer-shell wlroots/sway bar written in rust."; license = licenses.mit; platforms = platforms.linux; - mainProgram = "Hyprland"; + mainProgram = "ironbar"; }; } diff --git a/src/bar.rs b/src/bar.rs index bf51721..dce013c 100644 --- a/src/bar.rs +++ b/src/bar.rs @@ -190,11 +190,13 @@ fn add_modules( let popup = Popup::new(info, popup_gap); let popup = Arc::new(RwLock::new(popup)); + let orientation = info.bar_position.get_orientation(); + macro_rules! add_module { ($module:expr, $id:expr) => {{ let common = $module.common.take().expect("Common config did not exist"); let widget = create_module(*$module, $id, &info, &Arc::clone(&popup))?; - let container = wrap_widget(&widget, common); + let container = wrap_widget(&widget, common, orientation); content.add(&container); }}; } diff --git a/src/clients/clipboard.rs b/src/clients/clipboard.rs index 9eac7b2..68bbe59 100644 --- a/src/clients/clipboard.rs +++ b/src/clients/clipboard.rs @@ -59,8 +59,8 @@ impl ClipboardClient { let iter = senders.iter(); for (tx, sender_cache_size) in iter { if cache_size == *sender_cache_size { - let mut cache = lock!(cache); - let removed_id = cache + // let mut cache = lock!(cache); + let removed_id = lock!(cache) .remove_ref_first() .expect("Clipboard cache unexpectedly empty"); try_send!(tx, ClipboardEvent::Remove(removed_id)); @@ -131,8 +131,7 @@ impl ClipboardClient { } pub fn remove(&self, id: usize) { - let mut cache = lock!(self.cache); - cache.remove(id); + lock!(self.cache).remove(id); let senders = lock!(self.senders); let iter = senders.iter(); diff --git a/src/config/common.rs b/src/config/common.rs index eb65c2d..e0f97b5 100644 --- a/src/config/common.rs +++ b/src/config/common.rs @@ -3,7 +3,7 @@ use crate::script::{Script, ScriptInput}; use crate::send; use gtk::gdk::ScrollDirection; use gtk::prelude::*; -use gtk::EventBox; +use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType}; use serde::Deserialize; use tokio::spawn; use tracing::trace; @@ -13,6 +13,8 @@ use tracing::trace; #[derive(Debug, Deserialize, Clone)] pub struct CommonConfig { pub show_if: Option, + pub transition_type: Option, + pub transition_duration: Option, pub on_click_left: Option, pub on_click_right: Option, @@ -25,10 +27,36 @@ pub struct CommonConfig { pub tooltip: Option, } +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub enum TransitionType { + None, + Crossfade, + SlideStart, + SlideEnd, +} + +impl TransitionType { + pub fn to_revealer_transition_type(&self, orientation: Orientation) -> RevealerTransitionType { + match (self, orientation) { + (TransitionType::SlideStart, Orientation::Horizontal) => { + RevealerTransitionType::SlideLeft + } + (TransitionType::SlideStart, Orientation::Vertical) => RevealerTransitionType::SlideUp, + (TransitionType::SlideEnd, Orientation::Horizontal) => { + RevealerTransitionType::SlideRight + } + (TransitionType::SlideEnd, Orientation::Vertical) => RevealerTransitionType::SlideDown, + (TransitionType::Crossfade, _) => RevealerTransitionType::Crossfade, + _ => RevealerTransitionType::None, + } + } +} + impl CommonConfig { /// Configures the module's container according to the common config options. - pub fn install(mut self, container: &EventBox) { - self.install_show_if(container); + pub fn install(mut self, container: &EventBox, revealer: &Revealer) { + self.install_show_if(container, revealer); let left_click_script = self.on_click_left.map(Script::new_polling); let middle_click_script = self.on_click_middle.map(Script::new_polling); @@ -91,7 +119,7 @@ impl CommonConfig { } } - fn install_show_if(&mut self, container: &EventBox) { + fn install_show_if(&mut self, container: &EventBox, revealer: &Revealer) { self.show_if.take().map_or_else( || { container.show_all(); @@ -100,6 +128,7 @@ impl CommonConfig { let script = Script::new_polling(show_if); let container = container.clone(); let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); + spawn(async move { script .run(None, |_, success| { @@ -107,13 +136,24 @@ impl CommonConfig { }) .await; }); - rx.attach(None, move |success| { - if success { - container.show_all(); - } else { - container.hide(); - }; - Continue(true) + + { + let revealer = revealer.clone(); + let container = container.clone(); + + rx.attach(None, move |success| { + if success { + container.show_all(); + } + revealer.set_reveal_child(success); + Continue(true) + }); + } + + revealer.connect_child_revealed_notify(move |revealer| { + if !revealer.reveals_child() { + container.hide() + } }); }, ); diff --git a/src/config/mod.rs b/src/config/mod.rs index a55570d..276c262 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -22,7 +22,7 @@ use crate::modules::workspaces::WorkspacesModule; use serde::Deserialize; use std::collections::HashMap; -pub use self::common::CommonConfig; +pub use self::common::{CommonConfig, TransitionType}; pub use self::truncate::{EllipsizeMode, TruncateMode}; #[derive(Debug, Deserialize, Clone)] diff --git a/src/dynamic_string.rs b/src/dynamic_string.rs index 077e234..edfacc7 100644 --- a/src/dynamic_string.rs +++ b/src/dynamic_string.rs @@ -88,9 +88,13 @@ impl DynamicString { let mut chars = input.chars().collect::>(); while !chars.is_empty() { - let char_pair = &chars[..=1]; + let char_pair = if chars.len() > 1 { + Some(&chars[..=1]) + } else { + None + }; - let (token, skip) = if let ['{', '{'] = char_pair { + let (token, skip) = if let Some(['{', '{']) = char_pair { const SKIP_BRACKETS: usize = 4; // two braces either side let str = chars diff --git a/src/main.rs b/src/main.rs index e6d41ca..5fadbec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,10 +60,10 @@ async fn main() -> Result<()> { |display| display, ); - let config_res = match env::var("IRONBAR_CONFIG") { - Ok(path) => ConfigLoader::load(path), - Err(_) => ConfigLoader::new("ironbar").find_and_load(), - }; + let config_res = env::var("IRONBAR_CONFIG").map_or_else( + |_| ConfigLoader::new("ironbar").find_and_load(), + ConfigLoader::load, + ); let config = match config_res { Ok(config) => config, diff --git a/src/modules/clipboard.rs b/src/modules/clipboard.rs index 8307fe5..5045a1a 100644 --- a/src/modules/clipboard.rs +++ b/src/modules/clipboard.rs @@ -21,6 +21,9 @@ pub struct ClipboardModule { #[serde(default = "default_icon")] icon: String, + #[serde(default = "default_icon_size")] + icon_size: i32, + #[serde(default = "default_max_items")] max_items: usize, @@ -35,6 +38,10 @@ fn default_icon() -> String { String::from("󰨸") } +const fn default_icon_size() -> i32 { + 32 +} + const fn default_max_items() -> usize { 10 } @@ -120,7 +127,7 @@ impl Module