This is a work in progress. [make this document be scripted, and use proc Q and proc A for generation] Q 1. 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 2. 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 3. 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 4. Is CreateNotify useful for a WM? A. CreateNotify is almost useless for a WM, and should be avoided in most cases, because menu windows with override_redirect 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 5. What is a ConfigureRequest event? A. It's an event that corresponds to a resize, stacking-order, or position change. XConfigureRequestEvent only has some members set at times, so some clever usage of XGetWindowAttributes or caching is needed. Q 6. What is a MapRequest event? A. The XMapRequestEvent is sent to the WM after the application has called XMapWindow. The WM calls XMapWindow if desired, and XMapWindow ends up sending a MapNotify to the application. Q 7. How do I do handle shaped windows? A. Shape the container of the window and possibly use an offset. The TWM sources handle this fairly well. Q 8. 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) { pwm_send_take_focus() } Where pwm_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; } TODO: 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 add another SubstructureRedirectMask for the frame/parent.