From: "Jasper St. Pierre" <jstpie...@mecheye.net> 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.rog...@canonical.com> Signed-off-by: Jasper St. Pierre <jstpie...@mecheye.net> Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- Xi/exevents.c | 32 ++++++++++++++++ Xi/extinit.c | 38 ++++++++++++++++++- Xi/xibarriers.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Xi/xibarriers.h | 8 ++-- dix/eventconvert.c | 39 +++++++++++++++++++ include/events.h | 1 + include/eventstr.h | 22 +++++++++++ include/inputstr.h | 2 +- mi/mieq.c | 4 ++ 9 files changed, 245 insertions(+), 8 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 2caf98c..e606d9e 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 1074b23..175d89b 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 0affde6..f16094d 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 8f2993f..f29bb6c 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_ */ diff --git a/dix/eventconvert.c b/dix/eventconvert.c index 2e422d7..bb5c8d3 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -57,6 +57,7 @@ static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce); static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi); +static int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi); static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi); /* Do not use, read comments below */ @@ -277,6 +278,9 @@ EventToXI2(InternalEvent *ev, xEvent **xi) case ET_RawTouchUpdate: case ET_RawTouchEnd: return eventToRawEvent(&ev->raw_event, xi); + case ET_BarrierHit: + case ET_BarrierLeave: + return eventToBarrierEvent(&ev->barrier_event, xi); default: break; } @@ -782,6 +786,35 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) return Success; } +static int +eventToBarrierEvent(BarrierEvent *ev, xEvent **xi) +{ + xXIBarrierEvent *barrier; + int len = sizeof(xXIBarrierEvent); + + *xi = calloc(1, len); + barrier = (xXIBarrierEvent*) *xi; + barrier->type = GenericEvent; + barrier->extension = IReqCode; + barrier->evtype = GetXI2Type(ev->type); + barrier->length = bytes_to_int32(len - sizeof(xEvent)); + barrier->deviceid = ev->deviceid; + barrier->sourceid = ev->sourceid; + barrier->time = ev->time; + barrier->event = ev->window; + barrier->root = ev->root; + barrier->dx = double_to_fp3232(ev->dx); + barrier->dy = double_to_fp3232(ev->dy); + barrier->dtime = ev->dt; + barrier->flags = ev->flags; + barrier->eventid = ev->event_id; + barrier->barrier = ev->barrierid; + barrier->root_x = double_to_fp1616(ev->root_x); + barrier->root_y = double_to_fp1616(ev->root_y); + + return Success; +} + /** * Return the corresponding core type for the given event or 0 if no core * equivalent exists. @@ -929,6 +962,12 @@ GetXI2Type(enum EventType type) case ET_TouchOwnership: xi2type = XI_TouchOwnership; break; + case ET_BarrierHit: + xi2type = XI_BarrierHit; + break; + case ET_BarrierLeave: + xi2type = XI_BarrierLeave; + break; default: break; } 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 eddba87..38fab4f 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -72,6 +72,8 @@ enum EventType { ET_RawTouchUpdate, ET_RawTouchEnd, ET_XQuartz, + ET_BarrierHit, + ET_BarrierLeave, ET_Internal = 0xFF /* First byte */ }; @@ -227,6 +229,25 @@ 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_BarrierHit, ET_BarrierLeave */ + 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; + Window root; + double dx; + double dy; + double root_x; + double root_y; + int16_t dt; + int32_t event_id; + uint32_t flags; +}; + #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 bb0a779..17cee98 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_BarrierLeave #define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */ /** diff --git a/mi/mieq.c b/mi/mieq.c index b2c7769..22f8c91 100644 --- a/mi/mieq.c +++ b/mi/mieq.c @@ -407,6 +407,10 @@ ChangeDeviceID(DeviceIntPtr dev, InternalEvent *event) case ET_RawTouchUpdate: event->raw_event.deviceid = dev->id; break; + case ET_BarrierHit: + case ET_BarrierLeave: + event->barrier_event.deviceid = dev->id; + break; default: ErrorF("[mi] Unknown event type (%d), cannot change id.\n", event->any.type); -- 1.8.0.1 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel