diff options
| author | Linnea Gräf <nea@nea.moe> | 2025-04-13 19:42:47 +0200 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2025-04-13 19:42:47 +0200 |
| commit | 0d3b6a3f698853cbbf7d0ebf866eca8bccd196fb (patch) | |
| tree | e756da2ef87a13a269da71fac1cabd966423c2e9 /widget/Bar.tsx | |
| download | ags-master.tar.gz ags-master.tar.bz2 ags-master.zip | |
Diffstat (limited to 'widget/Bar.tsx')
| -rw-r--r-- | widget/Bar.tsx | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/widget/Bar.tsx b/widget/Bar.tsx new file mode 100644 index 0000000..ccbd496 --- /dev/null +++ b/widget/Bar.tsx @@ -0,0 +1,93 @@ +import { App, Astal, Gtk, Gdk } from "astal/gtk3" +import { exec, monitorFile, Variable } from "astal" +import { Button, Label } from "astal/gtk3/widget"; +import Pango from "gi://Pango?version=1.0"; + +const time = Variable("").poll(1000, "date") + +type Id = number +interface SwayNodeCommon { + id: Id, + orientation: 'horizontal' | 'vertical' | 'none', + name: string, + focus: Id[], + rect: Rect, + deco_rect: Rect, + window_rect: Rect, + geometry: Rect, +} +type SwayNode = SwayOutput | SwayRoot | SwayCon | SwayWorkspace; +type Rect = { x: number, y: number, width: number, height: number } +interface SwayWorkspace extends SwayNodeCommon { + type: 'workspace', + nodes: SwayCon[] +} +interface SwayCon extends SwayNodeCommon { + type: 'con', + window_properties?: { + class: string, + instance: string, + title: string, + window_role: string, + window_type: string, + }, +} +interface SwayOutput extends SwayNodeCommon { + type: 'output', + nodes: SwayWorkspace[], + focused: boolean, +} +interface SwayRoot extends SwayNodeCommon { + type: 'root', + nodes: SwayOutput[] +} +const swayTree = Variable({} as SwayRoot | { type: undefined }).poll(1000, "swaymsg -t get_tree", + text => JSON.parse(text) as SwayRoot +) +function omit<T extends object, K extends keyof T>(obj: T, ...ks: K[]): Omit<T, K> { + return Object.fromEntries(Object.entries(obj).filter(it => !ks.includes(it[0] as K))) as any +} +function Monitor(props: { monitor: SwayOutput }) { + return <> + <Label halign={Gtk.Align.START} className={"monitor"}> + {`${props.monitor.name} (${props.monitor.nodes.length})`} + </Label> + {props.monitor.nodes.map(ws => + <Workspace ws={ws} focused={props.monitor.focus.includes(ws.id)}></Workspace> + )} + </> +} +function Workspace(props: { ws: SwayWorkspace, focused: boolean }) { + return <> + <Button + halign={Gtk.Align.START} + onClickRelease={() => exec(['swaymsg', `workspace ${JSON.stringify(props.ws.name)}`])} + className={"workspace linky-button " + (props.focused ? 'active-ws ' : '')} relief={Gtk.ReliefStyle.NONE}> + {`Workspace ${props.ws.name}`} + </Button> + {props.ws.nodes.map(window => + <Label + ellipsize={Pango.EllipsizeMode.MIDDLE} + maxWidthChars={30} + halign={Gtk.Align.START} + className={"window"}>{window.window_properties?.title ?? window.name}</Label> + )} + </> +} +export default function Bar(gdkmonitor: Gdk.Monitor) { + const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor + return <window + className="Bar" + gdkmonitor={gdkmonitor} + exclusivity={Astal.Exclusivity.EXCLUSIVE} + anchor={TOP | LEFT | BOTTOM} + application={App}> + <box vertical className={"output-list"}> + {swayTree(root => !root.type ? null + : root.nodes + .map(monitor => monitor.name.startsWith("_") ? null : <Monitor monitor={monitor}></Monitor>) + .filter(it => it) + )} + </box> + </window> +} |
