aboutsummaryrefslogtreecommitdiff
path: root/.config/ags/widget/bar/buttons/Taskbar.ts
blob: b9c65fa7ae7c2e8109d4f3428f9a877df2ba4d29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { launchApp, icon } from "lib/utils"
import icons from "lib/icons"
import options from "options"
import PanelButton from "../PanelButton"

const hyprland = await Service.import("hyprland")
const apps = await Service.import("applications")
const { monochrome, exclusive, iconSize } = options.bar.taskbar
const { position } = options.bar

const focus = (address: string) => hyprland.messageAsync(
    `dispatch focuswindow address:${address}`)

const DummyItem = (address: string) => Widget.Box({
    attribute: { address },
    visible: false,
})

const AppItem = (address: string) => {
    const client = hyprland.getClient(address)
    if (!client || client.class === "")
        return DummyItem(address)

    const app = apps.list.find(app => app.match(client.class))

    const btn = PanelButton({
        class_name: "panel-button",
        tooltip_text: Utils.watch(client.title, hyprland, () =>
            hyprland.getClient(address)?.title || "",
        ),
        on_primary_click: () => focus(address),
        on_middle_click: () => app && launchApp(app),
        child: Widget.Icon({
            size: iconSize.bind(),
            icon: monochrome.bind().as(m => icon(
                (app?.icon_name || client.class) + (m ? "-symbolic" : ""),
                icons.fallback.executable + (m ? "-symbolic" : ""),
            )),
        }),
    })

    return Widget.Box(
        {
            attribute: { address },
            visible: Utils.watch(true, [exclusive, hyprland], () => {
                return exclusive.value
                    ? hyprland.active.workspace.id === client.workspace.id
                    : true
            }),
        },
        Widget.Overlay({
            child: btn,
            pass_through: true,
            overlay: Widget.Box({
                className: "indicator",
                hpack: "center",
                vpack: position.bind().as(p => p === "top" ? "start" : "end"),
                setup: w => w.hook(hyprland, () => {
                    w.toggleClassName("active", hyprland.active.client.address === address)
                }),
            }),
        }),
    )
}

function sortItems<T extends { attribute: { address: string } }>(arr: T[]) {
    return arr.sort(({ attribute: a }, { attribute: b }) => {
        const aclient = hyprland.getClient(a.address)!
        const bclient = hyprland.getClient(b.address)!
        return aclient.workspace.id - bclient.workspace.id
    })
}

export default () => Widget.Box({
    class_name: "taskbar",
    children: sortItems(hyprland.clients.map(c => AppItem(c.address))),
    setup: w => w
        .hook(hyprland, (w, address?: string) => {
            if (typeof address === "string")
                w.children = w.children.filter(ch => ch.attribute.address !== address)
        }, "client-removed")
        .hook(hyprland, (w, address?: string) => {
            if (typeof address === "string")
                w.children = sortItems([...w.children, AppItem(address)])
        }, "client-added")
        .hook(hyprland, (w, event?: string) => {
            if (event === "movewindow")
                w.children = sortItems(w.children)
        }, "event"),
})