Better handling of store/restore workspaces

This commit is contained in:
Magnus Åhall 2021-12-28 10:57:18 +01:00
parent 08e84947ef
commit f9e815b4e3
2 changed files with 82 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"os/exec" "os/exec"
"regexp" "regexp"
"sort"
"strconv" "strconv"
"strings" "strings"
) )
@ -299,14 +300,29 @@ func (sess I3Session) MarkMove() error {
func (sess *I3Session) StoreWorkspaces() (err error) { func (sess *I3Session) StoreWorkspaces() (err error) {
var workspaces []I3Workspace var workspaces []I3Workspace
sess.workspaces = make(map[int]string) sess.workspaces = make(map[string]string)
sess.workspacesActive = make(map[string]string)
workspaces, err = sess.Workspaces() workspaces, err = sess.Workspaces()
if err != nil { if err != nil {
return return
} }
for _, ws := range workspaces { for _, ws := range workspaces {
sess.workspaces[ws.Id] = ws.Output fmt.Printf("Store workspace: %s - %s\n", ws.Name, ws.Output)
sess.workspaces[ws.Name] = ws.Output
// Visible workspaces are stored to visit them at a restore,
// to make sure they still are visible afterwards.
if ws.Visible {
sess.workspacesActive[ws.Name] = ws.Output
}
// Focused workspace is switched to last, to ensure it is still
// the focused workspace.
if ws.Focused {
sess.activeWorkspace = ws.Name
}
} }
return return
} }
@ -318,18 +334,71 @@ func (sess *I3Session) RestoreWorkspaces() (err error) {
return err return err
} }
for wsId, output := range sess.workspaces { var list [][]string
var wsNum int
for wsName, output := range sess.workspaces {
//fmt.Printf("Restore workspace: %s to %s\n", wsName, output)
components := strings.Split(wsName, ":")
wsNum, err = strconv.Atoi(components[0])
if err != nil {
return err
}
cmd := fmt.Sprintf( cmd := fmt.Sprintf(
"[workspace=%d] move workspace to output %s", "[workspace=\"%s\"] move workspace to output \"%s\"",
wsId, wsName,
output, output,
) )
res, err := sess.Socket.Request(RUN_COMMAND, cmd) list = append(list, []string{
fmt.Sprintf("%03d", wsNum),
cmd,
})
if false {
}
}
sort.SliceStable(list, func(i, j int) bool {
return list[i][0] < list[j][0]
})
for _, cmd := range list {
fmt.Printf("%s: ", cmd)
res, err := sess.Socket.Request(RUN_COMMAND, cmd[1])
if err != nil { if err != nil {
return err return err
} }
fmt.Printf("%s\n", res) fmt.Printf("%s\n", res)
} }
// Visible workspaces are switched to to make sure they still are
// visible afterwards.
for wsName := range sess.workspacesActive {
cmd := fmt.Sprintf(
"workspace \"%s\"",
wsName,
)
_, err = sess.Socket.Request(RUN_COMMAND, cmd)
if err != nil {
return err
}
}
// i3 will often leave user on workspace "1", going to last workspace
// when stored makes for a better user experience.
if sess.activeWorkspace != "" {
cmd := fmt.Sprintf(
"workspace \"%s\"",
sess.activeWorkspace,
)
_, err = sess.Socket.Request(RUN_COMMAND, cmd)
if err != nil {
return err
}
}
return return
} }
@ -361,6 +430,7 @@ func (sess I3Session) FixWorkspaces() error {
// Is workspace on the wrong output? // Is workspace on the wrong output?
wsOutputIdx := ws.Num - (ws.Num % 10) wsOutputIdx := ws.Num - (ws.Num % 10)
if wsOutputIdx != outputIdx { if wsOutputIdx != outputIdx {
fmt.Printf("%s is on wrong output\n", ws.Name)
if (ws.Num % 10) >= len(workspaces) { if (ws.Num % 10) >= len(workspaces) {
return fmt.Errorf( return fmt.Errorf(
"Workspace index doesn't exist", "Workspace index doesn't exist",
@ -368,9 +438,10 @@ func (sess I3Session) FixWorkspaces() error {
} }
cmd := fmt.Sprintf( cmd := fmt.Sprintf(
"[workspace=\"%s\"] move window to workspace \"%d:%s\"", "[workspace=\"%s\"] move window to workspace "+
"\"%d:%s\"",
ws.Name, ws.Name,
(outputIdx*10)+(ws.Num % 10), outputIdx+(ws.Num % 10),
workspaces[(ws.Num % 10)].Name, workspaces[(ws.Num % 10)].Name,
) )
_, err := sess.Socket.Request(RUN_COMMAND, cmd) _, err := sess.Socket.Request(RUN_COMMAND, cmd)

View File

@ -10,7 +10,9 @@ type I3Session struct {
filename string filename string
// workspace ID → output name // workspace ID → output name
workspaces map[int]string workspaces map[string]string
workspacesActive map[string]string
activeWorkspace string
} }
type I3Socket struct { type I3Socket struct {