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>
This commit is contained in:
parent
85a37ddcc2
commit
e130a46ab4
|
@ -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;
|
||||
|
|
38
Xi/extinit.c
38
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;
|
||||
|
|
107
Xi/xibarriers.c
107
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)
|
||||
{
|
||||
|
|
|
@ -39,9 +39,7 @@ XIDestroyPointerBarrier(ClientPtr client,
|
|||
Bool
|
||||
XIBarrierInit(void);
|
||||
|
||||
int SProcXIBarrierReleasePointer(ClientPtr client);
|
||||
int ProcXIBarrierReleasePointer(ClientPtr client);
|
||||
|
||||
#endif /* _XIBARRIERS_H_ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue