diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-11-01 16:06:40 -0400 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-12-17 15:01:45 +1000 |
commit | e130a46ab45839f91b29ee75bf19a597dfe3da28 (patch) | |
tree | 5320c18af170b6d61f5bf03af5bdbf71c8779882 /Xi | |
parent | 85a37ddcc2ff49adaec4075532b60e7d015f901c (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.c | 32 | ||||
-rw-r--r-- | Xi/extinit.c | 38 | ||||
-rw-r--r-- | Xi/xibarriers.c | 107 | ||||
-rw-r--r-- | Xi/xibarriers.h | 8 |
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_ */ |