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 attachedScreens []xinerama.ScreenInfo
var xroot xproto.ScreenInfo
var keymap [256][]xproto.Keysym
func main() {
+
+ // Build a connection to the X server --------------------------------------
+
xConn, err := xgb.NewConn()
if err != nil {
log.Fatal(err)
xc = xConn
defer xc.Close()
+ // Determine what sort of screen(s) will display output --------------------
+
setup := xproto.Setup(xc)
if setup == nil || len(setup.Roots) < 1 {
log.Fatal("ILLI: Unable to parse received SetupInfo from X11 server.")
}
}
+ // Establish a root for the tree -------------------------------------------
+
connInfo := xproto.Setup(xc)
if connInfo == nil {
log.Fatal("ILLI: Unable to parse X connection information")
}
xroot = connInfo.Roots[0]
- // Attempt to register as the window manager
+ // Register with the X server as the new window manager --------------------
+
if err := TakeWMOwnership(); err != nil {
if _, ok := err.(xproto.AccessError); ok {
log.Fatal("ILLI: Unable to register as window manager with X server. Perhaps another WM is already running?")
fmt.Println("ILLI: Successfully registered as WM with X server.")
-// -----------------------------------------------------------------------------
+ // Setup keysym mappings and register for WM-relevant key events -----------
const (
loKey = 8
}
}
-// -----------------------------------------------------------------------------
+ // Build a list of windows needing management ------------------------------
tree, err := xproto.QueryTree(xc, xroot.Root).Reply()
if err != nil {
}
+ // Main program loop reacts to X events ------------------------------------
+
eventloop:
for {
xevent, err := xc.WaitForEvent()
}
}
+// In addition to the basic key/button press/release events, by registering for
+// events like SubstructureRedirect, we are declaring our intent to act as
+// window manager for this X server. Only one WM is allowed per X server, a
+// policy enforced on the X server's side by refusing the registration request
+// for events like SubstructureRedirect if an existing process already receives
+// those events (i.e. is already the window manager).
func TakeWMOwnership() error {
return xproto.ChangeWindowAttributesChecked(
xc,
xproto.EventMaskButtonRelease |
xproto.EventMaskStructureNotify |
xproto.EventMaskSubstructureRedirect,
+ // TODO: Should we also register for EventMaskSubstructureNotify ?
+ // Where is the authoritative list of events located?
}).Check()
}
+// 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)
}
- // TODO: Verify this.
- // It appears that only windows with a `MapState` value of 2 should be 'viewable'.
- // - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L3772
- // - https://github.com/BurntSushi/xgb/blob/master/xproto/xproto.go#L10287
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:
default:
return nil
}
- return nil // What do I actually want to return here?
+ return nil // TODO: What do I actually want to return here?
}