This is a work in progress. [make this document be scripted, and use proc Q and proc A for generation] Q. How does a WM receive events? A. XSelectInput on the root window with a SubstructureRedirectMask causes redirection of mapping, size, and placement requests for application windows to the window manager. Only 1 application can request the SubstructureRedirectMask for a window. It also need not be only the root window. In fact most reparenting WM select SubstructureRedirectMask on the frame/container of an application window too. Q. How can I detect if another WM is running? A. Use XSetErrorHandler before calling XSelectInput. For example: int pwm_select_input_error_handler ( Display *display, XErrorEvent *event ) { ++pwm_error_count; if (BadAccess == event->error_code) { fprintf (stderr, "BadAccess when selecting input. Do you have another WM already running?\n"); } return 0; } Q. What is override_redirect? A. It's a setting that some windows have to override the WM redirection. Some common widgets that do this are menus, and splash screens. Q. Is CreateNotify useful for a WM? A. CreateNotify is almost useless for a WM, and should be avoided in most cases, because menu windows go through its path. Generally it's a bad idea to give menus a container frame, or do much of anything with them, because the applications and toolkits don't expect this. Q. What is a ConfigureRequest event? XConfigureRequestEvent only has some members set at times, so some clever usage of XGetWindowAttributes or caching is needed. XMapRequest - WM calls XMapWindow if desired. The WM must send a MapNotify event to the application, to let it know. PropertyNotify event, and endless cycles (Emacs). Updating windows for hints dynamically based on PropertyNotify. Focus models Focus transfer with XSetInputFocus() and sending the WM_TAKE_FOCUS message. Reparenting window managers, and yet another SubstructureRedirectMask for the frame/parent. Perhaps experiment with a style like; Q. How do I do handle shaped windows? A. ShapeNotify (learn about why Whim works anyway without handling this). Q. How do I transfer focus? A. First you must have saved some state from the WM_HINTS. The ->input member of the XWMHints structure returned by XGetWMHints() indicates if the application takes focus. if ((InputHint & wm_hints->flags) && (wm_hints->input)) { Use XSetInputFocus with RevertToPointerRoot and CurrentTime. } We should also send a synthetic message to some applications. Using XGetWMProtocols() we can search for a WM_TAKE_FOCUS Atom. If it's found we can save the state if (wm_hints->WM_TAKE_FOCUS) { send_take_focus() } Where send_take_focus might be something like this (taken from my own WM): int pwm_send_take_focus ( TCL_OBJ_CMD_ARGS ) { Window w; XClientMessageEvent cev; if (2 != objc) { Tcl_WrongNumArgs (interp, 1, objv, "Window"); return TCL_ERROR; } if (TCL_OK != hex_obj_to_window (interp, objv[1], &w)) return TCL_ERROR; cev.type = ClientMessage; cev.window = w; cev.message_type = PWM_WM_PROTOCOLS; cev.format = 32; cev.data.l[0] = PWM_WM_TAKE_FOCUS; cev.data.l[1] = CurrentTime; XSendEvent (pwm_display, w, 0, 0L, (XEvent *) &cev); XSync (pwm_display, 0); return TCL_OK; }