migrate to codeberg (#1)

This commit is contained in:
T. von Dein
2025-11-10 20:59:46 +01:00
parent d64c1ddcc0
commit 1cde07a07b
33 changed files with 59 additions and 77 deletions

98
v1/bar.go Normal file
View File

@@ -0,0 +1,98 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// Container gaps
type Gaps struct {
Top int `json:"top"`
Right int `json:"right"`
Bottom int `json:"bottom"`
Left int `json:"left"`
}
// Color definition, used primarily by bars
type Colors struct {
Background string `json:"background"`
Statusline string `json:"statusline"`
Separator string `json:"separator"`
FocusedBackground string `json:"focused_background"`
FocusedStatusline string `json:"focused_statusline"`
FocusedSeparator string `json:"focused_separator"`
FocusedWorkspaceBorder string `json:"focused_workspace_border"`
FocusedWorkspaceBg string `json:"focused_workspace_bg"`
FocusedWorkspaceText string `json:"focused_workspace_text"`
InactiveWorkspaceBorder string `json:"inactive_workspace_border"`
InactiveWorkspaceBg string `json:"inactive_workspace_bg"`
InactiveWorkspaceText string `json:"inactive_workspace_text"`
Active_workspaceBorder string `json:"active_workspace_border"`
Active_workspaceBg string `json:"active_workspace_bg"`
Active_workspaceText string `json:"active_workspace_text"`
Urgent_workspaceBorder string `json:"urgent_workspace_border"`
Urgent_workspaceBg string `json:"urgent_workspace_bg"`
Urgent_workspaceText string `json:"urgent_workspace_text"`
BindingModeBorder string `json:"binding_mode_border"`
BindingModeBg string `json:"binding_mode_bg"`
BindingModeText string `json:"binding_mode_text"`
}
// A bar such as a swaybar(5)
type Bar struct {
Id string `json:"id"`
Mode string `json:"mode"`
Position string `json:"position"`
Status_command string `json:"status_command"`
Font string `json:"font"`
Gaps *Gaps `json:"gaps"`
Height int `json:"bar_height"`
StatusPadding int `json:"status_padding"`
StatusEdgePadding int `json:"status_edge_padding"`
WorkspaceButtons bool `json:"workspace_buttons"`
WorkspaceMinWidth int `json:"workspace_min_width"`
BindingModeIndicator bool `json:"binding_mode_indicator"`
Verbose bool `json:"verbose"`
PangoMarkup bool `json:"pango_markup"`
Colors *Colors `json:"colors"`
}
// Get a list of currently visible and active bar names
func (ipc *SwayIPC) GetBars() ([]string, error) {
payload, err := ipc.get(GET_BAR_CONFIG)
if err != nil {
return nil, err
}
bars := []string{}
if err := json.Unmarshal(payload.Payload, &bars); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return bars, nil
}
// Get the bar object of the bar specified by the string 'id'
func (ipc *SwayIPC) GetBar(id string) (*Bar, error) {
err := ipc.sendHeader(GET_BAR_CONFIG, uint32(len(id)))
if err != nil {
return nil, err
}
err = ipc.sendPayload([]byte(id))
if err != nil {
return nil, fmt.Errorf("failed to send get_bar_config payload: %w", err)
}
payload, err := ipc.readResponse()
if err != nil {
return nil, err
}
bar := &Bar{}
if err := json.Unmarshal(payload.Payload, &bar); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return bar, nil
}

76
v1/command.go Normal file
View File

@@ -0,0 +1,76 @@
package swayipc
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
// Execute the specified global command[s] (one or more commands can be
// given) and returns a response list.
//
// Possible commands are all non-specific commands, see sway(5)
func (ipc *SwayIPC) RunGlobalCommand(command ...string) ([]Response, error) {
return ipc.RunCommand(0, "", command...)
}
// Execute the specified container command[s] (one or more commands can be
// given) and returns a response list.
//
// Possible commands are all container-specific commands, see sway(5)
func (ipc *SwayIPC) RunContainerCommand(id int, command ...string) ([]Response, error) {
return ipc.RunCommand(id, "con", command...)
}
// Execute the specified (target) command[s] (one or more commands can be
// given) and returns a response list.
//
// Possible commands are all container-specific commands, see sway(5).
//
// Target can be one of con, workspace, output, input, etc. see sway-ipc(7).
func (ipc *SwayIPC) RunCommand(id int, target string, command ...string) ([]Response, error) {
if len(command) == 0 {
return nil, errors.New("empty command arg")
}
commands := strings.Join(command, ",")
if id > 0 {
// a type specific command, otherwise global
commands = fmt.Sprintf("[%s_id=%d] %s", target, id, commands)
}
err := ipc.sendHeader(RUN_COMMAND, uint32(len(commands)))
if err != nil {
return nil, fmt.Errorf("failed to send run_command to IPC %w", err)
}
err = ipc.sendPayload([]byte(commands))
if err != nil {
return nil, fmt.Errorf("failed to send switch focus command: %w", err)
}
payload, err := ipc.readResponse()
if err != nil {
return nil, err
}
responses := []Response{}
if err := json.Unmarshal(payload.Payload, &responses); err != nil {
return nil, fmt.Errorf("failed to unmarshal json response: %w", err)
}
if len(responses) == 0 {
return nil, errors.New("got zero IPC response")
}
for _, response := range responses {
if !response.Success {
return responses, errors.New("one or more commands failed")
}
}
return responses, nil
}

19
v1/doc.go Normal file
View File

@@ -0,0 +1,19 @@
/*
Package swayipc can be used to control sway, swayfx and possibly
i3wmwindow managers via a unix domain socket.
swaywm's interprocess communication (or ipc) is the interface sway,
swayfx and i3wm use to receive commands from client applications such
as sway-msg. It also features a publish/subscribe mechanism for
notifying interested parties of window manager events.
swayipc is a go module for controlling the window manager. This project
is intended to be useful for general scripting, and for applications
that interact with the window manager like status line generators,
notification daemons, and window pagers. It is primarily designed to
work with sway and swayfx, but may also work with i3wm, although I
haven't tested it on i3wm.
The module uses the i3-IPC proctocol as outlined in sway-ipc(7).
*/
package swayipc

183
v1/event.go Normal file
View File

@@ -0,0 +1,183 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// Event types.
const (
EV_Workspace int = 0x80000000
EV_Output int = 0x80000001
EV_Mode int = 0x80000002
EV_Window int = 0x80000003
EV_BarconfigUpdate int = 0x80000004
EV_Binding int = 0x80000005
EV_Shutdown int = 0x80000006
EV_Tick int = 0x80000007
EV_BarStateUpdate int = 0x80000014
EV_Input int = 0x80000015
)
// Subscriber struct, use this to tell swayipc which events you want to
// subscribe.
type Event struct {
Workspace bool
Output bool
Mode bool
Window bool
BarconfigUpdate bool
Binding bool
Shutdown bool
Tick bool
BarStateUpdate bool
Input bool
}
// Workspace event response
type EventWorkspace struct {
Change string `json:"change"`
Current *Node `json:"workspace"`
Old *Node `json:"old"`
}
// Output event response
type EventOutput struct {
Change string `json:"change"`
}
// Mode event response
type EventMode struct {
Change string `json:"change"`
PangoMarkup *Node `json:"pango_markup"`
}
// Window event response
type EventWindow struct {
Change string `json:"change"`
Container *Node `json:"container"`
}
// BarConfig event response
type EventBarConfig struct {
Change string `json:"change"`
Binding *Binding `json:"binding"`
}
// Shutdown event response
type EventShutdown struct {
Change string `json:"change"`
}
// Tick event response
type EventTick struct {
First bool `json:"first"`
Payload string `json:"payload"`
}
// BarState event response
type EventBarState struct {
Id string `json:"id"`
VisibleByModifier bool `json:"visible_by_modifier"`
}
// Input event response
type EventInput struct {
Change string `json:"change"`
Input *Input `json:"input"`
}
// Subscribe to one or more events. Fill the swayipc.Event object
// accordingly.
//
// Returns a response list containing a response for every subscribed
// event.
func (ipc *SwayIPC) Subscribe(sub *Event) ([]*Response, error) {
events := []string{}
// looks ugly but makes it much more comfortable for the user
if sub.Workspace {
events = append(events, "workspace")
}
if sub.Output {
events = append(events, "output")
}
if sub.Mode {
events = append(events, "mode")
}
if sub.Window {
events = append(events, "window")
}
if sub.BarconfigUpdate {
events = append(events, "barconfig_update")
}
if sub.Binding {
events = append(events, "binding")
}
if sub.Shutdown {
events = append(events, "shutdown")
}
if sub.Tick {
events = append(events, "tick")
}
if sub.BarStateUpdate {
events = append(events, "bar_state_update")
}
if sub.Input {
events = append(events, "input")
}
jsonpayload, err := json.Marshal(events)
if err != nil {
return nil, fmt.Errorf("failed to json marshal event list: %w", err)
}
err = ipc.sendHeader(SUBSCRIBE, uint32(len(jsonpayload)))
if err != nil {
return nil, err
}
err = ipc.sendPayload(jsonpayload)
if err != nil {
return nil, err
}
payload, err := ipc.readResponse()
if err != nil {
responses := []*Response{}
if err := json.Unmarshal(payload.Payload, &responses); err != nil {
return nil, fmt.Errorf("failed to unmarshal json response: %w", err)
}
return responses, err
}
// register the subscribed events
ipc.Events = sub
return nil, nil
}
// Event loop: Once you have subscribed to an event, you need to enter
// an event loop over the same running socket connection. Sway will
// send event payloads for every subscribed event whenever it happens.
//
// You supply the loop a generic callback function, which will be
// called every time an event occurs. The function will receive the
// swayipc.RawResponse object for the event. You need to Unmarshall the
// Payload field yourself.
//
// If your callback function returns an error, the event loop returns
// with this error and finishes thus.
func (ipc *SwayIPC) EventLoop(callback func(event *RawResponse) error) error {
for {
payload, err := ipc.readResponse()
if err != nil {
return err
}
if err := callback(payload); err != nil {
return err
}
}
}

5
v1/go.mod Normal file
View File

@@ -0,0 +1,5 @@
module codeberg.org/scip/swayipc/v1
go 1.23
require github.com/alecthomas/repr v0.5.1 // indirect

2
v1/go.sum Normal file
View File

@@ -0,0 +1,2 @@
github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=
github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=

66
v1/input.go Normal file
View File

@@ -0,0 +1,66 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// An input (keyboard, mouse, whatever)
type Input struct {
Identifier string `json:"identifier"`
Name string `json:"name"`
Vendor int `json:"vendor"`
Product int `json:"product"`
Type string `json:"type"`
XkbActiveLayoutName string `json:"xkb_active_layout_name"`
XkbLayoutNames []string `json:"xkb_layout_names"`
XkbActiveLayoutIndex int `json:"xkb_active_layout_index"`
ScrollFactor float32 `json:"scroll_factor"`
Libinput *LibInput `json:"libinput"`
}
// Holds the data associated with libinput
type LibInput struct {
SendEvents string `json:"send_events"`
Tap string `json:"tap"`
TapButtonMap string `json:"tap_button_map"`
TapDrag string `json:"tap_drag"`
TapDragLock string `json:"tap_drag_lock"`
AccelSpeed float32 `json:"accel_speed"`
AccelProfile string `json:"accel_profile"`
NaturalScroll string `json:"natural_scroll"`
LeftHanded string `json:"left_handed"`
ClickMethod string `json:"click_method"`
ClickButtonMap string `json:"click_button_map"`
MiddleEmulation string `json:"middle_emulation"`
ScrollMethod string `json:"scroll_method"`
ScrollButton int `json:"scroll_button"`
ScrollButtonLock string `json:"scroll_button_lock"`
Dwt string `json:"dwt"`
Dwtp string `json:"dwtp"`
CalibrationMatrix []float32 `json:"calibration_matrix"`
}
// A key binding
type Binding struct {
Command string `json:"command"`
EventStateMask []string `json:"event_state_mask"`
InputCode int `json:"input_code"`
Symbol string `json:"symbol"`
InputType string `json:"input_type"`
}
// Get a list of all currently supported inputs
func (ipc *SwayIPC) GetInputs() ([]*Input, error) {
payload, err := ipc.get(GET_INPUTS)
if err != nil {
return nil, err
}
inputs := []*Input{}
if err := json.Unmarshal(payload.Payload, &inputs); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return inputs, nil
}

13
v1/io.go Normal file
View File

@@ -0,0 +1,13 @@
package swayipc
import "os"
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if err != nil {
return false
}
return !info.IsDir()
}

96
v1/net.go Normal file
View File

@@ -0,0 +1,96 @@
package swayipc
import (
"encoding/binary"
"errors"
"fmt"
"net"
"os"
)
// Contains a raw json response, not marshalled yet.
type RawResponse struct {
PayloadType int
Payload []byte
}
// Connect to unix domain ipc socket.
func (ipc *SwayIPC) Connect() error {
if !fileExists(ipc.SocketFile) {
ipc.SocketFile = os.Getenv(ipc.SocketFile)
if ipc.SocketFile == "" {
return fmt.Errorf("socket file %s doesn't exist", ipc.SocketFile)
}
}
conn, err := net.Dial("unix", ipc.SocketFile)
if err != nil {
return err
}
ipc.socket = conn
return nil
}
// Close the socket.
func (ipc *SwayIPC) Close() error {
return ipc.socket.Close()
}
func (ipc *SwayIPC) sendHeader(messageType uint32, len uint32) error {
sendPayload := make([]byte, IPC_HEADER_SIZE)
copy(sendPayload, []byte(IPC_MAGIC))
binary.LittleEndian.PutUint32(sendPayload[IPC_MAGIC_LEN:], len)
binary.LittleEndian.PutUint32(sendPayload[IPC_MAGIC_LEN+4:], messageType)
_, err := ipc.socket.Write(sendPayload)
if err != nil {
return fmt.Errorf("failed to send header to IPC socket %w", err)
}
return nil
}
func (ipc *SwayIPC) sendPayload(payload []byte) error {
_, err := ipc.socket.Write(payload)
if err != nil {
return fmt.Errorf("failed to send payload to IPC socket %w", err)
}
return nil
}
func (ipc *SwayIPC) readResponse() (*RawResponse, error) {
// read header
buf := make([]byte, IPC_HEADER_SIZE)
_, err := ipc.socket.Read(buf)
if err != nil {
return nil, fmt.Errorf("failed to read header from ipc socket: %s", err)
}
if string(buf[:6]) != IPC_MAGIC {
return nil, errors.New("got invalid response from IPC socket")
}
payloadLen := binary.LittleEndian.Uint32(buf[6:10])
if payloadLen == 0 {
return nil, errors.New("got empty payload response from IPC socket")
}
payloadType := binary.LittleEndian.Uint32(buf[10:])
// read payload
payload := make([]byte, payloadLen)
_, err = ipc.socket.Read(payload)
if err != nil {
return nil, fmt.Errorf("failed to read payload from IPC socket: %s", err)
}
return &RawResponse{PayloadType: int(payloadType), Payload: payload}, nil
}

108
v1/node.go Normal file
View File

@@ -0,0 +1,108 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// A node can be an output, a workspace, a container or a container
// containing a window.
type Node struct {
Id int `json:"id"`
Type string `json:"type"` // output, workspace or container
Name string `json:"name"` // workspace number or app name
Nodes []*Node `json:"nodes"`
FloatingNodes []*Node `json:"floating_nodes"`
Focused bool `json:"focused"`
Urgent bool `json:"urgent"`
Sticky bool `json:"sticky"`
Border string `json:"border"`
Layout string `json:"layout"`
Orientation string `json:"orientation"`
CurrentBorderWidth int `json:"current_border_width"`
Percent float32 `json:"percent"`
Focus []int `json:"focus"`
Window int `json:"window"` // wayland native
X11Window string `json:"app_id"` // x11 compat
Current_workspace string `json:"current_workspace"`
Rect Rect `json:"rect"`
WindowRect Rect `json:"window_rect"`
DecoRect Rect `json:"deco_rect"`
Geometry Rect `json:"geometry"`
}
var __focused *Node
var __currentworkspace string
// Get the whole information tree, contains everything from output to
// containers as a tree of nodes. Each node has a field 'Nodes' which
// points to a list subnodes. Some nodes also have a field
// 'FloatingNodes' which points to a list of floating containers.
//
// The top level node is the "root" node.
//
// Use the returned node oject to further investigate the wm setup.
func (ipc *SwayIPC) GetTree() (*Node, error) {
err := ipc.sendHeader(GET_TREE, 0)
if err != nil {
return nil, err
}
payload, err := ipc.readResponse()
if err != nil {
return nil, err
}
node := &Node{}
if err := json.Unmarshal(payload.Payload, &node); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return node, nil
}
// Usually called on the root node, returns the container which has
// currently the focus.
func (node *Node) FindFocused() *Node {
searchFocused(node.Nodes)
if __focused == nil {
searchFocused(node.FloatingNodes)
}
return __focused
}
// internal recursive focus node searcher
func searchFocused(nodes []*Node) {
for _, node := range nodes {
if node.Focused {
__focused = node
return
} else {
searchFocused(node.Nodes)
if __focused == nil {
searchFocused(node.FloatingNodes)
}
}
}
}
// Usually called on the root node, returns the current active
// workspace name.
func (node *Node) FindCurrentWorkspace() string {
searchCurrentWorkspace(node.Nodes)
return __currentworkspace
}
// internal recursive workspace node searcher
func searchCurrentWorkspace(nodes []*Node) {
for _, node := range nodes {
if node.Current_workspace != "" {
__currentworkspace = node.Current_workspace
return
} else {
searchCurrentWorkspace(node.Nodes)
}
}
}

47
v1/output.go Normal file
View File

@@ -0,0 +1,47 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// Store an output mode.
type Mode struct {
Width int `json:"width"`
Height int `json:"height"`
Refresh int `json:"refresh"`
}
// An output object (i.e. a physical monitor)
type Output struct {
Name string `json:"name"`
Make string `json:"make"`
Serial string `json:"serial"`
Active bool `json:"active"`
Primary bool `json:"primary"`
SubpixelHinting string `json:"subpixel_hinting"`
Transform string `json:"transform"`
Current_workspace string `json:"current_workspace"`
Modes []*Mode `json:"modes"`
CurrentMode *Mode `json:"current_mode"`
}
// Get a list of currently available and usable outputs.
func (ipc *SwayIPC) GetOutputs() ([]*Output, error) {
err := ipc.sendHeader(GET_OUTPUTS, 0)
if err != nil {
return nil, err
}
payload, err := ipc.readResponse()
if err != nil {
return nil, err
}
workspaces := []*Output{}
if err := json.Unmarshal(payload.Payload, &workspaces); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return workspaces, nil
}

29
v1/seat.go Normal file
View File

@@ -0,0 +1,29 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// Information about a seat containing input devices
type Seat struct {
Name string `json:"name"`
Capabilities int `json:"capabilities"`
Focus int `json:"focus"`
Devices []*Input `json:"devices"`
}
// Get input seats
func (ipc *SwayIPC) GetSeats() ([]*Seat, error) {
payload, err := ipc.get(GET_SEATS)
if err != nil {
return nil, err
}
seats := []*Seat{}
if err := json.Unmarshal(payload.Payload, &seats); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return seats, nil
}

90
v1/simpletons.go Normal file
View File

@@ -0,0 +1,90 @@
package swayipc
import (
"encoding/json"
"fmt"
)
func (ipc *SwayIPC) GetWorkspaces() ([]*Node, error) {
payload, err := ipc.get(GET_WORKSPACES)
if err != nil {
return nil, err
}
nodes := []*Node{}
if err := json.Unmarshal(payload.Payload, &nodes); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return nodes, nil
}
func (ipc *SwayIPC) GetMarks() ([]string, error) {
payload, err := ipc.get(GET_MARKS)
if err != nil {
return nil, err
}
marks := []string{}
if err := json.Unmarshal(payload.Payload, &marks); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return marks, nil
}
func (ipc *SwayIPC) GetBindingModes() ([]string, error) {
payload, err := ipc.get(GET_BINDING_MODES)
if err != nil {
return nil, err
}
modes := []string{}
if err := json.Unmarshal(payload.Payload, &modes); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return modes, nil
}
func (ipc *SwayIPC) GetBindingState() (*State, error) {
payload, err := ipc.get(GET_BINDING_STATE)
if err != nil {
return nil, err
}
state := &State{}
if err := json.Unmarshal(payload.Payload, &state); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return state, nil
}
func (ipc *SwayIPC) GetConfig() (string, error) {
payload, err := ipc.get(GET_CONFIG)
if err != nil {
return "", err
}
config := &Config{}
if err := json.Unmarshal(payload.Payload, &config); err != nil {
return "", fmt.Errorf("failed to unmarshal json: %w", err)
}
return config.Config, nil
}
func (ipc *SwayIPC) SendTick(payload string) error {
err := ipc.sendHeader(SEND_TICK, uint32(len(payload)))
if err != nil {
return err
}
err = ipc.sendPayload([]byte(payload))
if err != nil {
return err
}
return nil
}

98
v1/swayipc.go Normal file
View File

@@ -0,0 +1,98 @@
package swayipc
import (
"net"
)
const (
VERSION = "v1.0.0"
IPC_HEADER_SIZE = 14
IPC_MAGIC = "i3-ipc"
IPC_MAGIC_LEN = 6
)
const (
// message types
RUN_COMMAND = iota
GET_WORKSPACES
SUBSCRIBE
GET_OUTPUTS
GET_TREE
GET_MARKS
GET_BAR_CONFIG
GET_VERSION
GET_BINDING_MODES
GET_CONFIG
SEND_TICK
SYNC
GET_BINDING_STATE
GET_INPUTS = 100
GET_SEATS = 101
)
// This is the primary struct to work with the swayipc module.
type SwayIPC struct {
socket net.Conn
SocketFile string // filename of the i3 IPC socket
Events *Event // store subscribed events, see swayipc.Subscribe()
}
// A rectangle struct, used at various places for geometry etc.
type Rect struct {
X int `json:"x"` // X coordinate
Y int `json:"y"` // Y coordinate
Width int `json:"width"`
Height int `json:"height"`
}
// Stores responses retrieved via ipc
type Response struct {
Success bool `json:"success"`
ParseError bool `json:"parse_error"`
Error string `json:"error"`
}
// Stores the user config for the WM
type Config struct {
Config string `json:"config"`
}
// Stores the binding state
type State struct {
Name string `json:"name"`
}
// Create a new swayipc.SwayIPC object. Filename argument is optional and
// may denote a filename or the name of an environment variable.
//
// By default and if nothing is specified we look for the environment
// variable SWAYSOCK and use the file it points to as unix domain
// socket to communicate with sway (and possible i3).
func NewSwayIPC(file ...string) *SwayIPC {
ipc := &SwayIPC{}
if len(file) == 0 {
ipc.SocketFile = "SWAYSOCK"
} else {
ipc.SocketFile = file[0]
}
return ipc
}
// internal convenience wrapper
func (ipc *SwayIPC) get(command uint32) (*RawResponse, error) {
err := ipc.sendHeader(command, 0)
if err != nil {
return nil, err
}
payload, err := ipc.readResponse()
if err != nil {
return nil, err
}
return payload, nil
}

29
v1/version.go Normal file
View File

@@ -0,0 +1,29 @@
package swayipc
import (
"encoding/json"
"fmt"
)
// A version struct holding the sway wm version
type Version struct {
HumanReadable string `json:"human_readable"`
Major int `json:"major"`
Minor int `json:"minor"`
Patch int `json:"patch"`
}
// Get the sway software version
func (ipc *SwayIPC) GetVersion() (*Version, error) {
payload, err := ipc.get(GET_VERSION)
if err != nil {
return nil, err
}
version := &Version{}
if err := json.Unmarshal(payload.Payload, &version); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return version, nil
}