implemented everything else and added more examples and docs

This commit is contained in:
2025-08-15 12:16:08 +02:00
parent f5b0ee026f
commit 4f7e27528b
37 changed files with 954 additions and 3027 deletions

109
README.md Normal file
View File

@@ -0,0 +1,109 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/i3ipc)](https://goreportcard.com/report/github.com/tlinden/i3ipc)
[![Actions](https://github.com/tlinden/i3ipc/actions/workflows/ci.yaml/badge.svg)](https://github.com/tlinden/i3ipc/actions)
![GitHub License](https://img.shields.io/github/license/tlinden/i3ipc)
[![GoDoc](https://godoc.org/github.com/tlinden/i3ipc?status.svg)](https://godoc.org/github.com/tlinden/i3ipc)
# i3ipc - go bindings to control sway (and possibly i3)
This is a go module which you can use to control [sway](https://swaywm.org/),
[swayfx](https://github.com/WillPower3309/swayfx) and possibly [i3wm](http://i3wm.org/).
## About
i3ipc's interprocess communication (or ipc) is the interface i3wm and
sway use to receive commands from client applications such as
i3-msg. It also features a publish/subscribe mechanism for notifying
interested parties of window manager events.
i3ipc 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.
For details on how to use the library, see the
[reference documentation](https://godoc.org/github.com/tlinden/i3ipc).
## Example usage
In this example we retrieve the current focused window:
```go
package main
import (
"fmt"
"log"
"github.com/tlinden/i3ipc"
)
func main() {
ipc := i3ipc.NewI3ipc()
err := ipc.Connect()
if err != nil {
log.Fatal(err)
}
defer ipc.Close()
tree, err := ipc.GetTree()
if err != nil {
log.Fatal(err)
}
focused := tree.FindFocused()
if focused != nil {
fmt.Printf("focused node: %s\n id: %d\n Geometry: %dx%d\n",
focused.Name, focused.Id, focused.Geometry.Width,
focused.Geometry.Height)
}
}
```
Also take a look into the **_examples** folder for more examples.
You may take a look at the [tool swaycycle](https://github.com/tlinden/swaycycle)
which is using this module.
## Installation
Execute this to add the module to your project:
```sh
go get github.com/tlinden/i3ipc
```
## Acknowledgements
A couple of ideas have been taken from the [i3ipc python
module](https://github.com/altdesktop/i3ipc-python/), although this
one is not just a port of it and has been written from scratch.
## Getting help
Although I'm happy to hear from i3ipc users in private email, that's the
best way for me to forget to do something.
In order to report a bug, unexpected behavior, feature requests or to
submit a patch, please open an issue on github:
https://github.com/TLINDEN/i3ipc/issues.
## Copyright and license
This software is licensed under the GNU GENERAL PUBLIC LICENSE version 3.
## Authors
T.v.Dein <tom AT vondein DOT org>
## Project homepage
https://github.com/TLINDEN/i3ipc
## Copyright and License
Licensed under the GNU GENERAL PUBLIC LICENSE version 3.
## Author
T.v.Dein <tom AT vondein DOT org>

View File

@@ -1,8 +1,3 @@
# to be implemented # to be implemented
- subscribe
- events
- send_tick - send_tick
- `get_binding_state`
- get_inputs
- get_seats

View File

@@ -8,7 +8,7 @@ import (
) )
func main() { func main() {
ipc := i3ipc.NewI3ipc("SWAYSOCK") ipc := i3ipc.NewI3ipc()
err := ipc.Connect() err := ipc.Connect()
if err != nil { if err != nil {

58
_examples/events/main.go Normal file
View File

@@ -0,0 +1,58 @@
package main
/*
Demonstrate subscribing to events
*/
import (
"encoding/json"
"fmt"
"log"
"github.com/alecthomas/repr"
"github.com/tlinden/i3ipc"
)
// Event callback function, needs to implement each subscribed events,
// fed to it as RawResponse
func ProcessTick(event *i3ipc.RawResponse) error {
var err error
switch event.PayloadType {
case i3ipc.EV_Tick:
ev := &i3ipc.EventTick{}
err = json.Unmarshal(event.Payload, &ev)
repr.Println(ev)
case i3ipc.EV_Window:
ev := &i3ipc.EventWindow{}
err = json.Unmarshal(event.Payload, &ev)
repr.Println(ev)
default:
return fmt.Errorf("received unsubscribed event %d", event.PayloadType)
}
if err != nil {
return err
}
return nil
}
func main() {
ipc := i3ipc.NewI3ipc()
err := ipc.Connect()
if err != nil {
log.Fatal(err)
}
defer ipc.Close()
_, err = ipc.Subscribe(&i3ipc.Event{
Tick: true,
Window: true,
})
if err != nil {
log.Fatal(err)
}
ipc.EventLoop(ProcessTick)
}

View File

@@ -8,12 +8,13 @@ import (
) )
func main() { func main() {
ipc := i3ipc.NewI3ipc("SWAYSOCK") ipc := i3ipc.NewI3ipc()
err := ipc.Connect() err := ipc.Connect()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
tree, err := ipc.GetTree() tree, err := ipc.GetTree()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -19,6 +19,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
bars, err := ipc.GetBars() bars, err := ipc.GetBars()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -18,6 +18,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
config, err := ipc.GetConfig() config, err := ipc.GetConfig()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -0,0 +1,29 @@
package main
/*
Retrieve a list of current available inputs
*/
import (
"log"
"github.com/alecthomas/repr"
"github.com/tlinden/i3ipc"
)
func main() {
ipc := i3ipc.NewI3ipc()
err := ipc.Connect()
if err != nil {
log.Fatal(err)
}
defer ipc.Close()
inputs, err := ipc.GetInputs()
if err != nil {
log.Fatal(err)
}
repr.Println(inputs)
}

View File

@@ -18,6 +18,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
marks, err := ipc.GetMarks() marks, err := ipc.GetMarks()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -1,124 +0,0 @@
execve("/opt/bin/swaymsg", ["swaymsg", "-t", "get_bar_config", "bar-0"], 0x7ffca8a3d4b0 /* 96 vars */) = 0
brk(NULL) = 0x57744ffbd000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x70933d94d000
access("/etc/ld.so.preload", R_OK) = 0
openat(AT_FDCWD, "/etc/ld.so.preload", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
close(3) = 0
openat(AT_FDCWD, "glibc-hwcaps/x86-64-v3/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "glibc-hwcaps/x86-64-v2/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/", 0x7fffe6d741a0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/", 0x7fffe6d741a0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=137987, ...}) = 0
mmap(NULL, 137987, PROT_READ, MAP_PRIVATE, 3, 0) = 0x70933d92b000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libjson-c.so.5", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=80344, ...}) = 0
mmap(NULL, 82416, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x70933d916000
mmap(0x70933d91a000, 45056, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x70933d91a000
mmap(0x70933d925000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xf000) = 0x70933d925000
mmap(0x70933d929000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x12000) = 0x70933d929000
close(3) = 0
openat(AT_FDCWD, "glibc-hwcaps/x86-64-v3/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "glibc-hwcaps/x86-64-v2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/opt/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\247\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 840, 64) = 840
fstat(3, {st_mode=S_IFREG|0755, st_size=2178688, ...}) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 840, 64) = 840
mmap(NULL, 2223736, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x70933d600000
mmap(0x70933d628000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x70933d628000
mmap(0x70933d7bd000, 323584, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x70933d7bd000
mmap(0x70933d80c000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x20b000) = 0x70933d80c000
mmap(0x70933d812000, 52856, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x70933d812000
close(3) = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x70933d913000
arch_prctl(ARCH_SET_FS, 0x70933d913740) = 0
set_tid_address(0x70933d913a10) = 97421
set_robust_list(0x70933d913a20, 24) = 0
rseq(0x70933d913680, 0x20, 0, 0x53053053) = 0
mprotect(0x70933d80c000, 16384, PROT_READ) = 0
mprotect(0x70933d929000, 4096, PROT_READ) = 0
mprotect(0x577441241000, 4096, PROT_READ) = 0
mprotect(0x70933d98f000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x70933d92b000, 137987) = 0
ioctl(1, TCGETS, 0x7fffe6d74e80) = -1 ENOTTY (Inappropriate ioctl for device)
getrandom("\xf3\xb2\x5f\xb5\x3a\x0e\x13\x06", 8, GRND_NONBLOCK) = 8
brk(NULL) = 0x57744ffbd000
brk(0x57744ffde000) = 0x57744ffde000
socket(AF_UNIX, SOCK_STREAM, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/run/user/1000/sway-ipc.1000.3461.sock"}, 110) = 0
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO_OLD, "\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
write(3, "i3-ipc\5\0\0\0\6\0\0\0", 14) = 14
write(3, "bar-0", 5) = 5
recvfrom(3, "i3-ipc\332\4\0\0\6\0\0\0", 14, 0, NULL, NULL) = 14
recvfrom(3, "{ \"id\": \"bar-0\", \"mode\": \"dock\","..., 1242, 0, NULL, NULL) = 1242
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_DROPPABLE|MAP_ANONYMOUS, -1, 0) = 0x70933d94c000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x70933d94b000
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getrandom("\x92\xda\xab\x78\x81\x42\x79\x34\x6f\x90\x94\x8c\xb4\x47\xfb\x85\xc1\x00\x43\x1b\x00\x78\x10\x09\x87\x65\x09\x2e\x79\xdb\x4d\xf7", 32, 0) = 32
fstat(1, {st_mode=S_IFREG|0644, st_size=5648, ...}) = 0
close(3) = 0
write(1, "{\n \"id\": \"bar-0\",\n \"mode\": \"do"..., 1387{
"id": "bar-0",
"mode": "dock",
"hidden_state": "hide",
"position": "top",
"status_command": null,
"font": "monospace 10",
"gaps": {
"top": 0,
"right": 0,
"bottom": 0,
"left": 0
},
"bar_height": 0,
"status_padding": 1,
"status_edge_padding": 3,
"wrap_scroll": false,
"workspace_buttons": true,
"strip_workspace_numbers": false,
"strip_workspace_name": false,
"workspace_min_width": 0,
"binding_mode_indicator": true,
"verbose": false,
"pango_markup": true,
"colors": {
"background": "#000000ff",
"statusline": "#ffffffff",
"separator": "#666666ff",
"focused_background": "#000000ff",
"focused_statusline": "#ffffffff",
"focused_separator": "#666666ff",
"focused_workspace_border": "#4c7899ff",
"focused_workspace_bg": "#285577ff",
"focused_workspace_text": "#ffffffff",
"inactive_workspace_border": "#333333ff",
"inactive_workspace_bg": "#222222ff",
"inactive_workspace_text": "#888888ff",
"active_workspace_border": "#333333ff",
"active_workspace_bg": "#5f676aff",
"active_workspace_text": "#ffffffff",
"urgent_workspace_border": "#2f343aff",
"urgent_workspace_bg": "#900000ff",
"urgent_workspace_text": "#ffffffff",
"binding_mode_border": "#2f343aff",
"binding_mode_bg": "#900000ff",
"binding_mode_text": "#ffffffff"
},
"tray_padding": 2
}
) = 1387
exit_group(0) = ?
+++ exited with 0 +++

View File

@@ -18,6 +18,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
outputs, err := ipc.GetOutputs() outputs, err := ipc.GetOutputs()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -0,0 +1,29 @@
package main
/*
Retrieve a list of current available inputs
*/
import (
"log"
"github.com/alecthomas/repr"
"github.com/tlinden/i3ipc"
)
func main() {
ipc := i3ipc.NewI3ipc()
err := ipc.Connect()
if err != nil {
log.Fatal(err)
}
defer ipc.Close()
seats, err := ipc.GetSeats()
if err != nil {
log.Fatal(err)
}
repr.Println(seats)
}

View File

@@ -8,7 +8,7 @@ import (
) )
func main() { func main() {
ipc := i3ipc.NewI3ipc("SWAYSOCK") ipc := i3ipc.NewI3ipc()
err := ipc.Connect() err := ipc.Connect()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -18,6 +18,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
version, err := ipc.GetVersion() version, err := ipc.GetVersion()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -18,6 +18,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
workspaces, err := ipc.GetWorkspaces() workspaces, err := ipc.GetWorkspaces()
if err != nil { if err != nil {

View File

@@ -1,346 +0,0 @@
&i3ipc.Node{
Id: 1,
Type: "root",
Name: "root",
Nodes: []*i3ipc.Node{
{
Id: 2147483647,
Type: "output",
Name: "__i3",
Nodes: []*i3ipc.Node{
{
Id: 2147483646,
Type: "workspace",
Name: "__i3_scratch",
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "horizontal",
Focus: []int{
2147483646,
},
Rect: i3ipc.Rect{
Width: 3440,
},
},
{
Id: 4,
Type: "output",
Name: "HDMI-A-1",
Nodes: []*i3ipc.Node{
{
Id: 7,
Type: "workspace",
Name: "2",
Nodes: []*i3ipc.Node{
{
Id: 8,
Type: "con",
Name: "Terminal - 1:2:sh - \"tripod\" ",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.21511628,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 10,
Type: "con",
Name: "postgreslet - F-I-TS-Chat - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.78488374,
Window: 4194311,
Rect: i3ipc.Rect{
X: 740,
Y: 26,
Width: 2700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2696,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
10,
8,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 11,
Type: "workspace",
Name: "3",
Nodes: []*i3ipc.Node{
{
Id: 14,
Type: "con",
Name: "AdZ Desktop (SSL/TLS Secured, 256 bit)",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.3604651,
Window: 14680067,
Rect: i3ipc.Rect{
Y: 26,
Width: 1240,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1236,
},
Geometry: i3ipc.Rect{
Width: 2752,
},
},
{
Id: 12,
Type: "con",
Name: "E-Mail Thomas.vonDein@f-i-ts.de - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.6395349,
Window: 4194324,
Rect: i3ipc.Rect{
X: 1240,
Y: 26,
Width: 2200,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 2196,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
12,
14,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 15,
Type: "workspace",
Name: "4",
Nodes: []*i3ipc.Node{
{
Id: 16,
Type: "con",
Name: "AR System Customizable Home Page (Suchen) - Chromium",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 1,
Window: 4194338,
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
WindowRect: i3ipc.Rect{
Width: 3440,
},
Geometry: i3ipc.Rect{
Width: 1142,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
16,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 17,
Type: "workspace",
Name: "5",
Nodes: []*i3ipc.Node{
{
Id: 19,
Type: "con",
Name: "Terminal - 0:5:go - \"tripod\" ",
Focused: true,
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.50581396,
X11Window: "xfce4-terminal",
Rect: i3ipc.Rect{
Y: 26,
Width: 1740,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1736,
},
Geometry: i3ipc.Rect{
Width: 882,
},
},
{
Id: 18,
Type: "con",
Name: "emacs /home/scip/dev/i3ipc/_examples/tree/main.go",
Border: "pixel",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.49418604,
Window: 18874540,
Rect: i3ipc.Rect{
X: 1740,
Y: 26,
Width: 1700,
},
WindowRect: i3ipc.Rect{
X: 2,
Y: 2,
Width: 1696,
},
Geometry: i3ipc.Rect{
Width: 752,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
19,
18,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
{
Id: 20,
Type: "workspace",
Name: "6",
FloatingNodes: []*i3ipc.Node{
{
Id: 21,
Type: "floating_con",
Name: "Home - Webex - Google Chrome",
Border: "csd",
Layout: "none",
Orientation: "none",
CurrentBorderWidth: 2,
Percent: 0.7971424,
X11Window: "google-chrome",
Rect: i3ipc.Rect{
X: 481,
Y: 35,
Width: 2822,
},
WindowRect: i3ipc.Rect{
Width: 2822,
},
Geometry: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
21,
},
Rect: i3ipc.Rect{
Y: 26,
Width: 3440,
},
},
},
Border: "none",
Layout: "output",
Orientation: "none",
Percent: 1,
Focus: []int{
17,
7,
20,
11,
15,
},
Current_workspace: "5",
Rect: i3ipc.Rect{
Width: 3440,
},
},
},
Border: "none",
Layout: "splith",
Orientation: "horizontal",
Focus: []int{
4,
},
Rect: i3ipc.Rect{
Width: 3440,
},
}
root: root
node: __i3
focus: false
recursing
node: __i3_scratch
focus: false
recursing
nil

View File

@@ -20,6 +20,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
// retrieve the sway tree // retrieve the sway tree
tree, err := ipc.GetTree() tree, err := ipc.GetTree()
@@ -36,7 +37,7 @@ func main() {
// finally execute the given commands on it, you can use any run // finally execute the given commands on it, you can use any run
// command, see sway(5) // command, see sway(5)
responses, err := ipc.RunCommand(focused.Id, "floating toggle, border toggle") responses, err := ipc.RunContainerCommand(focused.Id, "floating toggle, border toggle")
if err != nil { if err != nil {
repr.Println(responses) repr.Println(responses)
log.Fatal(err) log.Fatal(err)

View File

@@ -19,6 +19,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer ipc.Close()
responses, err := ipc.RunGlobalCommand("border toggle") responses, err := ipc.RunGlobalCommand("border toggle")
if err != nil { if err != nil {

View File

@@ -0,0 +1,39 @@
package main
/*
send a tick with an arbitrary payload, supply some argument to the
command, which will then be attached to the tick. Use the events
example to retrieve the tick (command out the Window event type to
better see it)
*/
import (
"fmt"
"log"
"os"
"github.com/tlinden/i3ipc"
)
func main() {
payload := "send_tick.go"
if len(os.Args) > 1 {
payload = os.Args[1]
}
ipc := i3ipc.NewI3ipc()
err := ipc.Connect()
if err != nil {
log.Fatal(err)
}
defer ipc.Close()
err = ipc.SendTick(payload)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Sent tick with payload '%s'.\n", payload)
}

25
bar.go
View File

@@ -1,3 +1,19 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
@@ -5,6 +21,7 @@ import (
"fmt" "fmt"
) )
// Container gaps
type Gaps struct { type Gaps struct {
Top int `json:"top"` Top int `json:"top"`
Right int `json:"right"` Right int `json:"right"`
@@ -12,6 +29,7 @@ type Gaps struct {
Left int `json:"left"` Left int `json:"left"`
} }
// Color definition, used primarily by bars
type Colors struct { type Colors struct {
Background string `json:"background"` Background string `json:"background"`
Statusline string `json:"statusline"` Statusline string `json:"statusline"`
@@ -36,6 +54,7 @@ type Colors struct {
BindingModeText string `json:"binding_mode_text"` BindingModeText string `json:"binding_mode_text"`
} }
// A bar such as a swaybar(5)
type Bar struct { type Bar struct {
Id string `json:"id"` Id string `json:"id"`
Mode string `json:"mode"` Mode string `json:"mode"`
@@ -54,6 +73,7 @@ type Bar struct {
Colors *Colors `json:"colors"` Colors *Colors `json:"colors"`
} }
// Get a list of currently visible and active bar names
func (ipc *I3ipc) GetBars() ([]string, error) { func (ipc *I3ipc) GetBars() ([]string, error) {
payload, err := ipc.get(GET_BAR_CONFIG) payload, err := ipc.get(GET_BAR_CONFIG)
if err != nil { if err != nil {
@@ -61,13 +81,14 @@ func (ipc *I3ipc) GetBars() ([]string, error) {
} }
bars := []string{} bars := []string{}
if err := json.Unmarshal(payload, &bars); err != nil { if err := json.Unmarshal(payload.Payload, &bars); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err) return nil, fmt.Errorf("failed to unmarshal json: %w", err)
} }
return bars, nil return bars, nil
} }
// Get the bar object of the bar specified by the string 'id'
func (ipc *I3ipc) GetBar(id string) (*Bar, error) { func (ipc *I3ipc) GetBar(id string) (*Bar, error) {
err := ipc.sendHeader(GET_BAR_CONFIG, uint32(len(id))) err := ipc.sendHeader(GET_BAR_CONFIG, uint32(len(id)))
if err != nil { if err != nil {
@@ -85,7 +106,7 @@ func (ipc *I3ipc) GetBar(id string) (*Bar, error) {
} }
bar := &Bar{} bar := &Bar{}
if err := json.Unmarshal(payload, &bar); err != nil { if err := json.Unmarshal(payload.Payload, &bar); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err) return nil, fmt.Errorf("failed to unmarshal json: %w", err)
} }

93
command.go Normal file
View File

@@ -0,0 +1,93 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc
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 *I3ipc) 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 *I3ipc) 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 *I3ipc) 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
}

200
event.go Normal file
View File

@@ -0,0 +1,200 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc
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 i3ipc 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 i3ipc.Event object
// accordingly.
//
// Returns a response list containing a response for every subscribed
// event.
func (ipc *I3ipc) 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
// i3ipc.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 *I3ipc) 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
}
}
}

157
i3ipc.go
View File

@@ -1,10 +1,24 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
"encoding/json"
"fmt"
"net" "net"
"strings"
) )
const ( const (
@@ -30,34 +44,49 @@ const (
SEND_TICK SEND_TICK
SYNC SYNC
GET_BINDING_STATE GET_BINDING_STATE
GET_INPUTS
GET_SEATS GET_INPUTS = 100
GET_SEATS = 101
) )
// module struct // This is the primary struct to work with the i3ipc module.
type I3ipc struct { type I3ipc struct {
socket net.Conn socket net.Conn
SocketFile string SocketFile string // filename of the i3 IPC socket
Events *Event // store subscribed events, see i3ipc.Subscribe()
} }
// i3-ipc structs // A rectangle struct, used at various places for geometry etc.
type Rect struct { type Rect struct {
X int `json:"x"` X int `json:"x"` // X coordinate
Y int `json:"y"` Y int `json:"y"` // Y coordinate
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
} }
// Stores responses retrieved via ipc
type Response struct { type Response struct {
Success bool `json:"success"` Success bool `json:"success"`
ParseError bool `json:"parse_error"` ParseError bool `json:"parse_error"`
Error string `json:"error"` Error string `json:"error"`
} }
// Stores the user config for the WM
type Config struct { type Config struct {
Config string `json:"config"` Config string `json:"config"`
} }
// Stores the binding state
type State struct {
Name string `json:"name"`
}
// Create a new i3ipc.I3ipc 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 NewI3ipc(file ...string) *I3ipc { func NewI3ipc(file ...string) *I3ipc {
ipc := &I3ipc{} ipc := &I3ipc{}
@@ -70,7 +99,8 @@ func NewI3ipc(file ...string) *I3ipc {
return ipc return ipc
} }
func (ipc *I3ipc) get(command uint32) ([]byte, error) { // internal convenience wrapper
func (ipc *I3ipc) get(command uint32) (*RawResponse, error) {
err := ipc.sendHeader(command, 0) err := ipc.sendHeader(command, 0)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -83,108 +113,3 @@ func (ipc *I3ipc) get(command uint32) ([]byte, error) {
return payload, nil return payload, nil
} }
func (ipc *I3ipc) RunGlobalCommand(command ...string) ([]Response, error) {
return ipc.RunCommand(0, command...)
}
func (ipc *I3ipc) RunCommand(id int, command ...string) ([]Response, error) {
if len(command) == 0 {
return nil, fmt.Errorf("empty command arg")
}
commands := strings.Join(command, ",")
if id > 0 {
commands = fmt.Sprintf("[con_id=%d] %s", 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, &responses); err != nil {
return nil, fmt.Errorf("failed to unmarshal json response: %w", err)
}
if len(responses) == 0 {
return nil, fmt.Errorf("got zero IPC response")
}
for _, response := range responses {
if !response.Success {
return responses, fmt.Errorf("one or more commands failed")
}
}
return responses, nil
}
func (ipc *I3ipc) GetWorkspaces() ([]*Node, error) {
payload, err := ipc.get(GET_WORKSPACES)
if err != nil {
return nil, err
}
nodes := []*Node{}
if err := json.Unmarshal(payload, &nodes); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return nodes, nil
}
func (ipc *I3ipc) GetMarks() ([]string, error) {
payload, err := ipc.get(GET_MARKS)
if err != nil {
return nil, err
}
marks := []string{}
if err := json.Unmarshal(payload, &marks); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return marks, nil
}
func (ipc *I3ipc) GetBindingModes() ([]string, error) {
payload, err := ipc.get(GET_BINDING_MODES)
if err != nil {
return nil, err
}
modes := []string{}
if err := json.Unmarshal(payload, &modes); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err)
}
return modes, nil
}
func (ipc *I3ipc) GetConfig() (string, error) {
payload, err := ipc.get(GET_CONFIG)
if err != nil {
return "", err
}
config := &Config{}
if err := json.Unmarshal(payload, &config); err != nil {
return "", fmt.Errorf("failed to unmarshal json: %w", err)
}
return config.Config, nil
}

82
input.go Normal file
View File

@@ -0,0 +1,82 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc
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 *I3ipc) 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
}

36
net.go
View File

@@ -1,12 +1,31 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
) )
// Connect to unix domain ipc socket.
func (ipc *I3ipc) Connect() error { func (ipc *I3ipc) Connect() error {
if !fileExists(ipc.SocketFile) { if !fileExists(ipc.SocketFile) {
ipc.SocketFile = os.Getenv(ipc.SocketFile) ipc.SocketFile = os.Getenv(ipc.SocketFile)
@@ -25,6 +44,7 @@ func (ipc *I3ipc) Connect() error {
return nil return nil
} }
// Close the socket.
func (ipc *I3ipc) Close() { func (ipc *I3ipc) Close() {
ipc.socket.Close() ipc.socket.Close()
} }
@@ -55,7 +75,12 @@ func (ipc *I3ipc) sendPayload(payload []byte) error {
return nil return nil
} }
func (ipc *I3ipc) readResponse() ([]byte, error) { type RawResponse struct {
PayloadType int
Payload []byte
}
func (ipc *I3ipc) readResponse() (*RawResponse, error) {
// read header // read header
buf := make([]byte, IPC_HEADER_SIZE) buf := make([]byte, IPC_HEADER_SIZE)
@@ -65,15 +90,16 @@ func (ipc *I3ipc) readResponse() ([]byte, error) {
} }
if string(buf[:6]) != IPC_MAGIC { if string(buf[:6]) != IPC_MAGIC {
return nil, fmt.Errorf("got invalid response from IPC socket") return nil, errors.New("got invalid response from IPC socket")
} }
payloadLen := binary.LittleEndian.Uint32(buf[6:10]) payloadLen := binary.LittleEndian.Uint32(buf[6:10])
if payloadLen == 0 { if payloadLen == 0 {
return nil, fmt.Errorf("got empty payload response from IPC socket") return nil, errors.New("got empty payload response from IPC socket")
} }
payloadType := binary.LittleEndian.Uint32(buf[10:])
// read payload // read payload
payload := make([]byte, payloadLen) payload := make([]byte, payloadLen)
@@ -82,5 +108,5 @@ func (ipc *I3ipc) readResponse() ([]byte, error) {
return nil, fmt.Errorf("failed to read payload from IPC socket: %s", err) return nil, fmt.Errorf("failed to read payload from IPC socket: %s", err)
} }
return payload, nil return &RawResponse{PayloadType: int(payloadType), Payload: payload}, nil
} }

34
node.go
View File

@@ -1,3 +1,19 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
@@ -5,6 +21,8 @@ import (
"fmt" "fmt"
) )
// A node can be an output, a workspace, a container or a container
// containing a window.
type Node struct { type Node struct {
Id int `json:"id"` Id int `json:"id"`
Type string `json:"type"` // output, workspace or container Type string `json:"type"` // output, workspace or container
@@ -32,6 +50,14 @@ type Node struct {
var __focused *Node var __focused *Node
var __currentworkspace string 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 *I3ipc) GetTree() (*Node, error) { func (ipc *I3ipc) GetTree() (*Node, error) {
err := ipc.sendHeader(GET_TREE, 0) err := ipc.sendHeader(GET_TREE, 0)
if err != nil { if err != nil {
@@ -44,13 +70,15 @@ func (ipc *I3ipc) GetTree() (*Node, error) {
} }
node := &Node{} node := &Node{}
if err := json.Unmarshal(payload, &node); err != nil { if err := json.Unmarshal(payload.Payload, &node); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err) return nil, fmt.Errorf("failed to unmarshal json: %w", err)
} }
return node, nil return node, nil
} }
// Usually called on the root node, returns the container which has
// currently the focus.
func (node *Node) FindFocused() *Node { func (node *Node) FindFocused() *Node {
searchFocused(node.Nodes) searchFocused(node.Nodes)
if __focused == nil { if __focused == nil {
@@ -60,6 +88,7 @@ func (node *Node) FindFocused() *Node {
return __focused return __focused
} }
// internal recursive focus node searcher
func searchFocused(nodes []*Node) { func searchFocused(nodes []*Node) {
for _, node := range nodes { for _, node := range nodes {
if node.Focused { if node.Focused {
@@ -75,11 +104,14 @@ func searchFocused(nodes []*Node) {
} }
} }
// Usually called on the root node, returns the current active
// workspace name.
func (node *Node) FindCurrentWorkspace() string { func (node *Node) FindCurrentWorkspace() string {
searchCurrentWorkspace(node.Nodes) searchCurrentWorkspace(node.Nodes)
return __currentworkspace return __currentworkspace
} }
// internal recursive workspace node searcher
func searchCurrentWorkspace(nodes []*Node) { func searchCurrentWorkspace(nodes []*Node) {
for _, node := range nodes { for _, node := range nodes {
if node.Current_workspace != "" { if node.Current_workspace != "" {

View File

@@ -1,3 +1,19 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
@@ -5,12 +21,14 @@ import (
"fmt" "fmt"
) )
// Store an output mode.
type Mode struct { type Mode struct {
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
Refresh int `json:"refresh"` Refresh int `json:"refresh"`
} }
// An output object (i.e. a physical monitor)
type Output struct { type Output struct {
Name string `json:"name"` Name string `json:"name"`
Make string `json:"make"` Make string `json:"make"`
@@ -24,6 +42,7 @@ type Output struct {
CurrentMode *Mode `json:"current_mode"` CurrentMode *Mode `json:"current_mode"`
} }
// Get a list of currently available and usable outputs.
func (ipc *I3ipc) GetOutputs() ([]*Output, error) { func (ipc *I3ipc) GetOutputs() ([]*Output, error) {
err := ipc.sendHeader(GET_OUTPUTS, 0) err := ipc.sendHeader(GET_OUTPUTS, 0)
if err != nil { if err != nil {
@@ -36,7 +55,7 @@ func (ipc *I3ipc) GetOutputs() ([]*Output, error) {
} }
workspaces := []*Output{} workspaces := []*Output{}
if err := json.Unmarshal(payload, &workspaces); err != nil { if err := json.Unmarshal(payload.Payload, &workspaces); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err) return nil, fmt.Errorf("failed to unmarshal json: %w", err)
} }

45
seat.go Normal file
View File

@@ -0,0 +1,45 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc
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 *I3ipc) 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
simpletons.go Normal file
View File

@@ -0,0 +1,90 @@
package i3ipc
import (
"encoding/json"
"fmt"
)
func (ipc *I3ipc) 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 *I3ipc) 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 *I3ipc) 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 *I3ipc) 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 *I3ipc) 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 *I3ipc) 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
}

View File

@@ -1,3 +1,19 @@
/*
Copyright © 2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i3ipc package i3ipc
import ( import (
@@ -5,6 +21,7 @@ import (
"fmt" "fmt"
) )
// A version struct holding the sway wm version
type Version struct { type Version struct {
HumanReadable string `json:"human_readable"` HumanReadable string `json:"human_readable"`
Major int `json:"major"` Major int `json:"major"`
@@ -12,6 +29,7 @@ type Version struct {
Patch int `json:"patch"` Patch int `json:"patch"`
} }
// Get the sway software version
func (ipc *I3ipc) GetVersion() (*Version, error) { func (ipc *I3ipc) GetVersion() (*Version, error) {
payload, err := ipc.get(GET_VERSION) payload, err := ipc.get(GET_VERSION)
if err != nil { if err != nil {
@@ -19,7 +37,7 @@ func (ipc *I3ipc) GetVersion() (*Version, error) {
} }
version := &Version{} version := &Version{}
if err := json.Unmarshal(payload, &version); err != nil { if err := json.Unmarshal(payload.Payload, &version); err != nil {
return nil, fmt.Errorf("failed to unmarshal json: %w", err) return nil, fmt.Errorf("failed to unmarshal json: %w", err)
} }