// xorg's tools (novox/hq ADR 0208, research 026/05): node-display-server's verbs `displays` and // `layout`, and the module's own tools for one output's mode, the primary output, DPI, input devices, // the keyboard map, a screenshot and the server's log. // // Every tool that touches the screen acts in the operator's running session, which it finds through // internal/desktop: the node's runtime has none of its own. With no session, the answer says so as // structured data. A tool that changes the running server changes it until the next login; the // answer says what makes it last. package main import ( "context" "fmt" "os" "time" stdio "git.novox.be/novox/mesh-sdk/go" "xorg/internal/desktop" ) // The session's holders this module prefers as the session's own process. var sessionHolders = []string{"i3", "sway", "openbox", "bspwm", "awesome", "xmonad"} func main() { if err := stdio.Serve("", tools(desktop.Machine(sessionHolders...))); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } // call bounds one tool call below the runtime's 30 s limit. func call(run func(ctx context.Context, a desktop.Args) (any, error)) func(map[string]any) (any, error) { return func(args map[string]any) (any, error) { ctx, cancel := context.WithTimeout(context.Background(), 25*time.Second) defer cancel() return run(ctx, desktop.Args(args)) } } func tools(d desktop.Desk) []stdio.Tool { x := xorg{d: d} return []stdio.Tool{ { Name: "node-display-server.displays", Description: "The X screen and every output: connected or not, primary, where it sits, its rotation, " + "physical size and DPI, the monitor's identity from its EDID (manufacturer, product, serial, name, " + "fingerprint), the current and preferred mode, and every mode with its rates. Disconnected outputs " + "are listed by name only unless all is true. Also the autorandr profile in force, when one matches.", Input: desktop.Schema(map[string]any{ "all": desktop.Flag("list disconnected outputs in full (default false)"), "modes": desktop.Flag("list every mode of each output (default true)"), }), Run: call(x.displays), }, { Name: "node-display-server.layout", Description: "Monitor layout profiles (autorandr), keyed by the connected monitors' identities, so one " + "profile needs no machine's name. list: every profile with the monitors it is for, which match " + "the monitors connected now and which is in force. save: the current arrangement under a name " + "(replace true to overwrite). apply: load one. The profiles are the operator's data, never the mesh's.", Input: desktop.Schema(map[string]any{ "action": desktop.Enum("list, save or apply", "list", "save", "apply"), "name": desktop.Str("the profile to save or apply"), "replace": desktop.Flag("save over an existing profile of that name (default false)"), }, "action"), Run: call(x.layout), }, { Name: "xorg_set_mode", Description: "Change one output now, through xrandr: its mode (WxH, or auto for the preferred one), rate, " + "rotation, scale, position (x/y, or beside another output), on or off, primary. dry_run answers " + "the command without running it. Lasts until the next login or hotplug: save a layout profile to keep it.", Input: desktop.Schema(map[string]any{ "output": desktop.Str("the output, as displays names it (e.g. eDP-1)"), "mode": desktop.Str("WxH, or auto for the monitor's preferred mode"), "rate": desktop.Num("refresh rate in Hz"), "rotate": desktop.Enum("rotation", "normal", "left", "right", "inverted"), "scale": desktop.Num("scale factor, 0.25 to 4 (1 = none)"), "x": desktop.Int("left edge on the screen, in pixels"), "y": desktop.Int("top edge on the screen, in pixels"), "relation": desktop.Enum("place it beside another output instead of at x/y", "right-of", "left-of", "above", "below", "same-as"), "of": desktop.Str("the output the relation is to"), "off": desktop.Flag("switch the output off"), "primary": desktop.Flag("make it the primary output"), "dry_run": desktop.Flag("answer the command, run nothing"), }, "output"), Run: call(x.setMode), }, { Name: "xorg_primary", Description: "Which output is primary (the one the bar's tray and new windows prefer); with output, make it primary now.", Input: desktop.Schema(map[string]any{"output": desktop.Str("the output to make primary (optional)")}), Run: call(x.primary), }, { Name: "xorg_dpi", Description: "The DPI X programs are told (Xft.dpi) beside each monitor's physical DPI. With value, set " + "Xft.dpi and the screen's DPI now: programs started after it use it. The module's resources file " + "sets it again at the next login (96 until it is a setting).", Input: desktop.Schema(map[string]any{"value": desktop.Int("dots per inch, 48 to 480 (optional)")}), Run: call(x.dpi), }, { Name: "xorg_input_devices", Description: "The input devices the X server knows: id, name, pointer or keyboard, master or slave, and " + "for each pointer its libinput settings (tap, natural scroll, acceleration, disable while typing, " + "left handed, enabled).", Input: desktop.Schema(map[string]any{"name": desktop.Str("only devices whose name contains this (optional)")}), Run: call(x.inputDevices), }, { Name: "xorg_input_set", Description: "Change libinput settings of a device now: tap, tap_drag, natural_scroll, disable_while_typing, " + "left_handed, middle_emulation, enabled (true/false), accel_speed (-1 to 1). The device is an id or a " + "name; a name applies to every device of that name that has the setting. Lasts until the device " + "reconnects or the next login.", Input: desktop.Schema(map[string]any{ "device": desktop.Str("the device's id or exact name"), "tap": desktop.Flag("tap to click"), "tap_drag": desktop.Flag("tap and drag"), "natural_scroll": desktop.Flag("natural (reversed) scrolling"), "disable_while_typing": desktop.Flag("ignore the touchpad while typing"), "left_handed": desktop.Flag("swap the buttons"), "middle_emulation": desktop.Flag("both buttons together are the middle one"), "enabled": desktop.Flag("the device takes input at all"), "accel_speed": desktop.Num("pointer acceleration, -1 to 1"), }, "device"), Run: call(x.inputSet), }, { Name: "xorg_keyboard", Description: "The X keyboard map: rules, model, layout, variant and options. With layout, variant, model " + "or options, set them now (options replace the current ones; an empty list clears them). Lasts " + "until the next login.", Input: desktop.Schema(map[string]any{ "layout": desktop.Str("e.g. us, be, us,be"), "variant": desktop.Str("e.g. intl"), "model": desktop.Str("e.g. pc105"), "options": desktop.List("e.g. [\"caps:escape\", \"compose:ralt\"]"), }), Run: call(x.keyboard), }, { Name: "xorg_screenshot", Description: "Take a screenshot to a PNG file: the whole screen, one output, or one window by its X id " + "(cut from the screen as the compositor shows it, so a see-through window shows what is behind it). " + "Written under the account's home (default ~/Pictures/Screenshots/screenshot-