summaryrefslogtreecommitdiff
path: root/js/node
diff options
context:
space:
mode:
Diffstat (limited to 'js/node')
-rw-r--r--js/node/application.ts51
-rw-r--r--js/node/astal.ts38
-rw-r--r--js/node/widgets.ts63
3 files changed, 152 insertions, 0 deletions
diff --git a/js/node/application.ts b/js/node/application.ts
new file mode 100644
index 0000000..875c1c8
--- /dev/null
+++ b/js/node/application.ts
@@ -0,0 +1,51 @@
+import gi from "node-gtk"
+import { RequestHandler, Config, runJS } from "../src/application.js"
+const Astal = gi.require("Astal", "0.1")
+
+class AstalJS extends Astal.Application {
+ static GTypeName = "AstalJS"
+ static { gi.registerClass(this) }
+
+ eval = runJS
+ requestHandler?: RequestHandler
+
+ vfunc_response(msg: string, conn: any): void {
+ if (typeof this.requestHandler === "function") {
+ this.requestHandler(msg, response => {
+ Astal.writeSock(conn, response, (_, res) =>
+ Astal.writeSockFinish(res),
+ )
+ })
+ } else {
+ // @ts-expect-error missing type
+ super.vfunc_response(msg, conn)
+ }
+ }
+
+ start(
+ { requestHandler, css, ...cfg }: Omit<Config, "hold"> = {},
+ callback?: (args: string[]) => any,
+ ) {
+ Object.assign(this, cfg)
+
+ this.requestHandler = requestHandler
+ this.on("activate", () => {
+ callback?.(process.argv)
+ })
+
+ if (!this.acquireSocket()) {
+ console.error(`Astal instance "${this.instanceName}" already running`)
+ process.exit()
+ }
+
+ if (css)
+ this.applyCss(css, false)
+
+ // FIXME: promises never resolve
+ // https://github.com/romgrk/node-gtk/issues/121
+ // https://gitlab.gnome.org/GNOME/gjs/-/issues/468
+ App.run([])
+ }
+}
+
+export const App = new AstalJS
diff --git a/js/node/astal.ts b/js/node/astal.ts
new file mode 100644
index 0000000..9560a81
--- /dev/null
+++ b/js/node/astal.ts
@@ -0,0 +1,38 @@
+import gi from "node-gtk"
+import Time from "../src/time.js"
+import Process from "../src/process.js"
+import * as variable from "../src/variable.js"
+const Astal = gi.require("Astal", "0.1")
+
+const { interval, timeout, idle } = Time(Astal.Time)
+const { subprocess, exec, execAsync } = Process({
+ defaultOut: console.log,
+ defaultErr: console.error,
+ exec: Astal.Process.exec,
+ execv: Astal.Process.execv,
+ execAsync: Astal.Process.execAsync,
+ execAsyncv: Astal.Process.execAsyncv,
+ subprocess: Astal.Process.subprocess,
+ subprocessv: Astal.Process.subprocessv,
+})
+
+variable.config.defaultErrHandler = console.log
+variable.config.execAsync = execAsync
+variable.config.subprocess = subprocess
+variable.config.interval = interval
+variable.config.VariableBase = Astal.VariableBase
+Object.freeze(variable.config)
+
+export { subprocess, exec, execAsync }
+export { interval, timeout, idle }
+export { bind } from "../src/binding.js"
+export { Variable } from "../src/variable.js"
+export * as Widget from "./widgets.js"
+export { App } from "./application.js"
+
+// for convinience
+export const GLib = gi.require("GLib", "2.0")
+export const Gtk = gi.require("Gtk", "3.0")
+export const Gio = gi.require("Gio", "2.0")
+export const GObject = gi.require("GObject", "2.0")
+export { Astal, gi }
diff --git a/js/node/widgets.ts b/js/node/widgets.ts
new file mode 100644
index 0000000..914821d
--- /dev/null
+++ b/js/node/widgets.ts
@@ -0,0 +1,63 @@
+/* eslint-disable max-len */
+import gi from "node-gtk"
+import proxy, { type ConstructProps, type Widget } from "../src/astalify.js"
+import type GtkT from "@girs/node-gtk-3.0/node-gtk-3.0"
+import type AstalT from "@girs/node-astal-0.1/node-astal-0.1"
+
+const Astal = gi.require("Astal", "0.1")
+const Gtk = gi.require("Gtk", "3.0")
+
+const proxify = proxy(Gtk,
+ prop => `set${prop.charAt(0).toUpperCase() + prop.slice(1)}`,
+ {
+ cssGetter: Astal.widgetGetCss,
+ cssSetter: Astal.widgetSetCss,
+ classGetter: Astal.widgetGetClassNames,
+ classSetter: Astal.widgetSetClassNames,
+ cursorGetter: Astal.widgetGetCursor,
+ cursorSetter: Astal.widgetSetCursor,
+ })
+
+export function astalify<
+ C extends typeof Gtk.Widget,
+ P extends Record<string, any>,
+ N extends string = "Widget",
+>(klass: C) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ type Astal<N> = Omit<C, "new"> & {
+ new(props: P, ...children: GtkT.Widget[]): Widget<C>
+ (props: P, ...children: GtkT.Widget[]): Widget<C>
+ }
+
+ return proxify(klass) as unknown as Astal<N>
+}
+
+// Label
+export const Label = astalify<typeof Gtk.Label, LabelProps, "Label">(Gtk.Label)
+export type LabelProps = ConstructProps<typeof Gtk.Label, GtkT.Label.ConstructorProperties>
+
+// Icon
+export const Icon = astalify<typeof Astal.Icon, IconProps, "Icon">(Astal.Icon)
+export type IconProps = ConstructProps<typeof Astal.Icon, AstalT.Icon.ConstructorProperties>
+
+// Button
+export const Button = astalify<typeof Astal.Button, ButtonProps, "Button">(Astal.Button)
+export type ButtonProps = ConstructProps<typeof Astal.Button, AstalT.Button.ConstructorProperties, {
+ onClicked: (self: Widget<typeof Astal.Button>) => void
+}>
+
+// Window
+export const Window = astalify<typeof Astal.Window, WindowProps, "Window">(Astal.Window)
+export type WindowProps = ConstructProps<typeof Astal.Window, AstalT.Window.ConstructorProperties>
+
+// Box
+export const Box = astalify<typeof Astal.Box, BoxProps, "Box">(Astal.Box)
+export type BoxProps = ConstructProps<typeof Astal.Box, AstalT.Box.ConstructorProperties>
+
+// CenterBox
+export const CenterBox = astalify<typeof Astal.CenterBox, CenterBoxProps, "CenterBox">(Astal.CenterBox)
+export type CenterBoxProps = ConstructProps<typeof Astal.CenterBox, AstalT.CenterBox.ConstructorProperties>
+
+// EventBox
+export const EventBox = astalify<typeof Astal.EventBox, EventBoxProps, "EventBox">(Astal.EventBox)
+export type EventBoxProps = ConstructProps<typeof Astal.EventBox, AstalT.EventBox.ConstructorProperties>