xserver: Branch 'mpx' - 2 commits
Peter Hutterer
whot at kemper.freedesktop.org
Thu Feb 22 11:37:44 EET 2007
Xi/Makefile.am | 10 +
Xi/chaccess.c | 177 ++++++++++++++++++++++++++++++++
Xi/chaccess.h | 39 +++++++
Xi/chpkpair.c | 12 +-
Xi/extinit.c | 31 +++++
Xi/grabacc.c | 102 ++++++++++++++++++
Xi/grabacc.h | 41 +++++++
Xi/qryacces.c | 128 +++++++++++++++++++++++
Xi/qryacces.h | 41 +++++++
Xi/regpair.c | 108 +++++++++++++++++++
Xi/regpair.h | 43 +++++++
dix/Makefile.am | 1
dix/access.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++
dix/devices.c | 52 +++++++++
dix/dispatch.c | 2
dix/events.c | 23 ++--
dix/window.c | 21 +++
include/input.h | 31 +++++
include/windowstr.h | 9 +
19 files changed, 1145 insertions(+), 13 deletions(-)
New commits:
diff-tree 4b8b0e377a27ec904b2028c89aed11c6416af26c (from cd0af7a7856e8246e27acc5513d219a094211625)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date: Thu Feb 22 20:00:59 2007 +1030
Xi: Add access control request handling.
dix: New file access.c to handle all access control for devices.
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 5d3417e..e77c8a3 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -20,7 +20,9 @@ libXi_la_SOURCES = \
chgptr.c \
chgptr.h \
chpkpair.c \
- chpkpair.h \
+ chpkpair.h \
+ chaccess.c \
+ chaccess.h \
closedev.c \
closedev.h \
devbell.c \
@@ -46,6 +48,8 @@ libXi_la_SOURCES = \
getselev.h \
getvers.c \
getvers.h \
+ grabacc.c \
+ grabacc.h \
grabdev.c \
grabdev.h \
grabdevb.c \
@@ -62,6 +66,8 @@ libXi_la_SOURCES = \
querydp.h \
queryst.c \
queryst.h \
+ qryacces.c \
+ qryacces.h \
regpair.c \
regpair.h \
selectev.c \
diff --git a/Xi/chaccess.c b/Xi/chaccess.c
new file mode 100644
index 0000000..5005e94
--- /dev/null
+++ b/Xi/chaccess.c
@@ -0,0 +1,177 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "chaccess.h"
+
+/***********************************************************************
+ * This procedure allows a client to change window access control.
+ */
+
+int
+SProcXChangeWindowAccess(ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeWindowAccessReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->win, n);
+ return ProcXChangeWindowAccess(client);
+}
+
+int
+ProcXChangeWindowAccess(ClientPtr client)
+{
+ int padding, err, i;
+ CARD8* deviceids = NULL;
+ WindowPtr win;
+ DeviceIntPtr* perm_devices = NULL;
+ DeviceIntPtr* deny_devices = NULL;
+ REQUEST(xChangeWindowAccessReq);
+ REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq);
+
+
+ padding = (4 - ((stuff->npermit + stuff->ndeny) % 4)) % 4;
+
+ if (stuff->length != ((sizeof(xChangeWindowAccessReq) +
+ (stuff->npermit + stuff->ndeny + padding)) >> 2))
+ {
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+ 0, BadLength);
+ return Success;
+ }
+
+
+ err = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
+ if (err != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+ stuff->win, err);
+ return Success;
+ }
+
+ /* Are we clearing? if so, ignore the rest */
+ if (stuff->clear)
+ {
+ err = ACClearWindowAccess(client, win, stuff->clear);
+ if (err != Success)
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, err);
+ return Success;
+ }
+
+ if (stuff->npermit || stuff->ndeny)
+ deviceids = (CARD8*)&stuff[1];
+
+ if (stuff->npermit)
+ {
+ perm_devices =
+ (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr));
+ if (!perm_devices)
+ {
+ ErrorF("ProcXChangeWindowAccess: alloc failure.\n");
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
+ BadImplementation);
+ return Success;
+ }
+
+ /* if one of the devices cannot be accessed, we don't do anything.*/
+ for (i = 0; i < stuff->npermit; i++)
+ {
+ perm_devices[i] = LookupDeviceIntRec(deviceids[i]);
+ if (!perm_devices[i])
+ {
+ xfree(perm_devices);
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+ deviceids[i], BadDevice);
+ return Success;
+ }
+ }
+ }
+
+ if (stuff->ndeny)
+ {
+ deny_devices =
+ (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr));
+ if (!deny_devices)
+ {
+ ErrorF("ProcXChangeWindowAccecss: alloc failure.\n");
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
+ BadImplementation);
+
+ xfree(perm_devices);
+ return Success;
+ }
+
+ for (i = 0; i < stuff->ndeny; i++)
+ {
+ deny_devices[i] =
+ LookupDeviceIntRec(deviceids[i+stuff->npermit]);
+
+ if (!deny_devices[i])
+ {
+ xfree(perm_devices);
+ xfree(deny_devices);
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+ deviceids[i + stuff->npermit], BadDevice);
+ return Success;
+ }
+ }
+ }
+
+ err = ACChangeWindowAccess(client, win, stuff->defaultRule,
+ perm_devices, stuff->npermit,
+ deny_devices, stuff->ndeny);
+ if (err != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+ stuff->win, err);
+ return Success;
+ }
+
+ xfree(perm_devices);
+ xfree(deny_devices);
+ return Success;
+}
+
diff --git a/Xi/chaccess.h b/Xi/chaccess.h
new file mode 100644
index 0000000..8c2c600
--- /dev/null
+++ b/Xi/chaccess.h
@@ -0,0 +1,39 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef CHACCESS_H
+#define CHACCESS_H 1
+
+int SProcXChangeWindowAccess(ClientPtr /* client */);
+int ProcXChangeWindowAccess(ClientPtr /* client */);
+
+#endif /* CHACCESS_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index cf4f509..598348e 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -74,6 +74,7 @@ SOFTWARE.
/* modules local to Xi */
#include "allowev.h"
+#include "chaccess.h"
#include "chdevcur.h"
#include "chgdctl.h"
#include "chgfctl.h"
@@ -94,12 +95,14 @@ SOFTWARE.
#include "getselev.h"
#include "getvers.h"
#include "getvers.h"
+#include "grabacc.h"
#include "grabdev.h"
#include "grabdevb.h"
#include "grabdevk.h"
#include "gtmotion.h"
#include "listdev.h"
#include "opendev.h"
+#include "qryacces.c"
#include "querydp.h"
#include "queryst.h"
#include "regpair.h"
@@ -358,6 +361,12 @@ ProcIDispatch(register ClientPtr client)
return (ProcXChangePointerKeyboardPairing(client));
else if (stuff->data == X_RegisterPairingClient)
return (ProcXRegisterPairingClient(client));
+ else if (stuff->data == X_GrabAccessControl)
+ return (ProcXGrabAccessControl(client));
+ else if (stuff->data == X_ChangeWindowAccess)
+ return (ProcXChangeWindowAccess(client));
+ else if (stuff->data == X_QueryWindowAccess)
+ return ProcXQueryWindowAccess(client);
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -457,6 +466,12 @@ SProcIDispatch(register ClientPtr client
return (SProcXChangePointerKeyboardPairing(client));
else if (stuff->data == X_RegisterPairingClient)
return (SProcXRegisterPairingClient(client));
+ else if (stuff->data == X_GrabAccessControl)
+ return (SProcXGrabAccessControl(client));
+ else if (stuff->data == X_ChangeWindowAccess)
+ return (SProcXChangeWindowAccess(client));
+ else if (stuff->data == X_QueryWindowAccess)
+ return SProcXQueryWindowAccess(client);
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -531,10 +546,16 @@ SReplyIDispatch(ClientPtr client, int le
(xChangeDeviceControlReply *) rep);
else if (rep->RepType == X_QueryDevicePointer)
SRepXQueryDevicePointer(client, len,
- (xQueryDevicePointerReply *) rep);
+ (xQueryDevicePointerReply *) rep);
else if (rep->RepType == X_RegisterPairingClient)
SRepXRegisterPairingClient(client, len,
- (xRegisterPairingClientReply *) rep);
+ (xRegisterPairingClientReply *) rep);
+ else if (rep->RepType == X_GrabAccessControl)
+ SRepXGrabAccessControl(client, len,
+ (xGrabAccessControlReply*) rep);
+ else if (rep->RepType == X_QueryWindowAccess)
+ SRepXQueryWindowAccess(client, len,
+ (xQueryWindowAccessReply*) rep);
else {
FatalError("XINPUT confused sending swapped reply");
}
diff --git a/Xi/grabacc.c b/Xi/grabacc.c
new file mode 100644
index 0000000..db9c9f2
--- /dev/null
+++ b/Xi/grabacc.c
@@ -0,0 +1,102 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "grabacc.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to register as the global client to control
+ * any window access.
+ *
+ */
+int
+SProcXGrabAccessControl(ClientPtr client)
+{
+ char n;
+ REQUEST(xGrabAccessControlReq);
+
+ swaps(&stuff->length, n);
+ return ProcXGrabAccessControl(client);
+}
+
+int
+ProcXGrabAccessControl(ClientPtr client)
+{
+ xGrabAccessControlReply rep;
+ REQUEST(xGrabAccessControlReq);
+ REQUEST_SIZE_MATCH(xGrabAccessControlReq);
+
+ if (stuff->ungrab)
+ ACUnregisterClient(client);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_GrabAccessControl;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.success = stuff->ungrab || ACRegisterClient(client);
+
+ WriteReplyToClient(client, sizeof(xGrabAccessControlReply), &rep);
+ return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XGrabAccessControl function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXGrabAccessControl(ClientPtr client, int size,
+ xGrabAccessControlReply* rep)
+{
+ register char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/Xi/grabacc.h b/Xi/grabacc.h
new file mode 100644
index 0000000..6dcbcad
--- /dev/null
+++ b/Xi/grabacc.h
@@ -0,0 +1,41 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef GRABACC_H
+#define GRABACC_H 1
+
+int SProcXGrabAccessControl(ClientPtr /* client */);
+
+int ProcXGrabAccessControl(ClientPtr /* client */);
+void SRepXGrabAccessControl(ClientPtr client, int size,
+ xGrabAccessControlReply* rep);
+#endif /* GRABACC_H */
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
new file mode 100644
index 0000000..817bec8
--- /dev/null
+++ b/Xi/qryacces.c
@@ -0,0 +1,128 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "qryacces.h"
+
+/***********************************************************************
+ * This procedure allows a client to query window access control.
+ */
+
+int
+SProcXQueryWindowAccess(ClientPtr client)
+{
+ char n;
+ REQUEST(xQueryWindowAccessReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->win, n);
+ return ProcXQueryWindowAccess(client);
+}
+
+int
+ProcXQueryWindowAccess(ClientPtr client)
+{
+ int err;
+ WindowPtr win;
+ DeviceIntPtr *perm, *deny;
+ int nperm, ndeny, i;
+ int defaultRule;
+ CARD8* deviceids;
+ xQueryWindowAccessReply rep;
+
+ REQUEST(xQueryWindowAccessReq);
+ REQUEST_SIZE_MATCH(xQueryWindowAccessReq);
+
+ err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
+ if (err != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
+ stuff->win, err);
+ return Success;
+ }
+
+ ACQueryWindowAccess(win, &defaultRule, &perm, &nperm, &deny, &ndeny);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_QueryWindowAccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = (nperm + ndeny + 3) >> 2;
+ rep.defaultRule = defaultRule;
+ rep.npermit = nperm;
+ rep.ndeny = ndeny;
+ WriteReplyToClient(client, sizeof(xQueryWindowAccessReply), &rep);
+
+ if (nperm + ndeny)
+ {
+ deviceids = (CARD8*)xalloc((nperm + ndeny) * sizeof(CARD8));
+ if (!deviceids)
+ {
+ ErrorF("ProcXQueryWindowAccess: xalloc failure.\n");
+ SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
+ 0, BadImplementation);
+ return Success;
+ }
+
+ for (i = 0; i < nperm; i++)
+ deviceids[i] = perm[i]->id;
+ for (i = 0; i < ndeny; i++)
+ deviceids[i + nperm] = deny[i]->id;
+
+ WriteToClient(client, nperm + ndeny, (char*)deviceids);
+ xfree(deviceids);
+ }
+ return Success;
+}
+
+void
+SRepXQueryWindowAccess(ClientPtr client,
+ int size,
+ xQueryWindowAccessReply* rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ WriteToClient(client, size, (char*)rep);
+}
diff --git a/Xi/qryacces.h b/Xi/qryacces.h
new file mode 100644
index 0000000..5fce9ae
--- /dev/null
+++ b/Xi/qryacces.h
@@ -0,0 +1,41 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef QRYACCES_H
+#define QRYACCES_H 1
+
+int SProcXQueryWindowAccess(ClientPtr /* client */);
+int ProcXQueryWindowAccess(ClientPtr /* client */);
+void SRepXQueryWindowAccess(ClientPtr /* client */,
+ int /* size */,
+ xQueryWindowAccessReply* /* rep */);
+#endif
diff --git a/dix/Makefile.am b/dix/Makefile.am
index a1f02c1..d9083ea 100644
--- a/dix/Makefile.am
+++ b/dix/Makefile.am
@@ -5,6 +5,7 @@ AM_CFLAGS = $(DIX_CFLAGS) \
-DVENDOR_RELEASE="@VENDOR_RELEASE@"
libdix_la_SOURCES = \
+ access.c \
atom.c \
colormap.c \
cursor.c \
diff --git a/dix/access.c b/dix/access.c
new file mode 100644
index 0000000..970d7c4
--- /dev/null
+++ b/dix/access.c
@@ -0,0 +1,287 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+/* This file controls the access control lists for each window.
+ * Each device can be explicitely allowed or denied access to a given window.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XI.h>
+
+#include "input.h"
+#include "inputstr.h"
+#include "windowstr.h"
+
+
+/* Only one single client can be responsible for window access control. */
+static ClientPtr ACClient = NULL;
+
+
+/* Forward declarations */
+static void acReplaceList(DeviceIntPtr** list,
+ int* count,
+ DeviceIntPtr* devices,
+ int ndevices);
+
+/* Register global window access control client
+ * Return True on success or False otherwise.
+ */
+
+Bool
+ACRegisterClient(ClientPtr client)
+{
+ if (ACClient && ACClient != client)
+ return False;
+
+ ACClient = client;
+ return True;
+}
+
+
+/* Unregister global client. If client is not the registered client, nothing
+ * happens and False is returned. If no client is registered, return True.
+ * Returns True if client was registred and is now unregistered.
+ */
+
+Bool
+ACUnregisterClient(ClientPtr client)
+{
+ if (ACClient && ACClient != client)
+ return False;
+
+ ACClient = NULL;
+ return True;
+}
+
+/* Clears all access control for the window and remove the default rule,
+ * depending on what is set. */
+int ACClearWindowAccess(ClientPtr client,
+ WindowPtr win,
+ int what)
+{
+ if (client != ACClient && client != wClient(win))
+ return BadAccess;
+
+ if (!win->optional)
+ {
+ /* we shouldn't get here if programmers know what they're doing.
+ * A client should not request to clear a window's access controls
+ * if they've never been set before anyway. If they do, do nothing and
+ * let the client figure out what to do next.
+ */
+ return Success;
+ }
+
+ if (what & WindowAccessClearPerm)
+ {
+ xfree(win->optional->access.perm);
+ win->optional->access.perm = NULL;
+ win->optional->access.nperm = 0;
+ }
+
+ if (what & WindowAccessClearDeny)
+ {
+ xfree(win->optional->access.deny);
+ win->optional->access.deny = NULL;
+ win->optional->access.ndeny = 0;
+ }
+
+ if (what & WindowAccessClearRule)
+ win->optional->access.defaultRule = WindowAccessNoRule;
+
+ return Success;
+}
+
+/*
+ * Changes window access control.
+ *
+ * Returns Success or BadAccess if the client is not allowed to change
+ * anything.
+ */
+
+int
+ACChangeWindowAccess(ClientPtr client,
+ WindowPtr win,
+ int defaultRule,
+ DeviceIntPtr* perm_devices,
+ int nperm,
+ DeviceIntPtr* deny_devices,
+ int ndeny)
+{
+ if (client != ACClient && client != wClient(win))
+ return BadAccess;
+
+ if (!win->optional && !MakeWindowOptional(win))
+ {
+ ErrorF("ACChangeWindowAcccess: Failed to make window optional.\n");
+ return BadImplementation;
+ }
+
+ if (defaultRule != WindowAccessKeepRule)
+ win->optional->access.defaultRule = defaultRule;
+
+ if (nperm)
+ {
+ acReplaceList(&win->optional->access.perm,
+ &win->optional->access.nperm,
+ perm_devices, nperm);
+ }
+
+ if (ndeny)
+ {
+ acReplaceList(&win->optional->access.deny,
+ &win->optional->access.ndeny,
+ deny_devices, ndeny);
+ }
+
+ return Success;
+}
+
+static void
+acReplaceList(DeviceIntPtr** list,
+ int* count,
+ DeviceIntPtr* devices,
+ int ndevices)
+{
+ xfree(*list);
+ *list = NULL;
+ *count = 0;
+
+ if (ndevices)
+ {
+ *list =
+ xalloc(ndevices * sizeof(DeviceIntPtr*));
+ if (!*list)
+ {
+ ErrorF("ACChangeWindowAccess: out of memory\n");
+ return;
+ }
+ memcpy(*list,
+ devices,
+ ndevices * sizeof(DeviceIntPtr));
+ *count = ndevices;
+ }
+ return;
+}
+
+/*
+ * Query the given window for the devices allowed to access a window.
+ * The caller is responsible for freeing perm and deny.
+ */
+void
+ACQueryWindowAccess(WindowPtr win,
+ int* defaultRule,
+ DeviceIntPtr** perm,
+ int* nperm,
+ DeviceIntPtr** deny,
+ int* ndeny)
+{
+ *defaultRule = WindowAccessNoRule;
+ *perm = NULL;
+ *nperm = 0;
+ *deny = NULL;
+ *ndeny = 0;
+
+ if (!win->optional)
+ return;
+
+ *defaultRule = win->optional->access.defaultRule;
+
+ if (win->optional->access.nperm)
+ {
+ *nperm = win->optional->access.nperm;
+ *perm = (DeviceIntPtr*)xalloc(*nperm * sizeof(DeviceIntPtr));
+ if (!*perm)
+ {
+ ErrorF("ACQuerywinAccess: xalloc failure\n");
+ return;
+ }
+ memcpy(*perm,
+ win->optional->access.perm,
+ *nperm * sizeof(DeviceIntPtr));
+ }
+
+ if (win->optional->access.ndeny)
+ {
+ *ndeny = win->optional->access.ndeny;
+ *deny = (DeviceIntPtr*)xalloc(*ndeny * sizeof(DeviceIntPtr));
+ if (!*deny)
+ {
+ ErrorF("ACQuerywinAccess: xalloc failure\n");
+ return;
+ }
+ memcpy(*deny,
+ win->optional->access.deny,
+ *ndeny * sizeof(DeviceIntPtr));
+ }
+}
+
+/*
+ * Check if the given device is allowed to send events to the window. Returns
+ * true if device is allowed or false otherwise.
+ *
+ * Checks are done in the following order until a result is found:
+ * If the device is explicitely permitted, allow.
+ * If the window has a default of DenyAll, do not allow.
+ * If the device is explicitely denied, do not allow.
+ * Check parent window. Rinse, wash, repeat.
+ * If no rule could be found, allow.
+ */
+Bool
+ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev)
+{
+ int i;
+
+ if (!win) /* happens for parent of RootWindow */
+ return True;
+
+ if (!win->optional) /* no list, check parent */
+ return ACDeviceAllowed(win->parent, dev);
+
+ for (i = 0; i < win->optional->access.nperm; i++)
+ {
+ if (win->optional->access.perm[i]->id == dev->id)
+ return True;
+ }
+
+ if (win->optional->access.defaultRule == WindowAccessDenyAll)
+ return False;
+
+ for (i = 0; i < win->optional->access.ndeny; i++)
+ {
+ if (win->optional->access.deny[i]->id == dev->id)
+ return False;
+ }
+
+ return ACDeviceAllowed(win->parent, dev);
+}
+
diff --git a/dix/dispatch.c b/dix/dispatch.c
index a795d17..98183cc 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3568,6 +3568,7 @@ CloseDownClient(register ClientPtr clien
DeleteClientFromAnySelections(client);
ReleaseActiveGrabs(client);
DeleteClientFontStuff(client);
+ ACUnregisterClient(client);
UnregisterPairingClient(client); /* other clients can pair devices */
if (!really_close_down)
{
diff --git a/dix/events.c b/dix/events.c
index 57a356d..5ea9a65 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1663,6 +1663,9 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
this mask is the mask of the grab. */
int type = pEvents->u.u.type;
+
+ if (!ACDeviceAllowed(pWin, pDev))
+ return 0;
/* CantBeFiltered means only window owner gets the event */
if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
@@ -2748,16 +2751,20 @@ DeliverGrabbedEvent(register xEvent *xE,
}
if (!deliveries)
{
- FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
- deliveries = TryClientEvents(rClient(grab), xE, count,
- (Mask)grab->eventMask,
- filters[xE->u.u.type], grab);
- if (deliveries && (xE->u.u.type == MotionNotify
+ if (ACDeviceAllowed(grab->window, thisDev))
+ {
+
+ FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
+ deliveries = TryClientEvents(rClient(grab), xE, count,
+ (Mask)grab->eventMask,
+ filters[xE->u.u.type], grab);
+ if (deliveries && (xE->u.u.type == MotionNotify
#ifdef XINPUT
- || xE->u.u.type == DeviceMotionNotify
+ || xE->u.u.type == DeviceMotionNotify
#endif
- ))
- thisDev->valuator->motionHintWindow = grab->window;
+ ))
+ thisDev->valuator->motionHintWindow = grab->window;
+ }
}
if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
#ifdef XINPUT
diff --git a/dix/window.c b/dix/window.c
index 604af38..3d79728 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -452,6 +452,13 @@ CreateRootWindow(ScreenPtr pScreen)
pWin->optional->inputMasks = NULL;
pWin->optional->deviceCursors = NULL;
#endif
+
+ pWin->optional->access.perm = NULL;
+ pWin->optional->access.deny = NULL;
+ pWin->optional->access.nperm = 0;
+ pWin->optional->access.ndeny = 0;
+ pWin->optional->access.defaultRule = 0;
+
pWin->optional->colormap = pScreen->defColormap;
pWin->optional->visual = pScreen->rootVisual;
@@ -505,7 +512,6 @@ CreateRootWindow(ScreenPtr pScreen)
if (disableSaveUnders)
pScreen->saveUnderSupport = NotUseful;
-
return TRUE;
}
@@ -523,6 +529,7 @@ InitRootWindow(WindowPtr pWin)
pWin->optional->cursor = rootCursor;
rootCursor->refcnt++;
+
if (!blackRoot && !whiteRoot) {
MakeRootTile(pWin);
backFlag |= CWBackPixmap;
@@ -3660,6 +3667,9 @@ CheckWindowOptionalNeed (register Window
pNode = pNode->next;
}
}
+ if (optional->access.nperm != 0 ||
+ optional->access.ndeny != 0)
+ return;
parentOptional = FindWindowWithOptional(w)->optional;
if (optional->visual != parentOptional->visual)
@@ -3705,8 +3715,12 @@ MakeWindowOptional (register WindowPtr p
#endif
#ifdef XINPUT
optional->inputMasks = NULL;
- optional->deviceCursors = NULL;
#endif
+ optional->deviceCursors = NULL;
+ optional->access.nperm = 0;
+ optional->access.ndeny = 0;
+ optional->access.perm = NULL;
+ optional->access.deny = NULL;
parentOptional = FindWindowWithOptional(pWin)->optional;
optional->visual = parentOptional->visual;
if (!pWin->cursorIsNone)
@@ -3771,6 +3785,9 @@ DisposeWindowOptional (register WindowPt
pWin->optional->deviceCursors = NULL;
}
+ xfree(pWin->optional->access.perm);
+ xfree(pWin->optional->access.deny);
+
xfree (pWin->optional);
pWin->optional = NULL;
}
diff --git a/include/input.h b/include/input.h
index d2e26ef..a7b1e84 100644
--- a/include/input.h
+++ b/include/input.h
@@ -445,6 +445,37 @@ extern void SwitchCorePointer(DeviceIntP
extern DeviceIntPtr LookupDeviceIntRec(
CARD8 deviceid);
+/* Pairing input devices */
+extern int PairDevices(ClientPtr client,
+ DeviceIntPtr pointer,
+ DeviceIntPtr keyboard);
+
+extern Bool RegisterPairingClient(ClientPtr client);
+extern Bool UnregisterPairingClient(ClientPtr client);
+
+/* Window/device based access control */
+extern Bool ACRegisterClient(ClientPtr client);
+extern Bool ACUnregisterClient(ClientPtr client);
+extern int ACClearWindowAccess(ClientPtr client,
+ WindowPtr win,
+ int what);
+extern int ACChangeWindowAccess(ClientPtr client,
+ WindowPtr win,
+ int defaultRule,
+ DeviceIntPtr* perm_devices,
+ int npermit,
+ DeviceIntPtr* deny_devices,
+ int ndeny);
+extern void ACQueryWindowAccess(WindowPtr win,
+ int* defaultRule,
+ DeviceIntPtr** perm,
+ int* nperm,
+ DeviceIntPtr** deny,
+ int* ndeny);
+
+extern Bool ACDeviceAllowed(WindowPtr win,
+ DeviceIntPtr dev);
+
/* Implemented by the DDX. */
extern int NewInputDeviceRequest(
InputOption *options);
@@ -454,11 +485,4 @@ extern void DDXRingBell(
int pitch,
int duration);
-extern int PairDevices(ClientPtr client,
- DeviceIntPtr pointer,
- DeviceIntPtr keyboard);
-
-extern Bool RegisterPairingClient(ClientPtr client);
-extern Bool UnregisterPairingClient(ClientPtr client);
-
#endif /* INPUT_H */
diff --git a/include/windowstr.h b/include/windowstr.h
index 4e9c82c..882f8a5 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -77,6 +77,14 @@ typedef struct _DevCursorNode {
struct _DevCursorNode* next;
} DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
+typedef struct _WindowAccessRec {
+ int defaultRule; /* WindowAccessDenyAll */
+ DeviceIntPtr* perm;
+ int nperm;
+ DeviceIntPtr* deny;
+ int ndeny;
+} WindowAccessRec, *WindowAccessPtr;
+
typedef struct _WindowOpt {
VisualID visual; /* default: same as parent */
CursorPtr cursor; /* default: window.cursorNone */
@@ -97,6 +105,7 @@ typedef struct _WindowOpt {
struct _OtherInputMasks *inputMasks; /* default: NULL */
#endif
DevCursorList deviceCursors; /* default: NULL */
+ WindowAccessRec access;
} WindowOptRec, *WindowOptPtr;
#define BackgroundPixel 2L
diff-tree cd0af7a7856e8246e27acc5513d219a094211625 (from f6c3b9fa97ccf85e96f15435d564a1c261e40532)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date: Wed Feb 21 10:08:41 2007 +1030
Xi, dix: Only one client at a time can change the pointer-keyboard pairing,
using xRegisterPairingClient request.
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 9000030..5d3417e 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -62,6 +62,8 @@ libXi_la_SOURCES = \
querydp.h \
queryst.c \
queryst.h \
+ regpair.c \
+ regpair.h \
selectev.c \
selectev.h \
sendexev.c \
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
index b862417..8e79a75 100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@ -73,10 +73,13 @@ int
ProcXChangePointerKeyboardPairing(register ClientPtr client)
{
DeviceIntPtr pPointer, pKeyboard;
+ int ret;
REQUEST(xChangePointerKeyboardPairingReq);
REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
+ /* check if client is registered */
+
pPointer = LookupDeviceIntRec(stuff->pointer);
if (pPointer == NULL)
{
@@ -93,7 +96,14 @@ ProcXChangePointerKeyboardPairing(regist
return Success;
}
- pKeyboard->pSprite = pPointer->pSprite;
+ ret = PairDevices(client, pPointer, pKeyboard);
+ if (ret != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
+ 0, ret);
+ return Success;
+ }
+
/* TODO: generate event here... */
return Success;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index a08ec77..cf4f509 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -102,6 +102,7 @@ SOFTWARE.
#include "opendev.h"
#include "querydp.h"
#include "queryst.h"
+#include "regpair.h"
#include "selectev.h"
#include "sendexev.h"
#include "chgkmap.h"
@@ -355,6 +356,8 @@ ProcIDispatch(register ClientPtr client)
return (ProcXChangeDeviceCursor(client));
else if (stuff->data == X_ChangePointerKeyboardPairing)
return (ProcXChangePointerKeyboardPairing(client));
+ else if (stuff->data == X_RegisterPairingClient)
+ return (ProcXRegisterPairingClient(client));
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -452,6 +455,8 @@ SProcIDispatch(register ClientPtr client
return (SProcXChangeDeviceCursor(client));
else if (stuff->data == X_ChangePointerKeyboardPairing)
return (SProcXChangePointerKeyboardPairing(client));
+ else if (stuff->data == X_RegisterPairingClient)
+ return (SProcXRegisterPairingClient(client));
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -527,6 +532,9 @@ SReplyIDispatch(ClientPtr client, int le
else if (rep->RepType == X_QueryDevicePointer)
SRepXQueryDevicePointer(client, len,
(xQueryDevicePointerReply *) rep);
+ else if (rep->RepType == X_RegisterPairingClient)
+ SRepXRegisterPairingClient(client, len,
+ (xRegisterPairingClientReply *) rep);
else {
FatalError("XINPUT confused sending swapped reply");
}
diff --git a/Xi/regpair.c b/Xi/regpair.c
new file mode 100644
index 0000000..cfaddb8
--- /dev/null
+++ b/Xi/regpair.c
@@ -0,0 +1,108 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+/***********************************************************************
+ *
+ * Request to authenticate as pairing client
+ *
+ */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "regpair.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to register the pairing of a pointer
+ * with a keyboard.
+ *
+ */
+
+int
+SProcXRegisterPairingClient(ClientPtr client)
+{
+ char n;
+ REQUEST(xRegisterPairingClientReq);
+ swaps(&stuff->length, n);
+ return ProcXRegisterPairingClient(client);
+}
+
+int
+ProcXRegisterPairingClient(ClientPtr client)
+{
+ xRegisterPairingClientReply rep;
+
+ REQUEST(xRegisterPairingClientReq);
+ REQUEST_SIZE_MATCH(xRegisterPairingClientReq);
+
+ if (stuff->disable)
+ UnregisterPairingClient(client);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_RegisterPairingClient;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.success = stuff->disable || RegisterPairingClient(client);
+
+ WriteReplyToClient(client, sizeof(xRegisterPairingClientReply), &rep);
+ return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XRegisterPairingClient function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXRegisterPairingClient(ClientPtr client, int size,
+ xRegisterPairingClientReply* rep)
+{
+ register char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/Xi/regpair.h b/Xi/regpair.h
new file mode 100644
index 0000000..b2bfaff
--- /dev/null
+++ b/Xi/regpair.h
@@ -0,0 +1,43 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice 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 AUTHOR 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.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef REGPAIR_H
+#define REGPAIR_H 1
+
+int SProcXRegisterPairingClient(ClientPtr /* client */);
+int ProcXRegisterPairingClient(ClientPtr /* client */);
+
+void SRepXRegisterPairingClient(ClientPtr /* client */,
+ int /* size */,
+ xRegisterPairingClientReply* /* rep */);
+
+#endif /* REGPAIR_H */
diff --git a/dix/devices.c b/dix/devices.c
index bc7ca89..ad5cd50 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -81,6 +81,9 @@ SOFTWARE.
int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1;
+/* The client that is allowed to change pointer-keyboard pairings. */
+static ClientPtr pairingClient = NULL;
+
DeviceIntPtr
AddInputDevice(DeviceProc deviceProc, Bool autoStart)
{
@@ -1926,5 +1929,54 @@ ProcQueryKeymap(ClientPtr client)
bzero((char *)&rep.map[0], 32);
WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
+
+ return Success;
+}
+
+/* Pair the keyboard to the pointer device. Keyboard events will follow the
+ * pointer sprite.
+ */
+int
+PairDevices(ClientPtr client, DeviceIntPtr pointer, DeviceIntPtr keyboard)
+{
+ if (!pairingClient)
+ RegisterPairingClient(client);
+ else if (pairingClient != client)
+ return BadAccess;
+
+ keyboard->pSprite = pointer->pSprite;
return Success;
}
+
+/*
+ * Register a client to be able to pair devices.
+ */
+Bool
+RegisterPairingClient(ClientPtr client)
+{
+ if (!pairingClient)
+ {
+ pairingClient = client;
+ } else if (pairingClient != client)
+ {
+ return False;
+ }
+ return True;
+}
+
+/*
+ * Unregister pairing client;
+ */
+Bool
+UnregisterPairingClient(ClientPtr client)
+{
+ if (pairingClient)
+ {
+ if ( pairingClient == client)
+ {
+ pairingClient = NULL;
+ } else
+ return False;
+ }
+ return True;
+}
diff --git a/dix/dispatch.c b/dix/dispatch.c
index d44687e..a795d17 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3568,6 +3568,7 @@ CloseDownClient(register ClientPtr clien
DeleteClientFromAnySelections(client);
ReleaseActiveGrabs(client);
DeleteClientFontStuff(client);
+ UnregisterPairingClient(client); /* other clients can pair devices */
if (!really_close_down)
{
/* This frees resources that should never be retained
diff --git a/include/input.h b/include/input.h
index 96a28a5..d2e26ef 100644
--- a/include/input.h
+++ b/include/input.h
@@ -454,4 +454,11 @@ extern void DDXRingBell(
int pitch,
int duration);
+extern int PairDevices(ClientPtr client,
+ DeviceIntPtr pointer,
+ DeviceIntPtr keyboard);
+
+extern Bool RegisterPairingClient(ClientPtr client);
+extern Bool UnregisterPairingClient(ClientPtr client);
+
#endif /* INPUT_H */
More information about the xorg-commit
mailing list