summaryrefslogtreecommitdiff
path: root/examples/gtk3/js
diff options
context:
space:
mode:
authorAylur <[email protected]>2025-01-16 18:18:36 +0100
committerAylur <[email protected]>2025-01-16 18:18:41 +0100
commit8e00ed94760379ccba1ca04c8bcd069afaf30484 (patch)
tree03bd4fca2234db4ce6d4f2bdec7bca96b7e7f7ac /examples/gtk3/js
parent9e8634d892c559c5b44565a68bf35b13cbcb5572 (diff)
add: OSD ts example #195
Diffstat (limited to 'examples/gtk3/js')
-rw-r--r--examples/gtk3/js/osd/README.md7
-rw-r--r--examples/gtk3/js/osd/app.ts11
-rw-r--r--examples/gtk3/js/osd/osd/OSD.scss30
-rw-r--r--examples/gtk3/js/osd/osd/OSD.tsx69
-rw-r--r--examples/gtk3/js/osd/osd/brightness.ts45
-rw-r--r--examples/gtk3/js/osd/style.scss1
6 files changed, 163 insertions, 0 deletions
diff --git a/examples/gtk3/js/osd/README.md b/examples/gtk3/js/osd/README.md
new file mode 100644
index 0000000..ee1d497
--- /dev/null
+++ b/examples/gtk3/js/osd/README.md
@@ -0,0 +1,7 @@
+# On Screen Display
+
+![osd](https://github.com/user-attachments/assets/08e0e118-6b07-4cac-8ebc-08262594cee7)
+
+A simple widget that pops up when screen brightness or audio changes
+
+Uses the [WirePlumber library](https://aylur.github.io/astal/guide/libraries/wireplumber).
diff --git a/examples/gtk3/js/osd/app.ts b/examples/gtk3/js/osd/app.ts
new file mode 100644
index 0000000..50e314e
--- /dev/null
+++ b/examples/gtk3/js/osd/app.ts
@@ -0,0 +1,11 @@
+import { App } from "astal/gtk3"
+import style from "./style.scss"
+import OSD from "./osd/OSD"
+
+App.start({
+ instanceName: "osd-example",
+ css: style,
+ main() {
+ App.get_monitors().map(OSD)
+ },
+})
diff --git a/examples/gtk3/js/osd/osd/OSD.scss b/examples/gtk3/js/osd/osd/OSD.scss
new file mode 100644
index 0000000..d0fe4d1
--- /dev/null
+++ b/examples/gtk3/js/osd/osd/OSD.scss
@@ -0,0 +1,30 @@
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+
+window.OSD {
+ box.OSD {
+ border-radius: 100px;
+ background-color: $bg-color;
+ padding: 13px 16px;
+ margin: 13px;
+ box-shadow: 3px 3px 7px 0 rgba(0,0,0,.4);
+ }
+
+ icon {
+ font-size: 4rem;
+ }
+
+ label {
+ font-size: 2.4rem;
+ }
+
+ levelbar {
+ trough {
+ margin: 1 .6rem;
+ }
+
+ block {
+ min-height: 2rem;
+ }
+ }
+}
diff --git a/examples/gtk3/js/osd/osd/OSD.tsx b/examples/gtk3/js/osd/osd/OSD.tsx
new file mode 100644
index 0000000..df28da5
--- /dev/null
+++ b/examples/gtk3/js/osd/osd/OSD.tsx
@@ -0,0 +1,69 @@
+import { App, Astal, Gdk, Gtk } from "astal/gtk3"
+import { timeout } from "astal/time"
+import Variable from "astal/variable"
+import Brightness from "./brightness"
+import Wp from "gi://AstalWp"
+
+function OnScreenProgress({ visible }: { visible: Variable<boolean> }) {
+ const brightness = Brightness.get_default()
+ const speaker = Wp.get_default()!.get_default_speaker()
+
+ const iconName = Variable("")
+ const value = Variable(0)
+
+ let count = 0
+ function show(v: number, icon: string) {
+ visible.set(true)
+ value.set(v)
+ iconName.set(icon)
+ count++
+ timeout(2000, () => {
+ count--
+ if (count === 0) visible.set(false)
+ })
+ }
+
+ return (
+ <revealer
+ setup={(self) => {
+ self.hook(brightness, "notify::screen", () =>
+ show(brightness.screen, "display-brightness-symbolic"),
+ )
+
+ if (speaker) {
+ self.hook(speaker, "notify::volume", () =>
+ show(speaker.volume, speaker.volumeIcon),
+ )
+ }
+ }}
+ revealChild={visible()}
+ transitionType={Gtk.RevealerTransitionType.SLIDE_UP}
+ >
+ <box className="OSD">
+ <icon icon={iconName()} />
+ <levelbar valign={Gtk.Align.CENTER} widthRequest={100} value={value()} />
+ <label label={value(v => `${Math.floor(v * 100)}%`)} />
+ </box>
+ </revealer>
+ )
+}
+
+export default function OSD(monitor: Gdk.Monitor) {
+ const visible = Variable(false)
+
+ return (
+ <window
+ gdkmonitor={monitor}
+ className="OSD"
+ namespace="osd"
+ application={App}
+ layer={Astal.Layer.OVERLAY}
+ keymode={Astal.Keymode.ON_DEMAND}
+ anchor={Astal.WindowAnchor.BOTTOM}
+ >
+ <eventbox onClick={() => visible.set(false)}>
+ <OnScreenProgress visible={visible} />
+ </eventbox>
+ </window>
+ )
+}
diff --git a/examples/gtk3/js/osd/osd/brightness.ts b/examples/gtk3/js/osd/osd/brightness.ts
new file mode 100644
index 0000000..cf5060a
--- /dev/null
+++ b/examples/gtk3/js/osd/osd/brightness.ts
@@ -0,0 +1,45 @@
+import GObject, { register, property } from "astal/gobject"
+import { monitorFile, readFileAsync } from "astal/file"
+import { exec, execAsync } from "astal/process"
+
+const get = (args: string) => Number(exec(`brightnessctl ${args}`))
+const screen = exec(`bash -c "ls -w1 /sys/class/backlight | head -1"`)
+
+@register({ GTypeName: "Brightness" })
+export default class Brightness extends GObject.Object {
+ static instance: Brightness
+ static get_default() {
+ if (!this.instance)
+ this.instance = new Brightness()
+
+ return this.instance
+ }
+
+ #screenMax = get("max")
+ #screen = get("get") / (get("max") || 1)
+
+ @property(Number)
+ get screen() { return this.#screen }
+
+ set screen(percent) {
+ if (percent < 0)
+ percent = 0
+
+ if (percent > 1)
+ percent = 1
+
+ execAsync(`brightnessctl set ${Math.floor(percent * 100)}% -q`).then(() => {
+ this.#screen = percent
+ this.notify("screen")
+ })
+ }
+
+ constructor() {
+ super()
+ monitorFile(`/sys/class/backlight/${screen}/brightness`, async f => {
+ const v = await readFileAsync(f)
+ this.#screen = Number(v) / this.#screenMax
+ this.notify("screen")
+ })
+ }
+}
diff --git a/examples/gtk3/js/osd/style.scss b/examples/gtk3/js/osd/style.scss
new file mode 100644
index 0000000..ba6f06d
--- /dev/null
+++ b/examples/gtk3/js/osd/style.scss
@@ -0,0 +1 @@
+@use "./osd/OSD.scss";