shuttle-go/watch.go

121 wiersze
2.7 KiB
Go

package main
import (
"fmt"
"time"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgb/xtest"
)
type watcher struct {
conn *xgb.Conn
root xproto.Window
activeAtom, nameAtom xproto.Atom
prevWindowName string
lastWindowID xproto.Window
}
func NewWindowWatcher() *watcher {
return &watcher{}
}
func (w *watcher) Setup() error {
X, err := xgb.NewConn()
if err != nil {
return err
}
// Get the window id of the root window.
setup := xproto.Setup(X)
if err := xtest.Init(X); err != nil {
return err
}
w.conn = X
w.root = setup.DefaultScreen(X).Root
// Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW".
aname := "_NET_ACTIVE_WINDOW"
activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
aname).Reply()
if err != nil {
return fmt.Errorf("Couldn't get _NET_ACTIVE_WINDOW atom: %s", err)
}
// Get the atom id (i.e., intern an atom) of "_NET_WM_NAME".
aname = "_NET_WM_NAME"
nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
aname).Reply()
if err != nil {
return fmt.Errorf("Couldn't get _NET_WM_NAME atom: %s", err)
}
w.activeAtom = activeAtom.Atom
w.nameAtom = nameAtom.Atom
return nil
}
func (w *watcher) Run() {
for {
w.watch()
time.Sleep(2 * time.Second)
}
}
func (w *watcher) watch() {
// From github.com/BurntSushi/xgb's examples.
reply, err := xproto.GetProperty(w.conn, false, w.root, w.activeAtom,
xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
if err != nil {
fmt.Println("watch windows, failed to get window properties:", err)
return
}
windowID := xproto.Window(xgb.Get32(reply.Value))
reply, err = xproto.GetProperty(w.conn, false, windowID, w.nameAtom,
xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
if err != nil {
fmt.Println("watch windows, re-failed to get window properties:", err)
return
}
w.lastWindowID = windowID
windowName := string(reply.Value)
if w.prevWindowName != windowName {
w.prevWindowName = windowName
w.loadWindowConfiguration(windowName)
}
}
func (w *watcher) loadWindowConfiguration(windowName string) {
if loadedConfiguration == nil {
fmt.Println("Window name switched, but no configuration:", windowName)
return
}
for _, conf := range loadedConfiguration.Apps {
for _, re := range conf.windowTitleRegexps {
if *debugMode {
fmt.Println("Testing title:", windowName)
}
if re.MatchString(windowName) {
fmt.Printf("Switching configuration for app %q\n", conf.Name)
currentConfiguration = conf
return
}
}
}
if !*debugMode {
currentConfiguration = nil
} else {
fmt.Println("Keeping previous config even if window changed")
}
}