nixos-configs/modules/ags/config/lib.ts
matt1432 6ca0d7248b
All checks were successful
Discord / discord commits (push) Has been skipped
refactor: rename some flake attr directories
2024-12-16 15:51:41 -05:00

203 lines
5.1 KiB
TypeScript

import { idle } from 'astal';
import { App, Gdk, Gtk } from 'astal/gtk3';
import AstalHyprland from 'gi://AstalHyprland';
/* Types */
import PopupWindow from './widgets/misc/popup-window';
export interface Layer {
address: string
x: number
y: number
w: number
h: number
namespace: string
}
export interface Levels {
0?: Layer[] | null
1?: Layer[] | null
2?: Layer[] | null
3?: Layer[] | null
}
export interface Layers {
levels: Levels
}
export type LayerResult = Record<string, Layers>;
export interface CursorPos {
x: number
y: number
}
type PointProps = [number, number] | {
x: number
y: number
} | number;
export class Point {
public x = 0;
public y = 0;
get values(): [number, number] {
return [this.x, this.y];
}
constructor(props?: PointProps, y?: number) {
if (typeof props === 'number') {
if (y) {
this.x = props;
this.y = y;
}
else {
throw new Error('Wrong props');
}
}
else if (Array.isArray(props)) {
this.x = props[0];
this.y = props[1];
}
else if (props) {
this.x = props.x;
this.y = props.y;
}
}
}
export type BezierPoints = [number, number, number, number];
export class Bezier {
private _points: BezierPoints;
get points() {
return [...this._points] as BezierPoints;
}
constructor(x1: number, y1: number, x2: number, y2: number) {
this._points = [x1, y1, x2, y2];
}
}
export const get_hyprland_monitor = (monitor: Gdk.Monitor): AstalHyprland.Monitor | undefined => {
const hyprland = AstalHyprland.get_default();
const manufacturer = monitor.manufacturer?.replace(',', '');
const model = monitor.model?.replace(',', '');
const start = `${manufacturer} ${model}`;
return hyprland.get_monitors().find((m) => m.description?.startsWith(start));
};
export const get_hyprland_monitor_desc = (monitor: Gdk.Monitor): string => {
const hyprland = AstalHyprland.get_default();
const manufacturer = monitor.manufacturer?.replace(',', '');
const model = monitor.model?.replace(',', '');
const start = `${manufacturer} ${model}`;
return `desc:${hyprland.get_monitors().find((m) => m.description?.startsWith(start))?.description}`;
};
export const get_gdkmonitor_from_desc = (desc: string): Gdk.Monitor => {
const display = Gdk.Display.get_default();
for (let m = 0; m < (display?.get_n_monitors() ?? 0); m++) {
const monitor = display?.get_monitor(m);
if (monitor && desc === get_hyprland_monitor_desc(monitor)) {
return monitor;
}
}
throw Error(`Monitor ${desc} not found`);
};
export const get_monitor_desc = (mon: AstalHyprland.Monitor): string => {
return `desc:${mon.description}`;
};
export const hyprMessage = (message: string) => new Promise<string>((
resolution = () => { /**/ },
rejection = () => { /**/ },
) => {
const hyprland = AstalHyprland.get_default();
try {
hyprland.message_async(message, (_, asyncResult) => {
const result = hyprland.message_finish(asyncResult);
resolution(result);
});
}
catch (e) {
rejection(e);
}
});
export const centerCursor = (): void => {
const hyprland = AstalHyprland.get_default();
let x: number;
let y: number;
const monitor = hyprland.get_focused_monitor();
switch (monitor.transform) {
case 1:
x = monitor.x - (monitor.height / 2);
y = monitor.y - (monitor.width / 2);
break;
case 2:
x = monitor.x - (monitor.width / 2);
y = monitor.y - (monitor.height / 2);
break;
case 3:
x = monitor.x + (monitor.height / 2);
y = monitor.y + (monitor.width / 2);
break;
default:
x = monitor.x + (monitor.width / 2);
y = monitor.y + (monitor.height / 2);
break;
}
hyprMessage(`dispatch movecursor ${x} ${y}`);
};
export const closeAll = () => {
(App.get_windows() as PopupWindow[])
.filter((w) => w &&
w.close_on_unfocus &&
w.close_on_unfocus !== 'stay')
.forEach((w) => {
App.get_window(w.name)?.set_visible(false);
});
};
export const perMonitor = (window: (monitor: Gdk.Monitor) => Gtk.Widget) => idle(() => {
const display = Gdk.Display.get_default();
const windows = new Map<Gdk.Monitor, Gtk.Widget>();
const createWindow = (monitor: Gdk.Monitor) => {
windows.set(monitor, window(monitor));
};
for (let m = 0; m < (display?.get_n_monitors() ?? 0); m++) {
const monitor = display?.get_monitor(m);
if (monitor) {
createWindow(monitor);
}
}
display?.connect('monitor-added', (_, monitor) => {
createWindow(monitor);
});
display?.connect('monitor-removed', (_, monitor) => {
windows.get(monitor)?.destroy();
windows.delete(monitor);
});
});