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