From 88129a8f9747ec648dcd082b3b507d1703bd5614 Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Tue, 13 May 2025 15:06:14 -0300 Subject: [PATCH] :zap: ags(workspaces, arg-handler): drop variable on ::destroy, better help messages changed `show-ws-numbers` command to `peek-workspace-num` --- ags/scripts/arg-handler.ts | 52 ++++++++++++----------- ags/widget/bar/Workspaces.ts | 80 +++++++++++++++++++++--------------- hypr/shell/bindings.conf | 5 ++- 3 files changed, 76 insertions(+), 61 deletions(-) diff --git a/ags/scripts/arg-handler.ts b/ags/scripts/arg-handler.ts index fa81ff0..a83ceef 100644 --- a/ags/scripts/arg-handler.ts +++ b/ags/scripts/arg-handler.ts @@ -2,10 +2,11 @@ import { Wireplumber } from "./volume"; import { Windows } from "../windows"; import { restartInstance } from "./reload-handler"; -import { showWorkspaceNumbers } from "../widget/bar/Workspaces"; -import { timeout } from "astal"; +import { AstalIO, timeout } from "astal"; import { Runner } from "../runner/Runner"; +import { showWorkspaceNumber } from "../widget/bar/Workspaces"; +let wsTimeout: (AstalIO.Time|undefined); export function handleArguments(request: string): any { const args: Array = request.split(" "); @@ -36,12 +37,15 @@ export function handleArguments(request: string): any { : Runner.close(); return "Opening runner..." - case "show-ws-numbers": - if(!showWorkspaceNumbers.get()) { - showWorkspaceNumbers.set(true); - timeout(2200, () => showWorkspaceNumbers.set(false)); - } - return "Showing numbers"; + case "peek-workspace-num": + if(wsTimeout) return "Workspace numbers are already showing"; + + showWorkspaceNumber(true); + wsTimeout = timeout(2200, () => { + showWorkspaceNumber(false); + wsTimeout = undefined; + }); + return "Toggled workspace numbers"; default: return "command not found! try checking help"; @@ -141,14 +145,10 @@ function handleVolumeArgs(args: Array) { return ` Control speaker and microphone volumes easily! Options: - sink-set [number]: set sink(speaker) volume with [number], 0 to ${Wireplumber.getDefault().getMaxSinkVolume() || 100}. - sink-mute: toggle mute for the sink(speaker) device. - sink-increase [number]: increases sink(speaker) volume with [number]. - sink-decrease [number]: decreases sink(speaker) volume with [number]. - source-set [number]: set source(microphone) volume with [number], 0 to ${Wireplumber.getDefault().getMaxSourceVolume() || 100}. - source-mute: toggle mute for the source(microphone) device. - source-increase [number]: increases source(microphone) volume with [number]. - source-decrease [number]: decreases source(microphone) volume with [number] + (sink|source)-set [number]: set speaker/microphone volume. + (sink|source)-mute: toggle mute for the speaker/microphone device. + (sink|source)-increase [number]: increases speaker/microphone volume. + (sink|source)-decrease [number]: decreases speaker/microphone volume. `.trim(); } } @@ -157,16 +157,18 @@ function getHelp(): string { return `Manage Astal Windows and do more stuff. From retrozinndev's Hyprland Dots, using Astal and AGS by Aylur. - Options: - open [window_name]: sets specified window's visibility to true. - close [window_name]: sets specified window's visibility to false. - toggle [window_name]: toggles visibility of specified window. - windows: shows available windows to control. - reload: creates a new astal instance and removes this one. - volume: wireplumber volume controller, see "volume help". - runner [initial_text]: open the application runner. - show-ws-numbers: show or hide workspace numbers in bar. + Window and Audio options: + open [window]: opens the specified window. + close [window]: closes all instances of specified window. + toggle [window]: toggle-open/close the specified window. + windows: list shell windows. + reload: quit this instance and start a new one. + volume: speaker and microphone volume controller, see "volume help". h, help: shows this help message. + + Other options: + runner [initial_text]: open the application runner, optionally add an initial search. + peek-workspace-num: peek the workspace numbers on bar window. 2025 (c) retrozinndev's Hyprland-Dots, licensed under the MIT License. https://github.com/retrozinndev/Hyprland-Dots diff --git a/ags/widget/bar/Workspaces.ts b/ags/widget/bar/Workspaces.ts index 0847762..25b4523 100644 --- a/ags/widget/bar/Workspaces.ts +++ b/ags/widget/bar/Workspaces.ts @@ -3,50 +3,62 @@ import { Gtk, Widget } from "astal/gtk3"; import AstalHyprland from "gi://AstalHyprland"; import { getAppIcon } from "../../scripts/apps"; -const hyprland = AstalHyprland.get_default(); -export const showWorkspaceNumbers = new Variable(false); +let showWsNum: (Variable|undefined); +export const showWorkspaceNumber = (show: boolean) => + showWsNum?.set(show); + export function Workspaces(): Gtk.Widget { - - const workspaceSpacing = 4; + showWsNum = new Variable(false); return new Widget.EventBox({ onScroll: (_, event) => - event.delta_y > 0 ? hyprland.dispatch("workspace", "e-1") : hyprland.dispatch("workspace", "e+1"), - onHover: () => showWorkspaceNumbers.set(true), - onHoverLost: () => showWorkspaceNumbers.set(false), + event.delta_y > 0 ? + AstalHyprland.get_default().dispatch("workspace", "e-1") + : AstalHyprland.get_default().dispatch("workspace", "e+1"), + onHover: () => showWorkspaceNumber(true), + onHoverLost: () => showWorkspaceNumber(false), + onDestroy: () => { + showWsNum?.drop(); + showWsNum = undefined; + }, child: new Widget.Box({ className: "workspaces", - spacing: workspaceSpacing, - children: bind(hyprland, "workspaces").as((workspaces) => { - const sortedWorkspaces = workspaces.filter(ws => ws.id > 0).sort( - (a: AstalHyprland.Workspace, b: AstalHyprland.Workspace) => a.get_id() - b.get_id()); + spacing: 4, + children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) => + workspaces.filter((ws) => ws.id > 0).sort((a, b) => a.id - b.id).map((workspace) => { + const className = Variable.derive([ + bind(AstalHyprland.get_default(), "focusedWorkspace"), + showWsNum!() + ], (focusedWs, showWsNumbers) => + `${focusedWs.id === workspace.id ? "focus" : ""} ${showWsNumbers ? "show" : ""}` + ); - return sortedWorkspaces.map((workspace: AstalHyprland.Workspace) => - new Widget.EventBox({ - className: Variable.derive([ - bind(hyprland, "focusedWorkspace"), - showWorkspaceNumbers() - ], (focusedWs, showWsNumbers) => - `${focusedWs.id === workspace.id ? "focus" : ""} ${showWsNumbers ? "show" : ""}` - )(), + const tooltipText = Variable.derive([ + bind(workspace, "lastClient"), + bind(AstalHyprland.get_default(), "focusedWorkspace") + ], (lastClient, focusWs) => focusWs.id === workspace.id ? "" : + `Workspace ${workspace.id}${ lastClient ? ` - ${ + !lastClient.title.toLowerCase().includes(lastClient.class) ? + `${lastClient.get_class()}: ` + : "" + } ${lastClient.title}` : "" }` + ); + + return new Widget.EventBox({ + className: className(), onClickRelease: () => workspace.focus(), - tooltipText: Variable.derive([ - bind(workspace, "lastClient"), - bind(hyprland, "focusedWorkspace") - ], (lastClient, focusWs) => focusWs.id === workspace.id ? "" : - `Workspace ${workspace.id}${ lastClient ? ` - ${ - !lastClient.title.toLowerCase().includes(lastClient.class) ? - `${lastClient.get_class()}: ` - : "" - } ${lastClient.title}` : "" }` - )(), + tooltipText: tooltipText(), + onDestroy: () => { + className.drop(); + tooltipText.drop(); + }, child: new Widget.Box({ children: bind(workspace, "lastClient").as((lastClient) => [ new Widget.Revealer({ transitionDuration: 200, transitionType: Gtk.RevealerTransitionType.SLIDE_LEFT, - revealChild: showWorkspaceNumbers(), + revealChild: showWsNum!(), child: new Widget.Label({ label: bind(workspace, "id").as(String), className: "id", @@ -55,7 +67,7 @@ export function Workspaces(): Gtk.Widget { } as Widget.RevealerProps), new Widget.Icon({ className: "last-app-icon", - visible: bind(hyprland, "focusedWorkspace").as(focusedWorkspace => + visible: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusedWorkspace => workspace.id === focusedWorkspace.id ? false : Boolean(lastClient)), @@ -66,9 +78,9 @@ export function Workspaces(): Gtk.Widget { } as Widget.IconProps) ]) } as Widget.BoxProps) - } as Widget.EventBoxProps) - ) - }) + } as Widget.EventBoxProps); + }) + ) } as Widget.BoxProps) } as Widget.EventBoxProps); } diff --git a/hypr/shell/bindings.conf b/hypr/shell/bindings.conf index b021417..21f982d 100644 --- a/hypr/shell/bindings.conf +++ b/hypr/shell/bindings.conf @@ -8,7 +8,7 @@ bind = $mainMod, F11, fullscreen bind = , Print, exec, sh $XDG_CONFIG_HOME/hypr/scripts/screenshot.sh bind = $mainMod, Print, exec, sh $XDG_CONFIG_HOME/hypr/scripts/screenshot.sh full -# Test-only bind, used by developer +# Test-only bind, restarts colorshell bind = $mainMod, F7, exec, ags request reload bind = $mainMod, K, exec, $terminal @@ -23,7 +23,8 @@ bind = $mainMod, L, exec, hyprlock bind = $mainMod, V, exec, astal runner '>' || sh $XDG_CONFIG_HOME/hypr/scripts/clipboard-menu.sh bind = $mainMod, W, exec, astal runner '##' -bind = $mainMod, $mainMod_L, exec, astal show-ws-numbers +# bind = $mainMod, $mainMod_L, exec, astal toggle apps-window +bind = $mainMod, $mainMod_l, exec, astal peek-workspace-num bind = , XF86AudioLowerVolume, exec, astal volume sink-decrease 5 || wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- # Decrease volume bind = , XF86AudioRaiseVolume, exec, astal volume sink-increase 5 || wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ # Increase volume