Cleanup/familiarization commit after spending some time away from illi.
[illi] / illi.go
CommitLineData
6c708f25
AT
1package main
2
3import (
4 "fmt"
5 "log"
6 "os"
7 "os/exec"
8
9 "github.com/jezek/xgb"
6c708f25
AT
10 "github.com/jezek/xgb/xproto"
11)
12
13// TODO: Make a separate keysym file and fully populate it.
14const (
15 XK_q = 0x0071
16 XK_Return = 0xff0d
17)
18
6c708f25 19func main() {
effccebe
AT
20 fmt.Println("ILLI: Execution begins")
21
19cbf0a1
AT
22 xconn := connectToXServer()
23 attachedScreens := getAttachedScreens(xconn)
24 xroot := getXRoot(xconn)
effccebe 25 keymap := getKeyboardMap(xconn)
19cbf0a1 26 registerForKeyEvents(xconn, xroot, keymap)
12099ed6 27
19cbf0a1 28 becomeWM(xconn, xroot)
12099ed6 29
19cbf0a1 30 // Build a list of windows needing management ------------------------------
6c708f25 31
19cbf0a1
AT
32 if len(attachedScreens) > 0 {
33 fmt.Println("The Go compiler is waaaaay too picky about unused variables...")
6c708f25
AT
34 }
35
effccebe 36 tree, err := xproto.QueryTree(xconn, xroot.Root).Reply()
6c708f25
AT
37 if err != nil {
38 log.Fatal(err)
39 }
40 if tree != nil {
41 //workspaces = make(map[string]*Workspace)
42 //defaultw := &Workspace{mu: &sync.Mutex{}}
43 for _, c := range tree.Children {
effccebe 44 if isMappedWindow(xconn, c) {
6c708f25
AT
45// err := defaultw.Add(c)
46// if err != nil {
47// log.Println(err)
48// }
49 fmt.Println("ILLI: Found a client.")
50 }
51
52 }
53
54// if len(attachedScreens) > 0 {
55// defaultw.Screen = &attachedScreens[0]
56// }
57//
58// workspaces["default"] = defaultw
59//
60// if err := defaultw.TileWindows(); err != nil {
61// log.Println(err)
62// }
63
64 }
65
12099ed6
AT
66 // Main program loop reacts to X events ------------------------------------
67
6c708f25
AT
68eventloop:
69 for {
effccebe 70 xevent, err := xconn.WaitForEvent()
6c708f25
AT
71 if err != nil {
72 log.Println(err)
73 continue
74 }
75 switch e := xevent.(type) {
76 case xproto.KeyPressEvent:
effccebe 77 if err := handleKeyPressEvent(keymap, e); err != nil {
6c708f25
AT
78 break eventloop
79 }
80 default:
81 log.Println(xevent)
82 }
83 }
84}
85
12099ed6
AT
86// The client list appears to have some entries for windows that shouldn't
87// actually be viewable. For now, it appears that only windows with a
88// `MapState` value of 2 should be viewable. TODO: Verify this.
89// - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L3772
90// - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L10287
effccebe
AT
91func isMappedWindow(conn *xgb.Conn, windowID xproto.Window) bool {
92 reply, err := xproto.GetWindowAttributes(conn, windowID).Reply()
6c708f25
AT
93 if err != nil {
94 log.Fatal(err)
95 }
6c708f25
AT
96 if reply != nil && reply.MapState == 2 {
97 return true
98 }
99 return false
100}
101
12099ed6
AT
102// TODO: Determine how I want to split the main event loop from the various
103// event handlers (like this keypress handler). It shouldn't grow too
104// fragmented, nor should it grow into a monolithic beast, but the balance
105// needs to be selected after the handlers are built out more completely.
effccebe 106func handleKeyPressEvent(keymap [256][]xproto.Keysym, key xproto.KeyPressEvent) error {
6c708f25
AT
107 switch keymap[key.Detail][0] {
108 case XK_q:
109 switch key.State {
110 case xproto.ModMask1 | xproto.ModMaskShift:
111 // TODO: Where and how do I want to handle exit/restart?
112 // -------------------------
113 // We must manually close the X connection since we used
114 // `defer` when setting it up and os.Exit() short-circuits
115 // that deferral.
effccebe 116 //xc.Close()
6c708f25
AT
117 os.Exit(0)
118 }
119 case XK_Return:
120 switch key.State {
121 case xproto.ModMask1 | xproto.ModMaskShift:
122 cmd := exec.Command("xterm")
123 err := cmd.Start()
124 if err != nil {
125 log.Fatal(err)
126 }
127 }
128 default:
129 return nil
130 }
12099ed6 131 return nil // TODO: What do I actually want to return here?
6c708f25 132}