#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/keysym.h>
#include <X11/Xproto.h>
#include <math.h>
#include "misc.h"
#include "resource.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
#include "globals.h"
#include "dixevents.h"
#include "mipointer.h"
#include "eventstr.h"
#include "eventconvert.h"
#include "inpututils.h"
#include <X11/extensions/XKBproto.h>
#include "xkbsrv.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include <pixman.h>
#include "exglobals.h"
#include "exevents.h"
#include "exglobals.h"
#include "extnsionst.h"
#include "listdev.h"
#define MOTION_HISTORY_SIZE 256
EventListPtr InputEventList = NULL;
int InputEventListLen = 0;
int
GetEventList(EventListPtr* list)
{
*list = InputEventList;
return InputEventListLen;
}
int
GetMotionHistorySize(void)
{
return MOTION_HISTORY_SIZE;
}
void
set_button_down(DeviceIntPtr pDev, int button, int type)
{
if (type == BUTTON_PROCESSED)
SetBit(pDev->button->down, button);
else
SetBit(pDev->button->postdown, button);
}
void
set_button_up(DeviceIntPtr pDev, int button, int type)
{
if (type == BUTTON_PROCESSED)
ClearBit(pDev->button->down, button);
else
ClearBit(pDev->button->postdown, button);
}
Bool
button_is_down(DeviceIntPtr pDev, int button, int type)
{
Bool ret = FALSE;
if (type & BUTTON_PROCESSED)
ret = ret || BitIsOn(pDev->button->down, button);
if (type & BUTTON_POSTED)
ret = ret || BitIsOn(pDev->button->postdown, button);
return ret;
}
void
set_key_down(DeviceIntPtr pDev, int key_code, int type)
{
if (type == KEY_PROCESSED)
SetBit(pDev->key->down, key_code);
else
SetBit(pDev->key->postdown, key_code);
}
void
set_key_up(DeviceIntPtr pDev, int key_code, int type)
{
if (type == KEY_PROCESSED)
ClearBit(pDev->key->down, key_code);
else
ClearBit(pDev->key->postdown, key_code);
}
Bool
key_is_down(DeviceIntPtr pDev, int key_code, int type)
{
Bool ret = FALSE;
if (type & KEY_PROCESSED)
ret = ret || BitIsOn(pDev->key->down, key_code);
if (type & KEY_POSTED)
ret = ret || BitIsOn(pDev->key->postdown, key_code);
return ret;
}
static Bool
key_autorepeats(DeviceIntPtr pDev, int key_code)
{
return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
(1 << (key_code & 7)));
}
static void
init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
{
memset(event, 0, sizeof(DeviceEvent));
event->header = ET_Internal;
event->length = sizeof(DeviceEvent);
event->time = ms;
event->deviceid = dev->id;
event->sourceid = dev->id;
}
static void
init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
{
memset(event, 0, sizeof(RawDeviceEvent));
event->header = ET_Internal;
event->length = sizeof(RawDeviceEvent);
event->type = ET_RawKeyPress - ET_KeyPress + type;
event->time = ms;
event->deviceid = dev->id;
event->sourceid = dev->id;
event->detail.button = detail;
}
static void
set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
{
int i;
for (i = 0; i < valuator_mask_size(mask); i++)
{
if (valuator_mask_isset(mask, i))
{
SetBit(event->valuators.mask, i);
data[i] = valuator_mask_get(mask, i);
}
}
}
static void
set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
{
int i;
for (i = 0; i < valuator_mask_size(mask); i++)
{
if (valuator_mask_isset(mask, i))
{
SetBit(event->valuators.mask, i);
if (valuator_get_mode(dev, i) == Absolute)
SetBit(event->valuators.mode, i);
event->valuators.data[i] = valuator_mask_get(mask, i);
event->valuators.data_frac[i] =
dev->last.remainder[i] * (1 << 16) * (1 << 16);
}
else if (valuator_get_mode(dev, i) == Absolute)
event->valuators.data[i] = dev->valuator->axisVal[i];
}
}
void
CreateClassesChangedEvent(EventList* event,
DeviceIntPtr master,
DeviceIntPtr slave,
int type)
{
int i;
DeviceChangedEvent *dce;
CARD32 ms = GetTimeInMillis();
dce = (DeviceChangedEvent*)event->event;
memset(dce, 0, sizeof(DeviceChangedEvent));
dce->deviceid = slave->id;
dce->masterid = master->id;
dce->header = ET_Internal;
dce->length = sizeof(DeviceChangedEvent);
dce->type = ET_DeviceChanged;
dce->time = ms;
dce->flags = type;
dce->flags |= DEVCHANGE_SLAVE_SWITCH;
dce->sourceid = slave->id;
if (slave->button)
{
dce->buttons.num_buttons = slave->button->numButtons;
for (i = 0; i < dce->buttons.num_buttons; i++)
dce->buttons.names[i] = slave->button->labels[i];
}
if (slave->valuator)
{
dce->num_valuators = slave->valuator->numAxes;
for (i = 0; i < dce->num_valuators; i++)
{
dce->valuators[i].min = slave->valuator->axes[i].min_value;
dce->valuators[i].max = slave->valuator->axes[i].max_value;
dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
dce->valuators[i].mode = slave->valuator->axes[i].mode;
dce->valuators[i].name = slave->valuator->axes[i].label;
}
}
if (slave->key)
{
dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
}
}
static int
rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
int defmax)
{
int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
float value;
if(from && from->min_value < from->max_value) {
fmin = from->min_value;
fmax = from->max_value;
}
if(to && to->min_value < to->max_value) {
tmin = to->min_value;
tmax = to->max_value;
}
if(fmin == tmin && fmax == tmax) {
if (remainder_return)
*remainder_return = remainder;
return coord;
}
if(fmax == fmin) {
if (remainder_return)
*remainder_return = 0.0;
return 0;
}
value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
coord_return = lroundf(value);
if (remainder_return)
*remainder_return = value - coord_return;
return coord_return;
}
static void
updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
{
ScreenPtr scr = miPointerGetScreen(pDev);
int i;
DeviceIntPtr lastSlave;
pDev->last.valuators[0] = master->last.valuators[0];
pDev->last.valuators[1] = master->last.valuators[1];
if (!pDev->valuator)
return;
if(pDev->valuator->numAxes > 0)
pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
&pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
if(pDev->valuator->numAxes > 1)
pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
&pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
if ((lastSlave = master->last.slave) && lastSlave->valuator) {
for (i = 2; i < pDev->valuator->numAxes; i++) {
if (i >= lastSlave->valuator->numAxes)
pDev->last.valuators[i] = 0;
else
pDev->last.valuators[i] =
rescaleValuatorAxis(pDev->last.valuators[i],
pDev->last.remainder[i],
&pDev->last.remainder[i],
lastSlave->valuator->axes + i,
pDev->valuator->axes + i, 0);
}
}
}
void
AllocateMotionHistory(DeviceIntPtr pDev)
{
int size;
free(pDev->valuator->motion);
if (pDev->valuator->numMotionEvents < 1)
return;
if (IsMaster(pDev))
size = sizeof(INT32) * 3 * MAX_VALUATORS;
else {
ValuatorClassPtr v = pDev->valuator;
int numAxes;
for (numAxes = 0; numAxes < v->numAxes; numAxes++)
if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
break;
size = sizeof(INT32) * numAxes;
}
size += sizeof(Time);
pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
pDev->valuator->first_motion = 0;
pDev->valuator->last_motion = 0;
if (!pDev->valuator->motion)
ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
pDev->name, size * pDev->valuator->numMotionEvents);
}
int
GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
unsigned long stop, ScreenPtr pScreen, BOOL core)
{
char *ibuff = NULL, *obuff;
int i = 0, ret = 0;
int j, coord;
Time current;
int size;
int dflt;
AxisInfo from, *to;
INT32 *ocbuf, *icbuf;
INT16 *corebuf;
AxisInfo core_axis = {0};
if (!pDev->valuator || !pDev->valuator->numMotionEvents)
return 0;
if (core && !pScreen)
return 0;
if (IsMaster(pDev))
size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
else
size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
*buff = malloc(size * pDev->valuator->numMotionEvents);
if (!(*buff))
return 0;
obuff = (char *)*buff;
for (i = pDev->valuator->first_motion;
i != pDev->valuator->last_motion;
i = (i + 1) % pDev->valuator->numMotionEvents) {
ibuff = (char *) pDev->valuator->motion + (i * size);
memcpy(¤t, ibuff, sizeof(Time));
if (current > stop) {
return ret;
}
else if (current >= start) {
if (core)
{
memcpy(obuff, ibuff, sizeof(Time));
icbuf = (INT32*)(ibuff + sizeof(Time));
corebuf = (INT16*)(obuff + sizeof(Time));
memcpy(&from.min_value, icbuf++, sizeof(INT32));
memcpy(&from.max_value, icbuf++, sizeof(INT32));
memcpy(&coord, icbuf++, sizeof(INT32));
to = &core_axis;
to->max_value = pScreen->width;
coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
memcpy(corebuf, &coord, sizeof(INT16));
corebuf++;
memcpy(&from.min_value, icbuf++, sizeof(INT32));
memcpy(&from.max_value, icbuf++, sizeof(INT32));
memcpy(&coord, icbuf++, sizeof(INT32));
to->max_value = pScreen->height;
coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
memcpy(corebuf, &coord, sizeof(INT16));
} else if (IsMaster(pDev))
{
memcpy(obuff, ibuff, sizeof(Time));
ocbuf = (INT32*)(obuff + sizeof(Time));
icbuf = (INT32*)(ibuff + sizeof(Time));
for (j = 0; j < MAX_VALUATORS; j++)
{
if (j >= pDev->valuator->numAxes)
break;
memcpy(&from.min_value, icbuf++, sizeof(INT32));
memcpy(&from.max_value, icbuf++, sizeof(INT32));
memcpy(&coord, icbuf++, sizeof(INT32));
to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
if (j == 0 && (from.max_value < from.min_value))
from.max_value = pScreen->width;
else if (j == 1 && (from.max_value < from.min_value))
from.max_value = pScreen->height;
if (j == 0 && (to->max_value < to->min_value))
dflt = pScreen->width;
else if (j == 1 && (to->max_value < to->min_value))
dflt = pScreen->height;
else
dflt = 0;
coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
memcpy(ocbuf, &coord, sizeof(INT32));
ocbuf++;
}
} else
memcpy(obuff, ibuff, size);
if (core)
obuff += sizeof(INT32) + sizeof(Time);
else
obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
ret++;
}
}
return ret;
}
static void
updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
int *valuators)
{
char *buff = (char *) pDev->valuator->motion;
ValuatorClassPtr v;
int i;
if (!pDev->valuator->numMotionEvents)
return;
v = pDev->valuator;
if (IsMaster(pDev))
{
buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
v->last_motion;
memcpy(buff, &ms, sizeof(Time));
buff += sizeof(Time);
memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
for (i = 0; i < v->numAxes; i++)
{
if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
break;
if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
{
buff += 3 * sizeof(INT32);
continue;
}
memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
buff += sizeof(INT32);
memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
buff += sizeof(INT32);
memcpy(buff, &valuators[i], sizeof(INT32));
buff += sizeof(INT32);
}
} else
{
buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
pDev->valuator->last_motion;
memcpy(buff, &ms, sizeof(Time));
buff += sizeof(Time);
memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
for (i = 0; i < MAX_VALUATORS; i++)
{
if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
{
buff += sizeof(INT32);
continue;
}
memcpy(buff, &valuators[i], sizeof(INT32));
buff += sizeof(INT32);
}
}
pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
pDev->valuator->numMotionEvents;
if (pDev->valuator->first_motion == pDev->valuator->last_motion)
pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
pDev->valuator->numMotionEvents;
return;
}
int
GetMaximumEventsNum(void) {
return 3;
}
static void
clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
{
AxisInfoPtr axis;
if (axisNum >= pDev->valuator->numAxes)
return;
axis = pDev->valuator->axes + axisNum;
if (axis->max_value <= axis->min_value)
return;
if (*val < axis->min_value)
*val = axis->min_value;
if (*val > axis->max_value)
*val = axis->max_value;
}
static void
clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
{
int i;
for (i = 0; i < valuator_mask_size(mask); i++)
if (valuator_mask_isset(mask, i))
{
int val = valuator_mask_get(mask, i);
clipAxis(pDev, i, &val);
valuator_mask_set(mask, i, val);
}
}
EventListPtr
UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
{
DeviceIntPtr master;
master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD);
if (master && master->last.slave != dev)
{
CreateClassesChangedEvent(events, master, dev, type);
if (IsPointerDevice(master))
{
updateSlaveDeviceCoords(master, dev);
master->last.numValuators = dev->last.numValuators;
}
master->last.slave = dev;
(*num_events)++;
events++;
}
return events;
}
static void
moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
{
int i;
if (valuator_mask_isset(mask, 0))
*x = valuator_mask_get(mask, 0);
else
*x = dev->last.valuators[0];
if (valuator_mask_isset(mask, 1))
*y = valuator_mask_get(mask, 1);
else
*y = dev->last.valuators[1];
clipAxis(dev, 0, x);
clipAxis(dev, 1, y);
for (i = 2; i < valuator_mask_size(mask); i++)
{
if (valuator_mask_isset(mask, i))
{
dev->last.valuators[i] = valuator_mask_get(mask, i);
clipAxis(dev, i, &dev->last.valuators[i]);
}
}
}
static void
moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
{
int i;
*x = dev->last.valuators[0];
*y = dev->last.valuators[1];
if (valuator_mask_isset(mask, 0))
*x += valuator_mask_get(mask, 0);
if (valuator_mask_isset(mask, 1))
*y += valuator_mask_get(mask, 1);
if(dev->u.master && dev->valuator) {
if (valuator_get_mode(dev, 0) == Absolute)
clipAxis(dev, 0, x);
if (valuator_get_mode(dev, 1) == Absolute)
clipAxis(dev, 1, y);
}
for (i = 2; i < valuator_mask_size(mask); i++)
{
if (valuator_mask_isset(mask, i))
{
dev->last.valuators[i] += valuator_mask_get(mask, i);
if (valuator_get_mode(dev, i) == Absolute)
clipAxis(dev, i, &dev->last.valuators[i]);
valuator_mask_set(mask, i, dev->last.valuators[i]);
}
}
}
static void
accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
{
if (dev->valuator->accelScheme.AccelSchemeProc)
dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
}
static void
positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
{
int old_screenx, old_screeny;
if (dev->valuator && dev->valuator->numAxes > 0) {
*screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
dev->valuator->axes + 0, NULL, scr->width);
} else {
*screenx = dev->last.valuators[0];
*screenx_frac = dev->last.remainder[0];
}
if (dev->valuator && dev->valuator->numAxes > 1) {
*screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
dev->valuator->axes + 1, NULL, scr->height);
} else {
*screeny = dev->last.valuators[1];
*screeny_frac = dev->last.remainder[1];
}
if (*screenx <= 0 && *screenx_frac < 0.0f)
{
*screenx_frac = 0.0f;
x_frac = 0.0f;
}
if (*screeny <= 0 && *screeny_frac < 0.0f)
{
*screeny_frac = 0.0f;
y_frac = 0.0f;
}
old_screenx = *screenx;
old_screeny = *screeny;
miPointerSetPosition(dev, screenx, screeny);
if (dev->u.master) {
dev->u.master->last.valuators[0] = *screenx;
dev->u.master->last.valuators[1] = *screeny;
dev->u.master->last.remainder[0] = *screenx_frac;
dev->u.master->last.remainder[1] = *screeny_frac;
}
if (dev->valuator)
{
if(*screenx != old_screenx)
{
scr = miPointerGetScreen(dev);
*x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
dev->valuator->axes + 0, scr->width);
}
if(*screeny != old_screeny)
{
scr = miPointerGetScreen(dev);
*y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
dev->valuator->axes + 1, scr->height);
}
}
dev->last.valuators[0] = *x;
dev->last.valuators[1] = *y;
dev->last.remainder[0] = x_frac;
dev->last.remainder[1] = y_frac;
}
static void
updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
{
if (!dev->valuator)
return;
updateMotionHistory(dev, ms, mask, dev->last.valuators);
if (dev->u.master)
{
DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
updateMotionHistory(master, ms, mask, dev->last.valuators);
}
}
int
GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
ValuatorMask mask;
valuator_mask_zero(&mask);
return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
}
int
GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
int key_code, const ValuatorMask *mask_in) {
int num_events = 0;
CARD32 ms = 0;
DeviceEvent *event;
RawDeviceEvent *raw;
ValuatorMask mask;
if (!pDev->enabled)
return 0;
if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
(type != KeyPress && type != KeyRelease) ||
(key_code < 8 || key_code > 255))
return 0;
num_events = 1;
events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
if (!pDev->kbdfeed->ctrl.autoRepeat ||
!key_autorepeats(pDev, key_code) ||
pDev->key->xkbInfo->desc->map->modmap[key_code])
return 0;
}
ms = GetTimeInMillis();
raw = (RawDeviceEvent*)events->event;
events++;
num_events++;
valuator_mask_copy(&mask, mask_in);
init_raw(pDev, raw, ms, type, key_code);
set_raw_valuators(raw, &mask, raw->valuators.data_raw);
clipValuators(pDev, &mask);
set_raw_valuators(raw, &mask, raw->valuators.data);
event = (DeviceEvent*) events->event;
init_event(pDev, event, ms);
event->detail.key = key_code;
if (type == KeyPress) {
event->type = ET_KeyPress;
set_key_down(pDev, key_code, KEY_POSTED);
}
else if (type == KeyRelease) {
event->type = ET_KeyRelease;
set_key_up(pDev, key_code, KEY_POSTED);
}
clipValuators(pDev, &mask);
set_valuators(pDev, event, &mask);
return num_events;
}
EventListPtr
InitEventList(int num_events)
{
EventListPtr events;
int i;
events = (EventListPtr)calloc(num_events, sizeof(EventList));
if (!events)
return NULL;
for (i = 0; i < num_events; i++)
{
events[i].evlen = sizeof(InternalEvent);
events[i].event = calloc(1, sizeof(InternalEvent));
if (!events[i].event)
{
while(i--)
free(events[i].event);
free(events);
events = NULL;
break;
}
}
return events;
}
void
FreeEventList(EventListPtr list, int num_events)
{
if (!list)
return;
while(num_events--)
free(list[num_events].event);
free(list);
}
static void
transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
{
struct pixman_f_vector p;
p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
dev->last.valuators[0]);
p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
dev->last.valuators[1]);
p.v[2] = 1.0;
pixman_f_transform_point(&dev->transform, &p);
if (valuator_mask_isset(mask, 0))
valuator_mask_set(mask, 0, lround(p.v[0]));
if (valuator_mask_isset(mask, 1))
valuator_mask_set(mask, 1, lround(p.v[1]));
}
int
GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
int flags, const ValuatorMask *mask_in) {
int num_events = 1;
CARD32 ms;
DeviceEvent *event;
RawDeviceEvent *raw;
int x = 0, y = 0,
cx, cy;
float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
ScreenPtr scr = miPointerGetScreen(pDev);
ValuatorMask mask;
if (!pDev->enabled)
return 0;
if (!scr)
return 0;
switch (type)
{
case MotionNotify:
if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
return 0;
break;
case ButtonPress:
case ButtonRelease:
if (!pDev->button || !buttons)
return 0;
break;
default:
return 0;
}
ms = GetTimeInMillis();
events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
valuator_mask_copy(&mask, mask_in);
if ((flags & POINTER_NORAW) == 0)
{
raw = (RawDeviceEvent*)events->event;
events++;
num_events++;
init_raw(pDev, raw, ms, type, buttons);
set_raw_valuators(raw, &mask, raw->valuators.data_raw);
}
if (flags & POINTER_ABSOLUTE)
{
if (flags & POINTER_SCREEN)
{
int scaled;
if (valuator_mask_isset(&mask, 0))
{
scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
0.0, &x_frac, NULL,
pDev->valuator->axes + 0,
scr->width);
valuator_mask_set(&mask, 0, scaled);
}
if (valuator_mask_isset(&mask, 1))
{
scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
0.0, &y_frac, NULL,
pDev->valuator->axes + 1,
scr->height);
valuator_mask_set(&mask, 1, scaled);
}
}
transformAbsolute(pDev, &mask);
moveAbsolute(pDev, &x, &y, &mask);
} else {
if (flags & POINTER_ACCELERATE) {
int vals[2];
vals[0] = valuator_mask_isset(&mask, 0) ?
valuator_mask_get(&mask, 0) : 0;
vals[1] = valuator_mask_isset(&mask, 1) ?
valuator_mask_get(&mask, 1) : 0;
accelPointer(pDev, 0, 2, vals, ms);
if (valuator_mask_isset(&mask, 0))
valuator_mask_set(&mask, 0, vals[0]);
if (valuator_mask_isset(&mask, 1))
valuator_mask_set(&mask, 1, vals[1]);
x_frac = pDev->last.remainder[0];
y_frac = pDev->last.remainder[1];
}
moveRelative(pDev, &x, &y, &mask);
}
if ((flags & POINTER_NORAW) == 0)
set_raw_valuators(raw, &mask, raw->valuators.data);
positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
updateHistory(pDev, &mask, ms);
if (valuator_mask_isset(&mask, 0))
valuator_mask_set(&mask, 0, x);
if (valuator_mask_isset(&mask, 1))
valuator_mask_set(&mask, 1, y);
clipValuators(pDev, &mask);
event = (DeviceEvent*) events->event;
init_event(pDev, event, ms);
if (type == MotionNotify) {
event->type = ET_Motion;
event->detail.button = 0;
}
else {
if (type == ButtonPress) {
event->type = ET_ButtonPress;
set_button_down(pDev, buttons, BUTTON_POSTED);
}
else if (type == ButtonRelease) {
event->type = ET_ButtonRelease;
set_button_up(pDev, buttons, BUTTON_POSTED);
}
event->detail.button = buttons;
}
event->root_x = cx;
event->root_y = cy;
event->root_x_frac = cx_frac;
event->root_y_frac = cy_frac;
set_valuators(pDev, event, &mask);
return num_events;
}
int
GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
{
int num_events = 1, i;
DeviceEvent *event;
ValuatorMask mask;
if (!pDev->enabled)
return 0;
if ((type != ProximityIn && type != ProximityOut) || !mask_in)
return 0;
if (!pDev->valuator)
return 0;
valuator_mask_copy(&mask, mask_in);
for (i = 0; i < valuator_mask_size(&mask); i++)
{
if (valuator_mask_isset(&mask, i) &&
valuator_get_mode(pDev, i) == Relative)
valuator_mask_unset(&mask, i);
}
events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
event = (DeviceEvent *) events->event;
init_event(pDev, event, GetTimeInMillis());
event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
clipValuators(pDev, &mask);
set_valuators(pDev, event, &mask);
return num_events;
}
void
PostSyntheticMotion(DeviceIntPtr pDev,
int x,
int y,
int screen,
unsigned long time)
{
DeviceEvent ev;
#ifdef PANORAMIX
if (!noPanoramiXExtension) {
x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
}
#endif
memset(&ev, 0, sizeof(DeviceEvent));
init_event(pDev, &ev, time);
ev.root_x = x;
ev.root_y = y;
ev.type = ET_Motion;
ev.time = time;
(*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
}