summaryrefslogtreecommitdiff
path: root/docs/guide/ags/faq.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/guide/ags/faq.md')
-rw-r--r--docs/guide/ags/faq.md379
1 files changed, 0 insertions, 379 deletions
diff --git a/docs/guide/ags/faq.md b/docs/guide/ags/faq.md
deleted file mode 100644
index cb5d609..0000000
--- a/docs/guide/ags/faq.md
+++ /dev/null
@@ -1,379 +0,0 @@
-# Frequently asked question, common issues, tips and tricks
-
-## Monitor id does not match compositor
-
-The monitor property that windows expect is mapped by Gdk, which is not always
-the same as the compositor. Instead use the `gdkmonitor` property which expects
-a `Gdk.Monitor` object which you can get from compositor libraries.
-
-Example with Hyprland
-
-```tsx
-import Hyprland from "gi://AstalHyprland"
-
-function Bar(gdkmonitor) {
- return <window gdkmonitor={gdkmonitor} />
-}
-
-function main() {
- for (const m of Hyprland.get_default().get_monitors()) {
- Bar(m.gdk_monitor)
- }
-}
-
-App.start({ main })
-```
-
-## Environment variables
-
-JavaScript is **not** an bash.
-
-```ts
-const HOME = exec("echo $HOME") // does not work
-```
-
-`exec` and `execAsync` runs the passed program as is, its **not** run in a
-shell environment, so the above example just passes `$HOME` as a string literal
-to the `echo` program.
-
-:::danger Please don't do this
-You could pass it to bash, but that is a horrible approach.
-
-```ts
-const HOME = exec("bash -c 'echo $HOME'")
-```
-
-:::
-
-You can read environment variables with [GLib.getenv](https://gjs-docs.gnome.org/glib20~2.0/glib.getenv).
-
-```ts
-import GLib from "gi://GLib"
-
-const HOME = GLib.getenv("HOME")
-```
-
-## Custom svg symbolic icons
-
-Put the svgs in a directory, named `<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`,
- main() {
- Widget.Icon({
- icon: "custom-symbolic", // custom-symbolic.svg
- css: "color: green;", // can be colored, like other named icons
- })
- },
-})
-```
-
-:::
-
-:::info
-If there is a name clash with an icon from your current icon pack
-the icon pack will take precedence
-:::
-
-## Logging
-
-The `console` API in gjs uses glib logging functions.
-If you just want to print some text as is to stdout
-use the globally available `print` function or `printerr` for stderr.
-
-```ts
-print("print this line to stdout")
-printerr("print this line to stderr")
-```
-
-## Binding custom structures
-
-The `bind` function can take two types of objects.
-
-```ts
-interface Subscribable<T = unknown> {
- subscribe(callback: (value: T) => void): () => void
- get(): T
-}
-
-interface Connectable {
- connect(signal: string, callback: (...args: any[]) => unknown): number
- disconnect(id: number): void
-}
-```
-
-`Connectable` is for mostly gobjects, while `Subscribable` is for `Variables`
-and custom objects.
-
-For example you can compose `Variables` in using a class.
-
-```ts
-type MyVariableValue = {
- number: number
- string: string
-}
-
-class MyVariable {
- number = Variable(0)
- string = Variable("")
-
- get(): MyVariableValue {
- return {
- number: this.number.get(),
- string: this.string.get(),
- }
- }
-
- subscribe(callback: (v: MyVariableValue) => void) {
- const unsub1 = this.number.subscribe((value) => {
- callback({ string: value, number: this.number.get() })
- })
-
- const unsub2 = this.string.subscribe((value) => {
- callback({ number: value, string: this.string.get() })
- })
-
- return () => {
- unsub1()
- unsub2()
- }
- }
-}
-```
-
-Then it can be used with `bind`.
-
-```tsx
-function MyWidget() {
- const myvar = new MyVariable()
- const label = bind(myvar).as(({ string, number }) => {
- return `${string} ${number}`
- })
-
- return <label label={label} />
-}
-```
-
-## Populate the global scope with frequently accessed variables
-
-It might be annoying to always import Gtk only for `Gtk.Align` enums.
-
-:::code-group
-
-```ts [globals.ts]
-import Gtk from "gi://Gtk"
-
-declare global {
- const START: number
- const CENTER: number
- const END: number
- const FILL: number
-}
-
-Object.assign(globalThis, {
- START: Gtk.Align.START,
- CENTER: Gtk.Align.CENTER,
- END: Gtk.Align.END,
- FILL: Gtk.Align.FILL,
-})
-```
-
-:::
-
-:::code-group
-
-```tsx [Bar.tsx]
-export default function Bar() {
- return <window>
- <box halign={START} />
- </window>
-}
-```
-
-:::
-
-:::code-group
-
-```ts [app.ts]
-import "./globals"
-import Bar from "./Bar"
-
-App.start({
- main: Bar
-})
-```
-
-:::
-
-:::info
-It is considered bad practice to populate the global scope, but its your code, not a public library.
-:::
-
-## Auto create Window for each Monitor
-
-To have Window widgets appear on a monitor when its plugged in, listen to `App.monitor_added`.
-
-:::code-group
-
-```tsx [Bar.tsx]
-export default function Bar(gdkmonitor: Gdk.Monitor) {
- return <window gdkmonitor={gdkmonitor} />
-}
-```
-
-:::
-
-:::code-group
-
-```ts [app.ts]
-import { Gdk, Gtk } from "astal"
-import Bar from "./Bar"
-
-function main() {
- const bars = new Map<Gdk.Monitor, Gtk.Widget>()
-
- // initialize
- for (const gdkmonitor of App.get_monitors()) {
- bars.set(gdkmonitor, Bar(gdkmonitor))
- }
-
- App.connect("monitor-added", (_, gdkmonitor) => {
- bars.set(gdkmonitor, Bar(gdkmonitor))
- })
-
- App.connect("monitor-removed", (_, gdkmonitor) => {
- bars.get(gdkmonitor)?.destroy()
- bars.delete(gdkmonitor)
- })
-}
-
-App.start({ main })
-```
-
-:::
-
-## Error: Can't convert non-null pointer to JS value
-
-These happen when accessing list type properties. Gjs fails to correctly bind
-`List` and other array like types of Vala as a property.
-
-```ts
-import Notifd from "gi://AstalNotifd"
-const notifd = Notifd.get_default()
-
-notifd.notifications // ❌ // [!code error]
-
-notifd.get_notifications() // ✅
-```
-
-## How to create regular floating windows
-
-Use `Gtk.Window` with [Widget.astalify](/guide/ags/widget#how-to-use-non-builtin-gtk-widgets).
-
-By default `Gtk.Window` is destroyed on close. To prevent this add a handler for `delete-event`.
-
-```tsx {4-7}
-const RegularWindow = Widget.astalify(Gtk.Window)
-
-return <RegularWindow
- onDeleteEvent={(self) => {
- self.hide()
- return true
- }}
->
- {child}
-</RegularWindow>
-```
-
-## Avoiding unnecessary re-rendering
-
-As mentioned before, any object can be bound that implements the `Subscribable` interface.
-
-```ts
-interface Subscribable<T = unknown> {
- subscribe(callback: (value: T) => void): () => void
- get(): T
-}
-```
-
-This can be used to our advantage to create a reactive `Map` object.
-
-```ts
-import { type Subscribable } from "astal/binding"
-import { Gtk } from "astal"
-
-export class VarMap<K, T = Gtk.Widget> implements Subscribable {
- #subs = new Set<(v: Array<[K, T]>) => void>()
- #map: Map<K, T>
-
- #notifiy() {
- const value = this.get()
- for (const sub of this.#subs) {
- sub(value)
- }
- }
-
- #delete(key: K) {
- const v = this.#map.get(key)
-
- if (v instanceof Gtk.Widget) {
- v.destroy()
- }
-
- this.#map.delete(key)
- }
-
- constructor(initial?: Iterable<[K, T]>) {
- this.#map = new Map(initial)
- }
-
- add(key: K, value: T) {
- this.#delete(key)
- this.#map.set(key, value)
- this.#notifiy()
- }
-
- delete(key: K) {
- this.#delete(key)
- this.#notifiy()
- }
-
- get() {
- return [...this.#map.entries()]
- }
-
- subscribe(callback: (v: Array<[K, T]>) => void) {
- this.#subs.add(callback)
- return () => this.#subs.delete(callback)
- }
-}
-```
-
-And this `VarMap<key, Widget>` can be used as an alternative to `Variable<Array<Widget>>`.
-
-```tsx
-function MappedBox() {
- const map = new VarMap([
- [1, <MyWidget id={id} />]
- [2, <MyWidget id={id} />]
- ])
-
- const conns = [
- gobject.connect("added", (_, id) => map.set(id, MyWidget({ id }))),
- gobject.connect("removed", (_, id) => map.delete(id, MyWidget({ id }))),
- ]
-
- return <box onDestroy={() => conns.map(id => gobject.disconnect(id))}>
- {bind(map).as(arr => arr.sort(([a], [b]) => a - b).map(([,w]) => w))}
- </box>
-}
-```
-
-## Is there a way to limit the width/height of a widget?
-
-Unfortunately not. You can set a minimum size with `min-width` and `min-heigth` css attributes,
-but you can not set max size.