110 lines
2.0 KiB
Go
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))
|
|
}
|