aboutsummaryrefslogtreecommitdiff
path: root/linux/home/.config/ags/widget/overview/Workspace.ts
blob: 1b8d60b3ca6d1dfb783dc0d98f9a03db4961654f (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
import Window from "./Window"
import Gdk from "gi://Gdk"
import Gtk from "gi://Gtk?version=3.0"
import options from "options"

const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)]
const scale = (size: number) => (options.overview.scale.value / 100) * size
const hyprland = await Service.import("hyprland")

const dispatch = (args: string) => hyprland.messageAsync(`dispatch ${args}`)

const size = (id: number) => {
    const def = { h: 1080, w: 1920 }
    const ws = hyprland.getWorkspace(id)
    if (!ws)
        return def

    const mon = hyprland.getMonitor(ws.monitorID)
    return mon ? { h: mon.height, w: mon.width } : def
}

export default (id: number) => {
    const fixed = Widget.Fixed()

    // TODO: early return if position is unchaged
    async function update() {
        const json = await hyprland.messageAsync("j/clients").catch(() => null)
        if (!json)
            return

        fixed.get_children().forEach(ch => ch.destroy())
        const clients = JSON.parse(json) as typeof hyprland.clients
        clients
            .filter(({ workspace }) => workspace.id === id)
            .forEach(c => {
                const x = c.at[0] - (hyprland.getMonitor(c.monitor)?.x || 0)
                const y = c.at[1] - (hyprland.getMonitor(c.monitor)?.y || 0)
                c.mapped && fixed.put(Window(c), scale(x), scale(y))
            })
        fixed.show_all()
    }

    return Widget.Box({
        attribute: { id },
        tooltipText: `${id}`,
        class_name: "workspace",
        vpack: "center",
        css: options.overview.scale.bind().as(v => `
            min-width: ${(v / 100) * size(id).w}px;
            min-height: ${(v / 100) * size(id).h}px;
        `),
        setup(box) {
            box.hook(options.overview.scale, update)
            box.hook(hyprland, update, "notify::clients")
            box.hook(hyprland.active.client, update)
            box.hook(hyprland.active.workspace, () => {
                box.toggleClassName("active", hyprland.active.workspace.id === id)
            })
        },
        child: Widget.EventBox({
            expand: true,
            on_primary_click: () => {
                App.closeWindow("overview")
                dispatch(`workspace ${id}`)
            },
            setup: eventbox => {
                eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY)
                eventbox.connect("drag-data-received", (_w, _c, _x, _y, data) => {
                    const address = new TextDecoder().decode(data.get_data())
                    dispatch(`movetoworkspacesilent ${id},address:${address}`)
                })
            },
            child: fixed,
        }),
    })
}