diff options
Diffstat (limited to 'xorg-server/include/scrnintstr.h')
-rw-r--r-- | xorg-server/include/scrnintstr.h | 116 |
1 files changed, 103 insertions, 13 deletions
diff --git a/xorg-server/include/scrnintstr.h b/xorg-server/include/scrnintstr.h index 6acdadd7a..6955e77fd 100644 --- a/xorg-server/include/scrnintstr.h +++ b/xorg-server/include/scrnintstr.h @@ -259,23 +259,23 @@ typedef void (*SendGraphicsExposeProcPtr) (ClientPtr /*client */ , int /*major */ , int /*minor */ ); -typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr /*pScreen*/ , - void */*pTimeout */ , - void */*pReadmask */ ); +typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr pScreen, + void *pTimeout, + void *pReadmask); -typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr /*pScreen*/ , - unsigned long /*result */ , - void */*pReadMask */ ); +typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr pScreen, + unsigned long result, + void *pReadMask); typedef Bool (*CreateScreenResourcesProcPtr) (ScreenPtr /*pScreen */ ); -typedef Bool (*ModifyPixmapHeaderProcPtr) (PixmapPtr /*pPixmap */ , - int /*width */ , - int /*height */ , - int /*depth */ , - int /*bitsPerPixel */ , - int /*devKind */ , - void */*pPixData */ ); +typedef Bool (*ModifyPixmapHeaderProcPtr) (PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, + int devKind, + void *pPixData); typedef PixmapPtr (*GetWindowPixmapProcPtr) (WindowPtr /*pWin */ ); @@ -358,6 +358,96 @@ typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen, typedef int (*NameWindowPixmapProcPtr)(WindowPtr, PixmapPtr, CARD32); +/* Wrapping Screen procedures + + There are a few modules in the X server which dynamically add and + remove themselves from various screen procedure call chains. + + For example, the BlockHandler is dynamically modified by: + + * xf86Rotate + * miSprite + * composite + * render (for animated cursors) + + Correctly manipulating this chain is complicated by the fact that + the chain is constructed through a sequence of screen private + structures, each holding the next screen->proc pointer. + + To add a module to a screen->proc chain is fairly simple; just save + the current screen->proc value in the module screen private + and store the module's function in the screen->proc location. + + Removing a screen proc is a bit trickier. It seems like all you + need to do is set the screen->proc pointer back to the value saved + in your screen private. However, if some other module has come + along and wrapped on top of you, then the right place to store the + previous screen->proc value is actually in the wrapping module's + screen private structure(!). Of course, you have no idea what + other module may have wrapped on top, nor could you poke inside + its screen private in any case. + + To make this work, we restrict the unwrapping process to happen + during the invocation of the screen proc itself, and then we + require the screen proc to take some care when manipulating the + screen proc functions pointers. + + The requirements are: + + 1) The screen proc must set the screen->proc pointer back to the + value saved in its screen private before calling outside its + module. + + 2a) If the screen proc wants to be remove itself from the chain, + it must not manipulate screen->proc pointer again before + returning. + + 2b) If the screen proc wants to remain in the chain, it must: + + 2b.1) Re-fetch the screen->proc pointer and store that in + its screen private. This ensures that any changes + to the chain will be preserved. + + 2b.2) Set screen->proc back to itself + + One key requirement here is that these steps must wrap not just + any invocation of the nested screen->proc value, but must nest + essentially any calls outside the current module. This ensures + that other modules can reliably manipulate screen->proc wrapping + using these same rules. + + For example, the animated cursor code in render has two macros, + Wrap and Unwrap. + + #define Unwrap(as,s,elt) ((s)->elt = (as)->elt) + + Unwrap takes the screen private (as), the screen (s) and the + member name (elt), and restores screen->proc to that saved in the + screen private. + + #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) + + Wrap takes the screen private (as), the screen (s), the member + name (elt) and the wrapping function (func). It saves the + current screen->proc value in the screen private, and then sets the + screen->proc to the local wrapping function. + + Within each of these functions, there's a pretty simple pattern: + + Unwrap(as, pScreen, UnrealizeCursor); + + // Do local stuff, including possibly calling down through + // pScreen->UnrealizeCursor + + Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); + + The wrapping block handler is a bit different; it does the Unwrap, + the local operations and then only re-Wraps if the hook is still + required. Unwrap occurrs at the top of each function, just after + entry, and Wrap occurrs at the bottom of each function, just + before returning. + */ + typedef struct _Screen { int myNum; /* index of this instance in Screens[] */ ATOM id; |