mirror of
https://github.com/JakeStanger/ironbar.git
synced 2024-11-29 21:16:00 +03:00
Merge pull request #147 from yavko/add-always-workspaces
feat: Add favorite and hidden workspaces
This commit is contained in:
commit
50741941fb
579
Cargo.lock
generated
579
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -131,7 +131,7 @@ zbus = { version = "3.14.1", optional = true }
|
||||
|
||||
# workspaces
|
||||
swayipc-async = { version = "2.0.1", optional = true }
|
||||
hyprland = { version = "0.3.8", optional = true }
|
||||
hyprland = { version = "0.3.8", features = ["silent"], optional = true }
|
||||
futures-util = { version = "0.3.21", optional = true }
|
||||
|
||||
# shared
|
||||
|
@ -8,12 +8,14 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
|
||||
|
||||
> Type: `workspaces`
|
||||
|
||||
| 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. |
|
||||
| `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. |
|
||||
| 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. |
|
||||
| `favorites` | `Map<string, string[]>` or `string[]` | `[]` | Workspaces to always show. This can be for all monitors, or a map to set per monitor. |
|
||||
| `hidden` | `string[]` | `[]` | A list of workspace names to never show |
|
||||
| `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>
|
||||
<summary>JSON</summary>
|
||||
@ -28,6 +30,7 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
|
||||
"2": "",
|
||||
"3": ""
|
||||
},
|
||||
"favorites": ["1", "2", "3"],
|
||||
"all_monitors": false
|
||||
}
|
||||
]
|
||||
@ -43,6 +46,7 @@ Shows all current workspaces. Clicking a workspace changes focus to it.
|
||||
[[end]]
|
||||
type = "workspaces"
|
||||
all_monitors = false
|
||||
favorites = ["1", "2", "3"]
|
||||
|
||||
[[end.name_map]]
|
||||
1 = ""
|
||||
@ -63,6 +67,10 @@ end:
|
||||
1: ""
|
||||
2: ""
|
||||
3: ""
|
||||
favorites:
|
||||
- "1"
|
||||
- "2"
|
||||
- "3"
|
||||
all_monitors: false
|
||||
```
|
||||
|
||||
@ -79,6 +87,7 @@ end:
|
||||
name_map.1 = ""
|
||||
name_map.2 = ""
|
||||
name_map.3 = ""
|
||||
favorites = [ "1" "2" "3" ]
|
||||
all_monitors = false
|
||||
}
|
||||
]
|
||||
@ -98,4 +107,4 @@ end:
|
||||
| `.workspaces .item .text-icon` | Workspace button icon (textual 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
|
||||
];
|
||||
};
|
||||
mkRustToolchain = pkgs: pkgs.rust-bin.stable.latest.default;
|
||||
mkRustToolchain = pkgs:
|
||||
pkgs.rust-bin.stable.latest.default.override {
|
||||
extensions = ["rust-src"];
|
||||
};
|
||||
in {
|
||||
overlays.default = final: prev: let
|
||||
rust = mkRustToolchain final;
|
||||
@ -116,6 +119,14 @@
|
||||
gtk-layer-shell
|
||||
pkg-config
|
||||
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";
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::clients::compositor::{Compositor, WorkspaceUpdate};
|
||||
use crate::clients::compositor::{Compositor, Workspace, WorkspaceUpdate};
|
||||
use crate::config::CommonConfig;
|
||||
use crate::image::new_icon_button;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
@ -8,7 +8,7 @@ use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme};
|
||||
use serde::Deserialize;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
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)]
|
||||
pub struct WorkspacesModule {
|
||||
/// Map of actual workspace names to custom names.
|
||||
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.
|
||||
#[serde(default = "crate::config::default_false")]
|
||||
all_monitors: bool,
|
||||
@ -56,6 +77,7 @@ const fn default_icon_size() -> i32 {
|
||||
fn create_button(
|
||||
name: &str,
|
||||
focused: bool,
|
||||
inactive: bool,
|
||||
name_map: &HashMap<String, String>,
|
||||
icon_theme: &IconTheme,
|
||||
icon_size: i32,
|
||||
@ -71,6 +93,8 @@ fn create_button(
|
||||
|
||||
if 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 {
|
||||
type SendMessage = WorkspaceUpdate;
|
||||
type ReceiveMessage = String;
|
||||
@ -157,7 +188,9 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
) -> Result<ModuleParts<gtk::Box>> {
|
||||
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();
|
||||
|
||||
@ -176,19 +209,49 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
WorkspaceUpdate::Init(workspaces) => {
|
||||
if !has_initialized {
|
||||
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) => {
|
||||
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 item = create_button(
|
||||
&name,
|
||||
workspace.focused,
|
||||
false,
|
||||
&name_map,
|
||||
&icon_theme,
|
||||
icon_size,
|
||||
@ -236,12 +305,13 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
}
|
||||
}
|
||||
WorkspaceUpdate::Move(workspace) => {
|
||||
if !self.all_monitors {
|
||||
if !self.hidden.contains(&workspace.name) && !self.all_monitors {
|
||||
if workspace.monitor == output_name {
|
||||
let name = workspace.name;
|
||||
let item = create_button(
|
||||
&name,
|
||||
workspace.focused,
|
||||
false,
|
||||
&name_map,
|
||||
&icon_theme,
|
||||
icon_size,
|
||||
@ -267,7 +337,11 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
WorkspaceUpdate::Remove(workspace) => {
|
||||
let button = button_map.get(&workspace);
|
||||
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(_) => {}
|
||||
|
Loading…
Reference in New Issue
Block a user