X Window的核心服务是放在一个函数表中的,当客户端程序有请求到来时,X Window通过请求号从函数表中找到对应的服务函数,然后调用它,服务函数执行完成后返回结果。
9.X Window扩展机制--核心服务的扩展
X Window的核心服务是放在一个函数表中的,当客户端程序有请求到来时,X Window通过请求号从函数表中找到对应的服务函数,然后调用它,服务函数执行完成后返回结果。函数表其实也是一种抽象,它让框架不必知道实现的功能,扩展功能时,只要修改这个函数表,而不用修改框架。
这个函数表在programs/Xserver/dix/table.c中,其声明如下:
int (* ProcVector[256]) (
ClientPtr /**//* client */
) =
...{
ProcBadRequest,
ProcCreateWindow,
ProcChangeWindowAttributes,
ProcGetWindowAttributes,
ProcDestroyWindow,
ProcDestroySubwindows, /**//* 5 */
ProcChangeSaveSet,
ProcReparentWindow,
ProcMapWindow,
ProcMapSubwindows,
ProcUnmapWindow, /**//* 10 */
ProcUnmapSubwindows,
ProcConfigureWindow,
ProcCirculateWindow,
ProcGetGeometry,
ProcQueryTree, /**//* 15 */
ProcInternAtom,
ProcGetAtomName,
ProcChangeProperty,
ProcDeleteProperty,
ProcGetProperty, /**//* 20 */
ProcListProperties,
ProcSetSelectionOwner,
ProcGetSelectionOwner,
ProcConvertSelection,
ProcSendEvent, /**//* 25 */
ProcGrabPointer,
ProcUngrabPointer,
ProcGrabButton,
ProcUngrabButton,
ProcChangeActivePointerGrab, /**//* 30 */
ProcGrabKeyboard,
ProcUngrabKeyboard,
ProcGrabKey,
ProcUngrabKey,
ProcAllowEvents, /**//* 35 */
ProcGrabServer,
ProcUngrabServer,
ProcQueryPointer,
ProcGetMotionEvents,
ProcTranslateCoords, /**//* 40 */
ProcWarpPointer,
ProcSetInputFocus,
ProcGetInputFocus,
ProcQueryKeymap,
ProcOpenFont, /**//* 45 */
ProcCloseFont,
ProcQueryFont,
ProcQueryTextExtents,
ProcListFonts,
ProcListFontsWithInfo, /**//* 50 */
ProcSetFontPath,
ProcGetFontPath,
ProcCreatePixmap,
ProcFreePixmap,
ProcCreateGC, /**//* 55 */
ProcChangeGC,
ProcCopyGC,
ProcSetDashes,
ProcSetClipRectangles,
ProcFreeGC, /**//* 60 */
ProcClearToBackground,
ProcCopyArea,
ProcCopyPlane,
ProcPolyPoint,
ProcPolyLine, /**//* 65 */
ProcPolySegment,
ProcPolyRectangle,
ProcPolyArc,
ProcFillPoly,
ProcPolyFillRectangle, /**//* 70 */
ProcPolyFillArc,
ProcPutImage,
ProcGetImage,
ProcPolyText,
ProcPolyText, /**//* 75 */
ProcImageText8,
ProcImageText16,
ProcCreateColormap,
ProcFreeColormap,
ProcCopyColormapAndFree, /**//* 80 */
ProcInstallColormap,
ProcUninstallColormap,
ProcListInstalledColormaps,
ProcAllocColor,
ProcAllocNamedColor, /**//* 85 */
ProcAllocColorCells,
ProcAllocColorPlanes,
ProcFreeColors,
ProcStoreColors,
ProcStoreNamedColor, /**//* 90 */
ProcQueryColors,
ProcLookupColor,
ProcCreateCursor,
ProcCreateGlyphCursor,
ProcFreeCursor, /**//* 95 */
ProcRecolorCursor,
ProcQueryBestSize,
ProcQueryExtension,
ProcListExtensions,
ProcChangeKeyboardMapping, /**//* 100 */
ProcGetKeyboardMapping,
ProcChangeKeyboardControl,
ProcGetKeyboardControl,
ProcBell,
ProcChangePointerControl, /**//* 105 */
ProcGetPointerControl,
ProcSetScreenSaver,
ProcGetScreenSaver,
ProcChangeHosts,
ProcListHosts, /**//* 110 */
ProcChangeAccessControl,
ProcChangeCloseDownMode,
ProcKillClient,
ProcRotateProperties,
ProcForceScreenSaver, /**//* 115 */
ProcSetPointerMapping,
ProcGetPointerMapping,
ProcSetModifierMapping,
ProcGetModifierMapping,
0, /**//* 120 */
0,
0,
0,
0,
0, /**//* 125 */
0,
ProcNoOperation
}; 还有一个函数表,叫作SwappedProcVector,它与ProcVector中的函数功能上基本是对应的,特殊之处在于,在调用真正的服务前,先预处理一下请求的数据,客户端程序可能运行在不同字节顺序的机器上,这时候要交换一下数据的字节顺序。我们可以看SProcCreateWindow的实现:
Int SProcCreateWindow(ClientPtr client)
...{
char n;
REQUEST(xCreateWindowReq);
swaps(&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
swapl(&stuff->wid, n);
swapl(&stuff->parent, n);
swaps(&stuff->x, n);
swaps(&stuff->y, n);
swaps(&stuff->width, n);
swaps(&stuff->height, n);
swaps(&stuff->borderWidth, n);
swaps(&stuff->class, n);
swapl(&stuff->visual, n);
swapl(&stuff->mask, n);
SwapRestL(stuff);
return((* ProcVector[X_CreateWindow])(client));
}
有了这种机制,增加新的功能,只需要增一个处理函数就行了,处理函数并需要知道请求从何而来,何时被调用。相反,要裁剪某些功能,亦只需要从这里拿开这个函数就可以了。当然,实际很少直接修改这个函数表,增加新功能往往是扩展模块来实现,扩展模块最终也是修改这个函数表,这是后话,暂且不提。
查看本文来源