xserver: Branch 'master' - 21 commits

Keith Packard keithp at kemper.freedesktop.org
Fri Feb 8 08:59:26 PST 2013


 Xext/xtest.c                           |   17 +-
 Xi/exevents.c                          |    2 
 dix/devices.c                          |    6 
 dix/events.c                           |    6 
 dix/getevents.c                        |   48 ++++++-
 dix/ptrveloc.c                         |   38 +++---
 hw/dmx/config/xdmxconfig.c             |    3 
 hw/xfree86/os-support/linux/lnx_acpi.c |    9 -
 include/input.h                        |    1 
 include/list.h                         |    2 
 include/misc.h                         |    1 
 os/log.c                               |   19 ++-
 os/utils.c                             |   32 +++++
 test/signal-logging.c                  |  200 ++++++++++++++++-----------------
 xkb/xkbActions.c                       |  147 ++++++++++++++----------
 15 files changed, 328 insertions(+), 203 deletions(-)

New commits:
commit b173eb2ae3349c557db1ff9e424fa540b8289bb2
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Feb 8 08:57:43 2013 -0800

    os: Round fraction in pnprintf %f format
    
    Truncating the fraction part leads to a test failure where -1203.30 is
    printed as -1203.29. Round this to the nearest value instead by adding
    0.5 before converting to an integer
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/os/utils.c b/os/utils.c
index 3ba6499..60e828e 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1999,7 +1999,7 @@ FormatDouble(double dbl, char *string)
     int slen = 0;
     uint64_t frac;
 
-    frac = (dbl > 0 ? dbl : -dbl) * 100.0;
+    frac = (dbl > 0 ? dbl : -dbl) * 100.0 + 0.5;
     frac %= 100;
 
     /* write decimal part to string */
commit 509b3c3dc82e7abce1900d5e1cddd90f23be5a87
Author: Carlos Garnacho <carlosg at gnome.org>
Date:   Wed Feb 6 14:07:22 2013 +0100

    dix: Set focus field on XI2 crossing events
    
    Set on DeviceEnterLeaveEvent() the xXIEnterEvent->focus field
    similarly to how the CoreEnterLeaveEvent() function above does
    for core events.
    
    This fixes bug https://bugzilla.gnome.org/show_bug.cgi?id=677329
    reported to GTK+, where focus handling on window managers with
    sloppy focus or no window manager present was broken due to this
    field being always set to FALSE.
    
    Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index f72cdc7..2682ecd 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4569,6 +4569,7 @@ DeviceEnterLeaveEvent(DeviceIntPtr mouse,
 {
     GrabPtr grab = mouse->deviceGrab.grab;
     xXIEnterEvent *event;
+    WindowPtr focus;
     int filter;
     int btlen, len, i;
     DeviceIntPtr kbd;
@@ -4610,6 +4611,11 @@ DeviceEnterLeaveEvent(DeviceIntPtr mouse,
         event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
     }
 
+    focus = (kbd) ? kbd->focus->win : None;
+    if ((focus != NoneWin) &&
+        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
+        event->focus = TRUE;
+
     FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
                          None, FALSE);
 
commit 3e4be4033aed78b2bb3a18d51f0963989efd1af3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jan 25 11:47:32 2013 +1000

    dix: when shutting down slave devices, shut down xtest devices last
    
    XTest devices are the first ones in the list, being initialised together
    with the master devices. If we disable the devices in-order and a device has
    a button down when being disabled, the XTest device is checked for a
    required button release (xkbAccessX.c's ProcessPointerEvent). This fails if
    the device is already NULL.
    
    Instead of putting the check there, disable the devices in the reverse order
    they are initialised. Disable physical slaves first, then xtest devices,
    then the master devices.
    
    Testcase: shut down server with a button still held down on a physical
    device
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/devices.c b/dix/devices.c
index 3c7d480..172fc04 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -516,6 +516,12 @@ DisableAllDevices(void)
 {
     DeviceIntPtr dev, tmp;
 
+    /* Disable slave devices first, excluding XTest devices */
+    nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
+        if (!IsXTestDevice(dev, NULL) && !IsMaster(dev))
+            DisableDevice(dev, FALSE);
+    }
+    /* Disable XTest devices */
     nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
         if (!IsMaster(dev))
             DisableDevice(dev, FALSE);
commit 0d5bb882600ee7734af034fbea935a79d21d1e70
Merge: b33fcb1 61a99af
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Feb 8 14:10:52 2013 +1000

    Merge branch 'ptraccel-fixes' into for-keith

commit 61a99aff9d33728a0b67920254d2d4d79f80cf39
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jan 11 14:22:07 2013 +1000

    dix: pre-scale relative events from abs devices to desktop ratio (#31636)
    
    Absolute devices may send relative events depending on the mode (synaptics
    by default, wacom per option). The relative events are added to the previous
    position, converted into device coordinates and then scaled into desktop
    coordinates for pointer movement.
    
    Because the device range must be mapped into the desktop coordinate range,
    this results in uneven scaling depending dimensions, e.g. on a setup with
    width == 2 * height, a relative movement of 10/10 in device coordinates
    results in a cursor movement of 20/10 (+ acceleration)
    
    Other commonly user-visible results:
    * the touchpad changing acceleration once an external monitor as added.
    * drawing a circle on a wacom tablet in relative mode gives an ellipsis in
      the same ratio as the desktop dimensions.
    
    Solution: pre-scale the incoming relative x/y coordinates by width/height
    ratio of the total desktop size. Then add them to the previous
    coordinates and scale back with the previous mapping, which will undo the
    pre-scaling and give us the right movement.
    
    X.Org Bug 31636 <http://bugs.freedesktop.org/show_bug.cgi?id=31636>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/getevents.c b/dix/getevents.c
index a1e1938..5100607 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -776,11 +776,33 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl
  * @param[in,out] mask Valuator data for this event, modified in-place.
  */
 static void
-moveRelative(DeviceIntPtr dev, ValuatorMask *mask)
+moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
 {
     int i;
     Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
 
+    /* for abs devices in relative mode, we've just scaled wrong, since we
+       mapped the device's shape into the screen shape. Undo this. */
+    if ((flags & POINTER_ABSOLUTE) == 0 && dev->valuator &&
+        dev->valuator->axes[0].min_value < dev->valuator->axes[0].max_value) {
+
+        double ratio = 1.0 * screenInfo.width/screenInfo.height;
+
+        if (ratio > 1.0) {
+            double y;
+            if (valuator_mask_fetch_double(mask, 1, &y)) {
+                y *= ratio;
+                valuator_mask_set_double(mask, 1, y);
+            }
+        } else {
+            double x;
+            if (valuator_mask_fetch_double(mask, 0, &x)) {
+                x *= ratio;
+                valuator_mask_set_double(mask, 0, x);
+            }
+        }
+    }
+
     /* calc other axes, clip, drop back into valuators */
     for (i = 0; i < valuator_mask_size(mask); i++) {
         double val = dev->last.valuators[i];
@@ -1380,7 +1402,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
         if ((flags & POINTER_NORAW) == 0)
             set_raw_valuators(raw, &mask, raw->valuators.data);
 
-        moveRelative(pDev, &mask);
+        moveRelative(pDev, flags, &mask);
     }
 
     /* valuators are in device coordinate system in absolute coordinates */
commit a6ba2b79ae8ad0fdee3f208d5e030b012df48785
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jan 11 08:53:24 2013 +1000

    dix: unify prefix for ptraccel debugging in DebugAccelF macro
    
    If we're already using our own custom macro, might as well use it properly.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index b6d2dae..d6fef9c 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -77,7 +77,7 @@ DeletePredictableAccelerationProperties(DeviceIntPtr,
 /*#define PTRACCEL_DEBUGGING*/
 
 #ifdef PTRACCEL_DEBUGGING
-#define DebugAccelF ErrorFSigSafe
+#define DebugAccelF(...) ErrorFSigSafe("dix/ptraccel: " __VA_ARGS__)
 #else
 #define DebugAccelF(...)        /* */
 #endif
@@ -421,7 +421,7 @@ void
 InitTrackers(DeviceVelocityPtr vel, int ntracker)
 {
     if (ntracker < 1) {
-        ErrorF("(dix ptracc) invalid number of trackers\n");
+        ErrorF("invalid number of trackers\n");
         return;
     }
     free(vel->tracker);
@@ -566,7 +566,7 @@ FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t)
     vel->tracker[n].dy = 0.0;
     vel->tracker[n].time = cur_t;
     vel->tracker[n].dir = GetDirection(dx, dy);
-    DebugAccelF("(dix prtacc) motion [dx: %f dy: %f dir:%d diff: %d]\n",
+    DebugAccelF("motion [dx: %f dy: %f dir:%d diff: %d]\n",
                 dx, dy, vel->tracker[n].dir,
                 cur_t - vel->tracker[vel->cur_tracker].time);
     vel->cur_tracker = n;
@@ -614,7 +614,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
 
         /* bail out if data is too old and protect from overrun */
         if (age_ms >= vel->reset_time || age_ms < 0) {
-            DebugAccelF("(dix prtacc) query: tracker too old (reset after %d, age is %d)\n",
+            DebugAccelF("query: tracker too old (reset after %d, age is %d)\n",
                         vel->reset_time, age_ms);
             break;
         }
@@ -627,7 +627,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
          */
         dir &= tracker->dir;
         if (dir == 0) {         /* we've changed octant of movement (e.g. NE → NW) */
-            DebugAccelF("(dix prtacc) query: no longer linear\n");
+            DebugAccelF("query: no longer linear\n");
             /* instead of breaking it we might also inspect the partition after,
              * but actual improvement with this is probably rare. */
             break;
@@ -648,7 +648,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
                 velocity_diff / (initial_velocity + tracker_velocity) >=
                 vel->max_rel_diff) {
                 /* we're not in range, quit - it won't get better. */
-                DebugAccelF("(dix prtacc) query: tracker too different:"
+                DebugAccelF("query: tracker too different:"
                             " old %2.2f initial %2.2f diff: %2.2f\n",
                             tracker_velocity, initial_velocity, velocity_diff);
                 break;
@@ -661,14 +661,14 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
         }
     }
     if (offset == vel->num_tracker) {
-        DebugAccelF("(dix prtacc) query: last tracker in effect\n");
+        DebugAccelF("query: last tracker in effect\n");
         used_offset = vel->num_tracker - 1;
     }
     if (used_offset >= 0) {
 #ifdef PTRACCEL_DEBUGGING
         MotionTracker *tracker = TRACKER(vel, used_offset);
 
-        DebugAccelF("(dix prtacc) result: offset %i [dx: %f dy: %f diff: %i]\n",
+        DebugAccelF("result: offset %i [dx: %f dy: %f diff: %i]\n",
                     used_offset, tracker->dx, tracker->dy,
                     cur_t - tracker->time);
 #endif
@@ -694,6 +694,8 @@ ProcessVelocityData2D(DeviceVelocityPtr vel, double dx, double dy, int time)
 
     velocity = QueryTrackers(vel, time);
 
+    DebugAccelF("velocity is %f\n", velocity);
+
     vel->velocity = velocity;
     return velocity == 0;
 }
@@ -769,7 +771,7 @@ ComputeAcceleration(DeviceIntPtr dev,
     double result;
 
     if (vel->velocity <= 0) {
-        DebugAccelF("(dix ptracc) profile skipped\n");
+        DebugAccelF("profile skipped\n");
         /*
          * If we have no idea about device velocity, don't pretend it.
          */
@@ -793,13 +795,13 @@ ComputeAcceleration(DeviceIntPtr dev,
                                             threshold,
                                             acc);
         result /= 6.0f;
-        DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n",
+        DebugAccelF("profile average [%.2f ... %.2f] is %.3f\n",
                     vel->velocity, vel->last_velocity, result);
     }
     else {
         result = BasicComputeAcceleration(dev, vel,
                                           vel->velocity, threshold, acc);
-        DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n",
+        DebugAccelF("profile sample [%.2f] is %.3f\n",
                     vel->velocity, result);
     }
 
@@ -1111,6 +1113,7 @@ acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask *val, CARD32 evtime)
                                        (double) dev->ptrfeed->ctrl.num /
                                        (double) dev->ptrfeed->ctrl.den);
 
+            DebugAccelF("mult is %f\n", mult);
             if (mult != 1.0f || velocitydata->const_acceleration != 1.0f) {
                 if (mult > 1.0f && soften)
                     ApplySoftening(velocitydata, &dx, &dy);
commit 0d7d79406011169ad95e23c6e937f6d15a5ec3cc
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jan 11 08:52:08 2013 +1000

    dix: use BUG_RETURN_VAL for an error message
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index 6994bd5..b6d2dae 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -1051,11 +1051,8 @@ SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel,
 DeviceVelocityPtr
 GetDevicePredictableAccelData(DeviceIntPtr dev)
 {
-    /*sanity check */
-    if (!dev) {
-        ErrorF("[dix] accel: DeviceIntPtr was NULL");
-        return NULL;
-    }
+    BUG_RETURN_VAL(!dev, NULL);
+
     if (dev->valuator &&
         dev->valuator->accelScheme.AccelSchemeProc ==
         acceleratePointerPredictable &&
commit a0c38ea6cbad61edcfefff0e5dd6330edb706f13
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jan 11 08:49:15 2013 +1000

    dix: add some more info to a ptraccel debug msg
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index b95f194..6994bd5 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -614,7 +614,8 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
 
         /* bail out if data is too old and protect from overrun */
         if (age_ms >= vel->reset_time || age_ms < 0) {
-            DebugAccelF("(dix prtacc) query: tracker too old\n");
+            DebugAccelF("(dix prtacc) query: tracker too old (reset after %d, age is %d)\n",
+                        vel->reset_time, age_ms);
             break;
         }
 
commit 95125a7c0cbbbae40216a0497acdd863ddc645ed
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jan 10 13:19:27 2013 +1000

    dix: fix ptraccel debugging printfs
    
    This is mostly sigsafe code, so use sigsave printf. And update some fields
    to double that used to be int.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index c7994b0..b95f194 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -77,7 +77,7 @@ DeletePredictableAccelerationProperties(DeviceIntPtr,
 /*#define PTRACCEL_DEBUGGING*/
 
 #ifdef PTRACCEL_DEBUGGING
-#define DebugAccelF ErrorF
+#define DebugAccelF ErrorFSigSafe
 #else
 #define DebugAccelF(...)        /* */
 #endif
@@ -566,7 +566,7 @@ FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t)
     vel->tracker[n].dy = 0.0;
     vel->tracker[n].time = cur_t;
     vel->tracker[n].dir = GetDirection(dx, dy);
-    DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n",
+    DebugAccelF("(dix prtacc) motion [dx: %f dy: %f dir:%d diff: %d]\n",
                 dx, dy, vel->tracker[n].dir,
                 cur_t - vel->tracker[vel->cur_tracker].time);
     vel->cur_tracker = n;
@@ -667,7 +667,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t)
 #ifdef PTRACCEL_DEBUGGING
         MotionTracker *tracker = TRACKER(vel, used_offset);
 
-        DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n",
+        DebugAccelF("(dix prtacc) result: offset %i [dx: %f dy: %f diff: %i]\n",
                     used_offset, tracker->dx, tracker->dy,
                     cur_t - tracker->time);
 #endif
@@ -799,7 +799,7 @@ ComputeAcceleration(DeviceIntPtr dev,
         result = BasicComputeAcceleration(dev, vel,
                                           vel->velocity, threshold, acc);
         DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n",
-                    vel->velocity, res);
+                    vel->velocity, result);
     }
 
     return result;
@@ -1122,8 +1122,7 @@ acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask *val, CARD32 evtime)
                     valuator_mask_set_double(val, 0, mult * dx);
                 if (dy != 0.0)
                     valuator_mask_set_double(val, 1, mult * dy);
-                DebugAccelF("pos (%i | %i) delta x:%.3f y:%.3f\n", mult * dx,
-                            mult * dy);
+                DebugAccelF("delta x:%.3f y:%.3f\n", mult * dx, mult * dy);
             }
         }
     }
commit b33fcb149710a28fd8767b2307a97bf367de695e
Author: Andreas Wettstein <wettstein509 at solnet.ch>
Date:   Tue Jan 29 21:49:20 2013 +0100

    xkb: Fix repeat behaviour of redirect and message actions
    
    The redirect and the message action filter functions implicitly assumed that
    when they receive an event for the same keycode they were activated for, that
    this is the a release of the key that activated the filter.  This is not true
    if the key autorepeats.  Due to the incorrect assumption, the effective key
    repeat rate was effectively halved.
    
    Signed-off-by: Andreas Wettstein <wettstein509 at solnet.ch>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 1adb389..416de92 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -747,6 +747,15 @@ _XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
     XkbMessageAction *pMsg;
     DeviceIntPtr kbd;
 
+    if ((filter->keycode != 0) && (filter->keycode != keycode))
+	return 1;
+
+    /* This can happen if the key repeats, and the state (modifiers or group)
+       changes meanwhile. */
+    if ((filter->keycode == keycode) && pAction &&
+	(pAction->type != XkbSA_ActionMessage))
+	return 1;
+
     kbd = xkbi->device;
     if (filter->keycode == 0) { /* initial press */
         pMsg = &pAction->msg;
@@ -774,20 +783,27 @@ _XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
     }
     else if (filter->keycode == keycode) {
         pMsg = &filter->upAction.msg;
-        if (pMsg->flags & XkbSA_MessageOnRelease) {
-            xkbActionMessage msg;
-
-            msg.keycode = keycode;
-            msg.press = 0;
-            msg.keyEventFollows =
-                ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
-            memcpy((char *) msg.message, (char *) pMsg->message,
-                   XkbActionMessageLength);
-            XkbSendActionMessage(kbd, &msg);
+	if (pAction == NULL) {
+	    if (pMsg->flags & XkbSA_MessageOnRelease) {
+		xkbActionMessage msg;
+
+		msg.keycode = keycode;
+		msg.press = 0;
+		msg.keyEventFollows =
+		    ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
+		memcpy((char *) msg.message, (char *) pMsg->message,
+		       XkbActionMessageLength);
+		XkbSendActionMessage(kbd, &msg);
+	    }
+	    filter->keycode = 0;
+	    filter->active = 0;
+	    return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
+	} else if (memcmp(pMsg, pAction, 8) == 0) {
+	    /* Repeat: If we send the same message, avoid multiple messages
+	       on release from piling up. */
+	    filter->keycode = 0;
+	    filter->active = 0;
         }
-        filter->keycode = 0;
-        filter->active = 0;
-        return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
     }
     return 1;
 }
@@ -803,15 +819,21 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
     xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
     ProcessInputProc backupproc;
 
+    if ((filter->keycode != 0) && (filter->keycode != keycode))
+        return 1;
+
+    /* This can happen if the key repeats, and the state (modifiers or group)
+       changes meanwhile. */
+    if ((filter->keycode == keycode) && pAction &&
+	(pAction->type != XkbSA_RedirectKey))
+	return 1;
+
     /* never actually used uninitialised, but gcc isn't smart enough
      * to work that out. */
     memset(&old, 0, sizeof(old));
     memset(&old_prev, 0, sizeof(old_prev));
     memset(&ev, 0, sizeof(ev));
 
-    if ((filter->keycode != 0) && (filter->keycode != keycode))
-        return 1;
-
     GetSpritePosition(xkbi->device, &x, &y);
     ev.header = ET_Internal;
     ev.length = sizeof(DeviceEvent);
@@ -870,49 +892,60 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
             xkbi->state = old;
             xkbi->prev_state = old_prev;
         }
+	return 0;
     }
-    else if (filter->keycode == keycode) {
-
-        ev.type = ET_KeyRelease;
-        ev.detail.key = filter->upAction.redirect.new_key;
-
-        mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
-        mods = XkbSARedirectVMods(&filter->upAction.redirect);
-        if (mask)
-            XkbVirtualModsToReal(xkbi->desc, mask, &mask);
-        if (mods)
-            XkbVirtualModsToReal(xkbi->desc, mods, &mods);
-        mask |= filter->upAction.redirect.mods_mask;
-        mods |= filter->upAction.redirect.mods;
-
-        if (mask || mods) {
-            old = xkbi->state;
-            old_prev = xkbi->prev_state;
-            xkbi->state.base_mods &= ~mask;
-            xkbi->state.base_mods |= (mods & mask);
-            xkbi->state.latched_mods &= ~mask;
-            xkbi->state.latched_mods |= (mods & mask);
-            xkbi->state.locked_mods &= ~mask;
-            xkbi->state.locked_mods |= (mods & mask);
-            XkbComputeDerivedState(xkbi);
-            xkbi->prev_state = xkbi->state;
-        }
-
-        UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
-        xkbi->device->public.processInputProc((InternalEvent *) &ev,
-                                              xkbi->device);
-        COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
-                                     xkbUnwrapProc);
-
-        if (mask || mods) {
-            xkbi->state = old;
-            xkbi->prev_state = old_prev;
-        }
-
-        filter->keycode = 0;
-        filter->active = 0;
+    else {
+	/* If it is a key release, or we redirect to another key, release the
+	   previous new_key.  Otherwise, repeat. */
+	ev.detail.key = filter->upAction.redirect.new_key;
+	if (pAction == NULL ||  ev.detail.key != pAction->redirect.new_key) {
+	    ev.type = ET_KeyRelease;
+	    filter->active = 0;
+	}
+	else {
+	    ev.type = ET_KeyPress;
+	    ev.key_repeat = TRUE;
+	}
+
+	mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
+	mods = XkbSARedirectVMods(&filter->upAction.redirect);
+	if (mask)
+	    XkbVirtualModsToReal(xkbi->desc, mask, &mask);
+	if (mods)
+	    XkbVirtualModsToReal(xkbi->desc, mods, &mods);
+	mask |= filter->upAction.redirect.mods_mask;
+	mods |= filter->upAction.redirect.mods;
+
+	if (mask || mods) {
+	    old = xkbi->state;
+	    old_prev = xkbi->prev_state;
+	    xkbi->state.base_mods &= ~mask;
+	    xkbi->state.base_mods |= (mods & mask);
+	    xkbi->state.latched_mods &= ~mask;
+	    xkbi->state.latched_mods |= (mods & mask);
+	    xkbi->state.locked_mods &= ~mask;
+	    xkbi->state.locked_mods |= (mods & mask);
+	    XkbComputeDerivedState(xkbi);
+	    xkbi->prev_state = xkbi->state;
+	}
+
+	UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
+	xkbi->device->public.processInputProc((InternalEvent *) &ev,
+					      xkbi->device);
+	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
+				     xkbUnwrapProc);
+
+	if (mask || mods) {
+	    xkbi->state = old;
+	    xkbi->prev_state = old_prev;
+	}
+
+	/* We return 1 in case we have sent a release event because the new_key
+	   has changed.  Then, subsequently, we will call this function again
+	   with the same pAction, which will create the press for the new
+	   new_key. */
+	return (pAction && ev.detail.key != pAction->redirect.new_key);
     }
-    return 0;
 }
 
 static int
commit 8571c648a79444bcee9a0fe6e395129116372f49
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Sat Jan 26 15:53:08 2013 +1000

    Xext: if a root window is given in XTestFakeInput, move to that
    
    For absolute events, if the client specifies a screen number offset the
    coordinates by that. And add a new flag so we know when _not_ to add the
    screen offset in GPE.
    
    Without this offset and the flag, GPE would simply add the offset of the
    current screen if POINTER_SCREEN is set.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 209bbdd..0a854f3 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -305,7 +305,7 @@ ProcXTestFakeInput(ClientPtr client)
             numValuators = 2;
             firstValuator = 0;
             if (ev->u.u.detail == xFalse)
-                flags = POINTER_ABSOLUTE | POINTER_SCREEN;
+                flags = POINTER_ABSOLUTE | POINTER_DESKTOP;
             break;
         default:
             client->errorValue = ev->u.u.type;
@@ -376,6 +376,14 @@ ProcXTestFakeInput(ClientPtr client)
                 client->errorValue = ev->u.keyButtonPointer.root;
                 return BadValue;
             }
+
+            /* Add the root window's offset to the valuators */
+            if ((flags & POINTER_ABSOLUTE) && firstValuator <= 1 && numValuators > 0) {
+                if (firstValuator == 0)
+                    valuators[0] += root->drawable.pScreen->x;
+                if (firstValuator < 2 && firstValuator + numValuators > 1)
+                    valuators[1 - firstValuator] += root->drawable.pScreen->y;
+            }
         }
         if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) {
             client->errorValue = ev->u.u.detail;
diff --git a/dix/getevents.c b/dix/getevents.c
index 8fe54d7..02f5366 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -820,24 +820,30 @@ accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
  * device's coordinate range.
  *
  * @param dev The device to scale for.
- * @param[in, out] mask The mask in desktop coordinates, modified in place
+ * @param[in, out] mask The mask in desktop/screen coordinates, modified in place
  * to contain device coordinate range.
+ * @param flags If POINTER_SCREEN is set, mask is in per-screen coordinates.
+ *              Otherwise, mask is in desktop coords.
  */
 static void
-scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
+scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask, int flags)
 {
     double scaled;
     ScreenPtr scr = miPointerGetScreen(dev);
 
     if (valuator_mask_isset(mask, 0)) {
-        scaled = valuator_mask_get_double(mask, 0) + scr->x;
+        scaled = valuator_mask_get_double(mask, 0);
+        if (flags & POINTER_SCREEN)
+            scaled += scr->x;
         scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 0,
                                      screenInfo.x, screenInfo.width);
         valuator_mask_set_double(mask, 0, scaled);
     }
     if (valuator_mask_isset(mask, 1)) {
-        scaled = valuator_mask_get_double(mask, 1) + scr->y;
+        scaled = valuator_mask_get_double(mask, 1);
+        if (flags & POINTER_SCREEN)
+            scaled += scr->y;
         scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 1,
                                      screenInfo.y, screenInfo.height);
@@ -1363,10 +1369,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
     /* valuators are in driver-native format (rel or abs) */
 
     if (flags & POINTER_ABSOLUTE) {
-        if (flags & POINTER_SCREEN) {    /* valuators are in screen coords */
+        if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) {    /* valuators are in screen/desktop coords */
             sx = valuator_mask_get(&mask, 0);
             sy = valuator_mask_get(&mask, 1);
-            scale_from_screen(pDev, &mask);
+            scale_from_screen(pDev, &mask, flags);
         }
 
         transformAbsolute(pDev, &mask);
diff --git a/include/input.h b/include/input.h
index f53ed99..7b5ab94 100644
--- a/include/input.h
+++ b/include/input.h
@@ -69,6 +69,7 @@ SOFTWARE.
 #define POINTER_SCREEN		(1 << 4)        /* Data in screen coordinates */
 #define POINTER_NORAW		(1 << 5)        /* Don't generate RawEvents */
 #define POINTER_EMULATED	(1 << 6)        /* Event was emulated from another event */
+#define POINTER_DESKTOP		(1 << 7)        /* Data in desktop coordinates */
 
 /* GetTouchEvent flags */
 #define TOUCH_ACCEPT            (1 << 0)
commit 9fd6cb89539fde44a41ae5183c89ef9c8831c8dd
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Jan 29 15:13:44 2013 +1000

    Xext: pass the current screen to miProcessDeviceEvent() from xtest calls
    
    Not passing in a screen means we skip the screen crossing updates, so a
    xtest event that changes between ScreenRecs won't do so until the next
    physical event comes in or never, whichever comes earlier.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 6519b9c..209bbdd 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -418,7 +418,7 @@ ProcXTestFakeInput(ClientPtr client)
     }
 
     for (i = 0; i < nevents; i++)
-        mieqProcessDeviceEvent(dev, &xtest_evlist[i], NULL);
+        mieqProcessDeviceEvent(dev, &xtest_evlist[i], miPointerGetScreen(inputInfo.pointer));
 
     if (need_ptr_update)
         miPointerUpdateSprite(dev);
commit a191dbfe850ed9c6440346f59cb0078e0e844edc
Author: Sybren van Elderen <sowmestno at msn.com>
Date:   Tue Jan 29 15:43:57 2013 +1000

    dix: when scaling from desktop coord, take the total desktop size (#51904)
    
    Scaled is already in desktop coordinates, take the total width into account,
    not just the current screen's width.
    
    Fixes Xdmx pointer position calculation.
    
    X.Org Bug 51904 <http://bugs.freedesktop.org/show_bug.cgi?id=51904>
    
    Signed-off-by: Sybren van Elderen <sowmestno at msn.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/getevents.c b/dix/getevents.c
index a1e1938..8fe54d7 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -833,14 +833,14 @@ scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask)
         scaled = valuator_mask_get_double(mask, 0) + scr->x;
         scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 0,
-                                     0, scr->width);
+                                     screenInfo.x, screenInfo.width);
         valuator_mask_set_double(mask, 0, scaled);
     }
     if (valuator_mask_isset(mask, 1)) {
         scaled = valuator_mask_get_double(mask, 1) + scr->y;
         scaled = rescaleValuatorAxis(scaled,
                                      NULL, dev->valuator->axes + 1,
-                                     0, scr->height);
+                                     screenInfo.y, screenInfo.height);
         valuator_mask_set_double(mask, 1, scaled);
     }
 }
commit 1cb19803f0f8dfd1e0fb9d189afe2262e24a0be5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Jan 29 12:51:15 2013 +1000

    include: fix typo in list description
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/list.h b/include/list.h
index 2d48a86..067c679 100644
--- a/include/list.h
+++ b/include/list.h
@@ -358,7 +358,7 @@ xorg_list_is_empty(struct xorg_list *head)
  * struct foo *element = list;
  * while ((element = nt_list_next(element, next)) { }
  *
- * This macro is not safe for node deletion. Use xorg_list_for_each_entry_safe
+ * This macro is not safe for node deletion. Use nt_list_for_each_entry_safe
  * instead.
  *
  * @param list The list or current element.
commit 3d35dfcf5bad1b0a028fbecd65cb6cf6ebf12503
Author: Ted Felix <ted at tedfelix.com>
Date:   Tue Jan 29 16:36:48 2013 +1000

    xfree86: bail on misformed acpi strings (#73227)
    
    If acpid sends a string in a format that we can't parse, bail out instead of
    potentially dereferencing a NULL-pointer.
    
    X.Org Bug 73227 <http://bugs.freedesktop.org/show_bug.cgi?id=73227>
    
    Signed-off-by: Ted Felix <ted at tedfelix.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/lnx_acpi.c b/hw/xfree86/os-support/linux/lnx_acpi.c
index d98efa2..dcaa19e 100644
--- a/hw/xfree86/os-support/linux/lnx_acpi.c
+++ b/hw/xfree86/os-support/linux/lnx_acpi.c
@@ -82,18 +82,21 @@ lnxACPIGetEventFromOs(int fd, pmEvent * events, int num)
 
         video = strtok(ev, " ");
 
-        GFX = strtok(NULL, " ");
+        if (!(GFX = strtok(NULL, " ")))
+            return 0;
 #if 0
         ErrorF("GFX: %s\n", GFX);
 #endif
 
-        notify = strtok(NULL, " ");
+        if (!(notify = strtok(NULL, " ")))
+            return 0;
         notify_l = strtoul(notify, NULL, 16);
 #if 0
         ErrorF("notify: 0x%lx\n", notify_l);
 #endif
 
-        data = strtok(NULL, " ");
+        if (!(data = strtok(NULL, " ")))
+            return 0;
         data_l = strtoul(data, NULL, 16);
 #if 0
         ErrorF("data: 0x%lx\n", data_l);
commit fdc451588816c4bc798d54e56316530e9066be80
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Jan 29 11:01:29 2013 +1000

    Xi: limit valuator copy to valuator array size (#59939)
    
    mask[(MAX_VALUATORS + 7)/8] is larger than data[MAX_VALUATORS], so static
    code checkers think we may be running OOB on the data array. Mask is
    initialized to 0, so this should not happen, but change it anyway to shut up
    code analyzer noise.
    
    X.Org Bug 59939 <http://bugs.freedesktop.org/show_bug.cgi?id=59939>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 74f3610..609b126 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1263,7 +1263,7 @@ TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
 {
     int i;
 
-    for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
+    for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
         if (BitIsOn(ev->valuators.mask, i))
             valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
 }
commit 48bc30c5413a1be0039fa77affcbbb4fe677479f
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Tue Jan 29 10:24:32 2013 +1000

    Xext: avoid null-pointer dereference in XTestFakeInput (#59937)
    
    dv is still NULL at this point, so return firstValuator instead (which is
    the same value dv->firstValuator would be once initialized)
    
    X.Org Bug 59937 <http://bugs.freedesktop.org/show_bug.cgi?id=59937>
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 2abdc7f..6519b9c 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -156,7 +156,6 @@ ProcXTestFakeInput(ClientPtr client)
     DeviceIntPtr dev = NULL;
     WindowPtr root;
     Bool extension = FALSE;
-    deviceValuator *dv = NULL;
     ValuatorMask mask;
     int valuators[MAX_VALUATORS] = { 0 };
     int numValuators = 0;
@@ -241,14 +240,14 @@ ProcXTestFakeInput(ClientPtr client)
         }
 
         if (nev > 1 && !dev->valuator) {
-            client->errorValue = dv->first_valuator;
+            client->errorValue = firstValuator;
             return BadValue;
         }
 
         /* check validity of valuator events */
         base = firstValuator;
         for (n = 1; n < nev; n++) {
-            dv = (deviceValuator *) (ev + n);
+            deviceValuator *dv = (deviceValuator *) (ev + n);
             if (dv->type != DeviceValuator) {
                 client->errorValue = dv->type;
                 return BadValue;
commit 1058fcf57fdcb94d92e7b5f4483b347853d5f8e6
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Sat Jan 26 14:13:33 2013 +1000

    dmx: don't include dmx-config.h from xdmxconfig (#37502)
    
    dmx-config.h is a server header which includes dix-config.h. That again
    defines a bunch of server-specifics, including setting the size of XID to
    32 bit.
    
    libX11 uses unsigned long (8 bits on x86_64). XGCValues thus ends up being
    16 bytes smaller in xdmxconfig than in the library, causing garbage to be
    sent to the server.
    
    X.Org Bug 37502 <http://bugs.freedesktop.org/show_bug.cgi?id=37502>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/dmx/config/xdmxconfig.c b/hw/dmx/config/xdmxconfig.c
index f308412..2121dd7 100644
--- a/hw/dmx/config/xdmxconfig.c
+++ b/hw/dmx/config/xdmxconfig.c
@@ -31,9 +31,6 @@
  *
  */
 
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
commit cde7cbe9674e8a771f9a4e646c1772a46a8230fb
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jan 10 13:20:12 2013 +1000

    os: add support for %f to pnprintf
    
    This is the lazy man's %f support. Print the decimal part of the number,
    then append a decimal point, then print the first two digits of the
    fractional part. So %f in sigsafe printing is really %.2f.
    
    No boundary checks in place here.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/include/misc.h b/include/misc.h
index 3487176..0c67f11 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -250,6 +250,7 @@ extern char **xstrtokenize(const char *str, const char *separators);
 extern void FormatInt64(int64_t num, char *string);
 extern void FormatUInt64(uint64_t num, char *string);
 extern void FormatUInt64Hex(uint64_t num, char *string);
+extern void FormatDouble(double dbl, char *string);
 
 /**
  * Compare the two version numbers comprising of major.minor.
diff --git a/os/log.c b/os/log.c
index 2139064..7b5c9ee 100644
--- a/os/log.c
+++ b/os/log.c
@@ -351,7 +351,16 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
             for (i = 0; i < p_len && s_idx < size - 1; i++)
                 string[s_idx++] = number[i];
             break;
-
+        case 'f':
+            {
+                double d = va_arg(args, double);
+                FormatDouble(d, number);
+                p_len = strlen_sigsafe(number);
+
+                for (i = 0; i < p_len && s_idx < size - 1; i++)
+                    string[s_idx++] = number[i];
+            }
+            break;
         default:
             va_arg(args, char*);
             string[s_idx++] = '%';
diff --git a/os/utils.c b/os/utils.c
index e396ba4..3ba6499 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1990,6 +1990,38 @@ FormatUInt64(uint64_t num, char *string)
     string[len] = '\0';
 }
 
+/**
+ * Format a double number as %.2f.
+ */
+void
+FormatDouble(double dbl, char *string)
+{
+    int slen = 0;
+    uint64_t frac;
+
+    frac = (dbl > 0 ? dbl : -dbl) * 100.0;
+    frac %= 100;
+
+    /* write decimal part to string */
+    if (dbl < 0 && dbl > -1)
+        string[slen++] = '-';
+    FormatInt64((int64_t)dbl, &string[slen]);
+
+    while(string[slen] != '\0')
+        slen++;
+
+    /* append fractional part, but only if we have enough characters. We
+     * expect string to be 21 chars (incl trailing \0) */
+    if (slen <= 17) {
+        string[slen++] = '.';
+        if (frac < 10)
+            string[slen++] = '0';
+
+        FormatUInt64(frac, &string[slen]);
+    }
+}
+
+
 /* Format a number into a hexadecimal string in a signal safe manner. The string
  * should be at least 17 characters in order to handle all uint64_t values. */
 void
diff --git a/test/signal-logging.c b/test/signal-logging.c
index 127a28f..1ef17af 100644
--- a/test/signal-logging.c
+++ b/test/signal-logging.c
@@ -41,6 +41,11 @@ struct signed_number_format_test {
     char string[21];
 };
 
+struct float_number_format_test {
+    double number;
+    char string[21];
+};
+
 static Bool
 check_signed_number_format_test(long int number)
 {
@@ -59,6 +64,25 @@ check_signed_number_format_test(long int number)
 }
 
 static Bool
+check_float_format_test(double number)
+{
+    char string[21];
+    char expected[21];
+
+    /* we currently always print float as .2f */
+    sprintf(expected, "%.2f", number);
+
+    FormatDouble(number, string);
+    if(strncmp(string, expected, 21) != 0) {
+        fprintf(stderr, "Failed to convert %f to string (%s vs %s)\n",
+                number, expected, string);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static Bool
 check_number_format_test(long unsigned int number)
 {
     char string[21];
@@ -84,6 +108,11 @@ check_number_format_test(long unsigned int number)
     return TRUE;
 }
 
+/* FIXME: max range stuff */
+double float_tests[] = { 0, 5, 0.1, 0.01, 5.2342, 10.2301,
+                         -1, -2.00, -0.6023, -1203.30
+                        };
+
 static void
 number_formatting(void)
 {
@@ -116,6 +145,9 @@ number_formatting(void)
 
     for (i = 0; i < sizeof(unsigned_tests) / sizeof(signed_tests[0]); i++)
         assert(check_signed_number_format_test(signed_tests[i]));
+
+    for (i = 0; i < sizeof(float_tests) / sizeof(float_tests[0]); i++)
+        assert(check_float_format_test(float_tests[i]));
 }
 
 #pragma GCC diagnostic ignored "-Wformat-security"
@@ -232,6 +264,30 @@ static void logging_format(void)
         ptr <<= 1;
     } while(ptr);
 
+
+    for (i = 0; i < sizeof(float_tests)/sizeof(float_tests[0]); i++) {
+        double d = float_tests[i];
+        char expected[30];
+        sprintf(expected, "(EE) %.2f\n", d);
+        LogMessageVerbSigSafe(X_ERROR, -1, "%f\n", d);
+        read_log_msg(logmsg);
+        assert(strcmp(logmsg, expected) == 0);
+
+        /* test for length modifiers, we just ignore them atm */
+        LogMessageVerbSigSafe(X_ERROR, -1, "%.3f\n", d);
+        read_log_msg(logmsg);
+        assert(strcmp(logmsg, expected) == 0);
+
+        LogMessageVerbSigSafe(X_ERROR, -1, "%3f\n", d);
+        read_log_msg(logmsg);
+        assert(strcmp(logmsg, expected) == 0);
+
+        LogMessageVerbSigSafe(X_ERROR, -1, "%.0f\n", d);
+        read_log_msg(logmsg);
+        assert(strcmp(logmsg, expected) == 0);
+    }
+
+
     LogClose(EXIT_NO_ERROR);
     unlink(log_file_path);
 
commit 20def57632583aef095ca18792c7fce16d2d9004
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jan 10 13:24:05 2013 +1000

    os: silently ignore length modifiers in pnprintf
    
    Until we have support for them, ignore any length modifiers so we don't need
    to update all callers.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/os/log.c b/os/log.c
index 4820e9a..2139064 100644
--- a/os/log.c
+++ b/os/log.c
@@ -298,7 +298,13 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
             continue;
         }
 
-        switch (f[++f_idx]) {
+        f_idx++;
+
+        /* silently swallow length modifiers */
+        while (f_idx < f_len && ((f[f_idx] >= '0' && f[f_idx] <= '9') || f[f_idx] == '.'))
+            f_idx++;
+
+        switch (f[f_idx]) {
         case 's':
             string_arg = va_arg(args, char*);
             p_len = strlen_sigsafe(string_arg);
commit f53b2012f39085d866f267dda1442a48ace3c5a5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jan 17 16:19:51 2013 +1000

    test/signal-logging: simplify tests using sprintf
    
    Ever looked at your own code and thought 'WTF was I thinking?'. yeah, that.
    
    Instead of passing in the expected string just use sprintf to print the
    number for us and compare. In the end we're just trying to emulate printf
    behaviour anyway.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/test/signal-logging.c b/test/signal-logging.c
index 810bd20..127a28f 100644
--- a/test/signal-logging.c
+++ b/test/signal-logging.c
@@ -42,14 +42,16 @@ struct signed_number_format_test {
 };
 
 static Bool
-check_signed_number_format_test(const struct signed_number_format_test *test)
+check_signed_number_format_test(long int number)
 {
     char string[21];
+    char expected[21];
 
-    FormatInt64(test->number, string);
-    if(strncmp(string, test->string, 21) != 0) {
-        fprintf(stderr, "Failed to convert %jd to decimal string (%s vs %s)\n",
-                test->number, test->string, string);
+    sprintf(expected, "%ld", number);
+    FormatInt64(number, string);
+    if(strncmp(string, expected, 21) != 0) {
+        fprintf(stderr, "Failed to convert %jd to decimal string (expected %s but got %s)\n",
+                number, expected, string);
         return FALSE;
     }
 
@@ -57,21 +59,25 @@ check_signed_number_format_test(const struct signed_number_format_test *test)
 }
 
 static Bool
-check_number_format_test(const struct number_format_test *test)
+check_number_format_test(long unsigned int number)
 {
     char string[21];
+    char expected[21];
 
-    FormatUInt64(test->number, string);
-    if(strncmp(string, test->string, 21) != 0) {
+    sprintf(expected, "%lu", number);
+
+    FormatUInt64(number, string);
+    if(strncmp(string, expected, 21) != 0) {
         fprintf(stderr, "Failed to convert %ju to decimal string (%s vs %s)\n",
-                test->number, test->string, string);
+                number, expected, string);
         return FALSE;
     }
-    FormatUInt64Hex(test->number, string);
-    if(strncmp(string, test->hex_string, 17) != 0) {
-        fprintf(stderr,
-                "Failed to convert %ju to hexadecimal string (%s vs %s)\n",
-                test->number, test->hex_string, string);
+
+    sprintf(expected, "%lx", number);
+    FormatUInt64Hex(number, string);
+    if(strncmp(string, expected, 17) != 0) {
+        fprintf(stderr, "Failed to convert %ju to hexadecimal string (%s vs %s)\n",
+                number, expected, string);
         return FALSE;
     }
 
@@ -82,100 +88,34 @@ static void
 number_formatting(void)
 {
     int i;
-    struct number_format_test unsigned_tests[] = {
-        { /* Zero */
-            0,
-            "0",
-            "0",
-        },
-        { /* Single digit number */
-            5,
-            "5",
-            "5",
-        },
-        { /* Two digit decimal number */
-            12,
-            "12",
-            "c",
-        },
-        { /* Two digit hex number */
-            37,
-            "37",
-            "25",
-        },
-        { /* Large < 32 bit number */
-            0xC90B2,
-            "823474",
-            "c90b2",
-        },
-        { /* Large > 32 bit number */
-            0x15D027BF211B37A,
-            "98237498237498234",
-            "15d027bf211b37a",
-        },
-        { /* Maximum 64-bit number */
-            0xFFFFFFFFFFFFFFFF,
-            "18446744073709551615",
-            "ffffffffffffffff",
-        },
+    long unsigned int unsigned_tests[] = { 0,/* Zero */
+                                           5, /* Single digit number */
+                                           12, /* Two digit decimal number */
+                                           37, /* Two digit hex number */
+                                           0xC90B2, /* Large < 32 bit number */
+                                           0x15D027BF211B37A, /* Large > 32 bit number */
+                                           0xFFFFFFFFFFFFFFFF, /* Maximum 64-bit number */
     };
 
-    struct signed_number_format_test signed_tests[] = {
-        { /* Zero */
-            0,
-            "0",
-        },
-        { /* Single digit number */
-            5,
-            "5",
-        },
-        { /* Two digit decimal number */
-            12,
-            "12",
-        },
-        { /* Two digit hex number */
-            37,
-            "37",
-        },
-        { /* Large < 32 bit number */
-            0xC90B2,
-            "823474",
-        },
-        { /* Large > 32 bit number */
-            0x15D027BF211B37A,
-            "98237498237498234",
-        },
-        { /* Maximum 64-bit signed number */
-            0x7FFFFFFFFFFFFFFF,
-            "9223372036854775807",
-        },
-        { /* Single digit number */
-            -1,
-            "-1",
-        },
-        { /* Two digit decimal number */
-            -12,
-            "-12",
-        },
-        { /* Large < 32 bit number */
-            -0xC90B2,
-            "-823474",
-        },
-        { /* Large > 32 bit number */
-            -0x15D027BF211B37A,
-            "-98237498237498234",
-        },
-        { /* Maximum 64-bit number */
-            -0x7FFFFFFFFFFFFFFF,
-            "-9223372036854775807",
-        },
-    };
+    long int signed_tests[] = { 0,/* Zero */
+                                5, /* Single digit number */
+                                12, /* Two digit decimal number */
+                                37, /* Two digit hex number */
+                                0xC90B2, /* Large < 32 bit number */
+                                0x15D027BF211B37A, /* Large > 32 bit number */
+                                0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */
+                                -1, /* Single digit number */
+                                -12, /* Two digit decimal number */
+                                -0xC90B2, /* Large < 32 bit number */
+                                -0x15D027BF211B37A, /* Large > 32 bit number */
+                                -0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */
+    } ;
 
     for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++)
-        assert(check_number_format_test(unsigned_tests + i));
+        assert(check_number_format_test(unsigned_tests[i]));
 
     for (i = 0; i < sizeof(unsigned_tests) / sizeof(signed_tests[0]); i++)
-        assert(check_signed_number_format_test(signed_tests + i));
+        assert(check_signed_number_format_test(signed_tests[i]));
 }
 
 #pragma GCC diagnostic ignored "-Wformat-security"


More information about the xorg-commit mailing list