`
jinghuainfo
  • 浏览: 1525591 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

X Window研究笔记(11)

 
阅读更多
X Window研究笔记(11)

转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>

11.X Window扩展机制--对象装饰

Decorator模式是一个非常重要的模式,它在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。X Server是用C开发的,不方便使用正统的装饰模式,但大量使用了类似装饰模式的扩展方式。可以被装饰的对象有:

  1. 屏幕: ScreenRec
  2. 窗口:WindowRec
  3. 图片: PixmapRec
  4. 绘图上下文: GC
  5. 颜色映射: Colormap
  6. 客户端:ClientRec

其实现过程可以这样理解:
  1. 初始化时,把原始对象的部分函数指针保存下来,并用自己的函数去替代它。
  2. 调用时,装饰之后的函数被调用,在该函数中,完成一些装饰性功能,并适当的位置调用原始的函数。

其中,用得最多的是对ScreenRec的装饰,下面我们以sprite模块中对ScreenRec的装饰为例,分析一下它的实现原理:

sprite指像鼠标指针一类的屏幕精灵,它的特点是,形状可能不规则,可以在屏幕上移动,会覆盖当前位置的图像,当它移动到新的位置时,自动恢复先前位置的图像。

sprite的初始化是在miSpriteInitialize中完成的:

Bool
miSpriteInitialize(pScreen,cursorFuncs,screenFuncs)
ScreenPtrpScreen;
miSpriteCursorFuncPtrcursorFuncs;
miPointerScreenFuncPtrscreenFuncs;
...{
miSpriteScreenPtrpPriv;
VisualPtrpVisual;
#ifdefRENDER
PictureScreenPtrps
=GetPictureScreenIfSet(pScreen);
#endif

if(miSpriteGeneration!=serverGeneration)
...{
miSpriteScreenIndex
=AllocateScreenPrivateIndex();
if(miSpriteScreenIndex<0)
returnFALSE;
miSpriteGeneration
=serverGeneration;
miSpriteGCIndex
=AllocateGCPrivateIndex();
}

if(!AllocateGCPrivate(pScreen,miSpriteGCIndex,sizeof(miSpriteGCRec)))
returnFALSE;
pPriv
=(miSpriteScreenPtr)xalloc(sizeof(miSpriteScreenRec));
if(!pPriv)
returnFALSE;
if(!miPointerInitialize(pScreen,&miSpritePointerFuncs,screenFuncs,TRUE))
...{
xfree((pointer)pPriv);
returnFALSE;
}

for(pVisual=pScreen->visuals;
pVisual
->vid!=pScreen->rootVisual;
pVisual
++)
;
pPriv
->pVisual=pVisual;
pPriv
->CloseScreen=pScreen->CloseScreen;
pPriv
->GetImage=pScreen->GetImage;
pPriv
->GetSpans=pScreen->GetSpans;
pPriv
->SourceValidate=pScreen->SourceValidate;
pPriv
->CreateGC=pScreen->CreateGC;
pPriv
->BlockHandler=pScreen->BlockHandler;
pPriv
->InstallColormap=pScreen->InstallColormap;
pPriv
->StoreColors=pScreen->StoreColors;

pPriv
->PaintWindowBackground=pScreen->PaintWindowBackground;
pPriv
->PaintWindowBorder=pScreen->PaintWindowBorder;
pPriv
->CopyWindow=pScreen->CopyWindow;
pPriv
->ClearToBackground=pScreen->ClearToBackground;

pPriv
->SaveDoomedAreas=pScreen->SaveDoomedAreas;
pPriv
->RestoreAreas=pScreen->RestoreAreas;
#ifdefRENDER
if(ps)
...{
pPriv
->Composite=ps->Composite;
pPriv
->Glyphs=ps->Glyphs;
}

#endif

pPriv
->pCursor=NULL;
pPriv
->x=0;
pPriv
->y=0;
pPriv
->isUp=FALSE;
pPriv
->shouldBeUp=FALSE;
pPriv
->pCacheWin=NullWindow;
pPriv
->isInCacheWin=FALSE;
pPriv
->checkPixels=TRUE;
pPriv
->pInstalledMap=NULL;
pPriv
->pColormap=NULL;
pPriv
->funcs=cursorFuncs;
pPriv
->colors[SOURCE_COLOR].red=0;
pPriv
->colors[SOURCE_COLOR].green=0;
pPriv
->colors[SOURCE_COLOR].blue=0;
pPriv
->colors[MASK_COLOR].red=0;
pPriv
->colors[MASK_COLOR].green=0;
pPriv
->colors[MASK_COLOR].blue=0;
pScreen
->devPrivates[miSpriteScreenIndex].ptr=(pointer)pPriv;
pScreen
->CloseScreen=miSpriteCloseScreen;
pScreen
->GetImage=miSpriteGetImage;
pScreen
->GetSpans=miSpriteGetSpans;
pScreen
->SourceValidate=miSpriteSourceValidate;
pScreen
->CreateGC=miSpriteCreateGC;
pScreen
->BlockHandler=miSpriteBlockHandler;
pScreen
->InstallColormap=miSpriteInstallColormap;
pScreen
->StoreColors=miSpriteStoreColors;

pScreen
->PaintWindowBackground=miSpritePaintWindowBackground;
pScreen
->PaintWindowBorder=miSpritePaintWindowBorder;
pScreen
->CopyWindow=miSpriteCopyWindow;
pScreen
->ClearToBackground=miSpriteClearToBackground;

pScreen
->SaveDoomedAreas=miSpriteSaveDoomedAreas;
pScreen
->RestoreAreas=miSpriteRestoreAreas;
#ifdefRENDER
if(ps)
...{
ps
->Composite=miSpriteComposite;
ps
->Glyphs=miSpriteGlyphs;
}

#endif

returnTRUE;
}


这个函数有点长,但我们只需要理解关键几点:
  1. AllocateScreenPrivateIndex分配私有数据空间,用于保存原始函数指针等信息。
  2. pPriv->PaintWindowBackground = pScreen->PaintWindowBackground; 之类的语句用于保存原始的函数指针。
  3. pScreen->PaintWindowBackground = miSpritePaintWindowBackground; 之类的语句用于把原始的函数指针替换为装饰之后的函数。

这里要特别说明的是,所谓的原始函数指针,并非一定是原装正品,可能已经是被别的模块装饰之后的函数。

下面我们继续看函数调用的实现:

staticvoid
miSpritePaintWindowBackground(pWin,pRegion,what)
WindowPtrpWin;
RegionPtrpRegion;
intwhat;
...{
ScreenPtrpScreen;
miSpriteScreenPtrpScreenPriv;

pScreen
=pWin->drawable.pScreen;

SCREEN_PROLOGUE(pScreen,PaintWindowBackground);

pScreenPriv
=(miSpriteScreenPtr)pScreen->devPrivates[miSpriteScreenIndex].ptr;
if(pScreenPriv->isUp)
...{
/**//*
*Ifthecursorisonthesamescreenasthewindow,checkthe
*regiontopaintforthecursorandremoveitasnecessary
*/

if(RECT_IN_REGION(pScreen,pRegion,&pScreenPriv->saved)!=rgnOUT)
miSpriteRemoveCursor(pScreen);
}


(
*pScreen->PaintWindowBackground)(pWin,pRegion,what);

SCREEN_EPILOGUE(pScreen,PaintWindowBackground,miSpritePaintWindowBackground);
}


为了看明白这段程序,先得弄清楚两个宏:
SCREEN_PROLOGUE: 用于取出原始的函数指针,后面可以调用原始函数。
#define SCREEN_PROLOGUE(pScreen, field)/
((pScreen)->field = /
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)

SCREEN_EPILOGUE:重新把装饰过的放回去,以便于下次再调。
#define SCREEN_EPILOGUE(pScreen, field, wrapper)/
((pScreen)->field = wrapper)

弄清楚了这两个宏,上面的程序不难理解了。这种扩展方式的好处在于,运行时动态为对象添加功能,同时又避免了扩展功能与框架的耦合,这是通过子类继承父类,然后重载部分虚函数无法实现的。

(待续)

分享到:
评论

相关推荐

    X Window研究笔记

    X Window研究笔记 虽然X Window是一个非常复杂的系统,但只要静下心来分析,通常遇到的问题也是很容易解决的,前年我花了一段时间去研究X Window的实现,我发现了解它的实现后,很多问题都迎刃而解了

    X-window简略笔记

    X-window简略笔记

    X-Window程式设计入门 教程

    X Window 程式设计入门--第一章 什么是 X Window X Window 程式设计入门--第二章 X Programming 的第一步 X Window 程式设计入门--第三章 绘图(Graphic) X Window 程式设计入门--第三章 绘图(Graphic) X Window 程...

    Xwindow程序设计入门

    Xwindow程序设计入门,网上收藏,很好的资料,对了解xwindow编程很有帮助

    X Window 系统使用指南

    X Window System 是一套在各种位元映像显示器 (bitmapped dispalys) 上具有极大可携性 (portable) 的视窗系统 (window system), 它是由麻省理工学院 (MIT)所发展出来. X Windows System ( 本书以後部 份简称为...

    OpenGL for x window (1)

    This practical guide shows X programmers how to construct working 3D applications using OpenGL and how to tightly integrate OpenGL applications with the X Window System. Written by a Silicon Graphics...

    X window 直接渲染架构

    描述X window 直接渲染架构的概念,实现

    X window介绍及启动流程

    对Linux操作系统的桌面环境软件X window的介绍及启动流程

    xwindow程序设计相关资料

    X Window System 是一套在各种位元映像显示器 (bitmapped dispalys) 上具有极大可携性 (portable) 的视窗系统 (window system), 它是由麻省理工学院 (MIT)所发展出来. X Windows System ( 本书以後部 份简称为...

    Linux与X Window系统基础

    Linux与X Window系统基础 Linux与X Window系统基础

    Linux下X-Window系统程序设计简介.pdf

    Linux下X-Window系统程序设计简介.pdf

    X Window 用户指南

    这个文档为Linux用户提供了一些基本的关于理解和配置X-Window系统的信息。 这只是一个入门级别的文档。假设已经有了一个安装好的并且正在工作的 X-Window系统。

    window manager for x

    window manager for x window manager for x window manager for x

    X-Window介绍

    关于X window的介绍。让你了解并熟悉X window。

    xwindow相关包

    Xwindow 是一个非常出色的图形系统,你应该抱怨的是那些不稳定的包装,而不是 Xwindow 本身。

    Xming-X window 工具

    Xming, windows操作系统连接Linux, Unix的x window 工具。

    Window批处理命令学习笔记

    Window批处理命令学习笔记,批处理实用简小工具

    X Window架构与启动代码分析

    一份课程报告,介绍了X-Window的架构体系,并对启动代码做了分析

Global site tag (gtag.js) - Google Analytics