New milestone: can launch and display an xterm master origin/HEAD origin/master
authorAaron Taylor <ataylor@subgeniuskitty.com>
Sat, 4 Mar 2023 09:41:03 +0000 (01:41 -0800)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Sat, 4 Mar 2023 09:41:03 +0000 (01:41 -0800)
----
Illi is now able to connect to the X server, get a list of clients, register for (and handle) basic events.

illi.go

diff --git a/illi.go b/illi.go
index ad324c1..e527d65 100644 (file)
--- a/illi.go
+++ b/illi.go
@@ -7,6 +7,7 @@ import (
     "os/exec"
 
     "github.com/jezek/xgb"
     "os/exec"
 
     "github.com/jezek/xgb"
+    "github.com/jezek/xgb/xinerama"
     "github.com/jezek/xgb/xproto"
 )
 
     "github.com/jezek/xgb/xproto"
 )
 
@@ -16,57 +17,57 @@ const (
     XK_Return = 0xff0d
 )
 
     XK_Return = 0xff0d
 )
 
+type display struct {
+    screen    xinerama.ScreenInfo
+    windows   []xproto.Window
+}
+
 func main() {
 func main() {
-    fmt.Println("ILLI: Execution begins")
+    // Set ourselves up as the new window manager ------------------------------
 
     xconn := connectToXServer()
 
     xconn := connectToXServer()
-    attachedScreens := getAttachedScreens(xconn)
     xroot := getXRoot(xconn)
     keymap := getKeyboardMap(xconn)
     registerForKeyEvents(xconn, xroot, keymap)
 
     becomeWM(xconn, xroot)
 
     xroot := getXRoot(xconn)
     keymap := getKeyboardMap(xconn)
     registerForKeyEvents(xconn, xroot, keymap)
 
     becomeWM(xconn, xroot)
 
-    // Build a list of windows needing management ------------------------------
+    // Build a list of output devices ------------------------------------------
 
 
-    if len(attachedScreens) > 0 {
-        fmt.Println("The Go compiler is waaaaay too picky about unused variables...")
+    var attachedDisplays []display
+    for _, screen := range getAttachedScreens(xconn) {
+        attachedDisplays = append(attachedDisplays, display{screen: screen})
     }
     }
+    // TODO: Verify some displays actually exist and we don't have an empty array. Otherwise, die here.
+    // TODO: Should this all go in its own function and simply return attachedDisplays[] here instead? What will my fundamental data structure be?
 
 
+    // Build a list of windows needing management ------------------------------
+
+    // TODO: The following should all be an initialization function. It should not be here.
     tree, err := xproto.QueryTree(xconn, xroot.Root).Reply()
     if err != nil {
     tree, err := xproto.QueryTree(xconn, xroot.Root).Reply()
     if err != nil {
+        // TODO: Better error
         log.Fatal(err)
     }
     if tree != nil {
         log.Fatal(err)
     }
     if tree != nil {
-        //workspaces = make(map[string]*Workspace)
-        //defaultw := &Workspace{mu: &sync.Mutex{}}
         for _, c := range tree.Children {
             if isMappedWindow(xconn, c) {
         for _, c := range tree.Children {
             if isMappedWindow(xconn, c) {
-//                err := defaultw.Add(c)
-//                if err != nil {
-//                    log.Println(err)
-//                }
-                fmt.Println("ILLI: Found a client.")
+                // For now, dump any pre-existing windows into the first
+                // display. Later we can add functionality for tracking window
+                // attributes across window manager restarts.
+                attachedDisplays[0].windows = append(attachedDisplays[0].windows, c)
             }
 
         }
             }
 
         }
-
-//        if len(attachedScreens) > 0 {
-//            defaultw.Screen = &attachedScreens[0]
-//        }
-//
-//        workspaces["default"] = defaultw
-//
-//        if err := defaultw.TileWindows(); err != nil {
-//            log.Println(err)
-//        }
-
+        // TODO: Try tiling/displaying/whatever with any existing windows before entering the event loop.
     }
 
     // Main program loop reacts to X events ------------------------------------
 
 eventloop:
     for {
     }
 
     // Main program loop reacts to X events ------------------------------------
 
 eventloop:
     for {
+        fmt.Printf("ILLI: attachedDisplays: ")
+        fmt.Println(attachedDisplays)
         xevent, err := xconn.WaitForEvent()
         if err != nil {
             log.Println(err)
         xevent, err := xconn.WaitForEvent()
         if err != nil {
             log.Println(err)
@@ -74,11 +75,55 @@ eventloop:
         }
         switch e := xevent.(type) {
             case xproto.KeyPressEvent:
         }
         switch e := xevent.(type) {
             case xproto.KeyPressEvent:
+                fmt.Printf("ILLI: Received xproto.KeyPressEvent\n")
                 if err := handleKeyPressEvent(keymap, e); err != nil {
                     break eventloop
                 }
                 if err := handleKeyPressEvent(keymap, e); err != nil {
                     break eventloop
                 }
+            case xproto.KeyReleaseEvent:
+                fmt.Printf("ILLI: Received xproto.KeyReleaseEvent\n")
+            case xproto.DestroyNotifyEvent:
+                fmt.Printf("ILLI: Received xproto.DestroyNotifyEvent\n")
+            case xproto.ConfigureRequestEvent:
+                fmt.Printf("ILLI: Received xproto.ConfigureRequestEvent\n")
+                rewrittenEvent := xproto.ConfigureNotifyEvent{
+                    Event:            e.Window,
+                    Window:           e.Window,
+                    AboveSibling:     0,
+                    X:                e.X,
+                    Y:                e.Y,
+                    Width:            e.Width,
+                    Height:           e.Height,
+                    BorderWidth:      0,
+                    OverrideRedirect: false,
+                }
+                xproto.SendEventChecked(xconn, false, e.Window, xproto.EventMaskStructureNotify, string(rewrittenEvent.Bytes()))
+            case xproto.MapRequestEvent:
+                fmt.Printf("ILLI: Received xproto.MapRequestEvent\n")
+                if windowAttributes, err := xproto.GetWindowAttributes(xconn, e.Window).Reply(); err != nil || !windowAttributes.OverrideRedirect {
+                    xproto.MapWindowChecked(xconn, e.Window)
+                    attachedDisplays[0].windows = append(attachedDisplays[0].windows, e.Window)
+
+                    if err := xproto.ConfigureWindowChecked (
+                        xconn,
+                        attachedDisplays[0].windows[0],
+                        xproto.ConfigWindowX |
+                            xproto.ConfigWindowY |
+                            xproto.ConfigWindowWidth |
+                            xproto.ConfigWindowHeight,
+                        []uint32{
+                            uint32(100), // TODO: Temporarily hardcoding for testing.
+                            uint32(100), // TODO: Temporarily hardcoding for testing.
+                            uint32(1720), // TODO: Temporarily hardcoding for testing.
+                            uint32(1000), // TODO: Temporarily hardcoding for testing.
+                        }).Check(); err != nil {
+                        fmt.Println("ILLI: Failed to handle MapRequestEvent")
+                    }
+
+                }
+            case xproto.EnterNotifyEvent:
+                fmt.Printf("ILLI: Received xproto.EnterNotifyEvent\n")
             default:
             default:
-                log.Println(xevent)
+                fmt.Printf("ILLI: Unknown X event received: %s\n", xevent)
         }
     }
 }
         }
     }
 }