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:
parent
7e877f6631
commit
9f65cf293d
4 changed files with 458 additions and 267 deletions
579
Cargo.lock
generated
579
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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).
|
||||||
|
|
13
flake.nix
13
flake.nix
|
@ -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";
|
||||||
|
|
|
@ -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: >k::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(_) => {}
|
||||||
|
|
Loading…
Add table
Reference in a new issue