"os/exec"
"github.com/jezek/xgb"
+ "github.com/jezek/xgb/xinerama"
"github.com/jezek/xgb/xproto"
)
XK_Return = 0xff0d
)
+type display struct {
+ screen xinerama.ScreenInfo
+ windows []xproto.Window
+}
+
func main() {
- fmt.Println("ILLI: Execution begins")
+ // Set ourselves up as the new window manager ------------------------------
xconn := connectToXServer()
- attachedScreens := getAttachedScreens(xconn)
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 {
+ // 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(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 {
+ fmt.Printf("ILLI: attachedDisplays: ")
+ fmt.Println(attachedDisplays)
xevent, err := xconn.WaitForEvent()
if err != nil {
log.Println(err)
}
switch e := xevent.(type) {
case xproto.KeyPressEvent:
+ 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)
}
}
}