diff --git a/src/app.ts b/src/app.ts index 30dbc61..d6e01e0 100644 --- a/src/app.ts +++ b/src/app.ts @@ -22,7 +22,7 @@ import { createBinding, createComputed, createRoot, getScope, Scope } from "ags" import { OSDModes, triggerOSD } from "./window/osd"; import { programArgs, programInvocationName } from "system"; import { setConsoleLogDomain } from "console"; -import { createSubscription, encoder, secureBaseBinding } from "./modules/utils"; +import { createScopedConnection, createSubscription, encoder, secureBaseBinding } from "./modules/utils"; import { exec } from "ags/process"; import { NightLight } from "./modules/nightlight"; import { Backlights } from "./modules/backlight"; @@ -209,68 +209,67 @@ you should use the socket in the XDG_RUNTIME_DIR/colorshell.sock for a faster re ); // handle communication via socket - this.#connections.set(this.#socketService, - this.#socketService.connect("incoming", (_, conn) => { + createScopedConnection(this.#socketService, "incoming", (conn) => { const inputStream = Gio.DataInputStream.new(conn.inputStream); inputStream.read_upto_async('\x00', -1, GLib.PRIORITY_DEFAULT, null, (_, res) => { - const [args, len] = inputStream.read_upto_finish(res); - inputStream.close(null); - conn.inputStream.close(null); + const [args, len] = inputStream.read_upto_finish(res); + inputStream.close(null); + conn.inputStream.close(null); - if(len < 1) { - console.error(`Colorshell: No args provided via socket call`); - return; - } + if(len < 1) { + console.error(`Colorshell: No args provided via socket call`); + return; + } - try { - const [success, parsedArgs] = GLib.shell_parse_argv(`colorshell ${args}`); - parsedArgs?.splice(0, 1); // remove the unnecessary `colorshell` part + try { + const [success, parsedArgs] = GLib.shell_parse_argv(`colorshell ${args}`); + parsedArgs?.splice(0, 1); // remove the unnecessary `colorshell` part - if(success) { - handleArguments({ - print_literal: (msg) => conn.outputStream.write_bytes( - encoder.encode(`${msg}\n`), - null - ), - // TODO: support writing to stderr(i don't know how to do that :sob:) - printerr_literal: (msg) => conn.outputStream.write_bytes( - encoder.encode(`${msg}\n`), - null - ) - }, parsedArgs!); - - conn.outputStream.flush(null); - conn.close(null); - return; - } - - conn.outputStream.write_bytes( - encoder.encode("Error: Unexpected error occurred on argument parsing!"), - null - ); + if(success) { + handleArguments({ + print_literal: (msg) => conn.outputStream.write_bytes( + encoder.encode(`${msg}\n`), + null + ), + // TODO: support writing to stderr(i don't know how to do that :sob:) + printerr_literal: (msg) => conn.outputStream.write_bytes( + encoder.encode(`${msg}\n`), + null + ) + }, parsedArgs!); conn.outputStream.flush(null); conn.close(null); - } catch(_e) { - const e = _e as Error; - console.error(`Colorshell: An error occurred while writing to socket output. Stderr:\n${ - e.message}\n${e.stack}`); + return; } - }); - return false; - }) - ); + conn.outputStream.write_bytes( + encoder.encode("Error: Unexpected error occurred on argument parsing!"), + null + ); + + conn.outputStream.flush(null); + conn.close(null); + } catch(_e) { + const e = _e as Error; + console.error(`Colorshell: An error occurred while writing to socket output. Stderr:\n${ + e.message}\n${e.stack}`); + } + }); + + return false; + }); } private main(): void { Gtk.init(); Adw.init(); - this.init(); createRoot((dispose) => { console.log(`Colorshell: Initializing things`); this.#connections.set(this, this.connect("shutdown", () => dispose())); + + this.init(); this.#scope = getScope(); NightLight.getDefault(); diff --git a/src/modules/compositors/hyprland.ts b/src/modules/compositors/hyprland.ts index c2a3e08..cae1a27 100644 --- a/src/modules/compositors/hyprland.ts +++ b/src/modules/compositors/hyprland.ts @@ -1,15 +1,23 @@ -import { register } from "ags/gobject"; import { Compositors } from "."; -import { createRoot } from "ags"; +import { register } from "ags/gobject"; +import { createRoot, getScope, Scope } from "ags"; import { createScopedConnection } from "../utils"; + import AstalHyprland from "gi://AstalHyprland"; +type Event = "activewindow" | "activewindowv2" + | "workspace" | "workspacev2" + | "focusedmon" | "focusedmonv2"; + @register({ GTypeName: "CompositorHyprland" }) export class CompositorHyprland extends Compositors.Compositor { + #scope: Scope; hyprland: AstalHyprland.Hyprland; + protected _focusedClient: Compositors.Client | null = null; + constructor() { super(); @@ -19,16 +27,43 @@ export class CompositorHyprland extends Compositors.Compositor { throw new Error(`Couldn't initialize CompositorHyprland: ${e}`); } - createRoot(() => { + this.#scope = createRoot(() => { createScopedConnection( - this.hyprland, "workspace-added", (hws) => { - // check workspace existance - if(this._workspaces.filter(w => w.id === hws.id)[0]) - return; + this.hyprland, "event", (e, args) => { + switch(e as Event) { + case "activewindowv2": + const address = args; + const clients = AstalHyprland.get_default().clients; + const focusedClient = clients.filter(c => + c.address === address + )[0]; - // TODO + if(focusedClient) { + this._focusedClient = new Compositors.Client({ + address: address, + class: focusedClient.class ?? "", + initialClass: focusedClient.initialClass ?? "", + mapped: focusedClient.mapped, + position: [focusedClient.x, focusedClient.y], + title: focusedClient.title ?? "" + }); + + this.notify("focused-client"); + return; + } + + this._focusedClient = null; + this.notify("focused-client"); + break; + } } ); + + return getScope(); }); } + + vfunc_dispose(): void { + this.#scope.dispose(); + } } diff --git a/src/modules/compositors/index.ts b/src/modules/compositors/index.ts index 26be802..3176804 100644 --- a/src/modules/compositors/index.ts +++ b/src/modules/compositors/index.ts @@ -4,8 +4,6 @@ import GObject, { getter, gtype, property, register } from "ags/gobject"; import GLib from "gi://GLib?version=2.0"; -export default Compositors; - /** WIP modular implementation of a system that supports implementing * a variety of Wayland Compositors * @todo implement more general compositor info + a lot of stuff diff --git a/src/window/bar/widgets/FocusedClient.tsx b/src/window/bar/widgets/FocusedClient.tsx index 877dded..c9ebf60 100644 --- a/src/window/bar/widgets/FocusedClient.tsx +++ b/src/window/bar/widgets/FocusedClient.tsx @@ -1,16 +1,12 @@ +import { CompositorHyprland } from "../../../modules/compositors/hyprland"; import { Gtk } from "ags/gtk4"; import { createBinding, With } from "ags"; import { variableToBoolean } from "../../../modules/utils"; import { getAppIcon, getSymbolicIcon } from "../../../modules/apps"; import Pango from "gi://Pango?version=1.0"; -import AstalHyprland from "gi://AstalHyprland"; - -const hyprland = AstalHyprland.get_default(); - -// Fix empty focused-client on opening a window on an empty workspace -hyprland.connect("notify::clients", () => hyprland.notify("focused-client")); +const hyprland = new CompositorHyprland; export const FocusedClient = () => { const focusedClient = createBinding(hyprland, "focusedClient");