aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xext/xtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xext/xtest.c')
-rw-r--r--xorg-server/Xext/xtest.c253
1 files changed, 206 insertions, 47 deletions
diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c
index e5ab7b451..0400062d8 100644
--- a/xorg-server/Xext/xtest.c
+++ b/xorg-server/Xext/xtest.c
@@ -31,8 +31,8 @@
#endif
#include <X11/X.h>
-#define NEED_EVENTS
#include <X11/Xproto.h>
+#include <X11/Xatom.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
@@ -43,16 +43,40 @@
#include "dixevents.h"
#include "sleepuntil.h"
#include "mi.h"
-#define _XTEST_SERVER_
-#include <X11/extensions/XTest.h>
-#include <X11/extensions/xteststr.h>
+#include "xkbsrv.h"
+#include "xkbstr.h"
+#include <X11/extensions/xtestproto.h>
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
+#include "exglobals.h"
+#include "mipointer.h"
+#include "xserver-properties.h"
+#include "exevents.h"
#include "modinit.h"
extern int DeviceValuator;
-extern int DeviceMotionNotify;
+
+/* XTest events are sent during request processing and may be interruped by
+ * a SIGIO. We need a separate event list to avoid events overwriting each
+ * other's memory */
+static EventListPtr xtest_evlist;
+
+/* Used to store if a device is an XTest Virtual device */
+static int XTestDevicePrivateKeyIndex;
+DevPrivateKey XTestDevicePrivateKey = &XTestDevicePrivateKeyIndex;
+
+/**
+ * xtestpointer
+ * is the virtual pointer for XTest. It is the first slave
+ * device of the VCP.
+ * xtestkeyboard
+ * is the virtual keyboard for XTest. It is the first slave
+ * device of the VCK
+ *
+ * Neither of these devices can be deleted.
+ */
+DeviceIntPtr xtestpointer, xtestkeyboard;
#ifdef PANORAMIX
#include "panoramiX.h"
@@ -81,11 +105,12 @@ XTestExtensionInit(INITARGS)
AddExtension(XTestExtensionName, 0, 0,
ProcXTestDispatch, SProcXTestDispatch,
NULL, StandardMinorOpcode);
+
+ xtest_evlist = InitEventList(GetMaximumEventsNum());
}
static int
-ProcXTestGetVersion(client)
- ClientPtr client;
+ProcXTestGetVersion(ClientPtr client)
{
xXTestGetVersionReply rep;
int n;
@@ -105,8 +130,7 @@ ProcXTestGetVersion(client)
}
static int
-ProcXTestCompareCursor(client)
- ClientPtr client;
+ProcXTestCompareCursor(ClientPtr client)
{
REQUEST(xXTestCompareCursorReq);
xXTestCompareCursorReply rep;
@@ -144,8 +168,7 @@ ProcXTestCompareCursor(client)
}
static int
-ProcXTestFakeInput(client)
- ClientPtr client;
+ProcXTestFakeInput(ClientPtr client)
{
REQUEST(xXTestFakeInputReq);
int nev, n, type, rc;
@@ -157,7 +180,6 @@ ProcXTestFakeInput(client)
int valuators[MAX_VALUATORS] = {0};
int numValuators = 0;
int firstValuator = 0;
- EventListPtr events;
int nevents = 0;
int i;
int base = 0;
@@ -189,11 +211,34 @@ ProcXTestFakeInput(client)
switch (type) {
case XI_DeviceKeyPress:
case XI_DeviceKeyRelease:
+ if (!dev->key)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
case XI_DeviceButtonPress:
case XI_DeviceButtonRelease:
+ if (!dev->button)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
case XI_DeviceMotionNotify:
+ if (!dev->valuator)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
case XI_ProximityIn:
case XI_ProximityOut:
+ if (!dev->proximity)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
break;
default:
client->errorValue = ev->u.u.type;
@@ -221,7 +266,7 @@ ProcXTestFakeInput(client)
flags |= POINTER_ABSOLUTE;
}
- if (nev == 1 && type == XI_DeviceMotionNotify && !dev->valuator)
+ if (nev > 1 && !dev->valuator)
{
client->errorValue = dv->first_valuator;
return BadValue;
@@ -296,8 +341,7 @@ ProcXTestFakeInput(client)
return BadValue;
}
- if (dev->u.lastSlave)
- dev = dev->u.lastSlave;
+ dev = GetXTestDevice(dev);
}
/* If the event has a time set, wait for it to pass */
@@ -334,14 +378,20 @@ ProcXTestFakeInput(client)
{
case KeyPress:
case KeyRelease:
- if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
- ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
+ if (!dev->key)
+ return BadDevice;
+
+ if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
+ ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code)
{
client->errorValue = ev->u.u.detail;
return BadValue;
}
break;
case MotionNotify:
+ if (!dev->valuator)
+ return BadDevice;
+
/* broken lib, XI events have root uninitialized */
if (extension || ev->u.keyButtonPointer.root == None)
root = GetCurrentRootWindow(dev);
@@ -368,12 +418,9 @@ ProcXTestFakeInput(client)
break;
case ButtonPress:
case ButtonRelease:
- if (!extension)
- {
- dev = PickPointer(client);
- if (dev->u.lastSlave)
- dev = dev->u.lastSlave;
- }
+ if (!dev->button)
+ return BadDevice;
+
if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
{
client->errorValue = ev->u.u.detail;
@@ -384,35 +431,32 @@ ProcXTestFakeInput(client)
if (screenIsSaved == SCREEN_SAVER_ON)
dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
- OsBlockSignals();
- GetEventList(&events);
switch(type) {
case MotionNotify:
- nevents = GetPointerEvents(events, dev, type, 0, flags,
+ nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags,
firstValuator, numValuators, valuators);
break;
case ButtonPress:
case ButtonRelease:
- nevents = GetPointerEvents(events, dev, type, ev->u.u.detail,
+ nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
flags, firstValuator,
numValuators, valuators);
break;
case KeyPress:
case KeyRelease:
- nevents = GetKeyboardEvents(events, dev, type, ev->u.u.detail);
+ nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
break;
}
for (i = 0; i < nevents; i++)
- mieqEnqueue(dev, (events+i)->event);
- OsReleaseSignals();
+ mieqProcessDeviceEvent(dev, (InternalEvent*)(xtest_evlist+i)->event, NULL);
+ miPointerUpdateSprite(dev);
return client->noClientException;
}
static int
-ProcXTestGrabControl(client)
- ClientPtr client;
+ProcXTestGrabControl(ClientPtr client)
{
REQUEST(xXTestGrabControlReq);
@@ -430,8 +474,7 @@ ProcXTestGrabControl(client)
}
static int
-ProcXTestDispatch (client)
- ClientPtr client;
+ProcXTestDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
@@ -450,8 +493,7 @@ ProcXTestDispatch (client)
}
static int
-SProcXTestGetVersion(client)
- ClientPtr client;
+SProcXTestGetVersion(ClientPtr client)
{
int n;
REQUEST(xXTestGetVersionReq);
@@ -463,8 +505,7 @@ SProcXTestGetVersion(client)
}
static int
-SProcXTestCompareCursor(client)
- ClientPtr client;
+SProcXTestCompareCursor(ClientPtr client)
{
int n;
REQUEST(xXTestCompareCursorReq);
@@ -477,9 +518,7 @@ SProcXTestCompareCursor(client)
}
static int
-XTestSwapFakeInput(client, req)
- ClientPtr client;
- xReq *req;
+XTestSwapFakeInput(ClientPtr client, xReq *req)
{
int nev;
xEvent *ev;
@@ -503,8 +542,7 @@ XTestSwapFakeInput(client, req)
}
static int
-SProcXTestFakeInput(client)
- ClientPtr client;
+SProcXTestFakeInput(ClientPtr client)
{
int n;
REQUEST(xReq);
@@ -517,8 +555,7 @@ SProcXTestFakeInput(client)
}
static int
-SProcXTestGrabControl(client)
- ClientPtr client;
+SProcXTestGrabControl(ClientPtr client)
{
int n;
REQUEST(xXTestGrabControlReq);
@@ -529,8 +566,7 @@ SProcXTestGrabControl(client)
}
static int
-SProcXTestDispatch (client)
- ClientPtr client;
+SProcXTestDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
@@ -547,3 +583,126 @@ SProcXTestDispatch (client)
return BadRequest;
}
}
+
+/**
+ * Allocate an virtual slave device for xtest events, this
+ * is a slave device to inputInfo master devices
+ */
+void InitXTestDevices(void)
+{
+ if(AllocXTestDevice(serverClient, "Virtual core",
+ &xtestpointer, &xtestkeyboard,
+ inputInfo.pointer, inputInfo.keyboard) != Success)
+ FatalError("Failed to allocate XTest devices");
+
+ if (ActivateDevice(xtestpointer, TRUE) != Success ||
+ ActivateDevice(xtestkeyboard, TRUE) != Success)
+ FatalError("Failed to activate XTest core devices.");
+ if (!EnableDevice(xtestpointer, TRUE) ||
+ !EnableDevice(xtestkeyboard, TRUE))
+ FatalError("Failed to enable XTest core devices.");
+
+ AttachDevice(NULL, xtestpointer, inputInfo.pointer);
+ AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard);
+}
+
+/**
+ * Don't allow changing the XTest property.
+ */
+static int
+DeviceSetXTestProperty(DeviceIntPtr dev, Atom property,
+ XIPropertyValuePtr prop, BOOL checkonly)
+{
+ if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE))
+ return BadAccess;
+
+ return Success;
+}
+
+/**
+ * Allocate a device pair that is initialised as a slave
+ * device with properties that identify the devices as belonging
+ * to XTest subsystem.
+ * This only creates the pair, Activate/Enable Device
+ * still need to be called.
+ */
+int AllocXTestDevice (ClientPtr client, char* name,
+ DeviceIntPtr* ptr, DeviceIntPtr* keybd,
+ DeviceIntPtr master_ptr, DeviceIntPtr master_keybd)
+{
+ int retval;
+ int len = strlen(name);
+ char *xtestname = xcalloc(len + 7, 1 );
+ char dummy = 1;
+
+ strncpy( xtestname, name, len);
+ strncat( xtestname, " XTEST", 6 );
+
+ retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE);
+ if ( retval == Success ){
+ dixSetPrivate(&((*ptr)->devPrivates), XTestDevicePrivateKey, (void *)master_ptr->id);
+ dixSetPrivate(&((*keybd)->devPrivates), XTestDevicePrivateKey, (void *)master_keybd->id);
+ }
+
+ xfree( xtestname );
+
+ XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
+ XA_INTEGER, 8, PropModeReplace, 1, &dummy,
+ FALSE);
+ XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
+ XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL);
+ XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
+ XA_INTEGER, 8, PropModeReplace, 1, &dummy,
+ FALSE);
+ XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
+ XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
+
+ return retval;
+}
+
+/**
+ * If master is NULL, return TRUE if the given device is an xtest device or
+ * FALSE otherwise.
+ * If master is not NULL, return TRUE if the given device is this master's
+ * xtest device.
+ */
+BOOL
+IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
+{
+ int is_XTest = FALSE;
+ int mid;
+ void *tmp; /* shut up, gcc! */
+
+ if (IsMaster(dev))
+ return is_XTest;
+
+ tmp = dixLookupPrivate(&dev->devPrivates, XTestDevicePrivateKey);
+ mid = (int)tmp;
+
+ /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest
+ * device */
+ if ((!master && mid) ||
+ (master && mid == master->id))
+ is_XTest = TRUE;
+
+ return is_XTest;
+}
+
+/**
+ * @return The X Test virtual device for the given master.
+ */
+DeviceIntPtr
+GetXTestDevice(DeviceIntPtr master)
+{
+ DeviceIntPtr it;
+
+ for (it = inputInfo.devices; it; it = it->next)
+ {
+ if (IsXTestDevice(it, master))
+ return it;
+ }
+
+ /* This only happens if master is a slave device. don't do that */
+ return NULL;
+}
+