Files
niri/model_client.go
2025-07-25 13:41:23 +02:00

110 lines
2.0 KiB
Go

package niri
import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
"git.tordarus.net/tordarus/slices"
"github.com/adrg/xdg"
)
var niriSocketFilenameFormat = "niri.wayland-%d.%d.sock"
var niriSocketFilenamePattern = regexp.MustCompile(`^niri\.wayland-(\d+?)\.(\d+?)\.sock$`)
type Client struct {
display int
pid int
}
var ErrClientNotFound = errors.New("client not found")
func GetClientByPID(pid int) (*Client, error) {
clients, err := GetAllClients()
if err != nil {
return nil, err
}
for _, c := range clients {
if c.pid == pid {
return c, nil
}
}
return nil, ErrClientNotFound
}
func GetClientByDisplay(display int) (*Client, error) {
clients, err := GetAllClients()
if err != nil {
return nil, err
}
for _, c := range clients {
if c.display == display {
return c, nil
}
}
return nil, ErrClientNotFound
}
func GetDefaultClient() (*Client, error) {
if niriSocket, ok := os.LookupEnv("NIRI_SOCKET"); ok {
return GetClientBySocketPath(niriSocket)
}
if display, ok := os.LookupEnv("WAYLAND_DISPLAY"); ok {
displayInt, err := strconv.Atoi(display)
if err != nil {
return nil, err
}
return GetClientByDisplay(displayInt)
}
return nil, ErrClientNotFound
}
func GetAllClients() ([]*Client, error) {
runtimeDir := xdg.RuntimeDir
entries, err := os.ReadDir(runtimeDir)
if err != nil {
return nil, err
}
return slices.Filter(slices.Map(entries, parseEntryAsClient), notNull), nil
}
func GetClientBySocketPath(socketPath string) (*Client, error) {
baseName := filepath.Base(socketPath)
matches := niriSocketFilenamePattern.FindStringSubmatch(baseName)
if matches == nil {
return nil, errors.New("invalid niri socket path")
}
display, err := strconv.Atoi(matches[1])
if err != nil {
return nil, err
}
pid, err := strconv.Atoi(matches[2])
if err != nil {
return nil, err
}
return &Client{
display: display,
pid: pid,
}, nil
}
func (c Client) GetSocketPath() string {
return filepath.Join(xdg.RuntimeDir, fmt.Sprintf(niriSocketFilenameFormat, c.display, c.pid))
}