diff --git a/main.go b/main.go index ead1997..1fda674 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "os" - "regexp" "strings" ) @@ -62,48 +61,34 @@ func main() { } // Find outputs and assign an index to them - outputs, err := session.Outputs() + err = session.UpdateOutputIndices() if err != nil { fmt.Printf("Output error: %s\n", err) os.Exit(1) } - idx := 0 - for _, output := range outputs { - if output.Active { - outputIndices[output.Name] = idx - idx++ - } - } - - // XXX: still needed? Find the configured workspaces - if false { - var configData string - var configLines []string - configData, err = session.Config() - configLines = strings.Split(configData, "\n") - r := regexp.MustCompile(`(?i)^\s*workspace\s+["']?([^"']+?)["']?\s+output\s+["']?([^"']+?)["']?\s*$`) - for _, line := range configLines { - matches := r.FindAllStringSubmatch(line, -1) - if len(matches) > 0 && len(matches[0]) == 3 { - fmt.Printf("%#v\n", matches[0][1:]) - } - } - } // Listen for external commands var conn net.Conn + var n int for { conn, err = listener.Accept() if err != nil { fmt.Printf("Connection accept: %s\n", err) } buf := make([]byte, 1024) - _, err = conn.Read(buf) + n, err = conn.Read(buf) if err != nil { fmt.Printf("Connection read: %s\n", err) - } else { - fmt.Printf("%s\n", buf) } + + cmd := strings.TrimSpace(string(buf[:n])) + if cmd == "fix workspaces" { + err = session.FixWorkspaces() + if err != nil { + fmt.Printf("Fix workspaces: %s\n", err) + } + } + conn.Close() } } diff --git a/session.go b/session.go index 08fc85d..ee7388b 100644 --- a/session.go +++ b/session.go @@ -39,6 +39,28 @@ func (sess I3Session) Outputs() (outputs []I3Output, err error) { return } +// UpdateOutputIndices counts the outputs and assign incdices to them. +// The indices are used to calculate workspace IDs. +func (sess I3Session) UpdateOutputIndices() error { + outputIndices = make(map[string]int) + fmt.Printf("Update output indices:\n") + defer fmt.Printf("\n") + + outputs, err := sess.Outputs() + if err != nil { + return err + } + idx := 0 + for _, output := range outputs { + if output.Active { + fmt.Printf(" %2d %s\n", idx, output.Name) + outputIndices[output.Name] = idx + idx++ + } + } + return nil +} + // Marks query I3 for mark data. func (sess I3Session) Marks() (marks []string, err error) { var outputJson []byte @@ -368,4 +390,53 @@ func (sess I3Session) MarkMove() error { return nil } +// FixWorkspaces moves windows from workspaces on the wrong monitor to +// to workspaces on the correct monitor. For fixing when going to less +// outputs. +func (sess I3Session) FixWorkspaces() error { + // Outputs could be completely different, and could need to be updated. + err := sess.UpdateOutputIndices() + if err != nil { + return err + } + + // Identify workspaces on the wrong output + wss, err := sess.Workspaces() + if err != nil { + return err + } + + var outputIdx int + var found bool + for _, ws := range wss { + outputIdx, found = outputIndices[ws.Output] + outputIdx *= 10 + if !found { + return fmt.Errorf("Output %s not found", ws.Output) + } + + // Is workspace on the wrong output? + wsOutputIdx := ws.Num - (ws.Num % 10) + if wsOutputIdx != outputIdx { + if (ws.Num % 10) >= len(workspaces) { + return fmt.Errorf( + "Workspace index doesn't exist", + ) + } + + cmd := fmt.Sprintf( + "[workspace=\"%s\"] move window to workspace \"%d:%s\"", + ws.Name, + (outputIdx*10)+(ws.Num % 10), + workspaces[(ws.Num % 10)].Name, + ) + _, err := sess.Socket.Request(RUN_COMMAND, cmd) + if err != nil { + return err + } + } + } + return nil +} + // vim: foldmethod=marker