X-Git-Url: https://git.subgeniuskitty.com/illi/.git/blobdiff_plain/19cbf0a1d58d81bdabfdd3a7c83e9f356ea836a5..HEAD:/illi.go diff --git a/illi.go b/illi.go index e535cc5..e527d65 100644 --- a/illi.go +++ b/illi.go @@ -7,6 +7,7 @@ import ( "os/exec" "github.com/jezek/xgb" + "github.com/jezek/xgb/xinerama" "github.com/jezek/xgb/xproto" ) @@ -16,74 +17,113 @@ 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 keymap [256][]xproto.Keysym +type display struct { + screen xinerama.ScreenInfo + windows []xproto.Window +} func main() { + // Set ourselves up as the new window manager ------------------------------ + xconn := connectToXServer() - attachedScreens := getAttachedScreens(xconn) xroot := getXRoot(xconn) - keymap = getKeyboardMap(xconn) + keymap := getKeyboardMap(xconn) registerForKeyEvents(xconn, xroot, keymap) becomeWM(xconn, xroot) - // Build a list of windows needing management ------------------------------ + // Build a list of output devices ------------------------------------------ - xc = xconn - 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? - tree, err := xproto.QueryTree(xc, xroot.Root).Reply() + // 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 { + // TODO: Better error 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 isMappedWindow(xconn, c) { + // 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 { - xevent, err := xc.WaitForEvent() + fmt.Printf("ILLI: attachedDisplays: ") + fmt.Println(attachedDisplays) + xevent, err := xconn.WaitForEvent() if err != nil { log.Println(err) continue } switch e := xevent.(type) { case xproto.KeyPressEvent: - if err := handleKeyPressEvent(e); err != nil { + fmt.Printf("ILLI: Received xproto.KeyPressEvent\n") + 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: - log.Println(xevent) + fmt.Printf("ILLI: Unknown X event received: %s\n", xevent) } } } @@ -93,8 +133,8 @@ eventloop: // `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() +func isMappedWindow(conn *xgb.Conn, windowID xproto.Window) bool { + reply, err := xproto.GetWindowAttributes(conn, windowID).Reply() if err != nil { log.Fatal(err) } @@ -108,7 +148,7 @@ func isMappedWindow(windowID xproto.Window) bool { // 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 { +func handleKeyPressEvent(keymap [256][]xproto.Keysym, key xproto.KeyPressEvent) error { switch keymap[key.Detail][0] { case XK_q: switch key.State { @@ -118,7 +158,7 @@ func handleKeyPressEvent(key xproto.KeyPressEvent) error { // We must manually close the X connection since we used // `defer` when setting it up and os.Exit() short-circuits // that deferral. - xc.Close() + //xc.Close() os.Exit(0) } case XK_Return: