package main import ( // Standard "encoding/binary" "fmt" "net" ) const ( RUN_COMMAND = 0 GET_WORKSPACES = 1 SUBSCRIBE = 2 GET_OUTPUTS = 3 GET_TREE = 4 GET_MARKS = 5 GET_BAR_CONFIG = 6 GET_VERSION = 7 GET_BINDING_MODES = 8 GET_CONFIG = 9 SEND_TICK = 10 SYNC = 11 ) func NewI3Socket(filename string) (I3Socket, error) { var i3Socket I3Socket var err error i3Socket.conn, err = net.Dial("unix", filename) if err != nil { return i3Socket, err } return i3Socket, nil } func (sock I3Socket) Close() error { return sock.conn.Close() } func I3ReadMessage(sock I3Socket) (msg []byte, err error) { buf := make([]byte, 6) if _, err = sock.conn.Read(buf); err != nil { return nil, err } if string(buf) != "i3-ipc" { return nil, fmt.Errorf("Invalid i3 IPC answer") } // LE encoded length buf = make([]byte, 4) if _, err = sock.conn.Read(buf); err != nil { return nil, err } msgLength := binary.LittleEndian.Uint32(buf) // LE encoded msg type buf = make([]byte, 4) if _, err = sock.conn.Read(buf); err != nil { return nil, err } // Requested data buf = make([]byte, msgLength) if _, err = sock.conn.Read(buf); err != nil { return nil, err } msg = buf return } func (sock I3Socket) Request(typ int, message string) ([]byte, error) { header := []byte("i3-ipc") buf := make([]byte, 8) binary.LittleEndian.PutUint32(buf, uint32(len(message))) binary.LittleEndian.PutUint32(buf[4:], uint32(typ)) msg := append(header, buf...) msg = append(msg, ([]byte(message))...) _, err := sock.conn.Write(msg) if err != nil { return nil, err } buf, err = I3ReadMessage(sock) if err != nil { return nil, err } return buf, nil }