commit 76dc78859b31cd15c8327e64b7684fbc2063a0b4
parent c20f2aa6185c8ac1f7f309c469ea43acd8e8719c
Author: hhvn <dev@hhvn.uk>
Date: Tue, 31 Oct 2023 11:36:24 +0000
Successfully destroys and recreates windows upon bspwm reload
Diffstat:
3 files changed, 54 insertions(+), 21 deletions(-)
diff --git a/bar/bar.go b/bar/bar.go
@@ -42,8 +42,9 @@ var conf = struct {
"/usr/share/fonts/TTF/DejaVuSansMono.ttf",
11.0, 1 }
-var bars *list.List
-var font *truetype.Font
+var bars *list.List
+var font *truetype.Font
+var stoploop chan bool
type bar struct {
X *xgb.Conn
@@ -162,6 +163,7 @@ func (b *bar) draw() {
func (b *bar) destroy() {
b.Mon.TopPadding(0)
+ xproto.DestroyWindow(b.X, b.w)
}
type eventwrap struct {
@@ -198,8 +200,9 @@ func Init(state *bspc.State) (*Handle, error) {
h.NewState = make(chan *bspc.State)
h.Err = make(chan error)
- events := make(chan *eventwrap)
- xstop := make(chan bool, 1)
+ events := make(chan *eventwrap)
+ stoploop = make(chan bool, 1)
+ xstop := make(chan bool, 1)
go func() { for {
ev, err := x.WaitForEvent()
@@ -229,15 +232,16 @@ func Init(state *bspc.State) (*Handle, error) {
continue
}
- switch e.Ev.(type) {
- case xproto.DestroyNotifyEvent:
- h.Err <- fmt.Errorf("Window destroyed")
- return
- default:
- }
+ // switch e.Ev.(type) {
+ // case xproto.DestroyNotifyEvent:
+ // h.Err <- fmt.Errorf("Window destroyed")
+ // return
+ // default:
+ // }
case id := <- h.Destroy:
destroy(id)
case id := <- h.Create:
+ if getbar(id) != nil { break }
if err := create(x, xu, screen, state.GetMon(id)); err != nil {
h.Err <- fmt.Errorf("Couldn't create window: %s\n", err)
return
@@ -248,6 +252,8 @@ func Init(state *bspc.State) (*Handle, error) {
v.Mon = state.GetMon(v.Mon.ID)
go v.draw()
}
+ case <- stoploop:
+ return
}
}
}()
@@ -255,6 +261,16 @@ func Init(state *bspc.State) (*Handle, error) {
return &h, nil
}
+func getbar(monid int) (*bar) {
+ for e := bars.Front(); e != nil; e = e.Next() {
+ v := e.Value.(*bar)
+
+ if v.Mon.ID == monid { return v }
+ }
+
+ return nil
+}
+
func create(x *xgb.Conn, xu *xgbutil.XUtil,
scr *xproto.ScreenInfo, m *bspc.Monitor) (error) {
var b bar
@@ -284,7 +300,7 @@ func destroy(monid int) (bool) {
/* A monid of -1 means that we're doing
the bar.Cleanup schermoodle today */
- if monid == -1 || monid > 0 && v.Mon.ID == int(monid) {
+ if monid == -1 || monid > 0 && v.Mon.ID == monid {
v.destroy()
bars.Remove(e)
if monid != -1 { return true }
@@ -297,4 +313,5 @@ func destroy(monid int) (bool) {
func Cleanup() {
destroy(-1)
+ stoploop <- true
}
diff --git a/bspc/bspc.go b/bspc/bspc.go
@@ -186,6 +186,10 @@ func (s *Subscriber) get() (*Event, error) {
var err error
for {
line, err = s.getLine()
+ // if line == "W" {
+ // // Send this pseudo event so we know to reload the state
+ // return &Event{"reload", make([]string, 0)}, nil
+ // }
if len(line) > 0 && line[0] != 'W' { break }
}
diff --git a/main.go b/main.go
@@ -15,6 +15,8 @@ var reloadEvents = []string{
"monitor_rename",
"monitor_swap",
"monitor_focus",
+ "monitor_remove",
+ "monitor_geometry", // only event we get for monitors on restart
"desktop_add",
"desktop_rename",
"desktop_remove",
@@ -56,8 +58,11 @@ func handleEvents(events *bspc.Subscriber, bar *bar.Handle) (chan error, chan bo
id, err := common.Intify(event.Tokens[0])
if err == nil {
switch (event.Name) {
- case "monitor_add": bar.Create <- id
- case "monitor_remove": bar.Destroy <- id
+ case "monitor_add":
+ case "monitor_geometry":
+ bar.Create <- id
+ case "monitor_remove":
+ bar.Destroy <- id
}
}
}
@@ -106,15 +111,7 @@ func main() {
everr, evreload := handleEvents(events, barhandle)
for {
-
select {
- case <- evreload:
- state, err = reloadState(state)
- if err != nil {
- common.Error("Couldn't reload bspwm state: %s\n", err)
- }
-
- barhandle.NewState <- state
case err := <- everr:
common.Error("Couldn't read event: %s\n", err)
return
@@ -124,6 +121,21 @@ func main() {
case err := <- barhandle.Err:
common.Error("%s\n", err)
return
+ case <- evreload:
+ state, err = reloadState(state)
+ if err != nil {
+ common.Error("Couldn't reload bspwm state: %s\n", err)
+ }
+
+ // Check if there's been an error before sending the
+ // new state (or else the program gets stuck)
+ select {
+ case err := <- barhandle.Err:
+ common.Error("%s\n", err)
+ return
+ default:
+ }
+ barhandle.NewState <- state
}
}
}