RE: How to redraw a widget completely?




> For current GTK+, your best hope is:
> 
>  gdk_window_clear_area (widget->window, 
>                         widget->allocation.x,
>                         widget->allocation.y,
>                         widget->allocation.width,
>                         widget->allocation.height);
>  gtk_widget_queue_draw (widget);


I think this is slightly wrong - a widget's allocation is relative to its
parent widget's window, rather that its own (if it has one).

And it won't work for widgets which have extra child windows,
e.g. clist, hscale/vscale, hscrollbar/vscrollbar.

This is my latest attempt. I use gdk_window_get_children to recursively
clear child windows. It seems to work perfectly :-) but I haven't tested
it much yet:


void
editor_refresh_widget (GtkWidget *widget)
{
  GtkWidget *parent;
  gint x, y, w, h;
  GdkGC *gc;

  if (!GTK_WIDGET_DRAWABLE (widget))
    return;

  x = widget->allocation.x;
  y = widget->allocation.y;
  w = widget->allocation.width;
  h = widget->allocation.height;

  if (widget->parent)
    {
      gdk_window_clear_area (widget->parent->window, x, y, w, h);
      clear_child_windows (widget->parent->window, x, y, w, h);
    }
  else
    {
      gdk_window_clear (widget->window);			 
      clear_child_windows (widget->window, -1, -1, -1, -1);
    }

  /* queue_draw doesn't work with a clist. */
  /*gtk_widget_queue_draw (widget);*/
  gtk_widget_draw (widget, NULL);
  gtk_widget_draw_children (widget);
}


/* This clears all child windows which fall within the given rectangle.
   If the rectangle width is -1, then all children are cleared. */
static void
clear_child_windows (GdkWindow *window, gint x, gint y, gint w, gint h)
{
  GList *children;
  GdkWindow *child_window;
  gint win_x, win_y, win_w, win_h;
  XWindowAttributes xwa;

  children = gdk_window_get_children (window);
  while (children)
    {
      child_window = children->data;
      gdk_window_get_position (child_window, &win_x, &win_y);
      gdk_window_get_size (child_window, &win_w, &win_h);

      if (w == -1
	  || !(win_x >= x + w || win_x + win_w <= x
	       || win_y >= y + h || win_y + win_h <= y))
	{
	  /* We need to make sure this is not an InputOnly window, or we get
	     a BadMatch. CList uses InputOnly windows - for resizing columns.*/
	  XGetWindowAttributes (GDK_DISPLAY (),
				GDK_WINDOW_XWINDOW (child_window), &xwa);
	  if (xwa.class != InputOnly)
	    {
	      gdk_window_clear (child_window);
	      clear_child_windows (child_window, -1, -1, -1, -1);
	    }
	}
      children = children->next;
    }
  g_list_free (children);
}



Also, gtk_widget_queue_draw() doesn't redraw a GtkCList properly - the
column titles and the scrollbars are not drawn.
I have to use both of these:

  gtk_widget_draw (widget, NULL);
  gtk_widget_draw_children (widget);

Does this matter? Is this a bug in CList?

Damon




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