Adding some comments after re-reading last night's code commit.
authorAaron Taylor <ataylor@subgeniuskitty.com>
Wed, 8 Feb 2023 01:39:05 +0000 (17:39 -0800)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Wed, 8 Feb 2023 01:39:05 +0000 (17:39 -0800)
illi.go

diff --git a/illi.go b/illi.go
index 5cb1641..19c99b2 100644 (file)
--- a/illi.go
+++ b/illi.go
@@ -17,12 +17,18 @@ const (
     XK_Return = 0xff0d
 )
 
     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() {
 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)
     xConn, err := xgb.NewConn()
     if err != nil {
         log.Fatal(err)
@@ -30,6 +36,8 @@ func main() {
     xc = xConn
     defer xc.Close()
 
     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.")
     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")
     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]
 
     }
     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?")
     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.")
 
 
     fmt.Println("ILLI: Successfully registered as WM with X server.")
 
-// -----------------------------------------------------------------------------
+    // Setup keysym mappings and register for WM-relevant key events -----------
 
     const (
         loKey = 8
 
     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 {
 
     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()
 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,
 func TakeWMOwnership() error {
     return xproto.ChangeWindowAttributesChecked(
         xc,
@@ -195,24 +214,31 @@ func TakeWMOwnership() error {
                 xproto.EventMaskButtonRelease |
                 xproto.EventMaskStructureNotify |
                 xproto.EventMaskSubstructureRedirect,
                 xproto.EventMaskButtonRelease |
                 xproto.EventMaskStructureNotify |
                 xproto.EventMaskSubstructureRedirect,
+                // TODO: Should we also register for EventMaskSubstructureNotify ?
+                //       Where is the authoritative list of events located?
         }).Check()
 }
 
         }).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)
     }
 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
 }
 
     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:
 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
     }
         default:
             return nil
     }
-    return nil // What do I actually want to return here?
+    return nil // TODO: What do I actually want to return here?
 }
 }