-
Notifications
You must be signed in to change notification settings - Fork 7
/
main.go
139 lines (117 loc) · 2.79 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Example draw-text shows how to draw text to an xgraphics.Image type.
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"os/signal"
"syscall"
"time"
"github.com/TheCreeper/go-notify"
log "github.com/sirupsen/logrus"
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/randr"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/shimmerglass/bar3x/bar"
debugsrv "github.com/shimmerglass/bar3x/debug"
)
const childEnv = "BAR3X_CHILD"
func main() {
if os.Getenv(childEnv) != "" {
runChild()
return
}
var cmd *exec.Cmd
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGHUP)
go func() {
for range sigs {
if cmd != nil {
syscall.Kill(cmd.Process.Pid, syscall.SIGUSR1)
}
}
}()
for {
cmd = exec.Command(os.Args[0], os.Args[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=1", childEnv))
err := cmd.Run()
if err != nil {
log.Error(err)
}
code := cmd.ProcessState.ExitCode()
if code > 0 {
ntf := notify.NewNotification("bar3x", fmt.Sprintf("bar3x: exited with status %d", cmd.ProcessState.ExitCode()))
ntf.Show()
time.Sleep(time.Second)
}
}
}
func runChild() {
cfgPath := flag.String("config", "", "YAML Config file path")
themePath := flag.String("theme", "", "YAML Theme file path")
debug := flag.Bool("debug", false, "Enable profile server on port 6060")
debugAddr := flag.String("debug-addr", "127.0.0.1:6060", "Debug server addr")
flag.Parse()
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGHUP, syscall.SIGUSR1)
go func() {
for range sigs {
os.Exit(0)
}
}()
cfg, err := getConfig(*cfgPath, *themePath)
if err != nil {
log.Fatal(err)
}
X, err := xgbutil.NewConn()
if err != nil {
log.Fatal(err)
}
err = randr.Init(X.Conn())
if err != nil {
log.Fatal(err)
}
err = randr.SelectInputChecked(X.Conn(), X.RootWin(),
randr.NotifyMaskScreenChange|
randr.NotifyMaskCrtcChange|
randr.NotifyMaskOutputChange|
randr.NotifyMaskOutputProperty).Check()
if err != nil {
log.Fatal(err)
}
xevent.HookFun(func(xu *xgbutil.XUtil, event interface{}) bool {
switch event.(type) {
case randr.ScreenChangeNotifyEvent:
os.Exit(0)
case randr.NotifyEvent:
os.Exit(0)
}
return true
}).Connect(X)
xevent.ErrorHandlerSet(X, func(err xgb.Error) {
// we sometimes get BadWindow errors from the tray, I'm not sure why
// silence them to avoid flooding the output
if _, ok := err.(xproto.WindowError); ok {
return
}
log.Errorf("x handler error: %s", err)
})
bars, err := bar.CreateBars(cfg, X)
if err != nil {
log.Fatal(err)
}
if *debug {
go func() {
err := debugsrv.Run(*debugAddr, bars)
if err != nil {
log.Fatal(err)
}
}()
}
xevent.Main(X)
}