Dev laptop display died, replaced with 15-year old iMac. Updating Makefile accordingly.
[illi] / illi.go
package main
import (
"fmt"
"log"
"os"
"os/exec"
"github.com/jezek/xgb"
"github.com/jezek/xgb/xproto"
)
// TODO: Make a separate keysym file and fully populate it.
const (
XK_q = 0x0071
XK_Return = 0xff0d
)
// TODO: These module-level global variables have arisen while establishing
// basic functionality. Before proceeding much further, figure out what to do
// with them.
var xc *xgb.Conn
var keymap [256][]xproto.Keysym
func main() {
xconn := connectToXServer()
attachedScreens := getAttachedScreens(xconn)
xroot := getXRoot(xconn)
keymap = getKeyboardMap(xconn)
registerForKeyEvents(xconn, xroot, keymap)
becomeWM(xconn, xroot)
// Build a list of windows needing management ------------------------------
xc = xconn
if len(attachedScreens) > 0 {
fmt.Println("The Go compiler is waaaaay too picky about unused variables...")
}
tree, err := xproto.QueryTree(xc, xroot.Root).Reply()
if err != nil {
log.Fatal(err)
}
if tree != nil {
//workspaces = make(map[string]*Workspace)
//defaultw := &Workspace{mu: &sync.Mutex{}}
for _, c := range tree.Children {
if isMappedWindow(c) {
// err := defaultw.Add(c)
// if err != nil {
// log.Println(err)
// }
fmt.Println("ILLI: Found a client.")
}
}
// if len(attachedScreens) > 0 {
// defaultw.Screen = &attachedScreens[0]
// }
//
// workspaces["default"] = defaultw
//
// if err := defaultw.TileWindows(); err != nil {
// log.Println(err)
// }
}
// Main program loop reacts to X events ------------------------------------
eventloop:
for {
xevent, err := xc.WaitForEvent()
if err != nil {
log.Println(err)
continue
}
switch e := xevent.(type) {
case xproto.KeyPressEvent:
if err := handleKeyPressEvent(e); err != nil {
break eventloop
}
default:
log.Println(xevent)
}
}
}
// The client list appears to have some entries for windows that shouldn't
// actually be viewable. For now, it appears that only windows with a
// `MapState` value of 2 should be viewable. TODO: Verify this.
// - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L3772
// - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L10287
func isMappedWindow(windowID xproto.Window) bool {
reply, err := xproto.GetWindowAttributes(xc, windowID).Reply()
if err != nil {
log.Fatal(err)
}
if reply != nil && reply.MapState == 2 {
return true
}
return false
}
// TODO: Determine how I want to split the main event loop from the various
// event handlers (like this keypress handler). It shouldn't grow too
// fragmented, nor should it grow into a monolithic beast, but the balance
// needs to be selected after the handlers are built out more completely.
func handleKeyPressEvent(key xproto.KeyPressEvent) error {
switch keymap[key.Detail][0] {
case XK_q:
switch key.State {
case xproto.ModMask1 | xproto.ModMaskShift:
// TODO: Where and how do I want to handle exit/restart?
// -------------------------
// We must manually close the X connection since we used
// `defer` when setting it up and os.Exit() short-circuits
// that deferral.
xc.Close()
os.Exit(0)
}
case XK_Return:
switch key.State {
case xproto.ModMask1 | xproto.ModMaskShift:
cmd := exec.Command("xterm")
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
}
default:
return nil
}
return nil // TODO: What do I actually want to return here?
}