diff options
-rw-r--r-- | Xi/xiquerypointer.c | 25 | ||||
-rw-r--r-- | include/Xprintf.h | 12 | ||||
-rw-r--r-- | os/log.c | 105 | ||||
-rw-r--r-- | os/xprintf.c | 44 |
4 files changed, 123 insertions, 63 deletions
diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c index a2e7442e0..169436e14 100644 --- a/Xi/xiquerypointer.c +++ b/Xi/xiquerypointer.c @@ -79,10 +79,21 @@ ProcXIQueryPointer(ClientPtr client) XkbStatePtr state; char *buttons = NULL; int buttons_size = 0; /* size of buttons array */ + XIClientPtr xi_client; + Bool have_xi22 = FALSE; REQUEST(xXIQueryPointerReq); REQUEST_SIZE_MATCH(xXIQueryPointerReq); + /* Check if client is compliant with XInput 2.2 or later. Earlier clients + * do not know about touches, so we must report emulated button presses. 2.2 + * and later clients are aware of touches, so we don't include emulated + * button presses in the reply. */ + xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); + if (version_compare(xi_client->major_version, + xi_client->minor_version, 2, 2) >= 0) + have_xi22 = TRUE; + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); if (rc != Success) { client->errorValue = stuff->deviceid; @@ -132,7 +143,7 @@ ProcXIQueryPointer(ClientPtr client) } if (pDev->button) { - int i, down; + int i; rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); @@ -142,14 +153,12 @@ ProcXIQueryPointer(ClientPtr client) if (!buttons) return BadAlloc; - down = pDev->button->buttonsDown; + for (i = 1; i < pDev->button->numButtons; i++) + if (BitIsOn(pDev->button->down, i)) + SetBit(buttons, pDev->button->map[i]); - for (i = 0; i < pDev->button->numButtons && down; i++) { - if (BitIsOn(pDev->button->down, i)) { - SetBit(buttons, i); - down--; - } - } + if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0) + SetBit(buttons, pDev->button->map[1]); } else rep.buttons_len = 0; diff --git a/include/Xprintf.h b/include/Xprintf.h index 414fd46fb..9e8cdc5dc 100644 --- a/include/Xprintf.h +++ b/include/Xprintf.h @@ -66,4 +66,16 @@ _X_ATTRIBUTE_PRINTF(2, 0); #define vasprintf Xvasprintf #endif +/* + * These functions provide a portable implementation of the linux kernel + * scnprintf & vscnprintf routines that return the number of bytes actually + * copied during a snprintf, (excluding the final '\0'). + */ +extern _X_EXPORT int +Xscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, ...) +_X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT int +Xvscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, va_list va) +_X_ATTRIBUTE_PRINTF(3,0); + #endif /* XPRINTF_H */ @@ -165,7 +165,7 @@ asm(".desc ___crashreporter_info__, 0x10"); #define X_NOT_IMPLEMENTED_STRING "(NI)" #endif #ifndef X_NONE_STRING -#define X_NONE_STRING "" +#define X_NONE_STRING "" #endif /* @@ -223,7 +223,7 @@ LogInit(const char *fname, const char *backup) * needed. */ if (saveBuffer && bufferSize > 0) { - free(saveBuffer); /* Must be free(), not free() */ + free(saveBuffer); saveBuffer = NULL; bufferSize = 0; } @@ -265,36 +265,19 @@ LogSetParameter(LogParameter param, int value) } /* This function does the actual log message writes. */ - -void -LogVWrite(int verb, const char *f, va_list args) +static void +LogSWrite(int verb, const char *buf, size_t len, Bool end_line) { - static char tmpBuffer[1024]; - int len = 0; static Bool newline = TRUE; - if (newline) { - sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); - len = strlen(tmpBuffer); - if (logFile) - fwrite(tmpBuffer, len, 1, logFile); - } - - /* - * Since a va_list can only be processed once, write the string to a - * buffer, and then write the buffer out to the appropriate output - * stream(s). - */ - if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { - vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args); - len = strlen(tmpBuffer); - } - newline = (tmpBuffer[len - 1] == '\n'); - if ((verb < 0 || logVerbosity >= verb) && len > 0) - fwrite(tmpBuffer, len, 1, stderr); - if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { + if (verb < 0 || logVerbosity >= verb) + fwrite(buf, len, 1, stderr); + if (verb < 0 || logFileVerbosity >= verb) { if (logFile) { - fwrite(tmpBuffer, len, 1, logFile); + if (newline) + fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0); + newline = end_line; + fwrite(buf, len, 1, logFile); if (logFlush) { fflush(logFile); #ifndef WIN32 @@ -312,13 +295,19 @@ LogVWrite(int verb, const char *f, va_list args) FatalError("realloc() failed while saving log messages\n"); } bufferUnused -= len; - memcpy(saveBuffer + bufferPos, tmpBuffer, len); + memcpy(saveBuffer + bufferPos, buf, len); bufferPos += len; } } } void +LogVWrite(int verb, const char *f, va_list args) +{ + return LogVMessageVerb(X_NONE, verb, f, args); +} + +void LogWrite(int verb, const char *f, ...) { va_list args; @@ -371,22 +360,28 @@ void LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) { const char *type_str; - char tmpFormat[1024]; - const char *new_format; + char buf[1024]; + const size_t size = sizeof(buf); + Bool newline; + size_t len = 0; type_str = LogMessageTypeVerbString(type, verb); if (!type_str) return; - /* if type_str is not "", prepend it and ' ', to format */ - if (type_str[0] == '\0') - new_format = format; - else { - new_format = tmpFormat; - snprintf(tmpFormat, sizeof(tmpFormat), "%s %s", type_str, format); - } + /* if type_str is not "", prepend it and ' ', to message */ + if (type_str[0] != '\0') + len += Xscnprintf(&buf[len], size - len, "%s ", type_str); + + if (size - len > 1) + len += Xvscnprintf(&buf[len], size - len, format, args); + + /* Force '\n' at end of truncated line */ + if (size - len == 1) + buf[len - 1] = '\n'; - LogVWrite(verb, new_format, args); + newline = (buf[len - 1] == '\n'); + LogSWrite(verb, buf, len, newline); } /* Log message with verbosity level specified. */ @@ -416,31 +411,31 @@ 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; + char buf[1024]; + const size_t size = sizeof(buf); + Bool newline; + size_t len = 0; 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 is not "", prepend it and ' ', to message */ if (type_str[0] != '\0') - p += snprintf(tmpFormat, sizeof(tmpFormat), "%s ", type_str); + len += Xscnprintf(&buf[len], size - len, "%s ", type_str); + + if (hdr_format && size - len > 1) + len += Xvscnprintf(&buf[len], size - len, hdr_format, hdr_args); - /* 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); + if (msg_format && size - len > 1) + len += Xvscnprintf(&buf[len], size - len, msg_format, msg_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); + /* Force '\n' at end of truncated line */ + if (size - len == 1) + buf[len - 1] = '\n'; - LogVWrite(verb, tmpFormat, msg_args); + newline = (buf[len - 1] == '\n'); + LogSWrite(verb, buf, len, newline); } void diff --git a/os/xprintf.c b/os/xprintf.c index 17fea2ec7..80caa5790 100644 --- a/os/xprintf.c +++ b/os/xprintf.c @@ -186,6 +186,50 @@ XNFasprintf(char **ret, const char *_X_RESTRICT_KYWD format, ...) return size; } +/** + * Varargs snprintf that returns the actual number of bytes (excluding final + * '\0') that were copied into the buffer. + * This is opposed to the normal sprintf() usually returns the number of bytes + * that would have been written. + * + * @param s buffer to copy into + * @param n size of buffer s + * @param format printf style format string + * @param va variable argument list + * @return number of bytes actually copied, excluding final '\0' + */ +int +Xvscnprintf(char *s, int n, const char *format, va_list args) +{ + int x; + if (n == 0) + return 0; + x = vsnprintf(s, n , format, args); + return (x >= n) ? (n - 1) : x; +} + +/** + * snprintf that returns the actual number of bytes (excluding final '\0') that + * were copied into the buffer. + * This is opposed to the normal sprintf() usually returns the number of bytes + * that would have been written. + * + * @param s buffer to copy into + * @param n size of buffer s + * @param format printf style format string + * @param ... arguments for specified format + * @return number of bytes actually copied, excluding final '\0' + */ +int Xscnprintf(char *s, int n, const char *format, ...) +{ + int x; + va_list ap; + va_start(ap, format); + x = Xvscnprintf(s, n, format, ap); + va_end(ap); + return x; +} + /* Old api, now deprecated, may be removed in the future */ char * Xvprintf(const char *format, va_list va) |