const unsigned int BORDER_WIDTH = 3;
const unsigned long BORDER_COLOR = 0xff0000;
const unsigned long BG_COLOR = 0x0000ff;
// 获取窗口属性,主要是尺寸
XWindowAttributes w_attrs;
XGetWindowAttributes(display, w, &w_attrs)
// 发送CreateWindow请求,创建一个InputOutput窗口,以根窗口为父窗口
Window frame = XCreateSimpleWindow(display, root, w_attrs.x, w_attrs.y,
w_attrs.width, w_attrs.height, BORDER_WIDTH, BORDER_COLOR, BG_COLOR);
// 告知X11 server将frame直接子窗口的窗口请求和事件转发过来。
XSelectInput(display, frame, SubstructureRedirectMask | SubstructureNotifyMask);
// 发送ChangeSaveSet (SetModeInsert)请求,告知X11 server保存w叠层次序,WM崩溃后,可复原w原有叠层次序
XAddToSaveSet(display, w);
// 发送ReparentWindow请求,将w的父窗口由根窗口改为frame窗口
XReparentWindow(display, w, frame, 0, 0);
// 发送MapWindow请求,显示frame窗口
XMapWindow(display, frame);
// 在客户端窗口上抓取通用窗口管理操作:移动、缩放、关闭和切换窗口
// 分别发送GrabButton和GrabKey请求,捕获w窗口指定的鼠标和键盘事件,X11 server将事件转发给frame
// 发送GrabButton请求,ButtonMotionMask响应MotionNotify事件,ButtonPressMask/ButtonPressMask表示响应按键的两个状态(Press, Release)事件
// 发送GrabKey请求,捕获按键请求,响应KeyPress和KeyRelease事件
// 看来Mod1Mask修饰表示Alt,Button1表示left,Button2表示right。两个同时按下,在MotionNotify响应函数时处理
// alt + left按键移动窗口
XGrabButton(display, Button1, Mod1Mask, w, false,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync, GrabModeAsync, NULL, NULL);
// alt + right按键缩放窗口
XGrabButton(display, Button3, Mod1Mask, w, false,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync, GrabModeAsync, NULL, NULL);
// alt + f4关闭窗口
XGrabKey(display, XKeysymToKeycode(display, XK_F4),
Mod1Mask, w, false, GrabModeAsync, GrabModeAsync);
// alt + tab切换窗口
XGrabKey(display, XKeysymToKeycode(display_, XK_Tab),
Mod1Mask, w, false, GrabModeAsync, GrabModeAsync);