From 12099ed6e163f27199fbafe6e68870fdb107a404 Mon Sep 17 00:00:00 2001 From: Aaron Taylor Date: Tue, 7 Feb 2023 17:39:05 -0800 Subject: [PATCH] Adding some comments after re-reading last night's code commit. --- illi.go | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/illi.go b/illi.go index 5cb1641..19c99b2 100644 --- a/illi.go +++ b/illi.go @@ -17,12 +17,18 @@ const ( 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) @@ -30,6 +36,8 @@ func main() { 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.") @@ -54,6 +62,8 @@ func main() { } } + // Establish a root for the tree ------------------------------------------- + connInfo := xproto.Setup(xc) if connInfo == nil { log.Fatal("ILLI: Unable to parse X connection information") @@ -63,7 +73,8 @@ func main() { } 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?") @@ -73,7 +84,7 @@ func main() { fmt.Println("ILLI: Successfully registered as WM with X server.") -// ----------------------------------------------------------------------------- + // Setup keysym mappings and register for WM-relevant key events ----------- const ( loKey = 8 @@ -133,7 +144,7 @@ func main() { } } -// ----------------------------------------------------------------------------- + // Build a list of windows needing management ------------------------------ tree, err := xproto.QueryTree(xc, xroot.Root).Reply() if err != nil { @@ -165,6 +176,8 @@ func main() { } + // Main program loop reacts to X events ------------------------------------ + eventloop: for { xevent, err := xc.WaitForEvent() @@ -183,6 +196,12 @@ eventloop: } } +// 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, @@ -195,24 +214,31 @@ func TakeWMOwnership() error { 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: @@ -238,5 +264,5 @@ func handleKeyPressEvent(key xproto.KeyPressEvent) error { default: return nil } - return nil // What do I actually want to return here? + return nil // TODO: What do I actually want to return here? } -- 2.20.1