summaryrefslogtreecommitdiff
path: root/widget/Bar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'widget/Bar.tsx')
-rw-r--r--widget/Bar.tsx93
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>
+}