[Xquartz-changes] xserver: Branch 'server-1.11-apple' - 58 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Thu Mar 3 18:18:04 PST 2011


Rebased ref, commits from common ancestor:
commit 9a175eff729e0acea14af45be1f95c7ccca53f7b
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sat Oct 30 14:55:06 2010 -0700

    configure.ac: Add -fno-strict-aliasing to CFLAGS
    
    This should address https://bugs.freedesktop.org/show_bug.cgi?id=31238
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/configure.ac b/configure.ac
index 681f9d9..8edb10e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,12 @@ XORG_PROG_RAWCPP
 # easier overrides at build time.
 XSERVER_CFLAGS='$(CWARNFLAGS)'
 
+dnl Explicitly add -fno-strict-aliasing since this option should disappear
+dnl from util-macros CWARNFLAGS
+if  test "x$GCC" = xyes ; then
+    XSERVER_CFLAGS="$XSERVER_CFLAGS -fno-strict-aliasing"
+fi
+
 dnl Check for dtrace program (needed to build Xserver dtrace probes)
 dnl Also checks for <sys/sdt.h>, since some Linux distros have an 
 dnl ISDN trace program named dtrace
commit 10703e9406e0bbcc06ea146ee541801df5046f6b
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 12 19:48:52 2010 -0800

    fb: Revert fb changes that broke XQuartz
    
    http://bugs.freedesktop.org/show_bug.cgi?id=26124
    
    Revert "Fix source pictures getting random transforms after 2d6a8f668342a5190cdf43b5."
    Revert "fb: Adjust transform or composite coordinates for pixman operations"
    
    http://bugs.freedesktop.org/26124
    
    This reverts commit a72c65e9176c51de95db2fdbf4c5d946a4911695.
    This reverts commit a6bd5d2e482a5aa84acb3d4932e2a166d8670ef1.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/fb/fb.h b/fb/fb.h
index 021a940..0b248e1 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -2079,11 +2079,8 @@ fbFillRegionSolid (DrawablePtr	pDrawable,
 		   FbBits	xor);
 
 extern _X_EXPORT pixman_image_t *
-image_from_pict (PicturePtr	pict,
-		 Bool		has_clip,
-		 int		*xoff,
-		 int		*yoff);
-
+image_from_pict (PicturePtr pict,
+		 Bool       has_clip);
 extern _X_EXPORT void free_pixman_pict (PicturePtr, pixman_image_t *);
 
 #endif /* _FB_H_ */
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 312f3df..88de66a 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -50,24 +50,19 @@ fbComposite (CARD8      op,
 	     CARD16     height)
 {
     pixman_image_t *src, *mask, *dest;
-    int src_xoff, src_yoff;
-    int msk_xoff, msk_yoff;
-    int dst_xoff, dst_yoff;
     
     miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
     if (pMask)
 	miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
     
-    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
-    mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff);
-    dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+    src = image_from_pict (pSrc, TRUE);
+    mask = image_from_pict (pMask, TRUE);
+    dest = image_from_pict (pDst, TRUE);
 
     if (src && dest && !(pMask && !mask))
     {
 	pixman_image_composite (op, src, mask, dest,
-				xSrc + src_xoff, ySrc + src_yoff,
-				xMask + msk_xoff, yMask + msk_yoff,
-				xDst + dst_xoff, yDst + dst_yoff,
+				xSrc, ySrc, xMask, yMask, xDst, yDst,
 				width, height);
     }
 
@@ -146,22 +141,22 @@ create_conical_gradient_image (PictGradient *gradient)
 
 static pixman_image_t *
 create_bits_picture (PicturePtr pict,
-		     Bool       has_clip,
-		     int	*xoff,
-		     int	*yoff)
+		     Bool       has_clip)
 {
-    PixmapPtr pixmap;
     FbBits *bits;
     FbStride stride;
-    int bpp;
+    int bpp, xoff, yoff;
     pixman_image_t *image;
     
-    fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff);
-    fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
+
+    bits = (FbBits*)((CARD8*)bits +
+		     (pict->pDrawable->y + yoff) * stride * sizeof(FbBits) +
+		     (pict->pDrawable->x + xoff) * (bpp / 8));
 
     image = pixman_image_create_bits (
 	pict->format,
-	pixmap->drawable.width, pixmap->drawable.height,
+	pict->pDrawable->width, pict->pDrawable->height,
 	(uint32_t *)bits, stride * sizeof (FbStride));
     
     
@@ -187,55 +182,33 @@ create_bits_picture (PicturePtr pict,
 	if (pict->clientClipType != CT_NONE)
 	    pixman_image_set_has_client_clip (image, TRUE);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, *xoff, *yoff);
+	pixman_region_translate (pict->pCompositeClip, - pict->pDrawable->x, - pict->pDrawable->y);
 
 	pixman_image_set_clip_region (image, pict->pCompositeClip);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff);
+	pixman_region_translate (pict->pCompositeClip, pict->pDrawable->x, pict->pDrawable->y);
     }
     
     /* Indexed table */
     if (pict->pFormat->index.devPrivate)
 	pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
 
-    /* Add in drawable origin to position within the image */
-    *xoff += pict->pDrawable->x;
-    *yoff += pict->pDrawable->y;
-
     return image;
 }
 
 static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map);
+image_from_pict_internal (PicturePtr pict, Bool has_clip, Bool is_alpha_map);
 
 static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
+set_image_properties (pixman_image_t *image, PicturePtr pict, Bool is_alpha_map)
 {
     pixman_repeat_t repeat;
     pixman_filter_t filter;
     
     if (pict->transform)
     {
-	/* For source images, adjust the transform to account
-	 * for the drawable offset within the pixman image,
-	 * then set the offset to 0 as it will be used
-	 * to compute positions within the transformed image.
-	 */
-	if (!has_clip) {
-	    struct pixman_transform	adjusted;
-
-	    adjusted = *pict->transform;
-	    pixman_transform_translate(&adjusted,
-				       NULL,
-				       pixman_int_to_fixed(*xoff),
-				       pixman_int_to_fixed(*yoff));
-	    pixman_image_set_transform (image, &adjusted);
-	    *xoff = 0;
-	    *yoff = 0;
-	} else
-	    pixman_image_set_transform (image, pict->transform);
+	pixman_image_set_transform (
+	    image, (pixman_transform_t *)pict->transform);
     }
     
     switch (pict->repeatType)
@@ -265,8 +238,7 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
      */
     if (pict->alphaMap && !is_alpha_map)
     {
-	int alpha_xoff, alpha_yoff;
-	pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE);
+	pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, TRUE, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -299,7 +271,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
 }
 
 static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
+image_from_pict_internal (PicturePtr pict,
+		 Bool has_clip, Bool is_alpha_map)
 {
     pixman_image_t *image = NULL;
 
@@ -308,7 +281,7 @@ image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
 
     if (pict->pDrawable)
     {
-	image = create_bits_picture (pict, has_clip, xoff, yoff);
+	image = create_bits_picture (pict, has_clip);
     }
     else if (pict->pSourcePict)
     {
@@ -329,19 +302,18 @@ image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
 	    else if (sp->type == SourcePictTypeConical)
 		image = create_conical_gradient_image (gradient);
 	}
-	*xoff = *yoff = 0;
     }
     
     if (image)
-	set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map);
+	set_image_properties (image, pict, is_alpha_map);
     
     return image;
 }
 
 pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+image_from_pict (PicturePtr pict, Bool has_clip)
 {
-    return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE);
+    return image_from_pict_internal (pict, has_clip, FALSE);
 }
 
 void
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 2554fcc..421184f 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -37,8 +37,7 @@ fbAddTraps (PicturePtr	pPicture,
 	    int		ntrap,
 	    xTrap	*traps)
 {
-    int image_xoff, image_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
@@ -54,8 +53,7 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
 		      int	    x_off,
 		      int	    y_off)
 {
-    int	mask_xoff, mask_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
commit e2d598be3e211cd4fd0b7aba55805e9fd14b08f6
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Apr 30 13:08:25 2010 -0700

    Workaround the GC clipping problem in miPaintWindow and add some debugging output.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/miexpose.c b/mi/miexpose.c
index 94258b8..4f25c23 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -521,6 +521,7 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
+#include "../fb/fb.h"
 #endif 
 
 void
@@ -548,24 +549,37 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     Bool	solid = TRUE;
     DrawablePtr	drawable = &pWin->drawable;
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
+    ErrorF("      Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
+	                               prgn->extents.x2 - prgn->extents.x1,
+	                               prgn->extents.y2 - prgn->extents.y1);
+    ErrorF("      Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
+	                                       pWin->winSize.extents.x1, pWin->winSize.extents.y1,
+	                                       pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
+					       pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
+    ErrorF("     Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
+				       pWin->drawable.width, pWin->drawable.height);
+#endif
+
 #ifdef ROOTLESS
     if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
 	return;
-
-    if(IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-    
-        if(pWin->backgroundState == ParentRelative) {
-            if((what == PW_BACKGROUND) || 
-               (what == PW_BORDER && !pWin->borderIsPixel))
-                RootlessSetPixmapOfAncestors(pWin);
-        }
-    }
 #endif
     
     if (what == PW_BACKGROUND)
     {
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+
+	    if(pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	while (pWin->backgroundState == ParentRelative)
 	    pWin = pWin->parent;
 
@@ -587,6 +601,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     {
 	PixmapPtr   pixmap;
 
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+	    
+	    if(!pWin->borderIsPixel &&
+		pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	tile_x_off = drawable->x;
 	tile_y_off = drawable->y;
 	
@@ -595,6 +621,12 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
 	    return;
 	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
 	drawable = &pixmap->drawable;
+
+#ifdef XQUARTZ_CLIP_DEBUG
+	ErrorF("     Draw: %d %d %d %d\n",
+	       drawable->x, drawable->y, drawable->width, drawable->height);    
+#endif
+	
 #ifdef COMPOSITE
 	draw_x_off = pixmap->screen_x;
 	draw_y_off = pixmap->screen_y;
@@ -657,6 +689,57 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     ChangeGC (NullClient, pGC, gcmask, gcval);
     ValidateGC (drawable, pGC);
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
+#endif
+    
+#ifdef XQUARTZ
+    /* Looks like our clipping isn't set right for some reason:
+     * http://xquartz.macosforge.org/trac/ticket/290
+     */
+    if(what == PW_BORDER) {
+
+#if 0
+	if(solid) {
+#if 1
+	    fbFillRegionSolid(&pWin->drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       pWin->drawable.bitsPerPixel));
+#else
+	    fbFillRegionSolid(drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       drawable->bitsPerPixel));
+#endif
+	    return;
+	}
+#endif
+    
+	pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
+	pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
+	
+	if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
+	    pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
+	if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
+	    pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
+    }
+#endif
+
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);    
+#endif
+
     numRects = RegionNumRects(prgn);
     pbox = RegionRects(prgn);
     for (i= numRects; --i >= 0; pbox++, prect++)
commit 705f047876f78bbdfb368c3643925af1d1d17f71
Author: Julien Cristau <jcristau at debian.org>
Date:   Fri Mar 4 01:12:01 2011 +0100

    configure.ac: bump version for 1.11 development
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 8da6d21..681f9d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,8 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([xorg-server], 1.10.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2011-2-25"
+AC_INIT([xorg-server], 1.10.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="unreleased"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
commit 6c90e839d9872a37d371578c9c423e8213922044
Merge: 0bc95d5... edcceed...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 3 14:41:44 2011 -0800

    Merge remote branch 'whot/for-keith'

commit 0bc95d5b06dcea65a1aa193ea907b50f7dd168b5
Merge: 3f41f4a... 69a9171...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 3 14:33:08 2011 -0800

    Merge remote branch 'jeremyhu/master'

commit 3f41f4adea4bbb90d4bda4dab600595b655e3ed8
Merge: 8e4c3ce... dae24ab...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 3 14:12:36 2011 -0800

    Merge remote branch 'sandmann/for-keithp'

commit 8e4c3ce55b0f186bc6ba4039e30629669b6087b7
Merge: f3d19c0... 2965615...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 3 13:42:07 2011 -0800

    Merge remote branch 'rjy/clientids'

commit dae24abcd44f3bb1966faa88222f851c784b37dc
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Feb 28 11:10:38 2011 -0500

    Delete RegionClipSpans()
    
    Nothing uses it.
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Søren Sandmann Pedersen <ssp at redhat.com>

diff --git a/dix/region.c b/dix/region.c
index 5ba3457..6820c1e 100644
--- a/dix/region.c
+++ b/dix/region.c
@@ -1423,237 +1423,3 @@ RegionFromRects(int nrects, xRectangle *prect, int ctype)
     }
     return pRgn;
 }
-
-#define ExchangeSpans(a, b)				    \
-{							    \
-    DDXPointRec	tpt;				    	    \
-    int    	tw;					    \
-							    \
-    tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt;    \
-    tw = widths[a]; widths[a] = widths[b]; widths[b] = tw;  \
-}
-
-/* ||| I should apply the merge sort code to rectangle sorting above, and see
-   if mapping time can be improved.  But right now I've been at work 12 hours,
-   so forget it.
-*/
-
-static void QuickSortSpans(
-    DDXPointRec spans[],
-    int	    	widths[],
-    int	    	numSpans)
-{
-    int	    y;
-    int	    i, j, m;
-    DDXPointPtr    r;
-
-    /* Always called with numSpans > 1 */
-    /* Sorts only by y, doesn't bother to sort by x */
-
-    do
-    {
-	if (numSpans < 9)
-	{
-	    /* Do insertion sort */
-	    int yprev;
-
-	    yprev = spans[0].y;
-	    i = 1;
-	    do
-	    { /* while i != numSpans */
-		y = spans[i].y;
-		if (yprev > y)
-		{
-		    /* spans[i] is out of order.  Move into proper location. */
-		    DDXPointRec tpt;
-		    int	    tw, k;
-
-		    for (j = 0; y >= spans[j].y; j++) {}
-		    tpt = spans[i];
-		    tw  = widths[i];
-		    for (k = i; k != j; k--)
-		    {
-			spans[k] = spans[k-1];
-			widths[k] = widths[k-1];
-		    }
-		    spans[j] = tpt;
-		    widths[j] = tw;
-		    y = spans[i].y;
-		} /* if out of order */
-		yprev = y;
-		i++;
-	    } while (i != numSpans);
-	    return;
-	}
-
-	/* Choose partition element, stick in location 0 */
-	m = numSpans / 2;
-	if (spans[m].y > spans[0].y)		ExchangeSpans(m, 0);
-	if (spans[m].y > spans[numSpans-1].y)   ExchangeSpans(m, numSpans-1);
-	if (spans[m].y > spans[0].y)		ExchangeSpans(m, 0);
-	y = spans[0].y;
-
-        /* Partition array */
-        i = 0;
-        j = numSpans;
-        do
-	{
-	    r = &(spans[i]);
-	    do
-	    {
-		r++;
-		i++;
-            } while (i != numSpans && r->y < y);
-	    r = &(spans[j]);
-	    do
-	    {
-		r--;
-		j--;
-            } while (y < r->y);
-            if (i < j)
-		ExchangeSpans(i, j);
-        } while (i < j);
-
-        /* Move partition element back to middle */
-        ExchangeSpans(0, j);
-
-	/* Recurse */
-        if (numSpans-j-1 > 1)
-	    QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
-        numSpans = j;
-    } while (numSpans > 1);
-}
-
-#define NextBand()						    \
-{								    \
-    clipy1 = pboxBandStart->y1;					    \
-    clipy2 = pboxBandStart->y2;					    \
-    pboxBandEnd = pboxBandStart + 1;				    \
-    while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) {  \
-	pboxBandEnd++;						    \
-    }								    \
-    for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
-}
-
-/*
-    Clip a list of scanlines to a region.  The caller has allocated the
-    space.  FSorted is non-zero if the scanline origins are in ascending
-    order.
-    returns the number of new, clipped scanlines.
-*/
-
-int
-RegionClipSpans(
-    RegionPtr	prgnDst,
-    DDXPointPtr ppt,
-    int	    	*pwidth,
-    int		nspans,
-    DDXPointPtr	pptNew,
-    int		*pwidthNew,
-    int		fSorted)
-{
-    DDXPointPtr pptLast;
-    int	*pwidthNewStart;	/* the vengeance of Xerox! */
-    int	y, x1, x2;
-    int	numRects;
-
-    good(prgnDst);
-    pptLast = ppt + nspans;
-    pwidthNewStart = pwidthNew;
-
-    if (!prgnDst->data)
-    {
-	/* Do special fast code with clip boundaries in registers(?) */
-	/* It doesn't pay much to make use of fSorted in this case, 
-	   so we lump everything together. */
-
-	int clipx1, clipx2, clipy1, clipy2;
-
-	clipx1 = prgnDst->extents.x1;
-	clipy1 = prgnDst->extents.y1;
-	clipx2 = prgnDst->extents.x2;
-	clipy2 = prgnDst->extents.y2;
-	    
-	for (; ppt != pptLast; ppt++, pwidth++)
-	{
-	    y = ppt->y;
-	    x1 = ppt->x;
-	    if (clipy1 <= y && y < clipy2)
-	    {
-		x2 = x1 + *pwidth;
-		if (x1 < clipx1)    x1 = clipx1;
-		if (x2 > clipx2)    x2 = clipx2;
-		if (x1 < x2)
-		{
-		    /* part of span in clip rectangle */
-		    pptNew->x = x1;
-		    pptNew->y = y;
-		    *pwidthNew = x2 - x1;
-		    pptNew++;
-		    pwidthNew++;
-		}
-	    }
-	} /* end for */
-
-    }
-    else if ((numRects = prgnDst->data->numRects))
-    {
-	/* Have to clip against many boxes */
-	BoxPtr pboxBandStart, pboxBandEnd;
-	BoxPtr pbox;
-	BoxPtr pboxLast;
-	int clipy1, clipy2;
-
-	/* In this case, taking advantage of sorted spans gains more than
-	   the sorting costs. */
-	if ((! fSorted) && (nspans > 1))
-	    QuickSortSpans(ppt, pwidth, nspans);
-
-	pboxBandStart = RegionBoxptr(prgnDst);
-	pboxLast = pboxBandStart + numRects;
-    
-	NextBand();
-
-	for (; ppt != pptLast; )
-	{
-	    y = ppt->y;
-	    if (y < clipy2)
-	    {
-		/* span is in the current band */
-		pbox = pboxBandStart;
-		x1 = ppt->x;
-		x2 = x1 + *pwidth;
-		do
-		{ /* For each box in band */
-		    int newx1, newx2;
-
-		    newx1 = x1;
-		    newx2 = x2;
-		    if (newx1 < pbox->x1)   newx1 = pbox->x1;
-		    if (newx2 > pbox->x2)   newx2 = pbox->x2;
-		    if (newx1 < newx2)
-		    {
-			/* Part of span in clip rectangle */
-			pptNew->x = newx1;
-			pptNew->y = y;
-			*pwidthNew = newx2 - newx1;
-			pptNew++;
-			pwidthNew++;
-		    }
-		    pbox++;
-		} while (pbox != pboxBandEnd);
-		ppt++;
-		pwidth++;
-	    }
-	    else
-	    {
-		/* Move to next band, adjust ppt as needed */
-		pboxBandStart = pboxBandEnd;
-		if (pboxBandStart == pboxLast)
-		    break; /* We're completely done */
-		NextBand();
-	    }
-	}
-    }
-    return pwidthNew - pwidthNewStart;
-}
diff --git a/include/regionstr.h b/include/regionstr.h
index 627941b..3759fe1 100644
--- a/include/regionstr.h
+++ b/include/regionstr.h
@@ -318,16 +318,6 @@ extern _X_EXPORT Bool RegionIsValid(
 extern _X_EXPORT void RegionPrint(
     RegionPtr /*pReg*/);
 
-extern _X_EXPORT int RegionClipSpans(
-    RegionPtr /*prgnDst*/,
-    DDXPointPtr /*ppt*/,
-    int * /*pwidth*/,
-    int /*nspans*/,
-    DDXPointPtr /*pptNew*/,
-    int * /*pwidthNew*/,
-    int /*fSorted*/
-);
-
 #define INCLUDE_LEGACY_REGION_DEFINES
 #ifdef INCLUDE_LEGACY_REGION_DEFINES
 
commit edcceedbd35df576929685767d0b619659e5b020
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Feb 28 12:32:53 2011 -0500

    xext: Remove XCALIBRATE extension
    
    Nobody can have been using this, it's never called from extension init.
    XI2 device properties should now be a functional replacement.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index b6c95cb..cb432e0 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -94,12 +94,6 @@ if XCSECURITY
 BUILTIN_SRCS += $(XCSECURITY_SRCS)
 endif
 
-XCALIBRATE_SRCS = xcalibrate.c
-if XCALIBRATE
-BUILTIN_SRCS += $(XCALIBRATE_SRCS)
-# XCalibrate needs tslib
-endif
-
 # XF86 Big Font extension
 BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
 if XF86BIGFONT
@@ -132,7 +126,6 @@ EXTRA_DIST = \
 	$(XACE_SRCS) \
 	$(XCSECURITY_SRCS) \
 	$(XSELINUX_SRCS) \
-	$(XCALIBRATE_SRCS) \
 	$(XINERAMA_SRCS) \
 	$(BIGFONT_SRCS) \
 	$(DPMS_SRCS) \
diff --git a/Xext/xcalibrate.c b/Xext/xcalibrate.c
deleted file mode 100644
index bff1c31..0000000
--- a/Xext/xcalibrate.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright © 2003 Philip Blundell
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Philip Blundell not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Philip Blundell makes no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.
- *
- * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL PHILIP BLUNDELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_KDRIVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "swaprep.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/xcalibrateproto.h>
-#include <X11/extensions/xcalibratewire.h>
-
-extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure);
-extern void *tslib_raw_event_closure;
-
-static CARD8	XCalibrateReqCode;
-int		XCalibrateEventBase;
-int		XCalibrateReqBase;
-int		XCalibrateErrorBase;
-
-static ClientPtr xcalibrate_client;
-
-static void
-xcalibrate_event_hook (int x, int y, int pressure, void *closure)
-{
-  ClientPtr pClient = (ClientPtr) closure;
-  xXCalibrateRawTouchscreenEvent	ev;
-
-  ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen;
-  ev.x = x;
-  ev.y = y;
-  ev.pressure = pressure;
-
-  WriteEventsToClient (pClient, 1, (xEvent *) &ev);
-}
-
-static int
-ProcXCalibrateQueryVersion (ClientPtr client)
-{
-  REQUEST(xXCalibrateQueryVersionReq);
-  xXCalibrateQueryVersionReply rep;
-  CARD16 client_major, client_minor;  /* not used */
-
-  REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
-
-  client_major = stuff->majorVersion;
-  client_minor = stuff->minorVersion;
-
-  fprintf(stderr, "%s(): called\n", __func__); 
-
-  rep.type = X_Reply;
-  rep.length = 0;
-  rep.sequenceNumber = client->sequence;
-  rep.majorVersion = SERVER_XCALIBRATE_MAJOR_VERSION;
-  rep.minorVersion = SERVER_XCALIBRATE_MINOR_VERSION;
-  if (client->swapped) { 
-    int n;
-    swaps(&rep.sequenceNumber, n);
-    swapl(&rep.length, n);     
-    swaps(&rep.majorVersion, n);
-    swaps(&rep.minorVersion, n);
-  }
-  WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep);
-  return Success;
-}
-
-static int
-SProcXCalibrateQueryVersion (ClientPtr client)
-{
-    REQUEST(xXCalibrateQueryVersionReq);
-    int n;
-
-    REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
-    swaps(&stuff->majorVersion,n);
-    swaps(&stuff->minorVersion,n);
-    return ProcXCalibrateQueryVersion(client);
-}
-
-static int
-ProcXCalibrateSetRawMode (ClientPtr client)
-{
-  REQUEST(xXCalibrateRawModeReq);
-  xXCalibrateRawModeReply rep;
-
-  REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
-
-  memset (&rep, 0, sizeof (rep));
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-
-  if (stuff->on)
-    {
-      if (xcalibrate_client == NULL)
-	{
-	  /* Start calibrating.  */
-	  xcalibrate_client = client;
-	  tslib_raw_event_hook = xcalibrate_event_hook;
-	  tslib_raw_event_closure = client;
-	  rep.status = GrabSuccess;
-	}
-      else
-	{
-	  rep.status = AlreadyGrabbed;
-	}
-    }
-  else
-    {
-      if (xcalibrate_client == client)
-	{
-	  /* Stop calibrating.  */
-	  xcalibrate_client = NULL;
-	  tslib_raw_event_hook = NULL;
-	  tslib_raw_event_closure = NULL;
-	  rep.status = GrabSuccess;
-
-	  /* Cycle input off and on to reload configuration.  */
-	  KdDisableInput ();
-	  KdEnableInput ();
-	}
-      else
-	{
-	  rep.status = AlreadyGrabbed;
-	}
-    }
-
-  if (client->swapped)
-    {
-      int n;
-
-      swaps (&rep.sequenceNumber, n);
-      swaps (&rep.status, n);
-    }
-  WriteToClient(client, sizeof (rep), (char *) &rep);
-  return Success;
-}
-
-static int
-SProcXCalibrateSetRawMode (ClientPtr client)
-{
-  REQUEST(xXCalibrateRawModeReq);
-  int n;
-
-  REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
-
-  swaps(&stuff->on, n);
-
-  return ProcXCalibrateSetRawMode(client);
-}
-
-static int
-ProcXCalibrateScreenToCoord (ClientPtr client)
-{
-  REQUEST(xXCalibrateScreenToCoordReq);
-  xXCalibrateScreenToCoordReply rep;
-
-  REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
-
-  memset (&rep, 0, sizeof (rep));
-  rep.type = X_Reply;
-  rep.sequenceNumber = client->sequence;
-  rep.x = stuff->x;
-  rep.y = stuff->y;
-
-  KdScreenToPointerCoords(&rep.x, &rep.y);
-
-  if (client->swapped)
-    {
-      int n;
-
-      swaps (&rep.x, n);
-      swaps (&rep.y, n);
-    }
-  WriteToClient(client, sizeof (rep), (char *) &rep);
-  return Success;
-}
-
-static int
-SProcXCalibrateScreenToCoord (ClientPtr client)
-{
-  REQUEST(xXCalibrateScreenToCoordReq);
-  int n;
-
-  REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
-
-  swaps(&stuff->x, n);
-  swaps(&stuff->y, n);
-
-  return ProcXCalibrateScreenToCoord(client);
-}
-
-static int
-ProcXCalibrateDispatch (ClientPtr client)
-{
-    REQUEST(xReq);
-    switch (stuff->data) {
-    case X_XCalibrateQueryVersion:
-        return ProcXCalibrateQueryVersion(client);
-    case X_XCalibrateRawMode:
-        return ProcXCalibrateSetRawMode(client);
-    case X_XCalibrateScreenToCoord:
-        return ProcXCalibrateScreenToCoord(client);
-
-    default: break;
-    }
-
-    return BadRequest;
-}
-
-static int
-SProcXCalibrateDispatch (ClientPtr client)
-{
-    REQUEST(xReq);
-    int n;
-
-    swaps(&stuff->length,n);
-
-    switch (stuff->data) {
-    case X_XCalibrateQueryVersion:
-        return SProcXCalibrateQueryVersion(client);
-    case X_XCalibrateRawMode:
-        return SProcXCalibrateSetRawMode(client);
-    case X_XCalibrateScreenToCoord:
-        return SProcXCalibrateScreenToCoord(client);
-
-    default: break;
-    }
-
-    return BadRequest;
-}
-
-static void
-XCalibrateClientCallback (CallbackListPtr	*list,
-			  pointer		closure,
-			  pointer		data)
-{
-    NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
-    ClientPtr		pClient = clientinfo->client;
-
-    if (clientinfo->setup == NULL
-	&& xcalibrate_client != NULL
-	&& xcalibrate_client == pClient)
-      {
-	/* Stop calibrating.  */
-	xcalibrate_client = NULL;
-	tslib_raw_event_hook = NULL;
-	tslib_raw_event_closure = NULL;
-      }
-}
-
-void
-XCalibrateExtensionInit(void)
-{
-  ExtensionEntry *extEntry;
-
-  if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0))
-    return;  
-
-  extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors,
-			  ProcXCalibrateDispatch, SProcXCalibrateDispatch,
-			  NULL, StandardMinorOpcode);
-
-  if (!extEntry)
-    return;
-
-  XCalibrateReqCode = (unsigned char)extEntry->base;
-  XCalibrateEventBase = extEntry->eventBase;
-  XCalibrateErrorBase = extEntry->errorBase;
-
-  xcalibrate_client = 0;
-}
diff --git a/configure.ac b/configure.ac
index ac4bf8c..8eb919c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -626,7 +626,6 @@ AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF8
 AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
 AC_ARG_ENABLE(xselinux,       AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no])
 AC_ARG_ENABLE(xcsecurity,     AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no])
-AC_ARG_ENABLE(xcalibrate,     AS_HELP_STRING([--enable-xcalibrate], [Build XCalibrate extension (default: disabled)]), [XCALIBRATE=$enableval], [XCALIBRATE=no])
 AC_ARG_ENABLE(tslib,          AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no])
 AC_ARG_ENABLE(dbe,            AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes])
 AC_ARG_ENABLE(xf86bigfont,    AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no])
@@ -779,7 +778,6 @@ DRIPROTO="xf86driproto >= 2.1.0"
 DRI2PROTO="dri2proto >= 2.3"
 XINERAMAPROTO="xineramaproto"
 BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
-XCALIBRATEPROTO="xcalibrateproto"
 DGAPROTO="xf86dgaproto >= 2.0.99.1"
 GLPROTO="glproto >= 1.4.10"
 DMXPROTO="dmxproto >= 2.2.99.1"
@@ -1120,14 +1118,6 @@ if test "x$DPMSExtension" = xyes; then
 	AC_DEFINE(DPMSExtension, 1, [Support DPMS extension])
 fi
 
-if test "x$XCALIBRATE" = xyes && test "$KDRIVE" = yes; then
-   AC_DEFINE(XCALIBRATE, 1, [Build XCalibrate extension])
-   REQUIRED_MODULES="$REQUIRED_MODULES $XCALIBRATEPROTO"
-else
-   XCALIBRATE=no
-fi
-AM_CONDITIONAL(XCALIBRATE, [test "x$XCALIBRATE" = xyes])
-
 AC_DEFINE(RENDER, 1, [Support RENDER extension])
 RENDER_LIB='$(top_builddir)/render/librender.la'
 RENDER_INC='-I$(top_srcdir)/render'
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index c8c7f5f..cfba8ab 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -104,10 +104,6 @@
 #define SERVER_WINDOWSWM_MINOR_VERSION		0
 #define SERVER_WINDOWSWM_PATCH_VERSION		0
 
-/* Xcalibrate */
-#define SERVER_XCALIBRATE_MAJOR_VERSION		0
-#define SERVER_XCALIBRATE_MINOR_VERSION		1
-
 /* DGA */
 #define SERVER_XDGA_MAJOR_VERSION		2
 #define SERVER_XDGA_MINOR_VERSION		0
commit c2207d11f243900bc2f641e08d80da63d84e97a8
Merge: 0077993... 579ee8f...
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Feb 28 11:26:09 2011 +1000

    Merge branch 'next' into for-keith
    
    Conflicts:
    	dix/devices.c
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --cc dix/devices.c
index b73fb29,2931947..b8d8e7b
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -2448,10 -2387,8 +2427,10 @@@ AttachDevice(ClientPtr client, DeviceIn
          free(dev->spriteInfo->sprite);
      }
  
 +    ReleaseButtonsAndKeys(dev);
 +
-     oldmaster = dev->u.master;
-     dev->u.master = master;
+     oldmaster = GetMaster(dev, MASTER_ATTACHED);
+     dev->master = master;
  
      /* If device is set to floating, we need to create a sprite for it,
       * otherwise things go bad. However, we don't want to render the cursor,
commit 00779932de861bf7ac8c625802f1afed75d01b6f
Author: Matthieu Herrb <matthieu.herrb at laas.fr>
Date:   Sun Feb 27 20:16:03 2011 +0100

    Don't clobber input device options from xorg.conf
    
    Since commit b8d9c5ff removed commonOptions, we now
    need to append the "Core{Keyboard,Pointer}" options to
    the existing list.
    
    Fixes passing options to devices confirured in xorg.conf
    on systems where autoaddevices is false.
    
    Signed-off-by: Matthieu Herrb <matthieu.herrb at laas.fr>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 49d8fa8..9602e89 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1224,7 +1224,8 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
             devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
 	    *devs[count - 1] = Pointer;
 	    devs[count - 1]->options =
-				xf86addNewOption(NULL, xnfstrdup("CorePointer"), NULL);
+				xf86addNewOption(devs[count -1]->options,
+				    xnfstrdup("CorePointer"), NULL);
 	    devs[count] = NULL;
 	    servlayoutp->inputs = devs;
 	}
@@ -1364,7 +1365,8 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
             devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
 	    *devs[count - 1] = Keyboard;
 	    devs[count - 1]->options =
-				xf86addNewOption(NULL, xnfstrdup("CoreKeyboard"), NULL);
+				xf86addNewOption(devs[count - 1]->options,
+				    xnfstrdup("CoreKeyboard"), NULL);
 	    devs[count] = NULL;
 	    servlayoutp->inputs = devs;
 	}
commit 7dff79e39564b403c3afbc5e7bacffa0df190a23
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Feb 11 09:00:10 2011 -0500

    Implement fbAddTriangles() in terms of pixman_add_triangles()
    
    This allows the remaining triangle-to-trap conversion code to be
    deleted.
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Søren Sandmann <ssp at redhat.com>

diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 3b197b4..2554fcc 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -65,32 +65,6 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
     free_pixman_pict (pPicture, image);
 }
 
-static int
-_GreaterY (xPointFixed *a, xPointFixed *b)
-{
-    if (a->y == b->y)
-	return a->x > b->x;
-    return a->y > b->y;
-}
-
-/*
- * Note that the definition of this function is a bit odd because
- * of the X coordinate space (y increasing downwards).
- */
-static int
-_Clockwise (xPointFixed *ref, xPointFixed *a, xPointFixed *b)
-{
-    xPointFixed	ad, bd;
-
-    ad.x = a->x - ref->x;
-    ad.y = a->y - ref->y;
-    bd.x = b->x - ref->x;
-    bd.y = b->y - ref->y;
-
-    return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0;
-}
-
-/* FIXME -- this could be made more efficient */
 void
 fbAddTriangles (PicturePtr  pPicture,
 		INT16	    x_off,
@@ -98,63 +72,16 @@ fbAddTriangles (PicturePtr  pPicture,
 		int	    ntri,
 		xTriangle *tris)
 {
-    xPointFixed	  *top, *left, *right, *tmp;
-    xTrapezoid	    trap;
+    int image_xoff, image_yoff;
+    pixman_image_t *image =
+	image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
 
-    for (; ntri; ntri--, tris++)
-    {
-	top = &tris->p1;
-	left = &tris->p2;
-	right = &tris->p3;
-	if (_GreaterY (top, left)) {
-	    tmp = left; left = top; top = tmp;
-	}
-	if (_GreaterY (top, right)) {
-	    tmp = right; right = top; top = tmp;
-	}
-	if (_Clockwise (top, right, left)) {
-	    tmp = right; right = left; left = tmp;
-	}
-	
-	/*
-	 * Two cases:
-	 *
-	 *		+		+
-	 *	       / \             / \
-	 *	      /   \           /   \
-	 *	     /     +         +     \
-	 *          /    --           --    \
-	 *         /   --               --   \
-	 *        / ---                   --- \
-	 *	 +--                         --+
-	 */
-	
-	trap.top = top->y;
-	trap.left.p1 = *top;
-	trap.left.p2 = *left;
-	trap.right.p1 = *top;
-	trap.right.p2 = *right;
-	if (right->y < left->y)
-	    trap.bottom = right->y;
-	else
-	    trap.bottom = left->y;
-	fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
-	if (right->y < left->y)
-	{
-	    trap.top = right->y;
-	    trap.bottom = left->y;
-	    trap.right.p1 = *right;
-	    trap.right.p2 = *left;
-	}
-	else
-	{
-	    trap.top = left->y;
-	    trap.bottom = right->y;
-	    trap.left.p1 = *left;
-	    trap.left.p2 = *right;
-	}
-	fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
-    }
+    if (!image)
+	return;
+    
+    pixman_add_triangles (image, x_off, y_off, ntri, (pixman_triangle_t *)tris);
+
+    free_pixman_pict (pPicture, image);
 }
 
 typedef void (* CompositeShapesFunc) (pixman_op_t op,
commit 566f1931ee2916269e164e114bffaf2da1d039d1
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Jan 11 10:33:57 2011 -0500

    Move miTriangles to fb as fbTriangles()
    
    The fb version simply calls the new pixman_composite_triangles(). This
    allows us to get rid of miCreateAlphaPicture().
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Søren Sandmann <ssp at redhat.com>

diff --git a/fb/fbpict.c b/fb/fbpict.c
index 6e66db8..312f3df 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -367,6 +367,7 @@ fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     ps->Trapezoids = fbTrapezoids;
     ps->AddTraps = fbAddTraps;
     ps->AddTriangles = fbAddTriangles;
+    ps->Triangles = fbTriangles;
 
     return TRUE;
 }
diff --git a/fb/fbpict.h b/fb/fbpict.h
index 03d2665..b880ebb 100644
--- a/fb/fbpict.h
+++ b/fb/fbpict.h
@@ -75,4 +75,14 @@ fbTrapezoids (CARD8	    op,
 	      int	    ntrap,
 	      xTrapezoid    *traps);
 
+extern _X_EXPORT void
+fbTriangles (CARD8	    op,
+	     PicturePtr     pSrc,
+	     PicturePtr     pDst,
+	     PictFormatPtr  maskFormat,
+	     INT16	    xSrc,
+	     INT16	    ySrc,
+	     int	    ntris,
+	     xTriangle     *tris);
+
 #endif /* _FBPICT_H_ */
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 687de55..3b197b4 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -157,51 +157,56 @@ fbAddTriangles (PicturePtr  pPicture,
     }
 }
 
+typedef void (* CompositeShapesFunc) (pixman_op_t op,
+				      pixman_image_t *src,
+				      pixman_image_t *dst,
+				      pixman_format_code_t mask_format,
+				      int x_src, int y_src,
+				      int x_dst, int y_dst,
+				      int n_shapes, const uint8_t *shapes);
 
-void
-fbTrapezoids (CARD8	    op,
-	      PicturePtr    pSrc,
-	      PicturePtr    pDst,
-	      PictFormatPtr maskFormat,
-	      INT16	    xSrc,
-	      INT16	    ySrc,
-	      int	    ntrap,
-	      xTrapezoid    *traps)
+static void
+fbShapes (CompositeShapesFunc	composite,
+	  pixman_op_t		op,
+	  PicturePtr		pSrc,
+	  PicturePtr		pDst,
+	  PictFormatPtr		maskFormat,
+	  int16_t		xSrc,
+	  int16_t		ySrc,
+	  int16_t		xDst,
+	  int16_t		yDst,
+	  int			nshapes,
+	  int			shape_size,
+	  const uint8_t *	shapes)
 {
     pixman_image_t *src, *dst;
     int src_xoff, src_yoff;
     int dst_xoff, dst_yoff;
 
-    if (ntrap == 0)
-	return;
-    
     src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
     dst = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
 
     if (src && dst)
     {
 	pixman_format_code_t format;
-	int x_dst, y_dst;
-	int i;
 
-	x_dst = traps[0].left.p1.x >> 16;
-	y_dst = traps[0].left.p1.y >> 16;
-	    
 	if (!maskFormat)
 	{
+	    int i;
+
 	    if (pDst->polyEdge == PolyEdgeSharp)
 		format = PIXMAN_a1;
 	    else
 		format = PIXMAN_a8;
 
-	    for (i = 0; i < ntrap; ++i)
+	    for (i = 0; i < nshapes; ++i)
 	    {
-		pixman_composite_trapezoids (op, src, dst, format,
-					     xSrc + src_xoff,
-					     ySrc + src_yoff,
-					     x_dst + dst_xoff,
-					     y_dst + dst_yoff,
-					     1, (pixman_trapezoid_t *)traps++);
+		composite (op, src, dst, format,
+			   xSrc + src_xoff,
+			   ySrc + src_yoff,
+			   xDst + dst_xoff,
+			   yDst + dst_yoff,
+			   1, shapes + i * shape_size);
 	    }
 	}
 	else
@@ -221,16 +226,58 @@ fbTrapezoids (CARD8	    op,
 		format = PIXMAN_a8;
 		break;
 	    }
-
-	    pixman_composite_trapezoids (op, src, dst, format,
-					 xSrc + src_xoff,
-					 ySrc + src_yoff,
-					 x_dst + dst_xoff,
-					 y_dst + dst_yoff,
-					 ntrap, (pixman_trapezoid_t *)traps);
+	    
+	    composite (op, src, dst, format,
+		       xSrc + src_xoff,
+		       ySrc + src_yoff,
+		       xDst + dst_xoff,
+		       yDst + dst_yoff,
+		       nshapes, shapes);
 	}
     }
 
     free_pixman_pict (pSrc, src);
     free_pixman_pict (pDst, dst);
 }
+
+void
+fbTrapezoids (CARD8	    op,
+	      PicturePtr    pSrc,
+	      PicturePtr    pDst,
+	      PictFormatPtr maskFormat,
+	      INT16	    xSrc,
+	      INT16	    ySrc,
+	      int	    ntrap,
+	      xTrapezoid    *traps)
+{
+    int xDst, yDst;
+
+    xDst = traps[0].left.p1.x >> 16;
+    yDst = traps[0].left.p1.y >> 16;
+    
+    fbShapes ((CompositeShapesFunc)pixman_composite_trapezoids,
+	      op, pSrc, pDst, maskFormat,
+	      xSrc, ySrc, xDst, yDst,
+	      ntrap, sizeof (xTrapezoid), (const uint8_t *)traps);
+}
+
+void
+fbTriangles (CARD8	    op,
+	     PicturePtr    pSrc,
+	     PicturePtr    pDst,
+	     PictFormatPtr maskFormat,
+	     INT16	    xSrc,
+	     INT16	    ySrc,
+	     int	    ntris,
+	     xTriangle    *tris)
+{ 
+    int xDst, yDst;
+
+    xDst = tris[0].p1.x >> 16;
+    yDst = tris[0].p1.y >> 16;
+    
+    fbShapes ((CompositeShapesFunc)pixman_composite_triangles,
+	      op, pSrc, pDst, maskFormat,
+	      xSrc, ySrc, xDst, yDst,
+	      ntris, sizeof (xTriangle), (const uint8_t *)tris);
+}
diff --git a/render/mipict.c b/render/mipict.c
index 46b45b5..3b73888 100644
--- a/render/mipict.c
+++ b/render/mipict.c
@@ -632,7 +632,7 @@ miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     ps->Glyphs		= miGlyphs;
     ps->CompositeRects	= miCompositeRects;
     ps->Trapezoids	= 0;
-    ps->Triangles	= miTriangles;
+    ps->Triangles	= 0;
     ps->TriStrip	= miTriStrip;
     ps->TriFan		= miTriFan;
     
diff --git a/render/mipict.h b/render/mipict.h
index be7b20b..d149589 100644
--- a/render/mipict.h
+++ b/render/mipict.h
@@ -152,16 +152,6 @@ extern _X_EXPORT void
 miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds);
 
 extern _X_EXPORT void
-miTriangles (CARD8	    op,
-	     PicturePtr	    pSrc,
-	     PicturePtr	    pDst,
-	     PictFormatPtr  maskFormat,
-	     INT16	    xSrc,
-	     INT16	    ySrc,
-	     int	    ntri,
-	     xTriangle	    *tris);
-
-extern _X_EXPORT void
 miTriStrip (CARD8	    op,
 	    PicturePtr	    pSrc,
 	    PicturePtr	    pDst,
@@ -181,13 +171,6 @@ miTriFan (CARD8		op,
 	  int		npoint,
 	  xPointFixed	*points);
 
-extern _X_EXPORT PicturePtr
-miCreateAlphaPicture (ScreenPtr	    pScreen, 
-		      PicturePtr    pDst,
-		      PictFormatPtr pPictFormat,
-		      CARD16	    width,
-		      CARD16	    height);
-
 extern _X_EXPORT Bool
 miInitIndexed (ScreenPtr	pScreen,
 	       PictFormatPtr	pFormat);
diff --git a/render/mitrap.c b/render/mitrap.c
index 1f09a1e..445f236 100644
--- a/render/mitrap.c
+++ b/render/mitrap.c
@@ -34,55 +34,6 @@
 #include "picturestr.h"
 #include "mipict.h"
 
-PicturePtr
-miCreateAlphaPicture (ScreenPtr	    pScreen, 
-		      PicturePtr    pDst,
-		      PictFormatPtr pPictFormat,
-		      CARD16	    width,
-		      CARD16	    height)
-{
-    PixmapPtr	    pPixmap;
-    PicturePtr	    pPicture;
-    GCPtr	    pGC;
-    int		    error;
-    xRectangle	    rect;
-
-    if (width > 32767 || height > 32767)
-	return 0;
-
-    if (!pPictFormat)
-    {
-	if (pDst->polyEdge == PolyEdgeSharp)
-	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
-	else
-	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
-	if (!pPictFormat)
-	    return 0;
-    }
-
-    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 
-					pPictFormat->depth, 0);
-    if (!pPixmap)
-	return 0;
-    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
-    if (!pGC)
-    {
-	(*pScreen->DestroyPixmap) (pPixmap);
-	return 0;
-    }
-    ValidateGC (&pPixmap->drawable, pGC);
-    rect.x = 0;
-    rect.y = 0;
-    rect.width = width;
-    rect.height = height;
-    (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect);
-    FreeScratchGC (pGC);
-    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
-			      0, 0, serverClient, &error);
-    (*pScreen->DestroyPixmap) (pPixmap);
-    return pPicture;
-}
-
 static xFixed
 miLineFixedX (xLineFixed *l, xFixed y, Bool ceil)
 {
diff --git a/render/mitri.c b/render/mitri.c
index a805a71..b258c21 100644
--- a/render/mitri.c
+++ b/render/mitri.c
@@ -68,65 +68,6 @@ miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds)
 }
 
 void
-miTriangles (CARD8	    op,
-	     PicturePtr	    pSrc,
-	     PicturePtr	    pDst,
-	     PictFormatPtr  maskFormat,
-	     INT16	    xSrc,
-	     INT16	    ySrc,
-	     int	    ntri,
-	     xTriangle	    *tris)
-{
-    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
-    PictureScreenPtr    ps = GetPictureScreen(pScreen);
-    
-    /*
-     * Check for solid alpha add
-     */
-    if (op == PictOpAdd && miIsSolidAlpha (pSrc))
-    {
-	(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
-    }
-    else if (maskFormat)
-    {
-	BoxRec		bounds;
-	PicturePtr	pPicture;
-	INT16		xDst, yDst;
-	INT16		xRel, yRel;
-	
-	xDst = tris[0].p1.x >> 16;
-	yDst = tris[0].p1.y >> 16;
-
-	miTriangleBounds (ntri, tris, &bounds);
-	if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
-	    return;
-	pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
-					 bounds.x2 - bounds.x1,
-					 bounds.y2 - bounds.y1);
-	if (!pPicture)
-	    return;
-	(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
-	
-	xRel = bounds.x1 + xSrc - xDst;
-	yRel = bounds.y1 + ySrc - yDst;
-	CompositePicture (op, pSrc, pPicture, pDst,
-			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
-			  bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
-	FreePicture (pPicture, 0);
-    }
-    else
-    {
-	if (pDst->polyEdge == PolyEdgeSharp)
-	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
-	else
-	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
-	
-	for (; ntri; ntri--, tris++)
-	    miTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
-    }
-}
-
-void
 miTriStrip (CARD8	    op,
 	    PicturePtr	    pSrc,
 	    PicturePtr	    pDst,
commit 788ccb9a8bcf6a4fb4054c507111eec3338fb969
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Jan 11 09:46:46 2011 -0500

    Move miTrapezoids() into fb as fbTrapezoids()
    
    The main consumer of trapezoids, cairo, is using the Trapezoids
    request, which is currently implemented in the miTrapezoids()
    function. That function splits the request into smaller bits and calls
    lower level functions such as AddTrap.
    
    By moving the implementation of the whole request into fb, we can
    instead call pixman_composite_trapezoids() to do the whole request in
    one step.
    
    There are no callers of miTrapezoids in any of the open source
    drivers, although exa and uxa have their own copies of the function.
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Søren Sandmann <ssp at redhat.com>

diff --git a/fb/fbpict.c b/fb/fbpict.c
index 7636040..6e66db8 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -364,6 +364,7 @@ fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     ps->Glyphs = miGlyphs;
     ps->CompositeRects = miCompositeRects;
     ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
+    ps->Trapezoids = fbTrapezoids;
     ps->AddTraps = fbAddTraps;
     ps->AddTriangles = fbAddTriangles;
 
diff --git a/fb/fbpict.h b/fb/fbpict.h
index 9abced1..03d2665 100644
--- a/fb/fbpict.h
+++ b/fb/fbpict.h
@@ -65,4 +65,14 @@ fbAddTriangles (PicturePtr  pPicture,
 		int	    ntri,
 		xTriangle   *tris);
 
+extern _X_EXPORT void
+fbTrapezoids (CARD8	    op,
+	      PicturePtr    pSrc,
+	      PicturePtr    pDst,
+	      PictFormatPtr maskFormat,
+	      INT16	    xSrc,
+	      INT16	    ySrc,
+	      int	    ntrap,
+	      xTrapezoid    *traps);
+
 #endif /* _FBPICT_H_ */
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index c309ceb..687de55 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -123,9 +123,9 @@ fbAddTriangles (PicturePtr  pPicture,
 	 *	       / \             / \
 	 *	      /   \           /   \
 	 *	     /     +         +     \
-	 *      /    --           --    \
-	 *     /   --               --   \
-	 *    / ---                   --- \
+	 *          /    --           --    \
+	 *         /   --               --   \
+	 *        / ---                   --- \
 	 *	 +--                         --+
 	 */
 	
@@ -157,3 +157,80 @@ fbAddTriangles (PicturePtr  pPicture,
     }
 }
 
+
+void
+fbTrapezoids (CARD8	    op,
+	      PicturePtr    pSrc,
+	      PicturePtr    pDst,
+	      PictFormatPtr maskFormat,
+	      INT16	    xSrc,
+	      INT16	    ySrc,
+	      int	    ntrap,
+	      xTrapezoid    *traps)
+{
+    pixman_image_t *src, *dst;
+    int src_xoff, src_yoff;
+    int dst_xoff, dst_yoff;
+
+    if (ntrap == 0)
+	return;
+    
+    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
+    dst = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+
+    if (src && dst)
+    {
+	pixman_format_code_t format;
+	int x_dst, y_dst;
+	int i;
+
+	x_dst = traps[0].left.p1.x >> 16;
+	y_dst = traps[0].left.p1.y >> 16;
+	    
+	if (!maskFormat)
+	{
+	    if (pDst->polyEdge == PolyEdgeSharp)
+		format = PIXMAN_a1;
+	    else
+		format = PIXMAN_a8;
+
+	    for (i = 0; i < ntrap; ++i)
+	    {
+		pixman_composite_trapezoids (op, src, dst, format,
+					     xSrc + src_xoff,
+					     ySrc + src_yoff,
+					     x_dst + dst_xoff,
+					     y_dst + dst_yoff,
+					     1, (pixman_trapezoid_t *)traps++);
+	    }
+	}
+	else
+	{
+	    switch (PICT_FORMAT_A (maskFormat->format))
+	    {
+	    case 1:
+		format = PIXMAN_a1;
+		break;
+
+	    case 4:
+		format = PIXMAN_a4;
+		break;
+
+	    default:
+	    case 8:
+		format = PIXMAN_a8;
+		break;
+	    }
+
+	    pixman_composite_trapezoids (op, src, dst, format,
+					 xSrc + src_xoff,
+					 ySrc + src_yoff,
+					 x_dst + dst_xoff,
+					 y_dst + dst_yoff,
+					 ntrap, (pixman_trapezoid_t *)traps);
+	}
+    }
+
+    free_pixman_pict (pSrc, src);
+    free_pixman_pict (pDst, dst);
+}
diff --git a/render/mipict.c b/render/mipict.c
index de5eea6..46b45b5 100644
--- a/render/mipict.c
+++ b/render/mipict.c
@@ -631,7 +631,7 @@ miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     ps->Composite	= 0;			/* requires DDX support */
     ps->Glyphs		= miGlyphs;
     ps->CompositeRects	= miCompositeRects;
-    ps->Trapezoids	= miTrapezoids;
+    ps->Trapezoids	= 0;
     ps->Triangles	= miTriangles;
     ps->TriStrip	= miTriStrip;
     ps->TriFan		= miTriFan;
diff --git a/render/mipict.h b/render/mipict.h
index eb6b664..be7b20b 100644
--- a/render/mipict.h
+++ b/render/mipict.h
@@ -146,16 +146,6 @@ extern _X_EXPORT void
 miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box);
 
 extern _X_EXPORT void
-miTrapezoids (CARD8	    op,
-	      PicturePtr    pSrc,
-	      PicturePtr    pDst,
-	      PictFormatPtr maskFormat,
-	      INT16	    xSrc,
-	      INT16	    ySrc,
-	      int	    ntrap,
-	      xTrapezoid    *traps);
-
-extern _X_EXPORT void
 miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds);
     
 extern _X_EXPORT void
diff --git a/render/mitrap.c b/render/mitrap.c
index 8bdc8a8..1f09a1e 100644
--- a/render/mitrap.c
+++ b/render/mitrap.c
@@ -126,64 +126,3 @@ miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box)
 	    box->x2 = x2;
     }
 }
-
-void
-miTrapezoids (CARD8	    op,
-	      PicturePtr    pSrc,
-	      PicturePtr    pDst,
-	      PictFormatPtr maskFormat,
-	      INT16	    xSrc,
-	      INT16	    ySrc,
-	      int	    ntrap,
-	      xTrapezoid    *traps)
-{
-    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
-    PictureScreenPtr    ps = GetPictureScreen(pScreen);
-
-    /*
-     * Check for solid alpha add
-     */
-    if (op == PictOpAdd && miIsSolidAlpha (pSrc))
-    {
-	for (; ntrap; ntrap--, traps++)
-	    (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
-    } 
-    else if (maskFormat)
-    {
-	PicturePtr	pPicture;
-	BoxRec		bounds;
-	INT16		xDst, yDst;
-	INT16		xRel, yRel;
-	
-	xDst = traps[0].left.p1.x >> 16;
-	yDst = traps[0].left.p1.y >> 16;
-
-	miTrapezoidBounds (ntrap, traps, &bounds);
-	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
-	    return;
-	pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
-					 bounds.x2 - bounds.x1,
-					 bounds.y2 - bounds.y1);
-	if (!pPicture)
-	    return;
-	for (; ntrap; ntrap--, traps++)
-	    (*ps->RasterizeTrapezoid) (pPicture, traps, 
-				       -bounds.x1, -bounds.y1);
-	xRel = bounds.x1 + xSrc - xDst;
-	yRel = bounds.y1 + ySrc - yDst;
-	CompositePicture (op, pSrc, pPicture, pDst,
-			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
-			  bounds.x2 - bounds.x1,
-			  bounds.y2 - bounds.y1);
-	FreePicture (pPicture, 0);
-    }
-    else
-    {
-	if (pDst->polyEdge == PolyEdgeSharp)
-	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
-	else
-	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
-	for (; ntrap; ntrap--, traps++)
-	    miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
-    }
-}
commit 197df069a4037d6faa2723c31ffba09c95d71166
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Wed Feb 23 10:36:57 2011 -0500

    Require pixman 0.21.6
    
    The following patches need pixman_composite_trapezoids() and
    pixman_add_triangles().
    
    Signed-off-by: Soren Sandmann <ssp at redhat.com>

diff --git a/configure.ac b/configure.ac
index 85d5c98..f1bfbde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -807,7 +807,7 @@ LIBGLIB="glib-2.0 >= 2.16"
 LIBUDEV="libudev >= 143"
 LIBSELINUX="libselinux >= 2.0.86"
 LIBDBUS="dbus-1 >= 1.0"
-LIBPIXMAN="pixman-1 >= 0.15.20"
+LIBPIXMAN="pixman-1 >= 0.21.6"
 
 dnl Pixman is always required, but we separate it out so we can link
 dnl specific modules against it
commit 9d23459415b84606ee4f38bb2d19054c432c8552
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 25 11:08:19 2011 +1000

    dix: release all buttons and keys before reattaching a device (#34182)
    
    Testcase:
      xinput float <keyboard name>
    
    results in the keyboard's enter key being repeated as the device is detached
    while the key is still physically down. To avoid this, release all keys and
    buttons before reattaching the device.
    
    X.Org Bug 34182 <http://bugs.freedesktop.org/show_bug.cgi?id=34182>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Fernando Carrijo <fcarrijo at freedesktop.org>

diff --git a/dix/devices.c b/dix/devices.c
index 6c0dc42..b73fb29 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2376,6 +2376,46 @@ RecalculateMasterButtons(DeviceIntPtr slave)
 }
 
 /**
+ * Generate release events for all keys/button currently down on this
+ * device.
+ */
+static void
+ReleaseButtonsAndKeys(DeviceIntPtr dev)
+{
+    EventListPtr        eventlist = InitEventList(GetMaximumEventsNum());
+    ButtonClassPtr      b = dev->button;
+    KeyClassPtr         k = dev->key;
+    int                 i, j, nevents;
+
+    if (!eventlist) /* no release events for you */
+        return;
+
+    /* Release all buttons */
+    for (i = 0; b && i < b->numButtons; i++)
+    {
+        if (BitIsOn(b->down, i))
+        {
+            nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
+            for (j = 0; j < nevents; j++)
+                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
+        }
+    }
+
+    /* Release all keys */
+    for (i = 0; k && i < MAP_LENGTH; i++)
+    {
+        if (BitIsOn(k->down, i))
+        {
+            nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
+            for (j = 0; j < nevents; j++)
+                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
+        }
+    }
+
+    FreeEventList(eventlist, GetMaximumEventsNum());
+}
+
+/**
  * Attach device 'dev' to device 'master'.
  * Client is set to the client that issued the request, or NULL if it comes
  * from some internal automatic pairing.
@@ -2408,6 +2448,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         free(dev->spriteInfo->sprite);
     }
 
+    ReleaseButtonsAndKeys(dev);
+
     oldmaster = dev->u.master;
     dev->u.master = master;
 
commit 816f1f8ffafbfbf0dd31ea86f295987f84151feb
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Feb 22 12:48:04 2011 +1000

    include: document list interface.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/include/list.h b/include/list.h
index 4ce20a8..5933b97 100644
--- a/include/list.h
+++ b/include/list.h
@@ -26,11 +26,102 @@
 #ifndef _LIST_H_
 #define _LIST_H_
 
-/* classic doubly-link circular list */
+/**
+ * @file Classic doubly-link circular list implementation.
+ *
+ * Example:
+ * We need to keep a list of struct foo in the parent struct bar, i.e. what
+ * we want is something like this.
+ *
+ *     struct bar {
+ *          ...
+ *          struct foo *foos; -----> struct foo {}, struct foo {}, struct foo{}
+ *          ...
+ *     }
+ *
+ * We need one list head in bar and a list element in all foos (both are of
+ * data type 'struct list').
+ *
+ *     struct bar {
+ *          ...
+ *          struct list foos;
+ *          ...
+ *     }
+ *
+ *     struct foo {
+ *          ...
+ *          struct list entry;
+ *          ...
+ *     }
+ *
+ * Now we initialize the list head:
+ *
+ *     struct bar bar;
+ *     ...
+ *     list_init(&bar.foos);
+ *
+ * Then we create the first element and add it to this list:
+ *
+ *     struct foo *foo = malloc(...);
+ *     ....
+ *     list_add(&foo->entry, &bar.foos);
+ *
+ * Repeat the above for each element you want to add to the list. Deleting
+ * works with the element itself.
+ *      list_del(&foo->entry);
+ *      free(foo);
+ *
+ * Note: calling list_del(&bar.foos) will set bar.foos to an empty
+ * list again.
+ *
+ * Looping through the list requires a 'struct foo' as iterator and the
+ * name of the field the subnodes use.
+ *
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar.foos, entry) {
+ *      if (iterator->something == ...)
+ *             ...
+ * }
+ *
+ * Note: You must not call list_del() on the iterator if you continue the
+ * loop. You need to run the safe for-each loop instead:
+ *
+ * struct foo *iterator, *next;
+ * list_for_each_entry_safe(iterator, next, &bar.foos, entry) {
+ *      if (...)
+ *              list_del(&iterator->entry);
+ * }
+ *
+ */
+
+/**
+ * The linkage struct for list nodes. This struct must be part of your
+ * to-be-linked struct.
+ *
+ * Example:
+ * struct foo {
+ *      int a;
+ *      void *b;
+ *      struct list *mylist;
+ * }
+ *
+ * Position and name of the struct list field is irrelevant.
+ * There are no requirements that elements of a list are of the same type.
+ * There are no requirements for a list head, any struct list can be a list
+ * head.
+ */
 struct list {
     struct list *next, *prev;
 };
 
+/**
+ * Initialize the list as an empty list.
+ *
+ * Example:
+ * list_init(&foo->mylist);
+ *
+ * @param The list to initialized.
+ */
 static void
 list_init(struct list *list)
 {
@@ -48,6 +139,20 @@ __list_add(struct list *entry,
     prev->next = entry;
 }
 
+/**
+ * Insert a new element after the given list head.
+ * The list changes from:
+ *      head → some element → ...
+ * to
+ *      head → new element → older element → ...
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add(&newfoo->mylist, &foo->mylist);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
 static inline void
 list_add(struct list *entry, struct list *head)
 {
@@ -61,6 +166,20 @@ __list_del(struct list *prev, struct list *next)
     prev->next = next;
 }
 
+/**
+ * Remove the element from the list it is in. Using this function will reset
+ * the pointers to/from this element so it is removed from the list. It does
+ * NOT free the element itself or manipulate it otherwise.
+ *
+ * Using list_del on a pure list head (like in the example at the top of
+ * this file) will NOT remove the first element from
+ * the list but rather reset the list as empty list.
+ *
+ * Example:
+ * list_del(&newfoo->mylist);
+ *
+ * @param entry The element to remove.
+ */
 static inline void
 list_del(struct list *entry)
 {
@@ -68,32 +187,91 @@ list_del(struct list *entry)
     list_init(entry);
 }
 
+/**
+ * Check if the list is empty.
+ *
+ * Example:
+ * list_is_empty(&foo->mylist);
+ *
+ * @return True if the list contains one or more elements or False otherwise.
+ */
 static inline Bool
 list_is_empty(struct list *head)
 {
     return head->next == head;
 }
 
+/**
+ * Returns a pointer to the container of this list element.
+ *
+ * Example:
+ * struct foo* f;
+ * f = container_of(&foo->mylist, struct foo, mylist);
+ * assert(f == foo);
+ *
+ * @param ptr Pointer to the struct list.
+ * @param type Data type of the list element.
+ * @param member Member name of the struct list field in the list element.
+ * @return A pointer to the data struct containing the list head.
+ */
 #ifndef container_of
 #define container_of(ptr, type, member) \
     (type *)((char *)(ptr) - (char *) &((type *)0)->member)
 #endif
 
+/**
+ * Alias of container_of
+ */
 #define list_entry(ptr, type, member) \
     container_of(ptr, type, member)
 
+/**
+ * Retrieve the first list entry for the given list pointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_first_entry(&foo->mylist, struct foo, mylist);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list field in the list element.
+ * @return A pointer to the first list element.
+ */
 #define list_first_entry(ptr, type, member) \
     list_entry((ptr)->next, type, member)
 
 #define __container_of(ptr, sample, member)				\
     (void *)((char *)(ptr)						\
 	     - ((char *)&(sample)->member - (char *)(sample)))
-
+/**
+ * Loop through the list given by head and set pos to struct in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &foo->mylist, mylist) {
+ *      [modify iterator]
+ * }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param pos Iterator variable of the type of the list elements.
+ * @param head List head
+ * @param member Member name of the struct list in the list elements.
+ *
+ */
 #define list_for_each_entry(pos, head, member)				\
     for (pos = __container_of((head)->next, pos, member);		\
 	 &pos->member != (head);					\
 	 pos = __container_of(pos->member.next, pos, member))
 
+/**
+ * Loop through the list, keeping a backup pointer to the element. This
+ * macro allows for the deletion of a list element while looping through the
+ * list.
+ *
+ * See list_for_each_entry for more details.
+ */
 #define list_for_each_entry_safe(pos, tmp, head, member)		\
     for (pos = __container_of((head)->next, pos, member),		\
 	 tmp = __container_of(pos->member.next, pos, member);		\
commit 579ee8f5d84c3a523b7b3e3941eabb226d1d19e2
Merge: b636893... 17265cc...
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 23 08:44:42 2011 +1000

    Merge branch 'mi-cleanup' into next

commit b636893137da1695e235e3a9354bfd9243fdddc2
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 22 13:43:28 2011 +0000

    Input: Don't freeze unrelated devices in DeliverGrabbedEvent
    
    When delivering an event to a device grabbed with SyncBoth,
    DeliverGrabbedEvent walks the device tree looking for associated devices
    to freeze them.  Unfortunately, it froze all devices instead of just the
    paired device, and the previous fix in 4fbadc8b17237f3c would still break
    if the same client had a non-SyncBoth grab on another unrelated master
    device.
    
    Fix this by completely ignoring devices that aren't our paired device.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 2723f53..de803f6 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3904,16 +3904,15 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
 	switch (grabinfo->sync.state)
 	{
 	case FREEZE_BOTH_NEXT_EVENT:
-	    for (dev = inputInfo.devices; dev; dev = dev->next)
+	    dev = GetPairedDevice(thisDev);
+	    if (dev)
 	    {
-		if (dev == thisDev)
-		    continue;
 		FreezeThaw(dev, TRUE);
 		if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
 		    (CLIENT_BITS(grab->resource) ==
 		     CLIENT_BITS(dev->deviceGrab.grab->resource)))
 		    dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
-		else if (GetPairedDevice(thisDev) == dev)
+		else
                     dev->deviceGrab.sync.other = grab;
 	    }
 	    /* fall through */
commit 17265ccb027e3f956bf7409106174f44621d1cb8
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 12:28:43 2011 +1000

    Move master/lastSlave out of the union into separate fields.
    
    The removal of the double-use will cause some suble bugs as some conditions
    to check for the dev->u.master case were broken and also evaluated as true
    if lastSlave was set (instead of master).
    
    Also breaks the input ABI.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/devices.c b/dix/devices.c
index 058f32b..8fb06bb 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -457,8 +457,8 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
     {
         for (other = inputInfo.devices; other; other = other->next)
         {
-	    if (IsMaster(other) && other->u.lastSlave == dev)
-		other->u.lastSlave = NULL;
+	    if (IsMaster(other) && other->lastSlave == dev)
+		other->lastSlave = NULL;
 	}
     }
 
@@ -988,7 +988,7 @@ CloseDownDevices(void)
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
         if (!IsMaster(dev) && !IsFloating(dev))
-            dev->u.master = NULL;
+            dev->master = NULL;
     }
 
     CloseDeviceList(&inputInfo.devices);
@@ -2486,7 +2486,7 @@ GetMaster(DeviceIntPtr dev, int which)
     if (IsMaster(dev))
         master = dev;
     else
-        master = dev->u.master;
+        master = dev->master;
 
     if (master && which != MASTER_ATTACHED)
     {
@@ -2541,7 +2541,7 @@ AllocDevicePair (ClientPtr client, char* name,
     pointer->coreEvents = TRUE;
     pointer->spriteInfo->spriteOwner = TRUE;
 
-    pointer->u.lastSlave = NULL;
+    pointer->lastSlave = NULL;
     pointer->last.slave = NULL;
     pointer->type = (master) ? MASTER_POINTER : SLAVE;
 
@@ -2567,7 +2567,7 @@ AllocDevicePair (ClientPtr client, char* name,
     keyboard->coreEvents = TRUE;
     keyboard->spriteInfo->spriteOwner = FALSE;
 
-    keyboard->u.lastSlave = NULL;
+    keyboard->lastSlave = NULL;
     keyboard->last.slave = NULL;
     keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
 
diff --git a/dix/events.c b/dix/events.c
index 8b3bfb7..f39d8a9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3244,8 +3244,8 @@ ProcWarpPointer(ClientPtr client)
 	}
     }
 
-    if (dev->u.lastSlave)
-        dev = dev->u.lastSlave;
+    if (dev->lastSlave)
+        dev = dev->lastSlave;
     pSprite = dev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
diff --git a/dix/inpututils.c b/dix/inpututils.c
index abeabf2..077ffce 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -273,10 +273,10 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
                     do_modmap_change(client, tmp, modmap);
         }
     }
-    else if (!IsFloating(dev) && GetMaster(dev, MASTER_KEYBOARD)->u.lastSlave == dev) {
+    else if (!IsFloating(dev) && GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) {
         /* If this fails, expect the results to be weird. */
-        if (check_modmap_change(client, dev->u.master, modmap))
-            do_modmap_change(client, dev->u.master, modmap);
+        if (check_modmap_change(client, dev->master, modmap))
+            do_modmap_change(client, dev->master, modmap);
     }
 
     return Success;
diff --git a/include/inputstr.h b/include/inputstr.h
index 58d318f..4c67e3d 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -530,10 +530,8 @@ typedef struct _DeviceIntRec {
     PrivateRec		*devPrivates;
     DeviceUnwrapProc    unwrapProc;
     SpriteInfoPtr       spriteInfo;
-    union {
-        DeviceIntPtr        master;     /* master device */
-        DeviceIntPtr        lastSlave;  /* last slave device used */
-    } u;
+    DeviceIntPtr        master;     /* master device */
+    DeviceIntPtr        lastSlave;  /* last slave device used */
 
     /* last valuator values recorded, not posted to client;
      * for slave devices, valuators is in device coordinates
diff --git a/mi/mieq.c b/mi/mieq.c
index a3e6085..08a0c87 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -402,7 +402,7 @@ mieqProcessDeviceEvent(DeviceIntPtr dev,
     master = CopyGetMasterEvent(dev, event, &mevent);
 
     if (master)
-        master->u.lastSlave = dev;
+        master->lastSlave = dev;
 
     /* If someone's registered a custom event handler, let them
      * steal it. */
diff --git a/test/xi2/protocol-xiquerypointer.c b/test/xi2/protocol-xiquerypointer.c
index 810c615..a42d595 100644
--- a/test/xi2/protocol-xiquerypointer.c
+++ b/test/xi2/protocol-xiquerypointer.c
@@ -185,7 +185,7 @@ static void test_XIQueryPointer(void)
     request_XIQueryPointer(&client_request, &request, BadDevice);
 
     test_data.dev = devices.mouse;
-    devices.mouse->u.master = NULL; /* Float, kind-of */
+    devices.mouse->master = NULL; /* Float, kind-of */
     request.deviceid = devices.mouse->id;
     request_XIQueryPointer(&client_request, &request, Success);
 
diff --git a/test/xi2/protocol-xiwarppointer.c b/test/xi2/protocol-xiwarppointer.c
index 4f8860e..75b7617 100644
--- a/test/xi2/protocol-xiwarppointer.c
+++ b/test/xi2/protocol-xiwarppointer.c
@@ -145,7 +145,7 @@ static void test_XIWarpPointer(void)
     request.deviceid = devices.kbd->id;
     request_XIWarpPointer(&client_request, &request, BadDevice);
 
-    devices.mouse->u.master = NULL; /* Float, kind-of */
+    devices.mouse->master = NULL; /* Float, kind-of */
     request.deviceid = devices.mouse->id;
     request_XIWarpPointer(&client_request, &request, Success);
 
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 2241753..1583159 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5885,7 +5885,7 @@ ProcXkbGetKbdByName(ClientPtr client)
 
 	if (!IsMaster(dev)) {
 	    DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
-	    if (master && master->u.lastSlave == dev) {
+	    if (master && master->lastSlave == dev) {
 		XkbCopyDeviceKeymap(master, dev);
 		XkbSendNewKeyboardNotify(dev,&nkn);
 	    }
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index eda409c..65c678a 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1365,7 +1365,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, Valuat
 
     if (IsMaster(dev)) {
         mpointer = GetMaster(dev, MASTER_POINTER);
-        lastSlave = mpointer->u.lastSlave;
+        lastSlave = mpointer->lastSlave;
         ptr = GetXTestDevice(mpointer);
     } else if (IsFloating(dev))
         ptr = dev;
commit 77113dd3eef03dd65b556b672d976817b3f4542e
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:45:29 2011 +1000

    input: Change a bunch of direct dev->u.master accesses to use GetMaster()
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 0df6579..7368960 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -716,7 +716,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
     if (IsFloating(slave))
         return; /* set floating since the event */
 
-    if (slave->u.master->id != dce->masterid)
+    if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
         return; /* not our slave anymore, don't care */
 
     /* FIXME: we probably need to send a DCE for the new slave now */
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index b9cdedf..6683f6a 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -282,12 +282,12 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
         for (attached = inputInfo.devices; attached; attached = attached->next)
         {
             if (!IsMaster(attached)) {
-                if (attached->u.master == ptr)
+                if (GetMaster(attached, MASTER_ATTACHED) == ptr)
                 {
                     AttachDevice(client, attached, newptr);
                     flags[attached->id] |= XISlaveAttached;
                 }
-                if (attached->u.master == keybd)
+                if (GetMaster(attached, MASTER_ATTACHED) == keybd)
                 {
                     AttachDevice(client, attached, newkeybd);
                     flags[attached->id] |= XISlaveAttached;
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index 3cad8d7..8b54211 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -375,7 +375,7 @@ SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
 
 int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
 {
-    DeviceIntPtr master = dev->u.master;
+    DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
     int use;
 
     if (IsMaster(dev))
diff --git a/dix/devices.c b/dix/devices.c
index f7018d0..058f32b 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -446,7 +446,7 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
     {
         for (other = inputInfo.devices; other; other = other->next)
         {
-            if (other->u.master == dev)
+            if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev)
             {
                 AttachDevice(NULL, other, NULL);
                 flags[other->id] |= XISlaveDetached;
@@ -2327,7 +2327,7 @@ RecalculateMasterButtons(DeviceIntPtr slave)
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
         if (IsMaster(dev) ||
-            dev->u.master != master ||
+            GetMaster(dev, MASTER_ATTACHED) != master ||
             !dev->button)
             continue;
 
@@ -2408,8 +2408,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         free(dev->spriteInfo->sprite);
     }
 
-    oldmaster = dev->u.master;
-    dev->u.master = master;
+    oldmaster = GetMaster(dev, MASTER_ATTACHED);
+    dev->master = master;
 
     /* If device is set to floating, we need to create a sprite for it,
      * otherwise things go bad. However, we don't want to render the cursor,
@@ -2460,7 +2460,7 @@ DeviceIntPtr
 GetPairedDevice(DeviceIntPtr dev)
 {
     if (!IsMaster(dev) && !IsFloating(dev))
-        dev = dev->u.master;
+        dev = GetMaster(dev, MASTER_ATTACHED);
 
     return dev->spriteInfo->paired;
 }
diff --git a/dix/events.c b/dix/events.c
index b0e52f1..8b3bfb7 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1407,7 +1407,7 @@ DetachFromMaster(DeviceIntPtr dev)
     if (!IsFloating(dev))
         return;
 
-    dev->saved_master_id = dev->u.master->id;
+    dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
 
     AttachDevice(NULL, dev, NULL);
 }
@@ -3237,7 +3237,7 @@ ProcWarpPointer(ClientPtr client)
     dev = PickPointer(client);
 
     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
-        if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) {
+        if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
 	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
 	    if (rc != Success)
 		return rc;
diff --git a/mi/mieq.c b/mi/mieq.c
index 6853103..a3e6085 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -321,6 +321,7 @@ CopyGetMasterEvent(DeviceIntPtr sdev,
     DeviceIntPtr mdev;
     int len = original->any.length;
     int type = original->any.type;
+    int mtype; /* which master type? */
 
     CHECKEVENT(original);
 
@@ -337,20 +338,21 @@ CopyGetMasterEvent(DeviceIntPtr sdev,
     {
         case ET_KeyPress:
         case ET_KeyRelease:
-            mdev = GetMaster(sdev, MASTER_KEYBOARD);
+            mtype = MASTER_KEYBOARD;
             break;
         case ET_ButtonPress:
         case ET_ButtonRelease:
         case ET_Motion:
         case ET_ProximityIn:
         case ET_ProximityOut:
-            mdev = GetMaster(sdev, MASTER_POINTER);
+            mtype = MASTER_POINTER;
             break;
         default:
-            mdev = sdev->u.master;
+            mtype = MASTER_ATTACHED;
             break;
     }
 
+    mdev = GetMaster(sdev, mtype);
     memcpy(copy, original, len);
     ChangeDeviceID(mdev, copy);
     FixUpEventForMaster(mdev, sdev, original, copy);
@@ -466,7 +468,7 @@ mieqProcessInputEvents(void)
         pthread_mutex_unlock(&miEventQueueMutex);
 #endif
 
-        master  = (dev && !IsMaster(dev) && dev->u.master) ? dev->u.master : NULL;
+        master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL;
 
         if (screenIsSaved == SCREEN_SAVER_ON)
             dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
commit 2936635698619271a790004480a14285149277cb
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 12:06:56 2011 +1000

    xkb: Fix a check for MASTER_KEYBOARD
    
    And copy into the master keyboard, not just the directly attached device.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/xkb/xkb.c b/xkb/xkb.c
index 4557350..2241753 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5883,12 +5883,10 @@ ProcXkbGetKbdByName(ClientPtr client)
 	    nkn.changed|= XkbNKN_GeometryMask;
 	XkbSendNewKeyboardNotify(dev,&nkn);
 
-	if (!IsMaster(dev) && !IsFloating(dev))
-	{
-	    DeviceIntPtr master = dev->u.master;
-	    if (master->u.lastSlave == dev)
-	    {
-		XkbCopyDeviceKeymap(dev->u.master, dev);
+	if (!IsMaster(dev)) {
+	    DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
+	    if (master && master->u.lastSlave == dev) {
+		XkbCopyDeviceKeymap(master, dev);
 		XkbSendNewKeyboardNotify(dev,&nkn);
 	    }
 	}
commit 0ba526deeb4d54ee1a75400291ee7a3673ed4d96
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 12:04:46 2011 +1000

    mi: check for MASTER_POINTER instead of manual checks.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 5b82978..209ea06 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -540,7 +540,7 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
      * VCP, as this may cause a non-HW rendered cursor to be rendered during
      * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
      */
-    if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
+    if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
         && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
 	pPointer->devx = x;
commit 52c13896ce9a1e178d4eeed15f68020947cc20ed
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:57:06 2011 +1000

    mi: update macro to search for MASTER_POINTER
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/midispcur.c b/mi/midispcur.c
index 48feb88..9b3e87a 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -76,7 +76,7 @@ typedef struct {
 #define miGetDCDevice(dev, screen) \
  ((DevHasCursor(dev)) ? \
   (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
-  (miDCBufferPtr)dixLookupScreenPrivate(&dev->u.master->devPrivates, miDCDeviceKey, screen))
+  (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
 
 /* 
  * The core pointer buffer will point to the index of the virtual core pointer
commit d270f12a3e44f4ea01f176a86783e8cd4c59ddf7
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:55:51 2011 +1000

    xfree86:  update GetMaster check for the VCP.
    
    Same result, but now also triggers on slave keyboards that send pointer
    events.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index ec781aa..24c91cc 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -317,8 +317,7 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 
     /* only update for VCP, otherwise we get cursor jumps when removing a
        sprite. The second cursor is never HW rendered anyway. */
-    if (pDev == inputInfo.pointer ||
-        (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
+    if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)
     {
 	pCurs->refcnt++;
 	if (ScreenPriv->CurrentCursor)
@@ -386,8 +385,7 @@ xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 
     /* only update coordinate state for first sprite, otherwise we get jumps
        when removing a sprite. The second sprite is never HW rendered anyway */
-    if (pDev == inputInfo.pointer ||
-	(!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
+    if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)
     {
 	ScreenPriv->x = x;
 	ScreenPriv->y = y;
commit ce7f79efd588899f01c74f95c2f58d6dd6d816cd
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:53:06 2011 +1000

    dix: fix a master device access in change_modmap.
    
    We need to check if our master keyboard is the given device since we may be
    a pointer with keys and thus need to change the modmap too.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/inpututils.c b/dix/inpututils.c
index 8b7b035..abeabf2 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -268,12 +268,12 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
     /* Change any attached masters/slaves. */
     if (IsMaster(dev)) {
         for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
-            if (!IsMaster(tmp) && tmp->u.master == dev)
+            if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev)
                 if (check_modmap_change_slave(client, dev, tmp, modmap))
                     do_modmap_change(client, tmp, modmap);
         }
     }
-    else if (!IsFloating(dev) && dev->u.master->u.lastSlave == dev) {
+    else if (!IsFloating(dev) && GetMaster(dev, MASTER_KEYBOARD)->u.lastSlave == dev) {
         /* If this fails, expect the results to be weird. */
         if (check_modmap_change(client, dev->u.master, modmap))
             do_modmap_change(client, dev->u.master, modmap);
commit e1ac704185dee31b427a46cd41a00ef7a28b4129
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:42:09 2011 +1000

    dix: fix up a master check in ChangeKeyboardMapping handling.
    
    We don't just care about the directly attached master, we care about the
    master keyboard.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/devices.c b/dix/devices.c
index 8be1903..f7018d0 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1664,7 +1664,7 @@ ProcChangeKeyboardMapping(ClientPtr client)
                           stuff->keyCodes, NULL, client);
 
     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
-        if (IsMaster(tmp) || tmp->u.master != pDev)
+        if (IsMaster(tmp) || GetMaster(tmp, MASTER_KEYBOARD) != pDev)
             continue;
         if (!tmp->key)
             continue;
commit febce8cb814df46018f6ae1e6a9daea019b8ad0a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:32:28 2011 +1000

    Xi: replace a direct master access with GetMaster()
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index ea9daa9..0df6579 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -869,7 +869,7 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
              * event being delivered through the slave first
              */
             for (sd = inputInfo.devices; sd; sd = sd->next) {
-                if (IsMaster(sd) || sd->u.master != device)
+                if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
                     continue;
                 if (!sd->button)
                     continue;
commit df6559237a2d641b2fc38d14975beab9bae0d971
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 18 11:30:10 2011 +1000

    dix: add MASTER_ATTACHED as allowed type for GetMaster().
    
    In some cases, we don't know/care whether we want the master pointer or keyboard
    for a device. Add a new type MASTER_ATTACHED to return the master this
    device is attached to.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/devices.c b/dix/devices.c
index a3367f7..8be1903 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2473,7 +2473,10 @@ GetPairedDevice(DeviceIntPtr dev)
  * returned master is either the device itself or the paired master device.
  * If dev is a floating slave device, NULL is returned.
  *
- * @type ::MASTER_KEYBOARD or ::MASTER_POINTER
+ * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED
+ * @return The requested master device. In the case of MASTER_ATTACHED, this
+ * is the directly attached master to this device, regardless of the type.
+ * Otherwise, it is either the master keyboard or pointer for this device.
  */
 DeviceIntPtr
 GetMaster(DeviceIntPtr dev, int which)
@@ -2485,7 +2488,7 @@ GetMaster(DeviceIntPtr dev, int which)
     else
         master = dev->u.master;
 
-    if (master)
+    if (master && which != MASTER_ATTACHED)
     {
         if (which == MASTER_KEYBOARD)
         {
diff --git a/include/inputstr.h b/include/inputstr.h
index b74ee04..58d318f 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -493,6 +493,7 @@ typedef struct _SpriteInfoRec {
 #define MASTER_POINTER          1
 #define MASTER_KEYBOARD         2
 #define SLAVE                   3
+#define MASTER_ATTACHED         4  /* special type for GetMaster */
 
 typedef struct _DeviceIntRec {
     DeviceRec	public;
commit dc57f89959e549403f8488eb9f23425bd7118b22
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 12:47:37 2011 +1000

    Switch to use IsFloating()
    
    This is not a straightforward search/replacement due to a long-standing
    issue.
    
    dev->u.master is the same field as dev->u.lastSlave. Thus, if dev is a master
    device, a check for dev->u.master may give us false positives and false
    negatives.
    The switch to IsFloating() spells out these cases and modifies the
    conditions accordingly to cover both cases.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b39e202..ea9daa9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -713,7 +713,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
     if (IsMaster(slave))
         return;
 
-    if (!slave->u.master)
+    if (IsFloating(slave))
         return; /* set floating since the event */
 
     if (slave->u.master->id != dce->masterid)
@@ -1009,7 +1009,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
     b = device->button;
     k = device->key;
 
-    if (IsMaster(device) || !device->u.master)
+    if (IsMaster(device) || IsFloating(device))
         CheckMotion(event, device);
 
     switch (event->type)
@@ -1226,7 +1226,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
     DeviceIntPtr mouse;
     int btlen, len, i;
 
-    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
+    mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
 
     /* XI 2 event */
     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index e99b6e5..8663d12 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -162,10 +162,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
     if (!modifiers_failed)
         return BadAlloc;
 
-    if (!IsMaster(dev) && dev->u.master)
-        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
-    else
-        mod_dev = dev;
+    mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
 
     for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
     {
@@ -280,10 +277,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
     if (rc != Success)
         return rc;
 
-    if (!IsMaster(dev) && dev->u.master)
-        mod_dev = GetMaster(dev, MASTER_KEYBOARD);
-    else
-        mod_dev = dev;
+    mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
 
     tempGrab.resource = client->clientAsMask;
     tempGrab.device = dev;
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index fdd2c05..3cad8d7 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -383,7 +383,7 @@ int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
         DeviceIntPtr paired = GetPairedDevice(dev);
         use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
         *attachment = (paired ? paired->id : 0);
-    } else if (master)
+    } else if (!IsFloating(dev))
     {
         use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
         *attachment = master->id;
diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c
index 8df958e..5131799 100644
--- a/Xi/xiquerypointer.c
+++ b/Xi/xiquerypointer.c
@@ -93,7 +93,7 @@ ProcXIQueryPointer(ClientPtr client)
     }
 
     if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
-        (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */
+        (!IsMaster(pDev) && !IsFloating(pDev))) /* no attached devices */
     {
         client->errorValue = stuff->deviceid;
         return BadDevice;
diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c
index c01b115..a463ab9 100644
--- a/Xi/xiwarppointer.c
+++ b/Xi/xiwarppointer.c
@@ -97,7 +97,7 @@ ProcXIWarpPointer(ClientPtr client)
         return rc;
     }
 
-    if ((!IsMaster(pDev) && pDev->u.master) ||
+    if ((!IsMaster(pDev) && !IsFloating(pDev)) ||
         (IsMaster(pDev) && !IsPointerDevice(pDev)))
     {
         client->errorValue = stuff->deviceid;
diff --git a/dix/devices.c b/dix/devices.c
index 6c0dc42..a3367f7 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -987,7 +987,7 @@ CloseDownDevices(void)
      */
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-        if (!IsMaster(dev) && dev->u.master)
+        if (!IsMaster(dev) && !IsFloating(dev))
             dev->u.master = NULL;
     }
 
@@ -2397,11 +2397,11 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         return BadDevice;
 
     /* set from floating to floating? */
-    if (!dev->u.master && !master && dev->enabled)
+    if (IsFloating(dev) && !master && dev->enabled)
         return Success;
 
     /* free the existing sprite. */
-    if (!dev->u.master && dev->spriteInfo->paired == dev)
+    if (IsFloating(dev) && dev->spriteInfo->paired == dev)
     {
         screen = miPointerGetScreen(dev);
         screen->DeviceCursorCleanup(dev, screen);
@@ -2459,7 +2459,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 DeviceIntPtr
 GetPairedDevice(DeviceIntPtr dev)
 {
-    if (!IsMaster(dev) && dev->u.master)
+    if (!IsMaster(dev) && !IsFloating(dev))
         dev = dev->u.master;
 
     return dev->spriteInfo->paired;
diff --git a/dix/events.c b/dix/events.c
index f6d92cf..b0e52f1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1404,7 +1404,7 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 static void
 DetachFromMaster(DeviceIntPtr dev)
 {
-    if (!dev->u.master)
+    if (!IsFloating(dev))
         return;
 
     dev->saved_master_id = dev->u.master->id;
@@ -2806,7 +2806,7 @@ WindowsRestructured(void)
     DeviceIntPtr pDev = inputInfo.devices;
     while(pDev)
     {
-        if (IsMaster(pDev) || !pDev->u.master)
+        if (IsMaster(pDev) || IsFloating(pDev))
             CheckMotion(NULL, pDev);
         pDev = pDev->next;
     }
@@ -3401,7 +3401,7 @@ CheckPassiveGrabsOnWindow(
              * attached master keyboard. Since the slave may have been
              * reattached after the grab, the modifier device may not be the
              * same. */
-            if (!IsMaster(grab->device) && device->u.master)
+            if (!IsMaster(grab->device) && !IsFloating(device))
                 gdev = GetMaster(device, MASTER_KEYBOARD);
         }
 
diff --git a/dix/getevents.c b/dix/getevents.c
index 60282a8..5b8e379 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -767,7 +767,7 @@ moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
     /* if attached, clip both x and y to the defined limits (usually
      * co-ord space limit). If it is attached, we need x/y to go over the
      * limits to be able to change screens. */
-    if(dev->u.master && dev->valuator) {
+    if(dev->valuator && IsMaster(dev) || !IsFloating(dev)) {
         if (valuator_get_mode(dev, 0) == Absolute)
             clipAxis(dev, 0, x);
         if (valuator_get_mode(dev, 1) == Absolute)
@@ -865,7 +865,7 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
      * to the current screen. */
     miPointerSetPosition(dev, screenx, screeny);
 
-    if (dev->u.master) {
+    if(!IsMaster(dev) || !IsFloating(dev)) {
         DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
         master->last.valuators[0] = *screenx;
         master->last.valuators[1] = *screeny;
@@ -912,7 +912,7 @@ updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
         return;
 
     updateMotionHistory(dev, ms, mask, dev->last.valuators);
-    if (dev->u.master)
+    if(!IsMaster(dev) || !IsFloating(dev))
     {
         DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
         updateMotionHistory(master, ms, mask, dev->last.valuators);
diff --git a/dix/inpututils.c b/dix/inpututils.c
index ef3142c..8b7b035 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -273,7 +273,7 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
                     do_modmap_change(client, tmp, modmap);
         }
     }
-    else if (dev->u.master && dev->u.master->u.lastSlave == dev) {
+    else if (!IsFloating(dev) && dev->u.master->u.lastSlave == dev) {
         /* If this fails, expect the results to be weird. */
         if (check_modmap_change(client, dev->u.master, modmap))
             do_modmap_change(client, dev->u.master, modmap);
diff --git a/mi/mieq.c b/mi/mieq.c
index c0020c3..6853103 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -325,7 +325,7 @@ CopyGetMasterEvent(DeviceIntPtr sdev,
     CHECKEVENT(original);
 
     /* ET_XQuartz has sdev == NULL */
-    if (!sdev || IsMaster(sdev) || !sdev->u.master)
+    if (!sdev || IsMaster(sdev) || IsFloating(sdev))
         return NULL;
 
 #if XFreeXDGA
@@ -410,7 +410,7 @@ mieqProcessDeviceEvent(DeviceIntPtr dev,
         handler(screenNum, event, dev);
         /* Check for the SD's master in case the device got detached
          * during event processing */
-        if (master && dev->u.master)
+        if (master && !IsFloating(dev))
             handler(screenNum, &mevent, master);
     } else
     {
@@ -419,7 +419,7 @@ mieqProcessDeviceEvent(DeviceIntPtr dev,
 
         /* Check for the SD's master in case the device got detached
          * during event processing */
-        if (master && dev->u.master)
+        if (master && !IsFloating(dev))
             master->public.processInputProc(&mevent, master);
     }
 }
diff --git a/mi/mipointer.c b/mi/mipointer.c
index aa0ca6d..5b82978 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -73,7 +73,7 @@ DevPrivateKeyRec miPointerScreenKeyRec;
 DevPrivateKeyRec miPointerPrivKeyRec;
 
 #define MIPOINTER(dev) \
-    ((!IsMaster(dev) && !dev->u.master) ? \
+    (IsFloating(dev) ? \
         (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
         (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
 
@@ -332,7 +332,7 @@ miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
     SetupScreen(pScreen);
 
-    if (!IsMaster(pDev) && pDev->u.master)
+    if (!IsMaster(pDev) && !IsFloating(pDev))
         return;
 
     (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
diff --git a/mi/misprite.c b/mi/misprite.c
index 770951e..b0290af 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -143,7 +143,7 @@ typedef struct {
 #endif
 
 #define MISPRITE(dev) \
-    ((!IsMaster(dev) && !dev->u.master) ? \
+    (IsFloating(dev) ? \
        (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
        (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
 
@@ -766,7 +766,7 @@ miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     miCursorInfoPtr pCursorInfo;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return FALSE;
 
     pCursorInfo = MISPRITE(pDev);
@@ -790,7 +790,7 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
     miCursorInfoPtr     pPointer;
     miSpriteScreenPtr   pScreenPriv;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     pPointer = MISPRITE(pDev);
@@ -848,7 +848,7 @@ miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     CursorPtr pCursor;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     pCursor = MISPRITE(pDev)->pCursor;
@@ -905,7 +905,7 @@ miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
     miCursorInfoPtr     pCursorInfo;
 
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     DamageDrawInternal (pScreen, TRUE);
@@ -944,7 +944,7 @@ miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
     CursorPtr		pCursor;
     miCursorInfoPtr     pCursorInfo;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     DamageDrawInternal (pScreen, TRUE);
@@ -985,7 +985,7 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
     CursorPtr		pCursor;
     miCursorInfoPtr     pCursorInfo;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     DamageDrawInternal (pScreen, TRUE);
@@ -1025,7 +1025,7 @@ miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
     CursorPtr	    pCursor;
     miCursorInfoPtr pCursorInfo;
 
-    if (!IsMaster(pDev) && !pDev->u.master)
+    if (IsFloating(pDev))
         return;
 
     pCursorInfo = MISPRITE(pDev);
diff --git a/xkb/xkb.c b/xkb/xkb.c
index a57139f..4557350 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5883,7 +5883,7 @@ ProcXkbGetKbdByName(ClientPtr client)
 	    nkn.changed|= XkbNKN_GeometryMask;
 	XkbSendNewKeyboardNotify(dev,&nkn);
 
-	if (!IsMaster(dev) && dev->u.master)
+	if (!IsMaster(dev) && !IsFloating(dev))
 	{
 	    DeviceIntPtr master = dev->u.master;
 	    if (master->u.lastSlave == dev)
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 10c38ca..12fe2a1 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -694,7 +694,7 @@ ProcessInputProc backupproc;
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
 DeviceEvent     *event = &ev->device_event;
 
-    dev = (IsMaster(mouse) || mouse->u.master) ? GetMaster(mouse, MASTER_KEYBOARD) : mouse;
+    dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD);
 
     if (dev && dev->key)
     {
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 8d7c124..eda409c 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1367,7 +1367,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, Valuat
         mpointer = GetMaster(dev, MASTER_POINTER);
         lastSlave = mpointer->u.lastSlave;
         ptr = GetXTestDevice(mpointer);
-    } else if (!dev->u.master)
+    } else if (IsFloating(dev))
         ptr = dev;
     else
         return;
@@ -1397,7 +1397,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
     int                 gpe_flags = 0;
 
     /* ignore attached SDs */
-    if (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) != NULL)
+    if (!IsMaster(dev) && !IsFloating(dev))
         return;
 
     if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
@@ -1427,7 +1427,7 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
     if (IsMaster(dev)) {
         DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
         ptr = GetXTestDevice(mpointer);
-    } else if (!dev->u.master)
+    } else if (IsFloating(dev))
         ptr = dev;
     else
         return;
commit e48bf3b6403dde33586ca0e421db61e402525453
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 11:11:57 2011 +1000

    xfree86: replace two inputInfo.pointer uses with device loops.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
index d7ffff4..4663d03 100644
--- a/hw/xfree86/common/xf86RandR.c
+++ b/hw/xfree86/common/xf86RandR.c
@@ -242,11 +242,20 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
     ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
     XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
     DisplayModePtr	    mode;
-    int			    px, py;
+    int			    pos[MAXDEVICES][2];
     Bool		    useVirtual = FALSE;
     Rotation		    oldRotation = randrp->rotation;
+    DeviceIntPtr	    dev;
+    Bool		    view_adjusted = FALSE;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+	if (!IsMaster(dev) && !IsFloating(dev))
+		continue;
+
+	miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]);
+    }
 
-    miPointerGetPosition(inputInfo.pointer, &px, &py);
     for (mode = scrp->modes; ; mode = mode->next)
     {
 	if (mode->HDisplay == pSize->width &&
@@ -303,17 +312,31 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 	}
 	return FALSE;
     }
+
     /*
      * Move the cursor back where it belongs; SwitchMode repositions it
+     * FIXME: duplicated code, see modes/xf86RandR12.c
      */
-    if (pScreen == miPointerCurrentScreen ())
+    for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	px = (px >= pScreen->width ? (pScreen->width - 1) : px);
-	py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+	if (!IsMaster(dev) && !IsFloating(dev))
+		continue;
 
-        xf86SetViewport(pScreen, px, py);
+	if (pScreen == miPointerGetScreen(dev)) {
+	    int px = pos[dev->id][0];
+	    int py = pos[dev->id][1];
 
-        (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
+	    px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+	    py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+
+	    /* Setting the viewpoint makes only sense on one device */
+	    if (!view_adjusted && IsMaster(dev)) {
+		xf86SetViewport(pScreen, px, py);
+		view_adjusted = TRUE;
+	    }
+
+	    (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE);
+	}
     }
 
     return TRUE;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 407bf35..82d180b 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -584,10 +584,12 @@ xf86RandR12SetConfig (ScreenPtr		pScreen,
     ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     DisplayModePtr	mode;
-    int			px, py;
+    int			pos[MAXDEVICES][2];
     Bool		useVirtual = FALSE;
     int			maxX = 0, maxY = 0;
     Rotation		oldRotation = randrp->rotation;
+    DeviceIntPtr	dev;
+    Bool		view_adjusted = FALSE;
 
     randrp->rotation = rotation;
 
@@ -597,7 +599,14 @@ xf86RandR12SetConfig (ScreenPtr		pScreen,
 	randrp->virtualY = scrp->virtualY;
     }
 
-    miPointerGetPosition (inputInfo.pointer, &px, &py);
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+	if (!IsMaster(dev) && !IsFloating(dev))
+		continue;
+
+	miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]);
+    }
+
     for (mode = scrp->modes; ; mode = mode->next)
     {
 	if (randrp->maxX == 0 || randrp->maxY == 0)
@@ -643,15 +652,28 @@ xf86RandR12SetConfig (ScreenPtr		pScreen,
 
     /*
      * Move the cursor back where it belongs; SwitchMode repositions it
+     * FIXME: duplicated code, see modes/xf86RandR12.c
      */
-    if (pScreen == miPointerGetScreen(inputInfo.pointer))
+    for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-        px = (px >= pScreen->width ? (pScreen->width - 1) : px);
-        py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+	if (!IsMaster(dev) && !IsFloating(dev))
+		continue;
 
-	xf86SetViewport(pScreen, px, py);
+	if (pScreen == miPointerGetScreen(dev)) {
+	    int px = pos[dev->id][0];
+	    int py = pos[dev->id][1];
 
-	(*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
+	    px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+	    py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+
+	    /* Setting the viewpoint makes only sense on one device */
+	    if (!view_adjusted && IsMaster(dev)) {
+		xf86SetViewport(pScreen, px, py);
+		view_adjusted = TRUE;
+	    }
+
+	    (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE);
+	}
     }
 
     return TRUE;
commit 703baece7ebd128a6742d0523d5b3ebe65126fa5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 12:19:26 2011 +1000

    dix: Add IsFloating(device) wrapper.
    
    Simplifies check for floating devices.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/events.c b/dix/events.c
index 4826781..f6d92cf 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -328,6 +328,13 @@ IsMaster(DeviceIntPtr dev)
     return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
 }
 
+Bool
+IsFloating(DeviceIntPtr dev)
+{
+    return GetMaster(dev, MASTER_KEYBOARD) == NULL;
+}
+
+
 /**
  * Max event opcode.
  */
diff --git a/include/dix.h b/include/dix.h
index 12e4b59..3f99098 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -570,6 +570,7 @@ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
 extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
 extern Bool IsPointerEvent(InternalEvent *event);
 extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
+extern _X_EXPORT Bool IsFloating(DeviceIntPtr dev);
 
 extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
 extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
commit 77af45ebc3eda32dc534968cab8d5adfb01bd9e3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 12:48:30 2011 +1000

    dix: Simplify retrieving the master device.
    
    GetMaster() returns NULL for floating slaves.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/events.c b/dix/events.c
index 07f8b05..4826781 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4277,7 +4277,7 @@ DeviceEnterLeaveEvent(
         if (BitIsOn(mouse->button->down, i))
             SetBit(&event[1], i);
 
-    kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL;
+    kbd = GetMaster(mouse, MASTER_KEYBOARD);
     if (kbd && kbd->key)
     {
         event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
commit dc32a23890776edf575bf18b3f3c079da6214340
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 15:21:51 2011 +1000

    Fix two incorrect checks for master devices.
    
    These two were sideeffects of lastSlave being in the same field as the
    master. For devices generated by the master device directly, lastSlave was 0
    and the device would (with the old checks) be interpreted as floating.
    
    Add the required checks to safeguard against master devices.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 327873e..b39e202 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -710,6 +710,9 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
     if (rc != Success)
         return; /* Device has disappeared */
 
+    if (IsMaster(slave))
+        return;
+
     if (!slave->u.master)
         return; /* set floating since the event */
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 01da52a..c0020c3 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -325,7 +325,7 @@ CopyGetMasterEvent(DeviceIntPtr sdev,
     CHECKEVENT(original);
 
     /* ET_XQuartz has sdev == NULL */
-    if (!sdev || !sdev->u.master)
+    if (!sdev || IsMaster(sdev) || !sdev->u.master)
         return NULL;
 
 #if XFreeXDGA
commit d63c979c7fe0f2b114b27e73ebe0a706be8840ae
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 15:21:31 2011 +1000

    dix: replace direct master access with GetMaster and temp. device.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/dix/getevents.c b/dix/getevents.c
index 794df42..60282a8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -866,10 +866,11 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
     miPointerSetPosition(dev, screenx, screeny);
 
     if (dev->u.master) {
-        dev->u.master->last.valuators[0] = *screenx;
-        dev->u.master->last.valuators[1] = *screeny;
-        dev->u.master->last.remainder[0] = *screenx_frac;
-        dev->u.master->last.remainder[1] = *screeny_frac;
+        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
+        master->last.valuators[0] = *screenx;
+        master->last.valuators[1] = *screeny;
+        master->last.remainder[0] = *screenx_frac;
+        master->last.remainder[1] = *screeny_frac;
     }
 
     if (dev->valuator)
commit c2a9e0a96983f22f721196513e75a53ea0b86d7e
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 11:41:47 2011 +1000

    mi: simplify a "check for keyboard" condition
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 124f9de..aa0ca6d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -193,8 +193,7 @@ miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
     miPointerPtr pPointer;
 
     /* return for keyboards */
-    if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
-        (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
+    if (!IsPointerDevice(pDev))
             return FALSE;
 
     pPointer = MIPOINTER(pDev);
commit 3a6160b408447ce620140849f962683a5d139cb9
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 11:40:01 2011 +1000

    mi: remove if 0 code.
    
    Note sure why this is in if 0 but it's been that way since 2007.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index a3c26d0..124f9de 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -158,33 +158,8 @@ miPointerInitialize (ScreenPtr                  pScreen,
 static Bool
 miPointerCloseScreen (int index, ScreenPtr pScreen)
 {
-#if 0
-    miPointerPtr pPointer;
-    DeviceIntPtr pDev;
-#endif
-
     SetupScreen(pScreen);
 
-#if 0
-    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
-    {
-        if (DevHasCursor(pDev))
-        {
-            pPointer = MIPOINTER(pDev);
-
-            if (pScreen == pPointer->pScreen)
-                pPointer->pScreen = 0;
-            if (pScreen == pPointer->pSpriteScreen)
-                pPointer->pSpriteScreen = 0;
-        }
-    }
-
-    if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
-        MIPOINTER(inputInfo.pointer)->pScreen = 0;
-    if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
-        MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
-#endif
-
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     free((pointer) pScreenPriv);
     FreeEventList(events, GetMaximumEventsNum());
commit d9987c8c45236bc9cfcaf716f4bfcac2a9d0e7e6
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 11:22:45 2011 +1000

    mi: Add a few comments explaining various cursor move functions.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 5ee456c..a3c26d0 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -23,6 +23,29 @@ used in advertising or otherwise to promote the sale, use or other dealings
 in this Software without prior written authorization from The Open Group.
 */
 
+/**
+ * @file
+ * This file contains functions to move the pointer on the screen and/or
+ * restrict its movement. These functions are divided into two sets:
+ * Screen-specific functions that are used as function pointers from other
+ * parts of the server (and end up heavily wrapped by e.g. animcur and
+ * xfixes):
+ *      miPointerConstrainCursor
+ *      miPointerCursorLimits
+ *      miPointerDisplayCursor
+ *      miPointerRealizeCursor
+ *      miPointerUnrealizeCursor
+ *      miPointerSetCursorPosition
+ *      miRecolorCursor
+ *      miPointerDeviceInitialize
+ *      miPointerDeviceCleanup
+ * If wrapped, these are the last element in the wrapping chain. They may
+ * call into sprite-specific code through further function pointers though.
+ *
+ * The second type of functions are those that are directly called by the
+ * DIX, DDX and some drivers.
+ */
+
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
@@ -126,6 +149,12 @@ miPointerInitialize (ScreenPtr                  pScreen,
     return TRUE;
 }
 
+/**
+ * Destroy screen-specific information.
+ *
+ * @param index Screen index of the screen in screenInfo.screens[]
+ * @param pScreen The actual screen pointer
+ */
 static Bool
 miPointerCloseScreen (int index, ScreenPtr pScreen)
 {
@@ -201,6 +230,15 @@ miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
     return TRUE;
 }
 
+/**
+ * Set up the constraints for the given device. This function does not
+ * actually constrain the cursor but merely copies the given box to the
+ * internal constraint storage.
+ *
+ * @param pDev The device to constrain to the box
+ * @param pBox The rectangle to constrain the cursor to
+ * @param pScreen Used for copying screen confinement
+ */
 static void
 miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
 {
@@ -212,7 +250,17 @@ miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
     pPointer->confined = PointerConfinedToScreen(pDev);
 }
 
-/*ARGSUSED*/
+/**
+ * Should calculate the box for the given cursor, based on screen and the
+ * confinement given. But we assume that whatever box is passed in is valid
+ * anyway.
+ *
+ * @param pDev The device to calculate the cursor limits for
+ * @param pScreen The screen the confinement happens on
+ * @param pCursor The screen the confinement happens on
+ * @param pHotBox The confinement box for the cursor
+ * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
+ */
 static void
 miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
                       BoxPtr pHotBox, BoxPtr pTopLeftBox)
@@ -220,6 +268,27 @@ miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
     *pTopLeftBox = *pHotBox;
 }
 
+/**
+ * Set the device's cursor position to the x/y position on the given screen.
+ * Generates and event if required.
+ *
+ * This function is called from:
+ *    - sprite init code to place onto initial position
+ *    - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
+ *    - during the cursor update path in CheckMotion
+ *    - in the Xinerama part of NewCurrentScreen
+ *    - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
+ *      it's set back to the original pos)
+ *
+ * @param pDev The device to move
+ * @param pScreen The screen the device is on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ * @param generateEvent True if the pointer movement should generate an
+ * event.
+ *
+ * @return TRUE in all cases
+ */
 static Bool
 miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
                            int x, int y, Bool generateEvent)
@@ -236,9 +305,13 @@ miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
     return TRUE;
 }
 
-/* Set up sprite information for the device.
-   This function will be called once for each device after it is initialized
-   in the DIX.
+/**
+ * Set up sprite information for the device.
+ * This function will be called once for each device after it is initialized
+ * in the DIX.
+ *
+ * @param pDev The newly created device
+ * @param pScreen The initial sprite scree.
  */
 static Bool
 miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
@@ -273,8 +346,12 @@ miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
     return TRUE;
 }
 
-/* Clean up after device.
-   This function will be called once before the device is freed in the DIX
+/**
+ * Clean up after device.
+ * This function will be called once before the device is freed in the DIX
+ *
+ * @param pDev The device to be removed from the server
+ * @param pScreen Current screen of the device
  */
 static void
 miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
@@ -290,7 +367,17 @@ miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
 }
 
 
-/* Once signals are ignored, the WarpCursor function can call this */
+/**
+ * Warp the pointer to the given position on the given screen. May generate
+ * an event, depending on whether we're coming from miPointerSetPosition.
+ *
+ * Once signals are ignored, the WarpCursor function can call this
+ *
+ * @param pDev The device to warp
+ * @param pScreen Screen to warp on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
 
 void
 miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
@@ -323,16 +410,11 @@ miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
         UpdateSpriteForScreen (pDev, pScreen) ;
 }
 
-/*
- * Pointer/CursorDisplay interface routines
- */
-
-/*
- * miPointerUpdateSprite
+/**
+ * Syncronize the sprite with the cursor.
  *
- * Syncronize the sprite with the cursor - called from ProcessInputEvents
+ * @param pDev The device to sync
  */
-
 void
 miPointerUpdateSprite (DeviceIntPtr pDev)
 {
@@ -409,6 +491,14 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     }
 }
 
+/**
+ * Set the device to the coordinates on the given screen.
+ *
+ * @param pDev The device to move
+ * @param screen_no Index of the screen to move to
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
 void
 miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 {
@@ -427,12 +517,18 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
         pPointer->limits.y2 = pScreen->height;
 }
 
+/**
+ * @return The current screen of the VCP
+ */
 ScreenPtr
 miPointerCurrentScreen (void)
 {
     return miPointerGetScreen(inputInfo.pointer);
 }
 
+/**
+ * @return The current screen of the given device or NULL.
+ */
 ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
@@ -484,6 +580,18 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
     pPointer->pScreen = pScreen;
 }
 
+/**
+ * Set the devices' cursor position to the given x/y position.
+ *
+ * This function is called during the pointer update path in
+ * GetPointerEvents and friends (and the same in the xwin DDX).
+ *
+ * @param pDev The device to move
+ * @param[in,out] x The x coordiante in screen coordinates (in regards to total
+ * desktop size)
+ * @param[in,out] y The y coordiante in screen coordinates (in regards to total
+ * desktop size)
+ */
 void
 miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
@@ -537,6 +645,12 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
     miPointerMoveNoEvent(pDev, pScreen, *x, *y);
 }
 
+/**
+ * Get the current position of the device in desktop coordinates.
+ *
+ * @param x Return value for the current x coordinate in desktop coordiates.
+ * @param y Return value for the current y coordinate in desktop coordiates.
+ */
 void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
@@ -550,6 +664,15 @@ void darwinEvents_lock(void);
 void darwinEvents_unlock(void);
 #endif
 
+/**
+ * Move the device's pointer to the x/y coordinates on the given screen.
+ * This function generates and enqueues pointer events.
+ *
+ * @param pDev The device to move
+ * @param pScreen The screen the device is on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
 void
 miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
commit 15fe86e69fc256342881112cd07565527e32435b
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 11 11:01:19 2011 +1000

    mi: remove static GenerateEvent variable.
    
    Push into the respective devices. This should have no functional changes
    since we never warp more than one device at a time. In the glorious future
    with true multithreading, still the better thing to do.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Benjamin Tissoires <tissoire at cena.fr>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 554397a..5ee456c 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -220,15 +220,15 @@ miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
     *pTopLeftBox = *pHotBox;
 }
 
-static Bool GenerateEvent;
-
 static Bool
 miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
                            int x, int y, Bool generateEvent)
 {
     SetupScreen (pScreen);
+    miPointerPtr pPointer = MIPOINTER(pDev);
+
+    pPointer->generateEvent = generateEvent;
 
-    GenerateEvent = generateEvent;
     /* device dependent - must pend signal and call miPointerWarpCursor */
     (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
     if (!generateEvent)
@@ -261,6 +261,7 @@ miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
     pPointer->confined = FALSE;
     pPointer->x = 0;
     pPointer->y = 0;
+    pPointer->generateEvent = FALSE;
 
     if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
     {
@@ -306,7 +307,7 @@ miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
         changedScreen = TRUE;
     }
 
-    if (GenerateEvent)
+    if (pPointer->generateEvent)
 	miPointerMove (pDev, pScreen, x, y);
     else
         miPointerMoveNoEvent(pDev, pScreen, x, y);
diff --git a/mi/mipointrst.h b/mi/mipointrst.h
index bd9c24a..c912a17 100644
--- a/mi/mipointrst.h
+++ b/mi/mipointrst.h
@@ -44,6 +44,7 @@ typedef struct {
     Bool		    confined;	/* pointer can't change screens */
     int			    x, y;	/* hot spot location */
     int			    devx, devy;	/* sprite position */
+    Bool		    generateEvent; /* generate an event during warping? */
 } miPointerRec, *miPointerPtr;
 
 typedef struct {
commit 649269d40667cfb387cb5286dd3519dd68f7dd80
Author: Bryce Harrington <bryce at canonical.com>
Date:   Wed Feb 16 16:55:57 2011 -0800

    Check for OOM condition in XISendDeviceHierarchyEvent
    
    When system is out of memory, calloc can fail returning a NULL pointer.
    Check for this before dereferencing it, and bail out if it fails.
    
    Ref.: https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/720445
    
    Signed-off-by: Bryce Harrington <bryce at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index b9cdedf..21c74ed 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -70,6 +70,8 @@ void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
 
     ev = calloc(1, sizeof(xXIHierarchyEvent) +
                  MAXDEVICES * sizeof(xXIHierarchyInfo));
+    if (!ev)
+        return;
     ev->type = GenericEvent;
     ev->extension = IReqCode;
     ev->evtype = XI_HierarchyChanged;
commit 31ddb7ef4f5bac2c13c199e74a0716e43b8dc38e
Author: Simon Thum <simon.thum at gmx.de>
Date:   Wed Feb 2 00:03:44 2011 +0100

    dix: avoid FP promotion during pointer acceleration
    
    Signed-off-by: Simon Thum <simon.thum at gmx.de>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index 1b9c81b..e6ac2ed 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -1084,11 +1084,11 @@ acceleratePointerPredictable(
 					(float)dev->ptrfeed->ctrl.num /
 					(float)dev->ptrfeed->ctrl.den);
 
-            if(mult != 1.0 || velocitydata->const_acceleration != 1.0) {
+            if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) {
                 ApplySofteningAndConstantDeceleration( velocitydata,
 						       dx, dy,
 						       &fdx, &fdy,
-						       (mult > 1.0) && soften);
+						       (mult > 1.0f) && soften);
 
                 if (dx) {
                     tmp = mult * fdx + dev->last.remainder[0];
commit 006157f203f8493bb3d18e333a3fd3d6cb10f8ea
Author: Simon Thum <simon.thum at gmx.de>
Date:   Sat Sep 4 16:31:24 2010 +0200

    dix: refactor scheme init
    
    This makes it possible to init a scheme in one init call, so we
    get rid of the tightly coupled two-phase init used before.
    
    Signed-off-by: Simon Thum <simon.thum at gmx.de>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/devices.c b/dix/devices.c
index 6c0dc42..3065319 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1279,10 +1279,11 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
 
 /* global list of acceleration schemes */
 ValuatorAccelerationRec pointerAccelerationScheme[] = {
-    {PtrAccelNoOp,        NULL, NULL, NULL},
-    {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
-    {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
-    {-1, NULL, NULL, NULL} /* terminator */
+    {PtrAccelNoOp, NULL, NULL, NULL, NULL},
+    {PtrAccelPredictable, acceleratePointerPredictable, NULL,
+        InitPredictableAccelerationScheme, AccelerationDefaultCleanup},
+    {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL, NULL},
+    {-1, NULL, NULL, NULL, NULL} /* terminator */
 };
 
 /**
@@ -1294,59 +1295,37 @@ InitPointerAccelerationScheme(DeviceIntPtr dev,
                               int scheme)
 {
     int x, i = -1;
-    void* data = NULL;
     ValuatorClassPtr val;
 
     val = dev->valuator;
 
-    if(!val)
-	return FALSE;
+    if (!val)
+        return FALSE;
 
-    if(IsMaster(dev) && scheme != PtrAccelNoOp)
+    if (IsMaster(dev) && scheme != PtrAccelNoOp)
         return FALSE;
 
-    for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
+    for (x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
         if(pointerAccelerationScheme[x].number == scheme){
             i = x;
             break;
         }
     }
 
-    if(-1 == i)
+    if (-1 == i)
         return FALSE;
 
     if (val->accelScheme.AccelCleanupProc)
         val->accelScheme.AccelCleanupProc(dev);
 
-    /* init scheme-specific data */
-    switch(scheme){
-        case PtrAccelPredictable:
-        {
-            DeviceVelocityPtr s;
-            s = malloc(sizeof(DeviceVelocityRec));
-            if(!s)
-        	return FALSE;
-            InitVelocityData(s);
-            data = s;
-            break;
+    if (pointerAccelerationScheme[i].AccelInitProc) {
+        if (!pointerAccelerationScheme[i].AccelInitProc(dev,
+                                            &pointerAccelerationScheme[i])) {
+            return FALSE;
         }
-        default:
-            break;
+    } else {
+        val->accelScheme = pointerAccelerationScheme[i];
     }
-
-    val->accelScheme = pointerAccelerationScheme[i];
-    val->accelScheme.accelData = data;
-
-    /* post-init scheme */
-    switch(scheme){
-        case PtrAccelPredictable:
-            InitializePredictableAccelerationProperties(dev);
-            break;
-
-        default:
-            break;
-    }
-
     return TRUE;
 }
 
diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index 8f03321..1b9c81b 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -67,6 +67,10 @@ SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity,
                     float threshold, float acc);
 static PointerAccelerationProfileFunc
 GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
+static BOOL
+InitializePredictableAccelerationProperties(DeviceIntPtr dev);
+static BOOL
+DeletePredictableAccelerationProperties(DeviceIntPtr dev);
 
 /*#define PTRACCEL_DEBUGGING*/
 
@@ -85,7 +89,7 @@ GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
 
 
 /**
- * Init struct so it should match the average case
+ * Init DeviceVelocity struct so it should match the average case
  */
 void
 InitVelocityData(DeviceVelocityPtr vel)
@@ -107,7 +111,7 @@ InitVelocityData(DeviceVelocityPtr vel)
 
 
 /**
- * Clean up
+ * Clean up DeviceVelocityRec
  */
 void
 FreeVelocityData(DeviceVelocityPtr vel){
@@ -116,8 +120,28 @@ FreeVelocityData(DeviceVelocityPtr vel){
 }
 
 
-/*
- *  dix uninit helper, called through scheme
+/**
+ * Init predictable scheme
+ */
+Bool
+InitPredictableAccelerationScheme(DeviceIntPtr dev,
+				  ValuatorAccelerationPtr protoScheme) {
+    DeviceVelocityPtr vel;
+    ValuatorAccelerationRec scheme;
+    scheme = *protoScheme;
+    vel = calloc(1, sizeof(DeviceVelocityRec));
+    if (!vel)
+	return FALSE;
+    InitVelocityData(vel);
+    scheme.accelData = vel;
+    dev->valuator->accelScheme = scheme;
+    InitializePredictableAccelerationProperties(dev);
+    return TRUE;
+}
+
+
+/**
+ *  Uninit scheme
  */
 void
 AccelerationDefaultCleanup(DeviceIntPtr dev)
@@ -1024,12 +1048,10 @@ acceleratePointerPredictable(
     int *valuators,
     int evtime)
 {
-    float mult = 0.0;
+    float fdx, fdy, tmp, mult; /* no need to init */
     int dx = 0, dy = 0;
     int *px = NULL, *py = NULL;
-    DeviceVelocityPtr velocitydata =
-	(DeviceVelocityPtr) dev->valuator->accelScheme.accelData;
-    float fdx, fdy, tmp; /* no need to init */
+    DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev);
     Bool soften = TRUE;
 
     if (!num_valuators || !valuators || !velocitydata)
diff --git a/include/input.h b/include/input.h
index 0dc725a..643866f 100644
--- a/include/input.h
+++ b/include/input.h
@@ -150,6 +150,11 @@ typedef void (*PointerAccelSchemeProc)(
 typedef void (*DeviceCallbackProc)(
               DeviceIntPtr /*pDev*/);
 
+struct _ValuatorAccelerationRec;
+typedef Bool (*PointerAccelSchemeInitProc)(
+              DeviceIntPtr /*dev*/,
+              struct _ValuatorAccelerationRec* /*protoScheme*/);
+
 typedef struct _DeviceRec {
     pointer	devicePrivate;
     ProcessInputProc processInputProc;	/* current */
diff --git a/include/inputstr.h b/include/inputstr.h
index b74ee04..65b9ef9 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -266,6 +266,7 @@ typedef struct _ValuatorAccelerationRec {
     int                         number;
     PointerAccelSchemeProc      AccelSchemeProc;
     void                       *accelData; /* at disposal of AccelScheme */
+    PointerAccelSchemeInitProc  AccelInitProc;
     DeviceCallbackProc          AccelCleanupProc;
 } ValuatorAccelerationRec, *ValuatorAccelerationPtr;
 
diff --git a/include/ptrveloc.h b/include/ptrveloc.h
index 6f999a8..8c59c03 100644
--- a/include/ptrveloc.h
+++ b/include/ptrveloc.h
@@ -110,12 +110,6 @@ BasicComputeAcceleration(DeviceIntPtr dev, DeviceVelocityPtr vel,
 extern _X_EXPORT void
 FreeVelocityData(DeviceVelocityPtr vel);
 
-extern _X_INTERNAL BOOL
-InitializePredictableAccelerationProperties(DeviceIntPtr dev);
-
-extern _X_INTERNAL BOOL
-DeletePredictableAccelerationProperties(DeviceIntPtr dev);
-
 extern _X_EXPORT int
 SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
 
@@ -129,6 +123,10 @@ SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel,
 extern _X_INTERNAL void
 AccelerationDefaultCleanup(DeviceIntPtr dev);
 
+extern _X_INTERNAL Bool
+InitPredictableAccelerationScheme(DeviceIntPtr dev,
+				  struct _ValuatorAccelerationRec* protoScheme);
+
 extern _X_INTERNAL void
 acceleratePointerPredictable(DeviceIntPtr dev, int first_valuator,
                              int num_valuators, int *valuators, int evtime);
commit 38ffeec0c89e83afc62579dec221c325d667cc1e
Author: Simon Thum <simon.thum at gmx.de>
Date:   Sun Feb 6 19:13:00 2011 +0100

    xfree86: allow to check for options without warnings in the log
    
    This allows set_percent_option in synaptics to work as described,
    and should generally enable to check option syntax without log spam.
    
    Signed-off-by: Simon Thum <simon.thum at gmx.de>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index 455cafa..480f386 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -496,27 +496,33 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 	switch (p->type) {
 	case OPTV_INTEGER:
 	    if (*s == '\0') {
-		xf86DrvMsg(scrnIndex, X_WARNING,
-			   "Option \"%s\" requires an integer value\n",
-			   p->name);
+		if (markUsed) {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires an integer value\n",
+			       p->name);
+		}
 		p->found = FALSE;
 	    } else {
 		p->value.num = strtoul(s, &end, 0);
 		if (*end == '\0') {
 		    p->found = TRUE;
 		} else {
-		    xf86DrvMsg(scrnIndex, X_WARNING,
-			       "Option \"%s\" requires an integer value\n",
-			        p->name);
+		    if (markUsed) {
+			xf86DrvMsg(scrnIndex, X_WARNING,
+				   "Option \"%s\" requires an integer value\n",
+				    p->name);
+		    }
 		    p->found = FALSE;
 		}
 	    }
 	    break;
 	case OPTV_STRING:
 	    if (*s == '\0') {
-		xf86DrvMsg(scrnIndex, X_WARNING,
-			   "Option \"%s\" requires an string value\n",
-			   p->name);
+		if (markUsed) {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires an string value\n",
+			       p->name);
+		}
 		p->found = FALSE;
 	    } else {
 		p->value.str = s;
@@ -529,18 +535,22 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 	    break;
 	case OPTV_REAL:	
 	    if (*s == '\0') {
-		xf86DrvMsg(scrnIndex, X_WARNING,
-			   "Option \"%s\" requires a floating point value\n",
-			   p->name);
+		if (markUsed) {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires a floating point "
+			       "value\n", p->name);
+		}
 		p->found = FALSE;
 	    } else {
 		p->value.realnum = strtod(s, &end);
 		if (*end == '\0') {
 		    p->found = TRUE;
 		} else {
-		    xf86DrvMsg(scrnIndex, X_WARNING,
-			    "Option \"%s\" requires a floating point value\n",
-			    p->name);
+		    if (markUsed) {
+			xf86DrvMsg(scrnIndex, X_WARNING,
+				"Option \"%s\" requires a floating point "
+				"value\n", p->name);
+		    }
 		    p->found = FALSE;
 		}
 	    }
@@ -549,8 +559,11 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 	    if (GetBoolValue(p, s)) {
 		p->found = TRUE;
 	    } else {
-		xf86DrvMsg(scrnIndex, X_WARNING,
-			   "Option \"%s\" requires a boolean value\n", p->name);
+		if (markUsed) {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires a boolean value\n",
+			       p->name);
+		}
 		p->found = FALSE;
 	    }
 	    break;
@@ -561,8 +574,10 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 		 * hence 100 looks the same as 100% to the caller of sccanf
 		 */
 		if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') {
-		    xf86DrvMsg(scrnIndex, X_WARNING,
+		    if (markUsed) {
+			xf86DrvMsg(scrnIndex, X_WARNING,
 			       "Option \"%s\" requires a percent value\n", p->name);
+		    }
 		    p->found = FALSE;
 		} else {
 		    p->found = TRUE;
@@ -571,9 +586,11 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 	    break;
 	case OPTV_FREQ:	
 	    if (*s == '\0') {
-		xf86DrvMsg(scrnIndex, X_WARNING,
-			   "Option \"%s\" requires a frequency value\n",
-			   p->name);
+		if (markUsed) {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires a frequency value\n",
+			       p->name);
+		}
 		p->found = FALSE;
 	    } else {
 		double freq = strtod(s, &end);
@@ -590,17 +607,21 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 			     !xf86NameCmp(end, "M"))
 			units = 1000000;
 		    else {
-			xf86DrvMsg(scrnIndex, X_WARNING,
-			    "Option \"%s\" requires a frequency value\n",
-			    p->name);
+			if (markUsed) {
+			    xf86DrvMsg(scrnIndex, X_WARNING,
+				"Option \"%s\" requires a frequency value\n",
+				p->name);
+			}
 			p->found = FALSE;
 		    }
 		    if (p->found)
 			freq *= (double)units;
 		} else {
-		    xf86DrvMsg(scrnIndex, X_WARNING,
-			    "Option \"%s\" requires a frequency value\n",
-			    p->name);
+		    if (markUsed) {
+			xf86DrvMsg(scrnIndex, X_WARNING,
+				"Option \"%s\" requires a frequency value\n",
+				p->name);
+		    }
 		    p->found = FALSE;
 		}
 		if (p->found) {
commit 2fbccc881bfab4bdc5b97f74a7e5bcec7fdeae20
Author: Simon Thum <simon.thum at gmx.de>
Date:   Sun Feb 6 19:07:19 2011 +0100

    fix percent options parsing
    
    Signed-off-by: Simon Thum <simon.thum at gmx.de>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index 16c27e5..455cafa 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -212,7 +212,7 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed)
     return deflt;
 }
 
-static int
+static double
 LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed)
 {
     OptionInfoRec o;
commit 46b49796015762fd131bec96eff6caaa890bfd5f
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 15 11:28:02 2011 +0000

    Input: Allow EventToCore to return multiple events
    
    Some event types (notably Expose and GraphicsExpose) require multiple
    events, a la XI 1.x.  Bring the EventToCore API in line with EventToXI's
    and allow it to generate multiple events.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/eventconvert.c b/dix/eventconvert.c
index 7b894f0..8976919 100644
--- a/dix/eventconvert.c
+++ b/dix/eventconvert.c
@@ -97,8 +97,12 @@ EventIsKeyRepeat(xEvent *event)
  * @return Success or the matching error code.
  */
 int
-EventToCore(InternalEvent *event, xEvent *core)
+EventToCore(InternalEvent *event, xEvent **core_out, int *count_out)
 {
+    xEvent *core = NULL;
+    int count = 0;
+    int ret = BadImplementation;
+
     switch(event->any.type)
     {
         case ET_Motion:
@@ -108,7 +112,10 @@ EventToCore(InternalEvent *event, xEvent *core)
                  * present */
                 if (!BitIsOn(e->valuators.mask, 0) &&
                     !BitIsOn(e->valuators.mask, 1))
-                    return BadMatch;
+                {
+                    ret = BadMatch;
+                    goto out;
+                }
             }
             /* fallthrough */
         case ET_ButtonPress:
@@ -119,9 +126,15 @@ EventToCore(InternalEvent *event, xEvent *core)
                 DeviceEvent *e = &event->device_event;
 
                 if (e->detail.key > 0xFF)
-                    return BadMatch;
-
-                memset(core, 0, sizeof(xEvent));
+                {
+                    ret = BadMatch;
+                    goto out;
+                }
+
+                core = calloc(1, sizeof(*core));
+                if (!core)
+                    return BadAlloc;
+                count = 1;
                 core->u.u.type = e->type - ET_KeyPress + KeyPress;
                 core->u.u.detail = e->detail.key & 0xFF;
                 core->u.keyButtonPointer.time = e->time;
@@ -129,7 +142,10 @@ EventToCore(InternalEvent *event, xEvent *core)
                 core->u.keyButtonPointer.rootY = e->root_y;
                 core->u.keyButtonPointer.state = e->corestate;
                 core->u.keyButtonPointer.root = e->root;
-                EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat));
+                EventSetKeyRepeatFlag(core,
+                                      (e->type == ET_KeyPress &&
+                                       e->key_repeat));
+                ret = Success;
             }
             break;
         case ET_ProximityIn:
@@ -139,13 +155,18 @@ EventToCore(InternalEvent *event, xEvent *core)
         case ET_RawButtonPress:
         case ET_RawButtonRelease:
         case ET_RawMotion:
-            return BadMatch;
+            ret = BadMatch;
+            goto out;
         default:
             /* XXX: */
             ErrorF("[dix] EventToCore: Not implemented yet \n");
-            return BadImplementation;
+            ret = BadImplementation;
     }
-    return Success;
+
+out:
+    *core_out = core;
+    *count_out = count;
+    return ret;
 }
 
 /**
diff --git a/dix/events.c b/dix/events.c
index d547e57..2723f53 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2366,8 +2366,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
     Window child = None;
     Mask filter;
     int deliveries = 0;
-    xEvent core;
-    xEvent *xE = NULL;
+    xEvent *xE = NULL, *core = NULL;
     int rc, mask, count = 0;
 
     CHECKEVENT(event);
@@ -2417,13 +2416,13 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
             /* Core event */
             if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents)
             {
-                rc = EventToCore(event, &core);
+                rc = EventToCore(event, &core, &count);
                 if (rc == Success) {
-                    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) {
-                        filter = GetEventFilter(dev, &core);
-                        FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE);
-                        deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
-                                                           filter, grab);
+                    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, core, count) == Success) {
+                        filter = GetEventFilter(dev, core);
+                        FixUpEventFromWindow(pSprite, core, pWin, child, FALSE);
+                        deliveries = DeliverEventsToWindow(dev, pWin, core,
+                                                           count, filter, grab);
                         if (deliveries > 0)
                             goto unwind;
                     }
@@ -2445,6 +2444,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
     }
 
 unwind:
+    free(core);
     free(xE);
     return deliveries;
 }
@@ -3460,7 +3460,6 @@ CheckPassiveGrabsOnWindow(
 	{
             int rc, count = 0;
             xEvent *xE = NULL;
-            xEvent core;
 
             event->corestate &= 0x1f00;
             event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
@@ -3512,7 +3511,7 @@ CheckPassiveGrabsOnWindow(
 
             if (match & CORE_MATCH)
             {
-                rc = EventToCore((InternalEvent*)event, &core);
+                rc = EventToCore((InternalEvent*)event, &xE, &count);
                 if (rc != Success)
                 {
                     if (rc != BadMatch)
@@ -3520,8 +3519,6 @@ CheckPassiveGrabsOnWindow(
                                 "(%d, %d).\n", device->name, event->type, rc);
                     continue;
                 }
-                xE = &core;
-                count = 1;
             } else if (match & XI2_MATCH)
             {
                 rc = EventToXI2((InternalEvent*)event, &xE);
@@ -3551,6 +3548,7 @@ CheckPassiveGrabsOnWindow(
             {
                 FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
 
+                /* XXX: XACE? */
                 TryClientEvents(rClient(grab), device, xE, count,
                                        GetEventFilter(device, xE),
                                        GetEventFilter(device, xE), grab);
@@ -3564,8 +3562,7 @@ CheckPassiveGrabsOnWindow(
 		grabinfo->sync.state = FROZEN_WITH_EVENT;
             }
 
-            if (match & (XI_MATCH | XI2_MATCH))
-                free(xE); /* on core match xE == &core */
+            free(xE);
 	    return grab;
 	}
     }
@@ -3682,8 +3679,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
     DeviceIntPtr ptr;
     WindowPtr focus = keybd->focus->win;
     BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
-    xEvent core;
-    xEvent *xE = NULL, *xi2 = NULL;
+    xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
     int count, rc;
     int deliveries = 0;
 
@@ -3737,13 +3733,13 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
 
     if (sendCore)
     {
-        rc = EventToCore(event, &core);
+        rc = EventToCore(event, &core, &count);
         if (rc == Success) {
-            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) {
-                FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus,
+            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == Success) {
+                FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
                                      None, FALSE);
-                deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
-                                                   GetEventFilter(keybd, &core),
+                deliveries = DeliverEventsToWindow(keybd, focus, core, count,
+                                                   GetEventFilter(keybd, core),
                                                    NullGrab);
             }
         } else if (rc != BadMatch)
@@ -3752,6 +3748,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
     }
 
 unwind:
+    free(core);
     free(xE);
     free(xi2);
     return;
@@ -3777,6 +3774,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
     int rc, count = 0;
     xEvent *xi = NULL;
     xEvent *xi2 = NULL;
+    xEvent *core = NULL;
 
     grabinfo = &thisDev->deviceGrab;
     grab = grabinfo->grab;
@@ -3826,22 +3824,20 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
         /* try core event */
         if (sendCore && grab->grabtype == GRABTYPE_CORE)
         {
-            xEvent core;
-
-            rc = EventToCore(event, &core);
+            rc = EventToCore(event, &core, &count);
             if (rc == Success)
             {
-                FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE);
+                FixUpEventFromWindow(pSprite, core, grab->window, None, TRUE);
                 if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
-                            grab->window, &core, 1) ||
+                            grab->window, core, count) ||
                         XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
-                            grab->window, &core, 1))
+                            grab->window, core, count))
                     deliveries = 1; /* don't send, but pretend we did */
-                else if (!IsInterferingGrab(rClient(grab), thisDev, &core))
+                else if (!IsInterferingGrab(rClient(grab), thisDev, core))
                 {
                     deliveries = TryClientEvents(rClient(grab), thisDev,
-                            &core, 1, mask,
-                            GetEventFilter(thisDev, &core),
+                            core, count, mask,
+                            GetEventFilter(thisDev, core),
                             grab);
                 }
             } else if (rc != BadMatch)
@@ -3931,6 +3927,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
 	}
     }
 
+    free(core);
     free(xi);
     free(xi2);
 }
diff --git a/include/eventconvert.h b/include/eventconvert.h
index b1196a0..b000abc 100644
--- a/include/eventconvert.h
+++ b/include/eventconvert.h
@@ -30,7 +30,7 @@
 
 #define FP1616(integral, frac) ((integral) * (1 << 16) + (frac) * (1 << 16))
 
-_X_EXPORT int EventToCore(InternalEvent *event, xEvent *core);
+_X_EXPORT int EventToCore(InternalEvent *event, xEvent **core, int *count);
 _X_EXPORT int EventToXI(InternalEvent *ev, xEvent **xi, int *count);
 _X_EXPORT int EventToXI2(InternalEvent *ev, xEvent **xi);
 _X_INTERNAL int GetCoreType(InternalEvent* ev);
diff --git a/record/record.c b/record/record.c
index 6a93d7a..1168c43 100644
--- a/record/record.c
+++ b/record/record.c
@@ -804,6 +804,7 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
     RecordContextPtr pContext;
     RecordClientsAndProtocolPtr pRCAP;
     int eci; /* enabled context index */
+    int count;
 
     for (eci = 0; eci < numEnabledContexts; eci++)
     {
@@ -818,9 +819,11 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
 		/* TODO check return values */
 		if (IsMaster(pei->device))
 		{
-		    xEvent xE;
-		    EventToCore(pei->event, &xE);
-		    RecordSendProtocolEvents(pRCAP, pContext, &xE, 1);
+		    xEvent *core_events;
+		    EventToCore(pei->event, &core_events, &count);
+		    RecordSendProtocolEvents(pRCAP, pContext, core_events,
+                                             count);
+		    free(core_events);
 		}
 
 		EventToXI(pei->event, &xi_events, &count);
diff --git a/test/input.c b/test/input.c
index 879e14f..e7300a1 100644
--- a/test/input.c
+++ b/test/input.c
@@ -148,29 +148,32 @@ static void dix_check_grab_values(void)
 static void dix_event_to_core(int type)
 {
     DeviceEvent ev;
-    xEvent core;
+    xEvent *core;
     int time;
     int x, y;
     int rc;
     int state;
     int detail;
+    int count;
     const int ROOT_WINDOW_ID = 0x100;
 
     /* EventToCore memsets the event to 0 */
 #define test_event() \
     g_assert(rc == Success); \
-    g_assert(core.u.u.type == type); \
-    g_assert(core.u.u.detail == detail); \
-    g_assert(core.u.keyButtonPointer.time == time); \
-    g_assert(core.u.keyButtonPointer.rootX == x); \
-    g_assert(core.u.keyButtonPointer.rootY == y); \
-    g_assert(core.u.keyButtonPointer.state == state); \
-    g_assert(core.u.keyButtonPointer.eventX == 0); \
-    g_assert(core.u.keyButtonPointer.eventY == 0); \
-    g_assert(core.u.keyButtonPointer.root == ROOT_WINDOW_ID); \
-    g_assert(core.u.keyButtonPointer.event == 0); \
-    g_assert(core.u.keyButtonPointer.child == 0); \
-    g_assert(core.u.keyButtonPointer.sameScreen == FALSE);
+    g_assert(core); \
+    g_assert(count == 1); \
+    g_assert(core->u.u.type == type); \
+    g_assert(core->u.u.detail == detail); \
+    g_assert(core->u.keyButtonPointer.time == time); \
+    g_assert(core->u.keyButtonPointer.rootX == x); \
+    g_assert(core->u.keyButtonPointer.rootY == y); \
+    g_assert(core->u.keyButtonPointer.state == state); \
+    g_assert(core->u.keyButtonPointer.eventX == 0); \
+    g_assert(core->u.keyButtonPointer.eventY == 0); \
+    g_assert(core->u.keyButtonPointer.root == ROOT_WINDOW_ID); \
+    g_assert(core->u.keyButtonPointer.event == 0); \
+    g_assert(core->u.keyButtonPointer.child == 0); \
+    g_assert(core->u.keyButtonPointer.sameScreen == FALSE);
 
     x = 0;
     y = 0;
@@ -191,30 +194,33 @@ static void dix_event_to_core(int type)
 
     ev.type = type;
     ev.detail.key = 0;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     x = 1;
     y = 2;
     ev.root_x = x;
     ev.root_y = y;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     x = 0x7FFF;
     y = 0x7FFF;
     ev.root_x = x;
     ev.root_y = y;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     x = 0x8000; /* too high */
     y = 0x8000; /* too high */
     ev.root_x = x;
     ev.root_y = y;
-    rc = EventToCore((InternalEvent*)&ev, &core);
-    g_assert(core.u.keyButtonPointer.rootX != x);
-    g_assert(core.u.keyButtonPointer.rootY != y);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
+    g_assert(rc == Success);
+    g_assert(core);
+    g_assert(count == 1);
+    g_assert(core->u.keyButtonPointer.rootX != x);
+    g_assert(core->u.keyButtonPointer.rootY != y);
 
     x = 0x7FFF;
     y = 0x7FFF;
@@ -222,36 +228,39 @@ static void dix_event_to_core(int type)
     ev.root_y = y;
     time = 0;
     ev.time = time;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     detail = 1;
     ev.detail.key = detail;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     detail = 0xFF; /* highest value */
     ev.detail.key = detail;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     detail = 0xFFF; /* too big */
     ev.detail.key = detail;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     g_assert(rc == BadMatch);
 
     detail = 0xFF; /* too big */
     ev.detail.key = detail;
     state = 0xFFFF; /* highest value */
     ev.corestate = state;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     test_event();
 
     state = 0x10000; /* too big */
     ev.corestate = state;
-    rc = EventToCore((InternalEvent*)&ev, &core);
-    g_assert(core.u.keyButtonPointer.state != state);
-    g_assert(core.u.keyButtonPointer.state == (state & 0xFFFF));
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
+    g_assert(rc == Success);
+    g_assert(core);
+    g_assert(count == 1);
+    g_assert(core->u.keyButtonPointer.state != state);
+    g_assert(core->u.keyButtonPointer.state == (state & 0xFFFF));
 
 #undef test_event
 }
@@ -259,14 +268,15 @@ static void dix_event_to_core(int type)
 static void dix_event_to_core_fail(int evtype, int expected_rc)
 {
     DeviceEvent ev;
-    xEvent core;
+    xEvent *core;
     int rc;
+    int count;
 
     ev.header   = 0xFF;
     ev.length   = sizeof(DeviceEvent);
 
     ev.type     = evtype;
-    rc = EventToCore((InternalEvent*)&ev, &core);
+    rc = EventToCore((InternalEvent*)&ev, &core, &count);
     g_assert(rc == expected_rc);
 }
 
commit ea71495adabca52df44241c0eba39e6bceb58202
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 15 11:28:01 2011 +0000

    Input: Reduce use of filter in DeliverEvents
    
    Instead of switching on the event filter to determine delivery, use the
    event type instead.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 66c11b4..d547e57 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2466,9 +2466,8 @@ int
 DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
               WindowPtr otherParent)
 {
-    Mask filter;
-    int     deliveries;
     DeviceIntRec dummy;
+    int     deliveries;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
@@ -2479,11 +2478,42 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
 	return 0;
 
     dummy.id = XIAllDevices;
-    filter = GetEventFilter(&dummy, xE);
-    if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
-	xE->u.destroyNotify.event = pWin->drawable.id;
-    if (filter != StructureAndSubMask)
-	return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
+
+    switch (xE->u.u.type)
+    {
+        case DestroyNotify:
+        case UnmapNotify:
+        case MapNotify:
+        case MapRequest:
+        case ReparentNotify:
+        case ConfigureNotify:
+        case ConfigureRequest:
+        case GravityNotify:
+        case CirculateNotify:
+        case CirculateRequest:
+            xE->u.destroyNotify.event = pWin->drawable.id;
+            break;
+    }
+
+    switch (xE->u.u.type)
+    {
+        case DestroyNotify:
+        case UnmapNotify:
+        case MapNotify:
+        case ReparentNotify:
+        case ConfigureNotify:
+        case GravityNotify:
+        case CirculateNotify:
+            break;
+        default:
+        {
+            Mask filter;
+            filter = GetEventFilter(&dummy, xE);
+            return DeliverEventsToWindow(&dummy, pWin, xE, count, filter,
+                                         NullGrab);
+        }
+    }
+
     deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
                                        StructureNotifyMask, NullGrab);
     if (pWin->parent)
commit 8a0241656cecb6ab2fb377f02b14238d18e65fc1
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 15 11:28:00 2011 +0000

    Input: Rename EventIsDeliverable return masks
    
    Rename the return mask values for EventIsDeliverable:
        * CORE_MASK -> EVENT_CORE_MASK
        * XI_MASK -> EVENT_XI1_MASK
        * XI2_MASK -> EVENT_XI2_MASK
        * DONT_PROPAGATE_MASK -> EVENT_DONT_PROPAGATE_MASK
    
    And don't undef them in dix/events.c, since they're supposed to be
    global.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 5e8166d..66c11b4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2287,8 +2287,8 @@ FixUpEventFromWindow(
  * @param[in] event The event that is to be sent.
  * @param[in] win The current event window.
  *
- * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
- * ::DONT_PROPAGATE_MASK.
+ * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
+ *         ::EVENT_DONT_PROPAGATE_MASK.
  */
 int
 EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
@@ -2309,7 +2309,7 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
         ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
          ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
          (inputMasks->xi2mask[dev->id][type/8] & filter)))
-        rc |= XI2_MASK;
+        rc |= EVENT_XI2_MASK;
 
     type = GetXIType(event);
     ev.u.u.type = type;
@@ -2319,22 +2319,22 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
     if (type && inputMasks &&
         (inputMasks->deliverableEvents[dev->id] & filter) &&
         (inputMasks->inputEvents[dev->id] & filter))
-        rc |= XI_MASK;
+        rc |= EVENT_XI1_MASK;
 
     /* Check for XI DontPropagate mask */
     if (type && inputMasks &&
         (inputMasks->dontPropagateMask[dev->id] & filter))
-        rc |= DONT_PROPAGATE_MASK;
+        rc |= EVENT_DONT_PROPAGATE_MASK;
 
     /* Check for core mask */
     type = GetCoreType(event);
     if (type && (win->deliverableEvents & filter) &&
         ((wOtherEventMasks(win) | win->eventMask) & filter))
-        rc |= CORE_MASK;
+        rc |= EVENT_CORE_MASK;
 
     /* Check for core DontPropagate mask */
     if (type && (filter & wDontPropagateMask(win)))
-        rc |= DONT_PROPAGATE_MASK;
+        rc |= EVENT_DONT_PROPAGATE_MASK;
 
     return rc;
 }
@@ -2377,7 +2377,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
         if ((mask = EventIsDeliverable(dev, event, pWin)))
         {
             /* XI2 events first */
-            if (mask & XI2_MASK)
+            if (mask & EVENT_XI2_MASK)
             {
                 xEvent *xi2 = NULL;
                 rc = EventToXI2(event, &xi2);
@@ -2397,7 +2397,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
             }
 
             /* XI events */
-            if (mask & XI_MASK)
+            if (mask & EVENT_XI1_MASK)
             {
                 rc = EventToXI(event, &xE, &count);
                 if (rc == Success) {
@@ -2415,7 +2415,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
             }
 
             /* Core event */
-            if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents)
+            if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents)
             {
                 rc = EventToCore(event, &core);
                 if (rc == Success) {
@@ -2433,7 +2433,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
             }
 
             if ((deliveries < 0) || (pWin == stopAt) ||
-                (mask & DONT_PROPAGATE_MASK))
+                (mask & EVENT_DONT_PROPAGATE_MASK))
             {
                 deliveries = 0;
                 goto unwind;
@@ -2449,10 +2449,6 @@ unwind:
     return deliveries;
 }
 
-#undef XI_MASK
-#undef CORE_MASK
-#undef DONT_PROPAGATE_MASK
-
 /**
  * Deliver event to a window and it's immediate parent. Used for most window
  * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
diff --git a/include/input.h b/include/input.h
index f96a0a9..0dc725a 100644
--- a/include/input.h
+++ b/include/input.h
@@ -538,14 +538,15 @@ extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y);
 extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event,
                               WindowPtr win);
 /**
- * Return masks for EventIsDeliverable.
+ * Masks specifying the type of event to deliver for an InternalEvent; used
+ * by EventIsDeliverable.
  * @defgroup EventIsDeliverable return flags
  * @{
  */
-#define XI_MASK                 (1 << 0) /**< XI mask set on window */
-#define CORE_MASK               (1 << 1) /**< Core mask set on window */
-#define DONT_PROPAGATE_MASK     (1 << 2) /**< DontPropagate mask set on window */
-#define XI2_MASK                (1 << 3) /**< XI2 mask set on window */
+#define EVENT_XI1_MASK                (1 << 0) /**< XI1.x event */
+#define EVENT_CORE_MASK               (1 << 1) /**< Core event */
+#define EVENT_DONT_PROPAGATE_MASK     (1 << 2) /**< DontPropagate mask set */
+#define EVENT_XI2_MASK                (1 << 3) /**< XI2 mask set on window */
 /* @} */
 
 /* Implemented by the DDX. */
commit 737562257e8ee30b1c438e5160a61fbb26ca609e
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 15 11:27:59 2011 +0000

    Input: Actually send Xi 1.x DeviceStateNotify events
    
    When a client has selected for Xi 1.x DeviceStateNotify events, they
    should receive them when a DeviceFocusIn event is generated.  The code
    to do this was there, but an incorrect test meant they were never being
    sent.
    
    The "type" passed in is the XI2 type, the XI1 type is in event.type.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 5131167..cf38967 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1278,7 +1278,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
 				DeviceFocusChangeMask, NullGrab);
 
-    if ((type == DeviceFocusIn) &&
+    if ((event.type == DeviceFocusIn) &&
 	(wOtherInputMasks(pWin)) &&
 	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
     {
commit da39d57a20d4281fc4099e356645fef980290030
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Tue Feb 15 11:27:57 2011 +0000

    Input: Store passive-activating key in CheckDeviceGrabs
    
    CheckDeviceGrabs will activate a passive grab for KeyPress and
    ButtonPress events.  GrabInfoRec::activatingKey contains the keycode
    which activated the passive grab, so we can deactivate it later in
    ProcessOtherEvents.
    
    Previously, CheckDeviceGrabs relied on its callers to set
    activatingKey, which not all callers were doing (I'm looking at you,
    ComputeFreezes).  Just set it in CheckDeviceGrabs instead.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 327873e..5131167 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1047,10 +1047,8 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
     switch(event->type)
     {
         case ET_KeyPress:
-            if (!grab && CheckDeviceGrabs(device, event, 0)) {
-                device->deviceGrab.activatingKey = key;
+            if (!grab && CheckDeviceGrabs(device, event, 0))
                 return;
-            }
             break;
         case ET_KeyRelease:
             if (grab && device->deviceGrab.fromPassiveGrab &&
diff --git a/dix/events.c b/dix/events.c
index 07f8b05..5e8166d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3582,6 +3582,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
     WindowPtr pWin = NULL;
     FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
     BOOL sendCore = (IsMaster(device) && device->coreEvents);
+    Bool ret = FALSE;
 
     if (event->type != ET_ButtonPress &&
         event->type != ET_KeyPress)
@@ -3601,7 +3602,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
             if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
                 break;
         if (i == device->spriteInfo->sprite->spriteTraceGood)
-            return FALSE;
+            goto out;
     }
 
     if (focus)
@@ -3610,23 +3611,32 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
 	{
 	    pWin = focus->trace[i];
 	    if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
-		return TRUE;
+	    {
+		ret = TRUE;
+		goto out;
+	    }
 	}
 
 	if ((focus->win == NoneWin) ||
 	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
 	    (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
-	    return FALSE;
+	    goto out;
     }
 
     for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
     {
 	pWin = device->spriteInfo->sprite->spriteTrace[i];
 	if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
-	    return TRUE;
+	{
+	    ret = TRUE;
+	    goto out;
+	}
     }
 
-    return FALSE;
+out:
+    if (ret == TRUE && event->type == ET_KeyPress)
+        device->deviceGrab.activatingKey = event->detail.key;
+    return ret;
 }
 
 /**
commit 0f9c6f2f822ff53b9d12ff4fa0b26cbeb7394ba5
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 13 21:36:05 2011 -0800

    xkb: Replace malloc(strlen) + strcpy with strdup
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/xkb/XKBGAlloc.c b/xkb/XKBGAlloc.c
index f49aead..65f92fd 100644
--- a/xkb/XKBGAlloc.c
+++ b/xkb/XKBGAlloc.c
@@ -647,9 +647,7 @@ register XkbPropertyPtr prop;
     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
 	if ((prop->name)&&(strcmp(name,prop->name)==0)) {
 	    free(prop->value);
-	    prop->value= malloc(strlen(value)+1);
-	    if (prop->value)
-		strcpy(prop->value,value);
+	    prop->value= strdup(value);
 	    return prop;
 	}    
     }
@@ -658,17 +656,15 @@ register XkbPropertyPtr prop;
 	return NULL;
     }
     prop= &geom->properties[geom->num_properties];
-    prop->name= malloc(strlen(name)+1);
+    prop->name= strdup(name);
     if (!prop->name)
 	return NULL;
-    strcpy(prop->name,name);
-    prop->value= malloc(strlen(value)+1);
+    prop->value= strdup(value);
     if (!prop->value) {
 	free(prop->name);
 	prop->name= NULL;
 	return NULL;
     }
-    strcpy(prop->value,value);
     geom->num_properties++;
     return prop;
 }
@@ -720,10 +716,9 @@ register XkbColorPtr color;
     }
     color= &geom->colors[geom->num_colors];
     color->pixel= pixel;
-    color->spec= malloc(strlen(spec)+1);
+    color->spec= strdup(spec);
     if (!color->spec)
 	return NULL;
-    strcpy(color->spec,spec);
     geom->num_colors++;
     return color;
 }
commit 682865c460945e1299f943561140f46439e2b4cb
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 13 21:36:04 2011 -0800

    XkbAddGeomProperty: Fix checks for malloc failure
    
    Check the variable we just tried to malloc, not the string we're copying
    and already checked for NULL at the beginning of the function.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/xkb/XKBGAlloc.c b/xkb/XKBGAlloc.c
index 3ec9eda..f49aead 100644
--- a/xkb/XKBGAlloc.c
+++ b/xkb/XKBGAlloc.c
@@ -659,11 +659,11 @@ register XkbPropertyPtr prop;
     }
     prop= &geom->properties[geom->num_properties];
     prop->name= malloc(strlen(name)+1);
-    if (!name)
+    if (!prop->name)
 	return NULL;
     strcpy(prop->name,name);
     prop->value= malloc(strlen(value)+1);
-    if (!value) {
+    if (!prop->value) {
 	free(prop->name);
 	prop->name= NULL;
 	return NULL;
commit aac1b435664819008989ed19f73e9c89920602c5
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 13 21:36:03 2011 -0800

    Replace _XkbDupString with Xstrdup
    
    The two functions have identical semantics, including safely returning
    NULL when NULL is passed in (which POSIX strdup does not guarantee).
    
    Some callers could probably be adjusted to call libc strdup directly,
    when we know the input is non-NULL.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 9f1507e..422bae0 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -846,10 +846,6 @@ extern _X_EXPORT XkbGeometryPtr XkbLookupNamedGeometry(
 	Bool *			/* shouldFree */
 );
 
-extern _X_EXPORT char *	_XkbDupString(
-	const char *		/* str */
-);
-
 extern _X_EXPORT void	XkbConvertCase(
 	KeySym 			/* sym */,
 	KeySym *		/* lower */,
diff --git a/xkb/maprules.c b/xkb/maprules.c
index 0c91cdc..f940899 100644
--- a/xkb/maprules.c
+++ b/xkb/maprules.c
@@ -391,8 +391,8 @@ Bool 		append = FALSE;
             }
             if (*words == '\0')
                 return FALSE;
-            group->name = _XkbDupString(gname);
-            group->words = _XkbDupString(words);
+            group->name = Xstrdup(gname);
+            group->words = Xstrdup(words);
             for (i = 1, words = group->words; *words; words++) {
                  if ( *words == ' ') {
                      *words++ = '\0';
@@ -443,16 +443,16 @@ Bool 		append = FALSE;
 	 rule->flags|= XkbRF_Append;
     else
 	 rule->flags|= XkbRF_Normal;
-    rule->model= _XkbDupString(tmp.name[MODEL]);
-    rule->layout= _XkbDupString(tmp.name[LAYOUT]);
-    rule->variant= _XkbDupString(tmp.name[VARIANT]);
-    rule->option= _XkbDupString(tmp.name[OPTION]);
+    rule->model= Xstrdup(tmp.name[MODEL]);
+    rule->layout= Xstrdup(tmp.name[LAYOUT]);
+    rule->variant= Xstrdup(tmp.name[VARIANT]);
+    rule->option= Xstrdup(tmp.name[OPTION]);
 
-    rule->keycodes= _XkbDupString(tmp.name[KEYCODES]);
-    rule->symbols= _XkbDupString(tmp.name[SYMBOLS]);
-    rule->types= _XkbDupString(tmp.name[TYPES]);
-    rule->compat= _XkbDupString(tmp.name[COMPAT]);
-    rule->geometry= _XkbDupString(tmp.name[GEOMETRY]);
+    rule->keycodes= Xstrdup(tmp.name[KEYCODES]);
+    rule->symbols= Xstrdup(tmp.name[SYMBOLS]);
+    rule->types= Xstrdup(tmp.name[TYPES]);
+    rule->compat= Xstrdup(tmp.name[COMPAT]);
+    rule->geometry= Xstrdup(tmp.name[GEOMETRY]);
 
     rule->layout_num = rule->variant_num = 0;
     for (i = 0; i < nread; i++) {
@@ -497,7 +497,7 @@ MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
 
    memset((char *)mdefs, 0, sizeof(XkbRF_MultiDefsRec));
    mdefs->model = defs->model;
-   mdefs->options = _XkbDupString(defs->options);
+   mdefs->options = Xstrdup(defs->options);
    if (mdefs->options) squeeze_spaces(mdefs->options); 
 
    if (defs->layout) {
@@ -506,7 +506,7 @@ MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
        } else {
            char *p;
            int i;
-           mdefs->layout[1] = _XkbDupString(defs->layout);
+           mdefs->layout[1] = Xstrdup(defs->layout);
 	   if (mdefs->layout[1] == NULL)
 	      return FALSE;
            squeeze_spaces(mdefs->layout[1]);
@@ -530,7 +530,7 @@ MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
        } else {
            char *p;
            int i;
-           mdefs->variant[1] = _XkbDupString(defs->variant);
+           mdefs->variant[1] = Xstrdup(defs->variant);
 	   if (mdefs->variant[1] == NULL)
 	      return FALSE;
            squeeze_spaces(mdefs->variant[1]);
@@ -566,7 +566,7 @@ Apply(char *src, char **dst)
 	    *dst= _Concat(*dst, src);
         } else {
             if (*dst == NULL)
-	        *dst= _XkbDupString(src);
+	        *dst= Xstrdup(src);
         }
     }
 }
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 6fd66c5..d98e352 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5619,17 +5619,17 @@ ProcXkbGetKbdByName(ClientPtr client)
     else fwant= stuff->want|stuff->need;
     if ((!names.compat)&&
         (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
-        names.compat= _XkbDupString("%");
+        names.compat= Xstrdup("%");
     }
     if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
-        names.types= _XkbDupString("%");
+        names.types= Xstrdup("%");
     }
     if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
-        names.symbols= _XkbDupString("%");
+        names.symbols= Xstrdup("%");
     }
     geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
     if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
-        names.geometry= _XkbDupString("%");
+        names.geometry= Xstrdup("%");
         geom_changed= FALSE;
     }
 
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index fbf8f14..3d3febb 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -221,15 +221,15 @@ static void
 XkbSetRulesUsed(XkbRMLVOSet *rmlvo)
 {
     free(XkbRulesUsed);
-    XkbRulesUsed= (rmlvo->rules?_XkbDupString(rmlvo->rules):NULL);
+    XkbRulesUsed= (rmlvo->rules?Xstrdup(rmlvo->rules):NULL);
     free(XkbModelUsed);
-    XkbModelUsed= (rmlvo->model?_XkbDupString(rmlvo->model):NULL);
+    XkbModelUsed= (rmlvo->model?Xstrdup(rmlvo->model):NULL);
     free(XkbLayoutUsed);
-    XkbLayoutUsed= (rmlvo->layout?_XkbDupString(rmlvo->layout):NULL);
+    XkbLayoutUsed= (rmlvo->layout?Xstrdup(rmlvo->layout):NULL);
     free(XkbVariantUsed);
-    XkbVariantUsed= (rmlvo->variant?_XkbDupString(rmlvo->variant):NULL);
+    XkbVariantUsed= (rmlvo->variant?Xstrdup(rmlvo->variant):NULL);
     free(XkbOptionsUsed);
-    XkbOptionsUsed= (rmlvo->options?_XkbDupString(rmlvo->options):NULL);
+    XkbOptionsUsed= (rmlvo->options?Xstrdup(rmlvo->options):NULL);
     if (XkbWantRulesProp)
 	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
     return;
@@ -240,23 +240,23 @@ XkbSetRulesDflts(XkbRMLVOSet *rmlvo)
 {
     if (rmlvo->rules) {
         free(XkbRulesDflt);
-        XkbRulesDflt= _XkbDupString(rmlvo->rules);
+        XkbRulesDflt= Xstrdup(rmlvo->rules);
     }
     if (rmlvo->model) {
 	free(XkbModelDflt);
-	XkbModelDflt= _XkbDupString(rmlvo->model);
+	XkbModelDflt= Xstrdup(rmlvo->model);
     }
     if (rmlvo->layout) {
 	free(XkbLayoutDflt);
-	XkbLayoutDflt= _XkbDupString(rmlvo->layout);
+	XkbLayoutDflt= Xstrdup(rmlvo->layout);
     }
     if (rmlvo->variant) {
 	free(XkbVariantDflt);
-	XkbVariantDflt= _XkbDupString(rmlvo->variant);
+	XkbVariantDflt= Xstrdup(rmlvo->variant);
     }
     if (rmlvo->options) {
 	free(XkbOptionsDflt);
-	XkbOptionsDflt= _XkbDupString(rmlvo->options);
+	XkbOptionsDflt= Xstrdup(rmlvo->options);
     }
     return;
 }
diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c
index 7aa9863..dea3473 100644
--- a/xkb/xkbfmisc.c
+++ b/xkb/xkbfmisc.c
@@ -241,7 +241,7 @@ unsigned	wantNames,wantConfig,wantDflts;
 	if (wantNames&XkmTypesMask) {
 	    if (old_names->types!=None) {
 		tmp= NameForAtom(old_names->types);
-		names->types= _XkbDupString(tmp);
+		names->types= Xstrdup(tmp);
 	    }
 	    else {
 		wantDflts|= XkmTypesMask;
@@ -251,7 +251,7 @@ unsigned	wantNames,wantConfig,wantDflts;
 	if (wantNames&XkmCompatMapMask) {
 	    if (old_names->compat!=None) {
 		tmp= NameForAtom(old_names->compat);
-		names->compat= _XkbDupString(tmp);
+		names->compat= Xstrdup(tmp);
 	    }
 	    else wantDflts|= XkmCompatMapMask;
 	    complete|= XkmCompatMapMask; 
@@ -260,13 +260,13 @@ unsigned	wantNames,wantConfig,wantDflts;
 	    if (old_names->symbols==None)
 		return FALSE;
 	    tmp= NameForAtom(old_names->symbols);
-	    names->symbols= _XkbDupString(tmp);
+	    names->symbols= Xstrdup(tmp);
 	    complete|= XkmSymbolsMask; 
 	}
 	if (wantNames&XkmKeyNamesMask) {
 	   if (old_names->keycodes!=None) {
 		tmp= NameForAtom(old_names->keycodes);
-		names->keycodes= _XkbDupString(tmp);
+		names->keycodes= Xstrdup(tmp);
 	    }
 	    else wantDflts|= XkmKeyNamesMask;
 	    complete|= XkmKeyNamesMask;
@@ -275,7 +275,7 @@ unsigned	wantNames,wantConfig,wantDflts;
 	    if (old_names->geometry==None)
 		return FALSE;
 	    tmp= NameForAtom(old_names->geometry);
-	    names->geometry= _XkbDupString(tmp);
+	    names->geometry= Xstrdup(tmp);
 	    complete|= XkmGeometryMask; 
 	    wantNames&= ~XkmGeometryMask;
 	}
diff --git a/xkb/xkmread.c b/xkb/xkmread.c
index b564195..e8b97dc 100644
--- a/xkb/xkmread.c
+++ b/xkb/xkmread.c
@@ -51,19 +51,6 @@ XkbInternAtom(char *str,Bool only_if_exists)
     return MakeAtom(str,strlen(str),!only_if_exists);
 }
 
-char *
-_XkbDupString(const char *str)
-{
-char *new;
-   
-   if (str==NULL)
-	return NULL;
-   new= calloc(strlen(str)+1,sizeof(char));
-   if (new)
-	strcpy(new,str);
-   return new;
-}
-
 /***====================================================================***/
 
 static void *
@@ -845,9 +832,9 @@ int		nRead=0;
 	    doodad->text.height= doodadWire.text.height;
 	    doodad->text.color_ndx= doodadWire.text.color_ndx;
 	    nRead+= XkmGetCountedString(file,buf,100);
-	    doodad->text.text= _XkbDupString(buf);
+	    doodad->text.text= Xstrdup(buf);
 	    nRead+= XkmGetCountedString(file,buf,100);
-	    doodad->text.font= _XkbDupString(buf);
+	    doodad->text.font= Xstrdup(buf);
 	    break;
 	case XkbIndicatorDoodad:
 	    doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx;
@@ -859,7 +846,7 @@ int		nRead=0;
 	    doodad->logo.color_ndx= doodadWire.logo.color_ndx;
 	    doodad->logo.shape_ndx= doodadWire.logo.shape_ndx;
 	    nRead+= XkmGetCountedString(file,buf,100);
-	    doodad->logo.logo_name= _XkbDupString(buf);
+	    doodad->logo.logo_name= Xstrdup(buf);
 	    break;
 	default:
 	    /* report error? */
@@ -1021,7 +1008,7 @@ XkbGeometrySizesRec	sizes;
     geom->width_mm= wireGeom.width_mm;
     geom->height_mm= wireGeom.height_mm;
     nRead+= XkmGetCountedString(file,buf,100);
-    geom->label_font= _XkbDupString(buf);
+    geom->label_font= Xstrdup(buf);
     if (wireGeom.num_properties>0) {
 	char val[1024];
 	for (i=0;i<wireGeom.num_properties;i++) {
commit a4a2e814d5d0e6152307a301eda1d6fc1c555aaa
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 13 21:36:02 2011 -0800

    xkb: Use snprintf to measure string lengths instead of manual strlen math
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 51b5777..9686ea8 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -303,15 +303,16 @@ FILE *	file;
                 &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':')
 #endif
                 ) {
-	    if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir)
-		     +strlen(mapName)+6 <= PATH_MAX)
-	    {
-	        sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory,
-					xkm_output_dir,mapName);
-	    }
+            if (snprintf(buf, PATH_MAX, "%s/%s%s.xkm", XkbBaseDirectory,
+                         xkm_output_dir, mapName) >= PATH_MAX)
+                buf[0] = '\0';
+	}
+	else
+	{
+            if (snprintf(buf, PATH_MAX, "%s%s.xkm", xkm_output_dir, mapName)
+                >= PATH_MAX)
+                buf[0] = '\0';
 	}
-	else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX)
-	    sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName);
 	if (buf[0] != '\0')
 	    file= fopen(buf,"rb");
 	else file= NULL;
@@ -388,11 +389,11 @@ XkbRF_RulesPtr	rules;
     if (!rules_name)
 	return FALSE;
 
-    if (strlen(XkbBaseDirectory) + strlen(rules_name) + 8 > PATH_MAX) {
+    if (snprintf(buf, PATH_MAX, "%s/rules/%s", XkbBaseDirectory, rules_name)
+        >= PATH_MAX) {
         LogMessage(X_ERROR, "XKB: Rules name is too long\n");
         return FALSE;
     }
-    sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name);
 
     file = fopen(buf, "r");
     if (!file) {
diff --git a/xkb/maprules.c b/xkb/maprules.c
index c683c0d..0c91cdc 100644
--- a/xkb/maprules.c
+++ b/xkb/maprules.c
@@ -945,9 +945,8 @@ Bool		ok;
     if ((!base)||(!rules))
 	return FALSE;
     if (locale) {
-	if (strlen(base)+strlen(locale)+2 > PATH_MAX)
+	if (snprintf(buf, PATH_MAX, "%s-%s", base, locale) >= PATH_MAX)
 	    return FALSE;
-	sprintf(buf,"%s-%s", base, locale);
     }
     else {
 	if (strlen(base)+1 > PATH_MAX)
commit 296561506a91742cc150a0fb6fc0df5dbe98c780
Author: Rami Ylimäki <rami.ylimaki at vincit.fi>
Date:   Wed Dec 22 16:57:17 2010 +0200

    Xext: Use general OS functions to determine client command string in SELinux.
    
    Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
    Reviewed-by: Tiago Vignatti <tiago.vignatti at nokia.com>

diff --git a/Xext/xselinux_hooks.c b/Xext/xselinux_hooks.c
index 560e1e9..f1d8e5d 100644
--- a/Xext/xselinux_hooks.c
+++ b/Xext/xselinux_hooks.c
@@ -40,6 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "propertyst.h"
 #include "extnsionst.h"
 #include "xacestr.h"
+#include "client.h"
 #include "../os/osdep.h"
 #define _XSELINUX_NEED_FLASK_MAP
 #include "xselinuxint.h"
@@ -129,26 +130,25 @@ SELinuxLabelClient(ClientPtr client)
 
     /* For local clients, try and determine the executable name */
     if (XaceIsLocal(client)) {
-	struct ucred creds;
-	socklen_t len = sizeof(creds);
-	char path[PATH_MAX + 1];
-	size_t bytes;
-
-	memset(&creds, 0, sizeof(creds));
-	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
-	    goto finish;
+	/* Get cached command name if CLIENTIDS is enabled. */
+	const char *cmdname = GetClientCmdName(client);
+	Bool cached = (cmdname != NULL);
+	/* If CLIENTIDS is disabled, figure out the command name from
+	 * scratch. */
+	if (!cmdname)
+	{
+	    pid_t pid = DetermineClientPid(client);
+	    if (pid != -1)
+		DetermineClientCmd(pid, &cmdname, NULL);
+	}
 
-	snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
+	if (!cmdname)
 	    goto finish;
 
-	bytes = read(fd, path, PATH_MAX + 1);
-	close(fd);
-	if (bytes <= 0)
-	    goto finish;
+	strncpy(subj->command, cmdname, COMMAND_LEN - 1);
 
-	strncpy(subj->command, path, COMMAND_LEN - 1);
+	if (!cached)
+	    free((void *) cmdname); /* const char * */
     }
 
 finish:
commit 1e933665bef26c74196bb7c59910e6a78bcacf0e
Author: Rami Ylimäki <rami.ylimaki at vincit.fi>
Date:   Wed Dec 22 16:51:09 2010 +0200

    os: Add facilities for client ID tracking.
    
    An interface is provided for figuring out the PID and process name of
    a client. Make some existing functionality from SELinux and IA
    extensions available for general use.
    
    Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
    Reviewed-by: Tiago Vignatti <tiago.vignatti at nokia.com>

diff --git a/configure.ac b/configure.ac
index cbbf5c3..202edf0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -623,6 +623,7 @@ AC_ARG_ENABLE(vbe,            AS_HELP_STRING([--enable-vbe], [Build Xorg with VB
 AC_ARG_ENABLE(int10-module,     AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes])
 AC_ARG_ENABLE(windowswm,      AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no])
 AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
+AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -976,6 +977,18 @@ if test "x$RES" = xyes; then
 	REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO"
 fi
 
+# The XRes extension may support client ID tracking only if it has
+# been specifically enabled. Client ID tracking is implicitly not
+# supported if XRes extension is disabled.
+AC_MSG_CHECKING([whether to track client ids])
+if test "x$RES" = xyes && test "x$CLIENTIDS" = xyes; then
+	AC_DEFINE(CLIENTIDS, 1, [Support client ID tracking])
+else
+	CLIENTIDS=no
+fi
+AC_MSG_RESULT([$CLIENTIDS])
+AM_CONDITIONAL(CLIENTIDS, [test "x$CLIENTIDS" = xyes])
+
 if test "x$GLX" = xyes; then
 	PKG_CHECK_MODULES([XLIB], [x11])
 	PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 7b2132d..601b14a 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -130,6 +130,7 @@ int ProcInitialConnection();
 #include "inputstr.h"
 #include "xkbsrv.h"
 #include "site.h"
+#include "client.h"
 
 #ifdef XSERVER_DTRACE
 #include "registry.h"
@@ -3459,6 +3460,9 @@ CloseDownClient(ClientPtr client)
 	    CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
 	} 	    
 	FreeClientResources(client);
+	/* Disable client ID tracking. This must be done after
+	 * ClientStateCallback. */
+	ReleaseClientIds(client);
 #ifdef XSERVER_DTRACE
 	XSERVER_CLIENT_DISCONNECT(client->index);
 #endif	
@@ -3496,6 +3500,7 @@ void InitClient(ClientPtr client, int i, pointer ospriv)
     client->smart_start_tick = SmartScheduleTime;
     client->smart_stop_tick = SmartScheduleTime;
     client->smart_check_tick = SmartScheduleTime;
+    client->clientIds = NULL;
 }
 
 /************************
@@ -3535,6 +3540,11 @@ ClientPtr NextAvailableClient(pointer ospriv)
 	currentMaxClients++;
     while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
 	nextFreeClientID++;
+
+    /* Enable client ID tracking. This must be done before
+     * ClientStateCallback. */
+    ReserveClientIds(client);
+
     if (ClientStateCallback)
     {
 	NewClientInfoRec clientinfo;
diff --git a/dix/main.c b/dix/main.c
index 692bec1..31e2d48 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -104,6 +104,7 @@ Equipment Corporation.
 #include "extnsionst.h"
 #include "privates.h"
 #include "registry.h"
+#include "client.h"
 #ifdef PANORAMIX
 #include "panoramiXsrv.h"
 #else
@@ -258,6 +259,7 @@ int main(int argc, char *argv[], char *envp[])
         InitCoreDevices();
 	InitInput(argc, argv);
 	InitAndStartDevices();
+	ReserveClientIds(serverClient);
 
 	dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
 
@@ -323,6 +325,7 @@ int main(int argc, char *argv[], char *envp[])
 	    screenInfo.numScreens = i;
 	}
 
+	ReleaseClientIds(serverClient);
 	dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT);
 	serverClient->devPrivates = NULL;
 
diff --git a/hw/xfree86/loader/sdksyms.sh b/hw/xfree86/loader/sdksyms.sh
index f60b8ed..18bb735 100755
--- a/hw/xfree86/loader/sdksyms.sh
+++ b/hw/xfree86/loader/sdksyms.sh
@@ -259,6 +259,7 @@ cat > sdksyms.c << EOF
 #include "colormap.h"
 #include "colormapst.h"
 #include "hotplug.h"
+#include "client.h"
 #include "cursor.h"
 #include "cursorstr.h"
 #include "dix.h"
diff --git a/include/Makefile.am b/include/Makefile.am
index 42f0082..6f63c76 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -3,6 +3,7 @@ sdk_HEADERS =		\
 	XIstubs.h	\
 	Xprintf.h	\
 	callback.h	\
+	client.h	\
 	closestr.h	\
 	closure.h	\
 	colormap.h	\
diff --git a/include/client.h b/include/client.h
new file mode 100644
index 0000000..aaafc7d
--- /dev/null
+++ b/include/client.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
+ * rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Author: Rami Ylimäki <rami.ylimaki at vincit.fi> */
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif /* HAVE_DIX_CONFIG_H */
+#include <X11/Xfuncproto.h>
+#include <sys/types.h>
+
+/* Client IDs. Use GetClientPid, GetClientCmdName and GetClientCmdArgs
+ * instead of accessing the fields directly. */
+typedef struct {
+    pid_t pid;           /* process ID, -1 if not available */
+    const char *cmdname; /* process name, NULL if not available */
+    const char *cmdargs; /* process arguments, NULL if not available */
+} ClientIdRec, *ClientIdPtr;
+
+struct _Client;
+
+/* Initialize and clean up. */
+void ReserveClientIds(struct _Client *client);
+void ReleaseClientIds(struct _Client *client);
+
+/* Determine client IDs for caching. Exported on purpose for
+ * extensions such as SELinux. */
+extern _X_EXPORT pid_t DetermineClientPid(struct _Client *client);
+extern _X_EXPORT void DetermineClientCmd(pid_t, const char **cmdname, const char **cmdargs);
+
+/* Query cached client IDs. Exported on purpose for drivers. */
+extern _X_EXPORT pid_t GetClientPid(struct _Client *client);
+extern _X_EXPORT const char *GetClientCmdName(struct _Client *client);
+extern _X_EXPORT const char *GetClientCmdArgs(struct _Client *client);
+
+#endif /* CLIENT_H */
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 5622766..fc93f3e 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -279,6 +279,9 @@
 /* Support X resource extension */
 #undef RES
 
+/* Support client ID tracking in X resource extension */
+#undef CLIENTIDS
+
 /* Support MIT-SCREEN-SAVER extension */
 #undef SCREENSAVER
 
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 8547b16..443e8b0 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -24,6 +24,7 @@ SOFTWARE.
 #ifndef DIXSTRUCT_H
 #define DIXSTRUCT_H
 
+#include "client.h"
 #include "dix.h"
 #include "resource.h"
 #include "cursor.h"
@@ -121,6 +122,7 @@ typedef struct _Client {
     long    smart_check_tick;
     
     DeviceIntPtr clientPtr;
+    ClientIdPtr  clientIds;
 }           ClientRec;
 
 /*
diff --git a/os/Makefile.am b/os/Makefile.am
index 66a4a0f..91ca110 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -12,6 +12,7 @@ libos_la_SOURCES = 	\
 	access.c	\
 	auth.c		\
 	backtrace.c	\
+	client.c	\
 	connection.c	\
 	io.c		\
 	mitauth.c	\
diff --git a/os/client.c b/os/client.c
new file mode 100644
index 0000000..1311855
--- /dev/null
+++ b/os/client.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
+ * rights reserved.
+ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * This file contains functionality for identifying clients by various
+ * means. The primary purpose of identification is to simply aid in
+ * finding out which clients are using X server and how they are using
+ * it. For example, it's often necessary to monitor what requests
+ * clients are executing (to spot bad behaviour) and how they are
+ * allocating resources in X server (to spot excessive resource
+ * usage).
+ *
+ * This framework automatically allocates information, that can be
+ * used for client identification, when a client connects to the
+ * server. The information is freed when the client disconnects. The
+ * allocated information is just a collection of various IDs, such as
+ * PID and process name for local clients, that are likely to be
+ * useful in analyzing X server usage.
+ *
+ * Users of the framework can query ID information about clients at
+ * any time. To avoid repeated polling of IDs the users can also
+ * subscribe for notifications about the availability of ID
+ * information. IDs have been allocated before ClientStateCallback is
+ * called with ClientStateInitial state. Similarly the IDs will be
+ * released after ClientStateCallback is called with ClientStateGone
+ * state.
+ *
+ * Author: Rami Ylimäki <rami.ylimaki at vincit.fi>
+ */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "client.h"
+#include "os.h"
+#include "dixstruct.h"
+
+/**
+ * Try to determine a PID for a client from its connection
+ * information. This should be called only once when new client has
+ * connected, use GetClientPid to determine the PID at other times.
+ *
+ * @param[in] client Connection linked to some process.
+ *
+ * @return PID of the client. Error (-1) if PID can't be determined
+ *         for the client.
+ *
+ * @see GetClientPid
+ */
+pid_t DetermineClientPid(struct _Client *client)
+{
+    LocalClientCredRec *lcc = NULL;
+    pid_t pid = -1;
+
+    if (client == NullClient)
+        return pid;
+
+    if (client == serverClient)
+        return getpid();
+
+    if (GetLocalClientCreds(client, &lcc) != -1)
+    {
+        if (lcc->fieldsSet & LCC_PID_SET)
+            pid = lcc->pid;
+        FreeLocalClientCreds(lcc);
+    }
+
+    return pid;
+}
+
+/**
+ * Try to determine a command line string for a client based on its
+ * PID. Note that mapping PID to a command hasn't been implemented for
+ * some operating systems. This should be called only once when a new
+ * client has connected, use GetClientCmdName/Args to determine the
+ * string at other times.
+ *
+ * @param[in]  pid     Process ID of a client.
+
+ * @param[out] cmdname Client process name without arguments. You must
+ *                     release this by calling free. On error NULL is
+ *                     returned. Pass NULL if you aren't interested in
+ *                     this value.
+ * @param[out] cmdargs Arguments to client process. Useful for
+ *                     identifying a client that is executed from a
+ *                     launcher program. You must release this by
+ *                     calling free. On error NULL is returned. Pass
+ *                     NULL if you aren't interested in this value.
+ *
+ * @see GetClientCmdName/Args
+ */
+void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
+{
+    char path[PATH_MAX + 1];
+    int totsize = 0;
+    int cmdsize = 0;
+    int argsize = 0;
+    int fd = 0;
+
+    if (cmdname)
+        *cmdname = NULL;
+    if (cmdargs)
+        *cmdargs = NULL;
+
+    if (pid == -1)
+        return;
+
+    /* Check if /proc/pid/cmdline exists. It's not supported on all
+     * operating systems. */
+    if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
+        return;
+    fd = open(path, O_RDONLY);
+    if (fd < 0)
+        return;
+
+    /* Read the contents of /proc/pid/cmdline. It should contain the
+     * process name and arguments. */
+    totsize = read(fd, path, sizeof(path));
+    if (totsize <= 0)
+        return;
+    if (close(fd) < 0)
+        return;
+    path[totsize - 1] = '\0';
+
+    /* Contruct the process name without arguments. */
+    cmdsize = strlen(path) + 1;
+    if (cmdname)
+    {
+        char *name = malloc(cmdsize);
+        if (name)
+        {
+            strncpy(name, path, cmdsize);
+            name[cmdsize - 1] = '\0';
+            *cmdname = name;
+        }
+    }
+
+    /* Construct the arguments for client process. */
+    argsize = totsize - cmdsize;
+    if (cmdargs && (argsize > 0))
+    {
+        char *args = malloc(argsize);
+        if (args)
+        {
+            int i = 0;
+            for (i = 0; i < (argsize - 1); ++i)
+            {
+                const char c = path[cmdsize + i];
+                args[i] = (c == '\0') ? ' ' : c;
+            }
+            args[argsize - 1] = '\0';
+            *cmdargs = args;
+        }
+    }
+}
+
+/**
+ * Called when a new client connects. Allocates client ID information.
+ *
+ * @param[in] client Recently connected client.
+ */
+void ReserveClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+    if (client == NullClient)
+        return;
+
+    assert(!client->clientIds);
+    client->clientIds = calloc(1, sizeof(ClientIdRec));
+    if (!client->clientIds)
+        return;
+
+    client->clientIds->pid = DetermineClientPid(client);
+    if (client->clientIds->pid != -1)
+        DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs);
+
+    DebugF("client(%lx): Reserved pid(%d).\n",
+           client->clientAsMask, client->clientIds->pid);
+    DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n",
+           client->clientAsMask,
+           client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+           client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Called when an existing client disconnects. Frees client ID
+ * information.
+ *
+ * @param[in] client Recently disconnected client.
+ */
+void ReleaseClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+    if (client == NullClient)
+        return;
+
+    if (!client->clientIds)
+        return;
+
+    DebugF("client(%lx): Released pid(%d).\n",
+           client->clientAsMask, client->clientIds->pid);
+    DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n",
+           client->clientAsMask,
+           client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+           client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+
+    free((void *) client->clientIds->cmdname); /* const char * */
+    free((void *) client->clientIds->cmdargs); /* const char * */
+    free(client->clientIds);
+    client->clientIds = NULL;
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Get cached PID of a client.
+ *
+ * param[in] client Client whose PID has been already cached.
+ *
+ * @return Cached client PID. Error (-1) if called:
+ *         - before ClientStateInitial client state notification
+ *         - after ClientStateGone client state notification
+ *         - for remote clients
+ *
+ * @see DetermineClientPid
+ */
+pid_t GetClientPid(struct _Client *client)
+{
+    if (client == NullClient)
+        return -1;
+
+    if (!client->clientIds)
+        return -1;
+
+    return client->clientIds->pid;
+}
+
+/**
+ * Get cached command name string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ *                  cached.
+ *
+ * @return Cached client command name. Error (NULL) if called:
+ *         - before ClientStateInitial client state notification
+ *         - after ClientStateGone client state notification
+ *         - for remote clients
+ *         - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *GetClientCmdName(struct _Client *client)
+{
+    if (client == NullClient)
+        return NULL;
+
+    if (!client->clientIds)
+        return NULL;
+
+    return client->clientIds->cmdname;
+}
+
+/**
+ * Get cached command arguments string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ *                  cached.
+ *
+ * @return Cached client command arguments. Error (NULL) if called:
+ *         - before ClientStateInitial client state notification
+ *         - after ClientStateGone client state notification
+ *         - for remote clients
+ *         - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *GetClientCmdArgs(struct _Client *client)
+{
+    if (client == NullClient)
+        return NULL;
+
+    if (!client->clientIds)
+        return NULL;
+
+    return client->clientIds->cmdargs;
+}
commit 671b2a1823a1c90d0b6254e2e2af8865151fff8c
Author: Rami Ylimäki <rami.ylimaki at vincit.fi>
Date:   Wed Dec 22 16:38:54 2010 +0200

    config: Fix linking order of Xnest libraries.
    
    MAIN depends on DIX and not vice versa.
    
    Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>

diff --git a/configure.ac b/configure.ac
index de172ce..cbbf5c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1507,7 +1507,7 @@ if test "x$XNEST" = xyes; then
 	if test "x$have_xnest" = xno; then
 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
 	fi
-	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB"
+	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XNEST_LIBS])
 	AC_SUBST([XNEST_SYS_LIBS])
commit 2b364bf970b2ce6829af656990c33afd0d365f3c
Author: Rami Ylimäki <rami.ylimaki at vincit.fi>
Date:   Tue Jun 15 14:44:38 2010 +0200

    Revert "os: Prevent backtrace from being stopped in noreturn functions."
    
    This reverts commit 579715f830fbbca9e1ecb17dc18176132f5969e7.
    
    The patch is not needed anymore. I haven't encountered backtrace
    problems with GCC 4.3.3. Even if the problems still persisted, this
    commit should be removed and instead the definition of _X_NORETURN
    should be modified to be empty if GCC/ARM is used. However, currently
    it seems that ARM backtraces are OK even if _X_NORETURN is used and
    -mapcs-frame is not defined in CFLAGS.
    
    Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
    Reviewed-by: Jamey Sharp <jamey at minilop.net>

diff --git a/configure.ac b/configure.ac
index 1ceffe7..de172ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -312,19 +312,6 @@ AC_CHECK_HEADER([execinfo.h],[
     ])]
 )
 
-dnl ARM needs additional compiler flags for proper backtraces if GCC is
-dnl used. Compile a dummy program with the -mapcs-frame option. If it
-dnl succeeds, we know that we are building for ARM with GCC.
-old_CFLAGS="$CFLAGS"
-CFLAGS="-mapcs-frame"
-AC_COMPILE_IFELSE(
-        AC_LANG_PROGRAM([[ ]]),
-        ARM_BACKTRACE_CFLAGS="$CFLAGS",
-        ARM_BACKTRACE_CFLAGS=""
-)
-CFLAGS="$old_CFLAGS"
-AC_SUBST(ARM_BACKTRACE_CFLAGS)
-
 dnl ---------------------------------------------------------------------------
 dnl Bus options and CPU capabilities.  Replaces logic in
 dnl hw/xfree86/os-support/bus/Makefile.am, among others.
diff --git a/os/Makefile.am b/os/Makefile.am
index 3e4f2c5..66a4a0f 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -1,19 +1,11 @@
-noinst_LTLIBRARIES = libos.la liblog.la
+noinst_LTLIBRARIES = libos.la
 
 AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
 
 SECURERPC_SRCS = rpcauth.c
 XDMCP_SRCS = xdmcp.c
 STRLCAT_SRCS = strlcat.c strlcpy.c
-
-# Build a convenience library liblog.la that will be added into
-# libos.la. The split is done so that log.c can be built with
-# different compiler options.
-liblog_la_SOURCES = log.c
-# Add flags needed for proper backtraces of functions marked with GCC
-# __attribute__((noreturn)). Currently those flags are needed for
-# FatalError and AbortServer in log.c.
-liblog_la_CFLAGS = $(AM_CFLAGS) $(ARM_BACKTRACE_CFLAGS)
+XORG_SRCS = log.c
 
 libos_la_SOURCES = 	\
 	WaitFor.c	\
@@ -32,8 +24,9 @@ libos_la_SOURCES = 	\
 	xdmauth.c	\
 	xsha1.c		\
 	xstrans.c	\
-	xprintf.c
-libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) liblog.la
+	xprintf.c	\
+	$(XORG_SRCS)
+libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS)
 
 if SECURE_RPC
 libos_la_SOURCES += $(SECURERPC_SRCS)


More information about the Xquartz-changes mailing list