From b82f934db661c59d7397ce180d08cf8f8f7118b1 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Mon, 8 Aug 2011 15:09:45 +0800 Subject: [PATCH 01/42] os/log: Pull LogMessageTypeVerbString out of LogVMessageVerb Also, optimize how the type and format strings are combined. Signed-off-by: Daniel Kurtz Reviewed-by: Guillem Jover Signed-off-by: Peter Hutterer --- os/log.c | 102 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/os/log.c b/os/log.c index f51976284..4ff018078 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]; + const char *type_str; + char tmpFormat[1024]; + char *new_format; - /* 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; - } + type_str = LogMessageTypeVerbString(type, verb); + if (!type_str) + return; - /* 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); + /* 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. */ From b31d104fc09a7241856ff8d226be11ec562beac3 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Mon, 8 Aug 2011 15:09:46 +0800 Subject: [PATCH 02/42] 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 Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- include/os.h | 13 +++++++++++++ os/log.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/os.h b/include/os.h index a553f5783..5401ea478 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 4ff018078..2eddf066a 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; From cd8ee3e5cb29b9cd6402d2fbc71463c6b04b6077 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Mon, 8 Aug 2011 15:09:47 +0800 Subject: [PATCH 03/42] 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 Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- hw/xfree86/common/xf86Helper.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index f8e6c8b41..f42d0f9df 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 - : : */ + () : : */ 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 */ From 033f53c223dc12a91f00e10a69f87a4f2a7adb6b Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Mon, 8 Aug 2011 15:09:48 +0800 Subject: [PATCH 04/42] 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 Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- hw/xfree86/common/xf86Helper.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index f42d0f9df..d6c2a7b81 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 + () (): */ 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 From 44d53728a6a533fc0a6e0a10269d1cc99e9dad32 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 13:44:44 +1000 Subject: [PATCH 05/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 58b30dd68..ddd0b3684 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++; From 4527e2b776cfcdac2b189b5439b9a3d0b6433077 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 13:46:24 +1000 Subject: [PATCH 06/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index ddd0b3684..04d0180a9 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; } From 5aa826cdd1f2e768bedf23d399703a5d0b6302be Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 13:52:11 +1000 Subject: [PATCH 07/42] test: add a option duplication test Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- test/Makefile.am | 3 +- test/xfree86.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 test/xfree86.c diff --git a/test/Makefile.am b/test/Makefile.am index 7ef408c93..689dd7f60 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 000000000..2b591cfde --- /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 +#endif + +#include + + +#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; +} From 5669aa2d24dff9ab276e5f74a09f97ec77b90e75 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 14:05:30 +1000 Subject: [PATCH 08/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 04d0180a9..2dba088ad 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; } } From 7354f607833c69626d8692bc5176b18ea1cf6263 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 14:26:13 +1000 Subject: [PATCH 09/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 2dba088ad..c7d567d55 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; From 5b5477c05f691205064ca4d8034f8dd47ab975b7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 14:14:11 +1000 Subject: [PATCH 10/42] xfree86: update comment for InitInput Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Init.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c index 71926f8e7..5ee68cd26 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) { From fa8f4652819b692faaf2789cf32d7fa99fbb34aa Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Jul 2011 15:02:20 +1000 Subject: [PATCH 11/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 93 +++++++++++++++++----------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index c7d567d55..83eac8b73 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); } } From 95772598b57f6054fbf88683fa0a492c77605790 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 8 Jul 2011 16:10:07 +1000 Subject: [PATCH 12/42] xfree86: use xf86AllocateInput for implicit devices too Slowly merging the vastly different code-paths. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 83eac8b73..8670e535a 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(""); 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; } From 159b03e13760920274b573a2bccdbf6a79f059e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 Jul 2011 21:19:23 +0200 Subject: [PATCH 13/42] 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 --- config/udev.c | 18 ++++++++++++++++++ hw/xfree86/common/xf86Init.c | 19 +++++++++++++++++++ include/globals.h | 2 +- include/xserver-properties.h | 3 +++ man/Xserver.man | 6 ++++++ os/utils.c | 10 ++++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/config/udev.c b/config/udev.c index e7383dc36..fc6ee5dac 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 5ee68cd26..89bc82a97 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 @@ -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 8b80a652b..17bca8208 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 2b1feabb6..bf50042d0 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 f74391212..1a36b0956 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 36cb46f11..e8ecb7193 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) From 1357cd725143c1a35e32f15df658de111b151692 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 8 Jul 2011 16:13:45 +1000 Subject: [PATCH 14/42] 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 Reviewed-by: Daniel Stone --- hw/xfree86/common/xf86Config.c | 35 ---------------------------------- 1 file changed, 35 deletions(-) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 8670e535a..25755fd57 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(""); - 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. */ From e684e816acb617b4dc66a68e2b0ba8f80399170a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 20 Jul 2011 16:21:28 +1000 Subject: [PATCH 15/42] config: fix a log message PRODUCT was taken from the parent, hence ppath. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- config/udev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/udev.c b/config/udev.c index fc6ee5dac..b11c81d8e 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) From d33652dad8838ab0a9175ca4613a3161ebc5676f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 9 Aug 2011 11:20:31 +1000 Subject: [PATCH 16/42] 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 Reviewed-by: Daniel Stone --- config/config-backends.h | 2 +- config/config.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/config/config-backends.h b/config/config-backends.h index 0a2a22af0..0d36d7208 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 d86f7c649..af8f4f9b2 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; } From 20a61845d3c93c337bf3331a6bac30cf66c2a293 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 9 Aug 2011 11:21:06 +1000 Subject: [PATCH 17/42] 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 Reviewed-by: Daniel Stone --- config/dbus.c | 10 +--------- config/hal.c | 10 +--------- config/udev.c | 8 +------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/config/dbus.c b/config/dbus.c index 34e3caade..41eca998a 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 297520aa6..0b2d7d00c 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 b11c81d8e..1f431c1d3 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); From 80c37048539daa1d257d127d66502bde45c97c85 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 28 Jul 2011 15:43:10 +1000 Subject: [PATCH 18/42] 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 Reviewed-by: Daniel Stone --- dix/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index 8a4c6b9ac..25ff8997f 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) From 09496996accfdaf7bc01097a25db400912004d97 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 28 Jul 2011 15:56:08 +1000 Subject: [PATCH 19/42] 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 Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- dix/grabs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dix/grabs.c b/dix/grabs.c index 85ca9eee0..c28356d9b 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)) { From c9562bed0d5e26b7e3e55e26cf1ddc5086d61cc6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 09:52:38 +1000 Subject: [PATCH 20/42] =?UTF-8?q?dix:=20rename=20mieqSwitchScreen=20argume?= =?UTF-8?q?nt=20fromDix=20=E2=86=92=20set=5Fdequeue=5Fscreen,=20document?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Daniel Stone --- mi/mi.h | 2 +- mi/mieq.c | 19 +++++++++++++++++-- mi/mipointer.h | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/mi/mi.h b/mi/mi.h index c186940ff..24d1af911 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 fc3738a41..b75bde9de 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 539096e78..c4265f9d8 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; From b3c76b0c53ac42b70d12849da18465e8467e474c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 11:54:17 +1000 Subject: [PATCH 21/42] mi: fix comment typo, whitespace in miPointerSetPosition Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- mi/mipointer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mi/mipointer.c b/mi/mipointer.c index 7680ca19b..670f63b6e 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); From dbbe5735d1451bb32f43bce90f0bcfeff46f9743 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 2 Aug 2011 08:54:00 +1000 Subject: [PATCH 22/42] test: add a test for GetMaster() behaviour Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- test/input.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/input.c b/test/input.c index 837ce49dc..31597f9de 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; } From 98fe735ea1d756711019c3d90ed6abd9c06abebf Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 13:52:13 +1000 Subject: [PATCH 23/42] 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 Reviewed-by: Daniel Stone --- dix/devices.c | 31 ++++++++++++++++++++----------- include/inputstr.h | 5 ++++- test/input.c | 13 +++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/dix/devices.c b/dix/devices.c index 0ccf25277..334f5d3f5 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 00f72c260..838f9f021 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 31597f9de..c2b0eb012 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); } From 484cef5b29ef82402a15e155b3b8505b1e4a6830 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 2 Aug 2011 09:21:00 +1000 Subject: [PATCH 24/42] 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 Reviewed-by: Daniel Stone --- Xi/exevents.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 3e3c67b63..38089a27c 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); From 6fd2adc179141310e45a56ee90ef5b5f6115a1f6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 14:27:54 +1000 Subject: [PATCH 25/42] 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 Reviewed-by: Daniel Stone --- mi/misprite.c | 5 ----- mi/mivaltree.c | 2 -- 2 files changed, 7 deletions(-) diff --git a/mi/misprite.c b/mi/misprite.c index 1cfcdf6ee..1025c5a6f 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 0e00c2fb5..e1d47c06f 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); From 4b376ddeb4f3c9d9d279ffd2946d88edd5af4cfc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 14:20:53 +1000 Subject: [PATCH 26/42] 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 Reviewed-by: Daniel Stone --- dix/devices.c | 2 -- dix/events.c | 4 ---- dix/getevents.c | 8 -------- 3 files changed, 14 deletions(-) diff --git a/dix/devices.c b/dix/devices.c index 334f5d3f5..ab8a648a9 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 25ff8997f..8419064ba 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 a12462a4a..f7f4617e7 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)); From 3a077f246e9ac07a37c1b01c3d321e0f5ceb4153 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 3 Aug 2011 15:07:23 +1000 Subject: [PATCH 27/42] 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 --- dix/getevents.c | 19 ++++--------------- dix/inpututils.c | 14 ++++++++++++++ include/inpututils.h | 1 + xkb/xkbAccessX.c | 8 ++------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index f7f4617e7..be2840c47 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -153,17 +153,6 @@ key_autorepeats(DeviceIntPtr pDev, int key_code) (1 << (key_code & 7))); } -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) { @@ -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 49e175822..96320767d 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 92a754327..63e1a263a 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 12fe2a1f5..4115ff27d 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, From 8c5a4d6fbecf79f2dc4f2d836d741203b2d5e856 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 14:12:41 +1000 Subject: [PATCH 28/42] dix: don't use the pointer as modifier device in UngrabKey. Modifier device is always the keyboard. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- dix/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index 8419064ba..8e07532ec 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; From 799879797505a5e891ccaec2bea73fd838c94b7a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 11 Aug 2011 10:57:05 +1000 Subject: [PATCH 29/42] 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 Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/events.c | 53 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/dix/events.c b/dix/events.c index 8e07532ec..0e22fdc20 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,13 +447,27 @@ 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. */ @@ -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 { From 3be379f5076566edaf92c27df5a4d447bcf5d015 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 11 Aug 2011 10:59:07 +1000 Subject: [PATCH 30/42] 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 Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/events.c | 65 ++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/dix/events.c b/dix/events.c index 0e22fdc20..27c317290 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; + if ((type = GetXI2Type(event)) != 0) + { + filter = GetXI2EventFilterMask(type); - type = GetXIType(event); - ev.u.u.type = type; - filter = GetEventFilter(dev, &ev); + if (inputMasks && + (GetXI2MaskByte(inputMasks->xi2mask, dev, type) & filter)) + rc |= EVENT_XI2_MASK; + } - /* Check for XI mask */ - if (type && inputMasks && - (inputMasks->deliverableEvents[dev->id] & filter) && - (inputMasks->inputEvents[dev->id] & filter)) - rc |= EVENT_XI1_MASK; + if ((type = GetXIType(event)) != 0) + { + filter = GetEventFilterMask(dev, type); - /* Check for XI DontPropagate mask */ - if (type && inputMasks && - (inputMasks->dontPropagateMask[dev->id] & filter)) - rc |= EVENT_DONT_PROPAGATE_MASK; + /* Check for XI mask */ + if (inputMasks && + (inputMasks->deliverableEvents[dev->id] & filter) && + (inputMasks->inputEvents[dev->id] & filter)) + rc |= EVENT_XI1_MASK; - /* Check for core mask */ - type = GetCoreType(event); - if (type && (win->deliverableEvents & filter) && - ((wOtherEventMasks(win) | win->eventMask) & filter)) - rc |= EVENT_CORE_MASK; + /* Check for XI DontPropagate mask */ + if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) + rc |= EVENT_DONT_PROPAGATE_MASK; - /* Check for core DontPropagate mask */ - if (type && (filter & wDontPropagateMask(win))) - 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; } From b29ce0726d55ec41cfbce0814e21b0217ef64efe Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 9 Aug 2011 11:00:34 +0900 Subject: [PATCH 31/42] 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 Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- test/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/input.c b/test/input.c index c2b0eb012..5d4cbf686 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); From 2bfb802839688ecf328119c4c6979390fc60348d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 29 Jul 2011 16:33:54 +1000 Subject: [PATCH 32/42] 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 Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- dix/events.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/dix/events.c b/dix/events.c index 27c317290..7fe0fba5d 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 From 79ca7c0b5786a02a80a1c40ed475e928da7c82b3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 12 Aug 2011 15:55:48 +1000 Subject: [PATCH 33/42] xfree86: comment typo fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit in synch → in sync Signed-off-by: Peter Hutterer --- hw/xfree86/common/xf86Xinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index d22fdc8b9..83d5caedf 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 From fcafe825751bef99f4c0b36250ca6f15f127502f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 8 Aug 2011 15:21:46 +1000 Subject: [PATCH 34/42] 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 Reviewed-by: Alan Coopersmith --- include/list.h | 160 +++++++++++++++++++++++++++++++++++++++++++++++ test/list.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+) diff --git a/include/list.h b/include/list.h index 5933b973d..7825dce52 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 = + * 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 b101c7619..f7d7bffce 100644 --- a/test/list.c +++ b/test/list.c @@ -29,6 +29,7 @@ #include #include #include +#include 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; } From 05284a03f9002b03a66ae355b34790ec02b726f0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 4 Aug 2011 14:45:46 +1000 Subject: [PATCH 35/42] 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 Reviewed-by: Dan Nicholson --- config/config-backends.h | 2 +- config/config.c | 22 ----- config/dbus.c | 52 ++++-------- config/hal.c | 36 ++++----- config/udev.c | 35 ++++---- dix/inpututils.c | 141 +++++++++++++++++++++++++++++++++ hw/xfree86/common/xf86Xinput.c | 30 ++++--- include/input.h | 17 ++-- include/inputstr.h | 7 ++ test/input.c | 90 +++++++++++++++++++++ 10 files changed, 310 insertions(+), 122 deletions(-) diff --git a/config/config-backends.h b/config/config-backends.h index 0d36d7208..35ab8a044 100644 --- a/config/config-backends.h +++ b/config/config-backends.h @@ -27,10 +27,10 @@ #include #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 af8f4f9b2..9c28785c6 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 41eca998a..f0fc5686e 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 0b2d7d00c..aa234ebb4 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 1f431c1d3..1ba0d500d 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 96320767d..7aeb1e516 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 83d5caedf..e25115c9a 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 5377a0c13..0258f4f18 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 838f9f021..480e95671 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 5d4cbf686..b8dad1c60 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; } From 24823f1ab0f16e0815ef44340894537dc4babf6a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 3 Aug 2011 16:01:28 +1000 Subject: [PATCH 36/42] 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 Reviewed-by: Dan Nicholson 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 Reviewed-by: Alan Coopersmith --- hw/xfree86/common/Makefile.am | 2 +- hw/xfree86/common/xf86.h | 2 +- hw/xfree86/common/xf86Opt.h | 67 +++++++------- hw/xfree86/common/xf86Option.c | 111 +++++++++++------------ hw/xfree86/common/xf86Optionstr.h | 53 +++++++++++ hw/xfree86/common/xf86Xinput.c | 2 +- hw/xfree86/common/xf86Xinput.h | 4 +- hw/xfree86/doc/ddxDesign.xml | 14 +-- hw/xfree86/os-support/shared/posix_tty.c | 4 +- hw/xfree86/os-support/xf86_OSproc.h | 5 +- hw/xfree86/parser/Makefile.am | 2 + hw/xfree86/parser/xf86Optrec.h | 25 +---- test/xfree86.c | 11 ++- 13 files changed, 168 insertions(+), 134 deletions(-) create mode 100644 hw/xfree86/common/xf86Optionstr.h diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am index c031d4be3..23ddb5c34 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 54332e381..ae152b94b 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 9453f2a73..88392dc6d 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 a3a836fc1..73b6573f1 100644 --- a/hw/xfree86/common/xf86Option.c +++ b/hw/xfree86/common/xf86Option.c @@ -40,11 +40,12 @@ #include #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 000000000..8cc82d34c --- /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 e25115c9a..114cdd9d6 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 1b0b16f04..a4d9e58a5 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 02909602c..bc25c56d8 100644 --- a/hw/xfree86/doc/ddxDesign.xml +++ b/hw/xfree86/doc/ddxDesign.xml @@ -3175,7 +3175,7 @@ would not need to use these directly.
- pointer xf86FindOption(pointer options, const char *name); + XF86OptionPtr xf86FindOption(XF86OptionPtr options, const char *name);
Takes a list of options and an option name, and returns a handle @@ -3187,7 +3187,7 @@ would not need to use these directly.
- char *xf86FindOptionValue(pointer options, const char *name); + char *xf86FindOptionValue(XF86OptionPtr options, const char *name);
Takes a list of options and an option name, and returns the value @@ -3201,7 +3201,7 @@ would not need to use these directly.
- void xf86MarkOptionUsed(pointer option); + void xf86MarkOptionUsed(XF86OptionPtr option);
Takes a handle for an option, and marks that option as used. @@ -3211,7 +3211,7 @@ would not need to use these directly.
- void xf86MarkOptionUsedByName(pointer options, const char *name); + void xf86MarkOptionUsedByName(XF86OptionPtr options, const char *name);
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.
- void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts); + void xf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts);
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.
- void xf86ProcessOptions(int scrnIndex, pointer options, + void xf86ProcessOptions(int scrnIndex, XF86OptionPtr options, OptionInfoPtr optinfo);
@@ -3354,7 +3354,7 @@ Next, the higher level functions that most drivers would use.
- void xf86ShowUnusedOptions(int scrnIndex, pointer options); + void xf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr options);
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 fb8386022..cc12a31f2 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 f0cb768be..6a29fbdc9 100644 --- a/hw/xfree86/os-support/xf86_OSproc.h +++ b/hw/xfree86/os-support/xf86_OSproc.h @@ -126,6 +126,7 @@ #include #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 1cd70e7a5..002cfbf5c 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 5ccf7285b..61a8c5ff5 100644 --- a/hw/xfree86/parser/xf86Optrec.h +++ b/hw/xfree86/parser/xf86Optrec.h @@ -65,33 +65,10 @@ #define _xf86Optrec_h_ #include #include +#include "xf86Optionstr.h" #include -/* - * 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 2b591cfde..7012e90c3 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) From f52d5cd374563544dafe29587411f345e31bbdf8 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 31 Aug 2011 00:46:52 +0200 Subject: [PATCH 37/42] 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 Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/xipassivegrab.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index ae4343344..5cdd8aca6 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 && From 2d2dce558d24eeea0eb011ec9ebaa6c5c2273c39 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Wed, 14 Sep 2011 09:58:34 +0800 Subject: [PATCH 38/42] 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 Signed-off-by: Peter Hutterer --- dix/events.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index 7fe0fba5d..fbe4fc953 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) From 9125952b407090b040bffb3d752288293137cf77 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 5 Sep 2011 15:43:14 +1000 Subject: [PATCH 39/42] xfree86: fix comment typo Signed-off-by: Peter Hutterer --- hw/xfree86/common/xf86Xinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 114cdd9d6..526b92d3a 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 From cf51424a34fb2b567a867338ab44f83b5c43251c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 6 Sep 2011 09:39:01 +1000 Subject: [PATCH 40/42] xfree86: use subheader for Pointer Acceleration parts in xorg.conf(5) Signed-off-by: Peter Hutterer --- hw/xfree86/man/xorg.conf.man | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man index f406f82bb..6774dbc5e 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 From 4b4caecb7d2c8e0b7e4fedc95fba2a728bbc25e6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 6 Sep 2011 09:33:43 +1000 Subject: [PATCH 41/42] 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 Reviewed-by: Simon Thum --- hw/xfree86/common/xf86Xinput.c | 29 +++++++++++++++++++++++++++++ hw/xfree86/man/xorg.conf.man | 11 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 526b92d3a..9fbcba9d5 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 6774dbc5e..df877b998 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 From c7163fdd302f706a3d67f0fdf93eeb3396bb3332 Mon Sep 17 00:00:00 2001 From: "vdb@picaros.org" Date: Wed, 31 Aug 2011 07:23:01 +0200 Subject: [PATCH 42/42] xfree86: .BI style: monitor section in xorg.conf man page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Peter Hutterer --- hw/xfree86/man/xorg.conf.man | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man index df877b998..8615343f2 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.