diff --git a/src/app.ts b/src/app.ts index 44b7c5e..ecb9812 100644 --- a/src/app.ts +++ b/src/app.ts @@ -43,7 +43,9 @@ const runnerPlugins: Array = [ const defaultWindows: Array = []; +Gtk.init(); Adw.init(); +GLib.unsetenv("LD_PRELOAD"); @register({ GTypeName: "Shell" }) export class Shell extends Gtk.Application { @@ -51,8 +53,10 @@ export class Shell extends Gtk.Application { #loop!: GLib.MainLoop; #scope!: ReturnType; + #connections = new Map | number>(); #stylesheet: Uint8Array|undefined; #styleProvider: Gtk.CssProvider; + #gresource: Gio.Resource|null = null; get scope() { return this.#scope; } @@ -64,6 +68,12 @@ export class Shell extends Gtk.Application { }); this.#styleProvider = Gtk.CssProvider.new(); + try { + this.#gresource = Gio.Resource.load(GRESOURCES_FILE); + } catch(_e) { + const e = _e as Error; + console.error(`Error: couldn't load gresource! Stderr: ${e.message}\n${e.stack}`); + } } public static getDefault(): Shell { @@ -121,18 +131,22 @@ export class Shell extends Gtk.Application { printerr("Error: colorshell not running. Try to clean-run before using arguments"); return 1; } - - this.main(); + + this.activate(); } return 0; } + vfunc_activate(): void { + super.vfunc_activate(); + this.main(); + } + private main(): void { this.#loop = GLib.MainLoop.new(null, false); - const connections = new Map | number>(); - connections.set(this, this.connect("shutdown", () => this.#scope.dispose())); + this.#connections.set(this, this.connect("shutdown", () => this.#scope.dispose())); createRoot(() => { console.log(`Colorshell: initializing`); this.#scope = getScope(); @@ -148,12 +162,12 @@ export class Shell extends Gtk.Application { console.log("Adding runner plugins"); runnerPlugins.forEach(plugin => Runner.addPlugin(plugin)); - connections.set(Wireplumber.getDefault(), + this.#connections.set(Wireplumber.getDefault(), Wireplumber.getDefault().getDefaultSink().connect("notify::volume", () => triggerOSD()) ); - connections.set(Notifications.getDefault(), [ + this.#connections.set(Notifications.getDefault(), [ Notifications.getDefault().connect("notification-added", (_, _notif: AstalNotifd.Notification) => { Windows.getDefault().open("floating-notifications"); }), @@ -167,7 +181,7 @@ export class Shell extends Gtk.Application { this.#scope.onCleanup(() => { console.log("Colorshell: disposing connections and quitting because of ::shutdown"); - connections.forEach((ids, obj) => Array.isArray(ids) ? + this.#connections.forEach((ids, obj) => Array.isArray(ids) ? ids.forEach(id => obj.disconnect(id)) : obj.disconnect(ids)); }); diff --git a/src/env.d.ts b/src/env.d.ts index 467c0a4..55d4f96 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,4 +1,6 @@ declare const SRC: string +declare const DEVEL: boolean; +declare const GRESOURCES_FILE: string; declare module "inline:*" { const content: string diff --git a/src/windows.ts b/src/windows.ts index 20eb185..f9f247c 100644 --- a/src/windows.ts +++ b/src/windows.ts @@ -7,7 +7,7 @@ import { FloatingNotifications } from "./window/FloatingNotifications"; import { CenterWindow } from "./window/CenterWindow"; import { LogoutMenu } from "./window/LogoutMenu"; import { AppsWindow } from "./window/AppsWindow"; -import { Scope } from "/usr/share/ags/js/gnim/src/jsx/scope"; +import { createRoot, getScope, onCleanup, Scope } from "/usr/share/ags/js/gnim/src/jsx/scope"; import { Shell } from "./app"; import GObject, { getter, register, signal } from "ags/gobject"; @@ -35,6 +35,7 @@ export type WindowData = { class Windows extends GObject.Object { private static instance: (Windows | null); + #scope!: ReturnType; #windows: Record = { "bar": { create: this.createWindowForMonitors(Bar) }, "osd": { create: this.createWindowForFocusedMonitor(OSD), }, @@ -60,32 +61,24 @@ class Windows extends GObject.Object { constructor() { super(); - // Listen to monitor events - const hyprConnections = [ - AstalHyprland.get_default().connect("monitor-added", () => - this.reopen()), - AstalHyprland.get_default().connect("monitor-removed", () => - AstalHyprland.get_default().get_monitors().length > 0 && - this.reopen()) - ]; + createRoot((dispose) => { + this.#scope = getScope(); + Shell.getDefault().scope.onMount(dispose); - Shell.getDefault().scope.run(() => { - // open windows with the "open" status on startup - Object.keys(this.#windows).filter((key) => - this.#windows[key].status === "open" - ).forEach(name => { - this.open(name, true); - console.log(`Windows: opening window \`${name}\` on startup`); + // Listen to monitor events + const hyprConnections = [ + AstalHyprland.get_default().connect("monitor-added", () => + this.reopen()), + AstalHyprland.get_default().connect("monitor-removed", () => + AstalHyprland.get_default().get_monitors().length > 0 && + this.reopen()) + ]; + + onCleanup(() => { + hyprConnections.forEach(id => AstalHyprland.get_default().disconnect(id)); + this.openWindows.forEach(name => this.disconnectWindow(name)); }); - }); - Shell.getDefault().scope.onCleanup(() => { - hyprConnections.forEach(id => - GObject.signal_handler_is_connected(AstalHyprland.get_default(), id) && - AstalHyprland.get_default().disconnect(id) - ); - - this.openWindows.forEach(name => this.disconnectWindow(name)); }); } @@ -199,12 +192,14 @@ class Windows extends GObject.Object { // create a scope for every window generator function and dispose on ::close-request return () => monitors.map(mon => { - const scope = new Scope(null); - return scope.run(() => { + return createRoot(() => { + const scope = getScope(); const instance = create(mon.id, scope) as Astal.Window; const connection: number = instance.connect("close-request", () => scope.dispose()); + this.#scope.onMount(scope.dispose); + scope.onCleanup(() => instance.disconnect(connection)); return instance; @@ -227,12 +222,12 @@ class Windows extends GObject.Object { }); return () => { - const scope = new Scope(null); - return scope.run(() => { + return createRoot((dispose) => { + const scope = getScope(); const instance = create(focusedMonitor, scope) as Astal.Window; - const connection: number = instance.connect("close-request", () => - scope.dispose()); + const connection = instance.connect("close-request", () => dispose()); + this.#scope.onMount(dispose) scope.onCleanup(() => instance.disconnect(connection)); return instance;