138 lines
2.6 KiB
Go
138 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"syscall"
|
|
|
|
"github.com/jezek/xgbutil"
|
|
"github.com/jezek/xgbutil/xevent"
|
|
"tuxpa.in/a/zlog/log"
|
|
"tuxpa.in/t/wm/src/bsp"
|
|
"tuxpa.in/t/wm/src/handler"
|
|
"tuxpa.in/t/wm/src/handler/domains"
|
|
"tuxpa.in/t/wm/src/sock"
|
|
)
|
|
|
|
func main() {
|
|
|
|
c, err := _main()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
os.Exit(c)
|
|
|
|
}
|
|
func _main() (code int, err error) {
|
|
// connect to the x server
|
|
log.Printf("connecting to xorg")
|
|
x11, err := xgbutil.NewConn()
|
|
if err != nil {
|
|
return 1, err
|
|
}
|
|
defer x11.Conn().Close()
|
|
|
|
addr := parsePath(x11, "./bspwm.sock")
|
|
// create socket
|
|
log.Printf("starting bspwm")
|
|
ln, err := sock.Server(addr)
|
|
if err != nil {
|
|
return 1, err
|
|
}
|
|
defer ln.Close()
|
|
|
|
// construct context
|
|
ctx, stop := signal.NotifyContext(context.Background(),
|
|
os.Interrupt,
|
|
syscall.SIGTERM,
|
|
syscall.SIGQUIT,
|
|
syscall.SIGINT,
|
|
)
|
|
defer stop()
|
|
|
|
// initialize WM state
|
|
w := bsp.NewWM()
|
|
// create a wm-x11 connection
|
|
xwm := bsp.NewXWM(w, x11)
|
|
|
|
go func() {
|
|
err := xwm.Start(ctx)
|
|
if err != nil {
|
|
log.Err(err).Msg("x server shutdown")
|
|
stop()
|
|
}
|
|
}()
|
|
// create a handler
|
|
h := &handler.Handler{
|
|
XWM: xwm,
|
|
}
|
|
// install the handlers
|
|
handler.AddDomain[domains.Node](h, "node")
|
|
handler.AddDomain[domains.Todo](h, "desktop")
|
|
handler.AddDomain[domains.Monitor](h, "monitor")
|
|
handler.AddDomain[domains.Wm](h, "wm")
|
|
handler.AddDomain[domains.Todo](h, "rule")
|
|
handler.AddDomain[domains.Config](h, "config")
|
|
handler.AddDomain[domains.Todo](h, "subscribe")
|
|
handler.AddDomain[domains.Query](h, "query")
|
|
handler.AddDomain[domains.Echo](h, "echo")
|
|
|
|
codeCh := make(chan int, 1)
|
|
|
|
handler.AddDomain[domains.Todo](h, "quit")
|
|
h.AddDomainFunc("quit", func() handler.Domain {
|
|
d := &domains.Lambda{
|
|
Fn: func(x *bsp.XWM, msg *sock.Msg) ([]byte, error) {
|
|
if !msg.HasNext() {
|
|
codeCh <- 0
|
|
return nil, nil
|
|
}
|
|
str := msg.Next()
|
|
cd, err := strconv.Atoi(str)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
codeCh <- cd
|
|
return nil, nil
|
|
},
|
|
}
|
|
return d
|
|
})
|
|
|
|
beforeCh, afterCh, quitCh := xevent.MainPing(xwm.X)
|
|
// message listen loop
|
|
for {
|
|
select {
|
|
case <-beforeCh:
|
|
<-afterCh
|
|
case m := <-ln.Msg():
|
|
h.Run(m)
|
|
case cint := <-codeCh:
|
|
stop()
|
|
return cint, nil
|
|
case <-quitCh:
|
|
stop()
|
|
case <-ctx.Done():
|
|
return 0, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func parsePath(xc *xgbutil.XUtil, path string) *net.UnixAddr {
|
|
if path == "" {
|
|
path = os.Getenv(sock.SOCKET_ENV_VAR)
|
|
}
|
|
if path == "" {
|
|
path = fmt.Sprintf(sock.SOCKET_PATH_TPL, "", xc.Conn().DisplayNumber, xc.Conn().DefaultScreen)
|
|
}
|
|
addr, err := net.ResolveUnixAddr("unix", path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return addr
|
|
}
|