Index: gimp/app/display/gimpdisplayshell-callbacks.c
===================================================================
RCS file: /cvs/gnome/gimp/app/display/gimpdisplayshell-callbacks.c,v
retrieving revision 1.245
diff -p -u -r1.245 gimpdisplayshell-callbacks.c
--- gimp/app/display/gimpdisplayshell-callbacks.c	4 Apr 2004 17:17:39 -0000	1.245
+++ gimp/app/display/gimpdisplayshell-callbacks.c	13 Apr 2004 21:49:07 -0000
@@ -70,6 +70,17 @@
 
 #include "gimp-intl.h"
 
+typedef struct 
+{
+  GimpDisplayShell	*shell;
+  GdkEventMotion	*mevent;
+  GdkDevice		*device;
+  guint32		time;
+  GdkModifierType	state;
+  gint			keep_scrolling;
+  gint			timeout_id;
+} ScrollInfo;
+
 
 /* #define DEBUG_MOVE_PUSH 1 */
 
@@ -414,7 +425,7 @@ gimp_display_shell_canvas_expose (GtkWid
   gimp_display_shell_draw_guides (shell);
 
   /* draw the grid */
-  gimp_display_shell_draw_grid (shell, &eevent->area);
+  gimp_display_shell_draw_grid (shell);
 
   /* and the cursor (if we have a software cursor) */
   gimp_display_shell_draw_cursor (shell);
@@ -440,7 +451,9 @@ gimp_display_shell_check_device_cursor (
 gboolean
 gimp_display_shell_popup_menu (GtkWidget *widget)
 {
-  GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (widget);
+  GimpDisplayShell *shell;
+
+  shell = GIMP_DISPLAY_SHELL (widget);
 
   gimp_context_set_display (gimp_get_user_context (shell->gdisp->gimage->gimp),
                             shell->gdisp);
@@ -455,6 +468,90 @@ gimp_display_shell_popup_menu (GtkWidget
   return TRUE;
 }
 
+#define AUTOSCROLL_DT 20
+#define AUTOSCROLL_DX 5
+
+static gboolean
+autoscroll_timeout (gpointer data)
+{
+  GimpCoords device_coords, image_coords;
+  GimpDisplay *gdisp;
+  ScrollInfo *info = (ScrollInfo *)data;
+  gint off_x = 0;
+  gint off_y = 0;
+
+  if (!info->keep_scrolling)
+    {
+      info->timeout_id = 0;
+      return (FALSE);
+    }
+
+  info->time += AUTOSCROLL_DT;
+
+  gdisp = info->shell->gdisp;
+  gimp_display_shell_get_device_coords (info->shell,
+					info->device,
+					&device_coords);
+
+  if (device_coords.x < 0)
+    off_x = -AUTOSCROLL_DX;
+  else if (device_coords.x > info->shell->disp_width)
+    off_x = AUTOSCROLL_DX;
+  
+  if (device_coords.y < 0)
+    off_y = -AUTOSCROLL_DX;
+  else if (device_coords.y > info->shell->disp_height)
+    off_y = AUTOSCROLL_DX;
+
+  if( off_x == 0 && off_y == 0 )
+    {
+      info->timeout_id = 0;
+      return (FALSE);
+    }
+  else
+    {
+      gimp_display_shell_scroll (info->shell, off_x, off_y);
+
+      gimp_display_shell_untransform_coords (info->shell,
+					     &device_coords,
+					     &image_coords);
+
+      tool_manager_motion_active (gdisp->gimage->gimp,
+				  &image_coords, 
+				  info->time, info->state,
+				  gdisp);
+
+      return (TRUE);
+    }
+}
+
+  
+static void
+begin_autoscrolling (ScrollInfo *info,
+		     GimpDisplayShell *shell,
+		     GdkModifierType state,
+		     GdkEventMotion *mevent)
+{
+  if(info->timeout_id == 0)
+    {
+      info->shell = shell;
+      info->mevent = mevent;
+      info->device = mevent->device;
+      info->time = gdk_event_get_time ((GdkEvent*)mevent);
+      info->state = state;
+      info->timeout_id = g_timeout_add (AUTOSCROLL_DT, 
+					autoscroll_timeout, (gpointer)info);
+      info->keep_scrolling = TRUE;
+    }
+}
+
+static void
+end_autoscrolling (ScrollInfo *info)
+{
+  info->keep_scrolling = FALSE;
+  info->timeout_id = 0;
+}
+
 gboolean
 gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                        GdkEvent         *event,
@@ -471,6 +568,7 @@ gimp_display_shell_canvas_tool_events (G
   guint32          time;
   gboolean         return_val    = FALSE;
   gboolean         update_cursor = FALSE;
+  static ScrollInfo scroll_info = {NULL, NULL, 0, 0};
 
   static GimpToolInfo *space_shaded_tool  = NULL;
 
@@ -773,6 +871,8 @@ gimp_display_shell_canvas_tool_events (G
       {
         GdkEventButton *bevent = (GdkEventButton *) event;
 
+	end_autoscrolling (&scroll_info);
+
         if (gimp->busy)
           return TRUE;
 
@@ -1028,37 +1128,7 @@ gimp_display_shell_canvas_tool_events (G
                      mevent->y > shell->disp_height) &&
                     ! gimp_tool_control_scroll_lock (active_tool->control))
                   {
-                    gint off_x = 0;
-                    gint off_y = 0;
-
-                    /*  The cases for scrolling  */
-                    if (mevent->x < 0)
-                      off_x = mevent->x;
-                    else if (mevent->x > shell->disp_width)
-                      off_x = mevent->x - shell->disp_width;
-
-                    if (mevent->y < 0)
-                      off_y = mevent->y;
-                    else if (mevent->y > shell->disp_height)
-                      off_y = mevent->y - shell->disp_height;
-
-                    if (gimp_display_shell_scroll (shell, off_x, off_y))
-                      {
-                        GimpCoords device_coords;
-
-                        gimp_display_shell_get_device_coords (shell,
-                                                              mevent->device,
-                                                              &device_coords);
-
-                        if (device_coords.x == mevent->x &&
-                            device_coords.y == mevent->y)
-                          {
-                            /*  Put this event back on the queue
-                             *  so it keeps scrolling
-                             */
-                            gdk_event_put ((GdkEvent *) mevent);
-                          }
-                      }
+		    begin_autoscrolling (&scroll_info, shell, state, mevent);
                   }
 
                 tool_manager_motion_active (gimp,
