Redrawing patch



Here is a patch that

    - makes --gtk-debug=updates more entertaining to look at and
      only draw on the exact region that is being redrawn

    - fixes what I think is a typo in gdk_invalidate_maybe_recurse().
      Instead of actually recursing, the function called
      gdk_window_invalidate_region() with invalidate_children=TRUE

      The patch makes the function actually recurse down the window
      tree, based on the child_func(). If it is really intended to
      just "recurse" one level and then invalidate everything from
      there, I think the documentation should have a note about it

    - makes GtkFrame !redraw_on_allocate and handle invalidations
      itself in ->size_allocation()

      This uncovered a bug where there would sometimes be rounding
      errors in a calculation in gtk_frame_paint(). I think this fix
      should go in, even if the rest of the patch is rejected.

    - Makes GtkViewport !redraw_on_allocate. This is a really simple
      change that makes the viewport not invalidate all of its child
      if the child is a NO_WINDOW widget. 


Søren

? drawing.patch
Index: docs/Changes-2.0.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/Changes-2.0.txt,v
retrieving revision 1.38
diff -u -r1.38 Changes-2.0.txt
--- docs/Changes-2.0.txt	2001/11/04 22:57:01	1.38
+++ docs/Changes-2.0.txt	2001/11/11 22:09:49
@@ -509,8 +509,9 @@
   longer need to gtk_widget_push_cmap (gtk_preview_get_cmap ()) in
   your code.
 
-* The GtkBox, GtkTable, and GtkAlignment widgets now call
-  gtk_widget_set_redraw_on_allocate (widget, FALSE); on themselves.
-  If you want to actually draw contents in a widget derived from
-  one of these widgets, you'll probably want to change this
-  in your init() function.
+* The GtkBox, GtkTable, GtkViewport, GtkFrame and GtkAlignment widgets
+  now call gtk_widget_set_redraw_on_allocate (widget, FALSE); on
+  themselves.  If you want to actually draw contents in a widget
+  derived from one of these widgets, you'll probably want to change
+  this in your init() function.
+
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.124
diff -u -r1.124 gdkwindow.c
--- gdk/gdkwindow.c	2001/11/04 22:57:02	1.124
+++ gdk/gdkwindow.c	2001/11/11 22:09:50
@@ -1984,7 +1984,7 @@
 
           if (debug_updates)
             {
-              /* Make sure we see the red invalid area before redrawing. */
+              /* Make sure we see the invalid colored area before redrawing. */
               gdk_flush ();
               g_usleep (70000);
             }
@@ -2151,6 +2151,82 @@
   gdk_region_destroy (region);
 }
 
+static GdkColor
+get_ugly_color (void)
+{
+  static int x;
+  GdkColor ugly_color;
+  
+  x++;
+  if (x == 1)
+    {
+      ugly_color.pixel = 0;
+      ugly_color.red = 50000;
+      ugly_color.green = 20000;
+      ugly_color.blue = 20000;
+    }
+  else if (x == 2)
+    {
+      ugly_color.pixel = 0;
+      ugly_color.red = 20000;
+      ugly_color.green = 20000;
+      ugly_color.blue = 50000;
+    }
+  else if (x == 3)
+    {
+      ugly_color.pixel = 0;
+      ugly_color.red = 65000;
+      ugly_color.green = 65000;
+      ugly_color.blue = 20000;
+    }
+  else
+    {
+      ugly_color.pixel = 0;
+      ugly_color.red = 20000;
+      ugly_color.green = 60000;
+      ugly_color.blue = 20000;
+      
+      x = 0;
+    }
+
+  return ugly_color;
+}  
+
+static void
+draw_ugly_color (GdkWindow *window,
+		 GdkRegion *region)
+{
+  /* Draw ugly color all over the newly-invalid region */
+  GdkRectangle *ugly_rects;
+  gint n_ugly_rects;
+  int i;
+
+  gdk_region_get_rectangles (region, &ugly_rects, &n_ugly_rects);
+
+  for (i = 0; i < n_ugly_rects; i++)
+    {
+      GdkColor ugly_color = get_ugly_color ();
+      GdkGC *ugly_gc;
+    
+      ugly_gc = gdk_gc_new (window);
+      gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
+  
+      gdk_draw_rectangle (window,
+			  ugly_gc,
+			  TRUE,
+			  ugly_rects[i].x, ugly_rects[i].y,
+			  ugly_rects[i].width, ugly_rects[i].height);
+
+      g_object_unref (G_OBJECT (ugly_gc));
+    }
+      
+  gdk_flush ();
+
+  g_free (ugly_rects);
+  
+  g_usleep (10000);
+}      
+
 /**
  * gdk_window_invalidate_maybe_recurse:
  * @window: a #GdkWindow
@@ -2200,26 +2276,7 @@
   if (!gdk_region_empty (visible_region))
     {
       if (debug_updates)
-        {
-          /* Draw ugly color all over the newly-invalid region */
-          GdkRectangle ugly_rect;
-          GdkGC *ugly_gc;
-          GdkColor ugly_color = { 0, 60000, 10000, 10000 };
-          
-          ugly_gc = gdk_gc_new (window);
-
-          gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
-          
-	  gdk_region_get_clipbox (visible_region, &ugly_rect);
-
-          gdk_draw_rectangle (window,
-                              ugly_gc,
-                              TRUE,
-                              ugly_rect.x, ugly_rect.y,
-                              ugly_rect.width, ugly_rect.height);
-          
-          g_object_unref (G_OBJECT (ugly_gc));
-        }
+	draw_ugly_color (window, visible_region);
       
       if (private->update_area)
 	{
@@ -2256,7 +2313,7 @@
 		  child_region = gdk_region_copy (visible_region);
 		  gdk_region_offset (child_region, -x, -y);
 		  
-		  gdk_window_invalidate_region ((GdkWindow *)child, child_region, TRUE);
+		  gdk_window_invalidate_maybe_recurse ((GdkWindow *)child, child_region, child_func, user_data);
 		  
 		  gdk_region_destroy (child_region);
 		}
Index: gtk/gtkframe.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkframe.c,v
retrieving revision 1.41
diff -u -r1.41 gtkframe.c
--- gtk/gtkframe.c	2001/11/04 22:57:03	1.41
+++ gtk/gtkframe.c	2001/11/11 22:09:50
@@ -184,6 +184,8 @@
 static void
 gtk_frame_init (GtkFrame *frame)
 {
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (frame), FALSE);
+  
   frame->label_widget = NULL;
   frame->shadow_type = GTK_SHADOW_ETCHED_IN;
   frame->label_xalign = 0.0;
@@ -522,8 +524,10 @@
 	    xalign = 1 - frame->label_xalign;
 
 	  height_extra = MAX (0, child_requisition.height - widget->style->xthickness);
-	  y -= height_extra * (1 - frame->label_yalign);
-	  height += height_extra * (1 - frame->label_yalign);
+	  height_extra *= (1 - frame->label_yalign);
+
+	  y -= height_extra;
+	  height += height_extra;
 	  
 	  x2 = widget->style->xthickness + (frame->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_SIDE_PAD;
 
@@ -594,6 +598,28 @@
 }
 
 static void
+gtk_frame_invalidate_border (GtkFrame *frame)
+{
+  GtkWidget *widget = GTK_WIDGET (frame);
+
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      GdkRegion *border;
+      GdkRegion *child_area;
+
+      border = gdk_region_rectangle (&(widget->allocation));
+      child_area = gdk_region_rectangle (&(frame->child_allocation));
+
+      gdk_region_subtract (border, child_area);
+
+      gdk_window_invalidate_region (widget->window, border, FALSE);
+
+      gdk_region_destroy (child_area);
+      gdk_region_destroy (border);
+    }
+}
+
+static void
 gtk_frame_size_allocate (GtkWidget     *widget,
 			 GtkAllocation *allocation)
 {
@@ -601,24 +627,18 @@
   GtkBin *bin = GTK_BIN (widget);
   GtkAllocation new_allocation;
 
+  gtk_frame_invalidate_border (frame);
+  
   widget->allocation = *allocation;
 
   gtk_frame_compute_child_allocation (frame, &new_allocation);
   
-  /* If the child allocation changed, that means that the frame is drawn
-   * in a new place, so we must redraw the entire widget.
-   */
-  if (GTK_WIDGET_MAPPED (widget) &&
-      (new_allocation.x != frame->child_allocation.x ||
-       new_allocation.y != frame->child_allocation.y ||
-       new_allocation.width != frame->child_allocation.width ||
-       new_allocation.height != frame->child_allocation.height))
-    gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
-  
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     gtk_widget_size_allocate (bin->child, &new_allocation);
   
   frame->child_allocation = new_allocation;
+
+  gtk_frame_invalidate_border (frame);
   
   if (frame->label_widget && GTK_WIDGET_VISIBLE (frame->label_widget))
     {
Index: gtk/gtkviewport.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkviewport.c,v
retrieving revision 1.50
diff -u -r1.50 gtkviewport.c
--- gtk/gtkviewport.c	2001/11/02 21:16:54	1.50
+++ gtk/gtkviewport.c	2001/11/11 22:09:51
@@ -217,6 +217,7 @@
 gtk_viewport_init (GtkViewport *viewport)
 {
   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (viewport), FALSE);
 
   gtk_container_set_resize_mode (GTK_CONTAINER (viewport), GTK_RESIZE_QUEUE);
   
@@ -654,6 +655,8 @@
 
   if (GTK_WIDGET_REALIZED (widget))
     {
+      gdk_window_invalidate_rect (widget->window, NULL, FALSE);
+      
       gdk_window_move_resize (widget->window,
 			      allocation->x + border_width,
 			      allocation->y + border_width,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]