[PATCH 3/5] Add support for XI2.3: Pointer barrier notify events

Jasper St. Pierre jstpierre at mecheye.net
Tue Nov 20 11:50:43 PST 2012


From: "Jasper St. Pierre" <jstpierre at mecheye.net>

This adds support for clients that would like to get a notification
every time a barrier is released, along with a way to temporarily
release a barrier after it has been hit.

This adds two new events to XI: BarrierHitNotify and
BarrierPointerReleasedNotify.

Based on work by Chris Halse Rogers <chris.halse.rogers at canonical.com>

Signed-off-by: Jasper St. Pierre <jstpierre at mecheye.net>
---
 Xi/exevents.c                  | 43 ++++++++++++++++++
 Xi/extinit.c                   | 32 ++++++++++++++
 Xi/xibarriers.c                | 98 ++++++++++++++++++++++++++++++++++--------
 Xi/xibarriers.h                |  1 +
 dix/getevents.c                |  4 +-
 hw/xfree86/modes/xf86RandR12.c |  4 +-
 include/events.h               |  1 +
 include/eventstr.h             | 22 ++++++++++
 include/inputstr.h             |  2 +-
 include/protocol-versions.h    |  2 +-
 include/scrnintstr.h           |  2 +-
 mi/mieq.c                      |  3 ++
 mi/mipointer.c                 | 12 ++++--
 mi/mipointer.h                 |  4 +-
 randr/randrstr.h               |  2 +-
 randr/rrcrtc.c                 |  4 +-
 16 files changed, 204 insertions(+), 32 deletions(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4248b9a..98a2cee 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1649,6 +1649,46 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
         UpdateDeviceState(dev, &ev->device_event);
 }
 
+#define INT_TO_FP3232(x) ((FP3232) { (x), 0 })
+
+static void
+ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
+{
+    Mask filter;
+    WindowPtr pWin;
+    BarrierEvent *be = &e->barrier_event;
+    xXIBarrierNotifyEvent ev = {
+        .type = GenericEvent,
+        .extension = IReqCode,
+        .sequenceNumber = 0,
+        .length = 9,
+        .evtype = be->event_type,
+        .window = be->window,
+        .deviceid = dev->id,
+        .time = be->time,
+        .x = be->x,
+        .y = be->y,
+        .dx = INT_TO_FP3232(be->dx),
+        .dy = INT_TO_FP3232(be->dy),
+        .raw_dx = INT_TO_FP3232(be->raw_dx),
+        .raw_dy = INT_TO_FP3232(be->raw_dy),
+        .dt = be->dt,
+        .event_id = be->event_id,
+        .barrier = be->barrierid,
+    };
+
+    if (!IsMaster(dev))
+        return;
+
+    if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
+        return;
+
+    filter = GetEventFilter(dev, (xEvent *) &ev);
+
+    DeliverEventsToWindow(dev, pWin, (xEvent *) &ev, 1,
+                          filter, NullGrab);
+}
+
 /**
  * Process DeviceEvents and DeviceChangedEvents.
  */
@@ -1798,6 +1838,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
     case ET_TouchEnd:
         ProcessTouchEvent(ev, device);
         break;
+    case ET_BarrierNotify:
+        ProcessBarrierEvent(ev, device);
+        break;
     default:
         ProcessDeviceEvent(ev, device);
         break;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 1074b23..6571943 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -840,6 +840,33 @@ STouchOwnershipEvent(xXITouchOwnershipEvent * from, xXITouchOwnershipEvent * to)
     swapl(&to->child);
 }
 
+static void
+SBarrierNotifyEvent(xXIBarrierNotifyEvent * from,
+                    xXIBarrierNotifyEvent * to) {
+    to->type = from->type;
+
+    cpswaps(from->x, to->x);
+    cpswaps(from->y, to->y);
+    cpswaps(from->dt, to->dt);
+    cpswapl(from->length, to->length);
+    cpswapl(from->time, to->time);
+
+    cpswaps(from->event_id, to->event_id);
+    cpswapl(from->barrier, to->barrier);
+    cpswapl(from->window, to->window);
+
+#define SWAP_FP3232(x, y)                       \
+    do {                                        \
+        cpswapl((x).integral, (y).integral);    \
+        cpswapl((x).frac, (y).frac);            \
+    } while(0)
+
+    SWAP_FP3232(from->dx, to->dx);
+    SWAP_FP3232(from->dy, to->dy);
+    SWAP_FP3232(from->raw_dx, to->raw_dx);
+    SWAP_FP3232(from->raw_dy, to->raw_dy);
+}
+
 /** Event swapping function for XI2 events. */
 void
 XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
@@ -886,6 +913,11 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
     case XI_RawTouchEnd:
         SRawEvent((xXIRawEvent *) from, (xXIRawEvent *) to);
         break;
+    case XI_BarrierHitNotify:
+    case XI_BarrierPointerReleasedNotify:
+        SBarrierNotifyEvent((xXIBarrierNotifyEvent *) from,
+                            (xXIBarrierNotifyEvent *) to);
+        break;
     default:
         ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
         break;
diff --git a/Xi/xibarriers.c b/Xi/xibarriers.c
index a97db56..9b5f657 100644
--- a/Xi/xibarriers.c
+++ b/Xi/xibarriers.c
@@ -56,6 +56,8 @@
 #include "xace.h"
 #include "list.h"
 #include "exglobals.h"
+#include "eventstr.h"
+#include "mi.h"
 
 RESTYPE PointerBarrierType;
 
@@ -67,10 +69,16 @@ typedef struct PointerBarrierClient *PointerBarrierClientPtr;
 
 struct PointerBarrierClient {
     ScreenPtr screen;
+    WindowPtr window;
     struct PointerBarrier barrier;
     struct xorg_list entry;
     int num_devices;
     int *device_ids; /* num_devices */
+    Time last_timestamp;
+    int barrier_event_id;
+    int release_event_id;
+    Bool hit;
+    Bool last_hit;
 };
 
 typedef struct _BarrierScreen {
@@ -241,7 +249,7 @@ barrier_blocks_device(struct PointerBarrierClient *client,
 }
 
 /**
- * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2.
+ * Find the nearest barrier client that is blocking movement from x1/y1 to x2/y2.
  *
  * @param dir Only barriers blocking movement in direction dir are checked
  * @param x1 X start coordinate of movement vector
@@ -250,13 +258,12 @@ barrier_blocks_device(struct PointerBarrierClient *client,
  * @param y2 Y end coordinate of movement vector
  * @return The barrier nearest to the movement origin that blocks this movement.
  */
-static struct PointerBarrier *
+static struct PointerBarrierClient *
 barrier_find_nearest(BarrierScreenPtr cs, DeviceIntPtr dev,
                      int dir,
                      int x1, int y1, int x2, int y2)
 {
-    struct PointerBarrierClient *c;
-    struct PointerBarrier *nearest = NULL;
+    struct PointerBarrierClient *c, *nearest = NULL;
     double min_distance = INT_MAX;      /* can't get higher than that in X anyway */
 
     xorg_list_for_each_entry(c, &cs->barriers, entry) {
@@ -272,7 +279,7 @@ barrier_find_nearest(BarrierScreenPtr cs, DeviceIntPtr dev,
         if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) {
             if (min_distance > distance) {
                 min_distance = distance;
-                nearest = b;
+                nearest = c;
             }
         }
     }
@@ -308,16 +315,26 @@ barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
 
 static void
 BarrierConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
-                             int *x, int *y)
+                             int *x, int *y, int unclamped_x, int unclamped_y)
 {
     BarrierScreenPtr cs = GetBarrierScreen(screen);
 
     if (!xorg_list_is_empty(&cs->barriers) && !IsFloating(dev) &&
         mode == Relative) {
         int ox, oy;
+        int dx, dy;
         int dir;
-        int i;
         struct PointerBarrier *nearest = NULL;
+        PointerBarrierClientPtr c;
+        Time ms = GetTimeInMillis();
+        BarrierEvent ev = {
+            .header = ET_Internal,
+            .type = ET_BarrierNotify,
+            .length = sizeof (BarrierEvent),
+            .time = ms,
+            .deviceid = dev->id,
+            .sourceid = dev->id,
+        };
 
         /* where are we coming from */
         miPointerGetPosition(dev, &ox, &oy);
@@ -330,29 +347,68 @@ BarrierConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
          * destination, again finding the nearest barrier and clamping.
          */
         dir = barrier_get_direction(ox, oy, *x, *y);
+        dx = unclamped_x - ox;
+        dy = unclamped_y - oy;
 
 #define MAX_BARRIERS 2
         for (i = 0; i < MAX_BARRIERS; i++) {
-            nearest = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y);
-            if (!nearest)
+            c = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y);
+            if (!c)
                 break;
 
-            barrier_clamp_to_barrier(nearest, dir, x, y);
+            nearest = &c->barrier;
 
-            if (barrier_is_vertical(nearest)) {
-                dir &= ~(BarrierNegativeX | BarrierPositiveX);
-                ox = *x;
+            if (!c->last_hit) {
+                /* This is the start of a new barrier event */
+                c->barrier_event_id++;
             }
-            else if (barrier_is_horizontal(nearest)) {
-                dir &= ~(BarrierNegativeY | BarrierPositiveY);
-                oy = *y;
+
+            if (c->barrier_event_id == c->release_event_id) {
+                ev.event_type = XI_BarrierPointerReleasedNotify;
+            } else {
+                ev.event_type = XI_BarrierHitNotify;
+
+                barrier_clamp_to_barrier(nearest, dir, x, y);
+                c->hit = TRUE;
+
+                if (barrier_is_vertical(nearest)) {
+                    dir &= ~(BarrierNegativeX | BarrierPositiveX);
+                    ox = *x;
+                }
+                else if (barrier_is_horizontal(nearest)) {
+                    dir &= ~(BarrierNegativeY | BarrierPositiveY);
+                    oy = *y;
+                }
             }
+
+            ev.event_id = c->barrier_event_id;
+            ev.barrierid = nearest->id;
+
+            ev.x = *x;
+            ev.y = *y;
+            ev.dx = dx;
+            ev.dy = dy;
+
+            /* FIXME: add proper raw dx/dy */
+            ev.raw_dx = dx;
+            ev.raw_dy = dy;
+
+            ev.dt = ms - c->last_timestamp;
+            ev.window = c->window->drawable.id;
+            c->last_timestamp = ms;
+
+            mieqEnqueue(dev, (InternalEvent *) &ev);
+        }
+
+        xorg_list_for_each_entry(c, &cs->barriers, entry) {
+            c->last_hit = c->hit;
+            c->hit = FALSE;
         }
     }
 
     if (cs->ConstrainCursorHarder) {
         screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
-        screen->ConstrainCursorHarder(dev, screen, mode, x, y);
+        screen->ConstrainCursorHarder(dev, screen, mode, x, y, unclamped_x, unclamped_y);
         screen->ConstrainCursorHarder = BarrierConstrainCursorHarder;
     }
 }
@@ -378,7 +434,7 @@ CreatePointerBarrierClient(ClientPtr client,
         return BadAlloc;
     }
 
-    err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+    err = dixLookupWindow(&pWin, stuff->window, client, DixSendAccess);
     if (err != Success) {
         client->errorValue = stuff->window;
         goto error;
@@ -388,6 +444,7 @@ CreatePointerBarrierClient(ClientPtr client,
     cs = GetBarrierScreen(screen);
 
     ret->screen = screen;
+    ret->window = pWin;
     ret->num_devices = stuff->num_devices;
     if (ret->num_devices > 0)
         ret->device_ids = (int*)&ret[1];
@@ -414,6 +471,11 @@ CreatePointerBarrierClient(ClientPtr client,
         ret->device_ids[i] = device_id;
     }
 
+    ret->barrier.id = stuff->barrier;
+    ret->barrier_event_id = 0;
+    ret->release_event_id = 0;
+    ret->hit = FALSE;
+    ret->last_hit = FALSE;
     ret->barrier.x1 = min(stuff->x1, stuff->x2);
     ret->barrier.x2 = max(stuff->x1, stuff->x2);
     ret->barrier.y1 = min(stuff->y1, stuff->y2);
diff --git a/Xi/xibarriers.h b/Xi/xibarriers.h
index 8f2993f..91a0756 100644
--- a/Xi/xibarriers.h
+++ b/Xi/xibarriers.h
@@ -11,6 +11,7 @@
 extern _X_EXPORT RESTYPE PointerBarrierType;
 
 struct PointerBarrier {
+    XID    id;
     CARD16 x1, x2, y1, y2;
     CARD32 directions;
 };
diff --git a/dix/getevents.c b/dix/getevents.c
index 2a686e8..6f17534 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -933,7 +933,9 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
     /* miPointerSetPosition takes care of crossing screens for us, as well as
      * clipping to the current screen. Coordinates returned are in desktop
      * coord system */
-    scr = miPointerSetPosition(dev, mode, screenx, screeny);
+    scr = miPointerSetPosition(dev, mode, screenx, screeny,
+                               (int)floor(*screenx) - scr->x,
+                               (int)floor(*screeny) - scr->y);
 
     /* If we were constrained, rescale x/y from the screen coordinates so
      * the device valuators reflect the correct position. For screen
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 3530abf..55cfbd9 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1871,7 +1871,7 @@ xf86CrtcSetScanoutPixmap(RRCrtcPtr randr_crtc, PixmapPtr pixmap)
 }
 
 static void
-xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
+xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y, int unclamped_x, int unclamped_y)
 {
     XF86RandRInfoPtr randrp = XF86RANDRINFO(screen);
 
@@ -1880,7 +1880,7 @@ xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, i
 
     if (randrp->orig_ConstrainCursorHarder) {
         screen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder;
-        screen->ConstrainCursorHarder(dev, screen, mode, x, y);
+        screen->ConstrainCursorHarder(dev, screen, mode, x, y, unclamped_x, unclamped_y);
         screen->ConstrainCursorHarder = xf86RandR13ConstrainCursorHarder;
     }
 }
diff --git a/include/events.h b/include/events.h
index 222bf32..c0ef45d 100644
--- a/include/events.h
+++ b/include/events.h
@@ -27,6 +27,7 @@
 typedef struct _DeviceEvent DeviceEvent;
 typedef struct _DeviceChangedEvent DeviceChangedEvent;
 typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
+typedef struct _BarrierEvent BarrierEvent;
 
 #if XFreeXDGA
 typedef struct _DGAEvent DGAEvent;
diff --git a/include/eventstr.h b/include/eventstr.h
index dd6fbef..176bac0 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -72,6 +72,7 @@ enum EventType {
     ET_RawTouchUpdate,
     ET_RawTouchEnd,
     ET_XQuartz,
+    ET_BarrierNotify,
     ET_Internal = 0xFF          /* First byte */
 };
 
@@ -227,6 +228,26 @@ struct _RawDeviceEvent {
     uint32_t flags;       /**< Flags to be copied into the generated event */
 };
 
+struct _BarrierEvent {
+    unsigned char header; /**<  Always ET_Internal */
+    enum EventType type;  /**<  ET_BarrierNotify */
+    int length;           /**<  Length in bytes */
+    Time time;            /**<  Time in ms */
+    int deviceid;         /**< Device to post this event for */
+    int sourceid;         /**< The physical source device */
+    int barrierid;
+    Window window;
+    int16_t x;
+    int16_t y;
+    int32_t dx;
+    int32_t dy;
+    int32_t raw_dx;
+    int32_t raw_dy;
+    int16_t dt;
+    int16_t event_type;
+    int32_t event_id;
+};
+
 #ifdef XQUARTZ
 #define XQUARTZ_EVENT_MAXARGS 5
 struct _XQuartzEvent {
@@ -253,6 +274,7 @@ union _InternalEvent {
     DeviceEvent device_event;
     DeviceChangedEvent changed_event;
     TouchOwnershipEvent touch_ownership_event;
+    BarrierEvent barrier_event;
 #if XFreeXDGA
     DGAEvent dga_event;
 #endif
diff --git a/include/inputstr.h b/include/inputstr.h
index 5a38924..e4240c9 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -71,7 +71,7 @@ extern _X_EXPORT int CountBits(const uint8_t * mask, int len);
  * events to the protocol, the server will not support these events until
  * this number here is bumped.
  */
-#define XI2LASTEVENT    XI_RawTouchEnd
+#define XI2LASTEVENT    XI_BarrierPointerReleasedNotify
 #define XI2MASKSIZE     ((XI2LASTEVENT >> 3) + 1)       /* no of bytes for masks */
 
 /**
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index cb8e213..10f5117 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -127,7 +127,7 @@
 
 /* X Input */
 #define SERVER_XI_MAJOR_VERSION			2
-#define SERVER_XI_MINOR_VERSION			2
+#define SERVER_XI_MINOR_VERSION			3
 
 /* XKB */
 #define SERVER_XKB_MAJOR_VERSION		1
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index df74073..095b029 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -339,7 +339,7 @@ typedef void (*DeviceCursorCleanupProcPtr) (DeviceIntPtr /* pDev */ ,
                                             ScreenPtr /* pScreen */ );
 
 typedef void (*ConstrainCursorHarderProcPtr) (DeviceIntPtr, ScreenPtr, int,
-                                              int *, int *);
+                                              int *, int *, int, int);
 
 
 typedef Bool (*SharePixmapBackingProcPtr)(PixmapPtr, ScreenPtr, void **);
diff --git a/mi/mieq.c b/mi/mieq.c
index b2c7769..102fe95 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -407,6 +407,9 @@ ChangeDeviceID(DeviceIntPtr dev, InternalEvent *event)
     case ET_RawTouchUpdate:
         event->raw_event.deviceid = dev->id;
         break;
+    case ET_BarrierNotify:
+        event->barrier_event.deviceid = dev->id;
+        break;
     default:
         ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
                event->any.type);
diff --git a/mi/mipointer.c b/mi/mipointer.c
index f345063..b440fd1 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -271,7 +271,7 @@ miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
     pPointer->generateEvent = generateEvent;
 
     if (pScreen->ConstrainCursorHarder)
-        pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
+        pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y, 0, 0);
 
     /* device dependent - must pend signal and call miPointerWarpCursor */
     (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
@@ -562,10 +562,13 @@ miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
  * @param mode Movement mode (Absolute or Relative)
  * @param[in,out] screenx The x coordinate in desktop coordinates
  * @param[in,out] screeny The y coordinate in desktop coordinates
+ * @param unclamped_x The unclamped x coordinate in screen coordinates
+ * @param unclamped_x The unclamped y coordinate in screen coordinates
  */
 ScreenPtr
-miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
-                     double *screeny)
+miPointerSetPosition(DeviceIntPtr pDev, int mode,
+                     double *screenx, double *screeny,
+                     int unclamped_x, int unclamped_y)
 {
     miPointerScreenPtr pScreenPriv;
     ScreenPtr pScreen;
@@ -614,7 +617,8 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
         y = pPointer->limits.y2 - 1;
 
     if (pScreen->ConstrainCursorHarder)
-        pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y);
+        pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y,
+                                       unclamped_x, unclamped_y);
 
     if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen)
         miPointerMoveNoEvent(pDev, pScreen, x, y);
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 1500e21..9d008f4 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -115,7 +115,9 @@ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y);
 /* Moves the cursor to the specified position.  May clip the co-ordinates:
  * x and y are modified in-place. */
 extern _X_EXPORT ScreenPtr
-miPointerSetPosition(DeviceIntPtr pDev, int mode, double *x, double *y);
+miPointerSetPosition(DeviceIntPtr pDev, int mode,
+                     double *x, double *y,
+                     int unclamped_x, int unclamped_y);
 
 extern _X_EXPORT void
 miPointerUpdateSprite(DeviceIntPtr pDev);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index a16302f..1cc4dfd 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -704,7 +704,7 @@ int
  ProcRRSetPanning(ClientPtr client);
 
 void
- RRConstrainCursorHarder(DeviceIntPtr, ScreenPtr, int, int *, int *);
+ RRConstrainCursorHarder(DeviceIntPtr, ScreenPtr, int, int *, int *, int, int);
 
 /* rrdispatch.c */
 extern _X_EXPORT Bool
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e82d050..d0eb8dd 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1613,8 +1613,8 @@ static Bool constrain_all_screen_crtcs(DeviceIntPtr pDev, ScreenPtr pScreen, int
 }
 
 void
-RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
-                        int *y)
+RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode,
+                        int *x, int *y, int unclamped_x, int unclamped_y)
 {
     rrScrPriv(pScreen);
     Bool ret;
-- 
1.8.0



More information about the xorg-devel mailing list