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

Jeremy Huddleston jeremyhu at freedesktop.org
Thu Apr 26 21:07:21 PDT 2012


Rebased ref, commits from common ancestor:
commit f5334956856b92180d805c4041b8daee5fd26dcd
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>
    (cherry picked from commit e6fa592a74104aa9d0081387823314833526f306)

diff --git a/fb/fb.h b/fb/fb.h
index b327ce6..53a6c1a 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -1683,8 +1683,7 @@ fbFillRegionSolid(DrawablePtr pDrawable,
                   RegionPtr pRegion, FbBits and, FbBits xor);
 
 extern _X_EXPORT pixman_image_t *image_from_pict(PicturePtr pict,
-                                                 Bool has_clip,
-                                                 int *xoff, int *yoff);
+                                                 Bool has_clip);
 
 extern _X_EXPORT void free_pixman_pict(PicturePtr, pixman_image_t *);
 
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 097a1a6..dc0ca3c 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -46,23 +46,18 @@ fbComposite(CARD8 op,
             INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, 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, width, height);
+                               xSrc, ySrc, xMask, yMask, xDst, yDst,
+                               width, height);
     }
 
     free_pixman_pict(pSrc, src);
@@ -143,20 +138,22 @@ create_conical_gradient_image(PictGradient * gradient)
 }
 
 static pixman_image_t *
-create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+create_bits_picture(PicturePtr pict, 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, (uint32_t *) bits,
+                                     pict->pDrawable->width,
+                                     pict->pDrawable->height, (uint32_t *) bits,
                                      stride * sizeof(FbStride));
 
     if (!image)
@@ -183,57 +180,31 @@ create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
         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);
 
 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, pict->transform);
     }
 
     switch (pict->repeatType) {
@@ -261,10 +232,8 @@ set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
      * as the alpha map for this operation
      */
     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);
+            image_from_pict_internal(pict->alphaMap, TRUE, TRUE);
 
         pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
                                    pict->alphaOrigin.y);
@@ -298,8 +267,7 @@ set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
 }
 
 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;
 
@@ -307,7 +275,7 @@ image_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
         return NULL;
 
     if (pict->pDrawable) {
-        image = create_bits_picture(pict, has_clip, xoff, yoff);
+        image = create_bits_picture(pict, has_clip);
     }
     else if (pict->pSourcePict) {
         SourcePict *sp = pict->pSourcePict;
@@ -325,19 +293,17 @@ 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 bf82f8f..0145ce9 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -36,13 +36,12 @@ fbAddTraps(PicturePtr pPicture,
            INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
 {
     pixman_image_t *image;
-    int dst_xoff, dst_yoff;
 
-    if (!(image = image_from_pict(pPicture, FALSE, &dst_xoff, &dst_yoff)))
-        return;
-
-    pixman_add_traps(image, x_off + dst_xoff, y_off + dst_yoff,
-                     ntrap, (pixman_trap_t *) traps);
+    if (!(image = image_from_pict (pPicture, FALSE)))
+	return;
+    
+    pixman_add_traps(image, x_off, y_off,
+                     ntrap, (pixman_trap_t *)traps);
 
     free_pixman_pict(pPicture, image);
 }
@@ -52,13 +51,12 @@ fbRasterizeTrapezoid(PicturePtr pPicture,
                      xTrapezoid * trap, int x_off, 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);
+    pixman_rasterize_trapezoid(image, (pixman_trapezoid_t *)trap,
+                               x_off, y_off);
 
     free_pixman_pict(pPicture, image);
 }
@@ -68,14 +66,12 @@ fbAddTriangles(PicturePtr pPicture,
                INT16 x_off, INT16 y_off, int ntri, 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,
-                         ntri, (pixman_triangle_t *) tris);
+    
+    pixman_add_triangles(image, x_off, y_off, ntri,
+                         (pixman_triangle_t *)tris);
 
     free_pixman_pict(pPicture, image);
 }
@@ -98,13 +94,11 @@ fbShapes(CompositeShapesFunc composite,
          int16_t ySrc, int nshapes, int shape_size, 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) {
         pixman_format_code_t format;
@@ -121,9 +115,8 @@ fbShapes(CompositeShapesFunc composite,
 
             for (i = 0; i < nshapes; ++i) {
                 composite(op, src, dst, format,
-                          xSrc + src_xoff,
-                          ySrc + src_yoff,
-                          dst_xoff, dst_yoff, 1, shapes + i * shape_size);
+                          xSrc, ySrc, 0, 0, 
+                          1, shapes + i * shape_size);
             }
         }
         else {
@@ -143,8 +136,8 @@ fbShapes(CompositeShapesFunc composite,
             }
 
             composite(op, src, dst, format,
-                      xSrc + src_xoff,
-                      ySrc + src_yoff, dst_xoff, dst_yoff, nshapes, shapes);
+                      xSrc, ySrc, 0, 0,
+                      nshapes, shapes);
         }
 
         DamageRegionProcessPending(pDst->pDrawable);
commit e0901a8c1f1975bab1712579d02d3e5c4f063521
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>
    (cherry picked from commit d7e56959401ce32120af67b01632442c52f2cf85)

diff --git a/mi/miexpose.c b/mi/miexpose.c
index dbb29ca..93fd8a1 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -490,7 +490,8 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
-#endif
+#include "../fb/fb.h"
+#endif 
 
 void
 miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
@@ -519,23 +520,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;
+#endif
+    
+    if (what == PW_BACKGROUND)
+    {
+#ifdef ROOTLESS
+        if(IsFramedWindow(pWin)) {
+            RootlessStartDrawing(pWin);
+            RootlessDamageRegion(pWin, prgn);
 
-    if (IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-
-        if (pWin->backgroundState == ParentRelative) {
-            if ((what == PW_BACKGROUND) ||
-                (what == PW_BORDER && !pWin->borderIsPixel))
+            if(pWin->backgroundState == ParentRelative) {
                 RootlessSetPixmapOfAncestors(pWin);
+            }
         }
-    }
 #endif
 
-    if (what == PW_BACKGROUND) {
         while (pWin->backgroundState == ParentRelative)
             pWin = pWin->parent;
 
@@ -560,6 +575,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     else {
         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;
 
@@ -568,6 +595,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;
@@ -630,6 +663,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 2d71618f171c816cccddeb1a5c6736e3d60a5b5f
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Jan 13 12:00:57 2012 -0800

    sdksyms.sh: Use CPPFLAGS, not CFLAGS
    
    CFLAGS can include flags which are not useful to the preprocessor
    or can even cause it to fail.  This fixes a build issue on darwin
    when building for more than one architecture.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    (cherry picked from commit 290d366d4c6b6e051f0e337a1a6ee76f42d28003)

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 72be889..c0b81c3 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -38,7 +38,7 @@ DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
 bin_PROGRAMS = Xorg
 nodist_Xorg_SOURCES = sdksyms.c
 
-AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
+AM_CPPFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
 INCLUDES = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \
 	-I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac
 
@@ -109,7 +109,7 @@ CLEANFILES = sdksyms.c sdksyms.dep
 EXTRA_DIST += sdksyms.sh
 
 sdksyms.dep sdksyms.c: sdksyms.sh
-	CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $(srcdir)/sdksyms.sh $(top_srcdir) $(CFLAGS) $(AM_CFLAGS) $(INCLUDES)
+	CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $(srcdir)/sdksyms.sh $(top_srcdir) $(CPPFLAGS) $(AM_CPPFLAGS) $(INCLUDES)
 
 SDKSYMS_DEP = sdksyms.dep
 include $(SDKSYMS_DEP)
commit 6826d7bbf0d25194c5a1660403a3aed873fc6d7d
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 17 13:15:12 2012 -0800

    XQuartz: Detect FatalErrors on startup to prevent tight crash loops
    
    If a FatalError occurs before the server finishes launching, it will
    not have drained the launchd-owned DISPLAY socket, so launchd will
    just relaunch it.  This can cause the server to crash in a tight loop
    which will spam the user with CrashReporter windows that claim focus on
    appearance.
    
    This allows users stuck in this loop to "deal" with the problem without
    popping up a crash report every 10 seconds.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit 3505e1faadddeeec85a0d3f823c877ea33f86e00)
    
    Conflicts:
    
    	hw/xquartz/X11Application.h

diff --git a/hw/xquartz/X11Application.h b/hw/xquartz/X11Application.h
index 740a807..5ea6129 100644
--- a/hw/xquartz/X11Application.h
+++ b/hw/xquartz/X11Application.h
@@ -89,6 +89,9 @@ X11ApplicationCanEnterRandR(void);
 void
 X11ApplicationMain(int argc, char **argv, char **envp);
 
+void
+X11ApplicationFatalError(const char *f, va_list args) __printflike(1, 0);
+
 #define PREFS_APPSMENU                "apps_menu"
 #define PREFS_FAKEBUTTONS             "enable_fake_buttons"
 #define PREFS_KEYEQUIVS               "enable_key_equivalents"
diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index b686b00..c77b724 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -72,6 +72,7 @@ static dispatch_queue_t eventTranslationQueue;
 
 extern Bool noTestExtensions;
 extern Bool noRenderExtension;
+extern BOOL serverRunning;
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
 static TISInputSourceRef last_key_layout;
@@ -1073,6 +1074,50 @@ X11ApplicationCanEnterRandR(void)
     }
 }
 
+void
+X11ApplicationFatalError(const char *f, va_list args)
+{
+#ifdef HAVE_LIBDISPATCH
+    NSString *title, *msg;
+    char *error_msg;
+
+    /* This is called by FatalError() in the server thread just before
+     * we would abort.  If the server never got off the ground, We should
+     * inform the user of the error rather than letting the ever-so-friendly
+     * CrashReporter do it for us.
+     *
+     * This also has the benefit of forcing user interaction rather than
+     * allowing an infinite throttled-restart if the crash occurs before
+     * we can drain the launchd socket.
+     */
+
+    if (serverRunning) {
+        return;
+    }
+
+    title = NSLocalizedString(@"The application X11 could not be opened.",
+                              @"Dialog title when encountering a fatal error");
+    msg = NSLocalizedString(@"An error occurred while starting the X11 server: \"%s\"\n\nClick Quit to quit X11. Click Report to see more details or send a report to Apple.",
+                            @"Dialog when encountering a fatal error");
+
+    vasprintf(&error_msg, f, args);
+    msg = [NSString stringWithFormat:msg, error_msg];
+
+    /* We want the AppKit thread to actually service the alert or we will race [NSApp run] and create an
+     * 'NSInternalInconsistencyException', reason: 'NSApp with wrong _running count'
+     */
+    dispatch_sync(dispatch_get_main_queue(), ^{
+        if (NSAlertDefaultReturn == NSRunAlertPanel(title, msg, NSLocalizedString(@"Quit", @""),
+                                                    NSLocalizedString (@"Report...", @""), nil)) {
+            exit(EXIT_FAILURE);
+        }
+    });
+
+    /* fall back to caller to do the abort() in the DIX */
+#endif
+}
+
+
 static void
 check_xinitrc(void)
 {
diff --git a/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings b/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings
index bf2089c..36ae0ff 100644
Binary files a/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings and b/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings differ
diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c
index e2ab057..41db72a 100644
--- a/hw/xquartz/darwin.c
+++ b/hw/xquartz/darwin.c
@@ -78,6 +78,8 @@
 #include "quartzKeyboard.h"
 #include "quartz.h"
 
+#include "X11Application.h"
+
 aslclient aslc;
 
 void
@@ -672,7 +674,7 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
 void
 OsVendorFatalError(const char *f, va_list args)
 {
-    ErrorF("   OsVendorFatalError\n");
+    X11ApplicationFatalError(f, args);
 }
 
 /*
commit ef28cd2d7da9e1ea8399f1072a9c60a5af6b7fc0
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Apr 19 16:39:23 2012 -0700

    os: Annotate OsVendorFatalError as _X_ATTRIBUTE_PRINTF
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Tested-By: Michal Suchanek <hramrach at gmail.com>
    (cherry picked from commit d97868d934fd1a00f9e9ef23a1154a70c7bc0464)

diff --git a/include/os.h b/include/os.h
index 970ff02..8b58d7a 100644
--- a/include/os.h
+++ b/include/os.h
@@ -321,7 +321,8 @@ extern _X_EXPORT void
 OsCleanup(Bool);
 
 extern _X_EXPORT void
-OsVendorFatalError(const char *f, va_list args);
+OsVendorFatalError(const char *f, va_list args)
+_X_ATTRIBUTE_PRINTF(1, 0);
 
 extern _X_EXPORT void
 OsVendorInit(void);
commit 43e2760f536737cbd50dd3d8eb7faf39633b9e8c
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Wed Mar 28 15:07:51 2012 -0700

    os: Fix regression with FatalError not calling va_start
    
    Regression From: a818b305989bbcde4e585112a7ee70cbc0b14a92
    
    Found-by: Colin Harrison <colin.harrison at virgin.net>
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit 817cec8ffd6cdb1abbcc00decd43569d44801764)

diff --git a/os/log.c b/os/log.c
index d913449..501fd45 100644
--- a/os/log.c
+++ b/os/log.c
@@ -596,6 +596,8 @@ FatalError(const char *f, ...)
     else
         ErrorF("\nFatal server error:\n");
 
+    va_start(args, f);
+
     /* Make a copy for OsVendorFatalError */
     va_copy(args2, args);
 
commit 6eef64baedb616592a8dc5221d753b5388b9b969
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 17 12:35:02 2012 -0800

    os: Pass the FatalError message to OsVendorFatalError
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    (cherry picked from commit a818b305989bbcde4e585112a7ee70cbc0b14a92)

diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 09e3d74..5804353 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -905,7 +905,7 @@ OsVendorInit(void)
  * two routines mentioned here, as well as by others) to use the
  * referenced routine instead of \a vfprintf().) */
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
 }
 
diff --git a/hw/dmx/dmxlog.c b/hw/dmx/dmxlog.c
index b56bb93..33aee59 100644
--- a/hw/dmx/dmxlog.c
+++ b/hw/dmx/dmxlog.c
@@ -110,9 +110,6 @@ VFatalError(const char *format, va_list args)
 {
     VErrorF(format, args);
     ErrorF("\n");
-#ifdef DDXOSFATALERROR
-    OsVendorFatalError();
-#endif
     AbortServer();
  /*NOTREACHED*/}
 #endif
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index f65ab96..ecdae19 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -1104,7 +1104,7 @@ KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
 }
 
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
 }
 
diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 2d679a5..e2cd96c 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -219,7 +219,7 @@ OsVendorInit(void)
 }
 
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
 }
 
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 0974893..2a7d0a3 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -1053,7 +1053,7 @@ AbortDDX(enum ExitCode error)
 }
 
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
 #ifdef VENDORSUPPORT
     ErrorF("\nPlease refer to your Operating System Vendor support pages\n"
diff --git a/hw/xnest/Init.c b/hw/xnest/Init.c
index 0909826..330b8ca 100644
--- a/hw/xnest/Init.c
+++ b/hw/xnest/Init.c
@@ -142,7 +142,7 @@ OsVendorInit(void)
 }
 
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
     return;
 }
diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c
index 74e11fe..e2ab057 100644
--- a/hw/xquartz/darwin.c
+++ b/hw/xquartz/darwin.c
@@ -670,7 +670,7 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
  * OsVendorFatalError
  */
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
     ErrorF("   OsVendorFatalError\n");
 }
diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c
index 4049e97..a25307c 100644
--- a/hw/xwin/winerror.c
+++ b/hw/xwin/winerror.c
@@ -70,7 +70,7 @@ OsVendorVErrorF(const char *pszFormat, va_list va_args)
  * Attempt to do last-ditch, safe, important cleanup here.
  */
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
     /* Don't give duplicate warning if UseMsg was called */
     if (g_fSilentFatalError)
diff --git a/include/os.h b/include/os.h
index 4b5b440..970ff02 100644
--- a/include/os.h
+++ b/include/os.h
@@ -321,7 +321,7 @@ extern _X_EXPORT void
 OsCleanup(Bool);
 
 extern _X_EXPORT void
-OsVendorFatalError(void);
+OsVendorFatalError(const char *f, va_list args);
 
 extern _X_EXPORT void
 OsVendorInit(void);
diff --git a/os/log.c b/os/log.c
index 0ccd126..d913449 100644
--- a/os/log.c
+++ b/os/log.c
@@ -588,6 +588,7 @@ void
 FatalError(const char *f, ...)
 {
     va_list args;
+    va_list args2;
     static Bool beenhere = FALSE;
 
     if (beenhere)
@@ -595,22 +596,25 @@ FatalError(const char *f, ...)
     else
         ErrorF("\nFatal server error:\n");
 
-    va_start(args, f);
+    /* Make a copy for OsVendorFatalError */
+    va_copy(args2, args);
+
 #ifdef __APPLE__
     {
-        va_list args2;
+        va_list apple_args;
 
-        va_copy(args2, args);
-        (void) vsnprintf(__crashreporter_info_buff__,
-                         sizeof(__crashreporter_info_buff__), f, args2);
-        va_end(args2);
+        va_copy(apple_args, args);
+        (void)vsnprintf(__crashreporter_info_buff__,
+                        sizeof(__crashreporter_info_buff__), f, apple_args);
+        va_end(apple_args);
     }
 #endif
     VErrorF(f, args);
     va_end(args);
     ErrorF("\n");
     if (!beenhere)
-        OsVendorFatalError();
+        OsVendorFatalError(f, args2);
+    va_end(args2);
     if (!beenhere) {
         beenhere = TRUE;
         AbortServer();
diff --git a/test/ddxstubs.c b/test/ddxstubs.c
index a214b96..3647dc5 100644
--- a/test/ddxstubs.c
+++ b/test/ddxstubs.c
@@ -50,7 +50,7 @@ OsVendorInit(void)
 }
 
 void
-OsVendorFatalError(void)
+OsVendorFatalError(const char *f, va_list args)
 {
 }
 
commit ed33772a0d3ace5844e157ae78885ded000819ea
Author: Michal Suchanek <hramrach at gmail.com>
Date:   Wed Mar 28 18:12:39 2012 -0700

    xfree86: workaround crash on close
    
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41653
    
    Signed-off-by: Michal Suchanek <hramrach at gmail.com>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Tested-by: Knut Petersen <Knut_Petersen at t-online.de>
    (cherry picked from commit fa6dddc6ce51c1b7a43fb379fb2a19550f6c8683)

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 85d7557..cbc8687 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -290,14 +290,19 @@ xf86RotateDestroy(xf86CrtcPtr crtc)
      * Clean up damage structures when no crtcs are rotated
      */
     if (xf86_config->rotation_damage) {
+        DrawablePtr screenDrawable = NULL;
+        if (pScreen && pScreen->root)
+            screenDrawable = &pScreen->root->drawable;
         /* Free damage structure */
         if (xf86_config->rotation_damage_registered) {
-            DamageUnregister(&pScreen->root->drawable,
-                             xf86_config->rotation_damage);
+            if (screenDrawable)
+                DamageUnregister(screenDrawable,
+                        xf86_config->rotation_damage);
             xf86_config->rotation_damage_registered = FALSE;
             DisableLimitedSchedulingLatency();
         }
-        DamageDestroy(xf86_config->rotation_damage);
+        if (screenDrawable)
+            DamageDestroy(xf86_config->rotation_damage);
         xf86_config->rotation_damage = NULL;
     }
 }
commit e4dbdee392c78de13fab03c3826f9453f42a8a46
Author: Jonas Maebe <jonas.maebe at elis.ugent.be>
Date:   Sun Apr 22 20:52:47 2012 -0700

    glapi: Correct size of allocated _glapi_table struct
    
    The __glapi_gentable_set_remaining_noop() routine treats the _glapi_struct
    as an array of _glapi_get_dispatch_table_size() pointers, so we have to
    allocate _glapi_get_dispatch_table_size()*sizeof(void*) bytes rather than
    sizeof(struct _glapi_struct) bytes.
    
    Signed-off-by: Jonas Maebe <jonas.maebe at elis.ugent.be>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit adcb48a29dcb3f32ff570551de4b014775c1e147)

diff --git a/glx/glapi_gentable.c b/glx/glapi_gentable.c
index 1fb1431..4b28015 100644
--- a/glx/glapi_gentable.c
+++ b/glx/glapi_gentable.c
@@ -113,7 +113,7 @@ __glapi_gentable_set_remaining_noop(struct _glapi_table *disp)
 struct _glapi_table *
 _glapi_create_table_from_handle(void *handle, const char *symbol_prefix)
 {
-    struct _glapi_table *disp = calloc(1, sizeof(struct _glapi_table));
+    struct _glapi_table *disp = calloc(_glapi_get_dispatch_table_size(), sizeof(void*));
     char symboln[512];
 
     if (!disp)
commit 6b45dff0240729a78a43cc74f1631b2dd5a0d6b3
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Apr 19 16:38:06 2012 -0700

    XQuartz: darwinPointer now sends both absolute and relative motion
    
    This should hopefully help out wine clients that were continuing to
    have issues after the earlier changes.
    
    http://xquartz.macosforge.org/trac/ticket/548
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit e34519e525559b01a63d26639f13f0487468de28)

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 3517c49..b686b00 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -214,7 +214,8 @@ message_kit_thread(SEL selector, NSObject *arg)
     if (state) {
         if (bgMouseLocationUpdated) {
             DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
-                                    bgMouseLocation.x, bgMouseLocation.y);
+                                    bgMouseLocation.x, bgMouseLocation.y,
+                                    0.0, 0.0);
             bgMouseLocationUpdated = FALSE;
         }
         DarwinSendDDXEvent(kXquartzActivate, 0);
@@ -1547,14 +1548,16 @@ handle_mouse:
         if (bgMouseLocationUpdated) {
             if (!(ev_type == MotionNotify && ev_button == 0)) {
                 DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
-                                        location.x, location.y);
+                                        location.x, location.y,
+                                        0.0, 0.0);
             }
             bgMouseLocationUpdated = FALSE;
         }
 
         if (pDev == darwinPointer) {
             DarwinSendPointerEvents(pDev, ev_type, ev_button,
-                                    location.x, location.y);
+                                    location.x, location.y,
+                                    [e deltaX], [e deltaY]);
         } else {
             DarwinSendTabletEvents(pDev, ev_type, ev_button,
                                    location.x, location.y, pressure,
@@ -1619,7 +1622,8 @@ handle_mouse:
         if (!XQuartzServerVisible && noTestExtensions) {
             bgMouseLocationUpdated = FALSE;
             DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
-                                    location.x, location.y);
+                                    location.x, location.y,
+                                    0.0, 0.0);
         }
 #endif
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c
index 2d5174a..74e11fe 100644
--- a/hw/xquartz/darwin.c
+++ b/hw/xquartz/darwin.c
@@ -307,7 +307,7 @@ static int
 DarwinMouseProc(DeviceIntPtr pPointer, int what)
 {
 #define NBUTTONS 3
-#define NAXES    4
+#define NAXES    6
     // 3 buttons: left, middle, right
     CARD8 map[NBUTTONS + 1] = { 0, 1, 2, 3};
     Atom btn_labels[NBUTTONS] = { 0 };
@@ -321,10 +321,12 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what)
         btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
         btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
 
-        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
-        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
-        axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
-        axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL);
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+        axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+        axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+        axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
+        axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL);
 
         // Set button map.
         InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS,
@@ -332,21 +334,27 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what)
                                 (PtrCtrlProcPtr)NoopDDA,
                                 GetMotionHistorySize(), NAXES,
                                 axes_labels);
-        InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 
+        InitValuatorAxisStruct(pPointer, 0, axes_labels[0],
                                NO_AXIS_LIMITS, NO_AXIS_LIMITS,
-                               1, 0, 1, Relative);
-        InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 
+                               0, 0, 0, Absolute);
+        InitValuatorAxisStruct(pPointer, 1, axes_labels[1],
                                NO_AXIS_LIMITS, NO_AXIS_LIMITS,
-                               1, 0, 1, Relative);
+                               0, 0, 0, Absolute);
         InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 
                                NO_AXIS_LIMITS, NO_AXIS_LIMITS,
                                1, 0, 1, Relative);
         InitValuatorAxisStruct(pPointer, 3, axes_labels[3], 
                                NO_AXIS_LIMITS, NO_AXIS_LIMITS,
                                1, 0, 1, Relative);
+        InitValuatorAxisStruct(pPointer, 4, axes_labels[4], 
+                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
+                               1, 0, 1, Relative);
+        InitValuatorAxisStruct(pPointer, 5, axes_labels[5], 
+                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
+                               1, 0, 1, Relative);
 
-        SetScrollValuator(pPointer, 2, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED);
-        SetScrollValuator(pPointer, 3, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE);
+        SetScrollValuator(pPointer, 4, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED);
+        SetScrollValuator(pPointer, 5, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE);
         break;
 
     case DEVICE_ON:
@@ -397,23 +405,24 @@ DarwinTabletProc(DeviceIntPtr pPointer, int what)
                                 axes_labels);
         InitProximityClassDeviceStruct(pPointer);
 
-        InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0,
-                               XQUARTZ_VALUATOR_LIMIT, 1, 0, 1,
-                               Absolute);
-        InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0,
-                               XQUARTZ_VALUATOR_LIMIT, 1, 0, 1,
-                               Absolute);
-        InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0,
-                               XQUARTZ_VALUATOR_LIMIT, 1, 0, 1,
-                               Absolute);
+        InitValuatorAxisStruct(pPointer, 0, axes_labels[0],
+                               0, XQUARTZ_VALUATOR_LIMIT,
+                               1, 0, 1, Absolute);
+        InitValuatorAxisStruct(pPointer, 1, axes_labels[1],
+                               0, XQUARTZ_VALUATOR_LIMIT,
+                               1, 0, 1, Absolute);
+        InitValuatorAxisStruct(pPointer, 2, axes_labels[2],
+                               0, XQUARTZ_VALUATOR_LIMIT,
+                               1, 0, 1, Absolute);
         InitValuatorAxisStruct(pPointer, 3, axes_labels[3],
                                -XQUARTZ_VALUATOR_LIMIT,
-                               XQUARTZ_VALUATOR_LIMIT, 1, 0, 1,
-                               Absolute);
+                               XQUARTZ_VALUATOR_LIMIT,
+                               1, 0, 1, Absolute);
         InitValuatorAxisStruct(pPointer, 4, axes_labels[4],
                                -XQUARTZ_VALUATOR_LIMIT,
-                               XQUARTZ_VALUATOR_LIMIT, 1, 0, 1,
-                               Absolute);
+                               XQUARTZ_VALUATOR_LIMIT,
+                               1, 0, 1, Absolute);
+
         //          pPointer->use = IsXExtensionDevice;
         break;
 
diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 25f011b..b41c6fd 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -74,12 +74,6 @@
 
 #include <IOKit/hidsystem/IOLLEvent.h>
 
-/* Fake button press/release for scroll wheel move. */
-#define SCROLLWHEELUPFAKE    4
-#define SCROLLWHEELDOWNFAKE  5
-#define SCROLLWHEELLEFTFAKE  6
-#define SCROLLWHEELRIGHTFAKE 7
-
 #include <X11/extensions/applewmconst.h>
 #include "applewmExt.h"
 
@@ -497,12 +491,6 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
     pointer_x -= darwinMainScreenX + screen->x;
     pointer_y -= darwinMainScreenY + screen->y;
 
-    if (pointer_x < 0.0)
-        pointer_x = 0.0;
-
-    if (pointer_y < 0.0)
-        pointer_y = 0.0;
-    
     /* Adjust our pointer location to the [0,1] range */
     pointer_x = pointer_x / (double)screenInfo.width;
     pointer_y = pointer_y / (double)screenInfo.height;
@@ -528,7 +516,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
 
 void
 DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
-                        double pointer_x, double pointer_y)
+                        double pointer_x, double pointer_y,
+                        double pointer_dx, double pointer_dy)
 {
     static int darwinFakeMouseButtonDown = 0;
     ScreenPtr screen;
@@ -553,7 +542,7 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
             /* We're currently "down" with another button, so release it first */
             DarwinSendPointerEvents(pDev, ButtonRelease,
                                     darwinFakeMouseButtonDown,
-                                    pointer_x, pointer_y);
+                                    pointer_x, pointer_y, 0.0, 0.0);
             darwinFakeMouseButtonDown = 0;
         }
         if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
@@ -591,22 +580,23 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
     pointer_x -= darwinMainScreenX + screen->x;
     pointer_y -= darwinMainScreenY + screen->y;
 
-    if (pointer_x < 0.0)
-        pointer_x = 0.0;
-
-    if (pointer_y < 0.0)
-        pointer_y = 0.0;
-
     valuator_mask_zero(&valuators);
     valuator_mask_set_double(&valuators, 0, pointer_x);
     valuator_mask_set_double(&valuators, 1, pointer_y);
 
+    if (ev_type == MotionNotify) {
+        if (pointer_dx != 0.0)
+            valuator_mask_set_double(&valuators, 2, pointer_dx);
+        if (pointer_dy != 0.0)
+            valuator_mask_set_double(&valuators, 3, pointer_dy);
+    }
+
     darwinEvents_lock();
     {
         QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
                            &valuators);
         DarwinPokeEQ();
-    } darwinEvents_unlock();
+    } darwinEvents_unlock();   
 }
 
 void
@@ -647,8 +637,8 @@ DarwinSendScrollEvents(double scroll_x, double scroll_y) {
     }
 
     valuator_mask_zero(&valuators);
-    valuator_mask_set_double(&valuators, 2, scroll_y);
-    valuator_mask_set_double(&valuators, 3, scroll_x);
+    valuator_mask_set_double(&valuators, 4, scroll_y);
+    valuator_mask_set_double(&valuators, 5, scroll_x);
 
     darwinEvents_lock();
     {
diff --git a/hw/xquartz/darwinEvents.h b/hw/xquartz/darwinEvents.h
index 812a5dc..448e730 100644
--- a/hw/xquartz/darwinEvents.h
+++ b/hw/xquartz/darwinEvents.h
@@ -49,7 +49,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
                        double tilt_x, double tilt_y);
 void
 DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
-                        double pointer_x, double pointer_y);
+                        double pointer_x, double pointer_y,
+                        double pointer_dx, double pointer_dy);
 void
 DarwinSendKeyboardEvents(int ev_type, int keycode);
 void
commit 0d13e62da2b3527db7b3b6de91464015eb20a514
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Apr 19 18:48:22 2012 -0700

    XQuartz: Add a hack to better handle clicky wheel scroll mice
    
    We loose information from AppKit being in our way.  Before adopting
    smooth scrolling, we always rounded-up the number of scroll button
    clicks per NSEvent.  Now, the scroll value is accumulated in the
    dix, and clicky scroll wheels with legacy X11 clients are seeing
    an accumulation of error due to so many translations (button press
    to smooth scrolling value in AppKit, passed to the dix, and then
    synthesized into a button press).  This attempts to make the
    situation better.
    
    http://xquartz.macosforge.org/trac/ticket/562
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit 662d41acdde1dcb9774fbe4054e251c708acaffe)

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index f251d23..3517c49 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -1590,8 +1590,28 @@ handle_mouse:
 
     case NSScrollWheel:
     {
-        float deltaX = [e deltaX];
-        float deltaY = [e deltaY];
+        CGFloat deltaX = [e deltaX];
+        CGFloat deltaY = [e deltaY];
+        CGEventRef cge = [e CGEvent];
+        BOOL isContinuous =
+            CGEventGetIntegerValueField(cge, kCGScrollWheelEventIsContinuous);
+
+#if 0
+        /* Scale the scroll value by line height */
+        CGEventSourceRef source = CGEventCreateSourceFromEvent(cge);
+        if (source) {
+            double lineHeight = CGEventSourceGetPixelsPerLine(source);
+            CFRelease(source);
+            
+            /* There's no real reason for the 1/5 ratio here other than that
+             * it feels like a good ratio after some testing.
+             */
+            
+            deltaX *= lineHeight / 5.0;
+            deltaY *= lineHeight / 5.0;
+        }
+#endif
+        
 #if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0
         /* If we're in the background, we need to send a MotionNotify event
          * first, since we aren't getting them on background mouse motion
@@ -1611,6 +1631,93 @@ handle_mouse:
             deltaY *= -1;
         }
 #endif
+        /* This hack is in place to better deal with "clicky" scroll wheels:
+         * http://xquartz.macosforge.org/trac/ticket/562
+         */
+        if (!isContinuous) {
+            static NSTimeInterval lastScrollTime = 0.0;
+
+            /* These store how much extra we have already scrolled.
+             * ie, this is how much we ignore on the next event.
+             */
+            static double deficit_x = 0.0;
+            static double deficit_y = 0.0;
+
+            /* If we have past a second since the last scroll, wipe the slate
+             * clean
+             */
+            if ([e timestamp] - lastScrollTime > 1.0) {
+                deficit_x = deficit_y = 0.0;
+            }
+            lastScrollTime = [e timestamp];
+
+            if (deltaX != 0.0) {
+                /* If we changed directions, wipe the slate clean */
+                if ((deficit_x < 0.0 && deltaX > 0.0) ||
+                    (deficit_x > 0.0 && deltaX < 0.0)) {
+                    deficit_x = 0.0;
+                }
+
+                /* Eat up the deficit, but ensure that something is
+                 * always sent 
+                 */
+                if (fabs(deltaX) > fabs(deficit_x)) {
+                    deltaX -= deficit_x;
+
+                    if (deltaX > 0.0) {
+                        deficit_x = ceil(deltaX) - deltaX;
+                        deltaX = ceil(deltaX);
+                    } else {
+                        deficit_x = floor(deltaX) - deltaX;
+                        deltaX = floor(deltaX);
+                    }
+                } else {
+                    deficit_x -= deltaX;
+
+                    if (deltaX > 0.0) {
+                        deltaX = 1.0;
+                    } else {
+                        deltaX = -1.0;
+                    }
+
+                    deficit_x += deltaX;
+                }
+            }
+
+            if (deltaY != 0.0) {
+                /* If we changed directions, wipe the slate clean */
+                if ((deficit_y < 0.0 && deltaY > 0.0) ||
+                    (deficit_y > 0.0 && deltaY < 0.0)) {
+                    deficit_y = 0.0;
+                }
+
+                /* Eat up the deficit, but ensure that something is
+                 * always sent 
+                 */
+                if (fabs(deltaY) > fabs(deficit_y)) {
+                    deltaY -= deficit_y;
+
+                    if (deltaY > 0.0) {
+                        deficit_y = ceil(deltaY) - deltaY;
+                        deltaY = ceil(deltaY);
+                    } else {
+                        deficit_y = floor(deltaY) - deltaY;
+                        deltaY = floor(deltaY);
+                    }
+                } else {
+                    deficit_y -= deltaY;
+
+                    if (deltaY > 0.0) {
+                        deltaY = 1.0;
+                    } else {
+                        deltaY = -1.0;
+                    }
+
+                    deficit_y += deltaY;
+                }
+            }
+        }
+
         DarwinSendScrollEvents(deltaX, deltaY);
         break;
     }
commit 287f8271a3af18fb1a56a761fa02ec76148d9e32
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Apr 19 16:20:30 2012 -0700

    XQuartz: Use screenInfo.{width,height} instead of grabbing it from the first screen
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit eda85290ae47d8dd497ef9335d10268bbe3e02a0)

diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 9fc23a3..25f011b 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -504,8 +504,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
         pointer_y = 0.0;
     
     /* Adjust our pointer location to the [0,1] range */
-    pointer_x = pointer_x / (double)screenInfo.screens[0]->width;
-    pointer_y = pointer_y / (double)screenInfo.screens[0]->height;
+    pointer_x = pointer_x / (double)screenInfo.width;
+    pointer_y = pointer_y / (double)screenInfo.height;
 
     valuator_mask_zero(&valuators);
     valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x);
commit 67cc65ba3ca35b4eb9592e1e6f299938509cddec
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Wed Apr 18 17:50:55 2012 -0700

    XQuartz: Separate out tablet and mouse event delivery into separate functions
    
    This should have no immediate impact aside from fake mouse buttons no longer
    working with tablets (where they aren't needed or desired anyways).  This
    prepares us for future changes.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit b99586c9086ac29df144ef75df92f8c0c7554651)

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 7fd3d16..f251d23 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -214,9 +214,7 @@ message_kit_thread(SEL selector, NSObject *arg)
     if (state) {
         if (bgMouseLocationUpdated) {
             DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
-                                    bgMouseLocation.x, bgMouseLocation.y, 0.0,
-                                    0.0,
-                                    0.0);
+                                    bgMouseLocation.x, bgMouseLocation.y);
             bgMouseLocationUpdated = FALSE;
         }
         DarwinSendDDXEvent(kXquartzActivate, 0);
@@ -1501,9 +1499,9 @@ handle_mouse:
             if ([e isEnteringProximity])
                 needsProximityIn = YES;
             else
-                DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut,
-                                          location.x, location.y, pressure,
-                                          tilt.x, tilt.y);
+                DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0,
+                                       location.x, location.y, pressure,
+                                       tilt.x, tilt.y);
             return;
         }
 
@@ -1515,9 +1513,9 @@ handle_mouse:
             pDev = darwinTabletCurrent;
 
             if (needsProximityIn) {
-                DarwinSendProximityEvents(darwinTabletCurrent, ProximityIn,
-                                          location.x, location.y, pressure,
-                                          tilt.x, tilt.y);
+                DarwinSendTabletEvents(darwinTabletCurrent, ProximityIn, 0,
+                                       location.x, location.y, pressure,
+                                       tilt.x, tilt.y);
 
                 needsProximityIn = NO;
             }
@@ -1548,14 +1546,20 @@ handle_mouse:
 
         if (bgMouseLocationUpdated) {
             if (!(ev_type == MotionNotify && ev_button == 0)) {
-                DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x,
-                                        location.y, pressure, tilt.x, tilt.y);
+                DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
+                                        location.x, location.y);
             }
             bgMouseLocationUpdated = FALSE;
         }
 
-        DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x,
-                                location.y, pressure, tilt.x, tilt.y);
+        if (pDev == darwinPointer) {
+            DarwinSendPointerEvents(pDev, ev_type, ev_button,
+                                    location.x, location.y);
+        } else {
+            DarwinSendTabletEvents(pDev, ev_type, ev_button,
+                                   location.x, location.y, pressure,
+                                   tilt.x, tilt.y);
+        }
 
         break;
 
@@ -1579,9 +1583,9 @@ handle_mouse:
         if ([e isEnteringProximity])
             needsProximityIn = YES;
         else
-            DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut,
-                                      location.x, location.y, pressure,
-                                      tilt.x, tilt.y);
+            DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0,
+                                   location.x, location.y, pressure,
+                                   tilt.x, tilt.y);
         break;
 
     case NSScrollWheel:
@@ -1595,8 +1599,7 @@ handle_mouse:
         if (!XQuartzServerVisible && noTestExtensions) {
             bgMouseLocationUpdated = FALSE;
             DarwinSendPointerEvents(darwinPointer, MotionNotify, 0,
-                                    location.x, location.y, pressure, 
-                                    tilt.x, tilt.y);
+                                    location.x, location.y);
         }
 #endif
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index c62dd44..9fc23a3 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -44,19 +44,20 @@
 #include <dix-config.h>
 #endif
 
-#include   <X11/X.h>
-#include   <X11/Xmd.h>
-#include   <X11/Xproto.h>
-#include   "misc.h"
-#include   "windowstr.h"
-#include   "pixmapstr.h"
-#include   "inputstr.h"
-#include   "inpututils.h"
-#include   "eventstr.h"
-#include   "mi.h"
-#include   "scrnintstr.h"
-#include   "mipointer.h"
-#include   "os.h"
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "inputstr.h"
+#include "inpututils.h"
+#include "eventstr.h"
+#include "mi.h"
+#include "scrnintstr.h"
+#include "mipointer.h"
+#include "os.h"
+#include "exglobals.h"
 
 #include "darwin.h"
 #include "quartz.h"
@@ -442,56 +443,6 @@ DarwinPokeEQ(void)
     write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
 }
 
-/* Convert from Appkit pointer input values to X input values:
- * Note: pointer_x and pointer_y are relative to the upper-left of primary
- *       display.
- */
-static void
-DarwinPrepareValuators(DeviceIntPtr pDev, ValuatorMask *pmask,
-                       ScreenPtr screen,
-                       double pointer_x, double pointer_y,
-                       double pressure, double tilt_x,
-                       double tilt_y)
-{
-
-    valuator_mask_zero(pmask);
-
-    /* Fix offset between darwin and X screens */
-    pointer_x -= darwinMainScreenX + screen->x;
-    pointer_y -= darwinMainScreenY + screen->y;
-
-    if (pointer_x < 0.0)
-        pointer_x = 0.0;
-
-    if (pointer_y < 0.0)
-        pointer_y = 0.0;
-
-    if (pDev == darwinPointer) {
-        valuator_mask_set_double(pmask, 0, pointer_x);
-        valuator_mask_set_double(pmask, 1, pointer_y);
-    }
-    else {
-        valuator_mask_set_double(pmask, 0, XQUARTZ_VALUATOR_LIMIT *
-                                 (pointer_x /
-                                  (double)screenInfo.screens[0]->width));
-        valuator_mask_set_double(pmask, 1, XQUARTZ_VALUATOR_LIMIT *
-                                 (pointer_y /
-                                  (double)screenInfo.screens[0]->height));
-        valuator_mask_set_double(pmask, 2, XQUARTZ_VALUATOR_LIMIT * pressure);
-        valuator_mask_set_double(pmask, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x);
-        valuator_mask_set_double(pmask, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y);
-        DEBUG_LOG("Pointer (%lf, %lf), Valuators: {%lf,%lf,%lf,%lf,%lf}\n",
-                  pointer_x, pointer_y,
-                  valuator_mask_get_double(pmask,
-                                           0),
-                  valuator_mask_get_double(pmask, 1),
-                  valuator_mask_get_double(pmask,
-                                           2),
-                  valuator_mask_get_double(pmask, 3),
-                  valuator_mask_get_double(pmask, 4));
-    }
-}
-
 void
 DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev)
 {
@@ -521,27 +472,78 @@ DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev)
 }
 
 void
+DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
+                       double pointer_x, double pointer_y,
+                       double pressure, double tilt_x,
+                       double tilt_y)
+{
+    ScreenPtr screen;
+    ValuatorMask valuators;
+
+    if (!darwinEvents) {
+        DEBUG_LOG("%s called before darwinEvents was initialized\n",
+                  __FUNCTION__);
+        return;
+    }
+
+    screen = miPointerGetScreen(pDev);
+    if (!screen) {
+        DEBUG_LOG("%s called before screen was initialized\n",
+                  __FUNCTION__);
+        return;
+    }
+
+    /* Fix offset between darwin and X screens */
+    pointer_x -= darwinMainScreenX + screen->x;
+    pointer_y -= darwinMainScreenY + screen->y;
+
+    if (pointer_x < 0.0)
+        pointer_x = 0.0;
+
+    if (pointer_y < 0.0)
+        pointer_y = 0.0;
+    
+    /* Adjust our pointer location to the [0,1] range */
+    pointer_x = pointer_x / (double)screenInfo.screens[0]->width;
+    pointer_y = pointer_y / (double)screenInfo.screens[0]->height;
+
+    valuator_mask_zero(&valuators);
+    valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x);
+    valuator_mask_set_double(&valuators, 1, XQUARTZ_VALUATOR_LIMIT * pointer_y);
+    valuator_mask_set_double(&valuators, 2, XQUARTZ_VALUATOR_LIMIT * pressure);
+    valuator_mask_set_double(&valuators, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x);
+    valuator_mask_set_double(&valuators, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y);
+
+    darwinEvents_lock();
+    {
+        if (ev_type == ProximityIn || ev_type == ProximityOut) {
+            QueueProximityEvents(pDev, ev_type, &valuators);
+        } else {
+            QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
+                               &valuators);
+        }
+        DarwinPokeEQ();
+    } darwinEvents_unlock();
+}
+
+void
 DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
-                        double pointer_x, double pointer_y,
-                        double pressure, double tilt_x,
-                        double tilt_y)
+                        double pointer_x, double pointer_y)
 {
     static int darwinFakeMouseButtonDown = 0;
     ScreenPtr screen;
     ValuatorMask valuators;
 
-    //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
-
     if (!darwinEvents) {
-        DEBUG_LOG(
-            "DarwinSendPointerEvents called before darwinEvents was initialized\n");
+        DEBUG_LOG("%s called before darwinEvents was initialized\n",
+                  __FUNCTION__);
         return;
     }
 
     screen = miPointerGetScreen(pDev);
     if (!screen) {
-        DEBUG_LOG(
-            "DarwinSendPointerEvents called before screen was initialized\n");
+        DEBUG_LOG("%s called before screen was initialized\n",
+                  __FUNCTION__);
         return;
     }
 
@@ -550,9 +552,8 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
         if (darwinFakeMouseButtonDown != 0) {
             /* We're currently "down" with another button, so release it first */
             DarwinSendPointerEvents(pDev, ButtonRelease,
-                                    darwinFakeMouseButtonDown, pointer_x,
-                                    pointer_y, pressure, tilt_x,
-                                    tilt_y);
+                                    darwinFakeMouseButtonDown,
+                                    pointer_x, pointer_y);
             darwinFakeMouseButtonDown = 0;
         }
         if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
@@ -586,9 +587,20 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
         darwinFakeMouseButtonDown = 0;
     }
 
-    DarwinPrepareValuators(pDev, &valuators, screen, pointer_x, pointer_y,
-                           pressure, tilt_x,
-                           tilt_y);
+    /* Fix offset between darwin and X screens */
+    pointer_x -= darwinMainScreenX + screen->x;
+    pointer_y -= darwinMainScreenY + screen->y;
+
+    if (pointer_x < 0.0)
+        pointer_x = 0.0;
+
+    if (pointer_y < 0.0)
+        pointer_y = 0.0;
+
+    valuator_mask_zero(&valuators);
+    valuator_mask_set_double(&valuators, 0, pointer_x);
+    valuator_mask_set_double(&valuators, 1, pointer_y);
+
     darwinEvents_lock();
     {
         QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
@@ -615,42 +627,6 @@ DarwinSendKeyboardEvents(int ev_type, int keycode)
     } darwinEvents_unlock();
 }
 
-void
-DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, double pointer_x,
-                          double pointer_y,
-                          double pressure, double tilt_x,
-                          double tilt_y)
-{
-    ScreenPtr screen;
-    ValuatorMask valuators;
-
-    DEBUG_LOG("DarwinSendProximityEvents: %d l:%f,%f p:%f t:%f,%f\n", ev_type,
-              pointer_x, pointer_y, pressure, tilt_x,
-              tilt_y);
-
-    if (!darwinEvents) {
-        DEBUG_LOG(
-            "DarwinSendProximityEvents called before darwinEvents was initialized\n");
-        return;
-    }
-
-    screen = miPointerGetScreen(pDev);
-    if (!screen) {
-        DEBUG_LOG(
-            "DarwinSendPointerEvents called before screen was initialized\n");
-        return;
-    }
-
-    DarwinPrepareValuators(pDev, &valuators, screen, pointer_x, pointer_y,
-                           pressure, tilt_x,
-                           tilt_y);
-    darwinEvents_lock();
-    {
-        QueueProximityEvents(pDev, ev_type, &valuators);
-        DarwinPokeEQ();
-    } darwinEvents_unlock();
-}
-
 /* Send the appropriate number of button clicks to emulate scroll wheel */
 void
 DarwinSendScrollEvents(double scroll_x, double scroll_y) {
diff --git a/hw/xquartz/darwinEvents.h b/hw/xquartz/darwinEvents.h
index 61ace6e..812a5dc 100644
--- a/hw/xquartz/darwinEvents.h
+++ b/hw/xquartz/darwinEvents.h
@@ -44,14 +44,12 @@ DarwinEQSwitchScreen(ScreenPtr pScreen, Bool fromDIX);
 void
 DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev);
 void
-DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
-                        double pointer_x, double pointer_y, double pressure,
-                        double tilt_x,
-                        double tilt_y);
+DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
+                       double pointer_x, double pointer_y, double pressure,
+                       double tilt_x, double tilt_y);
 void
-DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, double pointer_x,
-                          double pointer_y, double pressure, double tilt_x,
-                          double tilt_y);
+DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
+                        double pointer_x, double pointer_y);
 void
 DarwinSendKeyboardEvents(int ev_type, int keycode);
 void
commit 72226dc434a5d1c4ec391390fe5f2a2c34287fb3
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Apr 19 16:06:45 2012 -0700

    XQuartz: Correct calculation of the size of our file descriptor array in console_redirect
    
    Reported-by: Joe Rohde <joer at valvesoftware.com>
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit 30623d6ff7bca223f9e1a825e86bd317eef8bf16)

diff --git a/hw/xquartz/console_redirect.c b/hw/xquartz/console_redirect.c
index 7b92eca..1e0e56b 100644
--- a/hw/xquartz/console_redirect.c
+++ b/hw/xquartz/console_redirect.c
@@ -336,7 +336,7 @@ xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd)
                   {
                       /* Reallocate if we need more space */
                       if (fd >= n_redirect_fds) {
-                          size_t new_n = 1 << (ffs(fd) + 1);
+                          size_t new_n = 1 << (fls(fd) + 1);
                           asl_redirect *new_array =
                               realloc(redirect_fds, new_n *
                                       sizeof(*redirect_fds));
commit 8a48d44574375ba4fa85c5a59678998811ea4e80
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Wed Apr 18 01:01:44 2012 -0700

    XQuartz: Fix a deadlock in pre-dispatch code
    
    The fact that this has been in place so long makes me really wonder if
    anybody cares about this running in Tiger or Leopard.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit b4c4c65a35640e7274ccd4228f62110147878b72)

diff --git a/hw/xquartz/xpr/xprFrame.c b/hw/xquartz/xpr/xprFrame.c
index 4c7aac4..01f1def 100644
--- a/hw/xquartz/xpr/xprFrame.c
+++ b/hw/xquartz/xpr/xprFrame.c
@@ -212,7 +212,7 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
 #else
     pthread_rwlock_wrlock(&window_hash_rwlock);
     x_hash_table_insert(window_hash, pFrame->wid, pFrame);
-    pthread_rwlock_wrlock(&window_hash_rwlock);
+    pthread_rwlock_unlock(&window_hash_rwlock);
 #endif
 
     xprSetNativeProperty(pFrame);
commit 9ef48c9ffff6704dbe7c976d86527f22b0e1d114
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 18:21:54 2012 -0700

    Replay original touch begin event instead of generated begin event
    
    The generated event does not have axes other than X and Y and has a
    newer timestamp. In particular, the newer timestamp may be newer than
    the real touch end event, which may be stuck in the syncEvents queue. If
    a client uses the timestamps for grabbing bad things may happen.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 00cf1c40b28417d7035c2917d048553eb720023c)

diff --git a/dix/touch.c b/dix/touch.c
index 67c4be2..dd16367 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -474,10 +474,22 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
     flags = TOUCH_CLIENT_ID | TOUCH_REPLAYING;
     if (ti->emulate_pointer)
         flags |= TOUCH_POINTER_EMULATED;
-    /* send fake begin event to next owner */
+    /* Generate events based on a fake touch begin event to get DCCE events if
+     * needed */
+    /* FIXME: This needs to be cleaned up */
     nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
-    for (i = 0; i < nev; i++)
-        DeliverTouchEvents(dev, ti, tel + i, resource);
+    for (i = 0; i < nev; i++) {
+        /* Send saved touch begin event */
+        if (tel[i].any.type == ET_TouchBegin) {
+            DeviceEvent *ev = &ti->history[0];
+            ev->flags |= TOUCH_REPLAYING;
+            DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource);
+        }
+        else {/* Send DCCE event */
+            tel[i].any.time = ti->history[0].time;
+            DeliverTouchEvents(dev, ti, tel + i, resource);
+        }
+    }
 
     valuator_mask_free(&mask);
     FreeEventList(tel, GetMaximumEventsNum());
commit 73cd880fe05c941391a8604406e9ecf657a77f02
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 11:15:40 2012 -0700

    Update currentTime in dispatch loop
    
    A request, like input device grabs, may check a request timestamp
    against currentTime. It is possible for currentTime to lag a previously
    sent event timestamp. If the client makes a request based on such an
    event timestamp, the request may fail the validity check against
    currentTime unless we always update the time before processing the
    request.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 312910b4e34215aaa50fc0c6092684d5878dc32f)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index bce3a0d..9a2e22f 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -393,6 +393,9 @@ Dispatch(void)
                 }
                 /* now, finally, deal with client requests */
 
+                /* Update currentTime so request time checks, such as for input
+                 * device grabs, are calculated correctly */
+                UpdateCurrentTimeIf();
                 result = ReadRequestFromClient(client);
                 if (result <= 0) {
                     if (result < 0)
commit 96d8df5bc9d400d55830b23afe5525b222f8dfc7
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 11:40:15 2012 -0700

    Update device state including when touch record does not exist
    
    If a touch is physically active, the pointer core state should reflect
    that the first button is pressed. Currently, this only occurs when there
    are active listeners of the touch sequence. By moving the device state
    updating to the beginning of touch processing we ensure it is updated
    according to the processed physical state no matter what.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit a986f2f30cbe2a00e72ded7315c4951d7703e549)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d85f01f..37ed5c7 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1597,6 +1597,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         touchid = ev->device_event.touchid;
 
+    if (emulate_pointer)
+        UpdateDeviceState(dev, &ev->device_event);
+
     if (type == ET_TouchBegin) {
         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
                              emulate_pointer);
@@ -1996,9 +1999,6 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
         DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
     }
-
-    if (ti->emulate_pointer)
-        UpdateDeviceState(dev, &ev->device_event);
 }
 
 int
diff --git a/dix/touch.c b/dix/touch.c
index f8f26c8..67c4be2 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -364,14 +364,6 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
 {
     if (ti->emulate_pointer) {
         GrabPtr grab;
-        DeviceEvent ev;
-
-        memset(&ev, 0, sizeof(ev));
-        ev.type = ET_TouchEnd;
-        ev.detail.button = 1;
-        ev.touchid = ti->client_id;
-        ev.flags = TOUCH_POINTER_EMULATED | TOUCH_END;
-        UpdateDeviceState(dev, &ev);
 
         if ((grab = dev->deviceGrab.grab)) {
             if (dev->deviceGrab.fromPassiveGrab &&
commit a9dbdb49698a15ba9bdf4172a6e2fef6133244f3
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 12:04:58 2012 -0700

    Check other clients' core masks properly when adding touch listener
    
    The current code checks the core event mask as though it were an XI
    mask. This change fixes the checks so the proper client and event masks
    are used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit ec9c4295830c3de610e65aca17f4da4a7af3c4c5)

diff --git a/dix/touch.c b/dix/touch.c
index 572bdfb..f8f26c8 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -811,6 +811,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (mask & EVENT_CORE_MASK) {
         int coretype = GetCoreType(TouchGetPointerEventType(ev));
         Mask core_filter = event_get_filter_from_type(dev, coretype);
+        OtherClients *oclients;
 
         /* window owner */
         if (IsMaster(dev) && (win->eventMask & core_filter)) {
@@ -822,13 +823,12 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
         }
 
         /* all others */
-        nt_list_for_each_entry(iclients, (InputClients *) wOtherClients(win),
-                               next) {
-            if (!(iclients->mask[XIAllDevices] & core_filter))
+        nt_list_for_each_entry(oclients, wOtherClients(win), next) {
+            if (!(oclients->mask & core_filter))
                 continue;
 
             TouchEventHistoryAllocate(ti);
-            TouchAddListener(ti, iclients->resource, CORE,
+            TouchAddListener(ti, oclients->resource, CORE,
                              type, LISTENER_AWAITING_BEGIN, win);
             return TRUE;
         }
commit 04431dd5e60dc91b61767157914b874515a18feb
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 11:39:10 2012 -0700

    Ensure touch is ended when last listener is rejected
    
    Currently, the touch is only logically ended if the touch has physically
    ended. If the touch hasn't physically ended, the touch record is never
    ended. If there aren't any more listeners, we don't need to keep the dix
    touch record around any more.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit e175971a6f44d94aa8306dc6b9228ccb2c8a0b4d)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a1eccaa..d85f01f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1234,14 +1234,6 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
         }
     }
 
-    /* If there are no other listeners left, and the touchpoint is pending
-     * finish, then we can just kill it now. */
-    if (ti->num_listeners == 1 && ti->pending_finish) {
-        TouchEndTouch(sourcedev, ti);
-        CheckOldestTouch(sourcedev);
-        return;
-    }
-
     /* Remove the resource from the listener list, updating
      * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
     if (TouchRemoveListener(ti, resource)) {
@@ -1254,6 +1246,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * the TouchOwnership or TouchBegin event to the new owner. */
     if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
+    else if (ti->num_listeners == 0)
+        TouchEndTouch(sourcedev, ti);
 
     CheckOldestTouch(sourcedev);
 }
commit 8ce9616a2ccd3f80bf56d69cb9e3fad89996fffb
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 10:49:14 2012 -0700

    Create a new dix touch record for an emulated touch with no listeners
    
    As a special case, if a still physically active pointer emulated touch
    has no listeners and the device is explicitly grabbed for pointer
    events, create a new dix touch record for the grab only.
    
    This allows for clients to "hand off" grabs. For example, when dragging
    a window under compiz the window decorator sees the button press and
    then ungrabs the implicit grab. It then tells compiz to grab the device,
    and compiz then moves the window with the pointer motion. This is racy,
    but is allowed by the input protocol for pointer events when there are
    no other clients with a grab on the device.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit d0449851d1233543c3133d77e0ab7233319cdf5f)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 0c483ac..a1eccaa 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1610,6 +1610,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         ti = TouchFindByClientID(dev, touchid);
 
+    /* Under the following circumstances we create a new touch record for an
+     * existing touch:
+     *
+     * - The touch may be pointer emulated
+     * - An explicit grab is active on the device
+     * - The grab is a pointer grab
+     *
+     * This allows for an explicit grab to receive pointer events for an already
+     * active touch.
+     */
+    if (!ti && type != ET_TouchBegin && emulate_pointer &&
+        dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+        (dev->deviceGrab.grab->grabtype == CORE ||
+         dev->deviceGrab.grab->grabtype == XI ||
+         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
+        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                             emulate_pointer);
+        if (!ti) {
+            DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+                   "grabbed touchpoint %d\n",
+                   dev->name, type, touchid);
+            return;
+        }
+
+        TouchBuildSprite(dev, ti, ev);
+        TouchSetupListeners(dev, ti, ev);
+    }
+
     if (!ti) {
         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
                dev->name, type, touchid);
diff --git a/dix/touch.c b/dix/touch.c
index e638a89..572bdfb 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -864,6 +864,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
     if (dev->deviceGrab.grab)
         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
 
+    /* We set up an active touch listener for existing touches, but not any
+     * passive grab or regular listeners. */
+    if (ev->any.type != ET_TouchBegin)
+        return;
+
     /* First, find all grabbing clients from the root window down
      * to the deepest child window. */
     for (i = 0; i < sprite->spriteTraceGood; i++) {
commit da9cedb1e5e50acc7d3dc40398e1a460b7e3cfdc
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 13:56:08 2012 -0700

    Rename TouchEnsureSprite to TouchBuildSprite and event type checks
    
    The function will be used for building a sprite for pointer emulation
    after an explicit device grab. This commit refactors the code so that
    TouchBuildSprite will function with any event type and moves the checks
    to the caller.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 3d06bfe93d33cfe6150d8fb0058ee7bc8d80622b)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index eace62e..0c483ac 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1625,9 +1625,11 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
         CheckMotion(&ev->device_event, dev);
 
     /* Make sure we have a valid window trace for event delivery; must be
-     * called after event type mutation. */
+     * called after event type mutation. Touch end events are always processed
+     * in order to end touch records. */
     /* FIXME: check this */
-    if (!TouchEnsureSprite(dev, ti, ev))
+    if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
         return;
 
     /* TouchOwnership events are handled separately from the rest, as they
diff --git a/dix/touch.c b/dix/touch.c
index 72faad5..e638a89 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -542,22 +542,12 @@ TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
  * TouchBegin events.
  */
 Bool
-TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                  InternalEvent *ev)
+TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                 InternalEvent *ev)
 {
     TouchClassPtr t = sourcedev->touch;
     SpritePtr sprite = &ti->sprite;
 
-    /* We may not have a sprite if there are no applicable grabs or
-     * event selections, or if they've disappeared, or if all the grab
-     * owners have rejected the touch.  Don't bother delivering motion
-     * events if not, but TouchEnd events still need to be processed so
-     * we can call FinishTouchPoint and release it for later use. */
-    if (ev->any.type == ET_TouchEnd)
-        return TRUE;
-    else if (ev->any.type != ET_TouchBegin)
-        return (sprite->spriteTraceGood > 0);
-
     if (t->mode == XIDirectTouch) {
         /* Focus immediately under the touchpoint in direct touch mode.
          * XXX: Do we need to handle crossing screens here? */
diff --git a/include/input.h b/include/input.h
index 9a6fdfe..991d648 100644
--- a/include/input.h
+++ b/include/input.h
@@ -563,8 +563,8 @@ extern void TouchAddListener(TouchPointInfoPtr ti, XID resource,
 extern Bool TouchRemoveListener(TouchPointInfoPtr ti, XID resource);
 extern void TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti,
                                 InternalEvent *ev);
-extern Bool TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                              InternalEvent *ev);
+extern Bool TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                             InternalEvent *ev);
 extern Bool TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite);
 extern int TouchConvertToPointerEvent(const InternalEvent *ev,
                                       InternalEvent *motion,
commit 7be71cb0894052943f94638ffa405cf8dd61bc4a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 08:39:38 2012 -0700

    When activating an explicit grab, update owning listener
    
    Pointer passive grabs may be changed by the grabbing client. This allows
    for a selecting client to change an implicit grab to an active grab,
    which is the mechanism used for pop-up windows like application menus.
    
    We need to do the same thing with touches. If the grabbing client is the
    owner of a touch sequence, change the listener record to reflect the new
    grab. If the grabbing client is not the owner, nothing changes for the
    touch.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 2efbed23c29020f9994ab7c3155ce7386950dc7a)

diff --git a/dix/events.c b/dix/events.c
index 72829c3..86336fe 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1408,6 +1408,38 @@ ReattachToOldMaster(DeviceIntPtr dev)
 }
 
 /**
+ * Update touch records when an explicit grab is activated. Any touches owned by
+ * the grabbing client are updated so the listener state reflects the new grab.
+ */
+static void
+UpdateTouchesForGrab(DeviceIntPtr mouse)
+{
+    int i;
+
+    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
+        return;
+
+    for (i = 0; i < mouse->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+        GrabPtr grab = mouse->deviceGrab.grab;
+
+        if (ti->active &&
+            CLIENT_BITS(ti->listeners[0].listener) == grab->resource) {
+            ti->listeners[0].listener = grab->resource;
+            ti->listeners[0].level = grab->grabtype;
+            ti->listeners[0].state = LISTENER_IS_OWNER;
+            ti->listeners[0].window = grab->window;
+
+            if (grab->grabtype == CORE || grab->grabtype == XI ||
+                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
+                ti->listeners[0].type = LISTENER_POINTER_GRAB;
+            else
+                ti->listeners[0].type = LISTENER_GRAB;
+        }
+    }
+}
+
+/**
  * Activate a pointer grab on the given device. A pointer grab will cause all
  * core pointer events of this device to be delivered to the grabbing client only.
  * No other device will send core events to the grab client while the grab is
@@ -1456,6 +1488,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
     grabinfo->fromPassiveGrab = isPassive;
     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
+    UpdateTouchesForGrab(mouse);
     CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
                       (Bool) grab->keyboardMode);
 }
commit 8ccc6ad63733c7de6bd64b1b11169836d941455b
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 15:53:51 2012 -0700

    Don't deactivate implicit pointer grab on fake touch end event
    
    Fake touch end events are generated by touch acceptance and rejection.
    These should not cause implicit pointer grabs to be deactivated.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit ef64b5ee97099618cf2e2cbbd3e471095695ae24)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 50b05fa..eace62e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1482,6 +1482,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
 
             if (ev->any.type == ET_TouchEnd &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
commit ea3afab228f44d9a41905daeda4c0f9236dbf8e6
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 15:31:47 2012 -0700

    End a pointer emulated touch event only on a "real" end event
    
    Fake end events are generated by touch acceptance or rejection. These
    should not end the touch point.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit fc518cd9f59060cc19bb90361767c0f47f0e25eb)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e76796a..50b05fa 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1856,7 +1856,8 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         if (ti->num_listeners > 1) {
             ev->any.type = ET_TouchUpdate;
             ev->device_event.flags |= TOUCH_PENDING_END;
-            ti->pending_finish = TRUE;
+            if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
+                ti->pending_finish = TRUE;
         }
 
         goto out;
commit fac2c4a5dc1d19bb347729eee8b1bbfc981b853a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 14:19:59 2012 -0700

    On touch accept, only process end event for owner if it has seen the end
    
    We still need to generate the touch ownership event to process the
    ending of the touch event in the case where the owner has the end
    already.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 80d7d1ec6a9d61aa96e7d019dc1bee29d90cea34)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7ef75ec..e76796a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1273,9 +1273,18 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (ev->reason == XIRejectTouch)
         TouchRejected(dev, ti, ev->resource, ev);
     else if (ev->reason == XIAcceptTouch) {
+        int i;
+
+        /* Go through the motions of ending the touch if the listener has
+         * already seen the end. This ensures that the touch record is ended in
+         * the server. */
+        if (ti->listeners[0].state == LISTENER_HAS_END)
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+
         /* The touch owner has accepted the touch.  Send TouchEnd events to
          * everyone else, and truncate the list of listeners. */
-        EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
+        for (i = 1; i < ti->num_listeners; i++)
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
commit aaf0063bde791659009eb9001485ac8c15745ae8
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 11:14:51 2012 -0700

    Fix copy/paste error from before git history in UpdateCurrentTimeIf()
    
    See UpdateCurrentTime() for reference. I don't know what bug this might
    trigger, but it wouldn't hurt to fix this.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 8dfd98245d2c44a1eb4c8b7c275e6cfc10fe40f1)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 104dcc9..bce3a0d 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -214,7 +214,7 @@ UpdateCurrentTimeIf(void)
     systime.milliseconds = GetTimeInMillis();
     if (systime.milliseconds < currentTime.milliseconds)
         systime.months++;
-    if (*checkForInput[0] == *checkForInput[1])
+    if (CompareTimeStamps(systime, currentTime) == LATER)
         currentTime = systime;
 }
 
commit acb74b9b36b55d4f80d85fd6a2790b7c72e197a5
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:17:25 2012 -0700

    When deactivating an explicit pointer grab, reject all grabs on touches
    
    Explicit pointer grabs are placed at the head of the touch listener
    array for pointer emulated touches. If the grab is deactivated, we must
    remove it from all touches for the device.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 6ca30cb33e829b4edd01822367e44ffe6f0951b0)

diff --git a/dix/events.c b/dix/events.c
index 30e3356..72829c3 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1472,6 +1472,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     DeviceIntPtr dev;
     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
                         mouse->deviceGrab.implicitGrab);
+    XID grab_resource = grab->resource;
+    int i;
 
     TouchRemovePointerGrab(mouse);
 
@@ -1496,6 +1498,15 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
         ReattachToOldMaster(mouse);
 
     ComputeFreezes();
+
+    /* If an explicit grab was deactivated, we must remove it from the head of
+     * all the touches' listener lists. */
+    for (i = 0; mouse->touch && i < mouse->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+
+        if (ti->active && TouchResourceIsOwner(ti, grab_resource))
+            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
+    }
 }
 
 /**
commit 0dea2b1c935ed4c80621e7f5d6fa5193ae09187a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:13:17 2012 -0700

    Accept touch sequence for pointer listener after second event delivery
    
    This is a bit of unimplemented code for touchscreen pointer emulation. A
    pointer grabbing client currently never accepts the touch sequence. The
    sequence must be accepted once any touch-derived event is irrevocably
    delivered to a client.
    
    The first pointer event, derived from a touch begin event, may be caught
    in a sync grab and then replayed. This is essentially a revocable
    delivery of an event. Thus, we must wait till a non-begin event is
    delivered.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit cacdb9a74065ccba7d50a82e14abdf04b36c5309)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 57a75cc..7ef75ec 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1466,6 +1466,12 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             if (!deliveries)
                 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
 
+            /* We must accept the touch sequence once a pointer listener has
+             * received one event past ButtonPress. */
+            if (deliveries && ev->any.type != ET_TouchBegin &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID))
+                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+
             if (ev->any.type == ET_TouchEnd &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
commit 2bb2eeb05c973ba410773e380e49c2503a2fe9e6
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:12:08 2012 -0700

    Split out helper function TouchListenerAcceptReject()
    
    This will be used for accepting and rejecting touches in the future.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 447fe7a1a72513aa68145962c47894242c589cc9)

diff --git a/dix/events.c b/dix/events.c
index 8b7d460..30e3356 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1272,18 +1272,11 @@ ComputeFreezes(void)
                        event->root_x, event->root_y);
         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
             if (IsTouchEvent((InternalEvent *) event)) {
-                InternalEvent *events = InitEventList(GetMaximumEventsNum());
-                int i, nev;
                 TouchPointInfoPtr ti =
                     TouchFindByClientID(replayDev, event->touchid);
                 BUG_WARN(!ti);
-                nev =
-                    GetTouchOwnershipEvents(events, replayDev, ti,
-                                            XIRejectTouch,
-                                            ti->listeners[0].listener, 0);
-                for (i = 0; i < nev; i++)
-                    mieqProcessDeviceEvent(replayDev, events + i, NULL);
-                ProcessInputEvents();
+
+                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
             }
             else if (replayDev->focus &&
                      !IsPointerEvent((InternalEvent *) event))
diff --git a/dix/touch.c b/dix/touch.c
index 0829b65..72faad5 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -960,15 +960,48 @@ TouchListenerGone(XID resource)
 }
 
 int
+TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
+                          int mode)
+{
+    InternalEvent *events;
+    int nev;
+    int i;
+
+    if (listener > 0) {
+        if (mode == XIRejectTouch)
+            TouchRejected(dev, ti, ti->listeners[listener].listener, NULL);
+        else
+            ti->listeners[listener].state = LISTENER_EARLY_ACCEPT;
+
+        return Success;
+    }
+
+    events = InitEventList(GetMaximumEventsNum());
+    if (!events) {
+        BUG_WARN_MSG(TRUE, "Failed to allocate touch ownership events\n");
+        return BadAlloc;
+    }
+
+    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
+                                  ti->listeners[0].listener, 0);
+    BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n");
+
+    for (i = 0; i < nev; i++)
+        mieqProcessDeviceEvent(dev, events + i, NULL);
+
+    ProcessInputEvents();
+
+    FreeEventList(events, GetMaximumEventsNum());
+
+    return nev ? Success : BadMatch;
+}
+
+int
 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                   uint32_t touchid, Window grab_window, XID *error)
 {
     TouchPointInfoPtr ti;
-    int nev, i;
-    InternalEvent *events = InitEventList(GetMaximumEventsNum());
-
-    if (!events)
-        return BadAlloc;
+    int i;
 
     if (!dev->touch) {
         *error = dev->id;
@@ -989,24 +1022,5 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
     if (i == ti->num_listeners)
         return BadAccess;
 
-    if (i > 0) {
-        if (mode == XIRejectTouch)
-            TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
-        else
-            ti->listeners[i].state = LISTENER_EARLY_ACCEPT;
-
-        return Success;
-    }
-
-    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-                                  ti->listeners[0].listener, 0);
-    if (nev == 0)
-        return BadAlloc;
-    for (i = 0; i < nev; i++)
-        mieqProcessDeviceEvent(dev, events + i, NULL);
-
-    ProcessInputEvents();
-
-    FreeEventList(events, GetMaximumEventsNum());
-    return Success;
+    return TouchListenerAcceptReject(dev, ti, i, mode);
 }
diff --git a/include/input.h b/include/input.h
index d891fe5..9a6fdfe 100644
--- a/include/input.h
+++ b/include/input.h
@@ -572,6 +572,8 @@ extern int TouchConvertToPointerEvent(const InternalEvent *ev,
 extern int TouchGetPointerEventType(const InternalEvent *ev);
 extern void TouchRemovePointerGrab(DeviceIntPtr dev);
 extern void TouchListenerGone(XID resource);
+extern int TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                                     int listener, int mode);
 extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                              uint32_t touchid, Window grab_window, XID *error);
 
commit a37539e794e2bff87ea68e0023cd0cce2bb8de60
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 4 12:59:55 2012 -0700

    Only set XI2 mask if pointer emulation is for XI2 client
    
    The current code returns a reference to memory that may not actually be
    an XI2 mask. Instead, only return a value when an XI2 client has
    selected for events.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 93c33403642a3de3c9d141ad7940a7b880846aad)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index abd68fc..57a75cc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1327,6 +1327,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
 {
     int rc;
     InputClients *iclients = NULL;
+    *mask = NULL;
 
     if (listener->type == LISTENER_GRAB ||
         listener->type == LISTENER_POINTER_GRAB) {
@@ -1378,6 +1379,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             if (!iclients)
                 return FALSE;
 
+            *mask = iclients->xi2mask;
             *client = rClient(iclients);
         }
         else if (listener->level == XI) {
@@ -1409,7 +1411,6 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             *client = oclients ? rClient(oclients) : wClient(*win);
         }
 
-        *mask = iclients ? iclients->xi2mask : NULL;
         *grab = NULL;
     }
 
commit d21d69c2d6b1eb292e9d3f6682339e93603913c9
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 4 12:57:40 2012 -0700

    Check core event mask properly for pointer emulated touch events
    
    The current code checks the core event mask as though it were an XI2
    mask. This change fixes the checks so the proper client and event masks
    are used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 4c1dfd21937efc6a85fb204a73dd7d7151d54daa)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b2dfc13..abd68fc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1377,6 +1377,8 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *client = rClient(iclients);
         }
         else if (listener->level == XI) {
             int xi_type = GetXIType(TouchGetPointerEventType(ev));
@@ -1389,20 +1391,24 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *client = rClient(iclients);
         }
         else {
             int coretype = GetCoreType(TouchGetPointerEventType(ev));
             Mask core_filter = event_get_filter_from_type(dev, coretype);
+            OtherClients *oclients;
 
             /* all others */
-            nt_list_for_each_entry(iclients,
-                                   (InputClients *) wOtherClients(*win), next)
-                if (iclients->mask[XIAllDevices] & core_filter)
-                break;
-            /* if owner selected, iclients is NULL */
+            nt_list_for_each_entry(oclients,
+                                   (OtherClients *) wOtherClients(*win), next)
+                if (oclients->mask & core_filter)
+                    break;
+
+            /* if owner selected, oclients is NULL */
+            *client = oclients ? rClient(oclients) : wClient(*win);
         }
 
-        *client = iclients ? rClient(iclients) : wClient(*win);
         *mask = iclients ? iclients->xi2mask : NULL;
         *grab = NULL;
     }
commit 3d3ed6023077c0324fcbf446f387edb1db677b84
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 3 17:31:01 2012 -0700

    Use touch state when querying pointer through core protocol
    
    QueryPointer is part of the core protocol. As such, it knows nothing
    about touch devices. Touches are converted to button 1 press, pointer
    motion, and button 1 release for core clients, so we should ensure the
    pointer state mask has button 1 set when XQueryPointer is used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 12188c8a8a537b38b1ca4cf8c0de5447e19c886a)

diff --git a/dix/events.c b/dix/events.c
index f7b9456..8b7d460 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5097,8 +5097,7 @@ ProcQueryPointer(ClientPtr client)
     memset(&rep, 0, sizeof(xQueryPointerReply));
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
-    rep.mask = mouse->button ? (mouse->button->state) : 0;
-    rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
+    rep.mask = event_get_corestate(mouse, keyboard);
     rep.length = 0;
     rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
     rep.rootX = pSprite->hot.x;
commit 50b71dcfb8b2ec14a55a119f042509d69847d776
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:42 2012 -0700

    Ensure sequential touches are pointer emulated sequentially
    
    Issue:
    * Two sequential touches (i.e. down, up, down, up)
    * Both are grabbed by a touch grab
    * Both have a second listener in the form of a pointer grab or selection
    * The second and first touches are rejected in that order
    
    The first touch must be pointer emulated before the second touch, so the
    second touch must be paused until the first touch is rejected or
    accepted and all events are delivered to pointer clients.
    
    This change ensures all pointer emulated events are emitted
    sequentially. It necessarily imposes a delay on further touch events
    when pointer grabs and selections are used, but there is no way around
    it.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 32ece7c09bf0ebc3d99b4078aacebbd44314776a)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index fc43f02..b2dfc13 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1111,6 +1111,48 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
 }
 
 /**
+ * Find the oldest touch that still has a pointer emulation client.
+ *
+ * Pointer emulation can only be performed for the oldest touch. Otherwise, the
+ * order of events seen by the client will be wrong. This function helps us find
+ * the next touch to be emulated.
+ *
+ * @param dev The device to find touches for.
+ */
+static TouchPointInfoPtr
+FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = NULL;
+    int i;
+
+    for (i = 0; i < dev->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = dev->touch->touches + i;
+        int j;
+
+        if (!ti->active || !ti->emulate_pointer)
+            continue;
+
+        for (j = 0; j < ti->num_listeners; j++) {
+            if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
+                ti->listeners[j].type == LISTENER_POINTER_REGULAR)
+                break;
+        }
+        if (j == ti->num_listeners)
+            continue;
+
+        if (!oldest) {
+            oldest = ti;
+            continue;
+        }
+
+        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
+            oldest = ti;
+    }
+
+    return oldest;
+}
+
+/**
  * If the current owner has rejected the event, deliver the
  * TouchOwnership/TouchBegin to the next item in the sprite stack.
  */
@@ -1123,8 +1165,16 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
         DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
                            ti->listeners[0].listener);
-    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
+    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
+        /* We can't punt to a pointer listener unless all older pointer
+         * emulated touches have been seen already. */
+        if ((ti->listeners[0].type == LISTENER_POINTER_GRAB ||
+             ti->listeners[0].type == LISTENER_POINTER_REGULAR) &&
+            ti != FindOldestPointerEmulatedTouch(dev))
+            return;
+
         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
+    }
 
     /* If we've just removed the last grab and the touch has physically
      * ended, send a TouchEnd event too and finalise the touch. */
@@ -1139,6 +1189,25 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
 }
 
 /**
+ * Check the oldest touch to see if it needs to be replayed to its pointer
+ * owner.
+ *
+ * Touch event propagation is paused if it hits a pointer listener while an
+ * older touch with a pointer listener is waiting on accept or reject. This
+ * function will restart propagation of a paused touch if needed.
+ *
+ * @param dev The device to check touches for.
+ */
+static void
+CheckOldestTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
+
+    if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
+        TouchPuntToNextOwner(dev, oldest, NULL);
+}
+
+/**
  * Process a touch rejection.
  *
  * @param sourcedev The source device of the touch sequence.
@@ -1169,6 +1238,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * finish, then we can just kill it now. */
     if (ti->num_listeners == 1 && ti->pending_finish) {
         TouchEndTouch(sourcedev, ti);
+        CheckOldestTouch(sourcedev);
         return;
     }
 
@@ -1184,6 +1254,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * the TouchOwnership or TouchBegin event to the new owner. */
     if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
+
+    CheckOldestTouch(sourcedev);
 }
 
 /**
@@ -1391,6 +1463,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
+                CheckOldestTouch(dev);
                 return Success;
             }
         }
commit fb01dfb55a6a718affa9354c384823e462ee784a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:41 2012 -0700

    Update event type when delivering end event to a pointer listener
    
    Just like when we deliver to a touch listener, we must convert a touch
    end event to an update event for further clients. This also ensures that
    the touch record is not deleted at the end of ProcessTouchEvent().
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 163b0f375d73c05873fb341652de3ed347337828)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 80ddfcc..fc43f02 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1757,6 +1757,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         listener->type == LISTENER_POINTER_GRAB) {
         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                        grab, xi2mask);
+
+        if (ti->num_listeners > 1) {
+            ev->any.type = ET_TouchUpdate;
+            ev->device_event.flags |= TOUCH_PENDING_END;
+            ti->pending_finish = TRUE;
+        }
+
         goto out;
     }
 
commit b56c1f95bb2d22996651e0a5ca6b6b0e71710a7b
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:40 2012 -0700

    Don't update listener after deactivating implicit pointer grab
    
    After the pointer grab is deactivated, the touch listener record is
    updated at the end of DeliverTouchEmulatedEvent. However, the touch
    record is ended when the grab is deactivated, so the update to the
    listener record is in an array of memory that has been freed.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 210cd12c47d063f97915ff23292b61d09abfd73a)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f681a8b..80ddfcc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1389,8 +1389,10 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
             if (ev->any.type == ET_TouchEnd &&
                 !dev->button->buttonsDown &&
-                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab))
+                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
+                return Success;
+            }
         }
     }
     else {
commit 8ca5a94f454d04ed5f1d0b18272a838b8e7f1e7a
Author: Andreas Wettstein <wettstein509 at solnet.ch>
Date:   Sat Feb 25 20:48:17 2012 +0100

    XKB: Redirect actions defunct with Gtk3 (XInput?)
    
    When redirect actions are used with Gtk3, Gtk3 complained about
    events not holding a GdkDevice.  This was caused by device IDs
    not being set for redirect actions.
    
    More seriously, Gtk3 did not receive state changes redirect
    actions might specify.  This was because event_set_state in
    dix/inpututils.c accesses the prev_state field, but the changes
    for the redirect action were only put into the state field.
    
    Signed-off-by: Andreas Wettstein <wettstein509 at solnet.ch>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 9e017cf0cf1f0c9d0d9c2cfeb82ea5dc0eb5905e)

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index c473df1..5ec1ed5 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -799,7 +799,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 {
     DeviceEvent ev;
     int x, y;
-    XkbStateRec old;
+    XkbStateRec old, old_prev;
     unsigned mods, mask;
     xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
     ProcessInputProc backupproc;
@@ -807,6 +807,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
     /* never actually used uninitialised, but gcc isn't smart enough
      * to work that out. */
     memset(&old, 0, sizeof(old));
+    memset(&old_prev, 0, sizeof(old_prev));
     memset(&ev, 0, sizeof(ev));
 
     if ((filter->keycode != 0) && (filter->keycode != keycode))
@@ -818,6 +819,11 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
     ev.time = GetTimeInMillis();
     ev.root_x = x;
     ev.root_y = y;
+    /* redirect actions do not work across devices, therefore the following is
+     * correct: */
+    ev.deviceid = xkbi->device->id;
+    /* filter->priv must be set up by the caller for the initial press. */
+    ev.sourceid = filter->priv;
 
     if (filter->keycode == 0) { /* initial press */
         if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
@@ -827,7 +833,6 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         filter->keycode = keycode;
         filter->active = 1;
         filter->filterOthers = 0;
-        filter->priv = 0;
         filter->filter = _XkbFilterRedirectKey;
         filter->upAction = *pAction;
 
@@ -845,6 +850,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 
         if (mask || mods) {
             old = xkbi->state;
+            old_prev = xkbi->prev_state;
             xkbi->state.base_mods &= ~mask;
             xkbi->state.base_mods |= (mods & mask);
             xkbi->state.latched_mods &= ~mask;
@@ -852,6 +858,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
             xkbi->state.locked_mods &= ~mask;
             xkbi->state.locked_mods |= (mods & mask);
             XkbComputeDerivedState(xkbi);
+            xkbi->prev_state = xkbi->state;
         }
 
         UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
@@ -860,8 +867,10 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
                                      xkbUnwrapProc);
 
-        if (mask || mods)
+        if (mask || mods) {
             xkbi->state = old;
+            xkbi->prev_state = old_prev;
+        }
     }
     else if (filter->keycode == keycode) {
 
@@ -879,6 +888,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 
         if (mask || mods) {
             old = xkbi->state;
+            old_prev = xkbi->prev_state;
             xkbi->state.base_mods &= ~mask;
             xkbi->state.base_mods |= (mods & mask);
             xkbi->state.latched_mods &= ~mask;
@@ -886,6 +896,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
             xkbi->state.locked_mods &= ~mask;
             xkbi->state.locked_mods |= (mods & mask);
             XkbComputeDerivedState(xkbi);
+            xkbi->prev_state = xkbi->state;
         }
 
         UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
@@ -894,8 +905,10 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
                                      xkbUnwrapProc);
 
-        if (mask || mods)
+        if (mask || mods) {
             xkbi->state = old;
+            xkbi->prev_state = old_prev;
+        }
 
         filter->keycode = 0;
         filter->active = 0;
@@ -1165,6 +1178,11 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
                 break;
             case XkbSA_RedirectKey:
                 filter = _XkbNextFreeFilter(xkbi);
+                /* redirect actions must create a new DeviceEvent.  The
+                 * source device id for this event cannot be obtained from
+                 * xkbi, so we pass it here explicitly. The field deviceid
+                 * equals to xkbi->device->id. */
+                filter->priv = event->sourceid;
                 sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, &act);
                 break;
             case XkbSA_DeviceBtn:
commit d75da4eccbabc3f83937cbd4eb2d6be2fd27a4b9
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Feb 20 12:09:33 2012 +1000

    dix: IsFloating() on master devices is always false
    
    There are a few subtle bugs during startup where IsFloating() returns true
    if the device is a master device that is not yet paired with its keyboard
    device.
    
    Force IsFloating() to always return FALSE for master devices, that was the
    intent after all and any code that relies on the other behaviour should be
    fixed instead.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Tested-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    (cherry picked from commit 5497ce3da442d27c2dc7796bfef6ccd670bbadc4)

diff --git a/dix/events.c b/dix/events.c
index 0e4ba86..f7b9456 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -341,7 +341,7 @@ IsMaster(DeviceIntPtr dev)
 Bool
 IsFloating(DeviceIntPtr dev)
 {
-    return GetMaster(dev, MASTER_KEYBOARD) == NULL;
+    return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
 }
 
 /**


More information about the Xquartz-changes mailing list