桌面窗口事件交互流程

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);