| #! /usr/bin/env node
|
| const
|
| { execSync } = require('child_process'),
|
|
|
| // limitation: can't act on hy3 nodes (and is generally unaware of them)
|
| // TODO add floating window resize
|
|
|
| // helpers
|
| hcd = args => {
|
| console.log(`hyprctl dispatch -- ${args}`)
|
| console.log(execSync(`hyprctl dispatch -- ${args}`).toString())
|
| },
|
| hcj = args => JSON.parse(execSync(`hyprctl -j ${args}`).toString()),
|
| leftOf = w => w.at[0],
|
| rightOf = w => w.at[0] + w.size[0],
|
| topOf = w => w.at[1],
|
| bottomOf = w => w.at[1] + w.size[1],
|
| maxBy = f => as => as.reduce((a, b) => f(a) > f(b) && a || b),
|
| minBy = f => as => as.reduce((a, b) => f(a) < f(b) && a || b),
|
| resizeX = Δ => ({ address }) => () => hcd(`resizewindowpixel ${Δ} 0,address:${address}`),
|
| resizeY = Δ => ({ address }) => () => hcd(`resizewindowpixel 0 ${Δ},address:${address}`),
|
|
|
| // args
|
| direction = process.argv[2],
|
| Δ = process.argv[3],
|
|
|
| // main
|
| workspaceId = hcj("activeworkspace").id,
|
| ws = hcj("clients").filter(w => w.workspace.id == workspaceId),
|
| target = ws.find(w => w.focusHistoryID == 0),
|
| targetLeft = leftOf(target),
|
| targetRight = rightOf(target),
|
| targetTop = topOf(target),
|
| targetBottom = bottomOf(target),
|
| halfΔ = Math.floor(Δ / 2),
|
| isLeftmost = ws.every(w => leftOf(w) >= targetLeft),
|
| isRightmost = ws.every(w => rightOf(w) <= targetRight),
|
| windowsLeft = ws.filter(w => leftOf(w) < targetLeft),
|
| isUpmost = ws.every(w => topOf(w) >= targetTop),
|
| isDownmost = ws.every(w => bottomOf(w) <= targetBottom),
|
| windowsUp = ws.filter(w => topOf(w) < targetTop),
|
|
|
| // HACK a limitation is that shrinking left doesn't mean only the window to the right will fill the empty space ― it will be distributed evenly
|
| // so we also expand the target window by half the distance. ditto for shrinking up
|
| resizeLeft =
|
| isLeftmost && resizeX(-Δ)(target)
|
| || isRightmost && resizeX(Δ)(target)
|
| || (() => { resizeX(-Δ)(maxBy(leftOf)(windowsLeft))(); resizeX(halfΔ)(target)() }),
|
|
|
| resizeRight =
|
| isRightmost && resizeX(-Δ)(target) || resizeX(Δ)(target),
|
|
|
| resizeUp =
|
| isUpmost && resizeY(-Δ)(target)
|
| || isDownmost && resizeY(Δ)(target)
|
| || (() => { resizeY(-Δ)(minBy(bottomOf)(windowsUp))(); resizeY(halfΔ)(target)() }),
|
|
|
| resizeDown =
|
| isDownmost && resizeY(-Δ)(target) || resizeY(Δ)(target),
|
|
|
| matchDirection = {
|
| '←': resizeLeft,
|
| '→': resizeRight,
|
| '↑': resizeUp,
|
| '↓': resizeDown
|
| }
|
|
|
| matchDirection[direction]()
|