Xi: add XIQueryDevice request handling.
This commit is contained in:
parent
560c58b53e
commit
dfa2e8e966
|
@ -60,6 +60,8 @@ libXi_la_SOURCES = \
|
|||
listdev.h \
|
||||
opendev.c \
|
||||
opendev.h \
|
||||
querydev.c \
|
||||
querydev.h \
|
||||
queryversion.h \
|
||||
queryversion.c \
|
||||
querydp.c \
|
||||
|
|
|
@ -104,6 +104,7 @@ SOFTWARE.
|
|||
#include "opendev.h"
|
||||
#include "querydp.h"
|
||||
#include "queryst.h"
|
||||
#include "querydev.h"
|
||||
#include "queryversion.h"
|
||||
#include "selectev.h"
|
||||
#include "sendexev.h"
|
||||
|
@ -237,7 +238,8 @@ static int (*ProcIVector[])(ClientPtr) = {
|
|||
ProcXISetClientPointer, /* 44 */
|
||||
ProcXIGetClientPointer, /* 45 */
|
||||
ProcXiSelectEvent, /* 46 */
|
||||
ProcXIQueryVersion /* 47 */
|
||||
ProcXIQueryVersion, /* 47 */
|
||||
ProcXIQueryDevice /* 48 */
|
||||
};
|
||||
|
||||
/* For swapped clients */
|
||||
|
@ -289,7 +291,8 @@ static int (*SProcIVector[])(ClientPtr) = {
|
|||
SProcXISetClientPointer, /* 44 */
|
||||
SProcXIGetClientPointer, /* 45 */
|
||||
SProcXiSelectEvent, /* 46 */
|
||||
SProcXIQueryVersion /* 47 */
|
||||
SProcXIQueryVersion, /* 47 */
|
||||
SProcXIQueryDevice /* 48 */
|
||||
};
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -480,6 +483,8 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
|
|||
(xXIQueryDevicePointerReply *) rep);
|
||||
else if (rep->RepType == X_XIGetClientPointer)
|
||||
SRepXIGetClientPointer(client, len, (xXIGetClientPointerReply*) rep);
|
||||
else if (rep->RepType == X_XIQueryDevice)
|
||||
SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
|
||||
else {
|
||||
FatalError("XINPUT confused sending swapped reply");
|
||||
}
|
||||
|
|
443
Xi/querydev.c
Normal file
443
Xi/querydev.c
Normal file
|
@ -0,0 +1,443 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Peter Hutterer
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Protocol handling for the XIQueryDevice request/reply.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "inputstr.h"
|
||||
#include <X11/X.h>
|
||||
#include <X11/extensions/XI2proto.h>
|
||||
#include "xkbstr.h"
|
||||
#include "xkbsrv.h"
|
||||
#include "xserver-properties.h"
|
||||
#include "exevents.h"
|
||||
|
||||
#include "querydev.h"
|
||||
|
||||
static int ListDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
|
||||
static int SizeDeviceInfo(DeviceIntPtr dev);
|
||||
static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
|
||||
int
|
||||
SProcXIQueryDevice(ClientPtr client)
|
||||
{
|
||||
char n;
|
||||
|
||||
REQUEST(xXIQueryDeviceReq);
|
||||
|
||||
swaps(&stuff->length, n);
|
||||
swaps(&stuff->deviceid, n);
|
||||
|
||||
return ProcXIQueryDevice(client);
|
||||
}
|
||||
|
||||
int
|
||||
ProcXIQueryDevice(ClientPtr client)
|
||||
{
|
||||
xXIQueryDeviceReply rep;
|
||||
DeviceIntPtr dev = NULL;
|
||||
int rc = Success;
|
||||
int len = 0;
|
||||
char *info, *ptr;
|
||||
|
||||
REQUEST(xXIQueryDeviceReq);
|
||||
REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
|
||||
|
||||
if (stuff->deviceid != AllDevices && stuff->deviceid != AllMasterDevices)
|
||||
{
|
||||
rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
|
||||
if (rc != Success)
|
||||
{
|
||||
client->errorValue = stuff->deviceid;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev)
|
||||
len += SizeDeviceInfo(dev);
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next)
|
||||
{
|
||||
if (stuff->deviceid == AllDevices ||
|
||||
(stuff->deviceid == AllMasterDevices && dev->isMaster))
|
||||
len += SizeDeviceInfo(dev);
|
||||
}
|
||||
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next)
|
||||
{
|
||||
if (stuff->deviceid == AllDevices ||
|
||||
(stuff->deviceid == AllMasterDevices && dev->isMaster))
|
||||
len += SizeDeviceInfo(dev);
|
||||
}
|
||||
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
info = xcalloc(1, len);
|
||||
if (!info)
|
||||
return BadAlloc;
|
||||
|
||||
memset(&rep, 0, sizeof(xXIQueryDeviceReply));
|
||||
rep.repType = X_Reply;
|
||||
rep.RepType = X_XIQueryDevice;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.length = len/4;
|
||||
rep.num_devices = 0;
|
||||
|
||||
ptr = info;
|
||||
if (dev)
|
||||
{
|
||||
len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
if (client->swapped)
|
||||
SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
info += len;
|
||||
rep.num_devices = 1;
|
||||
} else
|
||||
{
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next)
|
||||
{
|
||||
if (stuff->deviceid == AllDevices ||
|
||||
(stuff->deviceid == AllMasterDevices && dev->isMaster))
|
||||
{
|
||||
len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
if (client->swapped)
|
||||
SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
info += len;
|
||||
rep.num_devices++;
|
||||
}
|
||||
}
|
||||
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next)
|
||||
{
|
||||
if (stuff->deviceid == AllDevices ||
|
||||
(stuff->deviceid == AllMasterDevices && dev->isMaster))
|
||||
{
|
||||
len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
if (client->swapped)
|
||||
SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
|
||||
info += len;
|
||||
rep.num_devices++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
|
||||
WriteToClient(client, rep.length * 4, ptr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
|
||||
{
|
||||
char n;
|
||||
|
||||
swaps(&rep->sequenceNumber, n);
|
||||
swapl(&rep->length, n);
|
||||
swaps(&rep->num_devices, n);
|
||||
|
||||
/* Device info is already swapped, see ProcXIQueryDevice */
|
||||
|
||||
WriteToClient(client, size, (char *)rep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return The number of bytes needed to store this device's xXIDeviceInfo
|
||||
* (and its classes).
|
||||
*/
|
||||
static int
|
||||
SizeDeviceInfo(DeviceIntPtr dev)
|
||||
{
|
||||
int len = sizeof(xXIDeviceInfo);
|
||||
|
||||
/* 4-padded name */
|
||||
len += (((strlen(dev->name) + 3)/4)*4);
|
||||
|
||||
return len + SizeDeviceClasses(dev);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @return The number of bytes needed to store this device's classes.
|
||||
*/
|
||||
int
|
||||
SizeDeviceClasses(DeviceIntPtr dev)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (dev->button)
|
||||
{
|
||||
len += sizeof(xXIButtonInfo);
|
||||
len += dev->button->numButtons * sizeof(Atom);
|
||||
}
|
||||
|
||||
if (dev->key)
|
||||
{
|
||||
XkbDescPtr xkb = dev->key->xkbInfo->desc;
|
||||
len += sizeof(xXIKeyInfo);
|
||||
len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (dev->valuator)
|
||||
len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write button information into info.
|
||||
* @return Number of bytes written into info.
|
||||
*/
|
||||
static int
|
||||
ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
|
||||
{
|
||||
info->type = ButtonClass;
|
||||
info->num_buttons = dev->button->numButtons;
|
||||
info->length = 2 + info->num_buttons;
|
||||
|
||||
/** XXX: button labels */
|
||||
|
||||
return info->length * 4;
|
||||
}
|
||||
|
||||
static void
|
||||
SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
|
||||
{
|
||||
char n;
|
||||
Atom *btn;
|
||||
int i;
|
||||
swaps(&info->type, n);
|
||||
swaps(&info->length, n);
|
||||
|
||||
for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++)
|
||||
swaps(btn, n);
|
||||
|
||||
swaps(&info->num_buttons, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write key information into info.
|
||||
* @return Number of bytes written into info.
|
||||
*/
|
||||
static int
|
||||
ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
|
||||
{
|
||||
int i;
|
||||
XkbDescPtr xkb = dev->key->xkbInfo->desc;
|
||||
uint32_t *kc;
|
||||
|
||||
info->type = KeyClass;
|
||||
info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
|
||||
info->length = 2 + info->num_keycodes;
|
||||
|
||||
kc = (uint32_t*)&info[1];
|
||||
for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
|
||||
*kc = i;
|
||||
|
||||
return info->length * 4;
|
||||
}
|
||||
|
||||
static void
|
||||
SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
|
||||
{
|
||||
char n;
|
||||
uint32_t *key;
|
||||
int i;
|
||||
swaps(&info->type, n);
|
||||
swaps(&info->length, n);
|
||||
|
||||
for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++)
|
||||
swaps(key, n);
|
||||
|
||||
swaps(&info->num_keycodes, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* List axis information for the given axis.
|
||||
*
|
||||
* @return The number of bytes written into info.
|
||||
*/
|
||||
static int
|
||||
ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber)
|
||||
{
|
||||
ValuatorClassPtr v = dev->valuator;
|
||||
|
||||
info->type = ValuatorClass;
|
||||
info->length = sizeof(xXIValuatorInfo)/4;
|
||||
info->name = XIGetKnownProperty(AXIS_LABEL_PROP_REL_MISC); /* XXX */
|
||||
info->min.integral = v->axes[axisnumber].min_value;
|
||||
info->min.frac = 0;
|
||||
info->max.integral = v->axes[axisnumber].max_value;
|
||||
info->max.frac = 0;
|
||||
info->resolution = v->axes[axisnumber].resolution;
|
||||
info->number = axisnumber;
|
||||
info->mode = v->mode; /* Server doesn't have per-axis mode yet */
|
||||
|
||||
return info->length * 4;
|
||||
}
|
||||
|
||||
static void
|
||||
SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
|
||||
{
|
||||
char n;
|
||||
swaps(&info->type, n);
|
||||
swaps(&info->length, n);
|
||||
swapl(&info->name, n);
|
||||
swapl(&info->min.integral, n);
|
||||
swapl(&info->min.frac, n);
|
||||
swapl(&info->max.integral, n);
|
||||
swapl(&info->max.frac, n);
|
||||
swaps(&info->number, n);
|
||||
}
|
||||
|
||||
int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
|
||||
{
|
||||
DeviceIntPtr master = dev->u.master;
|
||||
int use;
|
||||
|
||||
if (dev->isMaster)
|
||||
{
|
||||
DeviceIntPtr paired = GetPairedDevice(dev);
|
||||
use = IsPointerDevice(dev) ? MasterPointer : MasterKeyboard;
|
||||
*attachment = (paired ? paired->id : 0);
|
||||
} else if (master)
|
||||
{
|
||||
use = IsPointerDevice(master) ? SlavePointer : SlaveKeyboard;
|
||||
*attachment = master->id;
|
||||
} else
|
||||
use = FloatingSlave;
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the info for device dev into the buffer pointed to by info.
|
||||
*
|
||||
* @return The number of bytes used.
|
||||
*/
|
||||
static int
|
||||
ListDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
|
||||
{
|
||||
char *any = (char*)&info[1];
|
||||
int len = 0, total_len = 0;
|
||||
|
||||
info->deviceid = dev->id;
|
||||
info->use = GetDeviceUse(dev, &info->attachment);
|
||||
info->num_classes = 0;
|
||||
info->name_len = strlen(dev->name);
|
||||
info->enabled = dev->enabled;
|
||||
total_len = sizeof(xXIDeviceInfo);
|
||||
|
||||
strncpy(any, dev->name, info->name_len);
|
||||
len = ((info->name_len + 3)/4) * 4;
|
||||
any += len;
|
||||
total_len += len;
|
||||
|
||||
return total_len + ListDeviceClasses(dev, any, &info->num_classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the class info of the device into the memory pointed to by any, set
|
||||
* nclasses to the number of classes in total and return the number of bytes
|
||||
* written.
|
||||
*/
|
||||
int
|
||||
ListDeviceClasses(DeviceIntPtr dev, char *any, uint16_t *nclasses)
|
||||
{
|
||||
int total_len = 0;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (dev->button)
|
||||
{
|
||||
(*nclasses)++;
|
||||
len = ListButtonInfo(dev, (xXIButtonInfo*)any);
|
||||
any += len;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
if (dev->key)
|
||||
{
|
||||
(*nclasses)++;
|
||||
len = ListKeyInfo(dev, (xXIKeyInfo*)any);
|
||||
any += len;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++)
|
||||
{
|
||||
(*nclasses)++;
|
||||
len = ListValuatorInfo(dev, (xXIValuatorInfo*)any, i);
|
||||
any += len;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static void
|
||||
SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
|
||||
{
|
||||
char n;
|
||||
char *any = (char*)&info[1];
|
||||
int i;
|
||||
|
||||
/* Skip over name */
|
||||
any += (((info->name_len + 3)/4) * 4);
|
||||
|
||||
for (i = 0; i < info->num_classes; i++)
|
||||
{
|
||||
switch(((xXIAnyInfo*)any)->type)
|
||||
{
|
||||
case ButtonClass:
|
||||
SwapButtonInfo(dev, (xXIButtonInfo*)any);
|
||||
break;
|
||||
case KeyClass:
|
||||
SwapKeyInfo(dev, (xXIKeyInfo*)any);
|
||||
break;
|
||||
case ValuatorClass:
|
||||
SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
|
||||
break;
|
||||
}
|
||||
|
||||
any += (((xXIAnyInfo*)any)->length * 4);
|
||||
}
|
||||
|
||||
swaps(&info->deviceid, n);
|
||||
swaps(&info->use, n);
|
||||
swaps(&info->attachment, n);
|
||||
swaps(&info->num_classes, n);
|
||||
swaps(&info->name_len, n);
|
||||
|
||||
}
|
42
Xi/querydev.h
Normal file
42
Xi/querydev.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Peter Hutterer
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#ifndef QUERYDEV_H
|
||||
#define QUERYDEV_H 1
|
||||
|
||||
#include <X11/extensions/XI2proto.h>
|
||||
|
||||
int SProcXIQueryDevice(ClientPtr client);
|
||||
int ProcXIQueryDevice(ClientPtr client);
|
||||
void SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep);
|
||||
int SizeDeviceClasses(DeviceIntPtr dev);
|
||||
int ListDeviceClasses(DeviceIntPtr dev, char* any, uint16_t* nclasses);
|
||||
int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment);
|
||||
#endif /* QUERYDEV_H */
|
|
@ -78,7 +78,7 @@ SOFTWARE.
|
|||
#include <X11/extensions/XIproto.h>
|
||||
#include "exglobals.h"
|
||||
#include "exevents.h"
|
||||
#include "listdev.h" /* for CopySwapXXXClass */
|
||||
#include "querydev.h" /* for SizeDeviceClasses */
|
||||
#include "xiproperty.h"
|
||||
#include "enterleave.h" /* for EnterWindow() */
|
||||
#include "xserver-properties.h"
|
||||
|
@ -274,7 +274,6 @@ EnableDevice(DeviceIntPtr dev)
|
|||
DeviceIntPtr *prev;
|
||||
int ret;
|
||||
DeviceIntPtr other;
|
||||
int namelen = 0; /* dummy */
|
||||
int evsize = sizeof(xEvent);
|
||||
int listlen;
|
||||
EventListPtr evlist;
|
||||
|
@ -316,7 +315,7 @@ EnableDevice(DeviceIntPtr dev)
|
|||
* device
|
||||
*/
|
||||
|
||||
SizeDeviceInfo(dev, &namelen, &evsize);
|
||||
evsize += SizeDeviceClasses(dev);
|
||||
|
||||
listlen = GetEventList(&evlist);
|
||||
OsBlockSignals();
|
||||
|
|
Loading…
Reference in New Issue
Block a user