Index: app/tools/gimppaintoptions-gui.c
===================================================================
--- app/tools/gimppaintoptions-gui.c	(revision 24620)
+++ app/tools/gimppaintoptions-gui.c	(working copy)
@@ -132,6 +132,14 @@
       gimp_scale_entry_set_logarithmic (adj, TRUE);
     }
 
+
+  /* smoothing */
+  gimp_prop_scale_entry_new (config, "smooth",
+                             GTK_TABLE (table), 0, table_row++,
+                             _("Smooth:"),
+                             0.01, 0.1, 2,
+                             FALSE, 0.0, 0.0);
+
   /*  the gradient  */
   if (tool_type == GIMP_TYPE_BLEND_TOOL)
     {
Index: app/display/gimpdisplayshell-callbacks.c
===================================================================
--- app/display/gimpdisplayshell-callbacks.c	(revision 24620)
+++ app/display/gimpdisplayshell-callbacks.c	(working copy)
@@ -47,6 +47,8 @@
 #include "tools/gimptoolcontrol.h"
 #include "tools/tool_manager.h"
 
+#include "paint/gimppaintoptions.h"
+
 #include "widgets/gimpactiongroup.h"
 #include "widgets/gimpcontrollers.h"
 #include "widgets/gimpcontrollerkeyboard.h"
@@ -92,7 +94,9 @@
 
 static GdkEvent * gimp_display_shell_compress_motion   (GimpDisplayShell *shell);
 
+static gdouble    gimp_display_shell_get_smooth_factor (GimpTool *active_tool);
 
+
 /*  public functions  */
 
 gboolean
@@ -1244,7 +1248,8 @@
                          * Defaulting smoothing to 0.4.
                          */
                         if (gimp_display_shell_eval_event (shell,
-                                                           &image_coords, 0.4,
+                                                           &image_coords,
+                                                           gimp_display_shell_get_smooth_factor (active_tool),
                                                            history_events[i]->time))
                           {
                             tool_manager_motion_active (gimp,
@@ -1253,7 +1258,6 @@
                                                         state,
                                                         display);
 
-                            shell->last_coords = image_coords;
                             shell->last_disp_motion_time = history_events[i]->time;
                           }
 
@@ -1268,7 +1272,8 @@
                      * Defaulting smoothing to 0.4.
                      */
                     if (gimp_display_shell_eval_event (shell,
-                                                       &image_coords, 0.4,
+                                                       &image_coords,
+                                                       gimp_display_shell_get_smooth_factor (active_tool),
                                                        time))
                       {
                         tool_manager_motion_active (gimp,
@@ -1277,7 +1282,6 @@
                                                     state,
                                                     display);
 
-                        shell->last_coords = image_coords;
                         shell->last_disp_motion_time = time;
                       }
 
@@ -1290,18 +1294,16 @@
                (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
           {
             /* Early removal of useless events saves CPU time.
-             * Smoothing coasting to avoid unpredicted jumps when making contact.
-             * This may need a different solution but cant properly test it without
-             * adjustment.
+             * Smoothing off for coasting.
              */
-            if (gimp_display_shell_eval_event (shell, &image_coords, 0.4, time))
+            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_disp_motion_time = time;
               }
 
             shell->last_read_motion_time = time;
@@ -1805,3 +1807,17 @@
 
   return last_motion;
 }
+
+static gdouble
+gimp_display_shell_get_smooth_factor (GimpTool *active_tool)
+{
+  if (active_tool)
+    {
+      GimpToolOptions *options = gimp_tool_get_options (active_tool);
+
+      if (GIMP_IS_PAINT_OPTIONS (options))
+         return (GIMP_PAINT_OPTIONS (options)->smooth); 
+    }
+
+   return 0.0;  /* default smooth to 0 for non-paint tools */
+}
Index: app/display/gimpdisplayshell-coords.c
===================================================================
--- app/display/gimpdisplayshell-coords.c	(revision 24620)
+++ app/display/gimpdisplayshell-coords.c	(working copy)
@@ -214,8 +214,14 @@
 {
   guint32        thistime      = time;
   gdouble        dist;
-  gdouble        xy_sfactor    = 0;
   const gdouble  smooth_factor = 0.3;
+  gdouble sin_avg;
+  gdouble sin_old;
+  gdouble sin_new;
+  gdouble cos_avg;
+  gdouble cos_old;
+  gdouble cos_new;
+  gdouble new_x, new_y;  
 
   if (shell->last_disp_motion_time == 0)
     {
@@ -224,9 +230,8 @@
        */
       coords->velocity   = 100;
       coords->delta_time = 0.001;
-      coords->distance   = 0;
+      coords->distance   = 1;
 
-      shell->last_coords = *coords;
     }
   else
     {
@@ -259,34 +264,52 @@
           /* A little smooth on this too, feels better in tools this way. */
           coords->velocity = (shell->last_coords.velocity * (1 - smooth_factor)
                               +  coords->velocity * smooth_factor);
-	  /* Speed needs upper limit */
+          /* Speed needs upper limit */
           coords->velocity=MIN(coords->velocity,1.0);
         }
 
       if (inertia_factor > 0)
         {
-          /* Apply smoothing to X and Y.
-           *
-           * The very high velocity values (yes, thats around 25
-           * according to tests) happen at great zoom outs and scream
-           * for heavyhanded smooth so I made it automatic. This
-           * should be bound to zoom level once theres a GUI foob to
-           * adjust smooth or disabled completely.
-           */
+          /* Apply smoothing to X and Y. */
 
-           /*Apply smoothing to X and Y.
-             Smooth is dampened for high speeds to minimize the whip effect.*/
-           xy_sfactor = inertia_factor - inertia_factor * fabs (coords->velocity);
-           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));
+           /* This tells how far from the pointer can stray from the line */
+           gdouble max_deviation = SQR (20 * inertia_factor);
+           gdouble cur_deviation = max_deviation;
 
+           sin_new = coords->delta_x / coords->distance;
+           sin_old = shell->last_coords.delta_x / shell->last_coords.distance;
+           sin_avg = sin (asin (sin_old) * inertia_factor +
+                          asin (sin_new) * (1 - inertia_factor));
+
+           cos_new = coords->delta_y / coords->distance;
+           cos_old = shell->last_coords.delta_y / shell->last_coords.distance;
+           cos_avg = cos (acos (cos_old) * inertia_factor + 
+                          acos (cos_new) * (1 - inertia_factor));
+
+           coords->delta_x = sin_avg * coords->distance;
+           coords->delta_y = cos_avg * coords->distance;
+
+           new_x = (shell->last_coords.x - coords->delta_x) * 0.5 + coords->x * 0.5;
+           new_y = (shell->last_coords.y - coords->delta_y) * 0.5 + coords->y * 0.5;
+
+           cur_deviation = SQR(coords->x-new_x) + SQR(coords->y-new_y);
+
+           while (cur_deviation >= max_deviation)
+             {
+               new_x = new_x * 0.8 + coords->x * 0.2;
+               new_y = new_y * 0.8 + coords->y * 0.2;
+               cur_deviation = SQR (coords->x - new_x) + SQR (coords->y - new_y);
+             }
+           coords->x = new_x;
+           coords->y = new_y;
+
+           coords->delta_x = shell->last_coords.x - coords->x;
+           coords->delta_y = shell->last_coords.y - coords->y;
            /* Recalculate 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));
+           coords->distance = sqrt ((coords->delta_x) *
+                                    (coords->delta_x) +
+                                    (coords->delta_y) *
+                                    (coords->delta_y));
 
         }
 
@@ -297,10 +320,10 @@
                   shell->last_coords.velocity,
                   coords->pressure,
                   coords->distance - dist,
-                  xy_sfactor);
+                  inertia_factor);
 #endif
 
     }
-
+  shell->last_coords = *coords;
   return TRUE;
 }
Index: app/paint/gimppaintoptions.c
===================================================================
--- app/paint/gimppaintoptions.c	(revision 24620)
+++ app/paint/gimppaintoptions.c	(working copy)
@@ -53,6 +53,8 @@
 #define DEFAULT_USE_JITTER            FALSE
 #define DEFAULT_JITTER_AMOUNT         0.2
 
+#define DEFAULT_SMOOTH                0.7
+
 #define DEFAULT_USE_GRADIENT          FALSE
 #define DEFAULT_GRADIENT_REVERSE      FALSE
 #define DEFAULT_GRADIENT_REPEAT       GIMP_REPEAT_TRIANGULAR
@@ -85,6 +87,8 @@
   PROP_USE_JITTER,
   PROP_JITTER_AMOUNT,
 
+  PROP_SMOOTH,
+
   PROP_BRUSH_VIEW_TYPE,
   PROP_BRUSH_VIEW_SIZE,
   PROP_PATTERN_VIEW_TYPE,
@@ -194,6 +198,11 @@
                                    0.0, 50.0, DEFAULT_JITTER_AMOUNT,
                                    GIMP_PARAM_STATIC_STRINGS);
 
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SMOOTH,
+                                   "smooth", NULL,
+                                   0.0, 1.0, DEFAULT_SMOOTH,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
   GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_GRADIENT,
                                     "use-gradient", NULL,
                                     DEFAULT_USE_GRADIENT,
@@ -352,6 +361,10 @@
       jitter_options->jitter_amount = g_value_get_double (value);
       break;
 
+    case PROP_SMOOTH:
+      options->smooth = g_value_get_double (value);
+      break;
+
     case PROP_USE_GRADIENT:
       gradient_options->use_gradient = g_value_get_boolean (value);
       break;
@@ -467,6 +480,10 @@
       g_value_set_double (value, jitter_options->jitter_amount);
       break;
 
+    case PROP_SMOOTH:
+      g_value_set_double (value, options->smooth);
+      break;
+
     case PROP_USE_GRADIENT:
       g_value_set_boolean (value, gradient_options->use_gradient);
       break;
Index: app/paint/gimppaintoptions.h
===================================================================
--- app/paint/gimppaintoptions.h	(revision 24620)
+++ app/paint/gimppaintoptions.h	(working copy)
@@ -97,6 +97,8 @@
   GimpGradientOptions      *gradient_options;
   GimpJitterOptions        *jitter_options;
 
+  gdouble                   smooth;
+
   GimpViewType              brush_view_type;
   GimpViewSize              brush_view_size;
   GimpViewType              pattern_view_type;
