Index: app/core/core-types.h
===================================================================
--- app/core/core-types.h	(revision 24605)
+++ app/core/core-types.h	(working copy)
@@ -190,6 +190,11 @@
   gdouble xtilt;
   gdouble ytilt;
   gdouble wheel;
+  gdouble delta_time;
+  gdouble delta_x;
+  gdouble delta_y;
+  gdouble distance;
+  gdouble velocity;
 };
 
 
Index: app/display/gimpdisplayshell.h
===================================================================
--- app/display/gimpdisplayshell.h	(revision 24605)
+++ app/display/gimpdisplayshell.h	(working copy)
@@ -178,13 +178,17 @@
   gint              scroll_start_x;
   gint              scroll_start_y;
   gboolean          button_press_before_focus;
-  guint32           last_motion_time;
+  guint32           last_disp_motion_time; /*  previous time of a forwarded motion event  */
+  guint32           last_read_motion_time;
 
   GdkRectangle     *highlight;         /* in image coordinates, can be NULL   */
   GimpDrawable     *mask;
   GimpChannelType   mask_color;
 
   gpointer          scroll_info;
+
+  GimpCoords      last_coords;     /* last motion event */
+
 };
 
 struct _GimpDisplayShellClass
Index: app/display/gimpdisplayshell-callbacks.c
===================================================================
--- app/display/gimpdisplayshell-callbacks.c	(revision 24605)
+++ app/display/gimpdisplayshell-callbacks.c	(working copy)
@@ -645,7 +645,6 @@
   gimp_display_shell_untransform_coordinate (shell,
                                              &display_coords,
                                              &image_coords);
-
   active_tool = tool_manager_get_active (gimp);
 
   if (active_tool && gimp_tool_control_get_snap_to (active_tool->control))
@@ -902,7 +901,7 @@
                                                       &image_coords,
                                                       time, state, display);
 
-                    shell->last_motion_time = bevent->time;
+                    shell->last_read_motion_time = bevent->time;
                   }
               }
             break;
@@ -1193,19 +1192,25 @@
                   {
                     gimp_display_shell_autoscroll_start (shell, state, mevent);
                   }
-
-                if (gimp_tool_control_get_motion_mode (active_tool->control) ==
-                    GIMP_MOTION_MODE_EXACT &&
+                /* gdk_device_get_history has several quirks. First is that events with borderline 
+                 * timestamps at both ends are included. Because of that we need to add 1 to lower
+                 * border. The second is due to poor X event resolution. We need to do -1 to ensure 
+                 * that the amount of events between timestamps is final or risk loosing some.
+                 */ 
+                if ((gimp_tool_control_get_motion_mode (active_tool->control) ==
+                    GIMP_MOTION_MODE_EXACT)&&
                     gdk_device_get_history (mevent->device, mevent->window,
-                                            shell->last_motion_time,
-                                            mevent->time,
+                                            shell->last_read_motion_time+1,
+                                            mevent->time-1,
                                             &history_events,
                                             &n_history_events))
                   {
+
                     gint i;
 
                     for (i = 0; i < n_history_events; i++)
                       {
+
                         gimp_display_shell_get_time_coords (shell,
                                                             mevent->device,
                                                             history_events[i],
@@ -1217,7 +1222,7 @@
                         gimp_display_shell_untransform_coordinate (shell,
                                                                    &display_coords,
                                                                    &image_coords);
-
+ 
                         if (gimp_tool_control_get_snap_to (active_tool->control))
                           {
                             gint x, y, width, height;
@@ -1230,34 +1235,53 @@
                                                             &image_coords,
                                                             x, y, width, height);
                           }
-
+                        /*Early removal of useless events saves tonn of CPU time. Defaulting smooth to 0.4*/
+                        if(gimp_display_shell_eval_event (shell, &image_coords, 0.4,history_events[i]->time))
+                          {
+                            tool_manager_motion_active (gimp,
+                                                        &image_coords,
+                                                        history_events[i]->time,
+                                                        state,
+                                                        display);
+                            shell->last_coords=image_coords;
+                            shell->last_disp_motion_time=history_events[i]->time;
+                          }
+                         shell->last_read_motion_time=history_events[i]->time;  
+                      }
+                    gdk_device_free_history (history_events, n_history_events);
+                  }
+                else
+                  {
+                    /*Early removal of useless events saves tonn of CPU time. Defaulting smooth to 0.4*/
+                    if(gimp_display_shell_eval_event (shell, &image_coords, 0.4,time))
+                      {
                         tool_manager_motion_active (gimp,
                                                     &image_coords,
-                                                    history_events[i]->time,
+                                                    time,
                                                     state,
                                                     display);
+                        shell->last_coords=image_coords;
+                        shell->last_disp_motion_time=time;
                       }
-
-                    gdk_device_free_history (history_events, n_history_events);
+                    shell->last_read_motion_time=time;  
                   }
-                else
-                  {
-                    tool_manager_motion_active (gimp,
-                                                &image_coords, time, state,
-                                                display);
-                  }
-
-                shell->last_motion_time = mevent->time;
               }
           }
 
         if (! (state &
                (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
           {
-            tool_manager_oper_update_active (gimp,
-                                             &image_coords, state,
-                                             shell->proximity,
-                                             display);
+            /*Early removal of useless events saves tonn of CPU time. And here, when floating no smooth is needed*/
+            if(gimp_display_shell_eval_event (shell, &image_coords, 0.0,time))
+              {
+                tool_manager_oper_update_active (gimp,
+                                                 &image_coords, state,
+                                                 shell->proximity,
+                                                 display);
+                shell->last_coords=image_coords;
+		shell->last_disp_motion_time=time;
+              }
+            shell->last_read_motion_time=time;  
           }
       }
       break;
Index: app/display/gimpdisplayshell-coords.c
===================================================================
--- app/display/gimpdisplayshell-coords.c	(revision 24605)
+++ app/display/gimpdisplayshell-coords.c	(working copy)
@@ -18,6 +18,8 @@
 
 #include "config.h"
 
+#include <math.h>
+
 #include <gtk/gtk.h>
 
 #include "display-types.h"
@@ -177,3 +179,99 @@
 {
   gdk_device_get_state (device, shell->canvas->window, NULL, state);
 }
+/* gimp_display_shell_eval_event:
+ *     This function evaluates the event to decide if the change is big enough to need handling and 
+ *  returns FALSE, if change is less than one image pixel taking a whole lot of load off any draw 
+ *  tools that have no use for these sub-pixel events anyway. 
+ *  If the event is seen fit at first look, it is evaluated for speed and smoothed.
+ *  Due to lousy time resolution of events pretty strong smoothing is applied to timestamps for
+ *  sensible speed result. This function is also ideal for other event adjustment like pressure curve
+ *  or calculating other derived dynamics factors like angular velocity calculation from tilt values, 
+ *  to allow for even more dynamic brushes. Calculated distance to last event is stored in GimpCoords
+ *  because its a sideproduct of velocity calculation and is currently calculated in each tool. If 
+ *  they were to use this distance, more resouces on recalculating the same value would be saved.
+ */
+gboolean
+gimp_display_shell_eval_event (GimpDisplayShell *shell,
+                               GimpCoords       *coords,
+			       gdouble  inertia_factor,
+			       guint32 time)
+{
+  guint32  thistime = time;
+  gdouble  dist;
+  gdouble  smooth_factor = 0.3;
+  gdouble  xy_sfactor = 0;
+  gdouble  dx,dy;
+  gdouble  fast_sl,slow_sl, abs_vel; 
+
+  if (shell->last_disp_motion_time == 0)
+    {
+      /*First pair is invalid to do any velocity calc so we constant it,*/
+      coords->velocity = 100;
+      coords->delta_time = 0.001;
+      coords->delta_x = 0;
+      coords->delta_y = 0;
+      coords->distance = 0;
+      shell->last_coords = *coords;
+      
+    }
+  else
+    {
+      dx=coords->delta_x=shell->last_coords.x - coords->x;
+      dy=coords->delta_y=shell->last_coords.y - coords->y;
+
+      /*Events with distances less than 1 in either motion dir are not worth handling*/
+      if( (fabs(dx) < 1.0) && (fabs(dy) < 1.0) ) return FALSE; 
+
+      /* we want absolute difference, never mind wraps. Overflows work for us. */
+      coords->delta_time = thistime - shell->last_disp_motion_time;
+      coords->delta_time = shell->last_coords.delta_time * (1-smooth_factor)
+                           +coords->delta_time * smooth_factor;
+
+      coords->distance = dist = sqrt (dx * dx + dy * dy);
+      /*If even smoothed time resolution does not allow to guess for speed, use last.*/
+      if((coords->delta_time==0)) coords->velocity = shell->last_coords.velocity;
+      else
+        {
+          /*Lets calculate velocity*/
+          coords->velocity = (coords->distance / (gdouble) coords->delta_time)/10 ;
+          
+          /*A little smooth on this too, feels better in tools this way. 
+            This factor(also used in smoothing time) can be a hadcoded constant. DEFINE perhaps?*/
+          coords->velocity = shell->last_coords.velocity * (1 - smooth_factor) 
+                             +  coords->velocity * smooth_factor;
+          /* Speeds need speedlimit */
+          coords->velocity=MIN(coords->velocity,1.0);
+        }
+        
+      /*Smooth if requestested*/
+      if(inertia_factor>0)
+        {
+           /*Apply smoothing to X and Y.
+             Smooth is dampened for high speeds to minimize the whip effect.*/
+           abs_vel=fabs(coords->velocity);
+           xy_sfactor = inertia_factor - inertia_factor*abs_vel;
+           coords->x = shell->last_coords.x - (shell->last_coords.delta_x * xy_sfactor
+                                               + coords->delta_x * (1 - xy_sfactor));
+           coords->y = shell->last_coords.y - (shell->last_coords.delta_y * xy_sfactor
+                                               + coords->delta_y * (1 - xy_sfactor));			  
+           
+           /*Recalc deltas*/     
+           coords->delta_x=shell->last_coords.x - coords->x;
+           coords->delta_y=shell->last_coords.y - coords->y;
+
+           /* Recalc distance */
+           coords->distance = sqrt ((shell->last_coords.x - coords->x) *
+                                    (shell->last_coords.x - coords->x) +
+                                    (shell->last_coords.y - coords->y) *
+                                    (shell->last_coords.y - coords->y));
+        }
+
+#ifdef VERBOSE
+      g_printerr("DIST: %f, DT:%f, Vel:%f, Press:%f,smooth_dd:%f, sf %f\n",coords->distance,coords->delta_time, shell->last_coords.velocity,coords->pressure, coords->distance-dist,xy_sfactor );
+#endif
+
+    }
+  return TRUE;
+
+}
Index: app/display/gimpdisplayshell-coords.h
===================================================================
--- app/display/gimpdisplayshell-coords.h	(revision 24605)
+++ app/display/gimpdisplayshell-coords.h	(working copy)
@@ -38,6 +38,8 @@
 void     gimp_display_shell_get_device_state  (GimpDisplayShell *shell,
                                                GdkDevice        *device,
                                                GdkModifierType  *state);
-
-
+gboolean gimp_display_shell_eval_event        (GimpDisplayShell *shell,
+                                               GimpCoords       *coords,
+                                               gdouble          inertia_factor,
+                                               guint32          time);
 #endif /* __GIMP_DISPLAY_SHELL_COORDS_H__ */
Index: app/paint/gimpink.c
===================================================================
--- app/paint/gimpink.c	(revision 24605)
+++ app/paint/gimpink.c	(working copy)
@@ -77,18 +77,6 @@
                                           gdouble           ytilt,
                                           gdouble           velocity);
 
-static void      time_smoother_add       (GimpInk          *ink,
-                                          guint32           value);
-static guint32   time_smoother_result    (GimpInk          *ink);
-static void      time_smoother_init      (GimpInk          *ink,
-                                          guint32           initval);
-
-static void      dist_smoother_add       (GimpInk          *ink,
-                                          gdouble           value);
-static gdouble   dist_smoother_result    (GimpInk          *ink);
-static void      dist_smoother_init      (GimpInk          *ink,
-                                          gdouble           initval);
-
 static void      render_blob             (Blob             *blob,
                                           PixelRegion      *dest);
 
@@ -270,67 +258,25 @@
                                         paint_core->cur_coords.pressure,
                                         paint_core->cur_coords.xtilt,
                                         paint_core->cur_coords.ytilt,
-                                        10.0);
+                                        100);
 
       if (ink->start_blob)
         g_free (ink->start_blob);
 
       ink->start_blob = blob_duplicate (ink->last_blob);
 
-      time_smoother_init (ink, time);
-      ink->last_time = time;
-
-      dist_smoother_init (ink, 0.0);
-      ink->init_velocity = TRUE;
-
       blob_to_render = ink->last_blob;
     }
   else
     {
       Blob    *blob;
-      gdouble  dist;
-      gdouble  velocity;
-      guint32  lasttime = ink->last_time;
-      guint32  thistime;
-
-      time_smoother_add (ink, time);
-      thistime = ink->last_time = time_smoother_result (ink);
-
-      /* The time resolution on X-based GDK motion events is bloody
-       * awful, hence the use of the smoothing function.  Sadly this
-       * also means that there is always the chance of having an
-       * indeterminite velocity since this event and the previous
-       * several may still appear to issue at the same
-       * instant. -ADM
-       */
-      if (thistime == lasttime)
-        thistime = lasttime + 1;
-
-      dist = sqrt ((paint_core->last_coords.x - paint_core->cur_coords.x) *
-                   (paint_core->last_coords.x - paint_core->cur_coords.x) +
-                   (paint_core->last_coords.y - paint_core->cur_coords.y) *
-                   (paint_core->last_coords.y - paint_core->cur_coords.y));
-
-      if (ink->init_velocity)
-        {
-          dist_smoother_init (ink, dist);
-          ink->init_velocity = FALSE;
-        }
-      else
-        {
-          dist_smoother_add (ink, dist);
-          dist = dist_smoother_result (ink);
-        }
-
-      velocity = 10.0 * sqrt ((dist) / (gdouble) (thistime - lasttime));
-
       blob = ink_pen_ellipse (options,
                               paint_core->cur_coords.x,
                               paint_core->cur_coords.y,
                               paint_core->cur_coords.pressure,
                               paint_core->cur_coords.xtilt,
                               paint_core->cur_coords.ytilt,
-                              velocity);
+                              sqrt(paint_core->cur_coords.velocity)*100);
 
       blob_union = blob_convex_union (ink->last_blob, blob);
       g_free (ink->last_blob);
@@ -510,84 +456,6 @@
 }
 
 
-static void
-time_smoother_init (GimpInk *ink,
-                    guint32  initval)
-{
-  gint i;
-
-  ink->ts_index = 0;
-
-  for (i = 0; i < TIME_SMOOTHER_BUFFER; i++)
-    ink->ts_buffer[i] = initval;
-}
-
-static guint32
-time_smoother_result (GimpInk *ink)
-{
-  guint64 result = 0;
-  gint    i;
-
-  for (i = 0; i < TIME_SMOOTHER_BUFFER; i++)
-    result += ink->ts_buffer[i];
-
-  return (result / (guint64) TIME_SMOOTHER_BUFFER);
-}
-
-static void
-time_smoother_add (GimpInk *ink,
-                   guint32  value)
-{
-  guint64 long_value = (guint64) value;
-
-  /*  handle wrap-around of time values  */
-  if (long_value < ink->ts_buffer[ink->ts_index])
-    long_value += (guint64) + G_MAXUINT32;
-
-  ink->ts_buffer[ink->ts_index++] = long_value;
-
-  ink->ts_buffer[ink->ts_index++] = value;
-
-  if (ink->ts_index == TIME_SMOOTHER_BUFFER)
-    ink->ts_index = 0;
-}
-
-
-static void
-dist_smoother_init (GimpInk *ink,
-                    gdouble  initval)
-{
-  gint i;
-
-  ink->dt_index = 0;
-
-  for (i = 0; i < DIST_SMOOTHER_BUFFER; i++)
-    ink->dt_buffer[i] = initval;
-}
-
-static gdouble
-dist_smoother_result (GimpInk *ink)
-{
-  gint    i;
-  gdouble result = 0.0;
-
-  for (i = 0; i < DIST_SMOOTHER_BUFFER; i++)
-    result += ink->dt_buffer[i];
-
-  return (result / (gdouble) DIST_SMOOTHER_BUFFER);
-}
-
-static void
-dist_smoother_add (GimpInk *ink,
-                   gdouble  value)
-{
-  ink->dt_buffer[ink->dt_index++] = value;
-
-  if (ink->dt_index == DIST_SMOOTHER_BUFFER)
-    ink->dt_index = 0;
-}
-
-
 /*********************************/
 /*  Rendering functions          */
 /*********************************/
Index: app/paint/gimpink.h
===================================================================
--- app/paint/gimpink.h	(revision 24605)
+++ app/paint/gimpink.h	(working copy)
@@ -24,10 +24,6 @@
 #include "gimpink-blob.h"
 
 
-#define DIST_SMOOTHER_BUFFER 10
-#define TIME_SMOOTHER_BUFFER 10
-
-
 #define GIMP_TYPE_INK            (gimp_ink_get_type ())
 #define GIMP_INK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK, GimpInk))
 #define GIMP_INK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK, GimpInkClass))
@@ -47,17 +43,6 @@
   Blob          *cur_blob;     /*  current blob                   */
   Blob          *last_blob;    /*  blob for last cursor position  */
 
-  /* circular distance history buffer */
-  gdouble        dt_buffer[DIST_SMOOTHER_BUFFER];
-  gint           dt_index;
-
-  /* circular timing history buffer */
-  guint32        ts_buffer[TIME_SMOOTHER_BUFFER];
-  gint           ts_index;
-
-  guint32        last_time;     /*  previous time of a motion event  */
-
-  gboolean       init_velocity;
 };
 
 struct _GimpInkClass
Index: app/paint/gimpinkundo.c
===================================================================
--- app/paint/gimpinkundo.c	(revision 24605)
+++ app/paint/gimpinkundo.c	(working copy)
@@ -82,20 +82,6 @@
   if (ink->start_blob)
     ink_undo->last_blob = blob_duplicate (ink->start_blob);
 
-  memcpy (ink_undo->dt_buffer, ink->dt_buffer,
-          sizeof (ink_undo->dt_buffer));
-
-  ink_undo->dt_index = ink->dt_index;
-
-  memcpy (ink_undo->ts_buffer, ink->ts_buffer,
-          sizeof (ink_undo->ts_buffer));
-
-  ink_undo->ts_index = ink->ts_index;
-
-  ink_undo->last_time = ink->last_time;
-
-  ink_undo->init_velocity = ink->init_velocity;
-
   return object;
 }
 
@@ -112,44 +98,11 @@
     {
       GimpInk *ink = GIMP_INK (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core);
       Blob    *tmp_blob;
-      gint     tmp_int;
-      gdouble  tmp_double;
-      guint32  tmp_int_buf[DIST_SMOOTHER_BUFFER];
-      gdouble  tmp_double_buf[DIST_SMOOTHER_BUFFER];
 
       tmp_blob = ink->last_blob;
       ink->last_blob = ink_undo->last_blob;
       ink_undo->last_blob = tmp_blob;
 
-      memcpy (tmp_double_buf, ink->dt_buffer,
-              sizeof (tmp_double_buf));
-      memcpy (ink->dt_buffer, ink_undo->dt_buffer,
-              sizeof (tmp_double_buf));
-      memcpy (ink_undo->dt_buffer, tmp_double_buf,
-              sizeof (tmp_double_buf));
-
-      tmp_int = ink->dt_index;
-      ink->dt_index = ink_undo->dt_index;
-      ink_undo->dt_index = tmp_int;
-
-      memcpy (tmp_int_buf, ink->ts_buffer,
-              sizeof (tmp_int_buf));
-      memcpy (ink->ts_buffer, ink_undo->ts_buffer,
-              sizeof (tmp_int_buf));
-      memcpy (ink_undo->ts_buffer, tmp_int_buf,
-              sizeof (tmp_int_buf));
-
-      tmp_int = ink->ts_index;
-      ink->ts_index = ink_undo->ts_index;
-      ink_undo->ts_index = tmp_int;
-
-      tmp_double = ink->last_time;
-      ink->last_time = ink_undo->last_time;
-      ink_undo->last_time = tmp_double;
-
-      tmp_int = ink->init_velocity;
-      ink->init_velocity = ink_undo->init_velocity;
-      ink_undo->init_velocity = tmp_int;
     }
 }
 
Index: app/paint/gimpinkundo.h
===================================================================
--- app/paint/gimpinkundo.h	(revision 24605)
+++ app/paint/gimpinkundo.h	(working copy)
@@ -39,15 +39,6 @@
 
   Blob              *last_blob;
 
-  gdouble            dt_buffer[DIST_SMOOTHER_BUFFER];
-  gint               dt_index;
-
-  guint32            ts_buffer[TIME_SMOOTHER_BUFFER];
-  gint               ts_index;
-
-  gdouble            last_time;
-
-  gboolean           init_velocity;
 };
 
 struct _GimpInkUndoClass
