[Xquartz-changes] xserver: Branch 'server-1.12-apple' - 24 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Thu Oct 20 08:50:14 PDT 2011


Rebased ref, commits from common ancestor:
commit 23c73de6c142c64a5fc50f89062a4721baa1e862
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 eaa21ad..e65a1c0 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -2049,11 +2049,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 57c93fd..127e5c7 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);
     if (pMask)
 	miCompositeSourceValidate (pMask);
     
-    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 (
 	(pixman_format_code_t)pict->format,
-	pixmap->drawable.width, pixmap->drawable.height,
+	pict->pDrawable->width, pict->pDrawable->height,
 	(uint32_t *)bits, stride * sizeof (FbStride));
 
     if (!image)
@@ -189,55 +184,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)
@@ -267,8 +240,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);
@@ -301,7 +273,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;
 
@@ -310,7 +283,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)
     {
@@ -331,19 +304,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 0b5a638..fbe2647 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -39,12 +39,11 @@ fbAddTraps (PicturePtr	pPicture,
 	    xTrap	*traps)
 {
     pixman_image_t *image;
-    int dst_xoff, dst_yoff;
 
-    if (!(image = image_from_pict (pPicture, FALSE, &dst_xoff, &dst_yoff)))
+    if (!(image = image_from_pict (pPicture, FALSE)))
 	return;
     
-    pixman_add_traps (image, x_off + dst_xoff, y_off + dst_yoff,
+    pixman_add_traps (image, x_off, y_off,
 		      ntrap, (pixman_trap_t *)traps);
 
     free_pixman_pict (pPicture, image);
@@ -57,14 +56,13 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
 		      int	    y_off)
 {
     pixman_image_t *image;
-    int	dst_xoff, dst_yoff;
 
-    if (!(image = image_from_pict (pPicture, FALSE, &dst_xoff, &dst_yoff)))
+    if (!(image = image_from_pict (pPicture, FALSE)))
 	return;
 
     pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *)trap,
-				x_off + dst_xoff,
-				y_off + dst_yoff);
+				x_off,
+				y_off);
 
     free_pixman_pict (pPicture, image);
 }
@@ -77,13 +75,12 @@ fbAddTriangles (PicturePtr  pPicture,
 		xTriangle *tris)
 {
     pixman_image_t *image;
-    int dst_xoff, dst_yoff;
 
-    if (!(image = image_from_pict (pPicture, FALSE, &dst_xoff, &dst_yoff)))
+    if (!(image = image_from_pict (pPicture, FALSE)))
 	return;
     
     pixman_add_triangles (image,
-			  dst_xoff + x_off, dst_yoff + y_off,
+			  x_off, y_off,
 			  ntri, (pixman_triangle_t *)tris);
 
     free_pixman_pict (pPicture, image);
@@ -110,13 +107,11 @@ fbShapes (CompositeShapesFunc	composite,
 	  const uint8_t *	shapes)
 {
     pixman_image_t *src, *dst;
-    int src_xoff, src_yoff;
-    int dst_xoff, dst_yoff;
 
     miCompositeSourceValidate (pSrc);
 
-    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
-    dst = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+    src = image_from_pict (pSrc, FALSE);
+    dst = image_from_pict (pDst, TRUE);
 
     if (src && dst)
     {
@@ -136,10 +131,10 @@ fbShapes (CompositeShapesFunc	composite,
 	    for (i = 0; i < nshapes; ++i)
 	    {
 		composite (op, src, dst, format,
-			   xSrc + src_xoff,
-			   ySrc + src_yoff,
-			   dst_xoff,
-			   dst_yoff,
+			   xSrc,
+			   ySrc,
+			   0,
+			   0,
 			   1, shapes + i * shape_size);
 	    }
 	}
@@ -162,10 +157,10 @@ fbShapes (CompositeShapesFunc	composite,
 	    }
 	    
 	    composite (op, src, dst, format,
-		       xSrc + src_xoff,
-		       ySrc + src_yoff,
-		       dst_xoff,
-		       dst_yoff,
+		       xSrc,
+		       ySrc,
+		       0,
+		       0,
 		       nshapes, shapes);
 	}
 
commit 11c55731894db8e5c3a8052f2b11d3b9be8c42cf
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 0f1ebe5..dcbfe1c 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;
 
@@ -591,6 +605,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;
 	
@@ -599,6 +625,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;
@@ -661,6 +693,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 4c987d830188548f39afffd4736f519cdda7178a
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Oct 16 02:12:38 2011 -0700

    Xnest: Match the host's keymap
    
    This was a regression.
    
    Introduced by: 08363c5830bdea34012dcd954b45ccfdc79a3a7e and
                   32db27a7f867b503c2840ca7b815e96d10be9210
    Masked by: 1e69fd4a60147287b31e53bfc61543fb17bb82c8
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xnest/Keyboard.c b/hw/xnest/Keyboard.c
index ec629dc..c20ad12 100644
--- a/hw/xnest/Keyboard.c
+++ b/hw/xnest/Keyboard.c
@@ -114,11 +114,13 @@ xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
 int
 xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 {
+  XModifierKeymap *modifier_keymap;
   KeySym *keymap;
   int mapWidth;
   int min_keycode, max_keycode;
   KeySymsRec keySyms;
-  int i;
+  CARD8 modmap[MAP_LENGTH];
+  int i, j;
   XKeyboardState values;
   XkbDescPtr xkb;
   int op, event, error, major, minor;
@@ -130,7 +132,7 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 #ifdef _XSERVER64
       {
 	KeySym64 *keymap64;
-	int i, len;
+	int len;
 	keymap64 = XGetKeyboardMapping(xnestDisplay,
 				     min_keycode,
 				     max_keycode - min_keycode + 1,
@@ -147,7 +149,17 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
 				   max_keycode - min_keycode + 1,
 				   &mapWidth);
 #endif
-      
+
+      memset(modmap, 0, sizeof(modmap));
+      modifier_keymap = XGetModifierMapping(xnestDisplay);
+      for (j = 0; j < 8; j++)
+            for(i = 0; i < modifier_keymap->max_keypermod; i++) {
+                  CARD8 keycode;
+                  if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i]))
+                      modmap[keycode] |= 1<<j;
+      }
+      XFreeModifiermap(modifier_keymap);
+
       keySyms.minKeyCode = min_keycode;
       keySyms.maxKeyCode = max_keycode;
       keySyms.mapWidth = mapWidth;
@@ -165,7 +177,12 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
       XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
 
       InitKeyboardDeviceStruct(pDev, NULL,
-			       xnestBell, xnestChangeKeyboardControl);
+                               xnestBell, xnestChangeKeyboardControl);
+ 
+      XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
+                            keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+                            modmap, serverClient);
+
       XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
       XkbFreeKeyboard(xkb, 0, False);
       free(keymap);
commit 0fc0c01904d607a94c94b5b30d9f71ee5cde932b
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Mon Oct 17 23:45:32 2011 -0700

    test: Add unit test for mieq
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/test/input.c b/test/input.c
index 52bc2f5..5b4c8c1 100644
--- a/test/input.c
+++ b/test/input.c
@@ -40,6 +40,7 @@
 #include "dixgrabs.h"
 #include "eventstr.h"
 #include "inpututils.h"
+#include "mi.h"
 #include "assert.h"
 
 /**
@@ -1606,6 +1607,73 @@ dix_double_fp_conversion(void)
     }
 }
 
+/* The mieq test verifies that events added to the queue come out in the same
+ * order that they went in.
+ */
+static uint32_t mieq_test_event_last_processed;
+
+static void
+mieq_test_event_handler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
+    RawDeviceEvent *e = (RawDeviceEvent *)ie;
+
+    assert(e->type == ET_RawMotion);
+    assert(e->flags > mieq_test_event_last_processed);
+    mieq_test_event_last_processed = e->flags;
+}
+
+static void _mieq_test_generate_events(uint32_t start, uint32_t count) {
+    count += start;
+    while (start < count) {
+        RawDeviceEvent e = {0};
+        e.header = ET_Internal;
+        e.type = ET_RawMotion;
+        e.length = sizeof(e);
+        e.time = GetTimeInMillis();
+        e.flags = start;
+
+        mieqEnqueue(NULL, (InternalEvent*)&e);
+
+        start++;
+    }
+}
+
+#define mieq_test_generate_events(c) { _mieq_test_generate_events(next, c); next += c; }
+
+static void
+mieq_test(void) {
+    uint32_t next = 1;
+
+    mieq_test_event_last_processed = 0;
+    mieqInit();
+    mieqSetHandler(ET_RawMotion, mieq_test_event_handler);
+
+    /* Enough to fit the buffer but trigger a grow */
+    mieq_test_generate_events(180);
+
+    /* We should resize to 512 now */
+    mieqProcessInputEvents();
+
+    /* Some should now get dropped */
+    mieq_test_generate_events(500);
+
+    /* Tell us how many got dropped, 1024 now */
+    mieqProcessInputEvents();
+
+    /* Now make it 2048 */
+    mieq_test_generate_events(900);
+    mieqProcessInputEvents();
+
+    /* Now make it 4096 (max) */
+    mieq_test_generate_events(1950);
+    mieqProcessInputEvents();
+
+    /* Now overflow one last time with the maximal queue and reach the verbosity limit */
+    mieq_test_generate_events(10000);
+    mieqProcessInputEvents();
+
+    mieqFini();
+}
+
 int main(int argc, char** argv)
 {
     dix_double_fp_conversion();
@@ -1624,6 +1692,7 @@ int main(int argc, char** argv)
     dix_valuator_alloc();
     dix_get_master();
     input_option_test();
+    mieq_test();
 
     return 0;
 }
commit b120630fbb231cd6a096eb749c18c8dcdc653c34
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Mon Oct 17 21:16:37 2011 -0700

    mieq: Reserve some space in EQ for release and other special events
    
    The last 64 events in the event queue will be reserved for release
    events in order to help return the system to a cleaner state when
    it comes back from a soft wedge.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/mi/mieq.c b/mi/mieq.c
index c9a4370..9394074 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -60,7 +60,8 @@ in this Software without prior written authorization from The Open Group.
 #endif
 
 /* Maximum size should be initial size multiplied by a power of 2 */
-#define QUEUE_INITIAL_SIZE                 128
+#define QUEUE_INITIAL_SIZE                 256
+#define QUEUE_RESERVED_SIZE                 64
 #define QUEUE_MAXIMUM_SIZE                4096
 #define QUEUE_DROP_BACKTRACE_FREQUENCY     100
 #define QUEUE_DROP_BACKTRACE_MAX            10
@@ -205,6 +206,26 @@ mieqFini(void)
     free(miEventQueue.events);
 }
 
+/* This function will determine if the given event is allowed to used the reserved
+ * queue space.
+ */
+static Bool
+mieqReservedCandidate(InternalEvent *e) {
+    switch(e->any.type) {
+        case ET_KeyRelease:
+        case ET_ButtonRelease:
+#if XFreeXDGA
+        case ET_DGAEvent:
+#endif
+        case ET_RawKeyRelease:
+        case ET_RawButtonRelease:
+        case ET_XQuartz:
+            return TRUE;
+        default:
+            return FALSE;
+    }
+}
+
 /*
  * Must be reentrant with ProcessInputEvents.  Assumption: mieqEnqueue
  * will never be interrupted.  If this is called from both signal
@@ -220,6 +241,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     int                    isMotion = 0;
     int                    evlen;
     Time                   time;
+    size_t                 n_enqueued;
 
 #ifdef XQUARTZ
     wait_for_server_init();
@@ -228,6 +250,8 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
     verify_internal_event(e);
 
+    n_enqueued = mieqNumEnqueued(&miEventQueue);
+
     /* avoid merging events from different devices */
     if (e->any.type == ET_Motion)
         isMotion = pDev->id;
@@ -235,7 +259,8 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     if (isMotion && isMotion == miEventQueue.lastMotion &&
         oldtail != miEventQueue.head) {
         oldtail = (oldtail - 1) % miEventQueue.nevents;
-    } else if (((oldtail + 1) % miEventQueue.nevents) == miEventQueue.head) {
+    } else if ((n_enqueued + 1 == miEventQueue.nevents) ||
+               ((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) && !mieqReservedCandidate(e))) {
         /* Toss events which come in late.  Usually this means your server's
          * stuck in an infinite loop somewhere, but SIGIO is still getting
          * handled.
@@ -517,9 +542,9 @@ mieqProcessInputEvents(void)
     pthread_mutex_lock(&miEventQueueMutex);
 #endif
 
-    /* Grow our queue if we are reaching capacity: > 50% full */
+    /* Grow our queue if we are reaching capacity: < 2 * QUEUE_RESERVED_SIZE remaining */
     n_enqueued = mieqNumEnqueued(&miEventQueue);
-    if (n_enqueued >= (miEventQueue.nevents >> 1) &&
+    if (n_enqueued >= (miEventQueue.nevents - (2 * QUEUE_RESERVED_SIZE)) &&
         miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) {
         ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n", miEventQueue.nevents << 1);
         if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
commit 8251389d65fec4dcdaeebc46ba3fa28eb7a19958
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sat Oct 15 22:51:30 2011 -0700

    mieq: Provide better adaptability and diagnostics during mieq overflow
    
    This patch changes from a static length event queue (512) to one that
    starts at 128 and grows to 4096 as it overflows, logging each time it
    grows.
    
    This change also allows for multiple backtraces to be printed when the
    server is wedged rather than just one.  This increased sampling should
    help identify the true hog in cases where one backtrace might be
    insufficient.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/mieq.c b/mi/mieq.c
index b75bde9..c9a4370 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -59,7 +59,11 @@ in this Software without prior written authorization from The Open Group.
 # include <X11/extensions/dpmsconst.h>
 #endif
 
-#define QUEUE_SIZE  512
+/* Maximum size should be initial size multiplied by a power of 2 */
+#define QUEUE_INITIAL_SIZE                 128
+#define QUEUE_MAXIMUM_SIZE                4096
+#define QUEUE_DROP_BACKTRACE_FREQUENCY     100
+#define QUEUE_DROP_BACKTRACE_MAX            10
 
 #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
 #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
@@ -74,7 +78,9 @@ typedef struct _EventQueue {
     HWEventQueueType head, tail;         /* long for SetInputCheck */
     CARD32           lastEventTime;      /* to avoid time running backwards */
     int              lastMotion;         /* device ID if last event motion? */
-    EventRec         events[QUEUE_SIZE]; /* static allocation for signals */
+    EventRec         *events;            /* our queue as an array */
+    size_t           nevents;            /* the number of buckets in our queue */
+    size_t           dropped;            /* counter for number of consecutive dropped events */
     mieqHandler      handlers[128];      /* custom event handler */
 } EventQueueRec, *EventQueuePtr;
 
@@ -99,25 +105,87 @@ static inline void wait_for_server_init(void) {
 }
 #endif
 
+static size_t
+mieqNumEnqueued(EventQueuePtr eventQueue) {
+    size_t n_enqueued = 0;
+    if (eventQueue->nevents) {
+        /* % is not well-defined with negative numbers... sigh */
+        n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents;
+        if (n_enqueued >= eventQueue->nevents)
+            n_enqueued -= eventQueue->nevents;
+    }
+    return n_enqueued;
+}
+
+/* Pre-condition: Called with miEventQueueMutex held */
+static Bool
+mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) {
+    size_t i, n_enqueued, first_hunk;
+    EventRec *new_events;
+
+    if (!eventQueue) {
+        ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n");
+        return FALSE;
+    }
+
+    if (new_nevents <= eventQueue->nevents)
+        return FALSE;
+
+    new_events = calloc(new_nevents, sizeof(EventRec));
+    if (new_events == NULL) {
+        ErrorF("[mi] mieqGrowQueue memory allocation error.\n");
+        return FALSE;
+    }
+
+    n_enqueued = mieqNumEnqueued(eventQueue);
+
+    /* We block signals, so an mieqEnqueue triggered by SIGIO does not
+     * write to our queue as we are modifying it.
+     */
+    OsBlockSignals();
+
+    /* First copy the existing events */
+    first_hunk = eventQueue->nevents - eventQueue->head;
+    memcpy(new_events,
+           &eventQueue->events[eventQueue->head],
+           first_hunk * sizeof(EventRec));
+    memcpy(&new_events[first_hunk],
+           eventQueue->events,
+           eventQueue->head * sizeof(EventRec));
+
+    /* Initialize the new portion */
+    for (i = eventQueue->nevents; i < new_nevents; i++) {
+        InternalEvent* evlist = InitEventList(1);
+        if (!evlist) {
+            size_t j;
+            for (j = 0; j < i; j++)
+                FreeEventList(new_events[j].events, 1);
+            free(new_events);
+            OsReleaseSignals();
+            return FALSE;
+        }
+        new_events[i].events = evlist;
+    }
+
+    /* And update our record */
+    miEventQueue.tail = n_enqueued;
+    miEventQueue.head = 0;
+    miEventQueue.nevents = new_nevents;
+    free(miEventQueue.events);
+    miEventQueue.events = new_events;
+
+    OsReleaseSignals();
+    return TRUE;
+}
+
 Bool
 mieqInit(void)
 {
-    int i;
-
-    miEventQueue.head = miEventQueue.tail = 0;
+    memset(&miEventQueue, 0, sizeof(miEventQueue));
     miEventQueue.lastEventTime = GetTimeInMillis ();
-    miEventQueue.lastMotion = FALSE;
-    for (i = 0; i < 128; i++)
-        miEventQueue.handlers[i] = NULL;
-    for (i = 0; i < QUEUE_SIZE; i++)
-    {
-	if (miEventQueue.events[i].events == NULL) {
-	    InternalEvent* evlist = InitEventList(1);
-	    if (!evlist)
-		FatalError("Could not allocate event queue.\n");
-	    miEventQueue.events[i].events = evlist;
-	}
-    }
+
+    if(!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
+	FatalError("Could not allocate event queue.\n");
 
     SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
     return TRUE;
@@ -127,13 +195,14 @@ void
 mieqFini(void)
 {
     int i;
-    for (i = 0; i < QUEUE_SIZE; i++)
+    for (i = 0; i < miEventQueue.nevents; i++)
     {
 	if (miEventQueue.events[i].events != NULL) {
 	    FreeEventList(miEventQueue.events[i].events, 1);
 	    miEventQueue.events[i].events = NULL;
 	}
     }
+    free(miEventQueue.events);
 }
 
 /*
@@ -165,26 +234,31 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
     if (isMotion && isMotion == miEventQueue.lastMotion &&
         oldtail != miEventQueue.head) {
-        oldtail = (oldtail - 1) % QUEUE_SIZE;
-    }
-    else {
-        static int stuck = 0;
+        oldtail = (oldtail - 1) % miEventQueue.nevents;
+    } else if (((oldtail + 1) % miEventQueue.nevents) == miEventQueue.head) {
         /* Toss events which come in late.  Usually this means your server's
          * stuck in an infinite loop somewhere, but SIGIO is still getting
-         * handled. */
-        if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
-            if (!stuck) {
-                ErrorF("[mi] EQ overflowing. The server is probably stuck "
-                        "in an infinite loop.\n");
-                xorg_backtrace();
-                stuck = 1;
+         * handled.
+         */
+        miEventQueue.dropped++;
+        if (miEventQueue.dropped == 1) {
+            ErrorF("[mi] EQ overflowing.  Additional events will be discarded until existing events are processed.\n");
+            xorg_backtrace();
+            ErrorF("[mi] These backtraces from mieqEnqueue may point to a culprit higher up the stack.\n");
+            ErrorF("[mi] mieq is *NOT* the cause.  It is a victim.\n");
+        } else if (miEventQueue.dropped %  QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
+                   miEventQueue.dropped /  QUEUE_DROP_BACKTRACE_FREQUENCY <= QUEUE_DROP_BACKTRACE_MAX) {
+            ErrorF("[mi] EQ overflow continuing.  %lu events have been dropped.\n", miEventQueue.dropped);
+            if (miEventQueue.dropped /  QUEUE_DROP_BACKTRACE_FREQUENCY == QUEUE_DROP_BACKTRACE_MAX) {
+                ErrorF("[mi] No further overflow reports will be reported until the clog is cleared.\n");
             }
+            xorg_backtrace();
+        }
+
 #ifdef XQUARTZ
-            pthread_mutex_unlock(&miEventQueueMutex);
+        pthread_mutex_unlock(&miEventQueueMutex);
 #endif
-	        return;
-        }
-        stuck = 0;
+        return;
     }
 
     evlen = e->any.length;
@@ -203,7 +277,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
     miEventQueue.events[oldtail].pDev = pDev;
 
     miEventQueue.lastMotion = isMotion;
-    miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
+    miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents;
 #ifdef XQUARTZ
     pthread_mutex_unlock(&miEventQueueMutex);
 #endif
@@ -437,11 +511,28 @@ mieqProcessInputEvents(void)
     static InternalEvent event;
     DeviceIntPtr dev = NULL,
                  master = NULL;
+    size_t n_enqueued;
 
 #ifdef XQUARTZ
     pthread_mutex_lock(&miEventQueueMutex);
 #endif
-    
+
+    /* Grow our queue if we are reaching capacity: > 50% full */
+    n_enqueued = mieqNumEnqueued(&miEventQueue);
+    if (n_enqueued >= (miEventQueue.nevents >> 1) &&
+        miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) {
+        ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n", miEventQueue.nevents << 1);
+        if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
+            ErrorF("[mi] Increasing the size of EQ failed.\n");
+        }
+    }
+
+    if (miEventQueue.dropped) {
+        ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", miEventQueue.dropped);
+        ErrorF("[mi] This may be caused my a misbehaving driver monopolizing the server's resources.\n");
+        miEventQueue.dropped = 0;
+    }
+
     while (miEventQueue.head != miEventQueue.tail) {
         e = &miEventQueue.events[miEventQueue.head];
 
@@ -449,7 +540,7 @@ mieqProcessInputEvents(void)
         dev     = e->pDev;
         screen  = e->pScreen;
 
-        miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
+        miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents;
 
 #ifdef XQUARTZ
         pthread_mutex_unlock(&miEventQueueMutex);
commit 37510c50fe7a49b47a4d45296ee2f8d96ae7aba6
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 force the server to have -fno-strict-aliasing even once it
    is removed from the warning flags.
    
    See: https://bugs.freedesktop.org/show_bug.cgi?id=31238
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/configure.ac b/configure.ac
index 4bfa82c..63d59f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,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 499018548da2da2240f65dfd295d38f65212ea6a
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Wed Oct 5 15:02:52 2011 -0700

    test: Silence some debug lines from the input unit tests
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/test/input.c b/test/input.c
index 3475197..52bc2f5 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1480,8 +1480,6 @@ _test_double_fp16_values(double orig_d)
 {
     FP1616 first_fp16, final_fp16;
     double final_d;
-    char first_fp16_s[64];
-    char final_fp16_s[64];
 
     if (orig_d > 0x7FFF) {
         printf("Test out of range\n");
@@ -1492,10 +1490,15 @@ _test_double_fp16_values(double orig_d)
     final_d = fp1616_to_double(first_fp16);
     final_fp16 = double_to_fp1616(final_d);
 
-    snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff);
-    snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff);
-
-    printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s);
+    /* {
+     *    char first_fp16_s[64];
+     *    char final_fp16_s[64];
+     *    snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff);
+     *    snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff);
+     *
+     *    printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s);
+     * }
+     */
 
     /* since we lose precision, we only do rough range testing */
     assert(final_d > orig_d - 0.1);
commit ff61592441916b83aeb778c74352bb5b26247f84
Merge: af3f64f 525d417
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Oct 19 19:14:32 2011 -0700

    Merge remote-tracking branch 'aplattner/for-master'

commit af3f64fb77c13180e513ee99d1fd9a1b624fd8ea
Merge: 15bbdc1 df0dd36
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Oct 19 17:33:07 2011 -0700

    Merge remote-tracking branch 'hramrach/pull'

commit 15bbdc103b34b6b374815698946e6c409421a644
Merge: a5266dc 323869f
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Oct 19 17:26:50 2011 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit a5266dcb3a60587e1877f90c18552baf60b597a0
Author: Ville Syrjala <syrjala at sci.fi>
Date:   Sun Oct 9 01:11:04 2011 +0300

    composite: Update borderClip in compAllocPixmap()
    
    Previously the parent constrained borderClip was copied over
    when compRedirectWindow() is called. That is insufficient eg. in
    case the window was already redirected, but not yet realized. So
    copy the borderClip over in compAllocPixmap() instead.
    
    Example:
    Window 1 is below an automatically redirect window 2. Window 2 is
    unmapped and moved outside the extents of window 1. Window 2 is
    then mapped again, and MarkOverlappedWindows() uses the up to
    date borderSize of window 2 to mark windows, which leaves
    window 1 unmarked. Then exposures are calculated using the stale
    borderClip of window 2, which causes the window below window 2,
    to be exposed through an apparent hole in window 1.
    
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=22566
    
    Signed-off-by: Ville Syrjala <syrjala at sci.fi>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/composite/compalloc.c b/composite/compalloc.c
index f00bf4e..9857a92 100644
--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -196,11 +196,7 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
 
 	anyMarked = compMarkWindows (pWin, &pLayerWin);
 
-	/* Make sure our borderClip is correct for ValidateTree */
 	RegionNull(&cw->borderClip);
-	RegionCopy(&cw->borderClip, &pWin->borderClip);
-	cw->borderClipX = pWin->drawable.x;
-	cw->borderClipY = pWin->drawable.y;
 	cw->update = CompositeRedirectAutomatic;
 	cw->clients = 0;
 	cw->oldx = COMP_ORIGIN_INVALID;
@@ -658,6 +654,13 @@ compAllocPixmap (WindowPtr pWin)
 	DamageRegister (&pWin->drawable, cw->damage);
 	cw->damageRegistered = TRUE;
     }
+
+    /* Make sure our borderClip is up to date */
+    RegionUninit(&cw->borderClip);
+    RegionCopy(&cw->borderClip, &pWin->borderClip);
+    cw->borderClipX = pWin->drawable.x;
+    cw->borderClipY = pWin->drawable.y;
+
     return TRUE;
 }
 
commit e4787ec20b1b9d30fe00f17b60eb0898190bf77d
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Mon Oct 17 15:08:14 2011 -0400

    XWinrc.man: fix warning: tab character in unquoted macro argument #35054
    
    Spaces or tabs do not affect the text output layout.
    
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xwin/man/XWinrc.man b/hw/xwin/man/XWinrc.man
index e4c454f..71d8dad 100644
--- a/hw/xwin/man/XWinrc.man
+++ b/hw/xwin/man/XWinrc.man
@@ -88,15 +88,15 @@ this may be useful if you want no dialogs.
 This instruction defines a menu and asigns a \fIMenu_Name\fP to it.
 \fIMenu_Item_Line\fP are lines  of any of the following types:
 .TP 8
-.B \t SEPARATOR
+.B SEPARATOR
 .TP 8
-.B  \t \fIItem_Label\fP  EXEC \fICommand\fP
+.B \fIItem_Label\fP  EXEC \fICommand\fP
 .TP 8
-.B \t \fIItem_Label\fP  MENU \fIpreviously-defined-menu-name\fP
+.B \fIItem_Label\fP  MENU \fIpreviously-defined-menu-name\fP
 .TP 8
-.B \t \fIItem_Label\fP  ALWAYSONTOP
+.B \fIItem_Label\fP  ALWAYSONTOP
 .TP 8
-.B \t \fIItem_Label\fP  RELOAD
+.B \fIItem_Label\fP  RELOAD
 .br
 The \fIItem_Label\fP is the string that is written in the menu item.
 .br
commit 321873f8045139edd47b526a765f8b1c66f53cd4
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Mon Oct 17 15:08:13 2011 -0400

    xorg.conf.man: fix 382: warning: missing `)' (got `R') #35054
    
    http://www.gnu.org/software/groff/manual/html_node/Man-usage.html
    
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index 7f98851..996798f 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -379,7 +379,9 @@ is a number used to order the fontfile FPEs. Examples:
 .I misc:unscaled:pri=10 \-> /usr/share/X11/fonts/misc
 .fi
 .PP
-.RE .RE .RE
+.RE
+.RE
+.RE
 .PP
 .RS 7
 Font server identifiers:
commit 3e145d3d67b472cb5d74cb8078b614160c4722b7
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Thu Oct 13 12:01:10 2011 -0700

    crtc: match full preferred modes if possible when choosing an initial config
    
    It's fairly common to have multiple, identical monitors plugged in.  In
    that case, it's preferable to run the monitor's preferred mode on each
    output, rather than just matching the width & height and end up with
    different timings or refresh rates.
    
    Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index cbe0b5c..384d8b4 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -2060,13 +2060,28 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
 		if (o == p)
 		    continue;
 
-		for (mode = output->probed_modes; mode; mode = mode->next) {
-		    Rotation r = output->initial_rotation;
-		    if (xf86ModeWidth(mode, r) == pref_width &&
-			    xf86ModeHeight(mode, r) == pref_height) {
+		/*
+		 * First see if the preferred mode matches on the next
+		 * output as well.  This catches the common case of identical
+		 * monitors and makes sure they all have the same timings
+		 * and refresh.  If that fails, we fall back to trying to
+		 * match just width & height.
+		 */
+		mode = xf86OutputHasPreferredMode(output, pref_width,
+						  pref_height);
+		if (mode && xf86ModesEqual(mode, preferred[p])) {
 			preferred[o] = mode;
 			match = TRUE;
-		    }
+		} else {
+			for (mode = output->probed_modes; mode;
+			     mode = mode->next) {
+				Rotation r = output->initial_rotation;
+				if (xf86ModeWidth(mode, r) == pref_width &&
+				    xf86ModeHeight(mode, r) == pref_height) {
+					preferred[o] = mode;
+					match = TRUE;
+				}
+			}
 		}
 
 		all_match &= match;
commit 525d4172b246e13b8122e059e3b22866e00561d9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 4 09:34:08 2011 -0700

    render: export TriStrip and TriFan to the drivers
    
    Rather than perform an intermediate copy and expand the strip and the
    fan into a triangle list (thereby tripling the number of edges that the
    driver needs to process), allow the backend to hook directly into the
    appropriate Composite function.
    
    In order to extend the PictureScreen, without needlessly bumping the
    ABI, we move the existing copy implementations to mipict.c and assign
    those by default. To notify the ddx that the new entry points are
    available, we introduce PICTURE_SCREEN_VERSION.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/render/mipict.c b/render/mipict.c
index 9a44c27..0b86bee 100644
--- a/render/mipict.c
+++ b/render/mipict.c
@@ -569,6 +569,64 @@ miRenderPixelToColor (PictFormatPtr format,
     }
 }
 
+void
+miTriStrip (CARD8	    op,
+	    PicturePtr	    pSrc,
+	    PicturePtr	    pDst,
+	    PictFormatPtr  maskFormat,
+	    INT16	    xSrc,
+	    INT16	    ySrc,
+	    int		    npoints,
+	    xPointFixed    *points)
+{
+    xTriangle           *tris, *tri;
+    int                 ntri;
+
+    ntri = npoints - 2;
+    tris = malloc(ntri * sizeof (xTriangle));
+    if (!tris)
+        return;
+
+    for (tri = tris; npoints >= 3; npoints--, points++, tri++)
+    {
+        tri->p1 = points[0];
+        tri->p2 = points[1];
+        tri->p3 = points[2];
+    }
+    CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
+    free(tris);
+}
+
+void
+miTriFan (CARD8		op,
+	  PicturePtr	pSrc,
+	  PicturePtr	pDst,
+	  PictFormatPtr	maskFormat,
+	  INT16		xSrc,
+	  INT16		ySrc,
+	  int		npoints,
+	  xPointFixed	*points)
+{
+    xTriangle		*tris, *tri;
+    xPointFixed		*first;
+    int			ntri;
+
+    ntri = npoints - 2;
+    tris = malloc(ntri * sizeof (xTriangle));
+    if (!tris)
+	return;
+
+    first = points++;
+    for (tri = tris; npoints >= 3; npoints--, points++, tri++)
+    {
+	tri->p1 = *first;
+	tri->p2 = points[0];
+	tri->p3 = points[1];
+    }
+    CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
+    free(tris);
+}
+
 Bool
 miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
 {
@@ -602,5 +660,8 @@ miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     ps->AddTraps	= 0;			/* requires DDX support */
     ps->AddTriangles	= 0;			/* requires DDX support */
 
+    ps->TriStrip	= miTriStrip; /* converts call to CompositeTriangles */
+    ps->TriFan		= miTriFan;
+
     return TRUE;
 }
diff --git a/render/mipict.h b/render/mipict.h
index f6d9dee..4399a6f 100644
--- a/render/mipict.h
+++ b/render/mipict.h
@@ -140,6 +140,26 @@ miCompositeRects (CARD8		op,
 		  xRectangle    *rects);
 
 extern _X_EXPORT void
+miTriStrip (CARD8	    op,
+	    PicturePtr	    pSrc,
+	    PicturePtr	    pDst,
+	    PictFormatPtr  maskFormat,
+	    INT16	    xSrc,
+	    INT16	    ySrc,
+	    int		    npoints,
+	    xPointFixed    *points);
+
+extern _X_EXPORT void
+miTriFan (CARD8		op,
+	  PicturePtr	pSrc,
+	  PicturePtr	pDst,
+	  PictFormatPtr	maskFormat,
+	  INT16		xSrc,
+	  INT16		ySrc,
+	  int		npoints,
+	  xPointFixed	*points);
+
+extern _X_EXPORT void
 miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box);
 
 extern _X_EXPORT void
diff --git a/render/picture.c b/render/picture.c
index 5640c4d..f134596 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -1715,23 +1715,14 @@ CompositeTriStrip (CARD8	    op,
 		   int		    npoints,
 		   xPointFixed	    *points)
 {
-    xTriangle           *tris, *tri;
-    int                 ntri;
-    
+    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
     if (npoints < 3)
         return;
-    ntri = npoints - 2;
-    tris = malloc(ntri * sizeof (xTriangle));
-    if (!tris)
-        return;
-    for (tri = tris; npoints >= 3; npoints--, points++, tri++)
-    {
-        tri->p1 = points[0];
-        tri->p2 = points[1];
-        tri->p3 = points[2];
-    }
-    CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
-    free(tris);
+
+    ValidatePicture (pSrc);
+    ValidatePicture (pDst);
+    (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
 }
 
 void
@@ -1744,25 +1735,14 @@ CompositeTriFan (CARD8		op,
 		 int		npoints,
 		 xPointFixed	*points)
 {
-    xTriangle		*tris, *tri;
-    xPointFixed		*first;
-    int			ntri;
-    
+    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
     if (npoints < 3)
 	return;
-    ntri = npoints - 2;
-    tris = malloc(ntri * sizeof (xTriangle));
-    if (!tris)
-	return;
-    first = points++;
-    for (tri = tris; npoints >= 3; npoints--, points++, tri++)
-    {
-	tri->p1 = *first;
-	tri->p2 = points[0];
-	tri->p3 = points[1];
-    }
-    CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
-    free(tris);
+
+    ValidatePicture (pSrc);
+    ValidatePicture (pDst);
+    (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
 }
 
 void
diff --git a/render/picturestr.h b/render/picturestr.h
index 7b7f911..1f3f5a4 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -260,6 +260,24 @@ typedef void	(*TrianglesProcPtr)	    (CARD8	    op,
 					     int	    ntri,
 					     xTriangle	    *tris);
 
+typedef void	(*TriStripProcPtr)	    (CARD8	    op,
+					     PicturePtr	    pSrc,
+					     PicturePtr	    pDst,
+					     PictFormatPtr  maskFormat,
+					     INT16	    xSrc,
+					     INT16	    ySrc,
+					     int	    npoint,
+					     xPointFixed    *points);
+
+typedef void	(*TriFanProcPtr)	    (CARD8	    op,
+					     PicturePtr	    pSrc,
+					     PicturePtr	    pDst,
+					     PictFormatPtr  maskFormat,
+					     INT16	    xSrc,
+					     INT16	    ySrc,
+					     int	    npoint,
+					     xPointFixed    *points);
+
 typedef Bool	(*InitIndexedProcPtr)	    (ScreenPtr	    pScreen,
 					     PictFormatPtr  pFormat);
 
@@ -348,6 +366,9 @@ typedef struct _PictureScreen {
     RealizeGlyphProcPtr   	RealizeGlyph;
     UnrealizeGlyphProcPtr 	UnrealizeGlyph;
 
+#define PICTURE_SCREEN_VERSION 2
+    TriStripProcPtr		TriStrip;
+    TriFanProcPtr		TriFan;
 } PictureScreenRec, *PictureScreenPtr;
 
 extern _X_EXPORT DevPrivateKeyRec PictureScreenPrivateKeyRec;
commit 9b26e6bc8d2cdf5bac3025796855ccf05972358f
Author: Luc Verhaegen <libv at skynet.be>
Date:   Tue Aug 23 15:19:59 2011 -0700

    randr: stop clients from deleting immutable output properties
    
    Immutable in randr means that clients are not able to alter the
    property itself, they are only allowed to alter the property value.
    This logically means that the property then should not be deleted
    by the client either.
    
    Signed-off-by: Luc Verhaegen <libv at skynet.be>
    Reviewed-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 6ed24d3..d0a9020 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -549,18 +549,31 @@ int
 ProcRRDeleteOutputProperty (ClientPtr client)
 {
     REQUEST(xRRDeleteOutputPropertyReq);
-    RROutputPtr	output;
-              
+    RROutputPtr		output;
+    RRPropertyPtr	prop;
+
     REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
     UpdateCurrentTime();
     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
-    
+
     if (!ValidAtom(stuff->property))
     {
 	client->errorValue = stuff->property;
 	return BadAtom;
     }
 
+    prop = RRQueryOutputProperty(output, stuff->property);
+    if (!prop)
+    {
+	client->errorValue = stuff->property;
+	return BadName;
+    }
+
+    if (prop->immutable)
+    {
+	client->errorValue = stuff->property;
+	return BadAccess;
+    }
 
     RRDeleteOutputProperty(output, stuff->property);
     return Success;
commit df0dd36deea0c756819825113e825059ddd19243
Author: Michal Suchanek <hramrach at centrum.cz>
Date:   Sat Oct 8 14:26:24 2011 +0200

    Do not uselessly reload modules in DuplicateModule
    
    The function does not initialize the module so it has no business
    loading it. If some user of DuplicateModule expects a module actually
    loaded they should use LoadModule.
    
    Signed-off-by: Michal Suchanek <hramrach at centrum.cz>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index 2e6c667..a21f43d6 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -94,6 +94,8 @@ const ModuleVersions LoaderVersionInfo = {
     ABI_FONT_VERSION
 };
 
+static int ModuleDuplicated[] = {};
+
 static void
 FreeStringList(char **paths)
 {
@@ -785,7 +787,6 @@ ModuleDescPtr
 DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
 {
     ModuleDescPtr ret;
-    int errmaj, errmin;
 
     if (!mod)
 	return NULL;
@@ -794,14 +795,11 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
     if (ret == NULL)
 	return NULL;
 
-    if (!(ret->handle = LoaderOpen(mod->path, &errmaj, &errmin))) {
-        free(ret);
-        return NULL;
-    }
+    ret->handle = mod->handle;
 
     ret->SetupProc = mod->SetupProc;
     ret->TearDownProc = mod->TearDownProc;
-    ret->TearDownData = NULL;
+    ret->TearDownData = ModuleDuplicated;
     ret->child = DuplicateModule(mod->child, ret);
     ret->sib = DuplicateModule(mod->sib, parent);
     ret->parent = parent;
@@ -1077,9 +1075,11 @@ UnloadModuleOrDriver(ModuleDescPtr mod)
     else
 	xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
 
-    if ((mod->TearDownProc) && (mod->TearDownData))
-	mod->TearDownProc(mod->TearDownData);
-    LoaderUnload(mod->name, mod->handle);
+    if (mod->TearDownData != ModuleDuplicated) {
+	if ((mod->TearDownProc) && (mod->TearDownData))
+	    mod->TearDownProc(mod->TearDownData);
+	LoaderUnload(mod->name, mod->handle);
+    }
 
     if (mod->child)
 	UnloadModuleOrDriver(mod->child);
commit 24d435163eb5fbd9b73cd8ba13a9b3cdbbe8a1df
Author: Michal Suchanek <hramrach at centrum.cz>
Date:   Sat Oct 8 14:19:34 2011 +0200

    Use UnloadModuleOrDriver for UnloadSubModule.
    
    Signed-off-by: Michal Suchanek <hramrach at centrum.cz>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index 9f82099..2e6c667 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -1072,7 +1072,10 @@ UnloadModuleOrDriver(ModuleDescPtr mod)
     if (mod == NULL || mod->name == NULL)
 	return;
 
-    xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
+    if (mod->parent)
+	xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name);
+    else
+	xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
 
     if ((mod->TearDownProc) && (mod->TearDownData))
 	mod->TearDownProc(mod->TearDownData);
@@ -1092,23 +1095,8 @@ UnloadSubModule(pointer _mod)
 {
     ModuleDescPtr mod = (ModuleDescPtr)_mod;
 
-    if (mod == NULL || mod->name == NULL)
-	return;
-
-    xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name);
-
-    if ((mod->TearDownProc) && (mod->TearDownData))
-	mod->TearDownProc(mod->TearDownData);
-    LoaderUnload(mod->name, mod->handle);
-
     RemoveChild(mod);
-
-    if (mod->child)
-	UnloadModuleOrDriver(mod->child);
-
-    free(mod->path);
-    free(mod->name);
-    free(mod);
+    UnloadModuleOrDriver(mod);
 }
 
 static void
@@ -1135,6 +1123,7 @@ RemoveChild(ModuleDescPtr child)
     }
     if (mdp == child)
 	prevsib->sib = child->sib;
+    child->sib = NULL;
     return;
 }
 
commit 0d4bb5442ceb8e8e4a8de6cfc4203cae469eee72
Author: Michal Suchanek <hramrach at centrum.cz>
Date:   Sat Oct 8 14:13:33 2011 +0200

    Unload submodules.
    
    Signed-off-by: Michal Suchanek <hramrach at centrum.cz>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index a8aa316..4e9bcad 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1643,13 +1643,7 @@ xf86LoadOneModule(char *name, pointer opt)
 void
 xf86UnloadSubModule(pointer mod)
 {
-    /*
-     * This is disabled for now.  The loader isn't smart enough yet to undo
-     * relocations.
-     */
-#if 0
     UnloadSubModule(mod);
-#endif
 }
 
 Bool
commit b04aff76ac2eb461c71b85525a00e25efb8bf267
Author: Michal Suchanek <hramrach at centrum.cz>
Date:   Thu Oct 13 17:14:53 2011 +0200

    Document -background none option
    
    Document option introduced in commit 8976e97.
    
    Signed-off-by: Michal Suchanek <hramrach at centrum.cz>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/man/Xserver.man b/man/Xserver.man
index 1a36b09..fe24337 100644
--- a/man/Xserver.man
+++ b/man/Xserver.man
@@ -100,6 +100,12 @@ specifies a file which contains a collection of authorization records used
 to authenticate access.  See also the \fIxdm\fP(1) and
 \fIXsecurity\fP(__miscmansuffix__) manual pages.
 .TP 8
+.BI \-background\ none
+Asks the driver not to clear the background on startup, if the driver supports that.
+May be useful for smooth transition with eg. fbdev driver.
+For security reasons this is not the default as the screen contents might
+show a previous user session.
+.TP 8
 .B \-br
 sets the default root window to solid black instead of the standard root weave
 pattern.   This is the default unless -retro or -wr is specified.
commit 323869f3298cbbfe864af9404a8aed1bf7995d79
Author: Tomáš Trnka <tomastrnka at gmx.com>
Date:   Tue Oct 11 09:11:18 2011 +0200

    Fix drain_console unregistration
    
    Bug introduced by 9dca441670d261a9a9fb6108960ed48f3d58fb7f
    xfree86: add a hook to replace the new console handler.
    
    console_handler was not being set, making the server eat up CPU spinning
    in WaitForSomething selecting consoleFd over and over again, every time
    trying to unregister drain_console without success due to
    console_handler being NULL.
    
    Let's just fix the unregistration in xf86SetConsoleHandler() and use that.
    
    But wait, there could be a catch: If some driver replaced the handler using
    xf86SetConsoleHandler(), the unregistration in xf86CloseConsole will unregister
    that one. I don't understand Xorg well enough to know whether this poses a
    problem (could mess up driver deinit somehow or something like that). As it is,
    xf86SetConsoleHandler() doesn't offer any way to prevent this (i.e. check which
    handler is currently registered).
    
    I had been using it for two days on my machine that previously hit 100% CPU
    several times a day. That has now gone away without any new problems appearing.
    
    Signed-off-by: Tomas Trnka <tomastrnka at gmx.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/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index c4a4db9..41ffabd 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -601,16 +601,15 @@ xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
 InputHandlerProc
 xf86SetConsoleHandler(InputHandlerProc proc, pointer data)
 {
-    static InputHandlerProc handler = NULL;
-    InputHandlerProc old_handler = handler;
+    static IHPtr handler = NULL;
+    IHPtr old_handler = handler;
 
     if (old_handler)
         xf86RemoveGeneralHandler(old_handler);
 
-    xf86AddGeneralHandler(xf86Info.consoleFd, proc, data);
-    handler = proc;
+    handler = xf86AddGeneralHandler(xf86Info.consoleFd, proc, data);
 
-    return old_handler;
+    return (old_handler) ? old_handler->ihproc : NULL;
 }
 
 static void
diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 9c91740..f18271f 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -45,15 +45,12 @@ static char vtname[11];
 static struct termios tty_attr; /* tty state to restore */
 static int tty_mode; /* kbd mode to restore */
 
-static void *console_handler;
-
 static void
 drain_console(int fd, void *closure)
 {
     errno = 0;
     if (tcflush(fd, TCIOFLUSH) == -1 && errno == EIO) {
-	xf86RemoveGeneralHandler(console_handler);
-	console_handler = NULL;
+        xf86SetConsoleHandler(NULL, NULL);
     }
 }
 
@@ -257,10 +254,11 @@ xf86CloseConsole(void)
         return;
     }
 
-    if (console_handler) {
-	xf86RemoveGeneralHandler(console_handler);
-	console_handler = NULL;
-    };
+    /*
+     * unregister the drain_console handler
+     * - what to do if someone else changed it in the meantime?
+     */
+    xf86SetConsoleHandler(NULL, NULL);
 
     /* Back to text mode ... */
     SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
commit 2cb63180fa9b54f763e7e92e433943e3e73741f3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Oct 5 12:08:31 2011 +1000

    dix: mark motion events as emulated if we're scrolling from button press
    
    The protocol requires that the emulated event is marked as such. So if a
    driver with smooth scrolling axis sends legacy button events, the motion
    event must be marked as emulated.
    
    Pass the real type to emulate_scroll_button_events and create the events
    accordingly. For real button press or relase events, only that event must be
    generated since a release event will follow or a press event has already
    occured, respectively. (This fixes a bug where we'd get two release events
    for each legacy button event)
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/getevents.c b/dix/getevents.c
index 874189f..7be39dc 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1228,6 +1228,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
  *
  * @param events The pointer to the event list to fill the events
  * @param dev The device to generate the events for
+ * @param type The real type of the event
  * @param axis The axis number to generate events for
  * @param mask State before this event in absolute coords
  * @param[in,out] last Last scroll state posted in absolute coords (modified
@@ -1239,6 +1240,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
 static int
 emulate_scroll_button_events(InternalEvent *events,
                              DeviceIntPtr dev,
+                             int type,
                              int axis,
                              const ValuatorMask *mask,
                              ValuatorMask *last,
@@ -1251,6 +1253,7 @@ emulate_scroll_button_events(InternalEvent *events,
     int num_events = 0;
     double total;
     int b;
+    int flags = 0;
 
     if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
         return 0;
@@ -1261,6 +1264,9 @@ emulate_scroll_button_events(InternalEvent *events,
     ax = &dev->valuator->axes[axis];
     incr = ax->scroll.increment;
 
+    if (type != ButtonPress && type != ButtonRelease)
+        flags |= POINTER_EMULATED;
+
     if (!valuator_mask_isset(last, axis))
         valuator_mask_set_double(last, axis, 0);
 
@@ -1288,14 +1294,20 @@ emulate_scroll_button_events(InternalEvent *events,
          */
         if (num_events + 4 < max_events)
         {
-            nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
-                                          POINTER_EMULATED, NULL);
-            events += nev_tmp;
-            num_events += nev_tmp;
-            nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
-                                          POINTER_EMULATED, NULL);
-            events += nev_tmp;
-            num_events += nev_tmp;
+            if (type != ButtonRelease)
+            {
+                nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
+                                              flags, NULL);
+                events += nev_tmp;
+                num_events += nev_tmp;
+            }
+            if (type != ButtonPress)
+            {
+                nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
+                                              flags, NULL);
+                events += nev_tmp;
+                num_events += nev_tmp;
+            }
         }
     }
 
@@ -1340,6 +1352,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     ValuatorMask mask;
     ValuatorMask scroll;
     int i;
+    int realtype = type;
 
     /* refuse events from disabled devices */
     if (!pDev->enabled)
@@ -1392,6 +1405,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
             valuator_mask_set_double(&mask, axis, val);
             type = MotionNotify;
             buttons = 0;
+            flags |= POINTER_EMULATED;
         }
     }
 
@@ -1411,7 +1425,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
 
         valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]);
 
-        nev_tmp = emulate_scroll_button_events(events, pDev, i, &scroll,
+        nev_tmp = emulate_scroll_button_events(events, pDev, realtype, i, &scroll,
                                                pDev->last.scroll, ms,
                                                GetMaximumEventsNum() - num_events);
         events += nev_tmp;
commit 82c60232c07f50774ccc0198950f64c9338057a5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Sep 30 10:59:47 2011 +1000

    dix: add valuator_mask_fetch_double()
    
    Using this call simplifies callers that don't know if the mask bit is set.
    
    Before:
      if (valuator_mask_isset(mask, valnum))
        value = valuator_mask_get_double(mask, valnum));
      else
        value = someothervalue;
    
    Now:
     if (!valuator_mask_fetch_double(mask, valnum, &value))
        value = someothervalue;
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/inpututils.c b/dix/inpututils.c
index eeae2a7..c27894b 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -539,6 +539,42 @@ valuator_mask_get(const ValuatorMask *mask, int valuator)
 }
 
 /**
+ * Set value to the requested valuator. If the mask bit is set for this
+ * valuator, value contains the requested valuator value and TRUE is
+ * returned.
+ * If the mask bit is not set for this valuator, value is unchanged and
+ * FALSE is returned.
+ */
+Bool
+valuator_mask_fetch_double(const ValuatorMask *mask, int valuator, double *value)
+{
+    if (valuator_mask_isset(mask, valuator))
+    {
+        *value = valuator_mask_get_double(mask, valuator);
+        return TRUE;
+    } else
+        return FALSE;
+}
+
+/**
+ * Set value to the requested valuator. If the mask bit is set for this
+ * valuator, value contains the requested valuator value and TRUE is
+ * returned.
+ * If the mask bit is not set for this valuator, value is unchanged and
+ * FALSE is returned.
+ */
+Bool
+valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value)
+{
+    if (valuator_mask_isset(mask, valuator))
+    {
+        *value = valuator_mask_get(mask, valuator);
+        return TRUE;
+    } else
+        return FALSE;
+}
+
+/**
  * Remove the valuator from the mask.
  */
 void
diff --git a/include/input.h b/include/input.h
index b7de5ca..a1930bb 100644
--- a/include/input.h
+++ b/include/input.h
@@ -597,6 +597,10 @@ extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest,
 extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum);
 extern _X_EXPORT double valuator_mask_get_double(const ValuatorMask *mask,
                                                  int valnum);
+extern _X_EXPORT Bool valuator_mask_fetch(const ValuatorMask *mask,
+                                          int valnum, int *val);
+extern _X_EXPORT Bool valuator_mask_fetch_double(const ValuatorMask *mask,
+                                                 int valnum, double *val);
 
 /* InputOption handling interface */
 extern _X_EXPORT InputOption* input_option_new(InputOption *list, const char *key, const char *value);
diff --git a/test/input.c b/test/input.c
index afc4d4d..5fb9a90 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1199,14 +1199,19 @@ static void dix_input_valuator_masks(void)
     assert(valuator_mask_num_valuators(mask) == num_vals);
     for (i = 0; i < nvaluators; i++)
     {
+        double val;
         if (i < first_val || i >= first_val + num_vals)
+        {
             assert(!valuator_mask_isset(mask, i));
-        else
+            assert(!valuator_mask_fetch_double(mask, i, &val));
+        } else
         {
             assert(valuator_mask_isset(mask, i));
             assert(valuator_mask_get(mask, i) == val_ranged[i - first_val]);
             assert(valuator_mask_get_double(mask, i) ==
                     val_ranged[i - first_val]);
+            assert(valuator_mask_fetch_double(mask, i, &val));
+            assert(val_ranged[i - first_val] == val);
         }
     }
 
@@ -1218,10 +1223,18 @@ static void dix_input_valuator_masks(void)
 
     for (i = 0; i < nvaluators; i++)
     {
+        double a, b;
         assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i));
+
+        if (!valuator_mask_isset(mask, i))
+            continue;
+
         assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i));
         assert(valuator_mask_get_double(mask, i) ==
                 valuator_mask_get_double(copy, i));
+        assert(valuator_mask_fetch_double(mask, i, &a));
+        assert(valuator_mask_fetch_double(copy, i, &b));
+        assert(a == b);
     }
 
     valuator_mask_free(&mask);


More information about the Xquartz-changes mailing list