summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/default.nix240
-rw-r--r--docs/guide/getting-started/installation.md8
-rw-r--r--docs/guide/getting-started/introduction.md12
-rw-r--r--docs/guide/getting-started/nix.md38
-rw-r--r--docs/guide/getting-started/supported-languages.md23
-rw-r--r--docs/guide/libraries/apps.md4
-rw-r--r--docs/guide/libraries/battery.md4
-rw-r--r--docs/guide/libraries/bluetooth.md4
-rw-r--r--docs/guide/libraries/greet.md4
-rw-r--r--docs/guide/libraries/hyprland.md4
-rw-r--r--docs/guide/libraries/mpris.md4
-rw-r--r--docs/guide/libraries/network.md4
-rw-r--r--docs/guide/libraries/notifd.md4
-rw-r--r--docs/guide/libraries/powerprofiles.md4
-rw-r--r--docs/guide/libraries/tray.md19
-rw-r--r--docs/guide/libraries/wireplumber.md2
-rw-r--r--docs/guide/lua/binding.md21
-rw-r--r--docs/guide/lua/examples.md11
-rw-r--r--docs/guide/typescript/cli-app.md6
-rw-r--r--docs/guide/typescript/examples.md11
-rw-r--r--docs/guide/typescript/faq.md42
-rw-r--r--docs/guide/typescript/first-widgets.md24
-rw-r--r--docs/guide/typescript/theming.md17
-rw-r--r--docs/guide/typescript/widget.md381
-rw-r--r--docs/package.json2
-rw-r--r--docs/public/showcase/aylur.pngbin3202086 -> 0 bytes
-rw-r--r--docs/public/showcase/aylur.webpbin0 -> 59972 bytes
-rw-r--r--docs/public/showcase/ezerinz.webpbin0 -> 191114 bytes
-rw-r--r--docs/public/showcase/hyprpanel_showcase.webpbin0 -> 87210 bytes
-rw-r--r--docs/public/showcase/tokyob0t.webp (renamed from docs/public/showcase/tokyob0t-super-duper-hiper-mega-ultra-contribution.webp)bin122412 -> 122412 bytes
-rw-r--r--docs/public/vitepress-logo-large.webpbin33980 -> 0 bytes
-rw-r--r--docs/showcases/showcases.ts20
32 files changed, 597 insertions, 316 deletions
diff --git a/docs/default.nix b/docs/default.nix
index 3eae600..5c7a8c7 100644
--- a/docs/default.nix
+++ b/docs/default.nix
@@ -2,239 +2,15 @@
self,
pkgs,
}: let
- inherit (builtins) replaceStrings readFile;
- readVer = file: replaceStrings ["\n"] [""] (readFile file);
+ inherit (builtins) removeAttrs concatStringsSep map attrValues;
+ packages = attrValues (removeAttrs self.packages.${pkgs.system} ["default" "docs" "gjs"]);
- toTOML = (pkgs.formats.toml {}).generate;
+ cp = pkg: ''
+ doc="${pkg.doc}/share/doc"
+ name=$(ls $doc)
- docgen = pkgs.gi-docgen.overrideAttrs {
- patches = [../nix/doc/gi-docgen.patch];
- };
-
- genLib = {
- flakepkg,
- gir,
- version,
- description,
- api-ver ? "0.1",
- authors ? "Aylur",
- dependencies ? {},
- out ? "libastal/${flakepkg}",
- browse ? flakepkg,
- website ? flakepkg,
- }: let
- name = "Astal${gir}-${api-ver}";
- src = self.packages.${pkgs.system}.${flakepkg}.dev;
-
- data = toTOML gir {
- library = {
- inherit description authors;
- version = readVer version;
- license = "LGPL-2.1";
- browse_url = "https://github.com/Aylur/astal/tree/main/lib/${browse}";
- repository_url = "https://github.com/aylur/aylur.git";
- website_url = "https://aylur.github.io/astal/guide/libraries/${website}";
- dependencies = ["GObject-2.0"] ++ (builtins.attrNames dependencies);
- };
-
- extra.urlmap_file = "urlmap.js";
- dependencies = {inherit (dependency) "GObject-2.0";} // dependencies;
- };
- in ''
- mkdir -p $out/${out}
- cat ${urlmap} > urlmap.js
- gi-docgen generate -C ${data} ${src}/share/gir-1.0/${name}.gir
- cp -r ${name}/* $out/${out}
- '';
-
- dependency = {
- "GObject-2.0" = {
- name = "GObject";
- description = "The base type system library";
- docs_url = "https://docs.gtk.org/gobject/";
- };
- "Gtk-3.0" = {
- name = "Gtk";
- description = "The GTK toolkit";
- docs_url = "https://docs.gtk.org/gtk3/";
- };
- "Gtk-4.0" = {
- name = "Gtk";
- description = "The GTK toolkit";
- docs_url = "https://docs.gtk.org/gtk4/";
- };
- "AstalIO-0.1" = {
- name = "AstalIO";
- description = "Astal Core library";
- docs_url = "https://aylur.github.io/libastal/io";
- };
- "NM-1.0" = {
- name = "NetworkManager";
- description = "The standard Linux network configuration tool suite";
- docs_url = "https://networkmanager.dev/docs/libnm/latest/";
- };
- "WP-0.5" = {
- name = "WirePlumber";
- description = "Modular session/policy manager for PipeWire";
- docs_url = "https://pipewire.pages.freedesktop.org/wireplumber/";
- };
- };
-
- urlmap = pkgs.writeText "urlmap" ''
- baseURLs = ${builtins.toJSON [
- ["GLib" "https://docs.gtk.org/glib/"]
- ["GObject" "https://docs.gtk.org/gobject/"]
- ["Gio" "https://docs.gtk.org/gio/"]
- ["Gdk" "https://docs.gtk.org/gdk3/"]
- ["Gtk" "https://docs.gtk.org/gtk3/"]
- ["GdkPixbuf" "https://docs.gtk.org/gdk-pixbuf/"]
- ["AstalIO" "https://aylur.github.io/libastal/io"]
-
- # FIXME: these are not gi-docgen generated, therefore links are broken
- ["NM" "https://networkmanager.dev/docs/libnm/latest/"]
- ["WP" "https://pipewire.pages.freedesktop.org/wireplumber/"]
- ]}
+ mkdir -p "$out/$name"
+ cp -r "$doc/$name" $out
'';
in
- pkgs.stdenvNoCC.mkDerivation {
- name = "reference";
- src = ./.;
-
- nativeBuildInputs = with pkgs; [
- docgen
- glib
- json-glib
- gobject-introspection
- gtk3
- gtk4
- gtk-layer-shell
- gtk4-layer-shell
- gdk-pixbuf
- libdbusmenu-gtk3
- wireplumber
- networkmanager
- self.packages.${system}.io
- ];
-
- installPhase = ''
- runHook preInstall
- ${genLib {
- flakepkg = "io";
- gir = "IO";
- api-ver = "0.1";
- browse = "astal/io";
- description = "Astal Core library";
- version = ../lib/astal/io/version;
- }}
- ${genLib {
- flakepkg = "astal3";
- gir = "";
- api-ver = "3.0";
- browse = "astal/gtk3";
- description = "Astal GTK3 widget library";
- version = ../lib/astal/gtk3/version;
- dependencies = {inherit (dependency) "AstalIO-0.1" "Gtk-3.0";};
- }}
- ${genLib {
- flakepkg = "astal4";
- gir = "";
- api-ver = "4.0";
- browse = "astal/gtk4";
- description = "Astal GTK4 widget library";
- version = ../lib/astal/gtk4/version;
- dependencies = {inherit (dependency) "AstalIO-0.1" "Gtk-4.0";};
- }}
- ${genLib {
- flakepkg = "apps";
- gir = "Apps";
- description = "Application query library";
- version = ../lib/apps/version;
- }}
- ${genLib {
- flakepkg = "auth";
- gir = "Auth";
- authors = "kotontrion";
- description = "Authentication using pam";
- version = ../lib/auth/version;
- }}
- ${genLib {
- flakepkg = "battery";
- gir = "Battery";
- description = "DBus proxy for upowerd devices";
- version = ../lib/battery/version;
- }}
- ${genLib {
- flakepkg = "bluetooth";
- gir = "Bluetooth";
- description = "DBus proxy for bluez";
- version = ../lib/bluetooth/version;
- }}
- ${genLib {
- flakepkg = "cava";
- gir = "Cava";
- description = "Audio visualization library using cava";
- version = ../lib/cava/version;
- authors = "kotontrion";
- }}
- ${genLib {
- flakepkg = "greet";
- gir = "Greet";
- description = "IPC client for greetd";
- version = ../lib/greet/version;
- }}
- ${genLib {
- flakepkg = "hyprland";
- gir = "Hyprland";
- description = "IPC client for Hyprland";
- version = ../lib/hyprland/version;
- }}
- ${genLib {
- flakepkg = "mpris";
- gir = "Mpris";
- description = "Control mpris players";
- version = ../lib/mpris/version;
- }}
- ${genLib {
- flakepkg = "network";
- gir = "Network";
- description = "NetworkManager wrapper library";
- version = ../lib/network/version;
- dependencies = {inherit (dependency) "NM-1.0";}; # FIXME: why does this not work?
- }}
- ${genLib {
- flakepkg = "notifd";
- gir = "Notifd";
- description = "Notification daemon library";
- version = ../lib/notifd/version;
- }}
- ${genLib {
- flakepkg = "powerprofiles";
- gir = "PowerProfiles";
- description = "DBus proxy for upowerd profiles";
- version = ../lib/powerprofiles/version;
- }}
- ${genLib {
- flakepkg = "river";
- gir = "River";
- description = "IPC client for River";
- version = ../lib/river/version;
- authors = "kotontrion";
- }}
- ${genLib {
- flakepkg = "tray";
- gir = "Tray";
- description = "StatusNotifierItem implementation";
- version = ../lib/tray/version;
- authors = "kotontrion";
- }}
- ${genLib {
- flakepkg = "wireplumber";
- gir = "Wp";
- description = "Wrapper library over the wireplumber API";
- version = ../lib/wireplumber/version;
- authors = "kotontrion";
- dependencies = {inherit (dependency) "WP-0.5";}; # FIXME: why does this not work?
- }}
- runHook postInstall
- '';
- }
+ pkgs.runCommand "docs" {} (concatStringsSep "" (map cp packages))
diff --git a/docs/guide/getting-started/installation.md b/docs/guide/getting-started/installation.md
index e32b6a9..0cda3c5 100644
--- a/docs/guide/getting-started/installation.md
+++ b/docs/guide/getting-started/installation.md
@@ -22,22 +22,22 @@ maintainer: [@Aylur](https://github.com/Aylur)
Read more about it on the [nix page](./nix#astal)
-## Bulding From Source
+## Building From Source
1. Install the following dependencies
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala gtk3 gtk-layer-shell gobject-introspection
+sudo pacman -Syu meson vala valadoc gtk3 gtk-layer-shell gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
-sudo dnf install meson vala valadoc gtk3-devel gtk-layer-shell-devel gobject-introspection-devel
+sudo dnf install meson vala valadoc gtk3-devel gtk-layer-shell-devel gobject-introspection-devel wayland-protocols-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libgtk-3-dev libgtk-layer-shell-dev gobject-introspection libgirepository1.0-dev
+sudo apt install meson valac valadoc libgtk-3-dev libgtk-layer-shell-dev gobject-introspection libgirepository1.0-dev
```
:::
diff --git a/docs/guide/getting-started/introduction.md b/docs/guide/getting-started/introduction.md
index 782c069..43a7bd8 100644
--- a/docs/guide/getting-started/introduction.md
+++ b/docs/guide/getting-started/introduction.md
@@ -2,13 +2,15 @@
## What is Astal?
-Astal (_meaning "desk"_) is a suite of libraries in Vala and C.
+Astal (_meaning "desk"_) is a suite of libraries written in Vala and C.
The core library [astal3](https://aylur.github.io/libastal/astal3) and
-[astal4](https://aylur.github.io/libastal/astal4) (not yet available)
-has some Gtk widgets that come packaged,
+[astal4](https://aylur.github.io/libastal/astal4)
+have some Gtk widgets that come packaged,
the most important one being the [Window](https://aylur.github.io/libastal/astal3/class.Window.html) which is the main toplevel component using [gtk-layer-shell](https://github.com/wmww/gtk-layer-shell).
This is what allows us to use Gtk as shell components on Wayland.
-The other part of the core library [astal-io](https://aylur.github.io/libastal/astal-io)
+The other component is [Application](https://aylur.github.io/libastal/astal3/class.Application.html)
+which provides a way to send messages from the cli to running Astal instances.
+The other part of the core library is [astal-io](https://aylur.github.io/libastal/astal-io)
which contains some utility GLib shortcut for running external processes,
reading, writing and monitoring files, timeout and interval functions.
@@ -23,4 +25,4 @@ or an applauncher, but gave up because writing a workspace widget,
implementing the notification daemon or handling a search filter was too much of a hassle?
Astal libraries have you [covered](../libraries/references#astal-libraries), you don't have to worry about these,
-you just define the layout, style it with CSS and that's it.
+you just define the layout, style with CSS hook up the state from libraries you want and that's it.
diff --git a/docs/guide/getting-started/nix.md b/docs/guide/getting-started/nix.md
index 6bc5d9b..3ded888 100644
--- a/docs/guide/getting-started/nix.md
+++ b/docs/guide/getting-started/nix.md
@@ -5,7 +5,43 @@ next:
---
# Nix
-Using Astal on Nix will require you to package your project.
+Using Astal on Nix will require you to write a derivation for your project.
+You can either copy and build off of these example flakes or you can
+incorporate the derivations into your existing flake/configuration.
+
+## Installing libraries versus installing executables
+
+In case you did not know already,
+you can't install libraries globally on Nix as you would with regular
+package managers like `pacman`, `dnf` or `apt`. You have to write a
+derivation for your projects like you would for any other program.
+If you try to install a library through `home.packages` or `environment.systemPackages`
+don't expect it to be picked up from runtimes.
+
+However, if you want to use the CLI tool that comes with some of the libraries
+you have to **also** install them through `home.packages` or `environment.systemPackages`
+alongside your derivations.
+
+### Astal CLI
+
+The core library also comes with a CLI tool that you can use to send
+requests to your app.
+
+:::code-group
+
+```nix [nixos]
+environment.systemPackages = [inputs.astal.packages.${system}.default];
+```
+
+```nix [home-manager]
+home.packages = [inputs.astal.packages.${system}.default];
+```
+
+:::
+
+```sh [astal cli]
+astal --list # list running instances
+```
## TypeScript
diff --git a/docs/guide/getting-started/supported-languages.md b/docs/guide/getting-started/supported-languages.md
index eacd1da..c38a001 100644
--- a/docs/guide/getting-started/supported-languages.md
+++ b/docs/guide/getting-started/supported-languages.md
@@ -18,16 +18,16 @@ The runtime is [GJS](https://gitlab.gnome.org/GNOME/gjs) and **not** nodejs
Examples:
-- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/js/simple-bar)
+- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
-- [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/js/notifications)
+- [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/notifications)
![notification-popups](https://github.com/user-attachments/assets/0df0eddc-5c74-4af0-a694-48dc8ec6bb44)
-- [Applauncher](https://github.com/Aylur/astal/tree/main/examples/js/applauncher)
+- [Applauncher](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/applauncher)
![launcher](https://github.com/user-attachments/assets/2695e3bb-dff4-478a-b392-279fe638bfd3)
-- [Media Player](https://github.com/Aylur/astal/tree/main/examples/js/media-player)
+- [Media Player](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/media-player)
![media-player](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)
## Lua
@@ -36,9 +36,18 @@ Lua is well-supported, but I would still recommend TypeScript, as Lua lacks a ty
Examples:
-- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/lua/simple-bar)
+- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/lua/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
+- [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/lua/notifications)
+![notification-popups](https://github.com/user-attachments/assets/0df0eddc-5c74-4af0-a694-48dc8ec6bb44)
+
+- [Applauncher](https://github.com/Aylur/astal/tree/main/examples/lua/applauncher)
+![launcher](https://github.com/user-attachments/assets/2695e3bb-dff4-478a-b392-279fe638bfd3)
+
+- [Media Player](https://github.com/Aylur/astal/tree/main/examples/lua/media-player)
+![media-player](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)
+
## Python
There is a WIP [package for python](https://github.com/aylur/astal/tree/feat/python),
@@ -47,7 +56,7 @@ However, you can still use python the OOP way [pygobject](https://pygobject.gnom
Examples:
-- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/py/simple-bar)
+- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/py/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
## Vala
@@ -58,7 +67,7 @@ using TypeScript or Lua over Vala as they are simpler to work with.
Examples:
-- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/vala/simple-bar)
+- [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/vala/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
## C
diff --git a/docs/guide/libraries/apps.md b/docs/guide/libraries/apps.md
index f1748db..4dba9ba 100644
--- a/docs/guide/libraries/apps.md
+++ b/docs/guide/libraries/apps.md
@@ -80,7 +80,7 @@ foreach (var app in apps.fuzzy_query("firefox")) {
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -88,7 +88,7 @@ sudo dnf install meson vala valadoc json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/battery.md b/docs/guide/libraries/battery.md
index 7e6fe24..0a06532 100644
--- a/docs/guide/libraries/battery.md
+++ b/docs/guide/libraries/battery.md
@@ -53,7 +53,7 @@ print(battery.percentage)
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -61,7 +61,7 @@ sudo dnf install meson vala valadoc json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/bluetooth.md b/docs/guide/libraries/bluetooth.md
index 9a3e5b8..e1e7508 100644
--- a/docs/guide/libraries/bluetooth.md
+++ b/docs/guide/libraries/bluetooth.md
@@ -60,7 +60,7 @@ end
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala gobject-introspection
+sudo pacman -Syu meson vala valadoc gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -68,7 +68,7 @@ sudo dnf install meson vala valadoc gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac gobject-introspection
+sudo apt install meson valac valadoc gobject-introspection
```
:::
diff --git a/docs/guide/libraries/greet.md b/docs/guide/libraries/greet.md
index 47f98b9..9c2f1b7 100644
--- a/docs/guide/libraries/greet.md
+++ b/docs/guide/libraries/greet.md
@@ -61,7 +61,7 @@ try {
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -69,7 +69,7 @@ sudo dnf install meson vala valadoc json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/hyprland.md b/docs/guide/libraries/hyprland.md
index 82d9e9d..5eefa2e 100644
--- a/docs/guide/libraries/hyprland.md
+++ b/docs/guide/libraries/hyprland.md
@@ -58,7 +58,7 @@ end
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -66,7 +66,7 @@ sudo dnf install meson vala valadoc json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/mpris.md b/docs/guide/libraries/mpris.md
index c2283cc..768bb45 100644
--- a/docs/guide/libraries/mpris.md
+++ b/docs/guide/libraries/mpris.md
@@ -61,7 +61,7 @@ end
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala gvfs json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc gvfs json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -69,7 +69,7 @@ sudo dnf install meson vala valadoc gvfs json-glib-devel gobject-introspection-d
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac gvfs libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc gvfs libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/network.md b/docs/guide/libraries/network.md
index 79a217c..0d9d6a8 100644
--- a/docs/guide/libraries/network.md
+++ b/docs/guide/libraries/network.md
@@ -55,7 +55,7 @@ print(network.wifi.ssid)
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala libnm gobject-introspection
+sudo pacman -Syu meson vala valadoc libnm gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -63,7 +63,7 @@ sudo dnf install meson vala valadoc NetworkManager-libnm-devel gobject-introspec
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libnm-dev gobject-introspection
+sudo apt install meson valac valadoc libnm-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/notifd.md b/docs/guide/libraries/notifd.md
index 1d61099..4112f94 100644
--- a/docs/guide/libraries/notifd.md
+++ b/docs/guide/libraries/notifd.md
@@ -67,7 +67,7 @@ end
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala gdk-pixbuf2 json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc gdk-pixbuf2 json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -75,7 +75,7 @@ sudo dnf install meson vala valadoc gdk-pixbuf2-devel json-glib-devel gobject-in
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libgdk-pixbuf-2.0-dev libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libgdk-pixbuf-2.0-dev libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/powerprofiles.md b/docs/guide/libraries/powerprofiles.md
index b42d7c6..a9e7559 100644
--- a/docs/guide/libraries/powerprofiles.md
+++ b/docs/guide/libraries/powerprofiles.md
@@ -53,7 +53,7 @@ print(powerprofiles.active_profile)
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala json-glib gobject-introspection
+sudo pacman -Syu meson vala valadoc json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
@@ -61,7 +61,7 @@ sudo dnf install meson vala valadoc json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson valac libjson-glib-dev gobject-introspection
+sudo apt install meson valac valadoc libjson-glib-dev gobject-introspection
```
:::
diff --git a/docs/guide/libraries/tray.md b/docs/guide/libraries/tray.md
index 43b3aa6..a7d4c33 100644
--- a/docs/guide/libraries/tray.md
+++ b/docs/guide/libraries/tray.md
@@ -58,27 +58,36 @@ end
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson gtk3 gobject-introspection libdbusmenu-gtk3
+sudo pacman -Syu meson json-glib gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
-sudo dnf install meson gcc gtk3-devel libdbusmenu-gtk3-devel gobject-introspection-devel
+sudo dnf install meson json-glib-devel gobject-introspection-devel
```
```sh [<i class="devicon-ubuntu-plain"></i> Ubuntu]
-sudo apt install meson libgtk-3-dev libdbusmenu-gtk3-dev gobject-introspection
+sudo apt install meson libjson-glib-dev gobject-introspection
```
:::
-2. clone repo
+2. install `appmenu-glib-translator`
+
+```sh
+git clone https://github.com/rilian-la-te/vala-panel-appmenu.git
+cd vala-panel-appmenu/subprojects/appmenu-glib-translator
+meson setup --prefix /usr build
+meson install -C build
+```
+
+3. clone repo
```sh
git clone https://github.com/aylur/astal.git
cd astal/lib/tray
```
-3. install
+4. install
```sh
meson setup --prefix /usr build
diff --git a/docs/guide/libraries/wireplumber.md b/docs/guide/libraries/wireplumber.md
index d6faea1..b3dbf6d 100644
--- a/docs/guide/libraries/wireplumber.md
+++ b/docs/guide/libraries/wireplumber.md
@@ -55,7 +55,7 @@ print(audio.default_speaker.volume)
:::code-group
```sh [<i class="devicon-archlinux-plain"></i> Arch]
-sudo pacman -Syu meson vala wireplumber gobject-introspection
+sudo pacman -Syu meson vala valadoc wireplumber gobject-introspection
```
```sh [<i class="devicon-fedora-plain"></i> Fedora]
diff --git a/docs/guide/lua/binding.md b/docs/guide/lua/binding.md
index f4d5f0b..f9957b5 100644
--- a/docs/guide/lua/binding.md
+++ b/docs/guide/lua/binding.md
@@ -68,12 +68,13 @@ local Gtk = require("astal.gtk3").Gtk
local Variable = require("astal.variable")
---@param initial table
+---@return varmap
return function(initial)
local map = initial
- local var = Variable()
+ local var = Variable.new({})
local function notify()
- local arr
+ local arr = {}
for _, value in pairs(map) do
table.insert(arr, value)
end
@@ -90,7 +91,13 @@ return function(initial)
notify() -- init
- return {
+ ---@class varmap
+ ---@field set fun(key: any, value: any): nil
+ ---@field delete fun(key: any): nil
+ ---@field get fun(): any
+ ---@field subscribe fun(callback: function): function
+ ---@overload fun(): Binding
+ return setmetatable({
set = function(key, value)
delete(key)
map[key] = value
@@ -106,7 +113,11 @@ return function(initial)
subscribe = function(callback)
return var:subscribe(callback)
end,
- }
+ }, {
+ __call = function()
+ return var()
+ end,
+ })
end
```
@@ -130,7 +141,7 @@ function MappedBox()
map.delete(id)
end)
end,
- bind(map):as(function (arr)
+ map():as(function(arr)
-- can be sorted here
return arr
end),
diff --git a/docs/guide/lua/examples.md b/docs/guide/lua/examples.md
index be46b6e..464f917 100644
--- a/docs/guide/lua/examples.md
+++ b/docs/guide/lua/examples.md
@@ -1,4 +1,13 @@
# Lua examples
-## [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/lua/simple-bar)
+## [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/lua/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
+
+### [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/gtk3/lua/notifications)
+![notification-popups](https://github.com/user-attachments/assets/0df0eddc-5c74-4af0-a694-48dc8ec6bb44)
+
+### [Applauncher](https://github.com/Aylur/astal/tree/main/examples/gtk3/lua/applauncher)
+![launcher](https://github.com/user-attachments/assets/2695e3bb-dff4-478a-b392-279fe638bfd3)
+
+### [Media Player](https://github.com/Aylur/astal/tree/main/examples/gtk3/lua/media-player)
+![media-player](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)
diff --git a/docs/guide/typescript/cli-app.md b/docs/guide/typescript/cli-app.md
index 9b299aa..41b1d7c 100644
--- a/docs/guide/typescript/cli-app.md
+++ b/docs/guide/typescript/cli-app.md
@@ -26,7 +26,7 @@ App.start({
## Instance identifier
-You can run multiple instance by defining a unique instance name.
+You can run multiple instances by defining a unique instance name.
```ts
App.start({
@@ -44,7 +44,7 @@ you can do so by sending a message.
App.start({
requestHandler(request: string, res: (response: any) => void) {
if (request == "say hi") {
- res("hi cli")
+ return res("hi cli")
}
res("unknown command")
},
@@ -140,7 +140,7 @@ App.start({
// every subsequent calls
client(message: (msg: string) => string, ...args: Array<string>) {
const res = message("you can message the main instance")
- console.log(res)
+ print(res)
},
// this runs in the main instance
diff --git a/docs/guide/typescript/examples.md b/docs/guide/typescript/examples.md
index ec51e89..81a6f35 100644
--- a/docs/guide/typescript/examples.md
+++ b/docs/guide/typescript/examples.md
@@ -2,13 +2,16 @@
## Gtk3
-### [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/js/simple-bar)
+### [Simple Bar](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/simple-bar)
![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
-### [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/js/notifications)
+### [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/notifications)
![notification-popups](https://github.com/user-attachments/assets/0df0eddc-5c74-4af0-a694-48dc8ec6bb44)
-### [Applauncher](https://github.com/Aylur/astal/tree/main/examples/js/applauncher)
+### [Applauncher](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/applauncher)
![launcher](https://github.com/user-attachments/assets/2695e3bb-dff4-478a-b392-279fe638bfd3)
-### [Media Player](https://github.com/Aylur/astal/tree/main/examples/js/media-player)
+### [Media Player](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/media-player)
![media-player](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)
+
+### [OSD](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/osd)
+![osd](https://github.com/user-attachments/assets/08e0e118-6b07-4cac-8ebc-08262594cee7)
diff --git a/docs/guide/typescript/faq.md b/docs/guide/typescript/faq.md
index 4ee616b..15a97e5 100644
--- a/docs/guide/typescript/faq.md
+++ b/docs/guide/typescript/faq.md
@@ -55,14 +55,14 @@ const HOME = GLib.getenv("HOME")
## Custom SVG symbolic icons
-Put the svgs in a directory, named `<icon-name>-symbolic.svg`
+Put the svgs in a directory, name them `<icon-name>-symbolic.svg`
and use `App.add_icons` or `icons` parameter in `App.start`
:::code-group
```ts [app.ts]
App.start({
- icons: `${SRC}/icons`,
+ icons: `/path/to/icons`, // this dir should include custom-symbolic.svg
main() {
Widget.Icon({
icon: "custom-symbolic", // custom-symbolic.svg
@@ -269,3 +269,41 @@ class MyWidget extends Widget.Box {
}
}
```
+
+## How do I register keybindings?
+
+If you want global keybindings use your compositor.
+Only **focused** windows can capture events. To make a window
+focusable set its keymode.
+
+::: code-group
+```tsx [gtk3]
+<window
+ keymode={Astal.Keymode.ON_DEMAND}
+ onKeyPressEvent={(self, event: Gdk.Event) => {
+ if (event.get_keyval()[1] === Gdk.KEY_Escape) {
+ self.hide()
+ }
+ }}
+/>
+```
+
+```tsx [gtk4]
+<window
+ keymode={Astal.Keymode.ON_DEMAND}
+ onKeyPressed={(self, keyval) => {
+ if (keyval === Gdk.KEY_Escape) {
+ self.hide()
+ }
+ }}
+/>
+```
+:::
+
+## How to create a Popup
+
+In Gtk4 simply use Gtk's builtin [Popover](https://docs.gtk.org/gtk4/class.Popover.html).
+
+In Gtk3 you can create an [Astal.Window](https://aylur.github.io/libastal/astal3/class.Window.html) and handle click events.
+
+Checkout [examples/gtk3/js/popover](https://github.com/Aylur/astal/tree/main/examples/gtk3/js/popover)
diff --git a/docs/guide/typescript/first-widgets.md b/docs/guide/typescript/first-widgets.md
index 77b2f61..9b8bf32 100644
--- a/docs/guide/typescript/first-widgets.md
+++ b/docs/guide/typescript/first-widgets.md
@@ -71,7 +71,7 @@ function MyButton(): JSX.Element {
}
```
-```ts [MyButton.ts]
+```ts [MyButton.ts (gtk3)]
import { Widget } from "astal/gtk3"
function MyButton(): Widget.Button {
@@ -82,6 +82,17 @@ function MyButton(): Widget.Button {
}
```
+```ts [MyButton.ts (gtk4)]
+import { Widget } from "astal/gtk4"
+
+function MyButton(): Widget.Button {
+ return Widget.Button(
+ { onClicked: "echo hello" },
+ Widget.Label({ label: "Click me!" }),
+ )
+}
+```
+
:::
:::info
@@ -218,6 +229,14 @@ Their types are not generated, but written by hand, which means not all of them
Refer to the Gtk and Astal docs to have a full list of them.
:::
+:::info
+Attributes prefixed with `onNotify` will connect to a `notify::` signal of the widget.
+
+```tsx
+<switch onNotifyActive={self => print("switched to", self.active)}>
+```
+:::
+
## How properties are passed
Using JSX, a custom widget will always have a single object as its parameter.
@@ -413,8 +432,7 @@ function Parent(props: {
:::tip
If you have a widget where you pass widgets in various ways, you can
-wrap `child` in `children` in a [`Subscribable`](./faq#custom-widgets-with-bindable-properties) and handle all cases
-as if they were bindings.
+wrap `child` and `children` props in a [`Subscribable`](./faq#custom-widgets-with-bindable-properties) and handle all cases as if they were bindings.
:::
:::info
diff --git a/docs/guide/typescript/theming.md b/docs/guide/typescript/theming.md
index 5944c4e..4cb3486 100644
--- a/docs/guide/typescript/theming.md
+++ b/docs/guide/typescript/theming.md
@@ -1,24 +1,25 @@
# Theming
-Since the widget toolkit is **GTK3** theming is done with **CSS**.
+Since the widget toolkit is **GTK** theming is done with **CSS**.
- [CSS tutorial](https://www.w3schools.com/css/)
-- [GTK CSS Overview wiki](https://docs.gtk.org/gtk3/css-overview.html)
-- [GTK CSS Properties Overview wiki](https://docs.gtk.org/gtk3/css-properties.html)
+- [GTK3 CSS Overview wiki](https://docs.gtk.org/gtk3/css-overview.html)
+- [GTK3 CSS Properties Overview wiki](https://docs.gtk.org/gtk3/css-properties.html)
+- [GTK4 CSS Overview wiki](https://docs.gtk.org/gtk4/css-overview.html)
+- [GTK4 CSS Properties Overview wiki](https://docs.gtk.org/gtk4/css-properties.html)
:::warning GTK is not the web
While most features are implemented in GTK,
you can't assume anything that works on the web will work with GTK.
-Refer to the [GTK docs](https://docs.gtk.org/gtk3/css-overview.html)
-to see what is available.
+Refer to the GTK docs to see what is available.
:::
-So far every widget you made used your default GTK3 theme.
+So far every widget you made used your default GTK theme.
To make them more custom, you can apply stylesheets to them.
## From file at startup
-You can pass a path to a file or css as a string in `App.start`
+You can pass a path to a file or CSS as a string in `App.start`
:::code-group
@@ -118,7 +119,7 @@ npm install -g sass # not packaged on Ubuntu
```ts [app.ts]
import { exec } from "astal/process"
-exec("sass", "./style.scss", "/tmp/style.css")
+exec("sass ./style.scss /tmp/style.css")
App.start({
css: "/tmp/style.css",
diff --git a/docs/guide/typescript/widget.md b/docs/guide/typescript/widget.md
index 7ed69e3..86e666b 100644
--- a/docs/guide/typescript/widget.md
+++ b/docs/guide/typescript/widget.md
@@ -6,15 +6,21 @@
These are properties that Astal additionally adds to Gtk.Widgets
-- className: `string` - List of class CSS selectors separated by white space.
-- css: `string` - Inline CSS. e.g `label { color: white; }`. If no selector is specified `*` will be assumed. e.g `color: white;` will be inferred as `* { color: white; }`.
-- cursor: `string` - Cursor style when hovering over widgets that have hover states, e.g it won't work on labels. [list of valid values](https://docs.gtk.org/gdk3/ctor.Cursor.new_from_name.html).
-- clickThrough: `boolean` - Lets click events through.
+- `className`: `string` - List of class CSS selectors separated by white space.
+- `css`: `string` - Inline CSS. e.g `label { color: white; }`. If no selector is specified `*` will be assumed. e.g `color: white;` will be inferred as `* { color: white; }`.
+- `cursor`: `string` - Cursor style when hovering over widgets that have hover states, e.g it won't work on labels. [list of valid values](https://docs.gtk.org/gdk3/ctor.Cursor.new_from_name.html).
+- `clickThrough`: `boolean` - Lets click events through.
To have a full list of available properties, reference the documentation of the widget.
- [Astal3 widgets](https://aylur.github.io/libastal/astal3/index.html#classes)
-- [Gtk widgets](https://docs.gtk.org/gtk3/#classes)
+- [Gtk3 widgets](https://docs.gtk.org/gtk3/#classes)
+
+Most common ones you will use frequently are
+ - [halign](https://docs.gtk.org/gtk3/property.Widget.halign.html)
+ - [valign](https://docs.gtk.org/gtk3/property.Widget.valign.html)
+ - [hexpand](https://docs.gtk.org/gtk3/property.Widget.hexpand.html)
+ - [vexpand](https://docs.gtk.org/gtk3/property.Widget.vexpand.html)
### Additional widget methods
@@ -27,7 +33,7 @@ without `setup`
```tsx
function MyWidget() {
- const button = Widget.Button()
+ const button = new Widget.Button()
// setup button
return button
}
@@ -94,14 +100,14 @@ function MyWidget() {
### How to use non builtin Gtk widgets
-Using the `Widget.astalify` mixin you can subclass widgets
+Using the `astalify` mixin you can subclass widgets
to behave like builtin widgets.
The `astalify` mixin will apply the following:
- set `visible` to true by default (Gtk3 widgets are invisible by default)
- make gobject properties accept and consume `Binding` objects
- add properties and methods listed above
-- sets up signal handlers that are passed as props prefixed with `on`
+- set up signal handlers that are passed as props prefixed with `on`
```tsx
import GObject from "gi://GObject"
@@ -135,7 +141,7 @@ function MyWidget() {
alpha: 0.5,
})}
onColorSet={(self) => {
- console.log(self.rgba)
+ print(self.rgba)
}}
/>
}
@@ -144,7 +150,7 @@ function MyWidget() {
:::info
Signal properties have to be annotated manually for TypeScript.
You can reference [Gtk3](https://gjs-docs.gnome.org/gtk30~3.0/)
-and [Astal](https://aylur.github.io/libastal/index.html#classes) for available signals.
+and [Astal3](https://aylur.github.io/libastal/astal3/#classes) for available signals.
:::
### TypeScript
@@ -189,28 +195,377 @@ export default function ToggleButton(btnprops: ToggleButtonProps) {
### Builtin Widgets
-You can check the [source code](https://github.com/aylur/astal/blob/main/lang/gjs/src/gtk3/index.ts) to have a full list of builtin widgets.
-
These widgets are available by default in JSX.
- box: [Astal.Box](https://aylur.github.io/libastal/astal3/class.Box.html)
+ ```tsx
+ <box>Horizontal Box</box>
+ ```
+ ```tsx
+ <box orientation={1}>Vertical Box</box>
+ ```
- button: [Astal.Button](https://aylur.github.io/libastal/astal3/class.Button.html)
+ ```tsx
+ <button onClicked={self => print(self, "was clicked")}>
+ Click Me
+ </button>
+ ```
- centerbox: [Astal.CenterBox](https://aylur.github.io/libastal/astal3/class.CenterBox.html)
+ ```tsx
+ <centerbox orientation={1}>
+ <label vexpand valign={Gtk.Align.START} label="Start Widget" />
+ <label label="Center Widget" />
+ <label vexpand valign={Gtk.Align.END} label="End Widget" />
+ </box>
+ ```
- circularprogress: [Astal.CircularProgress](https://aylur.github.io/libastal/astal3/class.CircularProgress.html)
+ ```tsx
+ <circularprogress value={.5} startAt={0.75} endAt={0.75}>
+ <icon />
+ </circularprogress>
+ ```
+ ```css
+ circularprogress {
+ color: green;
+ background-color: black;
+ font-size: 6px;
+ margin: 2px;
+ min-width: 32px;
+ }
+ ```
+
- drawingarea: [Gtk.DrawingArea](https://docs.gtk.org/gtk3/class.DrawingArea.html)
+ ```tsx
+ <drawingarea onDraw={drawingFunction} />
+ ```
+
- entry: [Gtk.Entry](https://docs.gtk.org/gtk3/class.Entry.html)
+ ```tsx
+ <window keymode={Astal.Keymode.ON_DEMAND}>
+ <entry
+ onChanged={self => print("text changed", self.text)}
+ onActivate={self => print("enter", self.text)}
+ />
+ </window>
+ ```
+
- eventbox: [Astal.EventBox](https://aylur.github.io/libastal/astal3/class.EventBox.html)
+ ```tsx
+ <eventbox
+ onClick={(_, event) => {
+ print(event.modifier, event.button)
+ }}
+ />
+ ```
+
- icon: [Astal.Icon](https://aylur.github.io/libastal/astal3/class.Icon.html)
+ ```tsx
+ <icon icon={GLib.get_os_info("LOGO") || "missing-symbolic"} />
+ ```
+ ```css
+ icon {
+ font-size: 16px;
+ }
+ ```
+
- label: [Astal.Label](https://aylur.github.io/libastal/astal3/class.Label.html)
+ ```tsx
+ <label label="hello" maxWidthChars={16} wrap />
+ ```
+
- levelbar: [Astal.LevelBar](https://aylur.github.io/libastal/astal3/class.LevelBar.html)
+ ```tsx
+ <levelbar value={0.5} widthRequest={200} />
+ ```
+
- overlay: [Astal.Overlay](https://aylur.github.io/libastal/astal3/class.Overlay.html)
+ ```tsx
+ <overlay>
+ <box heightRequest={40} widthRequest={40}>Child</box>
+ <box className="overlay" valign={Gtk.Align.START} halign={Gtk.Align.END}>1</box>
+ </overlay>
+ ```
+
- revealer: [Gtk.Revealer](https://docs.gtk.org/gtk3/class.Revealer.html)
+ ```tsx
+ <revealer
+ setup={self => timeout(500, () => self.revealChild = true)}
+ transitionType={Gtk.RevealerTransitionType.SLIDE_UP}>
+ <label label="Child" />
+ </revealer>
+ ```
+
- scrollable: [Astal.Scrollable](https://aylur.github.io/libastal/astal3/class.Scrollable.html)
+ ```tsx
+ <scrollable heightRequest={100}>
+ <box orientation={1}>
+ {Array.from({ length: 10 }, (_, i) => (
+ <button>{i}</button>
+ ))}
+ </box>
+ </scrollable>
+ ```
+
- slider: [Astal.Slider](https://aylur.github.io/libastal/astal3/class.Slider.html)
+ ```tsx
+ <slider widthRequest={100} onDragged={self => print("new value", self.value)} />
+ ```
+
- stack: [Astal.Stack](https://aylur.github.io/libastal/astal3/class.Stack.html)
+ ```tsx
+ <stack visibleChildName="child2">
+ <label name="child1" label="child1" />
+ <label name="child2" label="child2" />
+ </stack>
+ ```
+
- switch: [Gtk.Switch](https://docs.gtk.org/gtk3/class.Switch.html)
+ ```tsx
+ <switch onNotifyActive={self => print(self.active)} />
+ ```
+
- window: [Astal.Window](https://aylur.github.io/libastal/astal3/class.Window.html)
+ ```tsx
+ <window
+ className="Bar"
+ name="bar"
+ namespace="bar"
+ application={App}
+ monitor={0}
+ anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT}
+ exclusivity={Astal.Exclusivity.EXCLUSIVE}
+ keymode={Astal.Keymode.ON_DEMAND}
+ >
+ <centerbox />
+ </window>
+ ```
## Gtk4
-🚧 Work in Progress 🚧
+The Gtk4 js library does not add any additional properties to the widgets,
+but it still has some additional properties that the constructors handle.
+
+- `type`: `string` an arbitrary string that the [Buildable](https://docs.gtk.org/gtk4/iface.Buildable.html) interface uses.
+- event handlers for [EventControllers](https://docs.gtk.org/gtk4/class.EventController.html)
+ ```ts
+ type EventController<Self extends Gtk.Widget> = {
+ onFocusEnter?: (self: Self) => void
+ onFocusLeave?: (self: Self) => void
+
+ onKeyPressed?: (self: Self, keyval: number, keycode: number, state: Gdk.ModifierType) => void
+ onKeyReleased?: (self: Self, keyval: number, keycode: number, state: Gdk.ModifierType) => void
+ onKeyModifier?: (self: Self, state: Gdk.ModifierType) => void
+
+ onLegacy?: (self: Self, event: Gdk.Event) => void
+ onButtonPressed?: (self: Self, state: Gdk.ButtonEvent) => void
+ onButtonReleased?: (self: Self, state: Gdk.ButtonEvent) => void
+
+ onHoverEnter?: (self: Self, x: number, y: number) => void
+ onHoverLeave?: (self: Self) => void
+ onMotion?: (self: Self, x: number, y: number) => void
+
+ onScroll?: (self: Self, dx: number, dy: number) => void
+ onScrollDecelerate?: (self: Self, vel_x: number, vel_y: number) => void
+ }
+ ```
+
+- `setup`: `(self): void` setup function that runs after constructor
+ ```tsx
+ // without `setup`
+ function MyWidget() {
+ const button = Widget.Button()
+ // setup button
+ return button
+ }
+
+ // using `setup`
+ function MyWidget() {
+ function setup(button: Widget.Button) {
+ // setup button
+ }
+
+ return <buttons setup={setup} />
+ }
+ ```
+
+There is also a `hook` utility
+
+```tsx
+// without `hook`
+function MyWidget() {
+ const id = gobject.connect("signal", callback)
+ const unsub = variable.subscribe(callback)
+
+ return <box
+ onDestroy={() => {
+ gobject.disconnect(id)
+ unsub()
+ }}
+ />
+}
+
+// with `hook`
+import { hook } from "astal/gtk4"
+
+function MyWidget() {
+ return <box
+ setup={(self) => {
+ self.hook(gobject, "signal", callback)
+ self.hook(variable, callback)
+ }}
+ />
+}
+```
+
+### How to use non builtin Gtk widgets
+
+Using the `astalify` function you can create wrappers around widget constructors
+to make them behave like builtin widgets.
+The `astalify` function will do the followings:
+
+- make `gobject` properties accept and consume `Binding` objects
+- handle properties listed above
+- set up signal handlers that are passed as props prefixed with `on`
+
+```tsx
+import GObject from "gi://GObject"
+import { Gtk, astalify, type ConstructProps } from "astal/gtk4"
+
+type CalendarProps = ConstructProps<Gtk.Calendar, Gtk.Calendar.ConstructorProps>
+const Calendar = astalify<Gtk.Calendar, Gtk.Calendar.ConstructorProps>(Gtk.Calendar, {
+ // if it is a container widget, define children setter and getter here
+ getChildren(self) { return [] },
+ setChildren(self, children) {},
+})
+
+function MyWidget() {
+ function setup(button: Gtk.Calendar) {
+
+ }
+
+ return <Calendar
+ setup={setup}
+ onDaySelected={(self) => {
+ print(self.day)
+ }}
+ />
+}
+```
+
+### Builtin Widgets
+
+These widgets are available by default in JSX.
+
+- box: [Astal.Box](https://aylur.github.io/libastal/astal4/class.Box.html)
+ ```tsx
+ <box>Horizontal Box</box>
+ ```
+ ```tsx
+ <box orientation={1}>Vertical Box</box>
+ ```
+- button: [Gtk.Button](https://docs.gtk.org/gtk4/class.Button.html)
+ ```tsx
+ <button onClicked={self => print(self, "was clicked")}>
+ Click Me
+ </button>
+ ```
+- centerbox: [Gtk.CenterBox](https://docs.gtk.org/gtk4/class.CenterBox.html)
+ ```tsx
+ <centerbox orientation={1}>
+ <label label="Start Widget" />
+ <label label="Center Widget" />
+ <label label="End Widget" />
+ </box>
+ ```
+- entry: [Gtk.Entry](https://docs.gtk.org/gtk4/class.Entry.html)
+ ```tsx
+ <window keymode={Astal.Keymode.ON_DEMAND}>
+ <entry
+ onNotifyText={self => print("text changed", self.text)}
+ onActivate={self => print("enter", self.text)}
+ />
+ </window>
+ ```
+
+- image: [Gtk.Image](https://docs.gtk.org/gtk4/class.Image.html)
+ ```tsx
+ <image iconName={GLib.get_os_info("LOGO") || "missing-symbolic"} />
+ ```
+ ```css
+ image {
+ -gtk-icon-size: 16px;
+ }
+ ```
+
+- label: [Gtk.Label](https://docs.gtk.org/gtk4/class.Label.html)
+ ```tsx
+ <label label="hello" maxWidthChars={16} wrap />
+ ```
+
+- levelbar: [Gtk.LevelBar](https://docs.gtk.org/gtk4/class.LevelBar.html)
+ ```tsx
+ <levelbar value={0.5} widthRequest={200} />
+ ```
+
+- overlay: [Gtk.Overlay](https://docs.gtk.org/gtk4/class.Overlay.html)
+ ```tsx
+ <overlay>
+ <box heightRequest={40} widthRequest={40}>Child</box>
+ <box type="overlay measure" >1</box>
+ <box type="overlay clip" >2</box>
+ <box type="overlay clip measure" >3</box>
+ </overlay>
+ ```
+
+- revealer: [Gtk.Revealer](https://docs.gtk.org/gtk4/class.Revealer.html)
+ ```tsx
+ <revealer
+ setup={self => timeout(500, () => self.revealChild = true)}
+ transitionType={Gtk.RevealerTransitionType.SLIDE_UP}>
+ <label label="Child" />
+ </revealer>
+ ```
+
+- slider: [Astal.Slider](https://aylur.github.io/libastal/astal4/class.Slider.html)
+ ```tsx
+ <slider widthRequest={100} onNotifyValue={self => print("new value", self.value)} />
+ ```
+
+- stack: [Gtk.Stack](https://docs.gtk.org/gtk4/class.Stack.html)
+ ```tsx
+ <stack visibleChildName="child2">
+ <label name="child1" label="child1" />
+ <label name="child2" label="child2" />
+ </stack>
+ ```
+
+- switch: [Gtk.Switch](https://docs.gtk.org/gtk4/class.Switch.html)
+ ```tsx
+ <switch onNotifyActive={self => print(self.active)} />
+ ```
+
+- menubutton: [Gtk.MenuButton](https://docs.gtk.org/gtk4/class.MenuButton.html) and popover: [Gtk.Popover](https://docs.gtk.org/gtk4/class.Popover.html)
+ ```tsx
+ <menubutton>
+ <label label="Button Content" />
+ <popover>
+ <label label="Popover Content" />
+ </popover>
+ </menubutton>
+ ```
+
+- window: [Astal.Window](https://aylur.github.io/libastal/astal4/class.Window.html)
+ ```tsx
+ <window
+ cssClasses={["Bar"]}
+ name="bar"
+ namespace="bar"
+ application={App}
+ monitor={0}
+ anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT}
+ exclusivity={Astal.Exclusivity.EXCLUSIVE}
+ keymode={Astal.Keymode.ON_DEMAND}
+ >
+ <centerbox />
+ </window>
+ ```
diff --git a/docs/package.json b/docs/package.json
index ad76c9a..e01b189 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -12,7 +12,7 @@
"vue": "^3.4.38"
},
"scripts": {
- "dev": "vitepress dev",
+ "dev": "vitepress dev --open",
"build": "vitepress build",
"preview": "vitepress preview",
"vitepress": "vitepress",
diff --git a/docs/public/showcase/aylur.png b/docs/public/showcase/aylur.png
deleted file mode 100644
index 5dc5dd7..0000000
--- a/docs/public/showcase/aylur.png
+++ /dev/null
Binary files differ
diff --git a/docs/public/showcase/aylur.webp b/docs/public/showcase/aylur.webp
new file mode 100644
index 0000000..7f89e04
--- /dev/null
+++ b/docs/public/showcase/aylur.webp
Binary files differ
diff --git a/docs/public/showcase/ezerinz.webp b/docs/public/showcase/ezerinz.webp
new file mode 100644
index 0000000..7da8d7d
--- /dev/null
+++ b/docs/public/showcase/ezerinz.webp
Binary files differ
diff --git a/docs/public/showcase/hyprpanel_showcase.webp b/docs/public/showcase/hyprpanel_showcase.webp
new file mode 100644
index 0000000..6a9ad7c
--- /dev/null
+++ b/docs/public/showcase/hyprpanel_showcase.webp
Binary files differ
diff --git a/docs/public/showcase/tokyob0t-super-duper-hiper-mega-ultra-contribution.webp b/docs/public/showcase/tokyob0t.webp
index 94f6080..94f6080 100644
--- a/docs/public/showcase/tokyob0t-super-duper-hiper-mega-ultra-contribution.webp
+++ b/docs/public/showcase/tokyob0t.webp
Binary files differ
diff --git a/docs/public/vitepress-logo-large.webp b/docs/public/vitepress-logo-large.webp
deleted file mode 100644
index 2e47b15..0000000
--- a/docs/public/vitepress-logo-large.webp
+++ /dev/null
Binary files differ
diff --git a/docs/showcases/showcases.ts b/docs/showcases/showcases.ts
index 2aea04a..a673aaf 100644
--- a/docs/showcases/showcases.ts
+++ b/docs/showcases/showcases.ts
@@ -12,14 +12,14 @@ type Grid<T> = T | [T, T]
export default [
{
- image: "/astal/showcase/aylur.png",
+ image: "/astal/showcase/aylur.webp",
url: "https://github.com/Aylur/dotfiles",
icon: "devicon-typescript-plain",
- description: "Placeholder (this is an ags v1 screenshot)",
+ title: "Marble Shell",
author: "Aylur",
},
{
- image: "/astal/showcase/tokyob0t-super-duper-hiper-mega-ultra-contribution.webp",
+ image: "/astal/showcase/tokyob0t.webp",
url: "https://github.com/tokyob0t/dotfiles",
icon: "devicon-lua-plain",
title: "Tokyob0t's Desktop",
@@ -33,6 +33,20 @@ export default [
title: "kompass",
author: "kotontrion",
},
+ {
+ image: "/astal/showcase/ezerinz.webp",
+ url: "https://github.com/ezerinz/epik-shell",
+ icon: "devicon-javascript-plain",
+ title: "Epik Shell",
+ author: "ezerinz",
+ },
+ {
+ image: "/astal/showcase/hyprpanel_showcase.webp",
+ url: "https://github.com/Jas-SinghFSU/hyprpanel",
+ icon: "devicon-javascript-plain",
+ title: "HyprPanel",
+ author: "Jas",
+ },
// add more showcases here~
] satisfies Array<Grid<Showcase>>