package main import ( "encoding/json" "fmt" r "gitnet.fr/deblan/i3-blocks-go/rendering" // "os" "flag" "os/exec" "strconv" "strings" ) type WindowProperty struct { Title string `json:"title"` Instance int `json:"instance"` } const binI3Msg = "i3-msg" type Tree struct { Num int `json:"num"` Output string `json:"output"` FloatingNodes []Tree `json:"floating_nodes"` Nodes []Tree `json:"nodes"` Window int `json:"window"` Name string `json:"name"` Focused bool `json:"focused"` Urgent bool `json:"urgent"` WindowProperties WindowProperty `json:"window_properties"` } type Workspace struct { Num int `json:"num"` Visible bool `json:"visible"` } func Focus(window int) { exec.Command(binI3Msg, fmt.Sprintf("[id=%d] focus", window)).Run() } func GetTree() Tree { output, _ := exec.Command(binI3Msg, "-t", "get_tree").Output() tree := Tree{} json.Unmarshal(output, &tree) return tree } func GetVisibleWorkspaces() []Workspace { output, _ := exec.Command(binI3Msg, "-t", "get_workspaces").Output() workspaces := []Workspace{} datas := []Workspace{} json.Unmarshal(output, &datas) for _, workspace := range datas { if workspace.Visible { workspaces = append(workspaces, workspace) } } return workspaces } func GetVisibleNodes(tree Tree, workspaces []Workspace) []Tree { var nodes []Tree var visibleNodes []Tree for _, workspace := range workspaces { if tree.Num == workspace.Num { for _, node := range tree.Nodes { nodes = append(nodes, node) } for _, node := range tree.FloatingNodes { nodes = append(nodes, node) } } else if tree.Output == "__i3" && tree.Window > 0 { nodes = []Tree{tree} } } for _, node := range tree.Nodes { nNodes := GetVisibleNodes(node, workspaces) for _, n := range nNodes { nodes = append(nodes, n) } } for _, node := range tree.FloatingNodes { nNodes := GetVisibleNodes(node, workspaces) for _, n := range nNodes { nodes = append(nodes, n) } } for _, node := range nodes { if node.Window > 0 { visibleNodes = append(visibleNodes, node) } else { for _, sNode := range node.Nodes { visibleNodes = append(visibleNodes, sNode) } for _, sNode := range node.FloatingNodes { visibleNodes = append(visibleNodes, sNode) } } } return visibleNodes } func main() { workspaces := GetVisibleWorkspaces() tree := GetTree() nodes := GetVisibleNodes(tree, workspaces) argX := flag.String("x", "", "") flag.Parse() x := 0 minX := 0 if *argX != "" { x, _ = strconv.Atoi(*argX) } options := r.NewBlockOptions() for _, app := range nodes { foreground := "#9cb7d1" background := "#222222" title := strings.ToUpper(app.WindowProperties.Title) if len(title) > 30 { title = fmt.Sprintf("%s…", title[0:29]) } size := (len(title) + 4) * 6 maxX := minX + size isClicked := (x > minX && x < maxX) if app.Urgent { foreground = "#ffffff" background = "#07c0d4" } else if app.Focused || isClicked { foreground = "#07c0d4" background = "#333333" } else if app.Output == "__i3" { foreground = "#bababa" } if isClicked { Focus(app.Window) } fb := r.FB{ Foreground: foreground, Background: background, } options.FullText = fmt.Sprintf("%s%s", options.FullText, r.TextWithPadding(title, fb)) minX = maxX } block := r.Block("workspace_apps", options) fmt.Println(block) }