[Xquartz-changes] xserver: Branch 'for-keith' - 45 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Wed Sep 28 12:16:58 PDT 2011


Rebased ref, commits from common ancestor:
commit 239e6df38dee80e531b18bcfabc1d94ac9d9dd63
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Tue Sep 20 20:39:06 2011 -0700

    XQuartz: Use set_front_process rather than X11ApplicationSetFrontProcess since we're already in the AppKit thread
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 7fd7dab..12ff53c 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -356,7 +356,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                          */
                         _appFlags._active = YES;
 
-                        X11ApplicationSetFrontProcess();
+                        [self set_front_process:nil];
 
                         /* Get the Spaces preference for SwitchOnActivate */
                         (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock"));
commit 11d310bb9e27208ea1b7b2b68f939a15aa557ca7
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Sep 22 18:55:19 2011 -0700

    Address regressions from e8ff555b95ba and d206d52f657c to work with other compilers
    
    1) The error attribute appeared in gcc-4.3
    2) The return type of __builtin_constant_p is int
    3) Sun Studio 12.0 and later builtin support for __builtin_constant_p
    
    Found by Tinderbox.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    Reviewed-by: Matt Turner <mattst88 at gmail.com>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/include/misc.h b/include/misc.h
index 1fea73e..0867746 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -261,14 +261,16 @@ version_compare(uint16_t a_major, uint16_t a_minor,
 #define SwapRestL(stuff) \
     SwapLongs((CARD32 *)(stuff + 1), LengthRestL(stuff))
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
 void __attribute__((error("wrong sized variable passed to swap"))) wrong_size(void);
 #else
 static inline void wrong_size(void)
 {
 }
+#endif
 
-static inline void __builtin_constant_p(int x)
+#if !(defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C < 0x590)))
+static inline int __builtin_constant_p(int x)
 {
 	return 0;
 }
commit afb1fe695d197187a301c19863a128a65389b15c
Merge: 7fb4bef... c7163fd...
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Sep 26 20:24:15 2011 -0700

    Merge remote-tracking branch 'whot/next'

commit c7163fdd302f706a3d67f0fdf93eeb3396bb3332
Author: vdb at picaros.org <vdb at picaros.org>
Date:   Wed Aug 31 07:23:01 2011 +0200

    xfree86: .BI style: monitor section in xorg.conf man page
    
    The xorg.conf manual uses the following convention in most of its
    sections:
    
    bold = text to be copied literally to the config file,
    italic = a symbolic name to be substituted by a true value.
    
    Some configuration keywords seem to have been changed into generic
    options.  Prepending Option to the manual entry swapped the
    bold-italic logic.  This patch restores the convention in the monitor
    section and consists of
    
    -.BI "Option " "\*qPreferredMode\*q  " \*qstring\*q
    +.BI "Option \*qPreferredMode\*q \*q" name \*q
    
    modifications.
    
    Plus a few minor changes (Modes → Mode) and a typo fix.
    
    Signed-off-by: Servaas Vandenberghe
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index df877b9..8615343 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -1449,7 +1449,7 @@ driver plus the identifier of a monitor section, one associates a monitor
 section with an output by adding an option to the Device section in the
 following format:
 
-.B Option \*qMonitor-outputname\*q \*qmonitorsection\*q
+.BI "Option \*qMonitor-" outputname "\*q \*q" monitorsection \*q
 
 (for example,
 .B Option \*qMonitor-VGA\*q \*qVGA monitor\*q
@@ -1465,7 +1465,7 @@ modes available.
 When modes are specified explicitly in the
 .B Monitor
 section (with the
-.BR Modes ,
+.BR Mode ,
 .BR ModeLine ,
 or
 .B UseModes
@@ -1614,7 +1614,7 @@ mentioned above doubles this value.
 This entry is a more compact version of the
 .B Mode
 entry, and it also can be used to specify video modes for the monitor.
-is a single line format for specifying video modes.
+This is a single line format for specifying video modes.
 In most cases this isn't necessary because the built\-in set of VESA
 standard modes will be sufficient.
 .PP
@@ -1669,61 +1669,61 @@ The
 and
 .B VScan
 options mentioned above in the
-.B Modes
+.B Mode
 entry description can also be used here.
 .RE
 .TP 7
-.BI "Option " "\*qDPMS\*q  " \*qbool\*q
+.BI "Option \*qDPMS\*q \*q" bool \*q
 This option controls whether the server should enable the DPMS extension
 for power management for this screen.  The default is to enable the
 extension.
 .TP 7
-.BI "Option " "\*qSyncOnGreen\*q  " \*qbool\*q
+.BI "Option \*qSyncOnGreen\*q \*q" bool \*q
 This option controls whether the video card should drive the sync signal
 on the green color pin.  Not all cards support this option, and most
 monitors do not require it.  The default is off.
 .TP 7
-.BI "Option " "\*qPrimary\*q  " \*qbool\*q
+.BI "Option \*qPrimary\*q \*q" bool \*q
 This optional entry specifies that the monitor should be treated as the primary
 monitor. (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qPreferredMode\*q  " \*qstring\*q
+.BI "Option \*qPreferredMode\*q \*q" name \*q
 This optional entry specifies a mode to be marked as the preferred initial mode
 of the monitor.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qPosition\*q  " "\*qx y\*q"
+.BI "Option \*qPosition\*q \*q" x " " y \*q
 This optional entry specifies the position of the monitor within the X
 screen.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qLeftOf\*q  " \*qoutput\*q
+.BI "Option \*qLeftOf\*q \*q" output \*q
 This optional entry specifies that the monitor should be positioned to the
 left of the output (not monitor) of the given name.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qRightOf\*q  " \*qoutput\*q
+.BI "Option \*qRightOf\*q \*q" output \*q
 This optional entry specifies that the monitor should be positioned to the
 right of the output (not monitor) of the given name.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qAbove\*q  " \*qoutput\*q
+.BI "Option \*qAbove\*q \*q" output \*q
 This optional entry specifies that the monitor should be positioned above the
 output (not monitor) of the given name.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qBelow\*q  " \*qoutput\*q
+.BI "Option \*qBelow\*q \*q" output \*q
 This optional entry specifies that the monitor should be positioned below the
 output (not monitor) of the given name.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qEnable\*q  " \*qbool\*q
+.BI "Option \*qEnable\*q \*q" bool \*q
 This optional entry specifies whether the monitor should be turned on
 at startup.  By default, the server will attempt to enable all connected
 monitors.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qDefaultModes\*q  " \*qbool\*q
+.BI "Option \*qDefaultModes\*q \*q" bool \*q
 This optional entry specifies whether the server should add supported default
 modes to the list of modes offered on this monitor. By default, the server
 will add default modes; you should only disable this if you can guarantee
@@ -1731,21 +1731,21 @@ that EDID will be available at all times, or if you have added custom modelines
 which the server can use.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qMinClock\*q  " \*qfrequency\*q
+.BI "Option \*qMinClock\*q \*q" frequency \*q
 This optional entry specifies the minimum dot clock, in kHz, that is supported
 by the monitor.
 .TP 7
-.BI "Option " "\*qMaxClock\*q  " \*qfrequency\*q
+.BI "Option \*qMaxClock\*q \*q" frequency \*q
 This optional entry specifies the maximum dot clock, in kHz, that is supported
 by the monitor.
 .TP 7
-.BI "Option " "\*qIgnore\*q  " \*qbool\*q
+.BI "Option \*qIgnore\*q \*q" bool \*q
 This optional entry specifies that the monitor should be ignored entirely,
 and not reported through RandR.  This is useful if the hardware reports the
 presence of outputs that don't exist.
 (RandR 1.2-supporting drivers only)
 .TP 7
-.BI "Option " "\*qRotate\*q  " \*qrotation\*q
+.BI "Option \*qRotate\*q \*q" rotation \*q
 This optional entry specifies the initial rotation of the given monitor.
 Valid values for rotation are \*qnormal\*q, \*qleft\*q, \*qright\*q, and
 \*qinverted\*q.
commit 4b4caecb7d2c8e0b7e4fedc95fba2a728bbc25e6
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Sep 6 09:33:43 2011 +1000

    xfree86: expose Option "TransformationMatrix"
    
    Recent changes to the server change the default absolute input device
    behaviour on zaphods to span the whole desktop too. Since these setups
    usually use an xorg.conf, allow the transformation matrix to be specified in
    the config as well.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Simon Thum <simon.thum at gmx.de>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 526b92d..9fbcba9 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -266,6 +266,34 @@ ApplyAccelerationSettings(DeviceIntPtr dev){
     }
 }
 
+static void
+ApplyTransformationMatrix(DeviceIntPtr dev)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
+    char *str;
+    int rc;
+    float matrix[9] = {0};
+
+    if (!dev->valuator)
+        return;
+
+    str = xf86SetStrOption(pInfo->options, "TransformationMatrix", NULL);
+    if (!str)
+        return;
+
+    rc = sscanf(str, "%f %f %f %f %f %f %f %f %f", &matrix[0], &matrix[1], &matrix[2],
+                &matrix[3], &matrix[4], &matrix[5], &matrix[6], &matrix[7], &matrix[8]);
+    if (rc != 9) {
+        xf86Msg(X_ERROR, "%s: invalid format for transformation matrix. Ignoring configuration.\n",
+                pInfo->name);
+        return;
+    }
+
+    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
+                           XIGetKnownProperty(XATOM_FLOAT), 32,
+                           PropModeReplace, 9, matrix, FALSE);
+}
+
 /***********************************************************************
  *
  * xf86ProcessCommonOptions --
@@ -755,6 +783,7 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
 static int
 xf86InputDevicePostInit(DeviceIntPtr dev) {
     ApplyAccelerationSettings(dev);
+    ApplyTransformationMatrix(dev);
     return Success;
 }
 
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index 6774dbc..df877b9 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -948,6 +948,17 @@ is equivalent to
 
 This option controls the startup behavior only, a device
 may be reattached or set floating at runtime.
+.TP 7
+.BI "Option \*qTransformationMatrix\*q \*q" a " " b " " c " " d " " e " " f " " g " " h " " i \*q
+Specifies the 3x3 transformation matrix for absolute input devices. The
+input device will be bound to the area given in the matrix.  In most
+configurations, "a" and "e" specify the width and height of the area the
+device is bound to, and "c" and "f" specify the x and y offset of the area.
+The value range is 0 to 1, where 1 represents the width or height of all
+root windows together, 0.5 represents half the area, etc. The values
+represent a 3x3 matrix, with the first, second and third group of three
+values representing the first, second and third row of the matrix,
+respectively.  The identity matrix is "1 0 0 0 1 0 0 0 1".
 .SS POINTER ACCELERATION
 For pointing devices, the following options control how the pointer
 is accelerated or decelerated with respect to physical device motion. Most of
commit cf51424a34fb2b567a867338ab44f83b5c43251c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Sep 6 09:39:01 2011 +1000

    xfree86: use subheader for Pointer Acceleration parts in xorg.conf(5)
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index f406f82..6774dbc 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -948,7 +948,7 @@ is equivalent to
 
 This option controls the startup behavior only, a device
 may be reattached or set floating at runtime.
-.PP
+.SS POINTER ACCELERATION
 For pointing devices, the following options control how the pointer
 is accelerated or decelerated with respect to physical device motion. Most of
 these can be adjusted at runtime, see the xinput(1) man page for details. Only
commit 9125952b407090b040bffb3d752288293137cf77
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Sep 5 15:43:14 2011 +1000

    xfree86: fix comment typo
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 114cdd9..526b92d 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -746,7 +746,7 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
 }
 
 /*
- * Apply backend-specific initialization. Invoked after ActiveteDevice(),
+ * Apply backend-specific initialization. Invoked after ActivateDevice(),
  * i.e. after the driver successfully completed DEVICE_INIT and the device
  * is advertised.
  * @param dev the device
commit 2d2dce558d24eeea0eb011ec9ebaa6c5c2273c39
Author: Sam Spilsbury <sam.spilsbury at canonical.com>
Date:   Wed Sep 14 09:58:34 2011 +0800

    Remove the SendEvent bit (0x80) before doing range checks on event type.
    
    Some extension libraries may set this bit before converting the event to
    wire protocol and as such range checking the event will cause an invalid
    BadValue error to result. As the documentation suggests the the bit
    should be "forced on", remove it before doing range checks and continue
    to force it on in the server.
    
    Reviewed-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 7fe0fba..fbe4fc9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5251,6 +5251,8 @@ CloseDownEvents(void)
     InputEventList = NULL;
 }
 
+#define SEND_EVENT_BIT 0x80
+
 /**
  * Server-side protocol handling for SendEvent request.
  *
@@ -5268,6 +5270,16 @@ ProcSendEvent(ClientPtr client)
 
     REQUEST_SIZE_MATCH(xSendEventReq);
 
+    /* libXext and other extension libraries may set the bit indicating
+     * that this event came from a SendEvent request so remove it
+     * since otherwise the event type may fail the range checks
+     * and cause an invalid BadValue error to be returned.
+     *
+     * This is safe to do since we later add the SendEvent bit (0x80)
+     * back in once we send the event to the client */
+
+    stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
+
     /* The client's event type must be a core event type or one defined by an
 	extension. */
 
@@ -5325,7 +5337,7 @@ ProcSendEvent(ClientPtr client)
 	client->errorValue = stuff->propagate;
 	return BadValue;
     }
-    stuff->event.u.u.type |= 0x80;
+    stuff->event.u.u.type |= SEND_EVENT_BIT;
     if (stuff->propagate)
     {
 	for (;pWin; pWin = pWin->parent)
commit f52d5cd374563544dafe29587411f345e31bbdf8
Author: Carlos Garnacho <carlosg at gnome.org>
Date:   Wed Aug 31 00:46:52 2011 +0200

    Xi: Fix passive XI2 ungrabs on XIAll[Master]Devices
    
    The corresponding DeviceIntPtr wasn't being gotten properly,
    resulting in BadDevice from dixLookupDevice().
    
    Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index ae43433..5cdd8ac 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -261,9 +261,16 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
     REQUEST(xXIPassiveUngrabDeviceReq);
     REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
 
-    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
-    if (rc != Success)
-	return rc;
+    if (stuff->deviceid == XIAllDevices)
+        dev = inputInfo.all_devices;
+    else if (stuff->deviceid == XIAllMasterDevices)
+        dev = inputInfo.all_master_devices;
+    else
+    {
+        rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+        if (rc != Success)
+	    return rc;
+    }
 
     if (stuff->grab_type != XIGrabtypeButton &&
         stuff->grab_type != XIGrabtypeKeycode &&
commit 24823f1ab0f16e0815ef44340894537dc4babf6a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Aug 3 16:01:28 2011 +1000

    xfree86: switch options from pointer to XF86OptionPtr
    
    In all cases, the pointer was simply type-cast anyway. Let's get some
    compile-time type safety going, how about that.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>
    
    Squashed in:
    xfree86: Move definition of xf86OptionPtr into separate header file
    
    The pile of spaghettis that is the xfree86 include dependencies make it
    rather hard to have a single typedef somewhere that's not interfering with
    everything else or drags in a whole bunch of other includes.
    
    Move the xf86OptionRec and GenericListRec declarations into a separate
    header.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
index c031d4b..23ddb5c 100644
--- a/hw/xfree86/common/Makefile.am
+++ b/hw/xfree86/common/Makefile.am
@@ -51,7 +51,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \
               xf86PciInfo.h xf86Priv.h xf86Privstr.h \
               xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \
               $(XVSDKINCS) $(XF86VMODE_SDK) xorgVersion.h \
-              xf86sbusBus.h xf86VGAarbiter.h
+              xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h
 
 DISTCLEANFILES = xf86Build.h
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index 54332e3..ae152b9 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -332,7 +332,7 @@ extern _X_EXPORT DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePt
 
 /* xf86Option.c */
 
-extern _X_EXPORT void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts);
+extern _X_EXPORT void xf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts);
 
 
 /* xf86RandR.c */
diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h
index 9453f2a..88392dc 100644
--- a/hw/xfree86/common/xf86Opt.h
+++ b/hw/xfree86/common/xf86Opt.h
@@ -30,6 +30,7 @@
 
 #ifndef _XF86_OPT_H_
 #define _XF86_OPT_H_
+#include "xf86Optionstr.h"
 
 typedef struct {
     double freq;
@@ -69,34 +70,34 @@ typedef struct {
     Bool                found;
 } OptionInfoRec, *OptionInfoPtr;
 
-extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int deflt);
-extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt);
-extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt);
-extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt );
-extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, double deflt );
-extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt);
-extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt);
-extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt);
-extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt );
-extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, double deflt );
-extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val );
-extern _X_EXPORT pointer xf86NewOption(char *name, char *value );
-extern _X_EXPORT pointer xf86NextOption(pointer list );
-extern _X_EXPORT pointer xf86OptionListCreate(const char **options, int count, int used);
-extern _X_EXPORT pointer xf86OptionListMerge(pointer head, pointer tail);
-extern _X_EXPORT pointer xf86OptionListDuplicate(pointer list);
-extern _X_EXPORT void xf86OptionListFree(pointer opt);
-extern _X_EXPORT char *xf86OptionName(pointer opt);
-extern _X_EXPORT char *xf86OptionValue(pointer opt);
-extern _X_EXPORT void xf86OptionListReport(pointer parm);
-extern _X_EXPORT pointer xf86FindOption(pointer options, const char *name);
-extern _X_EXPORT char *xf86FindOptionValue(pointer options, const char *name);
-extern _X_EXPORT void xf86MarkOptionUsed(pointer option);
-extern _X_EXPORT void xf86MarkOptionUsedByName(pointer options, const char *name);
-extern _X_EXPORT Bool xf86CheckIfOptionUsed(pointer option);
-extern _X_EXPORT Bool xf86CheckIfOptionUsedByName(pointer options, const char *name);
-extern _X_EXPORT void xf86ShowUnusedOptions(int scrnIndex, pointer options);
-extern _X_EXPORT void xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo);
+extern _X_EXPORT int xf86SetIntOption(XF86OptionPtr optlist, const char *name, int deflt);
+extern _X_EXPORT double xf86SetRealOption(XF86OptionPtr optlist, const char *name, double deflt);
+extern _X_EXPORT char *xf86SetStrOption(XF86OptionPtr optlist, const char *name, char *deflt);
+extern _X_EXPORT int xf86SetBoolOption(XF86OptionPtr list, const char *name, int deflt );
+extern _X_EXPORT double xf86SetPercentOption(XF86OptionPtr list, const char *name, double deflt );
+extern _X_EXPORT int xf86CheckIntOption(XF86OptionPtr optlist, const char *name, int deflt);
+extern _X_EXPORT double xf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt);
+extern _X_EXPORT char *xf86CheckStrOption(XF86OptionPtr optlist, const char *name, char *deflt);
+extern _X_EXPORT int xf86CheckBoolOption(XF86OptionPtr list, const char *name, int deflt );
+extern _X_EXPORT double xf86CheckPercentOption(XF86OptionPtr list, const char *name, double deflt );
+extern _X_EXPORT XF86OptionPtr xf86AddNewOption(XF86OptionPtr head, const char *name, const char *val );
+extern _X_EXPORT XF86OptionPtr xf86NewOption(char *name, char *value );
+extern _X_EXPORT XF86OptionPtr xf86NextOption(XF86OptionPtr list );
+extern _X_EXPORT XF86OptionPtr xf86OptionListCreate(const char **options, int count, int used);
+extern _X_EXPORT XF86OptionPtr xf86OptionListMerge(XF86OptionPtr head, XF86OptionPtr tail);
+extern _X_EXPORT XF86OptionPtr xf86OptionListDuplicate(XF86OptionPtr list);
+extern _X_EXPORT void xf86OptionListFree(XF86OptionPtr opt);
+extern _X_EXPORT char *xf86OptionName(XF86OptionPtr opt);
+extern _X_EXPORT char *xf86OptionValue(XF86OptionPtr opt);
+extern _X_EXPORT void xf86OptionListReport(XF86OptionPtr parm);
+extern _X_EXPORT XF86OptionPtr xf86FindOption(XF86OptionPtr options, const char *name);
+extern _X_EXPORT char *xf86FindOptionValue(XF86OptionPtr options, const char *name);
+extern _X_EXPORT void xf86MarkOptionUsed(XF86OptionPtr option);
+extern _X_EXPORT void xf86MarkOptionUsedByName(XF86OptionPtr options, const char *name);
+extern _X_EXPORT Bool xf86CheckIfOptionUsed(XF86OptionPtr option);
+extern _X_EXPORT Bool xf86CheckIfOptionUsedByName(XF86OptionPtr options, const char *name);
+extern _X_EXPORT void xf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr options);
+extern _X_EXPORT void xf86ProcessOptions(int scrnIndex, XF86OptionPtr options, OptionInfoPtr optinfo);
 extern _X_EXPORT OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, int token);
 extern _X_EXPORT const char *xf86TokenToOptName(const OptionInfoRec *table, int token);
 extern _X_EXPORT Bool xf86IsOptionSet(const OptionInfoRec *table, int token);
@@ -110,9 +111,9 @@ extern _X_EXPORT Bool xf86GetOptValBool(const OptionInfoRec *table, int token, B
 extern _X_EXPORT Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def);
 extern _X_EXPORT int xf86NameCmp(const char *s1, const char *s2);
 extern _X_EXPORT char *xf86NormalizeName(const char *s);
-extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist,  const char *name, const int val);
-extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist,  const char *name, const double val);
-extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val);
-extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char *name, const double val);
-extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist,  const char *name, const char* val);
+extern _X_EXPORT XF86OptionPtr xf86ReplaceIntOption(XF86OptionPtr optlist,  const char *name, const int val);
+extern _X_EXPORT XF86OptionPtr xf86ReplaceRealOption(XF86OptionPtr optlist,  const char *name, const double val);
+extern _X_EXPORT XF86OptionPtr xf86ReplaceBoolOption(XF86OptionPtr optlist, const char *name, const Bool val);
+extern _X_EXPORT XF86OptionPtr xf86ReplacePercentOption(XF86OptionPtr optlist, const char *name, const double val);
+extern _X_EXPORT XF86OptionPtr xf86ReplaceStrOption(XF86OptionPtr optlist,  const char *name, const char* val);
 #endif
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index a3a836f..73b6573 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -40,11 +40,12 @@
 #include <X11/X.h>
 #include "os.h"
 #include "xf86.h"
+#include "xf86Opt.h"
 #include "xf86Xinput.h"
 #include "xf86Optrec.h"
 #include "xf86Parser.h"
 
-static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
+static Bool ParseOptionValue(int scrnIndex, XF86OptionPtr options, OptionInfoPtr p,
 			     Bool markUsed);
 
 /*
@@ -66,7 +67,7 @@ static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
  */
 
 void
-xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)
+xf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts)
 {
     XF86OptionPtr tmp;
     XF86OptionPtr extras = (XF86OptionPtr)extraOpts;
@@ -140,10 +141,10 @@ xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts)
  * Duplicate the option list passed in. The returned pointer will be a newly
  * allocated option list and must be freed by the caller.
  */
-pointer
-xf86OptionListDuplicate(pointer options)
+XF86OptionPtr
+xf86OptionListDuplicate(XF86OptionPtr options)
 {
-    pointer o = NULL;
+    XF86OptionPtr o = NULL;
 
     while (options)
     {
@@ -158,7 +159,7 @@ xf86OptionListDuplicate(pointer options)
 /* Created for new XInput stuff -- essentially extensions to the parser	*/
 
 static int
-LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed)
+LookupIntOption(XF86OptionPtr optlist, const char *name, int deflt, Bool markUsed)
 {
     OptionInfoRec o;
 
@@ -171,7 +172,7 @@ LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed)
 
 
 static double
-LookupRealOption(pointer optlist, const char *name, double deflt,
+LookupRealOption(XF86OptionPtr optlist, const char *name, double deflt,
 		 Bool markUsed)
 {
     OptionInfoRec o;
@@ -185,7 +186,7 @@ LookupRealOption(pointer optlist, const char *name, double deflt,
 
 
 static char *
-LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed)
+LookupStrOption(XF86OptionPtr optlist, const char *name, char *deflt, Bool markUsed)
 {
     OptionInfoRec o;
 
@@ -201,7 +202,7 @@ LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed)
 
 
 static int
-LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed)
+LookupBoolOption(XF86OptionPtr optlist, const char *name, int deflt, Bool markUsed)
 {
     OptionInfoRec o;
 
@@ -213,7 +214,7 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed)
 }
 
 static double
-LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed)
+LookupPercentOption(XF86OptionPtr optlist, const char *name, double deflt, Bool markUsed)
 {
     OptionInfoRec o;
 
@@ -227,34 +228,34 @@ LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUs
 /* These xf86Set* functions are intended for use by non-screen specific code */
 
 int
-xf86SetIntOption(pointer optlist, const char *name, int deflt)
+xf86SetIntOption(XF86OptionPtr optlist, const char *name, int deflt)
 {
     return LookupIntOption(optlist, name, deflt, TRUE);
 }
 
 
 double
-xf86SetRealOption(pointer optlist, const char *name, double deflt)
+xf86SetRealOption(XF86OptionPtr optlist, const char *name, double deflt)
 {
     return LookupRealOption(optlist, name, deflt, TRUE);
 }
 
 
 char *
-xf86SetStrOption(pointer optlist, const char *name, char *deflt)
+xf86SetStrOption(XF86OptionPtr optlist, const char *name, char *deflt)
 {
     return LookupStrOption(optlist, name, deflt, TRUE);
 }
 
 
 int
-xf86SetBoolOption(pointer optlist, const char *name, int deflt)
+xf86SetBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
 {
     return LookupBoolOption(optlist, name, deflt, TRUE);
 }
 
 double
-xf86SetPercentOption(pointer optlist, const char *name, double deflt)
+xf86SetPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
 {
     return LookupPercentOption(optlist, name, deflt, TRUE);
 }
@@ -264,35 +265,35 @@ xf86SetPercentOption(pointer optlist, const char *name, double deflt)
  * as used.
  */
 int
-xf86CheckIntOption(pointer optlist, const char *name, int deflt)
+xf86CheckIntOption(XF86OptionPtr optlist, const char *name, int deflt)
 {
     return LookupIntOption(optlist, name, deflt, FALSE);
 }
 
 
 double
-xf86CheckRealOption(pointer optlist, const char *name, double deflt)
+xf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt)
 {
     return LookupRealOption(optlist, name, deflt, FALSE);
 }
 
 
 char *
-xf86CheckStrOption(pointer optlist, const char *name, char *deflt)
+xf86CheckStrOption(XF86OptionPtr optlist, const char *name, char *deflt)
 {
     return LookupStrOption(optlist, name, deflt, FALSE);
 }
 
 
 int
-xf86CheckBoolOption(pointer optlist, const char *name, int deflt)
+xf86CheckBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
 {
     return LookupBoolOption(optlist, name, deflt, FALSE);
 }
 
 
 double
-xf86CheckPercentOption(pointer optlist, const char *name, double deflt)
+xf86CheckPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
 {
     return LookupPercentOption(optlist, name, deflt, FALSE);
 }
@@ -300,44 +301,44 @@ xf86CheckPercentOption(pointer optlist, const char *name, double deflt)
  * addNewOption() has the required property of replacing the option value
  * if the option is already present.
  */
-pointer
-xf86ReplaceIntOption(pointer optlist, const char *name, const int val)
+XF86OptionPtr
+xf86ReplaceIntOption(XF86OptionPtr optlist, const char *name, const int val)
 {
     char tmp[16];
     sprintf(tmp,"%i",val);
     return xf86AddNewOption(optlist,name,tmp);
 }
 
-pointer
-xf86ReplaceRealOption(pointer optlist, const char *name, const double val)
+XF86OptionPtr
+xf86ReplaceRealOption(XF86OptionPtr optlist, const char *name, const double val)
 {
     char tmp[32];
     snprintf(tmp,32,"%f",val);
     return xf86AddNewOption(optlist,name,tmp);
 }
 
-pointer
-xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val)
+XF86OptionPtr
+xf86ReplaceBoolOption(XF86OptionPtr optlist, const char *name, const Bool val)
 {
     return xf86AddNewOption(optlist,name,val?"True":"False");
 }
 
-pointer
-xf86ReplacePercentOption(pointer optlist, const char *name, const double val)
+XF86OptionPtr
+xf86ReplacePercentOption(XF86OptionPtr optlist, const char *name, const double val)
 {
     char tmp[16];
     sprintf(tmp, "%lf%%", val);
     return xf86AddNewOption(optlist,name,tmp);
 }
 
-pointer
-xf86ReplaceStrOption(pointer optlist, const char *name, const char* val)
+XF86OptionPtr
+xf86ReplaceStrOption(XF86OptionPtr optlist, const char *name, const char* val)
 {
       return xf86AddNewOption(optlist,name,val);
 }
 
-pointer
-xf86AddNewOption(pointer head, const char *name, const char *val)
+XF86OptionPtr
+xf86AddNewOption(XF86OptionPtr head, const char *name, const char *val)
 {
     /* XXX These should actually be allocated in the parser library. */
     char *tmp = val ? strdup(val) : NULL;
@@ -347,51 +348,51 @@ xf86AddNewOption(pointer head, const char *name, const char *val)
 }
 
 
-pointer
+XF86OptionPtr
 xf86NewOption(char *name, char *value)
 {
     return xf86newOption(name, value);
 }
 
 
-pointer
-xf86NextOption(pointer list)
+XF86OptionPtr
+xf86NextOption(XF86OptionPtr list)
 {
     return xf86nextOption(list);
 }
 
-pointer
+XF86OptionPtr
 xf86OptionListCreate(const char **options, int count, int used)
 {
 	return xf86optionListCreate(options, count, used);
 }
 
-pointer
-xf86OptionListMerge(pointer head, pointer tail)
+XF86OptionPtr
+xf86OptionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
 {
 	return xf86optionListMerge(head, tail);
 }
 
 void
-xf86OptionListFree(pointer opt)
+xf86OptionListFree(XF86OptionPtr opt)
 {
 	xf86optionListFree(opt);
 }
 
 char *
-xf86OptionName(pointer opt)
+xf86OptionName(XF86OptionPtr opt)
 {
 	return xf86optionName(opt);
 }
 
 char *
-xf86OptionValue(pointer opt)
+xf86OptionValue(XF86OptionPtr opt)
 {
 	return xf86optionValue(opt);
 }
 
 void
-xf86OptionListReport(pointer parm)
+xf86OptionListReport(XF86OptionPtr parm)
 {
     XF86OptionPtr opts = parm;
 
@@ -407,30 +408,30 @@ xf86OptionListReport(pointer parm)
 
 /* End of XInput-caused section	*/
 
-pointer
-xf86FindOption(pointer options, const char *name)
+XF86OptionPtr
+xf86FindOption(XF86OptionPtr options, const char *name)
 {
     return xf86findOption(options, name);
 }
 
 
 char *
-xf86FindOptionValue(pointer options, const char *name)
+xf86FindOptionValue(XF86OptionPtr options, const char *name)
 {
     return xf86findOptionValue(options, name);
 }
 
 
 void
-xf86MarkOptionUsed(pointer option)
+xf86MarkOptionUsed(XF86OptionPtr option)
 {
     if (option != NULL)
-	((XF86OptionPtr)option)->opt_used = TRUE;
+	option->opt_used = TRUE;
 }
 
 
 void
-xf86MarkOptionUsedByName(pointer options, const char *name)
+xf86MarkOptionUsedByName(XF86OptionPtr options, const char *name)
 {
     XF86OptionPtr opt;
 
@@ -440,16 +441,16 @@ xf86MarkOptionUsedByName(pointer options, const char *name)
 }
 
 Bool
-xf86CheckIfOptionUsed(pointer option)
+xf86CheckIfOptionUsed(XF86OptionPtr option)
 {
     if (option != NULL)
-	return ((XF86OptionPtr)option)->opt_used;
+	return option->opt_used;
     else
 	return FALSE;
 }
 
 Bool
-xf86CheckIfOptionUsedByName(pointer options, const char *name)
+xf86CheckIfOptionUsedByName(XF86OptionPtr options, const char *name)
 {
     XF86OptionPtr opt;
 
@@ -461,10 +462,8 @@ xf86CheckIfOptionUsedByName(pointer options, const char *name)
 }
 
 void
-xf86ShowUnusedOptions(int scrnIndex, pointer options)
+xf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr opt)
 {
-    XF86OptionPtr opt = options;
-
     while (opt) {
 	if (opt->opt_name && !opt->opt_used) {
 	    xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n",
@@ -482,7 +481,7 @@ GetBoolValue(OptionInfoPtr p, const char *s)
 }
 
 static Bool
-ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
+ParseOptionValue(int scrnIndex, XF86OptionPtr options, OptionInfoPtr p,
 		 Bool markUsed)
 {
     char *s, *end;
@@ -695,7 +694,7 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 
 
 void
-xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo)
+xf86ProcessOptions(int scrnIndex, XF86OptionPtr options, OptionInfoPtr optinfo)
 {
     OptionInfoPtr p;
 
diff --git a/hw/xfree86/common/xf86Optionstr.h b/hw/xfree86/common/xf86Optionstr.h
new file mode 100644
index 0000000..8cc82d3
--- /dev/null
+++ b/hw/xfree86/common/xf86Optionstr.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2011 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.
+ *
+ */
+
+#ifndef XF86OPTIONSTR_H
+#define XF86OPTIONSTR_H
+
+/*
+ * all records that need to be linked lists should contain a GenericList as
+ * their first field.
+ */
+typedef struct generic_list_rec
+{
+	void *next;
+}
+GenericListRec, *GenericListPtr, *glp;
+
+/*
+ * All options are stored using this data type.
+ */
+typedef struct _XF86OptionRec
+{
+	GenericListRec list;
+	char *opt_name;
+	char *opt_val;
+	int opt_used;
+	char *opt_comment;
+}
+XF86OptionRec;
+
+typedef struct _XF86OptionRec *XF86OptionPtr;
+
+#endif
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index e25115c..114cdd9 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -276,7 +276,7 @@ ApplyAccelerationSettings(DeviceIntPtr dev){
  */
 void
 xf86ProcessCommonOptions(InputInfoPtr pInfo,
-                         pointer	list)
+                         XF86OptionPtr list)
 {
     if (xf86SetBoolOption(list, "Floating", 0) ||
         !xf86SetBoolOption(list, "AlwaysCore", 1) ||
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 1b0b16f..a4d9e58 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -103,7 +103,7 @@ typedef struct _InputInfoRec {
     char *		    type_name;
     InputDriverPtr	    drv;
     pointer		    module;
-    pointer		    options;
+    XF86OptionPtr	    options;
     InputAttributes         *attrs;
 } *InputInfoPtr;
 
@@ -144,7 +144,7 @@ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int ke
 extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
 extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
 extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y);
-extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, pointer options);
+extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr options);
 extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
 				int maxval, int resolution, int min_res,
 				int max_res, int mode);
diff --git a/hw/xfree86/doc/ddxDesign.xml b/hw/xfree86/doc/ddxDesign.xml
index 0290960..bc25c56 100644
--- a/hw/xfree86/doc/ddxDesign.xml
+++ b/hw/xfree86/doc/ddxDesign.xml
@@ -3175,7 +3175,7 @@ would not need to use these directly.
 
     <blockquote><para>
 	<programlisting>
-    pointer xf86FindOption(pointer options, const char *name);
+    XF86OptionPtr xf86FindOption(XF86OptionPtr options, const char *name);
 	</programlisting>
 	<blockquote><para>
       Takes a list of options and an option name, and returns a handle
@@ -3187,7 +3187,7 @@ would not need to use these directly.
 
     <blockquote><para>
 	<programlisting>
-    char *xf86FindOptionValue(pointer options, const char *name);
+    char *xf86FindOptionValue(XF86OptionPtr options, const char *name);
 	</programlisting>
 	<blockquote><para>
       Takes a list of options and an option name, and returns the value
@@ -3201,7 +3201,7 @@ would not need to use these directly.
 
     <blockquote><para>
 	<programlisting>
-    void xf86MarkOptionUsed(pointer option);
+    void xf86MarkOptionUsed(XF86OptionPtr option);
 	</programlisting>
 	<blockquote><para>
       Takes a handle for an option, and marks that option as used.
@@ -3211,7 +3211,7 @@ would not need to use these directly.
 
     <blockquote><para>
 	<programlisting>
-    void xf86MarkOptionUsedByName(pointer options, const char *name);
+    void xf86MarkOptionUsedByName(XF86OptionPtr options, const char *name);
 	</programlisting>
 	<blockquote><para>
       Takes a list of options and an option name and marks the first
@@ -3225,7 +3225,7 @@ Next, the higher level functions that most drivers would use.
     </para>
     <blockquote><para>
 	<programlisting>
-    void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts);
+    void xf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts);
 	</programlisting>
 	<blockquote><para>
       Collect the options from each of the config file sections used by
@@ -3245,7 +3245,7 @@ Next, the higher level functions that most drivers would use.
 
     <blockquote><para>
 	<programlisting>
-    void xf86ProcessOptions(int scrnIndex, pointer options,
+    void xf86ProcessOptions(int scrnIndex, XF86OptionPtr options,
                             OptionInfoPtr optinfo);
 	</programlisting>
 	<blockquote><para>
@@ -3354,7 +3354,7 @@ Next, the higher level functions that most drivers would use.
 
     <blockquote><para>
 	<programlisting>
-    void xf86ShowUnusedOptions(int scrnIndex, pointer options);
+    void xf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr options);
 	</programlisting>
 	<blockquote><para>
       Prints out warning messages for each option in the list of options
diff --git a/hw/xfree86/os-support/shared/posix_tty.c b/hw/xfree86/os-support/shared/posix_tty.c
index fb83860..cc12a31 100644
--- a/hw/xfree86/os-support/shared/posix_tty.c
+++ b/hw/xfree86/os-support/shared/posix_tty.c
@@ -112,7 +112,7 @@ GetBaud (int baudrate)
 }
 
 int
-xf86OpenSerial (pointer options)
+xf86OpenSerial (XF86OptionPtr options)
 {
 	struct termios t;
 	int fd, i;
@@ -185,7 +185,7 @@ xf86OpenSerial (pointer options)
 }
 
 int
-xf86SetSerial (int fd, pointer options)
+xf86SetSerial (int fd, XF86OptionPtr options)
 {
 	struct termios t;
 	int val;
diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h
index f0cb768..6a29fbd 100644
--- a/hw/xfree86/os-support/xf86_OSproc.h
+++ b/hw/xfree86/os-support/xf86_OSproc.h
@@ -126,6 +126,7 @@
 
 #include <X11/Xfuncproto.h>
 #include "opaque.h"
+#include "xf86Optionstr.h"
 
 _XFUNCPROTOBEGIN
 
@@ -145,8 +146,8 @@ extern _X_EXPORT void xf86SetRGBOut(void);
 extern _X_EXPORT void xf86OSRingBell(int, int, int);
 extern _X_EXPORT void xf86SetReallySlowBcopy(void);
 extern _X_EXPORT void xf86SlowBcopy(unsigned char *, unsigned char *, int);
-extern _X_EXPORT int xf86OpenSerial(pointer options);
-extern _X_EXPORT int xf86SetSerial(int fd, pointer options);
+extern _X_EXPORT int xf86OpenSerial(XF86OptionPtr options);
+extern _X_EXPORT int xf86SetSerial(int fd, XF86OptionPtr options);
 extern _X_EXPORT int xf86SetSerialSpeed(int fd, int speed);
 extern _X_EXPORT int xf86ReadSerial(int fd, void *buf, int count);
 extern _X_EXPORT int xf86WriteSerial(int fd, const void *buf, int count);
diff --git a/hw/xfree86/parser/Makefile.am b/hw/xfree86/parser/Makefile.am
index 1cd70e7..002cfbf 100644
--- a/hw/xfree86/parser/Makefile.am
+++ b/hw/xfree86/parser/Makefile.am
@@ -50,3 +50,5 @@ EXTRA_DIST = \
 sdk_HEADERS = \
 	xf86Parser.h \
 	xf86Optrec.h
+
+INCLUDES = -I$(srcdir)/../common
diff --git a/hw/xfree86/parser/xf86Optrec.h b/hw/xfree86/parser/xf86Optrec.h
index 5ccf728..61a8c5f 100644
--- a/hw/xfree86/parser/xf86Optrec.h
+++ b/hw/xfree86/parser/xf86Optrec.h
@@ -65,33 +65,10 @@
 #define _xf86Optrec_h_
 #include <stdio.h>
 #include <string.h>
+#include "xf86Optionstr.h"
 
 #include <X11/Xfuncproto.h>
 
-/* 
- * all records that need to be linked lists should contain a GenericList as
- * their first field.
- */
-typedef struct generic_list_rec
-{
-	void *next;
-}
-GenericListRec, *GenericListPtr, *glp;
-
-/*
- * All options are stored using this data type.
- */
-typedef struct
-{
-	GenericListRec list;
-	char *opt_name;
-	char *opt_val;
-	int opt_used;
-	char *opt_comment;
-}
-XF86OptionRec, *XF86OptionPtr;
-
-
 extern _X_EXPORT XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val);
 extern _X_EXPORT XF86OptionPtr xf86optionListDup(XF86OptionPtr opt);
 extern _X_EXPORT void xf86optionListFree(XF86OptionPtr opt);
diff --git a/test/xfree86.c b/test/xfree86.c
index 2b591cf..7012e90 100644
--- a/test/xfree86.c
+++ b/test/xfree86.c
@@ -33,14 +33,15 @@
 static void
 xfree86_option_list_duplicate(void)
 {
-    pointer options;
-    pointer duplicate;
+    XF86OptionPtr options;
+    XF86OptionPtr duplicate;
     const char *o1 = "foo",
                *o2 = "bar",
                *v1 = "one",
                *v2 = "two";
     const char *o_null= "NULL";
     char *val1, *val2;
+    XF86OptionPtr a, b;
 
     duplicate = xf86OptionListDuplicate(NULL);
     assert(!duplicate);
@@ -67,9 +68,9 @@ xfree86_option_list_duplicate(void)
     assert(strcmp(val1, v2) == 0);
     assert(strcmp(val1, val2) == 0);
 
-    val1 = xf86FindOption(options, o_null);
-    val2 = xf86FindOption(duplicate, o_null);
-    assert(val1 && val2);
+    a = xf86FindOption(options, o_null);
+    b = xf86FindOption(duplicate, o_null);
+    assert(a && b);
 }
 
 int main(int argc, char** argv)
commit 05284a03f9002b03a66ae355b34790ec02b726f0
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Aug 4 14:45:46 2011 +1000

    input: make InputOption opaque, provide interface functions.
    
    InputOptions is not switched to use struct list for a future patch to unify
    it with the XF86OptionRec.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>

diff --git a/config/config-backends.h b/config/config-backends.h
index 0d36d72..35ab8a0 100644
--- a/config/config-backends.h
+++ b/config/config-backends.h
@@ -27,10 +27,10 @@
 #include <dix-config.h>
 #endif
 #include "input.h"
+#include "list.h"
 
 void remove_devices(const char *backend, const char *config_info);
 BOOL device_is_duplicate(const char *config_info);
-InputOption* add_option(InputOption **options, const char *key, const char *value);
 
 #ifdef CONFIG_UDEV
 int config_udev_init(void);
diff --git a/config/config.c b/config/config.c
index af8f4f9..9c28785 100644
--- a/config/config.c
+++ b/config/config.c
@@ -122,25 +122,3 @@ device_is_duplicate(const char *config_info)
     return FALSE;
 }
 
-/**
- * Allocate a new option and append to the list.
- *
- * @return A pointer to the newly allocated InputOption struct.
- */
-InputOption*
-add_option(InputOption **options, const char *key, const char *value)
-{
-    if (!value || *value == '\0')
-        return NULL;
-
-    for (; *options; options = &(*options)->next)
-        ;
-    *options = calloc(sizeof(**options), 1);
-    if (!*options) /* Yeesh. */
-        return NULL;
-    (*options)->key = strdup(key);
-    (*options)->value = strdup(value);
-    (*options)->next = NULL;
-
-    return *options;
-}
diff --git a/config/dbus.c b/config/dbus.c
index 41eca99..f0fc568 100644
--- a/config/dbus.c
+++ b/config/dbus.c
@@ -68,8 +68,7 @@ static int
 add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
 {
     DBusMessageIter iter, reply_iter, subiter;
-    InputOption *tmpo = NULL, *options = NULL;
-    char *tmp = NULL;
+    InputOption *input_options = NULL;
     int ret, err;
     DeviceIntPtr dev = NULL;
 
@@ -80,7 +79,8 @@ add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
         MALFORMED_MESSAGE();
     }
 
-    if (!add_option(&options, "_source", "client/dbus")) {
+    input_options = input_option_new(input_options, "_source", "client/dbus");
+    if (!input_options) {
         ErrorF("[config/dbus] couldn't allocate first key/value pair\n");
         ret = BadAlloc;
         goto unwind;
@@ -88,36 +88,22 @@ add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
 
     /* signature should be [ss][ss]... */
     while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
-        tmpo = calloc(sizeof(*tmpo), 1);
-        if (!tmpo) {
-            ErrorF("[config/dbus] couldn't allocate option\n");
-            ret = BadAlloc;
-            goto unwind;
-        }
-        tmpo->next = options;
-        options = tmpo;
-
+        char *key, *value;
         dbus_message_iter_recurse(&iter, &subiter);
 
         if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING)
             MALFORMED_MESSAGE();
 
-        dbus_message_iter_get_basic(&subiter, &tmp);
-        if (!tmp)
+        dbus_message_iter_get_basic(&subiter, &key);
+        if (!key)
             MALFORMED_MESSAGE();
         /* The _ prefix refers to internal settings, and may not be given by
          * the client. */
-        if (tmp[0] == '_') {
+        if (key[0] == '_') {
             ErrorF("[config/dbus] attempted subterfuge: option name %s given\n",
-                   tmp);
+                   key);
             MALFORMED_MESSAGE();
         }
-        options->key = strdup(tmp);
-        if (!options->key) {
-            ErrorF("[config/dbus] couldn't duplicate key!\n");
-            ret = BadAlloc;
-            goto unwind;
-        }
 
         if (!dbus_message_iter_has_next(&subiter))
             MALFORMED_MESSAGE();
@@ -125,20 +111,16 @@ add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
         if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING)
             MALFORMED_MESSAGE();
 
-        dbus_message_iter_get_basic(&subiter, &tmp);
-        if (!tmp)
+        dbus_message_iter_get_basic(&subiter, &value);
+        if (!value)
             MALFORMED_MESSAGE();
-        options->value = strdup(tmp);
-        if (!options->value) {
-            ErrorF("[config/dbus] couldn't duplicate option!\n");
-            ret = BadAlloc;
-            goto unwind;
-        }
+
+        input_options = input_option_new(input_options, key, value);
 
         dbus_message_iter_next(&iter);
     }
 
-    ret = NewInputDeviceRequest(options, NULL, &dev);
+    ret = NewInputDeviceRequest(input_options, NULL, &dev);
     if (ret != Success) {
         DebugF("[config/dbus] NewInputDeviceRequest failed\n");
         goto unwind;
@@ -172,13 +154,7 @@ unwind:
         dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err);
     }
 
-    while (options) {
-        tmpo = options;
-        options = options->next;
-        free(tmpo->key);
-        free(tmpo->value);
-        free(tmpo);
-    }
+    input_option_free_list(&input_options);
 
     return ret;
 }
diff --git a/config/hal.c b/config/hal.c
index 0b2d7d0..aa234eb 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -128,7 +128,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
 {
     char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
     char *hal_tags, *parent;
-    InputOption *options = NULL, *tmpo = NULL;
+    InputOption *input_options = NULL;
     InputAttributes attrs = {0};
     DeviceIntPtr dev = NULL;
     DBusError error;
@@ -205,18 +205,19 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         free(parent);
     }
 
-    if (!add_option(&options, "_source", "server/hal")) {
+    input_options = input_option_new(NULL, "_source", "server/hal");
+    if (!input_options) {
         LogMessage(X_ERROR, "config/hal: couldn't allocate first key/value pair\n");
         goto unwind;
     }
 
     /* most drivers use device.. not path. evdev uses both however, but the
      * path version isn't documented apparently. support both for now. */
-    add_option(&options, "path", path);
-    add_option(&options, "device", path);
+    input_options = input_option_new(input_options, "path", path);
+    input_options = input_option_new(input_options, "device", path);
 
-    add_option(&options, "driver", driver);
-    add_option(&options, "name", name);
+    input_options = input_option_new(input_options, "driver", driver);
+    input_options = input_option_new(input_options, "name", name);
 
     if (asprintf (&config_info, "hal:%s", udi) == -1) {
         config_info = NULL;
@@ -290,7 +291,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
                     } else
                     {
                         /* all others */
-                        add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
+                        input_options = input_option_new(input_options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
                         free(tmp_val);
                     }
                 } else
@@ -358,20 +359,20 @@ device_added(LibHalContext *hal_ctx, const char *udi)
 
     /* Now add xkb options */
     if (xkb_opts.layout)
-        add_option(&options, "xkb_layout", xkb_opts.layout);
+        input_options = input_option_new(input_options, "xkb_layout", xkb_opts.layout);
     if (xkb_opts.rules)
-        add_option(&options, "xkb_rules", xkb_opts.rules);
+        input_options = input_option_new(input_options, "xkb_rules", xkb_opts.rules);
     if (xkb_opts.variant)
-        add_option(&options, "xkb_variant", xkb_opts.variant);
+        input_options = input_option_new(input_options, "xkb_variant", xkb_opts.variant);
     if (xkb_opts.model)
-        add_option(&options, "xkb_model", xkb_opts.model);
+        input_options = input_option_new(input_options, "xkb_model", xkb_opts.model);
     if (xkb_opts.options)
-        add_option(&options, "xkb_options", xkb_opts.options);
-    add_option(&options, "config_info", config_info);
+        input_options = input_option_new(input_options, "xkb_options", xkb_opts.options);
+    input_options = input_option_new(input_options, "config_info", config_info);
 
     /* this isn't an error, but how else do you output something that the user can see? */
     LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
-    if ((rc = NewInputDeviceRequest(options, &attrs, &dev)) != Success) {
+    if ((rc = NewInputDeviceRequest(input_options, &attrs, &dev)) != Success) {
         LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n", rc);
         dev = NULL;
         goto unwind;
@@ -384,12 +385,7 @@ unwind:
     free(driver);
     free(name);
     free(config_info);
-    while ((tmpo = options)) {
-        options = tmpo->next;
-        free(tmpo->key);        /* NULL if dev != NULL */
-        free(tmpo->value);      /* NULL if dev != NULL */
-        free(tmpo);
-    }
+    input_option_free_list(&input_options);
 
     free(attrs.product);
     free(attrs.vendor);
diff --git a/config/udev.c b/config/udev.c
index 1f431c1..1ba0d50 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -60,7 +60,7 @@ device_added(struct udev_device *udev_device)
     const char *syspath;
     const char *tags_prop;
     const char *key, *value, *tmp;
-    InputOption *options = NULL, *tmpo;
+    InputOption *input_options;
     InputAttributes attrs = {};
     DeviceIntPtr dev = NULL;
     struct udev_list_entry *set, *entry;
@@ -93,8 +93,9 @@ device_added(struct udev_device *udev_device)
         return;
     }
 
-    if (!add_option(&options, "_source", "server/udev"))
-        goto unwind;
+    input_options = input_option_new(NULL, "_source", "server/udev");
+    if (!input_options)
+        return;
 
     parent = udev_device_get_parent(udev_device);
     if (parent) {
@@ -127,10 +128,9 @@ device_added(struct udev_device *udev_device)
         name = "(unnamed)";
     else
         attrs.product = strdup(name);
-    add_option(&options, "name", name);
-
-    add_option(&options, "path", path);
-    add_option(&options, "device", path);
+    input_options = input_option_new(input_options, "name", name);
+    input_options = input_option_new(input_options, "path", path);
+    input_options = input_option_new(input_options, "device", path);
     if (path)
         attrs.device = strdup(path);
 
@@ -160,15 +160,15 @@ device_added(struct udev_device *udev_device)
             LOG_PROPERTY(path, key, value);
             tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
             if (!strcasecmp(tmp, "rules"))
-                add_option(&options, "xkb_rules", value);
+                input_options = input_option_new(input_options, "xkb_rules", value);
             else if (!strcasecmp(tmp, "layout"))
-                add_option(&options, "xkb_layout", value);
+                input_options = input_option_new(input_options, "xkb_layout", value);
             else if (!strcasecmp(tmp, "variant"))
-                add_option(&options, "xkb_variant", value);
+                input_options = input_option_new(input_options, "xkb_variant", value);
             else if (!strcasecmp(tmp, "model"))
-                add_option(&options, "xkb_model", value);
+                input_options = input_option_new(input_options, "xkb_model", value);
             else if (!strcasecmp(tmp, "options"))
-                add_option(&options, "xkb_options", value);
+                input_options = input_option_new(input_options, "xkb_options", value);
         } else if (!strcmp(key, "ID_VENDOR")) {
             LOG_PROPERTY(path, key, value);
             attrs.vendor = strdup(value);
@@ -193,22 +193,17 @@ device_added(struct udev_device *udev_device)
         }
     }
 
-    add_option(&options, "config_info", config_info);
+    input_options = input_option_new(input_options, "config_info", config_info);
 
     LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
                name, path);
-    rc = NewInputDeviceRequest(options, &attrs, &dev);
+    rc = NewInputDeviceRequest(input_options, &attrs, &dev);
     if (rc != Success)
         goto unwind;
 
  unwind:
     free(config_info);
-    while ((tmpo = options)) {
-        options = tmpo->next;
-        free(tmpo->key);        /* NULL if dev != NULL */
-        free(tmpo->value);      /* NULL if dev != NULL */
-        free(tmpo);
-    }
+    input_option_free_list(&input_options);
 
     free(attrs.usb_id);
     free(attrs.pnp_id);
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 9632076..7aeb1e5 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -598,3 +598,144 @@ void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
     event->deviceid = dev->id;
     event->sourceid = dev->id;
 }
+
+/**
+ * Delete the element with the key from the list, freeing all memory
+ * associated with the element..
+ */
+static void
+input_option_free(InputOption *o)
+{
+    free(o->key);
+    free(o->value);
+    free(o);
+}
+
+/*
+ * Create a new InputOption with the key/value pair provided.
+ * If a list is provided, the new options is added to the list and the list
+ * is returned.
+ *
+ * If a new option is added to a list that already contains that option, the
+ * previous option is overwritten.
+ *
+ * @param list The list to add to.
+ * @param key Option key, will be copied.
+ * @param value Option value, will be copied.
+ *
+ * @return If list is not NULL, the list with the new option added. If list
+ * is NULL, a new option list with one element. On failure, NULL is
+ * returned.
+ */
+InputOption*
+input_option_new(InputOption* list, const char *key, const char *value)
+{
+    InputOption *opt = NULL;
+
+    if (!key)
+        return NULL;
+
+    if (list)
+    {
+        nt_list_for_each_entry(opt, list, next)
+        {
+            if (strcmp(input_option_get_key(opt), key) == 0)
+            {
+                input_option_set_value(opt, value);
+                return list;
+            }
+        }
+    }
+
+    opt = calloc(1, sizeof(InputOption));
+    if (!opt)
+        return NULL;
+
+    nt_list_init(opt, next);
+    input_option_set_key(opt, key);
+    input_option_set_value(opt, value);
+
+    if (list)
+    {
+        nt_list_append(opt, list, InputOption, next);
+        return list;
+    } else
+        return opt;
+}
+
+InputOption*
+input_option_free_element(InputOption *list, const char *key)
+{
+    InputOption *element;
+
+    nt_list_for_each_entry(element, list, next) {
+        if (strcmp(input_option_get_key(element), key) == 0) {
+            nt_list_del(element, list, InputOption, next);
+            input_option_free(element);
+            break;
+        }
+    }
+    return list;
+}
+
+/**
+ * Free the list pointed at by opt.
+ */
+void
+input_option_free_list(InputOption **opt)
+{
+    InputOption *element, *tmp;
+
+    nt_list_for_each_entry_safe(element, tmp, *opt, next) {
+        nt_list_del(element, *opt, InputOption, next);
+        input_option_free(element);
+    }
+    *opt = NULL;
+}
+
+
+/**
+ * Find the InputOption with the given option name.
+ *
+ * @return The InputOption or NULL if not present.
+ */
+InputOption*
+input_option_find(InputOption *list, const char *key)
+{
+    InputOption *element;
+
+    nt_list_for_each_entry(element, list, next) {
+        if (strcmp(input_option_get_key(element), key) == 0)
+            return element;
+    }
+
+    return NULL;
+}
+
+const char*
+input_option_get_key(const InputOption *opt)
+{
+    return opt->key;
+}
+
+const char*
+input_option_get_value(const InputOption *opt)
+{
+    return opt->value;
+}
+
+void
+input_option_set_key(InputOption *opt, const char *key)
+{
+    free(opt->key);
+    if (key)
+        opt->key = strdup(key);
+}
+
+void
+input_option_set_value(InputOption *opt, const char *value)
+{
+    free(opt->value);
+    if (value)
+        opt->value = strdup(value);
+}
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 83d5cae..e25115c 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -879,35 +879,35 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
     if (!pInfo)
         return BadAlloc;
 
-    for (option = options; option; option = option->next) {
-        if (strcasecmp(option->key, "driver") == 0) {
+    nt_list_for_each_entry(option, options, next) {
+        if (strcasecmp(input_option_get_key(option), "driver") == 0) {
             if (pInfo->driver) {
                 rval = BadRequest;
                 goto unwind;
             }
-            pInfo->driver = xstrdup(option->value);
+            pInfo->driver = xstrdup(input_option_get_value(option));
             if (!pInfo->driver) {
                 rval = BadAlloc;
                 goto unwind;
             }
         }
 
-        if (strcasecmp(option->key, "name") == 0 ||
-            strcasecmp(option->key, "identifier") == 0) {
+        if (strcasecmp(input_option_get_key(option), "name") == 0 ||
+            strcasecmp(input_option_get_key(option), "identifier") == 0) {
             if (pInfo->name) {
                 rval = BadRequest;
                 goto unwind;
             }
-            pInfo->name = xstrdup(option->value);
+            pInfo->name = xstrdup(input_option_get_value(option));
             if (!pInfo->name) {
                 rval = BadAlloc;
                 goto unwind;
             }
         }
 
-        if (strcmp(option->key, "_source") == 0 &&
-            (strcmp(option->value, "server/hal") == 0 ||
-             strcmp(option->value, "server/udev") == 0)) {
+        if (strcmp(input_option_get_key(option), "_source") == 0 &&
+            (strcmp(input_option_get_value(option), "server/hal") == 0 ||
+             strcmp(input_option_get_value(option), "server/udev") == 0)) {
             is_auto = 1;
             if (!xf86Info.autoAddDevices) {
                 rval = BadMatch;
@@ -916,13 +916,11 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
         }
     }
 
-    for (option = options; option; option = option->next) {
-        /* Steal option key/value strings from the provided list.
-         * We need those strings, the InputOption list doesn't. */
-        pInfo->options = xf86addNewOption(pInfo->options,
-                                               option->key, option->value);
-        option->key = NULL;
-        option->value = NULL;
+    nt_list_for_each_entry(option, options, next) {
+        /* Copy option key/value strings from the provided list */
+        pInfo->options = xf86AddNewOption(pInfo->options,
+                                          input_option_get_key(option),
+                                          input_option_get_value(option));
     }
 
     /* Apply InputClass settings */
diff --git a/include/input.h b/include/input.h
index 5377a0c..0258f4f 100644
--- a/include/input.h
+++ b/include/input.h
@@ -56,6 +56,7 @@ SOFTWARE.
 #include "window.h"     /* for WindowPtr */
 #include "xkbrules.h"
 #include "events.h"
+#include "list.h"
 
 #define DEVICE_INIT	0
 #define DEVICE_ON	1
@@ -202,11 +203,7 @@ typedef struct {
 extern _X_EXPORT KeybdCtrl	defaultKeyboardControl;
 extern _X_EXPORT PtrCtrl	defaultPointerControl;
 
-typedef struct _InputOption {
-    char                *key;
-    char                *value;
-    struct _InputOption *next;
-} InputOption;
+typedef struct _InputOption InputOption;
 
 typedef struct _InputAttributes {
     char                *product;
@@ -595,4 +592,14 @@ extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest,
                                          const ValuatorMask *src);
 extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum);
 
+/* InputOption handling interface */
+extern _X_EXPORT InputOption* input_option_new(InputOption *list, const char *key, const char *value);
+extern _X_EXPORT void input_option_free_list(InputOption **opt);
+extern _X_EXPORT InputOption* input_option_free_element(InputOption *opt, const char *key);
+extern _X_EXPORT InputOption* input_option_find(InputOption *list, const char *key);
+extern _X_EXPORT const char* input_option_get_key(const InputOption *opt);
+extern _X_EXPORT const char* input_option_get_value(const InputOption *opt);
+extern _X_EXPORT void input_option_set_key(InputOption *opt, const char* key);
+extern _X_EXPORT void input_option_set_value(InputOption *opt, const char* value);
+
 #endif /* INPUT_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index 838f9f0..480e956 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -602,4 +602,11 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite)
     return sprite->spriteTrace[sprite->spriteTraceGood - 1];
 }
 
+struct _InputOption {
+    char                *key;
+    char                *value;
+    struct _InputOption *next;
+};
+
+
 #endif /* INPUTSTRUCT_H */
diff --git a/test/input.c b/test/input.c
index 5d4cbf6..b8dad1c 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1308,6 +1308,95 @@ static void dix_get_master(void)
 }
 
 
+static void input_option_test(void)
+{
+    InputOption *list = NULL;
+    InputOption *opt;
+    const char *val;
+
+    printf("Testing input_option list interface\n");
+
+    list = input_option_new(list, "key", "value");
+    assert(list);
+    opt = input_option_find(list, "key");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "value") == 0);
+
+    list = input_option_new(list, "2", "v2");
+    opt = input_option_find(list, "key");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "value") == 0);
+
+    opt = input_option_find(list, "2");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "v2") == 0);
+
+    list = input_option_new(list, "3", "v3");
+
+    /* search, delete */
+    opt = input_option_find(list, "key");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "value") == 0);
+    list = input_option_free_element(list, "key");
+    opt = input_option_find(list, "key");
+    assert(opt == NULL);
+
+    opt = input_option_find(list, "2");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "v2") == 0);
+    list = input_option_free_element(list, "2");
+    opt = input_option_find(list, "2");
+    assert(opt == NULL);
+
+    opt = input_option_find(list, "3");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "v3") == 0);
+    list = input_option_free_element(list, "3");
+    opt = input_option_find(list, "3");
+    assert(opt == NULL);
+
+    /* list deletion */
+    list = input_option_new(list, "1", "v3");
+    list = input_option_new(list, "2", "v3");
+    list = input_option_new(list, "3", "v3");
+    input_option_free_list(&list);
+
+    assert(list == NULL);
+
+    list = input_option_new(list, "1", "v1");
+    list = input_option_new(list, "2", "v2");
+    list = input_option_new(list, "3", "v3");
+
+    /* value replacement */
+    opt = input_option_find(list, "2");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "v2") == 0);
+    input_option_set_value(opt, "foo");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "foo") == 0);
+    opt = input_option_find(list, "2");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "foo") == 0);
+
+    /* key replacement */
+    input_option_set_key(opt, "bar");
+    val = input_option_get_key(opt);
+    assert(strcmp(val, "bar") == 0);
+    opt = input_option_find(list, "bar");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "foo") == 0);
+
+    /* value replacement in input_option_new */
+    list = input_option_new(list, "bar", "foobar");
+    opt = input_option_find(list, "bar");
+    val = input_option_get_value(opt);
+    assert(strcmp(val, "foobar") == 0);
+
+    input_option_free_list(&list);
+    assert(list == NULL);
+}
+
+
 int main(int argc, char** argv)
 {
     dix_input_valuator_masks();
@@ -1324,6 +1413,7 @@ int main(int argc, char** argv)
     xi_unregister_handlers();
     dix_valuator_alloc();
     dix_get_master();
+    input_option_test();
 
     return 0;
 }
commit fcafe825751bef99f4c0b36250ca6f15f127502f
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 8 15:21:46 2011 +1000

    Add null-terminated list interface.
    
    This is a set of macros to provide a struct list-alike interface for classic
    linked lists such as the XF86OptionRec or the DeviceIntRec. The typical
    format for these is to have a "struct foo *next" pointer in each struct foo
    and walk through those. These macros provide a few basic functions to add to,
    remove from and iterate through these lists.
    
    While struct list is in some ways more flexible, switching legacy code to
    use struct list is not alway viable. These macros at least reduce the amount
    of open-coded lists.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/include/list.h b/include/list.h
index 5933b97..7825dce 100644
--- a/include/list.h
+++ b/include/list.h
@@ -278,4 +278,164 @@ list_is_empty(struct list *head)
 	 &pos->member != (head);					\
 	 pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
 
+
+
+/* NULL-Terminated List Interface
+ *
+ * The interface below does _not_ use the struct list as described above.
+ * It is mainly for legacy structures that cannot easily be switched to
+ * struct list.
+ *
+ * This interface is for structs like
+ *      struct foo {
+ *          [...]
+ *          struct foo *next;
+ *           [...]
+ *      };
+ *
+ * The position and field name of "next" are arbitrary.
+ */
+
+/**
+ * Init the element as null-terminated list.
+ *
+ * Example:
+ * struct foo *list = malloc();
+ * nt_list_init(list, next);
+ *
+ * @param list The list element that will be the start of the list
+ * @param member Member name of the field pointing to next struct
+ */
+#define nt_list_init(_list, _member) \
+	(_list)->_member = NULL
+
+/**
+ * Returns the next element in the list or NULL on termination.
+ *
+ * Example:
+ * struct foo *element = list;
+ * while ((element = nt_list_next(element, next)) { }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param list The list or current element.
+ * @param member Member name of the field pointing to next struct.
+ */
+#define nt_list_next(_list, _member) \
+	(_list)->_member
+
+/**
+ * Iterate through each element in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * nt_list_for_each_entry(iterator, list, next) {
+ *      [modify iterator]
+ * }
+ *
+ * @param entry Assigned to the current list element
+ * @param list The list to iterate through.
+ * @param member Member name of the field pointing to next struct.
+ */
+#define nt_list_for_each_entry(_entry, _list, _member)			\
+	for (_entry = _list; _entry; _entry = (_entry)->_member)
+
+/**
+ * Iterate through each element in the list, keeping a backup pointer to the
+ * element. This macro allows for the deletion of a list element while
+ * looping through the list.
+ *
+ * See nt_list_for_each_entry for more details.
+ *
+ * @param entry Assigned to the current list element
+ * @param tmp The pointer to the next element
+ * @param list The list to iterate through.
+ * @param member Member name of the field pointing to next struct.
+ */
+#define nt_list_for_each_entry_safe(_entry, _tmp, _list, _member)	\
+	for (_entry = _list, _tmp = (_entry) ? (_entry)->_member : NULL;\
+		_entry;							\
+		_entry = _tmp, _tmp = (_tmp) ? (_tmp)->_member: NULL)
+
+
+/**
+ * Append the element to the end of the list. This macro may be used to
+ * merge two lists.
+ *
+ * Example:
+ * struct foo *elem = malloc(...);
+ * nt_list_init(elem, next)
+ * nt_list_append(elem, list, struct foo, next);
+ *
+ * Resulting list order:
+ * list_item_0 -> list_item_1 -> ... -> elem_item_0 -> elem_item_1 ...
+ *
+ * @param entry An entry (or list) to append to the list
+ * @param list The list to append to. This list must be a valid list, not
+ * NULL.
+ * @param type The list type
+ * @param member Member name of the field pointing to next struct
+ */
+#define nt_list_append(_entry, _list, _type, _member)		        \
+    do {								\
+	_type *__iterator = _list;					\
+	while (__iterator->_member) { __iterator = __iterator->_member;}\
+	__iterator->_member = _entry;					\
+    } while (0)
+
+/**
+ * Insert the element at the next position in the list. This macro may be
+ * used to insert a list into a list.
+ *
+ * struct foo *elem = malloc(...);
+ * nt_list_init(elem, next)
+ * nt_list_insert(elem, list, struct foo, next);
+ *
+ * Resulting list order:
+ * list_item_0 -> elem_item_0 -> elem_item_1 ... -> list_item_1 -> ...
+ *
+ * @param entry An entry (or list) to append to the list
+ * @param list The list to insert to. This list must be a valid list, not
+ * NULL.
+ * @param type The list type
+ * @param member Member name of the field pointing to next struct
+ */
+#define nt_list_insert(_entry, _list, _type, _member)			\
+    do {								\
+	nt_list_append((_list)->_member, _entry, _type, _member);	\
+	(_list)->_member = _entry;					\
+    } while (0)
+
+/**
+ * Delete the entry from the list by iterating through the list and
+ * removing any reference from the list to the entry.
+ *
+ * Example:
+ * struct foo *elem = <assign to right element>
+ * nt_list_del(elem, list, struct foo, next);
+ *
+ * @param entry The entry to delete from the list. entry is always
+ * re-initialized as a null-terminated list.
+ * @param list The list containing the entry, set to the new list without
+ * the removed entry.
+ * @param type The list type
+ * @param member Member name of the field pointing to the next entry
+ */
+#define nt_list_del(_entry, _list, _type, _member)		\
+	do {							\
+		_type *__e = _entry;				\
+		if (__e == NULL) break;				\
+		if ((_list) == __e) {				\
+		    _list = __e->_member;			\
+		} else {					\
+		    _type *__prev = _list;			\
+		    while (__prev->_member && __prev->_member != __e)	\
+			__prev = nt_list_next(__prev, _member);	\
+		    if (__prev->_member)			\
+			__prev->_member = __e->_member;		\
+		}						\
+		nt_list_init(__e, _member);			\
+	} while(0)
+
 #endif
diff --git a/test/list.c b/test/list.c
index b101c76..f7d7bff 100644
--- a/test/list.c
+++ b/test/list.c
@@ -29,6 +29,7 @@
 #include <list.h>
 #include <string.h>
 #include <assert.h>
+#include <stdlib.h>
 
 struct parent {
     int a;
@@ -161,6 +162,164 @@ test_list_for_each(void)
     }
 }
 
+struct foo {
+    char a;
+    struct foo *next;
+    char b;
+};
+
+static void
+test_nt_list_init(void)
+{
+    struct foo foo;
+
+    foo.a = 10;
+    foo.b = 20;
+    nt_list_init(&foo, next);
+
+    assert(foo.a == 10);
+    assert(foo.b == 20);
+    assert(foo.next == NULL);
+    assert(nt_list_next(&foo, next) == NULL);
+}
+
+static void
+test_nt_list_append(void)
+{
+    int i;
+    struct foo *foo = calloc(10, sizeof(struct foo));
+    struct foo *item;
+
+    for (item = foo, i = 1; i <= 10; i++, item++)
+    {
+	item->a = i;
+	item->b = i * 2;
+	nt_list_init(item, next);
+
+	if (item != foo)
+	    nt_list_append(item, foo, struct foo, next);
+    }
+
+    /* Test using nt_list_next */
+    for (item = foo, i = 1; i <= 10; i++, item = nt_list_next(item, next))
+    {
+	assert(item->a = i);
+	assert(item->b = i * 2);
+    }
+
+    /* Test using nt_list_for_each_entry */
+    i = 1;
+    nt_list_for_each_entry(item, foo, next) {
+	assert(item->a = i);
+	assert(item->b = i * 2);
+	i++;
+    }
+    assert(i == 11);
+}
+
+static void
+test_nt_list_insert(void)
+{
+    int i;
+    struct foo *foo = calloc(10, sizeof(struct foo));
+    struct foo *item;
+
+    foo->a = 10;
+    foo->b = 20;
+    nt_list_init(foo, next);
+
+    for (item = &foo[1], i = 9; i > 0; i--, item++)
+    {
+	item->a = i;
+	item->b = i * 2;
+	nt_list_init(item, next);
+	nt_list_insert(item, foo, struct foo, next);
+    }
+
+    /* Test using nt_list_next */
+    for (item = foo, i = 10; i > 0; i--, item = nt_list_next(item, next))
+    {
+	assert(item->a = i);
+	assert(item->b = i * 2);
+    }
+
+    /* Test using nt_list_for_each_entry */
+    i = 1;
+    nt_list_for_each_entry(item, foo, next) {
+	assert(item->a = i);
+	assert(item->b = i * 2);
+	i++;
+    }
+    assert(i == 11);
+}
+
+static void
+test_nt_list_delete(void)
+{
+    int i = 1;
+    struct foo *list = calloc(10, sizeof(struct foo));
+    struct foo *foo = list;
+    struct foo *item, *tmp;
+    struct foo *empty_list = foo;
+
+    nt_list_init(empty_list, next);
+    nt_list_del(empty_list, empty_list, struct foo, next);
+    assert(!empty_list);
+
+    for (item = foo, i = 1; i <= 10; i++, item++)
+    {
+	item->a = i;
+	item->b = i * 2;
+	nt_list_init(item, next);
+
+	if (item != foo)
+	    nt_list_append(item, foo, struct foo, next);
+    }
+
+    i = 0;
+    nt_list_for_each_entry(item, foo, next) {
+	i++;
+    }
+    assert(i == 10);
+
+    /* delete last item */
+    nt_list_del(&foo[9], foo, struct foo, next);
+    i = 0;
+    nt_list_for_each_entry(item, foo, next) {
+	assert(item->a != 10); /* element 10 is gone now */
+	i++;
+    }
+    assert(i == 9); /* 9 elements left */
+
+    /* delete second item */
+    nt_list_del(foo->next, foo, struct foo, next);
+    assert(foo->next->a == 3);
+
+    i = 0;
+    nt_list_for_each_entry(item, foo, next) {
+	assert(item->a != 10); /* element 10 is gone now */
+	assert(item->a != 2); /* element 2 is gone now */
+	i++;
+    }
+    assert(i == 8); /* 9 elements left */
+
+    item = foo;
+    /* delete first item */
+    nt_list_del(foo, foo, struct foo, next);
+    assert(item != foo);
+    assert(item->next == NULL);
+    assert(foo->a == 3);
+    assert(foo->next->a == 4);
+
+    nt_list_for_each_entry_safe(item, tmp, foo, next) {
+	nt_list_del(item, foo, struct foo, next);
+    }
+
+    assert(!foo);
+    assert(!item);
+
+    free(list);
+}
 
 int main(int argc, char** argv)
 {
@@ -169,5 +328,10 @@ int main(int argc, char** argv)
     test_list_del();
     test_list_for_each();
 
+    test_nt_list_init();
+    test_nt_list_append();
+    test_nt_list_insert();
+    test_nt_list_delete();
+
     return 0;
 }
commit 79ca7c0b5786a02a80a1c40ed475e928da7c82b3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Aug 12 15:55:48 2011 +1000

    xfree86: comment typo fix
    
    in synch → in sync
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index d22fdc8..83d5cae 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -1348,7 +1348,7 @@ xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
 }
 
 /*
- * Set the valuator values to be in synch with dix/event.c
+ * Set the valuator values to be in sync with dix/event.c
  * DefineInitialRootWindow().
  */
 void
commit 2bfb802839688ecf328119c4c6979390fc60348d
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jul 29 16:33:54 2011 +1000

    dix: don't XWarpPointer through the last slave anymore (#38313)
    
    This line was introduced pre-1.6 to fix Bug 19297. The effect of warping
    through the VCP then was that if a device had custom valuator ranges, the
    warp position would be wrong. The better device for this effect is the the
    XTest device.
    
    This fixes a server crash where the lastSlave is a pointer device without
    valuators (Bug 38313#0).
    
    And while we're at it, make sure the Xinerama code-path does the same.
    
    X.Org Bug 38313 <http://bugs.freedesktop.org/show_bug.cgi?id=38313>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/events.c b/dix/events.c
index 27c3172..7fe0fba 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3377,16 +3377,21 @@ XineramaWarpPointer(ClientPtr client)
 {
     WindowPtr	dest = NULL;
     int		x, y, rc;
-    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
+    DeviceIntPtr dev;
+    SpritePtr   pSprite;
 
     REQUEST(xWarpPointerReq);
 
-
     if (stuff->dstWid != None) {
 	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
 	if (rc != Success)
 	    return rc;
     }
+
+    /* Post through the XTest device */
+    dev = PickPointer(client);
+    dev = GetXTestDevice(dev);
+    pSprite = dev->spriteInfo->sprite;
     x = pSprite->hotPhys.x;
     y = pSprite->hotPhys.y;
 
@@ -3436,9 +3441,9 @@ XineramaWarpPointer(ClientPtr client)
     else if (y >= pSprite->physLimits.y2)
 	y = pSprite->physLimits.y2 - 1;
     if (pSprite->hotShape)
-	ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
+	ConfineToShape(dev, pSprite->hotShape, &x, &y);
 
-    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
+    XineramaSetCursorPosition(dev, x, y, TRUE);
 
     return Success;
 }
@@ -3456,7 +3461,7 @@ ProcWarpPointer(ClientPtr client)
     WindowPtr	dest = NULL;
     int		x, y, rc;
     ScreenPtr	newScreen;
-    DeviceIntPtr dev, tmp;
+    DeviceIntPtr dev, tmp, xtest_dev = NULL;
     SpritePtr   pSprite;
 
     REQUEST(xWarpPointerReq);
@@ -3469,11 +3474,13 @@ ProcWarpPointer(ClientPtr client)
 	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
 	    if (rc != Success)
 		return rc;
+            if (IsXTestDevice(tmp, dev))
+                xtest_dev = tmp;
 	}
     }
 
-    if (dev->lastSlave)
-        dev = dev->lastSlave;
+    /* Use the XTest device to actually move the pointer */
+    dev = xtest_dev;
     pSprite = dev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
commit b29ce0726d55ec41cfbce0814e21b0217ef64efe
Author: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
Date:   Tue Aug 9 11:00:34 2011 +0900

    Disable check of double-aligned in test/input.c on Renesas SH
    
    Renesas SH is not aligned at size of double.
    When structure has double value, It is aligned in 4byte (long).
    
    Signed-off-by: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/test/input.c b/test/input.c
index c2b0eb0..5d4cbf6 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1223,7 +1223,7 @@ static void dix_valuator_alloc(void)
 
         assert(v);
         assert(v->numAxes == num_axes);
-#ifndef __i386__
+#if !defined(__i386__) && !defined(__sh__)
         /* must be double-aligned on 64 bit */
         assert(((void*)v->axisVal - (void*)v) % sizeof(double) == 0);
         assert(((void*)v->axes - (void*)v) % sizeof(double) == 0);
commit 3be379f5076566edaf92c27df5a4d447bcf5d015
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Aug 11 10:59:07 2011 +1000

    dix: use helper functions in EventIsDeliverable
    
    Proximity events don't have an XI2 type and caused error messages in the
    log when trying to get the event filter. Use this opportunity to
    clean up the code, instead of manually setting the fields that
    GetEventFilter requires use EventTo(XI2|XI|Core) instead.
    
    Co-Authored-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/events.c b/dix/events.c
index 0e22fdc..27c3172 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2503,44 +2503,45 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
     int filter = 0;
     int type;
     OtherInputMasks *inputMasks = wOtherInputMasks(win);
-    xEvent ev;
-
-    /* XXX: this makes me gag */
-    type = GetXI2Type(event);
-    ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
-    ((xGenericEvent*)&ev)->extension = IReqCode;
-    ((xGenericEvent*)&ev)->evtype = type;
-    filter = GetEventFilter(dev, &ev);
-    if (type && inputMasks &&
-        ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
-         ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
-         (inputMasks->xi2mask[dev->id][type/8] & filter)))
-        rc |= EVENT_XI2_MASK;
-
-    type = GetXIType(event);
-    ev.u.u.type = type;
-    filter = GetEventFilter(dev, &ev);
-
-    /* Check for XI mask */
-    if (type && inputMasks &&
-        (inputMasks->deliverableEvents[dev->id] & filter) &&
-        (inputMasks->inputEvents[dev->id] & filter))
-        rc |= EVENT_XI1_MASK;
-
-    /* Check for XI DontPropagate mask */
-    if (type && inputMasks &&
-        (inputMasks->dontPropagateMask[dev->id] & filter))
-        rc |= EVENT_DONT_PROPAGATE_MASK;
-
-    /* Check for core mask */
-    type = GetCoreType(event);
-    if (type && (win->deliverableEvents & filter) &&
-        ((wOtherEventMasks(win) | win->eventMask) & filter))
-        rc |= EVENT_CORE_MASK;
-
-    /* Check for core DontPropagate mask */
-    if (type && (filter & wDontPropagateMask(win)))
-        rc |= EVENT_DONT_PROPAGATE_MASK;
+
+    if ((type = GetXI2Type(event)) != 0)
+    {
+        filter = GetXI2EventFilterMask(type);
+
+        if (inputMasks &&
+            (GetXI2MaskByte(inputMasks->xi2mask,  dev, type) & filter))
+            rc |= EVENT_XI2_MASK;
+    }
+
+    if ((type = GetXIType(event)) != 0)
+    {
+        filter = GetEventFilterMask(dev, type);
+
+        /* Check for XI mask */
+        if (inputMasks &&
+            (inputMasks->deliverableEvents[dev->id] & filter) &&
+            (inputMasks->inputEvents[dev->id] & filter))
+            rc |= EVENT_XI1_MASK;
+
+        /* Check for XI DontPropagate mask */
+        if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
+            rc |= EVENT_DONT_PROPAGATE_MASK;
+
+    }
+
+    if ((type = GetCoreType(event)) != 0)
+    {
+        filter = GetEventFilterMask(dev, type);
+
+        /* Check for core mask */
+        if ((win->deliverableEvents & filter) &&
+            ((wOtherEventMasks(win) | win->eventMask) & filter))
+            rc |= EVENT_CORE_MASK;
+
+        /* Check for core DontPropagate mask */
+        if (filter & wDontPropagateMask(win))
+            rc |= EVENT_DONT_PROPAGATE_MASK;
+    }
 
     return rc;
 }
commit 799879797505a5e891ccaec2bea73fd838c94b7a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Aug 11 10:57:05 2011 +1000

    dix: abstract XI2 filter mask lookup
    
    Don't access the xi2mask bytes directly or calculate the offsets manually,
    use a few helper functions instead. XI2 masks are a bit weird in the event
    handling code since they slot onto the legacy code. For core/XI 1.x events,
    the event mask is a CARD32. That mask is used together with the event filter
    (also 32 bit) to determine if event delivery should be attempted.
    XI2 masks are of arbitrary size and their mask is simply the byte of the
    mask that contains the event mask. Likewise, the filter is a single byte
    matching that mask. Provide helper functions get these bytes and masks in
    the right order instead of accessing them manually.
    
    EventIsDeliverable should be part of this cleanup patch but it will be
    gutted with the next patch.
    
    Co-Authored-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/events.c b/dix/events.c
index 8e07532..0e22fdc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -408,6 +408,24 @@ static const Mask default_filter[128] =
 	CantBeFiltered		       /* MappingNotify */
 };
 
+static inline Mask
+GetEventFilterMask(DeviceIntPtr dev, int evtype)
+{
+    return filters[dev ? dev->id : 0][evtype];
+}
+
+static inline Mask
+GetXI2EventFilterMask(int evtype)
+{
+    return (1 << (evtype % 8));
+}
+
+static inline int
+GetXI2EventFilterOffset(int evtype)
+{
+    return (evtype / 8);
+}
+
 /**
  * For the given event, return the matching event filter. This filter may then
  * be AND'ed with the selected event mask.
@@ -429,14 +447,28 @@ GetEventFilter(DeviceIntPtr dev, xEvent *event)
     int evtype = 0;
 
     if (event->u.u.type != GenericEvent)
-        return filters[dev ? dev->id : 0][event->u.u.type];
+        return GetEventFilterMask(dev, event->u.u.type);
     else if ((evtype = xi2_get_type(event)))
-        return (1 << (evtype % 8));
+        return GetXI2EventFilterMask(evtype);
     ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
     return 0;
 }
 
 /**
+ * Return the single byte of the device's XI2 mask that contains the mask
+ * for the event_type.
+ */
+static int
+GetXI2MaskByte(unsigned char xi2mask[][XI2MASKSIZE], DeviceIntPtr dev, int event_type)
+{
+    int byte = GetXI2EventFilterOffset(event_type);
+    return xi2mask[dev->id][byte] |
+           xi2mask[XIAllDevices][byte] |
+           (IsMaster(dev) ? xi2mask[XIAllMasterDevices][byte] : 0);
+}
+
+
+/**
  * Return the windows complete XI2 mask for the given XI2 event type.
  */
 Mask
@@ -452,9 +484,7 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
     evtype = ((xGenericEvent*)ev)->evtype;
     filter = GetEventFilter(dev, ev);
 
-    return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
-            inputMasks->xi2mask[XIAllDevices][evtype/8] ||
-            (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
+    return (GetXI2MaskByte(inputMasks->xi2mask, dev, evtype) & filter);
 }
 
 Mask
@@ -465,10 +495,7 @@ GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
     /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
     if ((evtype = xi2_get_type(event)))
     {
-        int byte = evtype / 8;
-        return (other->xi2mask[dev->id][byte] |
-                other->xi2mask[XIAllDevices][byte] |
-                (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
+        return GetXI2MaskByte(other->xi2mask, dev, evtype);
     } else if (core_get_type(event) != 0)
         return other->mask[XIAllDevices];
     else
@@ -4061,9 +4088,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
             if (rc == Success)
             {
                 int evtype = xi2_get_type(xi2);
-                mask = grab->xi2mask[XIAllDevices][evtype/8] |
-                    grab->xi2mask[XIAllMasterDevices][evtype/8] |
-                    grab->xi2mask[thisDev->id][evtype/8];
+                mask = GetXI2MaskByte(grab->xi2mask, thisDev, evtype);
                 /* try XI2 event */
                 FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
                 /* XXX: XACE */
@@ -4542,9 +4567,7 @@ DeviceEnterLeaveEvent(
     if (grab)
     {
         Mask mask;
-        mask = grab->xi2mask[XIAllDevices][type/8] |
-               grab->xi2mask[XIAllMasterDevices][type/8] |
-               grab->xi2mask[mouse->id][type/8];
+        mask = GetXI2MaskByte(grab->xi2mask, mouse, type);
         TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
                         filter, grab);
     } else {
commit 8c5a4d6fbecf79f2dc4f2d836d741203b2d5e856
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 14:12:41 2011 +1000

    dix: don't use the pointer as modifier device in UngrabKey.
    
    Modifier device is always the keyboard.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/events.c b/dix/events.c
index 8419064..8e07532 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5356,7 +5356,7 @@ ProcUngrabKey(ClientPtr client)
     tempGrab.window = pWin;
     tempGrab.modifiersDetail.exact = stuff->modifiers;
     tempGrab.modifiersDetail.pMask = NULL;
-    tempGrab.modifierDevice = GetPairedDevice(keybd);
+    tempGrab.modifierDevice = keybd;
     tempGrab.type = KeyPress;
     tempGrab.grabtype = GRABTYPE_CORE;
     tempGrab.detail.exact = stuff->key;
commit 3a077f246e9ac07a37c1b01c3d321e0f5ceb4153
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Aug 3 15:07:23 2011 +1000

    input: provide a single function to init DeviceEvents to 0
    
    getevents.c already had that function, but XKB was manually initializing it,
    causing bugs when the event structure was updated in one place but not the
    other.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/getevents.c b/dix/getevents.c
index f7f4617..be2840c 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -154,17 +154,6 @@ key_autorepeats(DeviceIntPtr pDev, int key_code)
 }
 
 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));
@@ -1006,7 +995,7 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     set_raw_valuators(raw, &mask, raw->valuators.data);
 
     event = &events->device_event;
-    init_event(pDev, event, ms);
+    init_device_event(event, pDev, ms);
     event->detail.key = key_code;
 
     if (type == KeyPress) {
@@ -1228,7 +1217,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
     clipValuators(pDev, &mask);
 
     event = &events->device_event;
-    init_event(pDev, event, ms);
+    init_device_event(event, pDev, ms);
 
     if (type == MotionNotify) {
         event->type = ET_Motion;
@@ -1321,7 +1310,7 @@ GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, const Val
     events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
 
     event = &events->device_event;
-    init_event(pDev, event, GetTimeInMillis());
+    init_device_event(event, pDev, GetTimeInMillis());
     event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
 
     clipValuators(pDev, &mask);
@@ -1357,7 +1346,7 @@ PostSyntheticMotion(DeviceIntPtr pDev,
 #endif
 
     memset(&ev, 0, sizeof(DeviceEvent));
-    init_event(pDev, &ev, time);
+    init_device_event(&ev, pDev, time);
     ev.root_x = x;
     ev.root_y = y;
     ev.type = ET_Motion;
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 49e1758..9632076 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -584,3 +584,17 @@ void verify_internal_event(const InternalEvent *ev)
         FatalError("Wrong event type %d. Aborting server\n", ev->any.header);
     }
 }
+
+/**
+ * Initializes the given event to zero (or default values), for the given
+ * device.
+ */
+void init_device_event(DeviceEvent *event, DeviceIntPtr dev, 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;
+}
diff --git a/include/inpututils.h b/include/inpututils.h
index 92a7543..63e1a26 100644
--- a/include/inpututils.h
+++ b/include/inpututils.h
@@ -38,5 +38,6 @@ struct _ValuatorMask {
 };
 
 extern void verify_internal_event(const InternalEvent *ev);
+extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms);
 
 #endif
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 12fe2a1..4115ff2 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -124,15 +124,11 @@ AccessXKeyboardEvent(DeviceIntPtr	keybd,
 				 Bool		isRepeat)
 {
     DeviceEvent event;
-    memset(&event, 0, sizeof(DeviceEvent));
-    event.header = ET_Internal;
+
+    init_device_event(&event, keybd, GetTimeInMillis());
     event.type = type;
     event.detail.key = keyCode;
-    event.time = GetTimeInMillis();
-    event.length = sizeof(DeviceEvent);
     event.key_repeat = isRepeat;
-    event.sourceid = keybd->id;
-    event.deviceid = keybd->id;
 
     if (xkbDebugFlags&0x8) {
 	DebugF("[xkb] AXKE: Key %d %s\n", keyCode,
commit 4b376ddeb4f3c9d9d279ffd2946d88edd5af4cfc
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 14:20:53 2011 +1000

    dix: fix compiler warnings ("foo" set but not used)
    
    devices.c: In function 'AttachDevice':
    devices.c:2409:18: warning: variable 'oldmaster' set but not used
    [-Wunused-but-set-variable]
    
    events.c: In function 'ConfineToShape':
    events.c:683:15: warning: variable 'pSprite' set but not used
    [-Wunused-but-set-variable]
    
    events.c: In function 'ProcGrabPointer':
    events.c:4759:15: warning: variable 'time' set but not used
    [-Wunused-but-set-variable]
    
    getevents.c: In function 'GetMotionHistory':
    getevents.c:425:9: warning: variable 'dflt' set but not used
    [-Wunused-but-set-variable]
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/devices.c b/dix/devices.c
index 334f5d3..ab8a648 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2406,7 +2406,6 @@ int
 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 {
     ScreenPtr screen;
-    DeviceIntPtr oldmaster;
     if (!dev || IsMaster(dev))
         return BadDevice;
 
@@ -2425,7 +2424,6 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         free(dev->spriteInfo->sprite);
     }
 
-    oldmaster = GetMaster(dev, MASTER_ATTACHED);
     dev->master = master;
 
     /* If device is set to floating, we need to create a sprite for it,
diff --git a/dix/events.c b/dix/events.c
index 25ff899..8419064 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -680,9 +680,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
-    SpritePtr pSprite;
 
-    pSprite = pDev->spriteInfo->sprite;
     if (RegionContainsPoint(shape, x, y, &box))
 	return;
     box = *RegionExtents(shape);
@@ -4765,7 +4763,6 @@ ProcGrabPointer(ClientPtr client)
     WindowPtr confineTo;
     CursorPtr oldCursor;
     REQUEST(xGrabPointerReq);
-    TimeStamp time;
     int rc;
 
     REQUEST_SIZE_MATCH(xGrabPointerReq);
@@ -4811,7 +4808,6 @@ ProcGrabPointer(ClientPtr client)
     if (oldCursor && rep.status == GrabSuccess)
         FreeCursor (oldCursor, (Cursor)0);
 
-    time = ClientTimeToServerTime(stuff->time);
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
diff --git a/dix/getevents.c b/dix/getevents.c
index a12462a..f7f4617 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -414,7 +414,6 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
     Time current;
     /* The size of a single motion event. */
     int size;
-    int dflt;
     AxisInfo from, *to; /* for scaling */
     INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
     INT16 *corebuf;
@@ -502,13 +501,6 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
                     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;
-
                     /* scale from stored range into current range */
                     coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
                     memcpy(ocbuf, &coord, sizeof(INT32));
commit 6fd2adc179141310e45a56ee90ef5b5f6115a1f6
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 14:27:54 2011 +1000

    mi: fix compiler warnings ("foo" set but not used)
    
    misprite.c: In function 'miSpriteSaveUnderCursor':
    misprite.c:940:12: warning: variable 'y' set but not used
    [-Wunused-but-set-variable]
    misprite.c:940:9: warning: variable 'x' set but not used
    [-Wunused-but-set-variable]
    
    mivaltree.c: In function 'miComputeClips':
    mivaltree.c:226:10: warning: variable 'resized' set but not used
    [-Wunused-but-set-variable]
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/mi/misprite.c b/mi/misprite.c
index 1cfcdf6..1025c5a 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -937,8 +937,6 @@ static void
 miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
     miSpriteScreenPtr   pScreenPriv;
-    int			x, y;
-    CursorPtr		pCursor;
     miCursorInfoPtr     pCursorInfo;
 
     if (IsFloating(pDev))
@@ -949,10 +947,7 @@ miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
     pCursorInfo = MISPRITE(pDev);
 
     miSpriteComputeSaved (pDev, pScreen);
-    pCursor = pCursorInfo->pCursor;
 
-    x = pCursorInfo->x - (int)pCursor->bits->xhot;
-    y = pCursorInfo->y - (int)pCursor->bits->yhot;
     miSpriteDisableDamage(pScreen, pScreenPriv);
 
     miDCSaveUnderCursor(pDev,
diff --git a/mi/mivaltree.c b/mi/mivaltree.c
index 0e00c2f..e1d47c0 100644
--- a/mi/mivaltree.c
+++ b/mi/mivaltree.c
@@ -223,7 +223,6 @@ miComputeClips (
     RegionRec		childUnion;
     Bool		overlap;
     RegionPtr		borderVisible;
-    Bool		resized;
     /*
      * Figure out the new visibility of this window.
      * The extent of the universe should be the same as the extent of
@@ -378,7 +377,6 @@ miComputeClips (
     }
 
     borderVisible = pParent->valdata->before.borderVisible;
-    resized = pParent->valdata->before.resized;
     RegionNull(&pParent->valdata->after.borderExposed);
     RegionNull(&pParent->valdata->after.exposed);
 
commit 484cef5b29ef82402a15e155b3b8505b1e4a6830
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Aug 2 09:21:00 2011 +1000

    Xi: silence compiler warnings (set but not used)
    
    exevents.c: In function 'UpdateDeviceState':
    exevents.c:719:9: warning: variable 'bit' set but not used
    [-Wunused-but-set-variable]
    
    exevents.c: In function 'ProcessOtherEvent':
    exevents.c:889:22: warning: variable 'v' set but not used
    [-Wunused-but-set-variable]
    exevents.c:888:17: warning: variable 'k' set but not used
    [-Wunused-but-set-variable]
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 3e3c67b..38089a2 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -716,7 +716,6 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
 {
     int i;
     int key = 0,
-        bit = 0,
         last_valuator;
 
     KeyClassPtr k       = NULL;
@@ -750,7 +749,6 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
     b = device->button;
 
     key = event->detail.key;
-    bit = 1 << (key & 7);
 
     /* Update device axis */
     /* Check valuators first */
@@ -888,8 +886,6 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, rootX, rootY;
     ButtonClassPtr b;
-    KeyClassPtr k;
-    ValuatorClassPtr v;
     int ret = 0;
     int state, i;
     DeviceIntPtr mouse = NULL, kbd = NULL;
@@ -953,9 +949,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
     if (ret == DONT_PROCESS)
         return;
 
-    v = device->valuator;
     b = device->button;
-    k = device->key;
 
     if (IsMaster(device) || IsFloating(device))
         CheckMotion(event, device);
commit 98fe735ea1d756711019c3d90ed6abd9c06abebf
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 13:52:13 2011 +1000

    dix: add KEYBOARD_OR_FLOAT and POINTER_OR_FLOAT to GetMaster()
    
    GetMaster() currently requires an attached slave device as parameter,
    resuling in many calls being IsFloating(dev) ? dev : GetMaster(...);
    
    Add two new parameters so GetMaster can be called unconditionally to get the
    right device.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/devices.c b/dix/devices.c
index 0ccf252..334f5d3 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2484,16 +2484,22 @@ GetPairedDevice(DeviceIntPtr dev)
 
 
 /**
- * Returns the right master for the type of event needed. If the event is a
- * keyboard event.
- * This function may be called with a master device as argument. If so, the
- * returned master is either the device itself or the paired master device.
- * If dev is a floating slave device, NULL is returned.
+ * Returns the requested master for this device.
+ * The return values are:
+ * - MASTER_ATTACHED: the master for this device or NULL for a floating
+ *   slave.
+ * - MASTER_KEYBOARD: the master keyboard for this device or NULL for a
+ *   floating slave
+ * - MASTER_POINTER: the master keyboard for this device or NULL for a
+ *   floating slave
+ * - POINTER_OR_FLOAT: the master pointer for this device or the device for
+ *   a floating slave
+ * - KEYBOARD_OR_FLOAT: the master keyboard for this device or the device for
+ *   a floating slave
  *
- * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED
- * @return The requested master device. In the case of MASTER_ATTACHED, this
- * is the directly attached master to this device, regardless of the type.
- * Otherwise, it is either the master keyboard or pointer for this device.
+ * @param which ::MASTER_KEYBOARD or ::MASTER_POINTER, ::MASTER_ATTACHED,
+ * ::POINTER_OR_FLOAT or ::KEYBOARD_OR_FLOAT.
+ * @return The requested master device
  */
 DeviceIntPtr
 GetMaster(DeviceIntPtr dev, int which)
@@ -2502,12 +2508,15 @@ GetMaster(DeviceIntPtr dev, int which)
 
     if (IsMaster(dev))
         master = dev;
-    else
+    else {
         master = dev->master;
+        if (!master && (which == POINTER_OR_FLOAT || which == KEYBOARD_OR_FLOAT))
+            return dev;
+    }
 
     if (master && which != MASTER_ATTACHED)
     {
-        if (which == MASTER_KEYBOARD)
+        if (which == MASTER_KEYBOARD || which == KEYBOARD_OR_FLOAT)
         {
             if (master->type != MASTER_KEYBOARD)
                 master = GetPairedDevice(master);
diff --git a/include/inputstr.h b/include/inputstr.h
index 00f72c2..838f9f0 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -472,7 +472,10 @@ typedef struct _SpriteInfoRec {
 #define MASTER_POINTER          1
 #define MASTER_KEYBOARD         2
 #define SLAVE                   3
-#define MASTER_ATTACHED         4  /* special type for GetMaster */
+/* special types for GetMaster */
+#define MASTER_ATTACHED         4       /* Master for this device */
+#define KEYBOARD_OR_FLOAT       5       /* Keyboard master for this device or this device if floating */
+#define POINTER_OR_FLOAT        6       /* Pointer master for this device or this device if floating */
 
 typedef struct _DeviceIntRec {
     DeviceRec	public;
diff --git a/test/input.c b/test/input.c
index 31597f9..c2b0eb0 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1292,6 +1292,19 @@ static void dix_get_master(void)
     assert(GetMaster(&floating, MASTER_POINTER) == NULL);
     assert(GetMaster(&floating, MASTER_KEYBOARD) == NULL);
     assert(GetMaster(&floating, MASTER_ATTACHED) == NULL);
+
+    assert(GetMaster(&vcp, POINTER_OR_FLOAT) == &vcp);
+    assert(GetMaster(&vck, POINTER_OR_FLOAT) == &vcp);
+    assert(GetMaster(&ptr, POINTER_OR_FLOAT) == &vcp);
+    assert(GetMaster(&kbd, POINTER_OR_FLOAT) == &vcp);
+
+    assert(GetMaster(&vcp, KEYBOARD_OR_FLOAT) == &vck);
+    assert(GetMaster(&vck, KEYBOARD_OR_FLOAT) == &vck);
+    assert(GetMaster(&ptr, KEYBOARD_OR_FLOAT) == &vck);
+    assert(GetMaster(&kbd, KEYBOARD_OR_FLOAT) == &vck);
+
+    assert(GetMaster(&floating, KEYBOARD_OR_FLOAT) == &floating);
+    assert(GetMaster(&floating, POINTER_OR_FLOAT) == &floating);
 }
 
 
commit dbbe5735d1451bb32f43bce90f0bcfeff46f9743
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Aug 2 08:54:00 2011 +1000

    test: add a test for GetMaster() behaviour
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/test/input.c b/test/input.c
index 837ce49..31597f9 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1234,6 +1234,67 @@ static void dix_valuator_alloc(void)
     free(v);
 }
 
+static void dix_get_master(void)
+{
+    DeviceIntRec vcp, vck;
+    DeviceIntRec ptr, kbd;
+    DeviceIntRec floating;
+    SpriteInfoRec vcp_sprite, vck_sprite;
+    SpriteInfoRec ptr_sprite, kbd_sprite;
+    SpriteInfoRec floating_sprite;
+
+    memset(&vcp, 0, sizeof(DeviceIntRec));
+    memset(&vck, 0, sizeof(DeviceIntRec));
+    memset(&ptr, 0, sizeof(DeviceIntRec));
+    memset(&kbd, 0, sizeof(DeviceIntRec));
+    memset(&floating, 0, sizeof(DeviceIntRec));
+
+    memset(&vcp_sprite, 0, sizeof(DeviceIntRec));
+    memset(&vck_sprite, 0, sizeof(DeviceIntRec));
+    memset(&ptr_sprite, 0, sizeof(DeviceIntRec));
+    memset(&kbd_sprite, 0, sizeof(DeviceIntRec));
+    memset(&floating_sprite, 0, sizeof(DeviceIntRec));
+
+    vcp.type = MASTER_POINTER;
+    vck.type = MASTER_KEYBOARD;
+    ptr.type = SLAVE;
+    kbd.type = SLAVE;
+    floating.type = SLAVE;
+
+    vcp.spriteInfo = &vcp_sprite;
+    vck.spriteInfo = &vck_sprite;
+    ptr.spriteInfo = &ptr_sprite;
+    kbd.spriteInfo = &kbd_sprite;
+    floating.spriteInfo = &floating_sprite;
+
+    vcp_sprite.paired = &vck;
+    vck_sprite.paired = &vcp;
+    ptr_sprite.paired = &vcp;
+    kbd_sprite.paired = &vck;
+    floating_sprite.paired = &floating;
+
+    vcp_sprite.spriteOwner = TRUE;
+    floating_sprite.spriteOwner = TRUE;
+
+    ptr.master = &vcp;
+    kbd.master = &vck;
+
+    assert(GetPairedDevice(&vcp) == &vck);
+    assert(GetPairedDevice(&vck) == &vcp);
+    assert(GetMaster(&ptr, MASTER_POINTER) == &vcp);
+    assert(GetMaster(&ptr, MASTER_KEYBOARD) == &vck);
+    assert(GetMaster(&kbd, MASTER_POINTER) == &vcp);
+    assert(GetMaster(&kbd, MASTER_KEYBOARD) == &vck);
+    assert(GetMaster(&ptr, MASTER_ATTACHED) == &vcp);
+    assert(GetMaster(&kbd, MASTER_ATTACHED) == &vck);
+
+    assert(GetPairedDevice(&floating) == &floating);
+    assert(GetMaster(&floating, MASTER_POINTER) == NULL);
+    assert(GetMaster(&floating, MASTER_KEYBOARD) == NULL);
+    assert(GetMaster(&floating, MASTER_ATTACHED) == NULL);
+}
+
+
 int main(int argc, char** argv)
 {
     dix_input_valuator_masks();
@@ -1249,6 +1310,7 @@ int main(int argc, char** argv)
     include_bit_test_macros();
     xi_unregister_handlers();
     dix_valuator_alloc();
+    dix_get_master();
 
     return 0;
 }
commit b3c76b0c53ac42b70d12849da18465e8467e474c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 11:54:17 2011 +1000

    mi: fix comment typo, whitespace in miPointerSetPosition
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 7680ca1..670f63b 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -569,9 +569,9 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
  *
  * @param pDev The device to move
  * @param mode Movement mode (Absolute or Relative)
- * @param[in,out] x The x coordiante in screen coordinates (in regards to total
+ * @param[in,out] x The x coordinate in screen coordinates (in regards to total
  * desktop size)
- * @param[in,out] y The y coordiante in screen coordinates (in regards to total
+ * @param[in,out] y The y coordinate in screen coordinates (in regards to total
  * desktop size)
  */
 void
@@ -603,7 +603,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
 		pScreen = newScreen;
 		(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
 							     FALSE);
-	    	/* Smash the confine to the new screen */
+		/* Smash the confine to the new screen */
                 pPointer->limits.x2 = pScreen->width;
                 pPointer->limits.y2 = pScreen->height;
 	    }
@@ -622,8 +622,8 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
     if (pScreen->ConstrainCursorHarder)
        pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
 
-    if (pPointer->x == *x && pPointer->y == *y && 
-            pPointer->pScreen == pScreen) 
+    if (pPointer->x == *x && pPointer->y == *y &&
+            pPointer->pScreen == pScreen)
         return;
 
     miPointerMoveNoEvent(pDev, pScreen, *x, *y);
commit c9562bed0d5e26b7e3e55e26cf1ddc5086d61cc6
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Aug 1 09:52:38 2011 +1000

    dix: rename mieqSwitchScreen argument fromDix → set_dequeue_screen, document
    
    fromDIX is neither exactly true nor particularly helpful in understanding
    what this parameter triggers. Rename to set_dequeue_screen, because that's
    exactly what happens.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/mi/mi.h b/mi/mi.h
index c186940..24d1af9 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -206,7 +206,7 @@ extern _X_EXPORT void mieqEnqueue(
 extern _X_EXPORT void mieqSwitchScreen(
     DeviceIntPtr /* pDev */,
     ScreenPtr /*pScreen*/,
-    Bool /*fromDIX*/
+    Bool /*set_dequeue_screen*/
 );
 
 extern _X_EXPORT void mieqProcessDeviceEvent(
diff --git a/mi/mieq.c b/mi/mieq.c
index fc3738a..b75bde9 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -209,14 +209,29 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 #endif
 }
 
+/**
+ * Changes the screen reference events are being enqueued from.
+ * Input events are enqueued with a screen reference and dequeued and
+ * processed with a (potentially different) screen reference.
+ * This function is called whenever a new event has changed screen but is
+ * still logically on the previous screen as seen by the client.
+ * This usually happens whenever the visible cursor moves across screen
+ * boundaries during event generation, before the same event is processed
+ * and sent down the wire.
+ *
+ * @param pDev The device that triggered a screen change.
+ * @param pScreen The new screen events are being enqueued for.
+ * @param set_dequeue_screen If TRUE, pScreen is set as both enqueue screen
+ * and dequeue screen.
+ */
 void
-mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
+mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool set_dequeue_screen)
 {
 #ifdef XQUARTZ
     pthread_mutex_lock(&miEventQueueMutex);
 #endif
     EnqueueScreen(pDev) = pScreen;
-    if (fromDIX)
+    if (set_dequeue_screen)
         DequeueScreen(pDev) = pScreen;
 #ifdef XQUARTZ
     pthread_mutex_unlock(&miEventQueueMutex);
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 539096e..c4265f9 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -87,7 +87,7 @@ typedef struct _miPointerScreenFuncRec {
     void	(*NewEventScreen)(
 		    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
-		    Bool /* fromDIX */
+		    Bool /* set_dequeue_screen */
                     );
 } miPointerScreenFuncRec, *miPointerScreenFuncPtr;
 
commit 09496996accfdaf7bc01097a25db400912004d97
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jul 28 15:56:08 2011 +1000

    dix: ignore devices when adding passive core grabs to list (#39545)
    
    Passive core grabs are mostly device-independent. In an MPX scenario, they
    may change to reflect whichever master pair activated the grab last. For
    adding new grabs to the list, ignore the device for core grabs to return
    failures when trying to set the same grab combo twice on a window.
    
    X.Org Bug 39545 <http://bugs.freedesktop.org/show_bug.cgi?id=39545>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/grabs.c b/dix/grabs.c
index 85ca9ee..c28356d 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -479,7 +479,7 @@ AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab)
 
     for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
     {
-	if (GrabMatchesSecond(pGrab, grab, FALSE))
+	if (GrabMatchesSecond(pGrab, grab, (pGrab->grabtype == GRABTYPE_CORE)))
 	{
 	    if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
 	    {
commit 80c37048539daa1d257d127d66502bde45c97c85
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jul 28 15:43:10 2011 +1000

    dix: avoid using the VCP as modifier device
    
    Core grabs may change device when they're activated to reflect the master
    they apply to. If the device is a keyboard, modifierDevice is erroneously
    set to the Virtual Core Pointer.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/events.c b/dix/events.c
index 8a4c6b9..25ff899 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3678,7 +3678,7 @@ CheckPassiveGrabsOnWindow(
             if (tempGrab.type < GenericEvent)
             {
                 grab->device = device;
-                grab->modifierDevice = GetPairedDevice(device);
+                grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
             }
 
             for (other = inputInfo.devices; other; other = other->next)
commit 20a61845d3c93c337bf3331a6bac30cf66c2a293
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Aug 9 11:21:06 2011 +1000

    config: use add_option for '_source' too
    
    _source was being allocated manually, with all other options added to that
    list through add_option. Skip the manual part, allocate the first option
    _source with add_option too.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/config/dbus.c b/config/dbus.c
index 34e3caa..41eca99 100644
--- a/config/dbus.c
+++ b/config/dbus.c
@@ -80,15 +80,7 @@ add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
         MALFORMED_MESSAGE();
     }
 
-    options = calloc(sizeof(*options), 1);
-    if (!options) {
-        ErrorF("[config/dbus] couldn't allocate option\n");
-        return BadAlloc;
-    }
-
-    options->key = strdup("_source");
-    options->value = strdup("client/dbus");
-    if (!options->key || !options->value) {
+    if (!add_option(&options, "_source", "client/dbus")) {
         ErrorF("[config/dbus] couldn't allocate first key/value pair\n");
         ret = BadAlloc;
         goto unwind;
diff --git a/config/hal.c b/config/hal.c
index 297520a..0b2d7d0 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -205,15 +205,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         free(parent);
     }
 
-    options = calloc(sizeof(*options), 1);
-    if (!options){
-        LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n");
-        goto unwind;
-    }
-
-    options->key = strdup("_source");
-    options->value = strdup("server/hal");
-    if (!options->key || !options->value) {
+    if (!add_option(&options, "_source", "server/hal")) {
         LogMessage(X_ERROR, "config/hal: couldn't allocate first key/value pair\n");
         goto unwind;
     }
diff --git a/config/udev.c b/config/udev.c
index b11c81d..1f431c1 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -93,13 +93,7 @@ device_added(struct udev_device *udev_device)
         return;
     }
 
-    options = calloc(sizeof(*options), 1);
-    if (!options)
-        return;
-
-    options->key = strdup("_source");
-    options->value = strdup("server/udev");
-    if (!options->key || !options->value)
+    if (!add_option(&options, "_source", "server/udev"))
         goto unwind;
 
     parent = udev_device_get_parent(udev_device);
commit d33652dad8838ab0a9175ca4613a3161ebc5676f
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Aug 9 11:20:31 2011 +1000

    config: return the new InputOption from add_option.
    
    Change add_option to return the new InputOption on success, or NULL
    failure. This way we can at least check for errors in callers.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/config/config-backends.h b/config/config-backends.h
index 0a2a22a..0d36d72 100644
--- a/config/config-backends.h
+++ b/config/config-backends.h
@@ -30,7 +30,7 @@
 
 void remove_devices(const char *backend, const char *config_info);
 BOOL device_is_duplicate(const char *config_info);
-void add_option(InputOption **options, const char *key, const char *value);
+InputOption* add_option(InputOption **options, const char *key, const char *value);
 
 #ifdef CONFIG_UDEV
 int config_udev_init(void);
diff --git a/config/config.c b/config/config.c
index d86f7c6..af8f4f9 100644
--- a/config/config.c
+++ b/config/config.c
@@ -122,18 +122,25 @@ device_is_duplicate(const char *config_info)
     return FALSE;
 }
 
-void
+/**
+ * Allocate a new option and append to the list.
+ *
+ * @return A pointer to the newly allocated InputOption struct.
+ */
+InputOption*
 add_option(InputOption **options, const char *key, const char *value)
 {
     if (!value || *value == '\0')
-        return;
+        return NULL;
 
     for (; *options; options = &(*options)->next)
         ;
     *options = calloc(sizeof(**options), 1);
     if (!*options) /* Yeesh. */
-        return;
+        return NULL;
     (*options)->key = strdup(key);
     (*options)->value = strdup(value);
     (*options)->next = NULL;
+
+    return *options;
 }
commit e684e816acb617b4dc66a68e2b0ba8f80399170a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Jul 20 16:21:28 2011 +1000

    config: fix a log message
    
    PRODUCT was taken from the parent, hence ppath.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/config/udev.c b/config/udev.c
index fc6ee5d..b11c81d 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -126,7 +126,7 @@ device_added(struct udev_device *udev_device)
                 == -1)
                 attrs.usb_id = NULL;
             else
-                LOG_PROPERTY(path, "PRODUCT", product);
+                LOG_PROPERTY(ppath, "PRODUCT", product);
         }
     }
     if (!name)
commit 1357cd725143c1a35e32f15df658de111b151692
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jul 8 16:13:45 2011 +1000

    Revert "Attempt to add the 'mouse' driver in more situations."
    
    This reverts commit 43d9edd31e31b33b9da4a50d8ab05004881c8d5a.
    
    This commit was introduced in the 1.2 cycle when hotplugging was less than
    ideal (i.e. it didn't exist). From the commit message:
    
        Always add a mouse driver instance configured to send core events, unless
        a core pointer already exists using either the mouse or void drivers.  This
        handles the laptop case where the config file only specifies, say,
        synaptics, which causes the touchpad to work but not the pointing stick.
        We don't double-instantiate the mouse driver to avoid the mouse moving twice
        as fast, and we skip this logic when the user asked for a void core pointer
        since that probably means they want to run with no pointer at all.
    
    To get this case above, a user would need to disable hotplugging _and_ have a
    xorg.conf that only references one device. This is possible, but not a use-case
    we should worry about too much now.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 8670e53..25755fd 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1134,7 +1134,6 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
     XF86ConfInputPtr confInput;
     XF86ConfInputRec defPtr, defKbd;
     MessageType from = X_DEFAULT;
-    int found = 0;
     const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse",
 				   "void", NULL };
 
@@ -1251,40 +1250,6 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	return FALSE;
     }
 
-    /*
-     * always synthesize a 'mouse' section configured to send core
-     * events, unless a 'void' section is found, in which case the user
-     * probably wants to run footless.
-     *
-     * If you're using an evdev keyboard and expect a default mouse
-     * section ... deal.
-     */
-    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
-	const char **driver = mousedrivers;
-	while(*driver) {
-	    if (!strcmp((*devs)->driver, *driver)) {
-		found = 1;
-		break;
-	    }
-	    driver++;
-	}
-    }
-    if (!found && xf86Info.forceInputDevices) {
-	xf86Msg(X_INFO, "No default mouse found, adding one\n");
-	memset(&defPtr, 0, sizeof(defPtr));
-	defPtr.inp_identifier = strdup("<default pointer>");
-	defPtr.inp_driver = strdup("mouse");
-	confInput = &defPtr;
-	Pointer = xf86AllocateInput();
-	if (Pointer)
-	    foundPointer = configInput(Pointer, confInput, from);
-	if (foundPointer) {
-	    Pointer->options = xf86addNewOption(NULL,
-					       xnfstrdup("AlwaysCore"), "on");
-	    servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer);
-	}
-    }
-
     confInput = NULL;
 
     /* 1. Check for the -keyboard command line option. */
commit 159b03e13760920274b573a2bccdbf6a79f059e7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 18 21:19:23 2011 +0200

    config: add udev/systemd multi-seat support
    
    Add support for multi-seat-aware input device hotplugging. This
    implements the multi-seat scheme explained here:
    
    http://www.freedesktop.org/wiki/Software/systemd/multiseat
    
    This introduces a new X server switch "-seat" which allows configuration
    of the seat to enumerate hotplugging devices on. If specified the value
    of this parameter will also be exported as root window property
    Xorg_Seat.
    
    To properly support input hotplugging devices need to be tagged in udev
    according to the seat they are on. Untagged devices are assumed to be on
    the default seat "seat0". If no "-seat" parameter is passed only devices
    on "seat0" are used. This means that the new scheme is perfectly
    compatible with existing setups which have no tagged input devices.
    
    Note that the -seat switch takes a completely generic identifier, and
    that it has no effect on non-Linux systems. In fact, on other OSes a
    completely different identifier scheme for seats could be used but still
    be exposed with the Xorg_Seat and -seat.
    
    I tried to follow the coding style of the surrounding code blocks if
    there was any one could follow.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/udev.c b/config/udev.c
index e7383dc..fc6ee5d 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -35,6 +35,7 @@
 #include "hotplug.h"
 #include "config-backends.h"
 #include "os.h"
+#include "globals.h"
 
 #define UDEV_XKB_PROP_KEY "xkb"
 
@@ -65,6 +66,7 @@ device_added(struct udev_device *udev_device)
     struct udev_list_entry *set, *entry;
     struct udev_device *parent;
     int rc;
+    const char *dev_seat;
 
     path = udev_device_get_devnode(udev_device);
 
@@ -73,6 +75,16 @@ device_added(struct udev_device *udev_device)
     if (!path || !syspath)
         return;
 
+    dev_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
+    if (!dev_seat)
+        dev_seat = "seat0";
+
+    if (SeatId && strcmp(dev_seat, SeatId))
+        return;
+
+    if (!SeatId && strcmp(dev_seat, "seat0"))
+        return;
+
     if (!udev_device_get_property_value(udev_device, "ID_INPUT")) {
         LogMessageVerb(X_INFO, 10,
                        "config/udev: ignoring device %s without "
@@ -284,6 +296,9 @@ config_udev_init(void)
     udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", NULL);
     udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL); /* For Wacom serial devices */
 
+    if (SeatId && strcmp(SeatId, "seat0"))
+        udev_monitor_filter_add_match_tag(udev_monitor, SeatId);
+
     if (udev_monitor_enable_receiving(udev_monitor)) {
         ErrorF("config/udev: failed to bind the udev monitor\n");
         return 0;
@@ -296,6 +311,9 @@ config_udev_init(void)
     udev_enumerate_add_match_subsystem(enumerate, "input");
     udev_enumerate_add_match_subsystem(enumerate, "tty");
 
+    if (SeatId && strcmp(SeatId, "seat0"))
+        udev_enumerate_add_match_tag(enumerate, SeatId);
+
     udev_enumerate_scan_devices(enumerate);
     devices = udev_enumerate_get_list_entry(enumerate);
     udev_list_entry_foreach(device, devices) {
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 5ee68cd..89bc82a 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -80,6 +80,7 @@
 #include "xf86Bus.h"
 #include "xf86VGAarbiter.h"
 #include "globals.h"
+#include "xserver-properties.h"
 
 #ifdef DPMSExtension
 #include <X11/extensions/dpmsconst.h>
@@ -654,6 +655,24 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
       }
     }
 
+    if (SeatId) {
+        Atom SeatAtom;
+
+        SeatAtom = MakeAtom(SEAT_ATOM_NAME, sizeof(SEAT_ATOM_NAME) - 1, TRUE);
+
+        for (i = 0; i < xf86NumScreens; i++) {
+            int ret;
+
+            ret = xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex,
+                                                 SeatAtom, XA_STRING, 8,
+                                                 strlen(SeatId)+1, SeatId );
+            if (ret != Success) {
+                xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING,
+                           "Failed to register seat property\n");
+            }
+        }
+    }
+
     /* If a screen uses depth 24, show what the pixmap format is */
     for (i = 0; i < xf86NumScreens; i++) {
 	if (xf86Screens[i]->depth == 24) {
diff --git a/include/globals.h b/include/globals.h
index 8b80a65..17bca82 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -21,7 +21,7 @@ extern _X_EXPORT int defaultColorVisualClass;
 
 extern _X_EXPORT int GrabInProgress;
 extern _X_EXPORT Bool noTestExtensions;
-
+extern _X_EXPORT char *SeatId;
 extern _X_EXPORT char *ConnectionInfo;
 
 #ifdef DPMSExtension
diff --git a/include/xserver-properties.h b/include/xserver-properties.h
index 2b1feab..bf50042 100644
--- a/include/xserver-properties.h
+++ b/include/xserver-properties.h
@@ -30,6 +30,9 @@
  * byte-ordering. */
 #define XATOM_FLOAT "FLOAT"
 
+/* STRING. Seat name of this display */
+#define SEAT_ATOM_NAME "Xorg_Seat"
+
 /* BOOL. 0 - device disabled, 1 - device enabled */
 #define XI_PROP_ENABLED      "Device Enabled"
 /* BOOL. If present, device is a virtual XTEST device */
diff --git a/man/Xserver.man b/man/Xserver.man
index f743912..1a36b09 100644
--- a/man/Xserver.man
+++ b/man/Xserver.man
@@ -220,6 +220,12 @@ sets screen-saver timeout time in minutes.
 .B \-su
 disables save under support on all screens.
 .TP 8
+.B \-seat \fIseat\fP
+seat to run on. Takes a string identifying a seat in a platform
+specific syntax. On platforms which support this feature this may be
+used to limit the server to expose only a specific subset of devices
+connected to the system.
+.TP 8
 .B \-t \fInumber\fP
 sets pointer acceleration threshold in pixels (i.e. after how many pixels
 pointer acceleration should take effect).
diff --git a/os/utils.c b/os/utils.c
index 36cb46f..e8ecb71 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -201,6 +201,8 @@ Bool PanoramiXExtensionDisabledHack = FALSE;
 
 int auditTrailLevel = 1;
 
+char *SeatId = NULL;
+
 #if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
 #define HAS_SAVED_IDS_AND_SETEUID
 #endif
@@ -511,6 +513,7 @@ void UseMsg(void)
     ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
     ErrorF("-retro                 start with classic stipple and cursor\n");
     ErrorF("-s #                   screen-saver timeout (minutes)\n");
+    ErrorF("-seat string           seat to run on\n");
     ErrorF("-t #                   default pointer threshold (pixels/t)\n");
     ErrorF("-terminate             terminate at server reset\n");
     ErrorF("-to #                  connection time out\n");
@@ -802,6 +805,13 @@ ProcessCommandLine(int argc, char *argv[])
 	    else
 		UseMsg();
 	}
+	else if ( strcmp( argv[i], "-seat") == 0)
+	{
+	    if(++i < argc)
+		SeatId = argv[i];
+	    else
+		UseMsg();
+	}
 	else if ( strcmp( argv[i], "-t") == 0)
 	{
 	    if(++i < argc)
commit 95772598b57f6054fbf88683fa0a492c77605790
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jul 8 16:10:07 2011 +1000

    xfree86: use xf86AllocateInput for implicit devices too
    
    Slowly merging the vastly different code-paths.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 83eac8b..8670e53 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1089,7 +1089,7 @@ freeDevice(InputInfoPtr *list, InputInfoPtr pInfo)
 
 /**
  * Append pInfo to the null-terminated list, allocating space as necessary.
- * pInfo is copied into the last element.
+ * pInfo is used as the last element.
  */
 static InputInfoPtr*
 addDevice(InputInfoPtr *list, InputInfoPtr pInfo)
@@ -1103,8 +1103,7 @@ addDevice(InputInfoPtr *list, InputInfoPtr pInfo)
     list = xnfrealloc(list, (count + 1) * sizeof(InputInfoPtr));
     list[count] = NULL;
 
-    list[count - 1] = xnfalloc(sizeof(InputInfoRec));
-    *list[count - 1] = *pInfo;
+    list[count - 1] = pInfo;
     return list;
 }
 
@@ -1131,7 +1130,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
     const char *pointerMsg = NULL, *keyboardMsg = NULL;
     InputInfoPtr *devs, /* iterator */
             indp;
-    InputInfoRec Pointer = {}, Keyboard = {};
+    InputInfoPtr Pointer, Keyboard;
     XF86ConfInputPtr confInput;
     XF86ConfInputRec defPtr, defKbd;
     MessageType from = X_DEFAULT;
@@ -1235,18 +1234,20 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 
     /* Add the core pointer device to the layout, and set it to Core. */
     if (foundPointer && confInput) {
-	foundPointer = configInput(&Pointer, confInput, from);
-        if (foundPointer) {
-	    Pointer.options = xf86addNewOption(Pointer.options,
+	Pointer = xf86AllocateInput();
+	if (Pointer)
+	    foundPointer = configInput(Pointer, confInput, from);
+	if (foundPointer) {
+	    Pointer->options = xf86addNewOption(Pointer->options,
 					       xnfstrdup("CorePointer"), "on");
-	    Pointer.fd = -1;
-	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Pointer);
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer);
 	}
     }
 
     if (!foundPointer && xf86Info.forceInputDevices) {
 	/* This shouldn't happen. */
 	xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n");
+	xf86DeleteInput(Pointer, 0);
 	return FALSE;
     }
 
@@ -1274,12 +1275,13 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	defPtr.inp_identifier = strdup("<default pointer>");
 	defPtr.inp_driver = strdup("mouse");
 	confInput = &defPtr;
-	foundPointer = configInput(&Pointer, confInput, from);
-        if (foundPointer) {
-	    Pointer.options = xf86addNewOption(NULL,
+	Pointer = xf86AllocateInput();
+	if (Pointer)
+	    foundPointer = configInput(Pointer, confInput, from);
+	if (foundPointer) {
+	    Pointer->options = xf86addNewOption(NULL,
 					       xnfstrdup("AlwaysCore"), "on");
-	    Pointer.fd = -1;
-	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Pointer);
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer);
 	}
     }
 
@@ -1356,18 +1358,20 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 
     /* Add the core keyboard device to the layout, and set it to Core. */
     if (foundKeyboard && confInput) {
-	foundKeyboard = configInput(&Keyboard, confInput, from);
-        if (foundKeyboard) {
-	    Keyboard.options = xf86addNewOption(Keyboard.options,
+	Keyboard = xf86AllocateInput();
+	if (Keyboard)
+	    foundKeyboard = configInput(Keyboard, confInput, from);
+	if (foundKeyboard) {
+	    Keyboard->options = xf86addNewOption(Keyboard->options,
 						xnfstrdup("CoreKeyboard"), "on");
-	    Keyboard.fd = -1;
-	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Keyboard);
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, Keyboard);
 	}
     }
 
     if (!foundKeyboard && xf86Info.forceInputDevices) {
 	/* This shouldn't happen. */
 	xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n");
+	xf86DeleteInput(Keyboard, 0);
 	return FALSE;
     }
 
commit fa8f4652819b692faaf2789cf32d7fa99fbb34aa
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 15:02:20 2011 +1000

    xfree86: factor out adding/removing a device from the input device array
    
    No functional changes, just readability improvements. This also gets rid of
    the count variable. Count was just used for resizing the null-terminated
    list. Since we're not in a time-critical path here at all we can afford to
    loop the list multiple times instead of keeping an extra variable around.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index c7d567d..83eac8b 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1068,6 +1068,46 @@ Bool xf86DRI2Enabled(void)
     return xf86Info.dri2;
 }
 
+/**
+ * Search for the pInfo in the null-terminated list given and remove (and
+ * free) it if present. All other devices are moved forward.
+ */
+static void
+freeDevice(InputInfoPtr *list, InputInfoPtr pInfo)
+{
+    InputInfoPtr *devs;
+
+    for (devs = list; devs && *devs; devs++) {
+	if (*devs == pInfo) {
+	    free(*devs);
+	    for (; devs && *devs; devs++)
+		devs[0] = devs[1];
+	    break;
+	}
+    }
+}
+
+/**
+ * Append pInfo to the null-terminated list, allocating space as necessary.
+ * pInfo is copied into the last element.
+ */
+static InputInfoPtr*
+addDevice(InputInfoPtr *list, InputInfoPtr pInfo)
+{
+    InputInfoPtr *devs;
+    int count = 1;
+
+    for (devs = list; devs && *devs; devs++)
+	count++;
+
+    list = xnfrealloc(list, (count + 1) * sizeof(InputInfoPtr));
+    list[count] = NULL;
+
+    list[count - 1] = xnfalloc(sizeof(InputInfoRec));
+    *list[count - 1] = *pInfo;
+    return list;
+}
+
 /*
  * Locate the core input devices.  These can be specified/located in
  * the following ways, in order of priority:
@@ -1094,7 +1134,6 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
     InputInfoRec Pointer = {}, Keyboard = {};
     XF86ConfInputPtr confInput;
     XF86ConfInputRec defPtr, defKbd;
-    int count = 0;
     MessageType from = X_DEFAULT;
     int found = 0;
     const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse",
@@ -1119,7 +1158,6 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 		coreKeyboard = indp;
 	    }
 	}
-	count++;
     }
 
     confInput = NULL;
@@ -1139,17 +1177,9 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	 * removed.
 	 */
 	if (corePointer) {
-	    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
-		if (*devs == corePointer) {
-		    free(*devs);
-		    for (; devs && *devs; devs++)
-			devs[0] = devs[1];
-		    break;
-		}
-	    }
-	    count--;
+	    freeDevice(servlayoutp->inputs, corePointer);
+	    corePointer = NULL;
 	}
-	corePointer = NULL;
 	foundPointer = TRUE;
     }
 
@@ -1210,14 +1240,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    Pointer.options = xf86addNewOption(Pointer.options,
 					       xnfstrdup("CorePointer"), "on");
 	    Pointer.fd = -1;
-	    count++;
-	    devs = xnfrealloc(servlayoutp->inputs,
-			      (count + 1) * sizeof(InputInfoPtr));
-            devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-	    devs[count] = NULL;
-
-	    *devs[count - 1] = Pointer;
-	    servlayoutp->inputs = devs;
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Pointer);
 	}
     }
 
@@ -1256,14 +1279,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    Pointer.options = xf86addNewOption(NULL,
 					       xnfstrdup("AlwaysCore"), "on");
 	    Pointer.fd = -1;
-	    count++;
-	    devs = xnfrealloc(servlayoutp->inputs,
-			      (count + 1) * sizeof(InputInfoPtr));
-            devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-	    devs[count] = NULL;
-
-	    *devs[count - 1] = Pointer;
-	    servlayoutp->inputs = devs;
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Pointer);
 	}
     }
 
@@ -1284,17 +1300,9 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	 * removed.
 	 */
 	if (coreKeyboard) {
-	    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
-		if (*devs == coreKeyboard) {
-		    free(*devs);
-		    for (; devs && *devs; devs++)
-			devs[0] = devs[1];
-		    break;
-		}
-	    }
-	    count--;
+	    freeDevice(servlayoutp->inputs, coreKeyboard);
+	    coreKeyboard = NULL;
 	}
-	coreKeyboard = NULL;
 	foundKeyboard = TRUE;
     }
 
@@ -1353,14 +1361,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    Keyboard.options = xf86addNewOption(Keyboard.options,
 						xnfstrdup("CoreKeyboard"), "on");
 	    Keyboard.fd = -1;
-	    count++;
-	    devs = xnfrealloc(servlayoutp->inputs,
-			      (count + 1) * sizeof(InputInfoPtr));
-            devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-	    devs[count] = NULL;
-
-	    *devs[count - 1] = Keyboard;
-	    servlayoutp->inputs = devs;
+	    servlayoutp->inputs = addDevice(servlayoutp->inputs, &Keyboard);
 	}
     }
 
commit 5b5477c05f691205064ca4d8034f8dd47ab975b7
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 14:14:11 2011 +1000

    xfree86: update comment for InitInput
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 71926f8..5ee68cd 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -806,11 +806,10 @@ duplicateDevice(InputInfoPtr pInfo)
     return dup;
 }
 
-/*
- * InitInput --
- *      Initialize all supported input devices.
+/**
+ * Initialize all supported input devices present and referenced in the
+ * xorg.conf.
  */
-
 void
 InitInput(int argc, char **argv)
 {
commit 7354f607833c69626d8692bc5176b18ea1cf6263
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 14:26:13 2011 +1000

    xfree86: nest loops instead of 0x1 pointers.
    
    If we find the core device, move all other device pointers forward right
    then and there. The break will jump out of the top loop.
    
    They had a special on braces today, so I added some for readability (and
    fixed up tab vs space indentation.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 2dba088..c7d567d 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1139,15 +1139,14 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	 * removed.
 	 */
 	if (corePointer) {
-	    for (devs = servlayoutp->inputs; devs && *devs; devs++)
-		if (*devs == corePointer)
-                {
-                    free(*devs);
-                    *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop*/
+	    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
+		if (*devs == corePointer) {
+		    free(*devs);
+		    for (; devs && *devs; devs++)
+			devs[0] = devs[1];
 		    break;
-                }
-	    for (; devs && *devs; devs++)
-		devs[0] = devs[1];
+		}
+	    }
 	    count--;
 	}
 	corePointer = NULL;
@@ -1285,15 +1284,14 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	 * removed.
 	 */
 	if (coreKeyboard) {
-	    for (devs = servlayoutp->inputs; devs && *devs; devs++)
-		if (*devs == coreKeyboard)
-                {
-                    free(*devs);
-                    *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop */
+	    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
+		if (*devs == coreKeyboard) {
+		    free(*devs);
+		    for (; devs && *devs; devs++)
+			devs[0] = devs[1];
 		    break;
-                }
-	    for (; devs && *devs; devs++)
-		devs[0] = devs[1];
+		}
+	    }
 	    count--;
 	}
 	coreKeyboard = NULL;
commit 5669aa2d24dff9ab276e5f74a09f97ec77b90e75
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 14:05:30 2011 +1000

    xfree86: improve readability of synthesized device.
    
    No functional changes.
    
    The options we assign are the ones from the Pointer/Keyboard device so we
    might as well use those readable names instead of dev[count-1]->options.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 04d0180..2dba088 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1208,16 +1208,16 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
     if (foundPointer && confInput) {
 	foundPointer = configInput(&Pointer, confInput, from);
         if (foundPointer) {
+	    Pointer.options = xf86addNewOption(Pointer.options,
+					       xnfstrdup("CorePointer"), "on");
+	    Pointer.fd = -1;
 	    count++;
 	    devs = xnfrealloc(servlayoutp->inputs,
 			      (count + 1) * sizeof(InputInfoPtr));
             devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-            Pointer.fd = -1;
-	    *devs[count - 1] = Pointer;
-	    devs[count - 1]->options =
-				xf86addNewOption(devs[count -1]->options,
-				    xnfstrdup("CorePointer"), "on");
 	    devs[count] = NULL;
+
+	    *devs[count - 1] = Pointer;
 	    servlayoutp->inputs = devs;
 	}
     }
@@ -1254,15 +1254,16 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	confInput = &defPtr;
 	foundPointer = configInput(&Pointer, confInput, from);
         if (foundPointer) {
+	    Pointer.options = xf86addNewOption(NULL,
+					       xnfstrdup("AlwaysCore"), "on");
+	    Pointer.fd = -1;
 	    count++;
 	    devs = xnfrealloc(servlayoutp->inputs,
 			      (count + 1) * sizeof(InputInfoPtr));
             devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-            Pointer.fd = -1;
-	    *devs[count - 1] = Pointer;
-	    devs[count - 1]->options =
-				xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), "on");
 	    devs[count] = NULL;
+
+	    *devs[count - 1] = Pointer;
 	    servlayoutp->inputs = devs;
 	}
     }
@@ -1351,16 +1352,16 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
     if (foundKeyboard && confInput) {
 	foundKeyboard = configInput(&Keyboard, confInput, from);
         if (foundKeyboard) {
+	    Keyboard.options = xf86addNewOption(Keyboard.options,
+						xnfstrdup("CoreKeyboard"), "on");
+	    Keyboard.fd = -1;
 	    count++;
 	    devs = xnfrealloc(servlayoutp->inputs,
 			      (count + 1) * sizeof(InputInfoPtr));
             devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
-            Keyboard.fd = -1;
-	    *devs[count - 1] = Keyboard;
-	    devs[count - 1]->options =
-				xf86addNewOption(devs[count - 1]->options,
-				    xnfstrdup("CoreKeyboard"), "on");
 	    devs[count] = NULL;
+
+	    *devs[count - 1] = Keyboard;
 	    servlayoutp->inputs = devs;
 	}
     }
commit 5aa826cdd1f2e768bedf23d399703a5d0b6302be
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 13:52:11 2011 +1000

    test: add a option duplication test
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/test/Makefile.am b/test/Makefile.am
index 7ef408c..689dd7f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,7 +1,7 @@
 if ENABLE_UNIT_TESTS
 if HAVE_LD_WRAP
 SUBDIRS= . xi2
-noinst_PROGRAMS = xkb input xtest list misc fixes
+noinst_PROGRAMS = xkb input xtest list misc fixes xfree86
 check_LTLIBRARIES = libxservertest.la
 
 TESTS=$(noinst_PROGRAMS)
@@ -23,6 +23,7 @@ xtest_LDADD=$(TEST_LDADD)
 list_LDADD=$(TEST_LDADD)
 misc_LDADD=$(TEST_LDADD)
 fixes_LDADD=$(TEST_LDADD)
+xfree86_LDADD=$(TEST_LDADD)
 
 nodist_libxservertest_la_SOURCES = $(top_builddir)/hw/xfree86/sdksyms.c
 libxservertest_la_LIBADD = \
diff --git a/test/xfree86.c b/test/xfree86.c
new file mode 100644
index 0000000..2b591cf
--- /dev/null
+++ b/test/xfree86.c
@@ -0,0 +1,80 @@
+/**
+ * Copyright © 2011 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <assert.h>
+
+
+#include "xf86.h"
+
+static void
+xfree86_option_list_duplicate(void)
+{
+    pointer options;
+    pointer duplicate;
+    const char *o1 = "foo",
+               *o2 = "bar",
+               *v1 = "one",
+               *v2 = "two";
+    const char *o_null= "NULL";
+    char *val1, *val2;
+
+    duplicate = xf86OptionListDuplicate(NULL);
+    assert(!duplicate);
+
+    options = xf86AddNewOption(NULL, o1, v1);
+    assert(options);
+    options = xf86AddNewOption(options, o2, v2);
+    assert(options);
+    options = xf86AddNewOption(options, o_null, NULL);
+    assert(options);
+
+    duplicate = xf86OptionListDuplicate(options);
+    assert(duplicate);
+
+    val1 = xf86CheckStrOption(options, o1, "1");
+    val2 = xf86CheckStrOption(duplicate, o1, "2");
+
+    assert(strcmp(val1, v1) == 0);
+    assert(strcmp(val1, val2) == 0);
+
+    val1 = xf86CheckStrOption(options, o2, "1");
+    val2 = xf86CheckStrOption(duplicate, o2, "2");
+
+    assert(strcmp(val1, v2) == 0);
+    assert(strcmp(val1, val2) == 0);
+
+    val1 = xf86FindOption(options, o_null);
+    val2 = xf86FindOption(duplicate, o_null);
+    assert(val1 && val2);
+}
+
+int main(int argc, char** argv)
+{
+    xfree86_option_list_duplicate();
+
+    return 0;
+}
commit 4527e2b776cfcdac2b189b5439b9a3d0b6433077
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 13:46:24 2011 +1000

    xfree86: when implicitly choosing a core device, set the option to a value
    
    Devices are core pointers/keyboards by default now anyway, but let's set the
    option to some value instead of just NULL.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index ddd0b36..04d0180 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1216,7 +1216,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    *devs[count - 1] = Pointer;
 	    devs[count - 1]->options =
 				xf86addNewOption(devs[count -1]->options,
-				    xnfstrdup("CorePointer"), NULL);
+				    xnfstrdup("CorePointer"), "on");
 	    devs[count] = NULL;
 	    servlayoutp->inputs = devs;
 	}
@@ -1261,7 +1261,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
             Pointer.fd = -1;
 	    *devs[count - 1] = Pointer;
 	    devs[count - 1]->options =
-				xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL);
+				xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), "on");
 	    devs[count] = NULL;
 	    servlayoutp->inputs = devs;
 	}
@@ -1359,7 +1359,7 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    *devs[count - 1] = Keyboard;
 	    devs[count - 1]->options =
 				xf86addNewOption(devs[count - 1]->options,
-				    xnfstrdup("CoreKeyboard"), NULL);
+				    xnfstrdup("CoreKeyboard"), "on");
 	    devs[count] = NULL;
 	    servlayoutp->inputs = devs;
 	}
commit 44d53728a6a533fc0a6e0a10269d1cc99e9dad32
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 4 13:44:44 2011 +1000

    xfree86: don't warn about duplicate core devices
    
    It doesn't matter. All devices are core pointer devices by default now
    anyway.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 58b30dd..ddd0b36 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1111,22 +1111,12 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
 	    xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) {
 	    if (!corePointer) {
 		corePointer = indp;
-	    } else {
-		    xf86ReplaceBoolOption(indp->options, "CorePointer", FALSE);
-		xf86Msg(X_WARNING, "Duplicate core pointer devices.  "
-			"Removing core pointer attribute from \"%s\"\n",
-			indp->name);
 	    }
 	}
 	if (indp->options &&
 	    xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) {
 	    if (!coreKeyboard) {
 		coreKeyboard = indp;
-	    } else {
-		    xf86ReplaceBoolOption(indp->options, "CoreKeyboard", FALSE);
-		xf86Msg(X_WARNING, "Duplicate core keyboard devices.  "
-			"Removing core keyboard attribute from \"%s\"\n",
-			indp->name);
 	    }
 	}
 	count++;
commit 033f53c223dc12a91f00e10a69f87a4f2a7adb6b
Author: Daniel Kurtz <djkurtz at chromium.org>
Date:   Mon Aug 8 15:09:48 2011 +0800

    xf86Helper: use LogHdrMessageVerb in xf86VDrvMsgVerb
    
    LogHdrMessageVerb allows passing a parameterized header to insert in a log
    message between MessageType and the formatted message body string.
    
    Signed-off-by: Daniel Kurtz <djkurtz at chromium.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index f42d0f9..d6c2a7b 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1027,36 +1027,20 @@ xf86EnableDisableFBAccess(int scrnIndex, Bool enable)
     }
 }
 
-/* Print driver messages in the standard format */
-
-#undef PREFIX_SIZE
-#define PREFIX_SIZE 14
-
+/* Print driver messages in the standard format of
+   (<type>) <screen name>(<screen index>): <message> */
 void
 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
 		va_list args)
 {
-    char *tmpFormat;
-
     /* Prefix the scrnIndex name to the format string. */
     if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
-	xf86Screens[scrnIndex]->name) {
-	tmpFormat = malloc(strlen(format) +
-			   strlen(xf86Screens[scrnIndex]->name) +
-			   PREFIX_SIZE + 1);
-	if (!tmpFormat)
-	    return;
-
-	snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ",
-		 xf86Screens[scrnIndex]->name, scrnIndex);
-
-	strcat(tmpFormat, format);
-	LogVMessageVerb(type, verb, tmpFormat, args);
-	free(tmpFormat);
-    } else
+	xf86Screens[scrnIndex]->name)
+	LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
+	    xf86Screens[scrnIndex]->name, scrnIndex);
+    else
 	LogVMessageVerb(type, verb, format, args);
 }
-#undef PREFIX_SIZE
 
 /* Print driver messages, with verbose level specified directly */
 void
commit cd8ee3e5cb29b9cd6402d2fbc71463c6b04b6077
Author: Daniel Kurtz <djkurtz at chromium.org>
Date:   Mon Aug 8 15:09:47 2011 +0800

    xf86Helper: use LogHdrMessageVerb in xf86VIDrvMsgVerb
    
    LogHdrMessageVerb allows passing a parameterized header to insert in a log
    message between MessageType and the formatted message body string.
    
    Signed-off-by: Daniel Kurtz <djkurtz at chromium.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index f8e6c8b..f42d0f9 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1082,20 +1082,23 @@ xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
 }
 
 /* Print input driver messages in the standard format of
-   <driver>: <device name>: <message> */
+   (<type>) <driver>: <device name>: <message> */
 void
-xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
-		 va_list args)
+xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb,
+		 const char *format, va_list args)
 {
-    char *msg;
+    const char *driverName = NULL;
+    const char *deviceName = NULL;
 
-    if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format)
-	== -1) {
-	LogVMessageVerb(type, verb, "%s", args);
-    } else {
-	LogVMessageVerb(type, verb, msg, args);
-	free(msg);
+    /* Prefix driver and device names to formatted message. */
+    if (dev) {
+	deviceName = dev->name;
+	if (dev->drv)
+	    driverName = dev->drv->driverName;
     }
+
+    LogHdrMessageVerb(type, verb, format, args, "%s: %s: ", driverName,
+	deviceName);
 }
 
 /* Print input driver message, with verbose level specified directly */
commit b31d104fc09a7241856ff8d226be11ec562beac3
Author: Daniel Kurtz <djkurtz at chromium.org>
Date:   Mon Aug 8 15:09:46 2011 +0800

    os/log: Add LogVHdrMessageVerb and friends
    
    LogVHdrMessageVerb allows a custom header to be inserted in a log message,
    between the Log system's MessageType string, and a formatted variable
    message body. The custom header can itself be a formatted variable string.
    
    These functions can be used, for example, by driver abstraction layers to
    format specific driver messages in a standard format, but do it in a way
    that is efficient, obeys the log-layers verbosity settings, and is safe
    to use in signal handlers (because they don't call malloc), even for
    types besides X_NONE.
    
    Signed-off-by: Daniel Kurtz <djkurtz at chromium.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/os.h b/include/os.h
index a553f57..5401ea4 100644
--- a/include/os.h
+++ b/include/os.h
@@ -525,6 +525,19 @@ extern _X_EXPORT void LogMessageVerb(MessageType type, int verb, const char *for
 			   ...) _X_ATTRIBUTE_PRINTF(3,4);
 extern _X_EXPORT void LogMessage(MessageType type, const char *format, ...)
 			_X_ATTRIBUTE_PRINTF(2,3);
+
+extern _X_EXPORT void LogVHdrMessageVerb(MessageType type, int verb,
+			    const char *msg_format, va_list msg_args,
+			    const char *hdr_format, va_list hdr_args)
+			_X_ATTRIBUTE_PRINTF(3,0) _X_ATTRIBUTE_PRINTF(5,0);
+extern _X_EXPORT void LogHdrMessageVerb(MessageType type, int verb,
+			    const char *msg_format, va_list msg_args,
+			    const char *hdr_format, ...)
+			_X_ATTRIBUTE_PRINTF(3,0) _X_ATTRIBUTE_PRINTF(5,6);
+extern _X_EXPORT void LogHdrMessage(MessageType type, const char *msg_format,
+			    va_list msg_args, const char *hdr_format, ...)
+			_X_ATTRIBUTE_PRINTF(2,0) _X_ATTRIBUTE_PRINTF(4,5);
+
 extern _X_EXPORT void FreeAuditTimer(void);
 extern _X_EXPORT void AuditF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
 extern _X_EXPORT void VAuditF(const char *f, va_list args) _X_ATTRIBUTE_PRINTF(1,0);
diff --git a/os/log.c b/os/log.c
index 4ff0180..2eddf06 100644
--- a/os/log.c
+++ b/os/log.c
@@ -411,6 +411,61 @@ LogMessage(MessageType type, const char *format, ...)
     va_end(ap);
 }
 
+
+void
+LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
+		   va_list msg_args, const char *hdr_format, va_list hdr_args)
+{
+    const char *type_str;
+    char tmpFormat[1024];
+    char *tmpFormat_end = &tmpFormat[sizeof(tmpFormat)];
+    char *p;
+    int left;
+
+    type_str = LogMessageTypeVerbString(type, verb);
+    if (!type_str)
+	return;
+
+    /* if type_str != "", copy it and ' ' to tmpFormat; set p after ' ' */
+    p = tmpFormat;
+    if (type_str[0] != '\0')
+	p += snprintf(tmpFormat, sizeof(tmpFormat), "%s ", type_str);
+
+    /* append as much of hdr as fits after type_str (if there was one) */
+    left = tmpFormat_end - p;
+    if (left > 1)
+	p += vsnprintf(p, left, hdr_format, hdr_args);
+
+    /* append as much of msg_format as will fit after hdr */
+    left = tmpFormat_end - p;
+    if (left > 1)
+	snprintf(p, left, "%s", msg_format);
+
+    LogVWrite(verb, tmpFormat, msg_args);
+}
+
+void
+LogHdrMessageVerb(MessageType type, int verb, const char *msg_format,
+		  va_list msg_args, const char *hdr_format, ...)
+{
+    va_list hdr_args;
+
+    va_start(hdr_args, hdr_format);
+    LogVHdrMessageVerb(type, verb, msg_format, msg_args, hdr_format, hdr_args);
+    va_end(hdr_args);
+}
+
+void
+LogHdrMessage(MessageType type, const char *msg_format, va_list msg_args,
+	      const char *hdr_format, ...)
+{
+    va_list hdr_args;
+
+    va_start(hdr_args, hdr_format);
+    LogVHdrMessageVerb(type, 1, msg_format, msg_args, hdr_format, hdr_args);
+    va_end(hdr_args);
+}
+
 void
 AbortServer(void) _X_NORETURN;
 
commit b82f934db661c59d7397ce180d08cf8f8f7118b1
Author: Daniel Kurtz <djkurtz at chromium.org>
Date:   Mon Aug 8 15:09:45 2011 +0800

    os/log: Pull LogMessageTypeVerbString out of LogVMessageVerb
    
    Also, optimize how the type and format strings are combined.
    
    Signed-off-by: Daniel Kurtz <djkurtz at chromium.org>
    Reviewed-by: Guillem Jover <guillem at hadrons.org>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/os/log.c b/os/log.c
index f519762..4ff0180 100644
--- a/os/log.c
+++ b/os/log.c
@@ -165,6 +165,9 @@ asm (".desc ___crashreporter_info__, 0x10");
 #ifndef X_NOT_IMPLEMENTED_STRING
 #define X_NOT_IMPLEMENTED_STRING	"(NI)"
 #endif
+#ifndef X_NONE_STRING
+#define X_NONE_STRING                   ""
+#endif
 
 /*
  * LogInit is called to start logging to a file.  It is also called (with
@@ -325,58 +328,65 @@ LogWrite(int verb, const char *f, ...)
     va_end(args);
 }
 
+/* Returns the Message Type string to prepend to a logging message, or NULL
+ * if the message will be dropped due to insufficient verbosity. */
+static const char *
+LogMessageTypeVerbString(MessageType type, int verb)
+{
+    if (type == X_ERROR)
+	verb = 0;
+
+    if (logVerbosity < verb && logFileVerbosity < verb)
+	return NULL;
+
+    switch (type) {
+    case X_PROBED:
+	return X_PROBE_STRING;
+    case X_CONFIG:
+	return X_CONFIG_STRING;
+    case X_DEFAULT:
+	return X_DEFAULT_STRING;
+    case X_CMDLINE:
+	return X_CMDLINE_STRING;
+    case X_NOTICE:
+	return X_NOTICE_STRING;
+    case X_ERROR:
+	return X_ERROR_STRING;
+    case X_WARNING:
+	return X_WARNING_STRING;
+    case X_INFO:
+	return X_INFO_STRING;
+    case X_NOT_IMPLEMENTED:
+	return X_NOT_IMPLEMENTED_STRING;
+    case X_UNKNOWN:
+	return X_UNKNOWN_STRING;
+    case X_NONE:
+	return X_NONE_STRING;
+    default:
+	return X_UNKNOWN_STRING;
+    }
+}
+
 void
 LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
 {
-    const char *s  = X_UNKNOWN_STRING;
-    char tmpBuf[1024];
-
-    /* Ignore verbosity for X_ERROR */
-    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
-	switch (type) {
-	case X_PROBED:
-	    s = X_PROBE_STRING;
-	    break;
-	case X_CONFIG:
-	    s = X_CONFIG_STRING;
-	    break;
-	case X_DEFAULT:
-	    s = X_DEFAULT_STRING;
-	    break;
-	case X_CMDLINE:
-	    s = X_CMDLINE_STRING;
-	    break;
-	case X_NOTICE:
-	    s = X_NOTICE_STRING;
-	    break;
-	case X_ERROR:
-	    s = X_ERROR_STRING;
-	    if (verb > 0)
-		verb = 0;
-	    break;
-	case X_WARNING:
-	    s = X_WARNING_STRING;
-	    break;
-	case X_INFO:
-	    s = X_INFO_STRING;
-	    break;
-	case X_NOT_IMPLEMENTED:
-	    s = X_NOT_IMPLEMENTED_STRING;
-	    break;
-	case X_UNKNOWN:
-	    s = X_UNKNOWN_STRING;
-	    break;
-	case X_NONE:
-	    s = NULL;
-	    break;
-	}
-
-        /* if s is not NULL we need a space before format */
-        snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
-                                                   s ? " " : "",
-                                                   format);
-        LogVWrite(verb, tmpBuf, args);
+    const char *type_str;
+    char tmpFormat[1024];
+    char *new_format;
+
+    type_str = LogMessageTypeVerbString(type, verb);
+    if (!type_str)
+	return;
+
+    /* if type_str is not "", prepend it and ' ', to format */
+    if (type_str[0] == '\0')
+        new_format = format;
+    else {
+        new_format = tmpFormat;
+        snprintf(tmpFormat, sizeof(tmpFormat), "%s %s", type_str, format);
     }
+
+    LogVWrite(verb, new_format, args);
 }
 
 /* Log message with verbosity level specified. */


More information about the Xquartz-changes mailing list