GtkButton as a no-window widget



The following patch makes GtkButton a no-window widget, using an
input-only window to catch events.

Advantages:

 - Many less subwindows - less temporary pixmaps created for exposes,
   less invalidation regions, etc.

 - Buttons move with the surrounding widgets, so problems of buttons
   moving faster / slower than surrounding widgets for an opaque
   resize are gone.

 - OS X jelly bean buttons. (Or, more conservatively, buttons with 
   rounded edges AA'ed into the background.)
 
 - Much code simplification in GtkToggleButton, since it doesn't
   need 

 - Get rid of some of the awful "pretend that things are transparent
   by using parent relative backgrounds" hacks.

Disadvantages:

 - The optimization that I got working over the weekend no longer
   helps for button widgets. Which was where it mainly helped.

Incompatibilities:

 - Widgets deriving from GtkButton need to modify their code to
   take into account the fact that they are NO_WINDOW. I'm 
   not sure there are many of these outside of GTK+, which
   has GtkToggleButton and GtkOptionMenu.

 - People putting GtkButton widgets into custom widgets have to
   take care to propagate exposes.

I think it makes things look a lot better, and would allow for some
really neat theming stuff... OTOH, people are probably going
to get angry at me for rejecting small additions and putting this
in...

Regards,
                                        Owen

? docs/reference/gtk/tmpl/gtkaccessible.sgml
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2541
diff -u -p -r1.2541 ChangeLog
--- ChangeLog	2001/11/05 17:48:57	1.2541
+++ ChangeLog	2001/11/06 00:01:20
@@ -1,3 +1,16 @@
+Mon Nov  5 18:52:47 2001  Owen Taylor  <otaylor redhat com>
+
+	* gtk/gtktreeview.c (gtk_tree_view_bin_expose) 
+	* gtk/gtkclist.c (gtk_clist_expose): Propagate
+	exposes to column header button widgets.
+
+	* gtk/gtkwidget.c (gtk_widget_set_events): Remove
+	check for GTK_WIDGET_NO_WINDOW (widget).
+
+	* gtk/gtkwidget.c (gtk_widget_add_events): Handle
+	NO_WINDOW widgets by recursing over the children
+	of widget->window.
+
 Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor redhat com>
 
 	* gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
Index: gtk/gtkbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.c,v
retrieving revision 1.73
diff -u -p -r1.73 gtkbutton.c
--- gtk/gtkbutton.c	2001/10/27 00:59:51	1.73
+++ gtk/gtkbutton.c	2001/11/06 00:01:20
@@ -76,6 +76,8 @@ static void gtk_button_get_property   (G
                                        GParamSpec      *pspec);
 static void gtk_button_realize        (GtkWidget        *widget);
 static void gtk_button_unrealize      (GtkWidget        *widget);
+static void gtk_button_map            (GtkWidget        *widget);
+static void gtk_button_unmap          (GtkWidget        *widget);
 static void gtk_button_size_request   (GtkWidget        *widget,
 				       GtkRequisition   *requisition);
 static void gtk_button_size_allocate  (GtkWidget        *widget,
@@ -159,6 +161,8 @@ gtk_button_class_init (GtkButtonClass *k
 
   widget_class->realize = gtk_button_realize;
   widget_class->unrealize = gtk_button_unrealize;
+  widget_class->map = gtk_button_map;
+  widget_class->unmap = gtk_button_unmap;
   widget_class->size_request = gtk_button_size_request;
   widget_class->size_allocate = gtk_button_size_allocate;
   widget_class->expose_event = gtk_button_expose;
@@ -289,7 +293,7 @@ static void
 gtk_button_init (GtkButton *button)
 {
   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
-  GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);
+  GTK_WIDGET_SET_FLAGS (button, GTK_NO_WINDOW);
 
   button->label_text = NULL;
   
@@ -582,9 +586,7 @@ gtk_button_realize (GtkWidget *widget)
   attributes.y = widget->allocation.y + border_width;
   attributes.width = widget->allocation.width - border_width * 2;
   attributes.height = widget->allocation.height - border_width * 2;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.wclass = GDK_INPUT_ONLY;
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
 			    GDK_BUTTON_PRESS_MASK |
@@ -592,13 +594,16 @@ gtk_button_realize (GtkWidget *widget)
 			    GDK_ENTER_NOTIFY_MASK |
 			    GDK_LEAVE_NOTIFY_MASK);
 
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
 
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, button);
+  widget->window = gtk_widget_get_parent_window (widget);
+  gdk_window_ref (widget->window);
+  
+  button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+					 &attributes, attributes_mask);
+  gdk_window_set_user_data (button->event_window, button);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
-  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 }
 
 static void
@@ -608,11 +613,44 @@ gtk_button_unrealize (GtkWidget *widget)
 
   if (button->activate_timeout)
     gtk_button_finish_activate (button, FALSE);
-    
+
+  if (button->event_window)
+    {
+      gdk_window_set_user_data (button->event_window, NULL);
+      gdk_window_destroy (button->event_window);
+      button->event_window = NULL;
+    }
+  
   GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
 }
 
 static void
+gtk_button_map (GtkWidget *widget)
+{
+  GtkButton *button = GTK_BUTTON (widget);
+  
+  g_return_if_fail (GTK_IS_BUTTON (widget));
+
+  if (button->event_window)
+    gdk_window_show (button->event_window);
+
+  GTK_WIDGET_CLASS (parent_class)->map (widget);
+}
+
+static void
+gtk_button_unmap (GtkWidget *widget)
+{
+  GtkButton *button = GTK_BUTTON (widget);
+    
+  g_return_if_fail (GTK_IS_BUTTON (widget));
+
+  if (button->event_window)
+    gdk_window_hide (button->event_window);
+
+  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+static void
 gtk_button_get_props (GtkButton *button,
 		      GtkBorder *default_border,
 		      GtkBorder *default_outside_border,
@@ -706,7 +744,7 @@ gtk_button_size_allocate (GtkWidget     
   widget->allocation = *allocation;
 
   if (GTK_WIDGET_REALIZED (widget))
-    gdk_window_move_resize (widget->window,
+    gdk_window_move_resize (button->event_window,
 			    widget->allocation.x + border_width,
 			    widget->allocation.y + border_width,
 			    widget->allocation.width - border_width * 2,
@@ -714,12 +752,12 @@ gtk_button_size_allocate (GtkWidget     
 
   if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
     {
-      child_allocation.x = (CHILD_SPACING + xthickness);
-      child_allocation.y = (CHILD_SPACING + ythickness);
+      child_allocation.x = widget->allocation.x + border_width + (CHILD_SPACING + xthickness);
+      child_allocation.y = widget->allocation.y + border_width + (CHILD_SPACING + ythickness);
 
-      child_allocation.width = MAX (1, (gint)widget->allocation.width - child_allocation.x * 2 -
+      child_allocation.width = MAX (1, (gint)widget->allocation.width - (CHILD_SPACING + xthickness) * 2 -
 	                         border_width * 2);
-      child_allocation.height = MAX (1, (gint)widget->allocation.height - child_allocation.y * 2 -
+      child_allocation.height = MAX (1, (gint)widget->allocation.height - (CHILD_SPACING + ythickness) * 2 -
 	                          border_width * 2);
 
       if (GTK_WIDGET_CAN_DEFAULT (button))
@@ -781,23 +819,22 @@ gtk_button_paint (GtkWidget    *widget,
   GtkShadowType shadow_type;
   gint width, height;
   gint x, y;
+  gint border_width;
   GtkBorder default_border;
   GtkBorder default_outside_border;
   gboolean interior_focus;
    
   if (GTK_WIDGET_DRAWABLE (widget))
     {
+      border_width = GTK_CONTAINER (widget)->border_width;
       button = GTK_BUTTON (widget);
 
       gtk_button_get_props (button, &default_border, &default_outside_border, &interior_focus);
 	
-      x = 0;
-      y = 0;
-      width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
-      height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
-
-      gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
-      gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
+      x = widget->allocation.x + border_width;
+      y = widget->allocation.y + border_width;
+      width = widget->allocation.width - border_width * 2;
+      height = widget->allocation.height - border_width * 2;
 
       if (GTK_WIDGET_HAS_DEFAULT (widget) &&
 	  GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
@@ -1040,7 +1077,7 @@ gtk_real_button_activate (GtkButton *but
 
   if (GTK_WIDGET_REALIZED (button) && !button->activate_timeout)
     {
-      if (gdk_keyboard_grab (widget->window, TRUE,
+      if (gdk_keyboard_grab (button->event_window, TRUE,
 			     gtk_get_current_event_time ()) == 0)
 	{
 	  gtk_grab_add (widget);
Index: gtk/gtkbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.h,v
retrieving revision 1.20
diff -u -p -r1.20 gtkbutton.h
--- gtk/gtkbutton.h	2001/10/26 15:44:20	1.20
+++ gtk/gtkbutton.h	2001/11/06 00:01:20
@@ -52,6 +52,8 @@ struct _GtkButton
 {
   GtkBin bin;
 
+  GdkWindow *event_window;
+
   gchar *label_text;
 
   guint activate_timeout;
Index: gtk/gtkcheckbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcheckbutton.c,v
retrieving revision 1.35
diff -u -p -r1.35 gtkcheckbutton.c
--- gtk/gtkcheckbutton.c	2001/10/01 05:20:43	1.35
+++ gtk/gtkcheckbutton.c	2001/11/06 00:01:20
@@ -261,6 +261,7 @@ gtk_check_button_size_allocate (GtkWidge
   g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
   g_return_if_fail (allocation != NULL);
   
+  button = GTK_BUTTON (widget);
   check_button = GTK_CHECK_BUTTON (widget);
   toggle_button = GTK_TOGGLE_BUTTON (widget);
 
@@ -273,11 +274,9 @@ gtk_check_button_size_allocate (GtkWidge
 						    
       widget->allocation = *allocation;
       if (GTK_WIDGET_REALIZED (widget))
-	gdk_window_move_resize (toggle_button->event_window,
+	gdk_window_move_resize (button->event_window,
 				allocation->x, allocation->y,
 				allocation->width, allocation->height);
-      
-      button = GTK_BUTTON (widget);
       
       if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
 	{
Index: gtk/gtkclist.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclist.c,v
retrieving revision 1.208
diff -u -p -r1.208 gtkclist.c
--- gtk/gtkclist.c	2001/10/31 20:20:11	1.208
+++ gtk/gtkclist.c	2001/11/06 00:01:20
@@ -4806,6 +4806,19 @@ gtk_clist_expose (GtkWidget      *widget
 	  (clist, g_list_nth (clist->row_list,
 			      clist->drag_highlight_row)->data,
 	   clist->drag_highlight_row, clist->drag_highlight_pos);
+
+      if (event->window == clist->title_window)
+	{
+	  gint i;
+	  
+	  for (i = 0; i < clist->columns; i++)
+	    {
+	      if (clist->column[i].button)
+		gtk_container_propagate_expose (GTK_CONTAINER (clist),
+						clist->column[i].button,
+						event);
+	    }
+	}
     }
 
   return FALSE;
Index: gtk/gtkoptionmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkoptionmenu.c,v
retrieving revision 1.54
diff -u -p -r1.54 gtkoptionmenu.c
--- gtk/gtkoptionmenu.c	2001/10/31 23:49:09	1.54
+++ gtk/gtkoptionmenu.c	2001/11/06 00:01:20
@@ -464,6 +464,7 @@ gtk_option_menu_size_allocate (GtkWidget
 			       GtkAllocation *allocation)
 {
   GtkWidget *child;
+  GtkButton *button = GTK_BUTTON (widget);
   GtkAllocation child_allocation;
   GtkOptionMenuProps props;
   gint border_width;
@@ -473,19 +474,21 @@ gtk_option_menu_size_allocate (GtkWidget
 
   widget->allocation = *allocation;
   if (GTK_WIDGET_REALIZED (widget))
-    gdk_window_move_resize (widget->window,
+    gdk_window_move_resize (button->event_window,
 			    allocation->x + border_width, allocation->y + border_width,
 			    allocation->width - border_width * 2, allocation->height - border_width * 2);
 
   child = GTK_BIN (widget)->child;
   if (child && GTK_WIDGET_VISIBLE (child))
     {
-      child_allocation.x = GTK_WIDGET (widget)->style->xthickness + 1;
-      child_allocation.y = GTK_CONTAINER (widget)->border_width + 1;
-      child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2 - border_width * 2 -
+      gint xthickness = GTK_WIDGET (widget)->style->xthickness;
+    
+      child_allocation.x = widget->allocation.x + border_width + xthickness + 1;
+      child_allocation.y = widget->allocation.y + 2 * border_width + 1;
+      child_allocation.width = MAX (1, (gint)allocation->width - (xthickness + 1) * 2 - border_width * 2 -
 				    props.indicator_size.width - props.indicator_spacing.left - props.indicator_spacing.right -
 				    CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING - 2);
-      child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2 - border_width * 2 -
+      child_allocation.height = MAX (1, (gint)allocation->height - (border_width + 1) * 2 - border_width * 2 -
 				     CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING - 2);
       child_allocation.x += CHILD_LEFT_SPACING;
       child_allocation.y += CHILD_TOP_SPACING;
@@ -510,8 +513,8 @@ gtk_option_menu_paint (GtkWidget    *wid
       border_width = GTK_CONTAINER (widget)->border_width;
       gtk_option_menu_get_props (GTK_OPTION_MENU (widget), &props);
 
-      button_area.x = 0;
-      button_area.y = 0;
+      button_area.x = widget->allocation.x + border_width;
+      button_area.y = widget->allocation.y + border_width;
       button_area.width = widget->allocation.width - 2 * border_width;
       button_area.height = widget->allocation.height - 2 * border_width;
 
@@ -521,13 +524,6 @@ gtk_option_menu_paint (GtkWidget    *wid
 	  button_area.y += 1;
 	  button_area.width -= 2;
 	  button_area.height -= 2;
-
-	  /* This is evil, and should be elimated here and in the button
-	   * code. The point is to clear the focus, and make it
-	   * sort of transparent if it isn't there.
-	   */
-	  gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
-	  gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
 	}
 
       gtk_paint_box (widget->style, widget->window,
@@ -873,6 +869,7 @@ gtk_option_menu_position (GtkMenu  *menu
   GtkOptionMenu *option_menu;
   GtkWidget *active;
   GtkWidget *child;
+  GtkWidget *widget;
   GtkRequisition requisition;
   GList *children;
   gint screen_width;
@@ -883,14 +880,16 @@ gtk_option_menu_position (GtkMenu  *menu
   g_return_if_fail (GTK_IS_OPTION_MENU (user_data));
 
   option_menu = GTK_OPTION_MENU (user_data);
+  widget = GTK_WIDGET (option_menu);
 
   gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
   menu_width = requisition.width;
 
   active = gtk_menu_get_active (GTK_MENU (option_menu->menu));
-  gdk_window_get_origin (GTK_WIDGET (option_menu)->window, &menu_xpos, &menu_ypos);
+  gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
 
-  menu_ypos += GTK_WIDGET (option_menu)->allocation.height / 2 - 2;
+  menu_xpos += widget->allocation.x;
+  menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
 
   if (active != NULL)
     {
Index: gtk/gtktogglebutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktogglebutton.c,v
retrieving revision 1.41
diff -u -p -r1.41 gtktogglebutton.c
--- gtk/gtktogglebutton.c	2001/08/27 01:05:07	1.41
+++ gtk/gtktogglebutton.c	2001/11/06 00:01:20
@@ -51,8 +51,6 @@ static void gtk_toggle_button_class_init
 static void gtk_toggle_button_init          (GtkToggleButton      *toggle_button);
 static void gtk_toggle_button_paint         (GtkWidget            *widget,
 					     GdkRectangle         *area);
-static void gtk_toggle_button_size_allocate (GtkWidget            *widget,
-					     GtkAllocation        *allocation);
 static gint gtk_toggle_button_expose        (GtkWidget            *widget,
 					     GdkEventExpose       *event);
 static void gtk_toggle_button_pressed       (GtkButton            *button);
@@ -66,10 +64,6 @@ static void gtk_toggle_button_get_proper
 					     guint                 prop_id,
 					     GValue               *value,
 					     GParamSpec           *pspec);
-static void gtk_toggle_button_realize       (GtkWidget            *widget);
-static void gtk_toggle_button_unrealize     (GtkWidget            *widget);
-static void gtk_toggle_button_map           (GtkWidget            *widget);
-static void gtk_toggle_button_unmap         (GtkWidget            *widget);
 static void gtk_toggle_button_update_state  (GtkButton            *button);
 
 static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
@@ -121,12 +115,7 @@ gtk_toggle_button_class_init (GtkToggleB
   gobject_class->set_property = gtk_toggle_button_set_property;
   gobject_class->get_property = gtk_toggle_button_get_property;
 
-  widget_class->size_allocate = gtk_toggle_button_size_allocate;
   widget_class->expose_event = gtk_toggle_button_expose;
-  widget_class->realize = gtk_toggle_button_realize;
-  widget_class->unrealize = gtk_toggle_button_unrealize;
-  widget_class->map = gtk_toggle_button_map;
-  widget_class->unmap = gtk_toggle_button_unmap;
 
   button_class->pressed = gtk_toggle_button_pressed;
   button_class->released = gtk_toggle_button_released;
@@ -174,7 +163,6 @@ gtk_toggle_button_init (GtkToggleButton 
 {
   toggle_button->active = FALSE;
   toggle_button->draw_indicator = FALSE;
-  GTK_WIDGET_UNSET_FLAGS (toggle_button, GTK_NO_WINDOW);
 }
 
 
@@ -273,35 +261,7 @@ gtk_toggle_button_set_mode (GtkToggleBut
 
   if (toggle_button->draw_indicator != draw_indicator)
     {
-      if (GTK_WIDGET_REALIZED (toggle_button))
-	{
-	  gboolean visible = GTK_WIDGET_VISIBLE (toggle_button);
-
-	  if (visible)
-	    gtk_widget_hide (widget);
-
-	  gtk_widget_unrealize (widget);
-	  toggle_button->draw_indicator = draw_indicator;
-
-	  if (toggle_button->draw_indicator)
-	    GTK_WIDGET_SET_FLAGS (toggle_button, GTK_NO_WINDOW);
-	  else
-	    GTK_WIDGET_UNSET_FLAGS (toggle_button, GTK_NO_WINDOW);
-	  
-	  gtk_widget_realize (widget);
-
-	  if (visible)
-	    gtk_widget_show (widget);
-	}
-      else
-	{
-	  toggle_button->draw_indicator = draw_indicator;
-
-	  if (toggle_button->draw_indicator)
-	    GTK_WIDGET_SET_FLAGS (toggle_button, GTK_NO_WINDOW);
-	  else
-	    GTK_WIDGET_UNSET_FLAGS (toggle_button, GTK_NO_WINDOW);
-	}
+      toggle_button->draw_indicator = draw_indicator;
 
       if (GTK_WIDGET_VISIBLE (toggle_button))
 	gtk_widget_queue_resize (GTK_WIDGET (toggle_button));
@@ -418,6 +378,7 @@ gtk_toggle_button_paint (GtkWidget    *w
   GtkStateType state_type;
   gint width, height;
   gboolean interior_focus;
+  gint border_width;
   gint x, y;
 
   button = GTK_BUTTON (widget);
@@ -425,16 +386,15 @@ gtk_toggle_button_paint (GtkWidget    *w
 
   if (GTK_WIDGET_DRAWABLE (widget))
     {
+      border_width = GTK_CONTAINER (widget)->border_width;
+      
       gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);
       
-      x = 0;
-      y = 0;
-      width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
-      height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+      x = widget->allocation.x + border_width;
+      y = widget->allocation.y + border_width;
+      width = widget->allocation.width - border_width * 2;
+      height = widget->allocation.height - border_width * 2;
 
-      gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
-      gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
-
       if (GTK_WIDGET_HAS_DEFAULT (widget) &&
           GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
         {
@@ -505,15 +465,6 @@ gtk_toggle_button_paint (GtkWidget    *w
     }
 }
 
-static void
-gtk_toggle_button_size_allocate (GtkWidget     *widget,
-				 GtkAllocation *allocation)
-{
-  if (!GTK_WIDGET_NO_WINDOW (widget) &&
-      GTK_WIDGET_CLASS (parent_class)->size_allocate)
-    GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
-}
-
 static gint
 gtk_toggle_button_expose (GtkWidget      *widget,
 			  GdkEventExpose *event)
@@ -564,104 +515,6 @@ gtk_toggle_button_clicked (GtkButton *bu
   gtk_toggle_button_update_state (button);
 
   g_object_notify (G_OBJECT (toggle_button), "active");
-}
-
-static void
-gtk_toggle_button_realize (GtkWidget *widget)
-{
-  GtkToggleButton *toggle_button;
-  GdkWindowAttr attributes;
-  gint attributes_mask;
-  gint border_width;
-  
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
-  
-  toggle_button = GTK_TOGGLE_BUTTON (widget);
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-  
-  border_width = GTK_CONTAINER (widget)->border_width;
-  
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x + border_width;
-  attributes.y = widget->allocation.y + border_width;
-  attributes.width = widget->allocation.width - border_width * 2;
-  attributes.height = widget->allocation.height - border_width * 2;
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= (GDK_EXPOSURE_MASK |
-			    GDK_BUTTON_PRESS_MASK |
-			    GDK_BUTTON_RELEASE_MASK |
-			    GDK_ENTER_NOTIFY_MASK |
-			    GDK_LEAVE_NOTIFY_MASK);
-
-  if (GTK_WIDGET_NO_WINDOW (widget))
-    {
-      attributes.wclass = GDK_INPUT_ONLY;
-      attributes_mask = GDK_WA_X | GDK_WA_Y;
-
-      widget->window = gtk_widget_get_parent_window (widget);
-      gdk_window_ref (widget->window);
-      
-      toggle_button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
-						    &attributes, attributes_mask);
-      gdk_window_set_user_data (toggle_button->event_window, toggle_button);
-    }
-  else
-    {
-      attributes.wclass = GDK_INPUT_OUTPUT;
-      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-      attributes.visual = gtk_widget_get_visual (widget);
-      attributes.colormap = gtk_widget_get_colormap (widget);
-      widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
-				       &attributes, attributes_mask);
-      gdk_window_set_user_data (widget->window, toggle_button);
-    }
-
-  widget->style = gtk_style_attach (widget->style, widget->window);
-
-  if (!GTK_WIDGET_NO_WINDOW (widget))
-    gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-}
-  
-static void
-gtk_toggle_button_unrealize (GtkWidget *widget)
-{
-  GtkToggleButton *toggle_button;
-  
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
-
-  toggle_button = GTK_TOGGLE_BUTTON (widget);
-  
-  if (GTK_WIDGET_NO_WINDOW (widget))
-    {
-      gdk_window_set_user_data (toggle_button->event_window, NULL);
-      gdk_window_destroy (toggle_button->event_window);
-      toggle_button->event_window = NULL;
-    }
-
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
-}
-
-static void
-gtk_toggle_button_map (GtkWidget *widget)
-{
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
-
-  if (GTK_WIDGET_NO_WINDOW (widget))
-    gdk_window_show (GTK_TOGGLE_BUTTON (widget)->event_window);
-
-  GTK_WIDGET_CLASS (parent_class)->map (widget);
-}
-
-static void
-gtk_toggle_button_unmap (GtkWidget *widget)
-{
-  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
-
-  if (GTK_WIDGET_NO_WINDOW (widget))
-    gdk_window_hide (GTK_TOGGLE_BUTTON (widget)->event_window);
-
-  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
 }
 
 static void
Index: gtk/gtktogglebutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktogglebutton.h,v
retrieving revision 1.14
diff -u -p -r1.14 gtktogglebutton.h
--- gtk/gtktogglebutton.h	2001/08/23 15:26:48	1.14
+++ gtk/gtktogglebutton.h	2001/11/06 00:01:20
@@ -55,8 +55,6 @@ struct _GtkToggleButton
   guint active : 1;
   guint draw_indicator : 1;
   guint inconsistent : 1;
-  
-  GdkWindow *event_window;
 };
 
 struct _GtkToggleButtonClass
Index: gtk/gtktreeview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeview.c,v
retrieving revision 1.168
diff -u -p -r1.168 gtktreeview.c
--- gtk/gtktreeview.c	2001/11/02 21:47:27	1.168
+++ gtk/gtktreeview.c	2001/11/06 00:01:21
@@ -2497,6 +2497,7 @@ gtk_tree_view_bin_expose (GtkWidget     
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
   tree_view = GTK_TREE_VIEW (widget);
+
   gtk_widget_style_get (widget,
 			"horizontal_separator", &horizontal_separator,
 			"vertical_separator", &vertical_separator,
@@ -2870,6 +2871,20 @@ gtk_tree_view_expose (GtkWidget      *wi
 
   if (event->window == tree_view->priv->bin_window)
     return gtk_tree_view_bin_expose (widget, event);
+  else if (event->window == tree_view->priv->header_window)
+    {
+      GList *list;
+      
+      for (list = tree_view->priv->columns; list != NULL; list = list->next)
+	{
+	  GtkTreeViewColumn *column = list->data;
+	  
+	  if (column->visible)
+	    gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
+					    column->button,
+					    event);
+	}
+    }
 
   return TRUE;
 }
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.262
diff -u -p -r1.262 gtkwidget.c
--- gtk/gtkwidget.c	2001/11/04 22:57:03	1.262
+++ gtk/gtkwidget.c	2001/11/06 00:01:21
@@ -4698,7 +4698,6 @@ gtk_widget_set_events (GtkWidget *widget
   gint *eventp;
   
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
   g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
   
   eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_event_mask);
@@ -4736,8 +4735,7 @@ gtk_widget_add_events (GtkWidget *widget
   gint *eventp;
   
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
-  
+
   eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_event_mask);
   
   if (events)
@@ -4759,8 +4757,25 @@ gtk_widget_add_events (GtkWidget *widget
 
   if (GTK_WIDGET_REALIZED (widget))
     {
-      gdk_window_set_events (widget->window,
-			     gdk_window_get_events (widget->window) | events);
+      if (GTK_WIDGET_NO_WINDOW (widget))
+	{
+	  GList *children = gdk_window_get_children (widget->window);
+	  GList *tmp_list = children;
+
+	  while (tmp_list)
+	    {
+	      GdkWindow *window = tmp_list->data;
+	      gpointer user_data;
+
+	      gdk_window_get_user_data (window, &user_data);
+	      if (user_data == widget)
+		gdk_window_set_events (window, gdk_window_get_events (window) | events);
+	    }
+	}
+      else
+	{
+	  gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | events);
+	}
     }
 
   g_object_notify (G_OBJECT (widget), "events");


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