summaryrefslogtreecommitdiff
path: root/Xi
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-11-01 16:06:40 -0400
committerPeter Hutterer <peter.hutterer@who-t.net>2012-12-17 15:01:45 +1000
commite130a46ab45839f91b29ee75bf19a597dfe3da28 (patch)
tree5320c18af170b6d61f5bf03af5bdbf71c8779882 /Xi
parent85a37ddcc2ff49adaec4075532b60e7d015f901c (diff)
Add support for XI2.3: Pointer barrier events and releases.
This adds support for clients that would like to get a notification every time a barrier is hit, and allows clients to temporarily release a barrier so that pointers can go through them, without having to destroy and recreate barriers. Based on work by Chris Halse Rogers <chris.halse.rogers@canonical.com> Signed-off-by: Jasper St. Pierre <jstpierre@mecheye.net> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'Xi')
-rw-r--r--Xi/exevents.c32
-rw-r--r--Xi/extinit.c38
-rw-r--r--Xi/xibarriers.c107
-rw-r--r--Xi/xibarriers.h8
4 files changed, 178 insertions, 7 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 2caf98c25..e606d9ea5 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1639,6 +1639,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
UpdateDeviceState(dev, &ev->device_event);
}
+static void
+ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
+{
+ Mask filter;
+ WindowPtr pWin;
+ BarrierEvent *be = &e->barrier_event;
+ xEvent *ev;
+ int rc;
+
+ if (!IsMaster(dev))
+ return;
+
+ if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
+ return;
+
+ rc = EventToXI2(e, &ev);
+ if (rc != Success) {
+ ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
+ return;
+ }
+
+ filter = GetEventFilter(dev, ev);
+
+ DeliverEventsToWindow(dev, pWin, ev, 1,
+ filter, NullGrab);
+ free(ev);
+}
+
/**
* Process DeviceEvents and DeviceChangedEvents.
*/
@@ -1788,6 +1816,10 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
case ET_TouchEnd:
ProcessTouchEvent(ev, device);
break;
+ case ET_BarrierHit:
+ case ET_BarrierLeave:
+ ProcessBarrierEvent(ev, device);
+ break;
default:
ProcessDeviceEvent(ev, device);
break;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 1074b237c..175d89b00 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -252,7 +252,8 @@ static int (*ProcIVector[]) (ClientPtr) = {
ProcXIChangeProperty, /* 57 */
ProcXIDeleteProperty, /* 58 */
ProcXIGetProperty, /* 59 */
- ProcXIGetSelectedEvents /* 60 */
+ ProcXIGetSelectedEvents, /* 60 */
+ ProcXIBarrierReleasePointer /* 61 */
};
/* For swapped clients */
@@ -317,7 +318,8 @@ static int (*SProcIVector[]) (ClientPtr) = {
SProcXIChangeProperty, /* 57 */
SProcXIDeleteProperty, /* 58 */
SProcXIGetProperty, /* 59 */
- SProcXIGetSelectedEvents /* 60 */
+ SProcXIGetSelectedEvents, /* 60 */
+ SProcXIBarrierReleasePointer /* 61 */
};
/*****************************************************************
@@ -840,6 +842,33 @@ STouchOwnershipEvent(xXITouchOwnershipEvent * from, xXITouchOwnershipEvent * to)
swapl(&to->child);
}
+static void
+SBarrierEvent(xXIBarrierEvent * from,
+ xXIBarrierEvent * to) {
+ to->type = from->type;
+
+ cpswapl(from->length, to->length);
+ cpswapl(from->time, to->time);
+ cpswaps(from->deviceid, to->deviceid);
+ cpswaps(from->sourceid, to->sourceid);
+ cpswapl(from->event, to->event);
+ cpswapl(from->root, to->root);
+ cpswapl(from->root_x, to->root_x);
+ cpswapl(from->root_y, to->root_y);
+
+#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);
+ cpswapl(from->dtime, to->dtime);
+ cpswapl(from->barrier, to->barrier);
+ cpswapl(from->eventid, to->eventid);
+}
+
/** Event swapping function for XI2 events. */
void
XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
@@ -886,6 +915,11 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
case XI_RawTouchEnd:
SRawEvent((xXIRawEvent *) from, (xXIRawEvent *) to);
break;
+ case XI_BarrierHit:
+ case XI_BarrierLeave:
+ SBarrierEvent((xXIBarrierEvent *) from,
+ (xXIBarrierEvent *) 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 0affde68d..f16094d45 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;
@@ -66,11 +68,18 @@ static DevPrivateKeyRec BarrierScreenPrivateKeyRec;
typedef struct PointerBarrierClient *PointerBarrierClientPtr;
struct PointerBarrierClient {
+ XID id;
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 {
@@ -315,6 +324,18 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
int i;
struct PointerBarrier *nearest = NULL;
PointerBarrierClientPtr c;
+ Time ms = GetTimeInMillis();
+ BarrierEvent ev = {
+ .header = ET_Internal,
+ .type = 0,
+ .length = sizeof (BarrierEvent),
+ .time = ms,
+ .deviceid = dev->id,
+ .sourceid = dev->id,
+ .dx = dest_x - current_x,
+ .dy = dest_y - current_y,
+ .root = screen->root->drawable.id,
+ };
if (xorg_list_is_empty(&cs->barriers) || IsFloating(dev))
goto out;
@@ -336,6 +357,13 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
nearest = &c->barrier;
+ c->seen = TRUE;
+ c->hit = TRUE;
+
+ if (c->barrier_event_id == c->release_event_id)
+ continue;
+
+ ev.type = ET_BarrierHit;
barrier_clamp_to_barrier(nearest, dir, &x, &y);
if (barrier_is_vertical(nearest)) {
@@ -346,6 +374,21 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
dir &= ~(BarrierNegativeY | BarrierPositiveY);
current_y = y;
}
+
+ ev.flags = 0;
+ ev.event_id = c->barrier_event_id;
+ ev.barrierid = c->id;
+
+ 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;
}
out:
@@ -384,6 +427,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];
@@ -410,6 +454,11 @@ CreatePointerBarrierClient(ClientPtr client,
ret->device_ids[i] = device_id;
}
+ ret->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);
@@ -489,6 +538,64 @@ XIDestroyPointerBarrier(ClientPtr client,
return Success;
}
+int
+SProcXIBarrierReleasePointer(ClientPtr client)
+{
+ xXIBarrierReleasePointerInfo *info;
+ REQUEST(xXIBarrierReleasePointerReq);
+ int i;
+
+ info = (xXIBarrierReleasePointerInfo*) &stuff[1];
+
+ swaps(&stuff->length);
+ swapl(&stuff->num_barriers);
+ for (i = 0; i < stuff->num_barriers; i++, info++) {
+ swaps(&info->deviceid);
+ swapl(&info->barrier);
+ swapl(&info->eventid);
+ }
+
+ return (ProcXIBarrierReleasePointer(client));
+}
+
+int
+ProcXIBarrierReleasePointer(ClientPtr client)
+{
+ int i;
+ int err;
+ struct PointerBarrierClient *barrier;
+ struct PointerBarrier *b;
+ xXIBarrierReleasePointerInfo *info;
+
+ REQUEST(xXIBarrierReleasePointerReq);
+ REQUEST_AT_LEAST_SIZE(xXIBarrierReleasePointerReq);
+
+ info = (xXIBarrierReleasePointerInfo*) &stuff[1];
+ for (i = 0; i < stuff->num_barriers; i++, info++) {
+ CARD32 barrier_id, event_id;
+ _X_UNUSED CARD32 device_id;
+
+ barrier_id = info->barrier;
+ event_id = info->eventid;
+
+ /* FIXME: per-device releases */
+ device_id = info->deviceid;
+
+ err = dixLookupResourceByType((void **) &b, barrier_id,
+ PointerBarrierType, client, DixReadAccess);
+ if (err != Success) {
+ client->errorValue = barrier_id;
+ return err;
+ }
+
+ barrier = container_of(b, struct PointerBarrierClient, barrier);
+ if (barrier->barrier_event_id == event_id)
+ barrier->release_event_id = event_id;
+ }
+
+ return Success;
+}
+
Bool
XIBarrierInit(void)
{
diff --git a/Xi/xibarriers.h b/Xi/xibarriers.h
index 8f2993f85..f29bb6c8f 100644
--- a/Xi/xibarriers.h
+++ b/Xi/xibarriers.h
@@ -39,9 +39,7 @@ XIDestroyPointerBarrier(ClientPtr client,
Bool
XIBarrierInit(void);
-#endif /* _XIBARRIERS_H_ */
-
-
-
-
+int SProcXIBarrierReleasePointer(ClientPtr client);
+int ProcXIBarrierReleasePointer(ClientPtr client);
+#endif /* _XIBARRIERS_H_ */