4026c63e4e
This gets rid of the nevents parameter, InternalEvents are always a single item per event. Also remove the special DeviceValuator handling in both enqueueing and dequeueing. Custom callback handlers are now broken until fixed. For bisectability, we copy the InternalEvent back into the XI required during POE and friends. Consider this a temporary solution. Note: Because of misc linker bonghits, Xvfb won't link in this revision. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
359 lines
10 KiB
C
359 lines
10 KiB
C
/*
|
|
* Copyright © 2009 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.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @file This file contains event conversion routines from InternalEvent to
|
|
* the matching protocol events.
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/extensions/XIproto.h>
|
|
#include <X11/extensions/XI.h>
|
|
|
|
#include "dix.h"
|
|
#include "inputstr.h"
|
|
#include "misc.h"
|
|
#include "events.h"
|
|
#include "exglobals.h"
|
|
#include "eventconvert.h"
|
|
#include "listdev.h"
|
|
|
|
static int countValuators(DeviceEvent *ev, int *first);
|
|
static int getValuatorEvents(DeviceEvent *ev, EventListPtr xi);
|
|
static int eventToKeyButtonPointer(DeviceEvent *ev, EventListPtr xi, int *count);
|
|
static int eventToClassesChanged(DeviceChangedEvent *ev, EventListPtr dcce,
|
|
int *count);
|
|
|
|
/**
|
|
* Convert the given event @ev to the respective core event and store it in
|
|
* @core.
|
|
*
|
|
* Return values:
|
|
* Success ... @core contains the matching core event.
|
|
* BadValue .. One or more values in the internal event are invalid.
|
|
* BadMatch .. The event has no core equivalent.
|
|
*
|
|
* @return Success or the matching error code.
|
|
*/
|
|
int
|
|
EventToCore(InternalEvent *event, xEvent *core)
|
|
{
|
|
switch(event->u.any.type)
|
|
{
|
|
case ET_Motion:
|
|
case ET_ButtonPress:
|
|
case ET_ButtonRelease:
|
|
case ET_KeyPress:
|
|
case ET_KeyRelease:
|
|
case ET_ProximityIn:
|
|
case ET_ProximityOut:
|
|
{
|
|
DeviceEvent *e = (DeviceEvent*)event;
|
|
|
|
if (e->detail.key > 0xFF)
|
|
return BadMatch;
|
|
|
|
memset(core, 0, sizeof(xEvent));
|
|
core->u.u.type = e->type - ET_KeyPress + KeyPress;
|
|
core->u.u.detail = e->detail.key & 0xFF;
|
|
core->u.keyButtonPointer.time = e->time;
|
|
core->u.keyButtonPointer.rootX = e->root_x;
|
|
core->u.keyButtonPointer.rootY = e->root_y;
|
|
core->u.keyButtonPointer.state = e->corestate;
|
|
}
|
|
break;
|
|
default:
|
|
/* XXX: */
|
|
ErrorF("[dix] EventToCore: Not implemented yet \n");
|
|
return BadImplementation;
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
/**
|
|
* Convert the given event @ev to the respective XI 1.x event and store it in
|
|
* @xi. @xi must be allocated by the caller, @count specifies the number of
|
|
* events in @xi.
|
|
*
|
|
*
|
|
* If less than @count events are needed, @count is set to the events stored
|
|
* in @xi and Success is returned.
|
|
*
|
|
* If more than @count events are needed, @count is set to the number of
|
|
* events required, and BadAlloc is returned. @xi is untouched.
|
|
*
|
|
* If necessary, @xi is realloced using SetMinimumEventSize() to fit the
|
|
* largest event being returned.
|
|
*
|
|
* If the event cannot be converted into an XI event because of protocol
|
|
* restrictions, @count is 0 and Success is returned.
|
|
*/
|
|
int
|
|
EventToXI(InternalEvent *ev, EventListPtr xi, int *count)
|
|
{
|
|
switch (ev->u.any.type)
|
|
{
|
|
case ET_Motion:
|
|
case ET_ButtonPress:
|
|
case ET_ButtonRelease:
|
|
case ET_KeyPress:
|
|
case ET_KeyRelease:
|
|
case ET_ProximityIn:
|
|
case ET_ProximityOut:
|
|
return eventToKeyButtonPointer((DeviceEvent*)ev, xi, count);
|
|
case ET_DeviceChanged:
|
|
return eventToClassesChanged((DeviceChangedEvent*)ev, xi, count);
|
|
break;
|
|
}
|
|
|
|
ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->u.any.type);
|
|
return BadImplementation;
|
|
}
|
|
|
|
static int
|
|
eventToKeyButtonPointer(DeviceEvent *ev, EventListPtr xi, int *count)
|
|
{
|
|
int num_events;
|
|
int first; /* dummy */
|
|
deviceKeyButtonPointer *kbp;
|
|
|
|
/* Sorry, XI 1.x protocol restrictions. */
|
|
if (ev->detail.button > 0xFF || ev->deviceid >= 0x80)
|
|
{
|
|
*count = 0;
|
|
return Success;
|
|
}
|
|
|
|
num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */
|
|
num_events++; /* the actual event event */
|
|
|
|
if (*count < num_events)
|
|
{
|
|
*count = num_events;
|
|
return BadAlloc;
|
|
}
|
|
|
|
SetMinimumEventSize(xi, *count, 32);
|
|
|
|
kbp = (deviceKeyButtonPointer*)xi->event;
|
|
kbp->detail = ev->detail.button;
|
|
kbp->time = ev->time;
|
|
kbp->root = ev->root;
|
|
kbp->root_x = ev->root_x;
|
|
kbp->root_y = ev->root_y;
|
|
kbp->deviceid = ev->deviceid;
|
|
kbp->state = ev->corestate;
|
|
|
|
if (num_events > 1)
|
|
kbp->deviceid |= MORE_EVENTS;
|
|
|
|
switch(ev->type)
|
|
{
|
|
case ET_Motion: kbp->type = DeviceMotionNotify; break;
|
|
case ET_ButtonPress: kbp->type = DeviceButtonPress; break;
|
|
case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break;
|
|
case ET_KeyPress: kbp->type = DeviceKeyPress; break;
|
|
case ET_KeyRelease: kbp->type = DeviceKeyRelease; break;
|
|
case ET_ProximityIn: kbp->type = ProximityIn; break;
|
|
case ET_ProximityOut: kbp->type = ProximityOut; break;
|
|
}
|
|
|
|
|
|
if (num_events > 1)
|
|
{
|
|
getValuatorEvents(ev, xi + 1);
|
|
}
|
|
|
|
*count = num_events;
|
|
return Success;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set @first to the first valuator in the event @ev and return the number of
|
|
* valuators from @first to the last set valuator.
|
|
*/
|
|
static int
|
|
countValuators(DeviceEvent *ev, int *first)
|
|
{
|
|
int first_valuator = -1, last_valuator = -1, num_valuators = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
|
|
{
|
|
if (BitIsOn(ev->valuators.mask, i))
|
|
{
|
|
if (first_valuator == -1)
|
|
first_valuator = i;
|
|
last_valuator = i;
|
|
}
|
|
}
|
|
|
|
if (first_valuator != -1)
|
|
{
|
|
num_valuators = last_valuator - first_valuator + 1;
|
|
*first = first_valuator;
|
|
}
|
|
|
|
return num_valuators;
|
|
}
|
|
|
|
static int
|
|
getValuatorEvents(DeviceEvent *ev, EventListPtr events)
|
|
{
|
|
int i;
|
|
deviceValuator *xv;
|
|
int first_valuator, num_valuators;
|
|
|
|
num_valuators = countValuators(ev, &first_valuator);
|
|
|
|
/* FIXME: non-continuous valuator data in internal events*/
|
|
for (i = 0; i < num_valuators; i += 6, events++) {
|
|
xv = (deviceValuator*)events->event;
|
|
xv->type = DeviceValuator;
|
|
xv->first_valuator = first_valuator + i;
|
|
xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
|
|
xv->deviceid = ev->deviceid;
|
|
switch (xv->num_valuators) {
|
|
case 6:
|
|
xv->valuator5 = ev->valuators.data[i + 5];
|
|
case 5:
|
|
xv->valuator4 = ev->valuators.data[i + 4];
|
|
case 4:
|
|
xv->valuator3 = ev->valuators.data[i + 3];
|
|
case 3:
|
|
xv->valuator2 = ev->valuators.data[i + 2];
|
|
case 2:
|
|
xv->valuator1 = ev->valuators.data[i + 1];
|
|
case 1:
|
|
xv->valuator0 = ev->valuators.data[i + 0];
|
|
}
|
|
|
|
if (i + 6 < num_valuators)
|
|
xv->deviceid |= MORE_EVENTS;
|
|
}
|
|
|
|
return (num_valuators + 5) / 6;
|
|
}
|
|
|
|
static int
|
|
eventToClassesChanged(DeviceChangedEvent *ev, EventListPtr events, int *count)
|
|
{
|
|
int len = sizeof(xEvent);
|
|
int namelen = 0; /* dummy */
|
|
DeviceIntPtr slave;
|
|
int rc;
|
|
deviceClassesChangedEvent *dcce = (deviceClassesChangedEvent*)events->event;
|
|
|
|
rc = dixLookupDevice(&slave, ev->new_slaveid,
|
|
serverClient, DixReadAccess);
|
|
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
SizeDeviceInfo(slave, &namelen, &len);
|
|
|
|
dcce->type = GenericEvent;
|
|
dcce->extension = IReqCode;
|
|
dcce->evtype = XI_DeviceClassesChangedNotify;
|
|
dcce->time = GetTimeInMillis();
|
|
dcce->new_slave = slave->id;
|
|
dcce->length = (len - sizeof(xEvent))/4;
|
|
|
|
*count = 1;
|
|
return Success;
|
|
}
|
|
|
|
/**
|
|
* Return the corresponding core type for the given @event or 0 if no core
|
|
* equivalent exists.
|
|
*/
|
|
int
|
|
GetCoreType(InternalEvent *event)
|
|
{
|
|
int coretype = 0;
|
|
switch(event->u.any.type)
|
|
{
|
|
case ET_Motion: coretype = MotionNotify; break;
|
|
case ET_ButtonPress: coretype = ButtonPress; break;
|
|
case ET_ButtonRelease: coretype = ButtonRelease; break;
|
|
case ET_KeyPress: coretype = KeyPress; break;
|
|
case ET_KeyRelease: coretype = KeyRelease; break;
|
|
}
|
|
return coretype;
|
|
}
|
|
|
|
/**
|
|
* Return the corresponding XI 1.x type for the given @event or 0 if no
|
|
* equivalent exists.
|
|
*/
|
|
int
|
|
GetXIType(InternalEvent *event)
|
|
{
|
|
int xitype = 0;
|
|
switch(event->u.any.type)
|
|
{
|
|
case ET_Motion: xitype = DeviceMotionNotify; break;
|
|
case ET_ButtonPress: xitype = DeviceButtonPress; break;
|
|
case ET_ButtonRelease: xitype = DeviceButtonRelease; break;
|
|
case ET_KeyPress: xitype = DeviceKeyPress; break;
|
|
case ET_KeyRelease: xitype = DeviceKeyRelease; break;
|
|
case ET_ProximityIn: xitype = ProximityIn; break;
|
|
case ET_ProximityOut: xitype = ProximityOut; break;
|
|
}
|
|
return xitype;
|
|
}
|
|
|
|
/*
|
|
* FIXME: A temporary solution to make the server bisectable. This code
|
|
* allocates during SIGIO and makes a number of assumptions about what's in
|
|
* events. Will be removed soon.
|
|
*/
|
|
|
|
int
|
|
ConvertBackToXI(InternalEvent *event, xEvent *ev)
|
|
{
|
|
int count = GetMaximumEventsNum();
|
|
int evlen, i;
|
|
|
|
EventListPtr tmp_list = InitEventList(count);
|
|
|
|
SetMinimumEventSize(tmp_list, count, 1000); /* just to be sure */
|
|
|
|
if (EventToXI(event, tmp_list, &count))
|
|
ErrorF("[dix] conversion to XI failed\n");
|
|
|
|
if (tmp_list->event->u.u.type == GenericEvent)
|
|
evlen = (GEV(tmp_list->event))->length * 4 + 32;
|
|
else
|
|
evlen = count * 32;
|
|
for (i = 0; i < count; i++)
|
|
memcpy(&ev[i], (tmp_list + i)->event, evlen);
|
|
return count;
|
|
}
|