comments and useful utils

This commit is contained in:
milarin 2024-02-14 17:21:50 +01:00
parent d617a7dde7
commit bd4b65256d
17 changed files with 93 additions and 0 deletions

View File

@ -11,6 +11,17 @@ import (
"sync" "sync"
) )
// Client is a single connection to a sway socket.
// All requests are synchronized in order to be thread-safe.
// That means they are processed in incoming order.
// If you want to be truly concurrent, use multiple clients
// connected to the same sway socket path.
// Subscriptions are the exception: They use their own socket connection
// so other requests are still possible.
// Subscription connections get closed as soon as the provided context is done.
// Use Client.Close after all requests are processed
// to close the connection to the socket.
// Client.Close does not handle subscriptions.
type Client struct { type Client struct {
sync.Mutex sync.Mutex
@ -18,6 +29,8 @@ type Client struct {
conn net.Conn conn net.Conn
} }
// GetDefaultClient returns a sway client for the current seat.
// It determines the current seat by the SWAYSOCK environment variable
func GetDefaultClient() (*Client, error) { func GetDefaultClient() (*Client, error) {
socket, ok := os.LookupEnv("SWAYSOCK") socket, ok := os.LookupEnv("SWAYSOCK")
if !ok { if !ok {
@ -27,6 +40,7 @@ func GetDefaultClient() (*Client, error) {
return GetClientBySocket(socket) return GetClientBySocket(socket)
} }
// GetClientBySocket returns a sway client for the provided socket.
func GetClientBySocket(socket string) (*Client, error) { func GetClientBySocket(socket string) (*Client, error) {
conn, err := net.Dial("unix", socket) conn, err := net.Dial("unix", socket)
if err != nil { if err != nil {
@ -39,6 +53,8 @@ func GetClientBySocket(socket string) (*Client, error) {
}, nil }, nil
} }
// Close closes the socket connection.
// All requests will return errors after calling Close
func (c *Client) Close() error { func (c *Client) Close() error {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()

View File

@ -1,9 +1,11 @@
package sway package sway
// GetBarIDs returns a string array containing the IDs of all sway bars
func (c *Client) GetBarIDs() ([]string, error) { func (c *Client) GetBarIDs() ([]string, error) {
return sendMessage[[]string](c, 6, "") return sendMessage[[]string](c, 6, "")
} }
// GetBarConfig returns the configuration for the given bar id
func (c *Client) GetBarConfig(barID string) (*BarConfig, error) { func (c *Client) GetBarConfig(barID string) (*BarConfig, error) {
return sendMessage[*BarConfig](c, 6, barID) return sendMessage[*BarConfig](c, 6, barID)
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetBindingModes returns all binding modes configured in the config file
func (c *Client) GetBindingModes() ([]string, error) { func (c *Client) GetBindingModes() ([]string, error) {
return sendMessage[[]string](c, 8, "") return sendMessage[[]string](c, 8, "")
} }

View File

@ -1,5 +1,7 @@
package sway package sway
// GetConfig returns the content of the content file.
// Includes are not handled
func (c *Client) GetConfig() (string, error) { func (c *Client) GetConfig() (string, error) {
cfg, err := sendMessage[config](c, 9, "") cfg, err := sendMessage[config](c, 9, "")
if err != nil { if err != nil {

View File

@ -1,5 +1,6 @@
package sway package sway
// GetCurrentBindingMode returns the currently active binding mode
func (c *Client) GetCurrentBindingMode() (string, error) { func (c *Client) GetCurrentBindingMode() (string, error) {
mode, err := sendMessage[name](c, 12, "") mode, err := sendMessage[name](c, 12, "")
if err != nil { if err != nil {

View File

@ -1,5 +1,6 @@
package sway package sway
// GetInputs returns all input devices and their properties
func (c *Client) GetInputs() ([]InputDevice, error) { func (c *Client) GetInputs() ([]InputDevice, error) {
return sendMessage[[]InputDevice](c, 100, "") return sendMessage[[]InputDevice](c, 100, "")
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetMarks returns a string array containing all current marks
func (c *Client) GetMarks() ([]string, error) { func (c *Client) GetMarks() ([]string, error) {
return sendMessage[[]string](c, 5, "") return sendMessage[[]string](c, 5, "")
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetOutputs returns all outputs and their properties
func (c *Client) GetOutputs() ([]Output, error) { func (c *Client) GetOutputs() ([]Output, error) {
return sendMessage[[]Output](c, 3, "") return sendMessage[[]Output](c, 3, "")
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetSeats returns all sway seats
func (c *Client) GetSeats() ([]Seat, error) { func (c *Client) GetSeats() ([]Seat, error) {
return sendMessage[[]Seat](c, 101, "") return sendMessage[[]Seat](c, 101, "")
} }

View File

@ -1,5 +1,8 @@
package sway package sway
// GetTree returns a Node object containing all
// outputs, workspaces, containers and windows in a recursive tree.
// Use Node.Find and Node.FindAll to search the tree recursively
func (c *Client) GetTree() (*Node, error) { func (c *Client) GetTree() (*Node, error) {
return sendMessage[*Node](c, 4, "") return sendMessage[*Node](c, 4, "")
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetVersion returns information about the sway version
func (c *Client) GetVersion() (*Version, error) { func (c *Client) GetVersion() (*Version, error) {
return sendMessage[*Version](c, 7, "") return sendMessage[*Version](c, 7, "")
} }

View File

@ -1,5 +1,6 @@
package sway package sway
// GetWorkspaces returns all currently opened workspaces
func (c *Client) GetWorkspaces() ([]Workspace, error) { func (c *Client) GetWorkspaces() ([]Workspace, error) {
return sendMessage[[]Workspace](c, 1, "") return sendMessage[[]Workspace](c, 1, "")
} }

View File

@ -4,6 +4,10 @@ import (
"git.milar.in/milarin/slices" "git.milar.in/milarin/slices"
) )
// RunCommand runs all provided commands.
// It will return an array of errors
// which represent the result of each command.
// The last error is for communication problems only.
func (c *Client) RunCommand(cmd string) ([]error, error) { func (c *Client) RunCommand(cmd string) ([]error, error) {
results, err := sendMessage[[]commandResult](c, 0, cmd) results, err := sendMessage[[]commandResult](c, 0, cmd)
if err != nil { if err != nil {

View File

@ -1,5 +1,6 @@
package sway package sway
// SendTick sends a tick with the given payload
func (c *Client) SendTick(payload string) error { func (c *Client) SendTick(payload string) error {
result, err := sendMessage[commandResult](c, 10, payload) result, err := sendMessage[commandResult](c, 10, payload)
if err != nil { if err != nil {

View File

@ -11,6 +11,11 @@ import (
"git.milar.in/milarin/slices" "git.milar.in/milarin/slices"
) )
// Subscribe subscribes to the given event types
// and returns a channel in which all events get written into.
// A new socket connection will be established
// so other requests can still be used during a subscription.
// The subscription connection will be closed as soon as ctx is closed.
func (c *Client) Subscribe(ctx context.Context, events ...EventType) (<-chan Event, error) { func (c *Client) Subscribe(ctx context.Context, events ...EventType) (<-chan Event, error) {
conn, err := net.Dial("unix", c.socket) conn, err := net.Dial("unix", c.socket)
if err != nil { if err != nil {

View File

@ -131,6 +131,53 @@ func (n Node) String() string {
return string(data) return string(data)
} }
// Find recursively searches n and returns the node
// for which condition returned true.
// condition is called in depth-first order:
// 1. for n
// 2. for n.Nodes (in order)
// 3. for n.FloatingNodes (in order)
//
// If no matching node is found, Find returns nil
func (n *Node) Find(condition func(n *Node) bool) *Node {
if condition(n) {
return n
}
for _, child := range n.Nodes {
if node := child.Find(condition); node != nil {
return node
}
}
for _, child := range n.FloatingNodes {
if node := child.Find(condition); node != nil {
return node
}
}
return nil
}
// FindAll behaves like Find but returns all matching nodes
func (n *Node) FindAll(condition func(n *Node) bool) []*Node {
nodes := []*Node{}
if condition(n) {
nodes = append(nodes, n)
}
for _, child := range n.Nodes {
nodes = append(nodes, child.FindAll(condition)...)
}
for _, child := range n.FloatingNodes {
nodes = append(nodes, child.FindAll(condition)...)
}
return nodes
}
type NodeType = string type NodeType = string
const ( const (

5
utils.go Normal file
View File

@ -0,0 +1,5 @@
package sway
func FindNodeByType(nodeType NodeType) func(n *Node) bool {
return func(n *Node) bool { return n.Type == nodeType }
}