1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-04-19 19:34:24 +02:00

feat(workspaces): add favorites and hidden options

This commit is contained in:
yavko 2023-05-09 02:05:26 -07:00 committed by Jake Stanger
parent 7e877f6631
commit 9f65cf293d
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
4 changed files with 458 additions and 267 deletions

579
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -8,12 +8,14 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
> Type: `workspaces` > Type: `workspaces`
| Name | Type | Default | Description | | Name | Type | Default | Description |
|----------------|--------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------------|---------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name_map` | `Map<string, string or image>` | `{}` | 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. | | `name_map` | `Map<string, string or image>` | `{}` | 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). | | `favorites` | `Map<string, string[]>` or `string[]` | `[]` | Workspaces to always show. This can be for all monitors, or a map to set per monitor. |
| `all_monitors` | `boolean` | `false` | Whether to display workspaces from all monitors. When `false`, only shows workspaces on the current monitor. | | `hidden` | `string[]` | `[]` | A list of workspace names to never show |
| `sort` | `'added'` or `'alphanumeric'` | `alphanumeric` | The method used for sorting workspaces. `added` always appends to the end, `alphanumeric` sorts by number/name. | | `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. |
<details> <details>
<summary>JSON</summary> <summary>JSON</summary>
@ -28,6 +30,7 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
"2": "", "2": "",
"3": "" "3": ""
}, },
"favorites": ["1", "2", "3"],
"all_monitors": false "all_monitors": false
} }
] ]
@ -43,6 +46,7 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
[[end]] [[end]]
type = "workspaces" type = "workspaces"
all_monitors = false all_monitors = false
favorites = ["1", "2", "3"]
[[end.name_map]] [[end.name_map]]
1 = "" 1 = ""
@ -63,6 +67,10 @@ end:
1: "" 1: ""
2: "" 2: ""
3: "" 3: ""
favorites:
- "1"
- "2"
- "3"
all_monitors: false all_monitors: false
``` ```
@ -79,6 +87,7 @@ end:
name_map.1 = "" name_map.1 = ""
name_map.2 = "" name_map.2 = ""
name_map.3 = "" name_map.3 = ""
favorites = [ "1" "2" "3" ]
all_monitors = false all_monitors = false
} }
] ]
@ -98,4 +107,4 @@ end:
| `.workspaces .item .text-icon` | Workspace button icon (textual only) | | `.workspaces .item .text-icon` | Workspace button icon (textual only) |
| `.workspaces .item .image` | Workspace button icon (image only) | | `.workspaces .item .image` | Workspace button icon (image only) |
For more information on styling, please see the [styling guide](styling-guide). For more information on styling, please see the [styling guide](styling-guide).

View file

@ -34,7 +34,10 @@
rust-overlay.overlays.default rust-overlay.overlays.default
]; ];
}; };
mkRustToolchain = pkgs: pkgs.rust-bin.stable.latest.default; mkRustToolchain = pkgs:
pkgs.rust-bin.stable.latest.default.override {
extensions = ["rust-src"];
};
in { in {
overlays.default = final: prev: let overlays.default = final: prev: let
rust = mkRustToolchain final; rust = mkRustToolchain final;
@ -116,6 +119,14 @@
gtk-layer-shell gtk-layer-shell
pkg-config pkg-config
openssl openssl
gdk-pixbuf
glib
glib-networking
shared-mime-info
gnome.adwaita-icon-theme
hicolor-icon-theme
gsettings-desktop-schemas
libxkbcommon
]; ];
RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library"; RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library";

View file

@ -1,4 +1,4 @@
use crate::clients::compositor::{Compositor, WorkspaceUpdate}; use crate::clients::compositor::{Compositor, Workspace, WorkspaceUpdate};
use crate::config::CommonConfig; use crate::config::CommonConfig;
use crate::image::new_icon_button; use crate::image::new_icon_button;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
@ -8,7 +8,7 @@ use gtk::prelude::*;
use gtk::{Button, IconTheme}; use gtk::{Button, IconTheme};
use serde::Deserialize; use serde::Deserialize;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use tokio::spawn; use tokio::spawn;
use tokio::sync::mpsc::{Receiver, Sender}; use tokio::sync::mpsc::{Receiver, Sender};
use tracing::trace; use tracing::trace;
@ -29,11 +29,32 @@ impl Default for SortOrder {
} }
} }
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
pub enum Favorites {
ByMonitor(HashMap<String, Vec<String>>),
Global(Vec<String>),
}
impl Default for Favorites {
fn default() -> Self {
Self::Global(vec![])
}
}
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct WorkspacesModule { pub struct WorkspacesModule {
/// Map of actual workspace names to custom names. /// Map of actual workspace names to custom names.
name_map: Option<HashMap<String, String>>, name_map: Option<HashMap<String, String>>,
/// Array of always shown workspaces, and what monitor to show on
#[serde(default)]
favorites: Favorites,
/// List of workspace names to never show
#[serde(default)]
hidden: Vec<String>,
/// Whether to display buttons for all monitors. /// Whether to display buttons for all monitors.
#[serde(default = "crate::config::default_false")] #[serde(default = "crate::config::default_false")]
all_monitors: bool, all_monitors: bool,
@ -56,6 +77,7 @@ const fn default_icon_size() -> i32 {
fn create_button( fn create_button(
name: &str, name: &str,
focused: bool, focused: bool,
inactive: bool,
name_map: &HashMap<String, String>, name_map: &HashMap<String, String>,
icon_theme: &IconTheme, icon_theme: &IconTheme,
icon_size: i32, icon_size: i32,
@ -71,6 +93,8 @@ fn create_button(
if focused { if focused {
style_context.add_class("focused"); style_context.add_class("focused");
} else if inactive {
style_context.add_class("inactive");
} }
{ {
@ -105,6 +129,13 @@ fn reorder_workspaces(container: &gtk::Box) {
} }
} }
impl WorkspacesModule {
fn show_workspace_check(&self, output: &String, work: &Workspace) -> bool {
(work.focused || !self.hidden.contains(&work.name))
&& (self.all_monitors || output == &work.monitor)
}
}
impl Module<gtk::Box> for WorkspacesModule { impl Module<gtk::Box> for WorkspacesModule {
type SendMessage = WorkspaceUpdate; type SendMessage = WorkspaceUpdate;
type ReceiveMessage = String; type ReceiveMessage = String;
@ -157,7 +188,9 @@ impl Module<gtk::Box> for WorkspacesModule {
) -> Result<ModuleParts<gtk::Box>> { ) -> Result<ModuleParts<gtk::Box>> {
let container = gtk::Box::new(info.bar_position.get_orientation(), 0); let container = gtk::Box::new(info.bar_position.get_orientation(), 0);
let name_map = self.name_map.unwrap_or_default(); let name_map = self.name_map.clone().unwrap_or_default();
let favs = self.favorites.clone();
let mut fav_names: Vec<String> = vec![];
let mut button_map: HashMap<String, Button> = HashMap::new(); let mut button_map: HashMap<String, Button> = HashMap::new();
@ -176,19 +209,49 @@ impl Module<gtk::Box> for WorkspacesModule {
WorkspaceUpdate::Init(workspaces) => { WorkspaceUpdate::Init(workspaces) => {
if !has_initialized { if !has_initialized {
trace!("Creating workspace buttons"); trace!("Creating workspace buttons");
for workspace in workspaces {
if self.all_monitors || workspace.monitor == output_name {
let item = create_button(
&workspace.name,
workspace.focused,
&name_map,
&icon_theme,
icon_size,
&context.controller_tx,
);
container.add(&item);
button_map.insert(workspace.name, item); let mut added = HashSet::new();
let mut add_workspace = |name: &str, focused: bool| {
let item = create_button(
name,
focused,
false,
&name_map,
&icon_theme,
icon_size,
&context.controller_tx,
);
container.add(&item);
button_map.insert(name.to_string(), item);
};
// add workspaces from client
for workspace in &workspaces {
if self.show_workspace_check(&output_name, workspace) {
add_workspace(&workspace.name, workspace.focused);
added.insert(workspace.name.to_string());
}
}
let mut add_favourites = |names: &Vec<String>| {
for name in names {
if !added.contains(name) {
add_workspace(name, false);
added.insert(name.to_string());
fav_names.push(name.to_string());
}
}
};
// add workspaces from favourites
match &favs {
Favorites::Global(names) => add_favourites(names),
Favorites::ByMonitor(map) => {
if let Some(to_add) = map.get(&output_name) {
add_favourites(to_add);
}
} }
} }
@ -212,11 +275,17 @@ impl Module<gtk::Box> for WorkspacesModule {
} }
} }
WorkspaceUpdate::Add(workspace) => { WorkspaceUpdate::Add(workspace) => {
if self.all_monitors || workspace.monitor == output_name { if fav_names.contains(&workspace.name) {
let btn = button_map.get(&workspace.name);
if let Some(btn) = btn {
btn.style_context().remove_class("inactive");
}
} else if self.show_workspace_check(&output_name, &workspace) {
let name = workspace.name; let name = workspace.name;
let item = create_button( let item = create_button(
&name, &name,
workspace.focused, workspace.focused,
false,
&name_map, &name_map,
&icon_theme, &icon_theme,
icon_size, icon_size,
@ -236,12 +305,13 @@ impl Module<gtk::Box> for WorkspacesModule {
} }
} }
WorkspaceUpdate::Move(workspace) => { WorkspaceUpdate::Move(workspace) => {
if !self.all_monitors { if !self.hidden.contains(&workspace.name) && !self.all_monitors {
if workspace.monitor == output_name { if workspace.monitor == output_name {
let name = workspace.name; let name = workspace.name;
let item = create_button( let item = create_button(
&name, &name,
workspace.focused, workspace.focused,
false,
&name_map, &name_map,
&icon_theme, &icon_theme,
icon_size, icon_size,
@ -267,7 +337,11 @@ impl Module<gtk::Box> for WorkspacesModule {
WorkspaceUpdate::Remove(workspace) => { WorkspaceUpdate::Remove(workspace) => {
let button = button_map.get(&workspace); let button = button_map.get(&workspace);
if let Some(item) = button { if let Some(item) = button {
container.remove(item); if fav_names.contains(&workspace) {
item.style_context().add_class("inactive");
} else {
container.remove(item);
}
} }
} }
WorkspaceUpdate::Update(_) => {} WorkspaceUpdate::Update(_) => {}