123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932 |
- /*
- * Copyright 2012 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright © 2002 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "xibarriers.h"
- #include "scrnintstr.h"
- #include "cursorstr.h"
- #include "dixevents.h"
- #include "servermd.h"
- #include "mipointer.h"
- #include "inputstr.h"
- #include "windowstr.h"
- #include "xace.h"
- #include "list.h"
- #include "exglobals.h"
- #include "eventstr.h"
- #include "mi.h"
- RESTYPE PointerBarrierType;
- static DevPrivateKeyRec BarrierScreenPrivateKeyRec;
- #define BarrierScreenPrivateKey (&BarrierScreenPrivateKeyRec)
- typedef struct PointerBarrierClient *PointerBarrierClientPtr;
- struct PointerBarrierDevice {
- struct xorg_list entry;
- int deviceid;
- Time last_timestamp;
- int barrier_event_id;
- int release_event_id;
- Bool hit;
- Bool seen;
- };
- struct PointerBarrierClient {
- XID id;
- ScreenPtr screen;
- Window window;
- struct PointerBarrier barrier;
- struct xorg_list entry;
- /* num_devices/device_ids are devices the barrier applies to */
- int num_devices;
- int *device_ids; /* num_devices */
- /* per_device keeps track of devices actually blocked by barriers */
- struct xorg_list per_device;
- };
- typedef struct _BarrierScreen {
- struct xorg_list barriers;
- } BarrierScreenRec, *BarrierScreenPtr;
- #define GetBarrierScreen(s) ((BarrierScreenPtr)dixLookupPrivate(&(s)->devPrivates, BarrierScreenPrivateKey))
- #define GetBarrierScreenIfSet(s) GetBarrierScreen(s)
- #define SetBarrierScreen(s,p) dixSetPrivate(&(s)->devPrivates, BarrierScreenPrivateKey, p)
- static struct PointerBarrierDevice *AllocBarrierDevice(void)
- {
- struct PointerBarrierDevice *pbd = NULL;
- pbd = malloc(sizeof(struct PointerBarrierDevice));
- if (!pbd)
- return NULL;
- pbd->deviceid = -1; /* must be set by caller */
- pbd->barrier_event_id = 1;
- pbd->release_event_id = 0;
- pbd->hit = FALSE;
- pbd->seen = FALSE;
- xorg_list_init(&pbd->entry);
- return pbd;
- }
- static void FreePointerBarrierClient(struct PointerBarrierClient *c)
- {
- struct PointerBarrierDevice *pbd = NULL, *tmp = NULL;
- xorg_list_for_each_entry_safe(pbd, tmp, &c->per_device, entry) {
- free(pbd);
- }
- free(c);
- }
- static struct PointerBarrierDevice *GetBarrierDevice(struct PointerBarrierClient *c, int deviceid)
- {
- struct PointerBarrierDevice *pbd = NULL;
- xorg_list_for_each_entry(pbd, &c->per_device, entry) {
- if (pbd->deviceid == deviceid)
- break;
- }
- BUG_WARN(!pbd);
- return pbd;
- }
- static BOOL
- barrier_is_horizontal(const struct PointerBarrier *barrier)
- {
- return barrier->y1 == barrier->y2;
- }
- static BOOL
- barrier_is_vertical(const struct PointerBarrier *barrier)
- {
- return barrier->x1 == barrier->x2;
- }
- /**
- * @return The set of barrier movement directions the movement vector
- * x1/y1 → x2/y2 represents.
- */
- int
- barrier_get_direction(int x1, int y1, int x2, int y2)
- {
- int direction = 0;
- /* which way are we trying to go */
- if (x2 > x1)
- direction |= BarrierPositiveX;
- if (x2 < x1)
- direction |= BarrierNegativeX;
- if (y2 > y1)
- direction |= BarrierPositiveY;
- if (y2 < y1)
- direction |= BarrierNegativeY;
- return direction;
- }
- /**
- * Test if the barrier may block movement in the direction defined by
- * x1/y1 → x2/y2. This function only tests whether the directions could be
- * blocked, it does not test if the barrier actually blocks the movement.
- *
- * @return TRUE if the barrier blocks the direction of movement or FALSE
- * otherwise.
- */
- BOOL
- barrier_is_blocking_direction(const struct PointerBarrier * barrier,
- int direction)
- {
- /* Barriers define which way is ok, not which way is blocking */
- return (barrier->directions & direction) != direction;
- }
- static BOOL
- inside_segment(int v, int v1, int v2)
- {
- if (v1 < 0 && v2 < 0) /* line */
- return TRUE;
- else if (v1 < 0) /* ray */
- return v <= v2;
- else if (v2 < 0) /* ray */
- return v >= v1;
- else /* line segment */
- return v >= v1 && v <= v2;
- }
- #define T(v, a, b) (((float)v) - (a)) / ((b) - (a))
- #define F(t, a, b) ((t) * ((a) - (b)) + (a))
- /**
- * Test if the movement vector x1/y1 → x2/y2 is intersecting with the
- * barrier. A movement vector with the startpoint or endpoint adjacent to
- * the barrier itself counts as intersecting.
- *
- * @param x1 X start coordinate of movement vector
- * @param y1 Y start coordinate of movement vector
- * @param x2 X end coordinate of movement vector
- * @param y2 Y end coordinate of movement vector
- * @param[out] distance The distance between the start point and the
- * intersection with the barrier (if applicable).
- * @return TRUE if the barrier intersects with the given vector
- */
- BOOL
- barrier_is_blocking(const struct PointerBarrier * barrier,
- int x1, int y1, int x2, int y2, double *distance)
- {
- if (barrier_is_vertical(barrier)) {
- float t, y;
- t = T(barrier->x1, x1, x2);
- if (t < 0 || t > 1)
- return FALSE;
- /* Edge case: moving away from barrier. */
- if (x2 > x1 && t == 0)
- return FALSE;
- y = F(t, y1, y2);
- if (!inside_segment(y, barrier->y1, barrier->y2))
- return FALSE;
- *distance = sqrt((pow(y - y1, 2) + pow(barrier->x1 - x1, 2)));
- return TRUE;
- }
- else {
- float t, x;
- t = T(barrier->y1, y1, y2);
- if (t < 0 || t > 1)
- return FALSE;
- /* Edge case: moving away from barrier. */
- if (y2 > y1 && t == 0)
- return FALSE;
- x = F(t, x1, x2);
- if (!inside_segment(x, barrier->x1, barrier->x2))
- return FALSE;
- *distance = sqrt((pow(x - x1, 2) + pow(barrier->y1 - y1, 2)));
- return TRUE;
- }
- }
- #define HIT_EDGE_EXTENTS 2
- static BOOL
- barrier_inside_hit_box(struct PointerBarrier *barrier, int x, int y)
- {
- int x1, x2, y1, y2;
- int dir;
- x1 = barrier->x1;
- x2 = barrier->x2;
- y1 = barrier->y1;
- y2 = barrier->y2;
- dir = ~(barrier->directions);
- if (barrier_is_vertical(barrier)) {
- if (dir & BarrierPositiveX)
- x1 -= HIT_EDGE_EXTENTS;
- if (dir & BarrierNegativeX)
- x2 += HIT_EDGE_EXTENTS;
- }
- if (barrier_is_horizontal(barrier)) {
- if (dir & BarrierPositiveY)
- y1 -= HIT_EDGE_EXTENTS;
- if (dir & BarrierNegativeY)
- y2 += HIT_EDGE_EXTENTS;
- }
- return x >= x1 && x <= x2 && y >= y1 && y <= y2;
- }
- static BOOL
- barrier_blocks_device(struct PointerBarrierClient *client,
- DeviceIntPtr dev)
- {
- int i;
- int master_id;
- /* Clients with no devices are treated as
- * if they specified XIAllDevices. */
- if (client->num_devices == 0)
- return TRUE;
- master_id = GetMaster(dev, POINTER_OR_FLOAT)->id;
- for (i = 0; i < client->num_devices; i++) {
- int device_id = client->device_ids[i];
- if (device_id == XIAllDevices ||
- device_id == XIAllMasterDevices ||
- device_id == master_id)
- return TRUE;
- }
- return FALSE;
- }
- /**
- * 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
- * @param y1 Y start coordinate of movement vector
- * @param x2 X end coordinate of movement vector
- * @param y2 Y end coordinate of movement vector
- * @return The barrier nearest to the movement origin that blocks this movement.
- */
- static struct PointerBarrierClient *
- barrier_find_nearest(BarrierScreenPtr cs, DeviceIntPtr dev,
- int dir,
- int x1, int y1, int x2, int y2)
- {
- 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) {
- struct PointerBarrier *b = &c->barrier;
- struct PointerBarrierDevice *pbd;
- double distance;
- pbd = GetBarrierDevice(c, dev->id);
- if (pbd->seen)
- continue;
- if (!barrier_is_blocking_direction(b, dir))
- continue;
- if (!barrier_blocks_device(c, dev))
- continue;
- if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) {
- if (min_distance > distance) {
- min_distance = distance;
- nearest = c;
- }
- }
- }
- return nearest;
- }
- /**
- * Clamp to the given barrier given the movement direction specified in dir.
- *
- * @param barrier The barrier to clamp to
- * @param dir The movement direction
- * @param[out] x The clamped x coordinate.
- * @param[out] y The clamped x coordinate.
- */
- void
- barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
- int *y)
- {
- if (barrier_is_vertical(barrier)) {
- if ((dir & BarrierNegativeX) & ~barrier->directions)
- *x = barrier->x1;
- if ((dir & BarrierPositiveX) & ~barrier->directions)
- *x = barrier->x1 - 1;
- }
- if (barrier_is_horizontal(barrier)) {
- if ((dir & BarrierNegativeY) & ~barrier->directions)
- *y = barrier->y1;
- if ((dir & BarrierPositiveY) & ~barrier->directions)
- *y = barrier->y1 - 1;
- }
- }
- void
- input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
- int current_x, int current_y,
- int dest_x, int dest_y,
- int *out_x, int *out_y,
- int *nevents, InternalEvent* events)
- {
- /* Clamped coordinates here refer to screen edge clamping. */
- BarrierScreenPtr cs = GetBarrierScreen(screen);
- int x = dest_x,
- y = dest_y;
- int dir;
- 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,
- };
- InternalEvent *barrier_events = events;
- DeviceIntPtr master;
- if (nevents)
- *nevents = 0;
- if (xorg_list_is_empty(&cs->barriers) || IsFloating(dev))
- goto out;
- /**
- * This function is only called for slave devices, but pointer-barriers
- * are for master-devices only. Flip the device to the master here,
- * continue with that.
- */
- master = GetMaster(dev, MASTER_POINTER);
- /* How this works:
- * Given the origin and the movement vector, get the nearest barrier
- * to the origin that is blocking the movement.
- * Clamp to that barrier.
- * Then, check from the clamped intersection to the original
- * destination, again finding the nearest barrier and clamping.
- */
- dir = barrier_get_direction(current_x, current_y, x, y);
- while (dir != 0) {
- int new_sequence;
- struct PointerBarrierDevice *pbd;
- c = barrier_find_nearest(cs, master, dir, current_x, current_y, x, y);
- if (!c)
- break;
- nearest = &c->barrier;
- pbd = GetBarrierDevice(c, master->id);
- new_sequence = !pbd->hit;
- pbd->seen = TRUE;
- pbd->hit = TRUE;
- if (pbd->barrier_event_id == pbd->release_event_id)
- continue;
- ev.type = ET_BarrierHit;
- barrier_clamp_to_barrier(nearest, dir, &x, &y);
- if (barrier_is_vertical(nearest)) {
- dir &= ~(BarrierNegativeX | BarrierPositiveX);
- current_x = x;
- }
- else if (barrier_is_horizontal(nearest)) {
- dir &= ~(BarrierNegativeY | BarrierPositiveY);
- current_y = y;
- }
- ev.flags = 0;
- ev.event_id = pbd->barrier_event_id;
- ev.barrierid = c->id;
- ev.dt = new_sequence ? 0 : ms - pbd->last_timestamp;
- ev.window = c->window;
- pbd->last_timestamp = ms;
- /* root x/y is filled in later */
- barrier_events->barrier_event = ev;
- barrier_events++;
- *nevents += 1;
- }
- xorg_list_for_each_entry(c, &cs->barriers, entry) {
- struct PointerBarrierDevice *pbd;
- int flags = 0;
- pbd = GetBarrierDevice(c, master->id);
- pbd->seen = FALSE;
- if (!pbd->hit)
- continue;
- if (barrier_inside_hit_box(&c->barrier, x, y))
- continue;
- pbd->hit = FALSE;
- ev.type = ET_BarrierLeave;
- if (pbd->barrier_event_id == pbd->release_event_id)
- flags |= XIBarrierPointerReleased;
- ev.flags = flags;
- ev.event_id = pbd->barrier_event_id;
- ev.barrierid = c->id;
- ev.dt = ms - pbd->last_timestamp;
- ev.window = c->window;
- pbd->last_timestamp = ms;
- /* root x/y is filled in later */
- barrier_events->barrier_event = ev;
- barrier_events++;
- *nevents += 1;
- /* If we've left the hit box, this is the
- * start of a new event ID. */
- pbd->barrier_event_id++;
- }
- out:
- *out_x = x;
- *out_y = y;
- }
- static void
- sort_min_max(INT16 *a, INT16 *b)
- {
- INT16 A, B;
- if (*a < 0 || *b < 0)
- return;
- A = *a;
- B = *b;
- *a = min(A, B);
- *b = max(A, B);
- }
- static int
- CreatePointerBarrierClient(ClientPtr client,
- xXFixesCreatePointerBarrierReq * stuff,
- PointerBarrierClientPtr *client_out)
- {
- WindowPtr pWin;
- ScreenPtr screen;
- BarrierScreenPtr cs;
- int err;
- int size;
- int i;
- struct PointerBarrierClient *ret;
- CARD16 *in_devices;
- DeviceIntPtr dev;
- size = sizeof(*ret) + sizeof(DeviceIntPtr) * stuff->num_devices;
- ret = malloc(size);
- if (!ret) {
- return BadAlloc;
- }
- xorg_list_init(&ret->per_device);
- err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
- if (err != Success) {
- client->errorValue = stuff->window;
- goto error;
- }
- screen = pWin->drawable.pScreen;
- cs = GetBarrierScreen(screen);
- ret->screen = screen;
- ret->window = stuff->window;
- ret->num_devices = stuff->num_devices;
- if (ret->num_devices > 0)
- ret->device_ids = (int*)&ret[1];
- else
- ret->device_ids = NULL;
- in_devices = (CARD16 *) &stuff[1];
- for (i = 0; i < stuff->num_devices; i++) {
- int device_id = in_devices[i];
- DeviceIntPtr device;
- if ((err = dixLookupDevice (&device, device_id,
- client, DixReadAccess))) {
- client->errorValue = device_id;
- goto error;
- }
- if (!IsMaster (device)) {
- client->errorValue = device_id;
- err = BadDevice;
- goto error;
- }
- ret->device_ids[i] = device_id;
- }
- /* Alloc one per master pointer, they're the ones that can be blocked */
- xorg_list_init(&ret->per_device);
- nt_list_for_each_entry(dev, inputInfo.devices, next) {
- struct PointerBarrierDevice *pbd;
- if (dev->type != MASTER_POINTER)
- continue;
- pbd = AllocBarrierDevice();
- if (!pbd) {
- err = BadAlloc;
- goto error;
- }
- pbd->deviceid = dev->id;
- xorg_list_add(&pbd->entry, &ret->per_device);
- }
- ret->id = stuff->barrier;
- ret->barrier.x1 = stuff->x1;
- ret->barrier.x2 = stuff->x2;
- ret->barrier.y1 = stuff->y1;
- ret->barrier.y2 = stuff->y2;
- sort_min_max(&ret->barrier.x1, &ret->barrier.x2);
- sort_min_max(&ret->barrier.y1, &ret->barrier.y2);
- ret->barrier.directions = stuff->directions & 0x0f;
- if (barrier_is_horizontal(&ret->barrier))
- ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
- if (barrier_is_vertical(&ret->barrier))
- ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
- xorg_list_add(&ret->entry, &cs->barriers);
- *client_out = ret;
- return Success;
- error:
- *client_out = NULL;
- FreePointerBarrierClient(ret);
- return err;
- }
- static int
- BarrierFreeBarrier(void *data, XID id)
- {
- struct PointerBarrierClient *c;
- Time ms = GetTimeInMillis();
- DeviceIntPtr dev = NULL;
- ScreenPtr screen;
- c = container_of(data, struct PointerBarrierClient, barrier);
- screen = c->screen;
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- struct PointerBarrierDevice *pbd;
- int root_x, root_y;
- BarrierEvent ev = {
- .header = ET_Internal,
- .type = ET_BarrierLeave,
- .length = sizeof (BarrierEvent),
- .time = ms,
- /* .deviceid */
- .sourceid = 0,
- .barrierid = c->id,
- .window = c->window,
- .root = screen->root->drawable.id,
- .dx = 0,
- .dy = 0,
- /* .root_x */
- /* .root_y */
- /* .dt */
- /* .event_id */
- .flags = XIBarrierPointerReleased,
- };
- if (dev->type != MASTER_POINTER)
- continue;
- pbd = GetBarrierDevice(c, dev->id);
- if (!pbd->hit)
- continue;
- ev.deviceid = dev->id;
- ev.event_id = pbd->barrier_event_id;
- ev.dt = ms - pbd->last_timestamp;
- GetSpritePosition(dev, &root_x, &root_y);
- ev.root_x = root_x;
- ev.root_y = root_y;
- mieqEnqueue(dev, (InternalEvent *) &ev);
- }
- xorg_list_del(&c->entry);
- FreePointerBarrierClient(c);
- return Success;
- }
- static void add_master_func(void *res, XID id, void *devid)
- {
- struct PointerBarrier *b;
- struct PointerBarrierClient *barrier;
- struct PointerBarrierDevice *pbd;
- int *deviceid = devid;
- b = res;
- barrier = container_of(b, struct PointerBarrierClient, barrier);
- pbd = AllocBarrierDevice();
- pbd->deviceid = *deviceid;
- xorg_list_add(&pbd->entry, &barrier->per_device);
- }
- static void remove_master_func(void *res, XID id, void *devid)
- {
- struct PointerBarrierDevice *pbd;
- struct PointerBarrierClient *barrier;
- struct PointerBarrier *b;
- DeviceIntPtr dev;
- int *deviceid = devid;
- int rc;
- Time ms = GetTimeInMillis();
- rc = dixLookupDevice(&dev, *deviceid, serverClient, DixSendAccess);
- if (rc != Success)
- return;
- b = res;
- barrier = container_of(b, struct PointerBarrierClient, barrier);
- pbd = GetBarrierDevice(barrier, *deviceid);
- if (pbd->hit) {
- BarrierEvent ev = {
- .header = ET_Internal,
- .type =ET_BarrierLeave,
- .length = sizeof (BarrierEvent),
- .time = ms,
- .deviceid = *deviceid,
- .sourceid = 0,
- .dx = 0,
- .dy = 0,
- .root = barrier->screen->root->drawable.id,
- .window = barrier->window,
- .dt = ms - pbd->last_timestamp,
- .flags = XIBarrierPointerReleased,
- .event_id = pbd->barrier_event_id,
- .barrierid = barrier->id,
- };
- mieqEnqueue(dev, (InternalEvent *) &ev);
- }
- xorg_list_del(&pbd->entry);
- free(pbd);
- }
- void XIBarrierNewMasterDevice(ClientPtr client, int deviceid)
- {
- FindClientResourcesByType(client, PointerBarrierType, add_master_func, &deviceid);
- }
- void XIBarrierRemoveMasterDevice(ClientPtr client, int deviceid)
- {
- FindClientResourcesByType(client, PointerBarrierType, remove_master_func, &deviceid);
- }
- int
- XICreatePointerBarrier(ClientPtr client,
- xXFixesCreatePointerBarrierReq * stuff)
- {
- int err;
- struct PointerBarrierClient *barrier;
- struct PointerBarrier b;
- b.x1 = stuff->x1;
- b.x2 = stuff->x2;
- b.y1 = stuff->y1;
- b.y2 = stuff->y2;
- if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
- return BadValue;
- /* no 0-sized barriers */
- if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
- return BadValue;
- /* no infinite barriers on the wrong axis */
- if (barrier_is_horizontal(&b) && (b.y1 < 0 || b.y2 < 0))
- return BadValue;
- if (barrier_is_vertical(&b) && (b.x1 < 0 || b.x2 < 0))
- return BadValue;
- if ((err = CreatePointerBarrierClient(client, stuff, &barrier)))
- return err;
- if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
- return BadAlloc;
- return Success;
- }
- int
- XIDestroyPointerBarrier(ClientPtr client,
- xXFixesDestroyPointerBarrierReq * stuff)
- {
- int err;
- void *barrier;
- err = dixLookupResourceByType((void **) &barrier, stuff->barrier,
- PointerBarrierType, client, DixDestroyAccess);
- if (err != Success) {
- client->errorValue = stuff->barrier;
- return err;
- }
- if (CLIENT_ID(stuff->barrier) != client->index)
- return BadAccess;
- FreeResource(stuff->barrier, RT_NONE);
- 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++) {
- struct PointerBarrierDevice *pbd;
- DeviceIntPtr dev;
- CARD32 barrier_id, event_id;
- _X_UNUSED CARD32 device_id;
- barrier_id = info->barrier;
- event_id = info->eventid;
- err = dixLookupDevice(&dev, info->deviceid, client, DixReadAccess);
- if (err != Success) {
- client->errorValue = BadDevice;
- return err;
- }
- err = dixLookupResourceByType((void **) &b, barrier_id,
- PointerBarrierType, client, DixReadAccess);
- if (err != Success) {
- client->errorValue = barrier_id;
- return err;
- }
- if (CLIENT_ID(barrier_id) != client->index)
- return BadAccess;
- barrier = container_of(b, struct PointerBarrierClient, barrier);
- pbd = GetBarrierDevice(barrier, dev->id);
- if (pbd->barrier_event_id == event_id)
- pbd->release_event_id = event_id;
- }
- return Success;
- }
- Bool
- XIBarrierInit(void)
- {
- int i;
- if (!dixRegisterPrivateKey(&BarrierScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
- for (i = 0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- BarrierScreenPtr cs;
- cs = (BarrierScreenPtr) calloc(1, sizeof(BarrierScreenRec));
- if (!cs)
- return FALSE;
- xorg_list_init(&cs->barriers);
- SetBarrierScreen(pScreen, cs);
- }
- PointerBarrierType = CreateNewResourceType(BarrierFreeBarrier,
- "XIPointerBarrier");
- return PointerBarrierType;
- }
- void
- XIBarrierReset(void)
- {
- int i;
- for (i = 0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- BarrierScreenPtr cs = GetBarrierScreen(pScreen);
- free(cs);
- SetBarrierScreen(pScreen, NULL);
- }
- }
|