From 44fd480c786fd2e945b7983af34e892d68d39bf6 Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Fri, 25 Apr 2025 13:42:33 -0300 Subject: [PATCH] :sparkles: ags(bar/special-workspaces): add support for hyprland special workspaces --- ags/style/_bar.scss | 11 ++++++-- ags/widget/bar/SpecialWorkspaces.ts | 40 +++++++++++++++++++++++++++++ ags/window/Bar.ts | 2 ++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 ags/widget/bar/SpecialWorkspaces.ts diff --git a/ags/style/_bar.scss b/ags/style/_bar.scss index 04fce02..6b7ece1 100644 --- a/ags/style/_bar.scss +++ b/ags/style/_bar.scss @@ -1,6 +1,7 @@ @use "sass:color"; @use "./mixins"; @use "./colors"; +@use "./wal"; .bar-container { @include mixins.reset-props; @@ -27,7 +28,7 @@ & > eventbox { &:hover { - & > box:not(.workspaces) { + & > box:not(.workspaces):not(.special-workspaces) { background: $color-hover; } } @@ -50,7 +51,7 @@ } } - .workspaces { + .workspaces, .special-workspaces { @include mixins.reset-props; & button { @@ -88,6 +89,12 @@ font-size: 16px; } } + + &.special-workspaces { + & button { + background: wal.$color4; + } + } } .focused-client { diff --git a/ags/widget/bar/SpecialWorkspaces.ts b/ags/widget/bar/SpecialWorkspaces.ts new file mode 100644 index 0000000..8d2781d --- /dev/null +++ b/ags/widget/bar/SpecialWorkspaces.ts @@ -0,0 +1,40 @@ +import { bind, Variable } from "astal"; +import { Gtk, Widget } from "astal/gtk3" +import AstalHyprland from "gi://AstalHyprland"; +import { getAppIcon } from "../../scripts/apps"; + +export const SpecialWorkspaces: (() => Gtk.Widget) = () => new Widget.EventBox({ + className: "special-ws-eventbox", + visible: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) => + workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).length > 0), + child: new Widget.Box({ + className: "special-workspaces", + children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) => + workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).map((workspace) => + new Widget.Button({ + className: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusWs => + `${focusWs.id === workspace.id ? "focus" : ""}`), + tooltipText: bind(workspace, "name").as((name) => { + name = name.replace(/^special\:/, ""); + return name.charAt(0).toUpperCase().concat(name.substring(1, name.length)); + }), + child: new Widget.Icon({ + className: "last-app-icon", + visible: Variable.derive([ + bind(workspace, "lastClient"), + bind(AstalHyprland.get_default(), "focusedWorkspace") + ], (lastClient, focusedWorkspace) => focusedWorkspace?.id === workspace.id ? + false : Boolean(lastClient))(), + icon: bind(workspace, "lastClient").as((lastClient) => + lastClient ? + getAppIcon(lastClient.initialClass) || "image-missing" + : "image-missing") + } as Widget.IconProps), + onClicked: () => AstalHyprland.get_default().dispatch( + "togglespecialworkspace", workspace.name.replace(/^special\:/, "") + ) + } as Widget.ButtonProps) + ) + ) + } as Widget.BoxProps) +} as Widget.EventBoxProps); diff --git a/ags/window/Bar.ts b/ags/window/Bar.ts index d10d5b9..2ecea2b 100644 --- a/ags/window/Bar.ts +++ b/ags/window/Bar.ts @@ -7,6 +7,7 @@ import { Media } from "../widget/bar/Media"; import { Apps } from "../widget/bar/Apps"; import { Clock } from "../widget/bar/Clock"; import { Status } from "../widget/bar/Status"; +import { SpecialWorkspaces } from "../widget/bar/SpecialWorkspaces"; export const Bar = (mon: number) => { const widgetSpacing = 4; @@ -32,6 +33,7 @@ export const Bar = (mon: number) => { spacing: widgetSpacing, children: [ Apps(), + SpecialWorkspaces(), Workspaces(), FocusedClient() ]