- 论坛徽章:
- 0
|
X Window研究笔记(10)
转载时请注明出处和作者联系方式
作者联系方式:李先静
10.X Window扩展机制--扩展(Extension)
XWindow
中有大量扩展模块,每个扩展模块完成一组相关的功能,把扩展功能从核心功能中剥离出来,可以大大提高X
Server的可配置性和扩展性。扩展模块的实现机制很简单:每一个扩展模块都有一个初始化函数,这个函数在X
Window起动时被调用,在这里面会初始化一些该模块的数据结构,然后会调用AddExtension把相关回调函数注册进去。
AddExtension的函数原型如下:
![]()
![]()
ExtensionEntry *
![]()
AddExtension(char *name, int NumEvents, int NumErrors,
![]()
int (*MainProc)(ClientPtr c1),
![]()
int (*SwappedMainProc)(ClientPtr c2),
![]()
void (*CloseDownProc)(ExtensionEntry *e),
![]()
unsigned short (*MinorOpcodeProc)(ClientPtr c3))
Name: 插件的名称。NumEvents: 为扩展保留的事件数。NumErrors:为扩展保留的错误码数。MainProc: 扩展的处理函数。SwappedMainProc: 扩展的处理函数,在处理前先交换字节顺序。CloseDownProc: 扩展的析构函数。MinorOpcodeProc: 用来得到子处理号,一般没有什么用处,在出错时,设置到错误信息里。
从AddExtension的实现中,我们很容易看出,扩展其实也是通过前一章所说的ProcVector来实现的。
![]()
i = NumExtensions;
![]()
newexts = (ExtensionEntry **) xrealloc(extensions,
![]()
(i + 1) * sizeof(ExtensionEntry *));
![]()
if (!newexts)
![]()
![]()
...{
![]()
xfree(ext->name);
![]()
xfree(ext);
![]()
return((ExtensionEntry *) NULL);
![]()
}
![]()
NumExtensions++;
![]()
extensions = newexts;
![]()
extensions = ext;
![]()
ext->index = i;
![]()
ext->base = i + EXTENSION_BASE;
![]()
ext->CloseDown = CloseDownProc;
![]()
ext->MinorOpcode = MinorOpcodeProc;
![]()
ProcVector[i + EXTENSION_BASE] = MainProc;
![]()
SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc;
从理论上说,框架完全是独立于扩展的,增加增/删扩展不需要修改框架的代码。但实际情况往往不是这样的,有的扩展依赖框架提供一些特殊功能,有的扩展依赖另外一些扩展,所以在X Server的代码中,常常出现很多ifdef之类的宏,这些宏用来控制是否启用某些扩展。
下面我们来看一个实际的例子(render):
在mi/miinitext.c: InitExtensions函数中,RenderExtensionInit函数被调用,RenderExtensionInit的实现如下:
![]()
void
![]()
RenderExtensionInit (INITARGS)
![]()
![]()
...{
![]()
ExtensionEntry *extEntry;
![]()
![]()
if (!PictureType)
![]()
return;
![]()
if (!PictureFinishInit ())
![]()
return;
![]()
RenderClientPrivateIndex = AllocateClientPrivateIndex ();
![]()
if (!AllocateClientPrivate (RenderClientPrivateIndex,
![]()
sizeof (RenderClientRec)))
![]()
return;
![]()
if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0))
![]()
return;
![]()
![]()
extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors,
![]()
ProcRenderDispatch, SProcRenderDispatch,
![]()
RenderResetProc, StandardMinorOpcode);
![]()
if (!extEntry)
![]()
return;
![]()
#if 0
![]()
RenderReqCode = (CARD8) extEntry->base;
![]()
#endif
![]()
RenderErrBase = extEntry->errorBase;
![]()
}
ProcRenderDispatch是扩展的主分发函数,它调用子处理函数去完成实际的请求。其中stuff->data是子处理号,以子处理号从ProcRenderVector中找到对应的函数,并调用它。
![]()
static int
![]()
ProcRenderDispatch (ClientPtr client)
![]()
![]()
...{
![]()
REQUEST(xReq);
![]()
![]()
if (stuff->data RenderNumberRequests)
![]()
return (*ProcRenderVector[stuff->data]) (client);
![]()
else
![]()
return BadRequest;
![]()
}
(待续)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/43721/showart_388007.html |
|