aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/include/scrnintstr.h
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/include/scrnintstr.h')
-rw-r--r--xorg-server/include/scrnintstr.h116
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;