Merge remote-tracking branch 'whot/barriers'
Conflicts: Xi/xichangehierarchy.c Small conflict with the patch from Xi: don't use devices after removing them Was easily resolved by hand. Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
commit
014a5c8a9d
|
@ -78,6 +78,8 @@ libXi_la_SOURCES = \
|
||||||
ungrdevk.h \
|
ungrdevk.h \
|
||||||
xiallowev.c \
|
xiallowev.c \
|
||||||
xiallowev.h \
|
xiallowev.h \
|
||||||
|
xibarriers.c \
|
||||||
|
xibarriers.h \
|
||||||
xichangecursor.c \
|
xichangecursor.c \
|
||||||
xichangecursor.h \
|
xichangecursor.h \
|
||||||
xichangehierarchy.c \
|
xichangehierarchy.c \
|
||||||
|
|
|
@ -1648,6 +1648,49 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
|
||||||
UpdateDeviceState(dev, &ev->device_event);
|
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;
|
||||||
|
GrabPtr grab = dev->deviceGrab.grab;
|
||||||
|
|
||||||
|
if (!IsMaster(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (grab)
|
||||||
|
be->flags |= XIBarrierDeviceIsGrabbed;
|
||||||
|
|
||||||
|
rc = EventToXI2(e, &ev);
|
||||||
|
if (rc != Success) {
|
||||||
|
ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A client has a grab, deliver to this client if the grab_window is the
|
||||||
|
barrier window.
|
||||||
|
|
||||||
|
Otherwise, deliver normally to the client.
|
||||||
|
*/
|
||||||
|
if (grab &&
|
||||||
|
CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
|
||||||
|
grab->window->drawable.id == be->window) {
|
||||||
|
DeliverGrabbedEvent(e, dev, FALSE);
|
||||||
|
} else {
|
||||||
|
filter = GetEventFilter(dev, ev);
|
||||||
|
|
||||||
|
DeliverEventsToWindow(dev, pWin, ev, 1,
|
||||||
|
filter, NullGrab);
|
||||||
|
}
|
||||||
|
free(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process DeviceEvents and DeviceChangedEvents.
|
* Process DeviceEvents and DeviceChangedEvents.
|
||||||
*/
|
*/
|
||||||
|
@ -1797,6 +1840,10 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
|
||||||
case ET_TouchEnd:
|
case ET_TouchEnd:
|
||||||
ProcessTouchEvent(ev, device);
|
ProcessTouchEvent(ev, device);
|
||||||
break;
|
break;
|
||||||
|
case ET_BarrierHit:
|
||||||
|
case ET_BarrierLeave:
|
||||||
|
ProcessBarrierEvent(ev, device);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ProcessDeviceEvent(ev, device);
|
ProcessDeviceEvent(ev, device);
|
||||||
break;
|
break;
|
||||||
|
|
41
Xi/extinit.c
41
Xi/extinit.c
|
@ -122,6 +122,7 @@ SOFTWARE.
|
||||||
#include "xiqueryversion.h"
|
#include "xiqueryversion.h"
|
||||||
#include "xisetclientpointer.h"
|
#include "xisetclientpointer.h"
|
||||||
#include "xiwarppointer.h"
|
#include "xiwarppointer.h"
|
||||||
|
#include "xibarriers.h"
|
||||||
|
|
||||||
/* Masks for XI events have to be aligned with core event (partially anyway).
|
/* Masks for XI events have to be aligned with core event (partially anyway).
|
||||||
* If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
|
* If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
|
||||||
|
@ -251,7 +252,8 @@ static int (*ProcIVector[]) (ClientPtr) = {
|
||||||
ProcXIChangeProperty, /* 57 */
|
ProcXIChangeProperty, /* 57 */
|
||||||
ProcXIDeleteProperty, /* 58 */
|
ProcXIDeleteProperty, /* 58 */
|
||||||
ProcXIGetProperty, /* 59 */
|
ProcXIGetProperty, /* 59 */
|
||||||
ProcXIGetSelectedEvents /* 60 */
|
ProcXIGetSelectedEvents, /* 60 */
|
||||||
|
ProcXIBarrierReleasePointer /* 61 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* For swapped clients */
|
/* For swapped clients */
|
||||||
|
@ -316,7 +318,8 @@ static int (*SProcIVector[]) (ClientPtr) = {
|
||||||
SProcXIChangeProperty, /* 57 */
|
SProcXIChangeProperty, /* 57 */
|
||||||
SProcXIDeleteProperty, /* 58 */
|
SProcXIDeleteProperty, /* 58 */
|
||||||
SProcXIGetProperty, /* 59 */
|
SProcXIGetProperty, /* 59 */
|
||||||
SProcXIGetSelectedEvents /* 60 */
|
SProcXIGetSelectedEvents, /* 60 */
|
||||||
|
SProcXIBarrierReleasePointer /* 61 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
|
@ -839,6 +842,32 @@ STouchOwnershipEvent(xXITouchOwnershipEvent * from, xXITouchOwnershipEvent * to)
|
||||||
swapl(&to->child);
|
swapl(&to->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SBarrierEvent(xXIBarrierEvent * from,
|
||||||
|
xXIBarrierEvent * to) {
|
||||||
|
|
||||||
|
*to = *from;
|
||||||
|
|
||||||
|
swaps(&from->sequenceNumber);
|
||||||
|
swapl(&from->length);
|
||||||
|
swaps(&from->evtype);
|
||||||
|
swapl(&from->time);
|
||||||
|
swaps(&from->deviceid);
|
||||||
|
swaps(&from->sourceid);
|
||||||
|
swapl(&from->event);
|
||||||
|
swapl(&from->root);
|
||||||
|
swapl(&from->root_x);
|
||||||
|
swapl(&from->root_y);
|
||||||
|
|
||||||
|
swapl(&from->dx.integral);
|
||||||
|
swapl(&from->dx.frac);
|
||||||
|
swapl(&from->dy.integral);
|
||||||
|
swapl(&from->dy.frac);
|
||||||
|
swapl(&from->dtime);
|
||||||
|
swapl(&from->barrier);
|
||||||
|
swapl(&from->eventid);
|
||||||
|
}
|
||||||
|
|
||||||
/** Event swapping function for XI2 events. */
|
/** Event swapping function for XI2 events. */
|
||||||
void
|
void
|
||||||
XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
|
XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
|
||||||
|
@ -885,6 +914,11 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
|
||||||
case XI_RawTouchEnd:
|
case XI_RawTouchEnd:
|
||||||
SRawEvent((xXIRawEvent *) from, (xXIRawEvent *) to);
|
SRawEvent((xXIRawEvent *) from, (xXIRawEvent *) to);
|
||||||
break;
|
break;
|
||||||
|
case XI_BarrierHit:
|
||||||
|
case XI_BarrierLeave:
|
||||||
|
SBarrierEvent((xXIBarrierEvent *) from,
|
||||||
|
(xXIBarrierEvent *) to);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
|
ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
|
||||||
break;
|
break;
|
||||||
|
@ -1263,6 +1297,9 @@ XInputExtensionInit(void)
|
||||||
if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
|
if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
|
||||||
FatalError("Failed to add callback to XI.\n");
|
FatalError("Failed to add callback to XI.\n");
|
||||||
|
|
||||||
|
if (!XIBarrierInit())
|
||||||
|
FatalError("Could not initialize barriers.\n");
|
||||||
|
|
||||||
extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
|
extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
|
||||||
SProcIDispatch, IResetProc, StandardMinorOpcode);
|
SProcIDispatch, IResetProc, StandardMinorOpcode);
|
||||||
if (extEntry) {
|
if (extEntry) {
|
||||||
|
|
|
@ -0,0 +1,916 @@
|
||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
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);
|
||||||
|
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 = 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(pointer res, XID id, pointer 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(pointer res, XID id, pointer 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;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
#ifdef HAVE_DIX_CONFIG_H
|
||||||
|
#include <dix-config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _XIBARRIERS_H_
|
||||||
|
#define _XIBARRIERS_H_
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
extern _X_EXPORT RESTYPE PointerBarrierType;
|
||||||
|
|
||||||
|
struct PointerBarrier {
|
||||||
|
INT16 x1, x2, y1, y2;
|
||||||
|
CARD32 directions;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
barrier_get_direction(int, int, int, int);
|
||||||
|
BOOL
|
||||||
|
barrier_is_blocking(const struct PointerBarrier *, int, int, int, int,
|
||||||
|
double *);
|
||||||
|
BOOL
|
||||||
|
barrier_is_blocking_direction(const struct PointerBarrier *, int);
|
||||||
|
void
|
||||||
|
barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
|
||||||
|
int *y);
|
||||||
|
|
||||||
|
#include <xfixesint.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
XICreatePointerBarrier(ClientPtr client,
|
||||||
|
xXFixesCreatePointerBarrierReq * stuff);
|
||||||
|
|
||||||
|
int
|
||||||
|
XIDestroyPointerBarrier(ClientPtr client,
|
||||||
|
xXFixesDestroyPointerBarrierReq * stuff);
|
||||||
|
|
||||||
|
Bool
|
||||||
|
XIBarrierInit(void);
|
||||||
|
|
||||||
|
int SProcXIBarrierReleasePointer(ClientPtr client);
|
||||||
|
int ProcXIBarrierReleasePointer(ClientPtr client);
|
||||||
|
|
||||||
|
void XIBarrierNewMasterDevice(ClientPtr client, int deviceid);
|
||||||
|
void XIBarrierRemoveMasterDevice(ClientPtr client, int deviceid);
|
||||||
|
|
||||||
|
#endif /* _XIBARRIERS_H_ */
|
|
@ -52,6 +52,7 @@
|
||||||
#include "xkbsrv.h"
|
#include "xkbsrv.h"
|
||||||
|
|
||||||
#include "xichangehierarchy.h"
|
#include "xichangehierarchy.h"
|
||||||
|
#include "xibarriers.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the current state of the device hierarchy to all clients.
|
* Send the current state of the device hierarchy to all clients.
|
||||||
|
@ -189,6 +190,8 @@ add_master(ClientPtr client, xXIAddMasterInfo * c, int flags[MAXDEVICES])
|
||||||
flags[XTestptr->id] |= XISlaveAttached;
|
flags[XTestptr->id] |= XISlaveAttached;
|
||||||
flags[XTestkeybd->id] |= XISlaveAttached;
|
flags[XTestkeybd->id] |= XISlaveAttached;
|
||||||
|
|
||||||
|
XIBarrierNewMasterDevice(client, ptr->id);
|
||||||
|
|
||||||
unwind:
|
unwind:
|
||||||
free(name);
|
free(name);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -293,6 +296,8 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XIBarrierRemoveMasterDevice(client, ptr->id);
|
||||||
|
|
||||||
/* disable the remove the devices, XTest devices must be done first
|
/* disable the remove the devices, XTest devices must be done first
|
||||||
else the sprites they rely on will be destroyed */
|
else the sprites they rely on will be destroyed */
|
||||||
DisableDevice(XTestptr, FALSE);
|
DisableDevice(XTestptr, FALSE);
|
||||||
|
|
|
@ -788,7 +788,7 @@ XPROTO="xproto >= 7.0.22"
|
||||||
RANDRPROTO="randrproto >= 1.4.0"
|
RANDRPROTO="randrproto >= 1.4.0"
|
||||||
RENDERPROTO="renderproto >= 0.11"
|
RENDERPROTO="renderproto >= 0.11"
|
||||||
XEXTPROTO="xextproto >= 7.1.99"
|
XEXTPROTO="xextproto >= 7.1.99"
|
||||||
INPUTPROTO="inputproto >= 2.1.99.6"
|
INPUTPROTO="inputproto >= 2.2.99.1"
|
||||||
KBPROTO="kbproto >= 1.0.3"
|
KBPROTO="kbproto >= 1.0.3"
|
||||||
FONTSPROTO="fontsproto"
|
FONTSPROTO="fontsproto"
|
||||||
FIXESPROTO="fixesproto >= 5.0"
|
FIXESPROTO="fixesproto >= 5.0"
|
||||||
|
|
|
@ -57,6 +57,7 @@ static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count);
|
||||||
static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
|
static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
|
||||||
static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
|
static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
|
||||||
static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
|
static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
|
||||||
|
static int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi);
|
||||||
static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
|
static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
|
||||||
|
|
||||||
/* Do not use, read comments below */
|
/* Do not use, read comments below */
|
||||||
|
@ -160,6 +161,8 @@ EventToCore(InternalEvent *event, xEvent **core_out, int *count_out)
|
||||||
case ET_TouchUpdate:
|
case ET_TouchUpdate:
|
||||||
case ET_TouchEnd:
|
case ET_TouchEnd:
|
||||||
case ET_TouchOwnership:
|
case ET_TouchOwnership:
|
||||||
|
case ET_BarrierHit:
|
||||||
|
case ET_BarrierLeave:
|
||||||
ret = BadMatch;
|
ret = BadMatch;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -216,6 +219,8 @@ EventToXI(InternalEvent *ev, xEvent **xi, int *count)
|
||||||
case ET_TouchUpdate:
|
case ET_TouchUpdate:
|
||||||
case ET_TouchEnd:
|
case ET_TouchEnd:
|
||||||
case ET_TouchOwnership:
|
case ET_TouchOwnership:
|
||||||
|
case ET_BarrierHit:
|
||||||
|
case ET_BarrierLeave:
|
||||||
*count = 0;
|
*count = 0;
|
||||||
*xi = NULL;
|
*xi = NULL;
|
||||||
return BadMatch;
|
return BadMatch;
|
||||||
|
@ -277,6 +282,9 @@ EventToXI2(InternalEvent *ev, xEvent **xi)
|
||||||
case ET_RawTouchUpdate:
|
case ET_RawTouchUpdate:
|
||||||
case ET_RawTouchEnd:
|
case ET_RawTouchEnd:
|
||||||
return eventToRawEvent(&ev->raw_event, xi);
|
return eventToRawEvent(&ev->raw_event, xi);
|
||||||
|
case ET_BarrierHit:
|
||||||
|
case ET_BarrierLeave:
|
||||||
|
return eventToBarrierEvent(&ev->barrier_event, xi);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -782,6 +790,35 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
|
||||||
return Success;
|
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
|
* Return the corresponding core type for the given event or 0 if no core
|
||||||
* equivalent exists.
|
* equivalent exists.
|
||||||
|
@ -929,6 +966,12 @@ GetXI2Type(enum EventType type)
|
||||||
case ET_TouchOwnership:
|
case ET_TouchOwnership:
|
||||||
xi2type = XI_TouchOwnership;
|
xi2type = XI_TouchOwnership;
|
||||||
break;
|
break;
|
||||||
|
case ET_BarrierHit:
|
||||||
|
xi2type = XI_BarrierHit;
|
||||||
|
break;
|
||||||
|
case ET_BarrierLeave:
|
||||||
|
xi2type = XI_BarrierLeave;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
24
dix/events.c
24
dix/events.c
|
@ -219,6 +219,9 @@ static void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
|
||||||
static void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
|
static void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
|
||||||
Bool generateEvents, Bool confineToScreen,
|
Bool generateEvents, Bool confineToScreen,
|
||||||
ScreenPtr pScreen);
|
ScreenPtr pScreen);
|
||||||
|
static Bool IsWrongPointerBarrierClient(ClientPtr client,
|
||||||
|
DeviceIntPtr dev,
|
||||||
|
xEvent *event);
|
||||||
|
|
||||||
/** Key repeat hack. Do not use but in TryClientEvents */
|
/** Key repeat hack. Do not use but in TryClientEvents */
|
||||||
extern BOOL EventIsKeyRepeat(xEvent *event);
|
extern BOOL EventIsKeyRepeat(xEvent *event);
|
||||||
|
@ -2092,6 +2095,9 @@ DeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
|
||||||
if (IsInterferingGrab(client, dev, events))
|
if (IsInterferingGrab(client, dev, events))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (IsWrongPointerBarrierClient(client, dev, events))
|
||||||
|
continue;
|
||||||
|
|
||||||
mask = GetEventMask(dev, events, inputclients);
|
mask = GetEventMask(dev, events, inputclients);
|
||||||
|
|
||||||
if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
|
if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
|
||||||
|
@ -2446,6 +2452,8 @@ FixUpEventFromWindow(SpritePtr pSprite,
|
||||||
case XI_DeviceChanged:
|
case XI_DeviceChanged:
|
||||||
case XI_HierarchyChanged:
|
case XI_HierarchyChanged:
|
||||||
case XI_PropertyEvent:
|
case XI_PropertyEvent:
|
||||||
|
case XI_BarrierHit:
|
||||||
|
case XI_BarrierLeave:
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -6080,3 +6088,19 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PointerBarrier events are only delivered to the client that created that
|
||||||
|
* barrier */
|
||||||
|
static Bool
|
||||||
|
IsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
|
||||||
|
{
|
||||||
|
xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
|
||||||
|
|
||||||
|
if (ev->type != GenericEvent || ev->extension != IReqCode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return client->index != CLIENT_ID(ev->barrier);
|
||||||
|
}
|
||||||
|
|
|
@ -916,10 +916,13 @@ scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
|
||||||
* @param[in,out] devy y desktop-wide coordinate in device coordinate system
|
* @param[in,out] devy y desktop-wide coordinate in device coordinate system
|
||||||
* @param[in,out] screenx x coordinate in desktop coordinate system
|
* @param[in,out] screenx x coordinate in desktop coordinate system
|
||||||
* @param[in,out] screeny y coordinate in desktop coordinate system
|
* @param[in,out] screeny y coordinate in desktop coordinate system
|
||||||
|
* @param[out] nevents Number of barrier events added to events
|
||||||
|
* @param[in,out] events List of events barrier events are added to
|
||||||
*/
|
*/
|
||||||
static ScreenPtr
|
static ScreenPtr
|
||||||
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
||||||
double *devx, double *devy, double *screenx, double *screeny)
|
double *devx, double *devy, double *screenx, double *screeny,
|
||||||
|
int *nevents, InternalEvent* events)
|
||||||
{
|
{
|
||||||
ScreenPtr scr = miPointerGetScreen(dev);
|
ScreenPtr scr = miPointerGetScreen(dev);
|
||||||
double tmpx, tmpy;
|
double tmpx, tmpy;
|
||||||
|
@ -933,7 +936,7 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
|
||||||
/* miPointerSetPosition takes care of crossing screens for us, as well as
|
/* miPointerSetPosition takes care of crossing screens for us, as well as
|
||||||
* clipping to the current screen. Coordinates returned are in desktop
|
* clipping to the current screen. Coordinates returned are in desktop
|
||||||
* coord system */
|
* coord system */
|
||||||
scr = miPointerSetPosition(dev, mode, screenx, screeny);
|
scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events);
|
||||||
|
|
||||||
/* If we were constrained, rescale x/y from the screen coordinates so
|
/* If we were constrained, rescale x/y from the screen coordinates so
|
||||||
* the device valuators reflect the correct position. For screen
|
* the device valuators reflect the correct position. For screen
|
||||||
|
@ -1319,6 +1322,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
||||||
int sx, sy; /* for POINTER_SCREEN */
|
int sx, sy; /* for POINTER_SCREEN */
|
||||||
ValuatorMask mask;
|
ValuatorMask mask;
|
||||||
ScreenPtr scr;
|
ScreenPtr scr;
|
||||||
|
int num_barrier_events = 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
|
@ -1395,7 +1399,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
||||||
}
|
}
|
||||||
|
|
||||||
scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
|
scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
|
||||||
&mask, &devx, &devy, &screenx, &screeny);
|
&mask, &devx, &devy, &screenx, &screeny,
|
||||||
|
&num_barrier_events, events);
|
||||||
|
num_events += num_barrier_events;
|
||||||
|
events += num_barrier_events;
|
||||||
|
|
||||||
/* screenx, screeny are in desktop coordinates,
|
/* screenx, screeny are in desktop coordinates,
|
||||||
mask is in device coordinates per-screen (the event data)
|
mask is in device coordinates per-screen (the event data)
|
||||||
|
@ -1945,7 +1952,7 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
|
||||||
scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny);
|
scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny);
|
||||||
if (emulate_pointer)
|
if (emulate_pointer)
|
||||||
scr = positionSprite(dev, Absolute, &mask,
|
scr = positionSprite(dev, Absolute, &mask,
|
||||||
&devx, &devy, &screenx, &screeny);
|
&devx, &devy, &screenx, &screeny, NULL, NULL);
|
||||||
|
|
||||||
/* see fill_pointer_events for coordinate systems */
|
/* see fill_pointer_events for coordinate systems */
|
||||||
if (emulate_pointer)
|
if (emulate_pointer)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
typedef struct _DeviceEvent DeviceEvent;
|
typedef struct _DeviceEvent DeviceEvent;
|
||||||
typedef struct _DeviceChangedEvent DeviceChangedEvent;
|
typedef struct _DeviceChangedEvent DeviceChangedEvent;
|
||||||
typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
|
typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
|
||||||
|
typedef struct _BarrierEvent BarrierEvent;
|
||||||
|
|
||||||
#if XFreeXDGA
|
#if XFreeXDGA
|
||||||
typedef struct _DGAEvent DGAEvent;
|
typedef struct _DGAEvent DGAEvent;
|
||||||
|
|
|
@ -72,6 +72,8 @@ enum EventType {
|
||||||
ET_RawTouchUpdate,
|
ET_RawTouchUpdate,
|
||||||
ET_RawTouchEnd,
|
ET_RawTouchEnd,
|
||||||
ET_XQuartz,
|
ET_XQuartz,
|
||||||
|
ET_BarrierHit,
|
||||||
|
ET_BarrierLeave,
|
||||||
ET_Internal = 0xFF /* First byte */
|
ET_Internal = 0xFF /* First byte */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,7 +132,7 @@ struct _DeviceEvent {
|
||||||
*/
|
*/
|
||||||
struct _TouchOwnershipEvent {
|
struct _TouchOwnershipEvent {
|
||||||
unsigned char header; /**< Always ET_Internal */
|
unsigned char header; /**< Always ET_Internal */
|
||||||
enum EventType type; /**< One of EventType */
|
enum EventType type; /**< ET_TouchOwnership */
|
||||||
int length; /**< Length in bytes */
|
int length; /**< Length in bytes */
|
||||||
Time time; /**< Time in ms */
|
Time time; /**< Time in ms */
|
||||||
int deviceid; /**< Device to post this event for */
|
int deviceid; /**< Device to post this event for */
|
||||||
|
@ -227,6 +229,25 @@ struct _RawDeviceEvent {
|
||||||
uint32_t flags; /**< Flags to be copied into the generated event */
|
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
|
#ifdef XQUARTZ
|
||||||
#define XQUARTZ_EVENT_MAXARGS 5
|
#define XQUARTZ_EVENT_MAXARGS 5
|
||||||
struct _XQuartzEvent {
|
struct _XQuartzEvent {
|
||||||
|
@ -253,6 +274,7 @@ union _InternalEvent {
|
||||||
DeviceEvent device_event;
|
DeviceEvent device_event;
|
||||||
DeviceChangedEvent changed_event;
|
DeviceChangedEvent changed_event;
|
||||||
TouchOwnershipEvent touch_ownership_event;
|
TouchOwnershipEvent touch_ownership_event;
|
||||||
|
BarrierEvent barrier_event;
|
||||||
#if XFreeXDGA
|
#if XFreeXDGA
|
||||||
DGAEvent dga_event;
|
DGAEvent dga_event;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -678,4 +678,10 @@ extern _X_EXPORT void input_option_set_value(InputOption *opt,
|
||||||
extern _X_HIDDEN Bool point_on_screen(ScreenPtr pScreen, int x, int y);
|
extern _X_HIDDEN Bool point_on_screen(ScreenPtr pScreen, int x, int y);
|
||||||
extern _X_HIDDEN void update_desktop_dimensions(void);
|
extern _X_HIDDEN void update_desktop_dimensions(void);
|
||||||
|
|
||||||
|
extern _X_HIDDEN void input_constrain_cursor(DeviceIntPtr pDev, ScreenPtr screen,
|
||||||
|
int current_x, int current_y,
|
||||||
|
int dest_x, int dest_y,
|
||||||
|
int *out_x, int *out_y,
|
||||||
|
int *nevents, InternalEvent* events);
|
||||||
|
|
||||||
#endif /* INPUT_H */
|
#endif /* INPUT_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
|
* events to the protocol, the server will not support these events until
|
||||||
* this number here is bumped.
|
* this number here is bumped.
|
||||||
*/
|
*/
|
||||||
#define XI2LASTEVENT XI_RawTouchEnd
|
#define XI2LASTEVENT XI_BarrierLeave
|
||||||
#define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */
|
#define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -407,6 +407,10 @@ ChangeDeviceID(DeviceIntPtr dev, InternalEvent *event)
|
||||||
case ET_RawTouchUpdate:
|
case ET_RawTouchUpdate:
|
||||||
event->raw_event.deviceid = dev->id;
|
event->raw_event.deviceid = dev->id;
|
||||||
break;
|
break;
|
||||||
|
case ET_BarrierHit:
|
||||||
|
case ET_BarrierLeave:
|
||||||
|
event->barrier_event.deviceid = dev->id;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
|
ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
|
||||||
event->any.type);
|
event->any.type);
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
|
||||||
static void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
|
static void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
|
||||||
int y);
|
int y);
|
||||||
|
|
||||||
static InternalEvent *events; /* for WarpPointer MotionNotifies */
|
static InternalEvent *mipointermove_events; /* for WarpPointer MotionNotifies */
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
miPointerInitialize(ScreenPtr pScreen,
|
miPointerInitialize(ScreenPtr pScreen,
|
||||||
|
@ -143,7 +143,7 @@ miPointerInitialize(ScreenPtr pScreen,
|
||||||
pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
|
pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
|
||||||
pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
|
pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
|
||||||
|
|
||||||
events = NULL;
|
mipointermove_events = NULL;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +160,8 @@ miPointerCloseScreen(ScreenPtr pScreen)
|
||||||
|
|
||||||
pScreen->CloseScreen = pScreenPriv->CloseScreen;
|
pScreen->CloseScreen = pScreenPriv->CloseScreen;
|
||||||
free((pointer) pScreenPriv);
|
free((pointer) pScreenPriv);
|
||||||
FreeEventList(events, GetMaximumEventsNum());
|
FreeEventList(mipointermove_events, GetMaximumEventsNum());
|
||||||
events = NULL;
|
mipointermove_events = NULL;
|
||||||
return (*pScreen->CloseScreen) (pScreen);
|
return (*pScreen->CloseScreen) (pScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,13 +565,16 @@ miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
||||||
*/
|
*/
|
||||||
ScreenPtr
|
ScreenPtr
|
||||||
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
|
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
|
||||||
double *screeny)
|
double *screeny,
|
||||||
|
int *nevents, InternalEvent* events)
|
||||||
{
|
{
|
||||||
miPointerScreenPtr pScreenPriv;
|
miPointerScreenPtr pScreenPriv;
|
||||||
ScreenPtr pScreen;
|
ScreenPtr pScreen;
|
||||||
ScreenPtr newScreen;
|
ScreenPtr newScreen;
|
||||||
int x, y;
|
int x, y;
|
||||||
Bool switch_screen = FALSE;
|
Bool switch_screen = FALSE;
|
||||||
|
Bool should_constrain_barriers = FALSE;
|
||||||
|
int i;
|
||||||
|
|
||||||
miPointerPtr pPointer;
|
miPointerPtr pPointer;
|
||||||
|
|
||||||
|
@ -588,6 +591,25 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
|
||||||
x -= pScreen->x;
|
x -= pScreen->x;
|
||||||
y -= pScreen->y;
|
y -= pScreen->y;
|
||||||
|
|
||||||
|
should_constrain_barriers = (mode == Relative);
|
||||||
|
|
||||||
|
if (should_constrain_barriers) {
|
||||||
|
/* coordinates after clamped to a barrier */
|
||||||
|
int constrained_x, constrained_y;
|
||||||
|
int current_x, current_y; /* current position in per-screen coord */
|
||||||
|
|
||||||
|
current_x = MIPOINTER(pDev)->x - pScreen->y;
|
||||||
|
current_y = MIPOINTER(pDev)->y - pScreen->x;
|
||||||
|
|
||||||
|
input_constrain_cursor(pDev, pScreen,
|
||||||
|
current_x, current_y, x, y,
|
||||||
|
&constrained_x, &constrained_y,
|
||||||
|
nevents, events);
|
||||||
|
|
||||||
|
x = constrained_x;
|
||||||
|
y = constrained_y;
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_screen) {
|
if (switch_screen) {
|
||||||
pScreenPriv = GetScreenPrivate(pScreen);
|
pScreenPriv = GetScreenPrivate(pScreen);
|
||||||
if (!pPointer->confined) {
|
if (!pPointer->confined) {
|
||||||
|
@ -619,6 +641,18 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
|
||||||
if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen)
|
if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen)
|
||||||
miPointerMoveNoEvent(pDev, pScreen, x, y);
|
miPointerMoveNoEvent(pDev, pScreen, x, y);
|
||||||
|
|
||||||
|
/* check if we generated any barrier events and if so, update root x/y
|
||||||
|
* to the fully constrained coords */
|
||||||
|
if (should_constrain_barriers) {
|
||||||
|
for (i = 0; i < *nevents; i++) {
|
||||||
|
if (events[i].any.type == ET_BarrierHit ||
|
||||||
|
events[i].any.type == ET_BarrierLeave) {
|
||||||
|
events[i].barrier_event.root_x = x;
|
||||||
|
events[i].barrier_event.root_y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert to desktop coordinates again */
|
/* Convert to desktop coordinates again */
|
||||||
x += pScreen->x;
|
x += pScreen->x;
|
||||||
y += pScreen->y;
|
y += pScreen->y;
|
||||||
|
@ -676,17 +710,17 @@ miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
||||||
valuators[0] = x;
|
valuators[0] = x;
|
||||||
valuators[1] = y;
|
valuators[1] = y;
|
||||||
|
|
||||||
if (!events) {
|
if (!mipointermove_events) {
|
||||||
events = InitEventList(GetMaximumEventsNum());
|
mipointermove_events = InitEventList(GetMaximumEventsNum());
|
||||||
|
|
||||||
if (!events) {
|
if (!mipointermove_events) {
|
||||||
FatalError("Could not allocate event store.\n");
|
FatalError("Could not allocate event store.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valuator_mask_set_range(&mask, 0, 2, valuators);
|
valuator_mask_set_range(&mask, 0, 2, valuators);
|
||||||
nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
|
nevents = GetPointerEvents(mipointermove_events, pDev, MotionNotify, 0,
|
||||||
POINTER_SCREEN | POINTER_ABSOLUTE |
|
POINTER_SCREEN | POINTER_ABSOLUTE |
|
||||||
POINTER_NORAW, &mask);
|
POINTER_NORAW, &mask);
|
||||||
|
|
||||||
|
@ -695,7 +729,7 @@ miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
||||||
darwinEvents_lock();
|
darwinEvents_lock();
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < nevents; i++)
|
for (i = 0; i < nevents; i++)
|
||||||
mieqEnqueue(pDev, &events[i]);
|
mieqEnqueue(pDev, &mipointermove_events[i]);
|
||||||
#ifdef XQUARTZ
|
#ifdef XQUARTZ
|
||||||
darwinEvents_unlock();
|
darwinEvents_unlock();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -115,7 +115,8 @@ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y);
|
||||||
/* Moves the cursor to the specified position. May clip the co-ordinates:
|
/* Moves the cursor to the specified position. May clip the co-ordinates:
|
||||||
* x and y are modified in-place. */
|
* x and y are modified in-place. */
|
||||||
extern _X_EXPORT ScreenPtr
|
extern _X_EXPORT ScreenPtr
|
||||||
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *x, double *y);
|
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *x, double *y,
|
||||||
|
int *nevents, InternalEvent *events);
|
||||||
|
|
||||||
extern _X_EXPORT void
|
extern _X_EXPORT void
|
||||||
miPointerUpdateSprite(DeviceIntPtr pDev);
|
miPointerUpdateSprite(DeviceIntPtr pDev);
|
||||||
|
|
26
test/fixes.c
26
test/fixes.c
|
@ -265,6 +265,32 @@ fixes_pointer_barriers_test(void)
|
||||||
x2 = x + 100;
|
x2 = x + 100;
|
||||||
assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
|
assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
|
||||||
|
|
||||||
|
/* ray vert barrier */
|
||||||
|
barrier.x1 = x;
|
||||||
|
barrier.x2 = x;
|
||||||
|
barrier.y1 = -1;
|
||||||
|
barrier.y2 = y + 100;
|
||||||
|
|
||||||
|
/* ray barrier simple case */
|
||||||
|
y1 = y;
|
||||||
|
y2 = y;
|
||||||
|
x1 = x + 50;
|
||||||
|
x2 = x - 50;
|
||||||
|
assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
|
||||||
|
|
||||||
|
/* endpoint outside y range; should be blocked */
|
||||||
|
y1 = y - 1000;
|
||||||
|
y2 = y - 1000;
|
||||||
|
x1 = x + 50;
|
||||||
|
x2 = x - 50;
|
||||||
|
assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
|
||||||
|
|
||||||
|
/* endpoint outside y range */
|
||||||
|
y1 = y + 150;
|
||||||
|
y2 = y + 150;
|
||||||
|
x1 = x + 50;
|
||||||
|
x2 = x - 50;
|
||||||
|
assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -984,6 +984,221 @@ test_convert_XITouchOwnershipEvent(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_XIBarrierEvent(BarrierEvent *in)
|
||||||
|
{
|
||||||
|
xXIBarrierEvent *out, *swapped;
|
||||||
|
int count;
|
||||||
|
int rc;
|
||||||
|
int eventlen;
|
||||||
|
FP3232 value;
|
||||||
|
|
||||||
|
rc = EventToXI((InternalEvent*)in, (xEvent**)&out, &count);
|
||||||
|
assert(rc == BadMatch);
|
||||||
|
|
||||||
|
rc = EventToCore((InternalEvent*)in, (xEvent**)&out, &count);
|
||||||
|
assert(rc == BadMatch);
|
||||||
|
|
||||||
|
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
|
||||||
|
|
||||||
|
assert(out->type == GenericEvent);
|
||||||
|
assert(out->extension == 0); /* IReqCode defaults to 0 */
|
||||||
|
assert(out->evtype == GetXI2Type(in->type));
|
||||||
|
assert(out->time == in->time);
|
||||||
|
assert(out->deviceid == in->deviceid);
|
||||||
|
assert(out->sourceid == in->sourceid);
|
||||||
|
assert(out->barrier == in->barrierid);
|
||||||
|
assert(out->flags == in->flags);
|
||||||
|
assert(out->event == in->window);
|
||||||
|
assert(out->root == in->root);
|
||||||
|
assert(out->dtime == in->dt);
|
||||||
|
assert(out->eventid == in->event_id);
|
||||||
|
assert(out->root_x == double_to_fp1616(in->root_x));
|
||||||
|
assert(out->root_y == double_to_fp1616(in->root_y));
|
||||||
|
|
||||||
|
value = double_to_fp3232(in->dx);
|
||||||
|
assert(out->dx.integral == value.integral);
|
||||||
|
assert(out->dx.frac == value.frac);
|
||||||
|
value = double_to_fp3232(in->dy);
|
||||||
|
assert(out->dy.integral == value.integral);
|
||||||
|
assert(out->dy.frac == value.frac);
|
||||||
|
|
||||||
|
eventlen = sizeof(xEvent) + out->length * 4;
|
||||||
|
swapped = calloc(1, eventlen);
|
||||||
|
XI2EventSwap((xGenericEvent *) out, (xGenericEvent *) swapped);
|
||||||
|
|
||||||
|
swaps(&swapped->sequenceNumber);
|
||||||
|
swapl(&swapped->length);
|
||||||
|
swaps(&swapped->evtype);
|
||||||
|
swaps(&swapped->deviceid);
|
||||||
|
swapl(&swapped->time);
|
||||||
|
swapl(&swapped->eventid);
|
||||||
|
swapl(&swapped->root);
|
||||||
|
swapl(&swapped->event);
|
||||||
|
swapl(&swapped->barrier);
|
||||||
|
swapl(&swapped->dtime);
|
||||||
|
swaps(&swapped->sourceid);
|
||||||
|
swapl(&swapped->root_x);
|
||||||
|
swapl(&swapped->root_y);
|
||||||
|
swapl(&swapped->dx.integral);
|
||||||
|
swapl(&swapped->dx.frac);
|
||||||
|
swapl(&swapped->dy.integral);
|
||||||
|
swapl(&swapped->dy.frac);
|
||||||
|
|
||||||
|
assert(memcmp(swapped, out, eventlen) == 0);
|
||||||
|
|
||||||
|
free(swapped);
|
||||||
|
free(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_convert_XIBarrierEvent(void)
|
||||||
|
{
|
||||||
|
BarrierEvent in;
|
||||||
|
|
||||||
|
memset(&in, 0, sizeof(in));
|
||||||
|
in.header = ET_Internal;
|
||||||
|
in.type = ET_BarrierHit;
|
||||||
|
in.length = sizeof(in);
|
||||||
|
in.time = 0;
|
||||||
|
in.deviceid = 1;
|
||||||
|
in.sourceid = 2;
|
||||||
|
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.deviceid = 1;
|
||||||
|
while(in.deviceid & 0xFFFF) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.deviceid <<= 1;
|
||||||
|
}
|
||||||
|
in.deviceid = 0;
|
||||||
|
|
||||||
|
in.sourceid = 1;
|
||||||
|
while(in.sourceid & 0xFFFF) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.sourceid <<= 1;
|
||||||
|
}
|
||||||
|
in.sourceid = 0;
|
||||||
|
|
||||||
|
in.flags = 1;
|
||||||
|
while(in.flags) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.flags <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.barrierid = 1;
|
||||||
|
while(in.barrierid) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.barrierid <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.dt = 1;
|
||||||
|
while(in.dt) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dt <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.event_id = 1;
|
||||||
|
while(in.event_id) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.event_id <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.window = 1;
|
||||||
|
while(in.window) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.window <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.root = 1;
|
||||||
|
while(in.root) {
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pseudo-random 16 bit numbers */
|
||||||
|
in.root_x = 1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = 1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = 264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = 35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.root_x = -1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = -1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = -264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_x = -35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.root_y = 1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = 1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = 264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = 35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.root_y = -1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = -1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = -264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.root_y = -35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
/* equally pseudo-random 32 bit numbers */
|
||||||
|
in.dx = 1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = 1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = 264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = 35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = 2947813871.2342;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.dx = -1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = -1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = -264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = -35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dx = -2947813871.2342;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.dy = 1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = 1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = 264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = 35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = 2947813871.2342;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
|
||||||
|
in.dy = -1;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = -1.3;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = -264.908;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = -35638.292;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
in.dy = -2947813871.2342;
|
||||||
|
test_XIBarrierEvent(&in);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -992,6 +1207,7 @@ main(int argc, char **argv)
|
||||||
test_convert_XIDeviceEvent();
|
test_convert_XIDeviceEvent();
|
||||||
test_convert_XIDeviceChangedEvent();
|
test_convert_XIDeviceChangedEvent();
|
||||||
test_convert_XITouchOwnershipEvent();
|
test_convert_XITouchOwnershipEvent();
|
||||||
|
test_convert_XIBarrierEvent();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
432
xfixes/cursor.c
432
xfixes/cursor.c
|
@ -56,12 +56,11 @@
|
||||||
#include "windowstr.h"
|
#include "windowstr.h"
|
||||||
#include "xace.h"
|
#include "xace.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "exglobals.h"
|
#include "xibarriers.h"
|
||||||
|
|
||||||
static RESTYPE CursorClientType;
|
static RESTYPE CursorClientType;
|
||||||
static RESTYPE CursorHideCountType;
|
static RESTYPE CursorHideCountType;
|
||||||
static RESTYPE CursorWindowType;
|
static RESTYPE CursorWindowType;
|
||||||
RESTYPE PointerBarrierType;
|
|
||||||
static CursorPtr CursorCurrent[MAXDEVICES];
|
static CursorPtr CursorCurrent[MAXDEVICES];
|
||||||
|
|
||||||
static DevPrivateKeyRec CursorScreenPrivateKeyRec;
|
static DevPrivateKeyRec CursorScreenPrivateKeyRec;
|
||||||
|
@ -113,16 +112,6 @@ typedef struct _CursorHideCountRec {
|
||||||
XID resource;
|
XID resource;
|
||||||
} CursorHideCountRec;
|
} CursorHideCountRec;
|
||||||
|
|
||||||
typedef struct PointerBarrierClient *PointerBarrierClientPtr;
|
|
||||||
|
|
||||||
struct PointerBarrierClient {
|
|
||||||
ScreenPtr screen;
|
|
||||||
struct PointerBarrier barrier;
|
|
||||||
struct xorg_list entry;
|
|
||||||
int num_devices;
|
|
||||||
int *device_ids; /* num_devices */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrap DisplayCursor to catch cursor change events
|
* Wrap DisplayCursor to catch cursor change events
|
||||||
*/
|
*/
|
||||||
|
@ -130,9 +119,7 @@ struct PointerBarrierClient {
|
||||||
typedef struct _CursorScreen {
|
typedef struct _CursorScreen {
|
||||||
DisplayCursorProcPtr DisplayCursor;
|
DisplayCursorProcPtr DisplayCursor;
|
||||||
CloseScreenProcPtr CloseScreen;
|
CloseScreenProcPtr CloseScreen;
|
||||||
ConstrainCursorHarderProcPtr ConstrainCursorHarder;
|
|
||||||
CursorHideCountPtr pCursorHideCounts;
|
CursorHideCountPtr pCursorHideCounts;
|
||||||
struct xorg_list barriers;
|
|
||||||
} CursorScreenRec, *CursorScreenPtr;
|
} CursorScreenRec, *CursorScreenPtr;
|
||||||
|
|
||||||
#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
|
#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
|
||||||
|
@ -199,11 +186,9 @@ CursorCloseScreen(ScreenPtr pScreen)
|
||||||
Bool ret;
|
Bool ret;
|
||||||
_X_UNUSED CloseScreenProcPtr close_proc;
|
_X_UNUSED CloseScreenProcPtr close_proc;
|
||||||
_X_UNUSED DisplayCursorProcPtr display_proc;
|
_X_UNUSED DisplayCursorProcPtr display_proc;
|
||||||
_X_UNUSED ConstrainCursorHarderProcPtr constrain_proc;
|
|
||||||
|
|
||||||
Unwrap(cs, pScreen, CloseScreen, close_proc);
|
Unwrap(cs, pScreen, CloseScreen, close_proc);
|
||||||
Unwrap(cs, pScreen, DisplayCursor, display_proc);
|
Unwrap(cs, pScreen, DisplayCursor, display_proc);
|
||||||
Unwrap(cs, pScreen, ConstrainCursorHarder, constrain_proc);
|
|
||||||
deleteCursorHideCountsForScreen(pScreen);
|
deleteCursorHideCountsForScreen(pScreen);
|
||||||
ret = (*pScreen->CloseScreen) (pScreen);
|
ret = (*pScreen->CloseScreen) (pScreen);
|
||||||
free(cs);
|
free(cs);
|
||||||
|
@ -1013,384 +998,15 @@ CursorFreeWindow(pointer data, XID id)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
BOOL rc = FALSE;
|
|
||||||
float ua, ub, ud;
|
|
||||||
int dir = barrier_get_direction(x1, y1, x2, y2);
|
|
||||||
|
|
||||||
/* Algorithm below doesn't handle edge cases well, hence the extra
|
|
||||||
* checks. */
|
|
||||||
if (barrier_is_vertical(barrier)) {
|
|
||||||
/* handle immediate barrier adjacency, moving away */
|
|
||||||
if (dir & BarrierPositiveX && x1 == barrier->x1)
|
|
||||||
return FALSE;
|
|
||||||
if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1))
|
|
||||||
return FALSE;
|
|
||||||
/* startpoint adjacent to barrier, moving towards -> block */
|
|
||||||
if (dir & BarrierPositiveX && x1 == (barrier->x1 - 1) && y1 >= barrier->y1 && y1 <= barrier->y2) {
|
|
||||||
*distance = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (dir & BarrierNegativeX && x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) {
|
|
||||||
*distance = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* handle immediate barrier adjacency, moving away */
|
|
||||||
if (dir & BarrierPositiveY && y1 == barrier->y1)
|
|
||||||
return FALSE;
|
|
||||||
if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1))
|
|
||||||
return FALSE;
|
|
||||||
/* startpoint adjacent to barrier, moving towards -> block */
|
|
||||||
if (dir & BarrierPositiveY && y1 == (barrier->y1 - 1) && x1 >= barrier->x1 && x1 <= barrier->x2) {
|
|
||||||
*distance = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (dir & BarrierNegativeY && y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) {
|
|
||||||
*distance = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not an edge case, compute distance */
|
|
||||||
ua = 0;
|
|
||||||
ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 -
|
|
||||||
barrier->x1) * (y2 - y1);
|
|
||||||
if (ud != 0) {
|
|
||||||
ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) -
|
|
||||||
(barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud;
|
|
||||||
ub = ((x2 - x1) * (y1 - barrier->y1) -
|
|
||||||
(y2 - y1) * (x1 - barrier->x1)) / ud;
|
|
||||||
if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
|
|
||||||
ua = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ua > 0 && ua <= 1) {
|
|
||||||
double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1);
|
|
||||||
double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1);
|
|
||||||
|
|
||||||
*distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2));
|
|
||||||
rc = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 PointerBarrier *
|
|
||||||
barrier_find_nearest(CursorScreenPtr cs, DeviceIntPtr dev,
|
|
||||||
int dir,
|
|
||||||
int x1, int y1, int x2, int y2)
|
|
||||||
{
|
|
||||||
struct PointerBarrierClient *c;
|
|
||||||
struct PointerBarrier *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;
|
|
||||||
double distance;
|
|
||||||
|
|
||||||
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 = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode,
|
|
||||||
int *x, int *y)
|
|
||||||
{
|
|
||||||
CursorScreenPtr cs = GetCursorScreen(screen);
|
|
||||||
|
|
||||||
if (!xorg_list_is_empty(&cs->barriers) && !IsFloating(dev) &&
|
|
||||||
mode == Relative) {
|
|
||||||
int ox, oy;
|
|
||||||
int dir;
|
|
||||||
int i;
|
|
||||||
struct PointerBarrier *nearest = NULL;
|
|
||||||
|
|
||||||
/* where are we coming from */
|
|
||||||
miPointerGetPosition(dev, &ox, &oy);
|
|
||||||
|
|
||||||
/* 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(ox, oy, *x, *y);
|
|
||||||
|
|
||||||
#define MAX_BARRIERS 2
|
|
||||||
for (i = 0; i < MAX_BARRIERS; i++) {
|
|
||||||
nearest = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y);
|
|
||||||
if (!nearest)
|
|
||||||
break;
|
|
||||||
|
|
||||||
barrier_clamp_to_barrier(nearest, dir, x, y);
|
|
||||||
|
|
||||||
if (barrier_is_vertical(nearest)) {
|
|
||||||
dir &= ~(BarrierNegativeX | BarrierPositiveX);
|
|
||||||
ox = *x;
|
|
||||||
}
|
|
||||||
else if (barrier_is_horizontal(nearest)) {
|
|
||||||
dir &= ~(BarrierNegativeY | BarrierPositiveY);
|
|
||||||
oy = *y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cs->ConstrainCursorHarder) {
|
|
||||||
screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
|
|
||||||
screen->ConstrainCursorHarder(dev, screen, mode, x, y);
|
|
||||||
screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
|
|
||||||
xXFixesCreatePointerBarrierReq * stuff,
|
|
||||||
PointerBarrierClientPtr *client_out)
|
|
||||||
{
|
|
||||||
CursorScreenPtr cs = GetCursorScreen(screen);
|
|
||||||
int err;
|
|
||||||
int size;
|
|
||||||
int i;
|
|
||||||
CARD16 *in_devices;
|
|
||||||
struct PointerBarrierClient *ret;
|
|
||||||
|
|
||||||
size = sizeof(*ret) + sizeof(int) * stuff->num_devices;
|
|
||||||
ret = malloc(size);
|
|
||||||
|
|
||||||
*client_out = NULL;
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
return BadAlloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret->screen = screen;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret->barrier.x1 = min(stuff->x1, stuff->x2);
|
|
||||||
ret->barrier.x2 = max(stuff->x1, stuff->x2);
|
|
||||||
ret->barrier.y1 = min(stuff->y1, stuff->y2);
|
|
||||||
ret->barrier.y2 = max(stuff->y1, stuff->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:
|
|
||||||
free(ret);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ProcXFixesCreatePointerBarrier(ClientPtr client)
|
ProcXFixesCreatePointerBarrier(ClientPtr client)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
WindowPtr pWin;
|
|
||||||
struct PointerBarrierClient *barrier;
|
|
||||||
struct PointerBarrier b;
|
|
||||||
|
|
||||||
REQUEST(xXFixesCreatePointerBarrierReq);
|
REQUEST(xXFixesCreatePointerBarrierReq);
|
||||||
|
|
||||||
REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
|
REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
|
||||||
LEGAL_NEW_RESOURCE(stuff->barrier, client);
|
LEGAL_NEW_RESOURCE(stuff->barrier, client);
|
||||||
|
|
||||||
err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
|
return XICreatePointerBarrier(client, stuff);
|
||||||
if (err != Success) {
|
|
||||||
client->errorValue = stuff->window;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if ((err = CreatePointerBarrierClient(pWin->drawable.pScreen,
|
|
||||||
client, stuff, &barrier)))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
|
|
||||||
return BadAlloc;
|
|
||||||
|
|
||||||
return Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1418,49 +1034,14 @@ SProcXFixesCreatePointerBarrier(ClientPtr client)
|
||||||
return ProcXFixesVector[stuff->xfixesReqType] (client);
|
return ProcXFixesVector[stuff->xfixesReqType] (client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
CursorFreeBarrier(void *data, XID id)
|
|
||||||
{
|
|
||||||
struct PointerBarrierClient *b = NULL, *barrier;
|
|
||||||
ScreenPtr screen;
|
|
||||||
CursorScreenPtr cs;
|
|
||||||
|
|
||||||
barrier = container_of(data, struct PointerBarrierClient, barrier);
|
|
||||||
|
|
||||||
screen = barrier->screen;
|
|
||||||
cs = GetCursorScreen(screen);
|
|
||||||
|
|
||||||
/* find and unlink from the screen private */
|
|
||||||
xorg_list_for_each_entry(b, &cs->barriers, entry) {
|
|
||||||
if (b == barrier) {
|
|
||||||
xorg_list_del(&b->entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(barrier);
|
|
||||||
return Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ProcXFixesDestroyPointerBarrier(ClientPtr client)
|
ProcXFixesDestroyPointerBarrier(ClientPtr client)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
void *barrier;
|
|
||||||
|
|
||||||
REQUEST(xXFixesDestroyPointerBarrierReq);
|
REQUEST(xXFixesDestroyPointerBarrierReq);
|
||||||
|
|
||||||
REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
|
REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
|
||||||
|
|
||||||
err = dixLookupResourceByType((void **) &barrier, stuff->barrier,
|
return XIDestroyPointerBarrier(client, stuff);
|
||||||
PointerBarrierType, client, DixDestroyAccess);
|
|
||||||
if (err != Success) {
|
|
||||||
client->errorValue = stuff->barrier;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeResource(stuff->barrier, RT_NONE);
|
|
||||||
return Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1492,10 +1073,8 @@ XFixesCursorInit(void)
|
||||||
cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
|
cs = (CursorScreenPtr) calloc(1, sizeof(CursorScreenRec));
|
||||||
if (!cs)
|
if (!cs)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
xorg_list_init(&cs->barriers);
|
|
||||||
Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
|
Wrap(cs, pScreen, CloseScreen, CursorCloseScreen);
|
||||||
Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
|
Wrap(cs, pScreen, DisplayCursor, CursorDisplayCursor);
|
||||||
Wrap(cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
|
|
||||||
cs->pCursorHideCounts = NULL;
|
cs->pCursorHideCounts = NULL;
|
||||||
SetCursorScreen(pScreen, cs);
|
SetCursorScreen(pScreen, cs);
|
||||||
}
|
}
|
||||||
|
@ -1505,9 +1084,6 @@ XFixesCursorInit(void)
|
||||||
"XFixesCursorHideCount");
|
"XFixesCursorHideCount");
|
||||||
CursorWindowType = CreateNewResourceType(CursorFreeWindow,
|
CursorWindowType = CreateNewResourceType(CursorFreeWindow,
|
||||||
"XFixesCursorWindow");
|
"XFixesCursorWindow");
|
||||||
PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
|
|
||||||
"XFixesPointerBarrier");
|
|
||||||
|
|
||||||
return CursorClientType && CursorHideCountType && CursorWindowType &&
|
return CursorClientType && CursorHideCountType && CursorWindowType;
|
||||||
PointerBarrierType;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
extern _X_EXPORT RESTYPE RegionResType;
|
extern _X_EXPORT RESTYPE RegionResType;
|
||||||
extern _X_EXPORT RESTYPE PointerBarrierType;
|
|
||||||
extern _X_EXPORT int XFixesErrorBase;
|
extern _X_EXPORT int XFixesErrorBase;
|
||||||
|
|
||||||
#define VERIFY_REGION(pRegion, rid, client, mode) \
|
#define VERIFY_REGION(pRegion, rid, client, mode) \
|
||||||
|
@ -52,20 +51,6 @@ extern _X_EXPORT int XFixesErrorBase;
|
||||||
extern _X_EXPORT RegionPtr
|
extern _X_EXPORT RegionPtr
|
||||||
XFixesRegionCopy(RegionPtr pRegion);
|
XFixesRegionCopy(RegionPtr pRegion);
|
||||||
|
|
||||||
struct PointerBarrier {
|
#include "xibarriers.h"
|
||||||
CARD16 x1, x2, y1, y2;
|
|
||||||
CARD32 directions;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int
|
|
||||||
barrier_get_direction(int, int, int, int);
|
|
||||||
extern BOOL
|
|
||||||
barrier_is_blocking(const struct PointerBarrier *, int, int, int, int,
|
|
||||||
double *);
|
|
||||||
extern BOOL barrier_is_blocking_direction(const struct PointerBarrier *, int);
|
|
||||||
extern void
|
|
||||||
|
|
||||||
barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x,
|
|
||||||
int *y);
|
|
||||||
|
|
||||||
#endif /* _XFIXES_H_ */
|
#endif /* _XFIXES_H_ */
|
||||||
|
|
Loading…
Reference in New Issue