mirror of
https://github.com/nickolaj-jepsen/nixos.git
synced 2026-01-22 16:16:50 +01:00
update
This commit is contained in:
parent
2b7b63a18c
commit
638ef7093e
140 changed files with 307 additions and 121 deletions
13
modules/desktop/astal/src/utils/gtk.ts
Normal file
13
modules/desktop/astal/src/utils/gtk.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { Gdk, Gtk } from "astal/gtk4";
|
||||
|
||||
export const hasIcon = (name: string): boolean => {
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
const display = Gdk.Display.get_default();
|
||||
if (!display) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Gtk.IconTheme.get_for_display(display).has_icon(name);
|
||||
};
|
||||
59
modules/desktop/astal/src/utils/io.ts
Normal file
59
modules/desktop/astal/src/utils/io.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { GLib, Gio } from "astal";
|
||||
|
||||
interface WalkDirOptions {
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export const findFiles = async (
|
||||
path: string | Gio.File,
|
||||
options?: WalkDirOptions,
|
||||
): Promise<string[]> => {
|
||||
const patternSpec = options?.pattern
|
||||
? GLib.PatternSpec.new(options.pattern)
|
||||
: null;
|
||||
|
||||
// const src = Gio.File.new_for_path(path);
|
||||
const src = typeof path === "string" ? Gio.File.new_for_path(path) : path;
|
||||
const root = Gio.File.new_for_path(".");
|
||||
|
||||
const iter = src.enumerate_children(
|
||||
"standard::*",
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = [];
|
||||
while (true) {
|
||||
const [open, info, file] = iter.iterate(null);
|
||||
if (!open || !info) {
|
||||
break; // end of iterator
|
||||
}
|
||||
if (!file) {
|
||||
throw new Error("Failed to get file");
|
||||
}
|
||||
|
||||
const file_type = info.get_file_type();
|
||||
|
||||
if (file_type === Gio.FileType.DIRECTORY) {
|
||||
result.push(...(await findFiles(file, options)));
|
||||
}
|
||||
|
||||
if (info.get_file_type() !== Gio.FileType.REGULAR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = info.get_name();
|
||||
const path = root.get_relative_path(file);
|
||||
|
||||
if (!path) {
|
||||
throw new Error("Failed to get relative path");
|
||||
}
|
||||
|
||||
if (patternSpec && !patternSpec.match_string(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push(`./${path}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
53
modules/desktop/astal/src/utils/monitors.ts
Normal file
53
modules/desktop/astal/src/utils/monitors.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import Hyprland from "gi://AstalHyprland";
|
||||
import { App, type Gdk } from "astal/gtk4";
|
||||
import config from "../config";
|
||||
|
||||
export type SecondaryMonitor = Gdk.Monitor & {
|
||||
relation: "left" | "right" | "top" | "bottom";
|
||||
};
|
||||
|
||||
export const getMonitors = (): {
|
||||
main: Gdk.Monitor;
|
||||
secondary: SecondaryMonitor[];
|
||||
} => {
|
||||
const scanFn = [
|
||||
// Monitor in config
|
||||
(monitor: Gdk.Monitor) => config.monitor.main === monitor.get_connector(),
|
||||
// First monitor
|
||||
() => true,
|
||||
];
|
||||
|
||||
const monitors = App.get_monitors();
|
||||
console.log("config.monitor.main", config.monitor.main);
|
||||
const main =
|
||||
scanFn.map((fn) => monitors.find(fn)).find((m) => m) || monitors[0];
|
||||
const secondary = monitors
|
||||
.filter((m) => m !== main)
|
||||
.map((m) => {
|
||||
const monitor = m as SecondaryMonitor;
|
||||
const { x: mx, y: my } = main.get_geometry();
|
||||
const { x, y } = m.get_geometry();
|
||||
|
||||
const verticalDiff = Math.abs(y - my);
|
||||
const horizontalDiff = Math.abs(x - mx);
|
||||
|
||||
if (verticalDiff > horizontalDiff) {
|
||||
monitor.relation = y < my ? "top" : "bottom";
|
||||
} else {
|
||||
monitor.relation = x < mx ? "left" : "right";
|
||||
}
|
||||
|
||||
return monitor;
|
||||
});
|
||||
return { main, secondary };
|
||||
};
|
||||
|
||||
export function getHyprlandMonitor(monitor: Gdk.Monitor): Hyprland.Monitor {
|
||||
const hyprland = Hyprland.get_default();
|
||||
const monitors = hyprland.get_monitors();
|
||||
for (const hyprmonitor of monitors) {
|
||||
if (hyprmonitor.get_name() === monitor.get_connector()) return hyprmonitor;
|
||||
}
|
||||
|
||||
throw new Error("GDK monitor does not map to a Hyprland monitor");
|
||||
}
|
||||
24
modules/desktop/astal/src/utils/timeout.ts
Normal file
24
modules/desktop/astal/src/utils/timeout.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { GLib, type Time, timeout } from "astal";
|
||||
|
||||
const runningTimeouts: Map<string, Time> = new Map();
|
||||
export const cancelTimeout = (id: string) => {
|
||||
const runningTimeout = runningTimeouts.get(id);
|
||||
if (runningTimeout) {
|
||||
runningTimeout.cancel();
|
||||
runningTimeouts.delete(id);
|
||||
}
|
||||
};
|
||||
export const cancelableTimeout = (
|
||||
callback: () => void,
|
||||
id: string,
|
||||
delay: number,
|
||||
) => {
|
||||
cancelTimeout(id);
|
||||
runningTimeouts.set(
|
||||
id,
|
||||
timeout(delay, () => {
|
||||
callback();
|
||||
runningTimeouts.delete(id);
|
||||
}),
|
||||
);
|
||||
};
|
||||
55
modules/desktop/astal/src/utils/var-map.ts
Normal file
55
modules/desktop/astal/src/utils/var-map.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import type { Subscribable } from "astal/binding";
|
||||
import { Gtk } from "astal/gtk4";
|
||||
|
||||
export class VarMap<K, T = Gtk.Widget> implements Subscribable {
|
||||
#subs = new Set<(v: T[]) => void>();
|
||||
protected map: Map<K, T>;
|
||||
|
||||
#notifiy() {
|
||||
const value = this.get();
|
||||
for (const sub of this.#subs) {
|
||||
sub(value);
|
||||
}
|
||||
}
|
||||
|
||||
#delete(key: K) {
|
||||
const v = this.map.get(key);
|
||||
|
||||
if (v instanceof Gtk.Widget) {
|
||||
v.unparent();
|
||||
}
|
||||
|
||||
this.map.delete(key);
|
||||
}
|
||||
|
||||
constructor(initial?: Iterable<[K, T]>) {
|
||||
this.map = new Map(initial);
|
||||
}
|
||||
|
||||
clear() {
|
||||
for (const key of this.map.keys()) {
|
||||
this.#delete(key);
|
||||
}
|
||||
this.#notifiy();
|
||||
}
|
||||
|
||||
set(key: K, value: T) {
|
||||
this.#delete(key);
|
||||
this.map.set(key, value);
|
||||
this.#notifiy();
|
||||
}
|
||||
|
||||
delete(key: K) {
|
||||
this.#delete(key);
|
||||
this.#notifiy();
|
||||
}
|
||||
|
||||
get() {
|
||||
return [...this.map.values()];
|
||||
}
|
||||
|
||||
subscribe(callback: (v: T[]) => void) {
|
||||
this.#subs.add(callback);
|
||||
return () => this.#subs.delete(callback);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue