]> Pileus Git - ~andy/gtk/blob - gtk/gtkwidget.c
made GtkWidget::grab_focus a RUN_LAST and RUN_ACTION signal. moved stuff
[~andy/gtk] / gtk / gtkwidget.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <stdarg.h>
20 #include <string.h>
21 #include "gtkcontainer.h"
22 #include "gtkmain.h"
23 #include "gtkrc.h"
24 #include "gtkselection.h"
25 #include "gtksignal.h"
26 #include "gtkwidget.h"
27 #include "gtkwindow.h"
28 #include "gtkbindings.h"
29 #include "gtkprivate.h"
30 #include "gdk/gdk.h"
31 #include "gdk/gdkx.h"
32
33
34 #define WIDGET_CLASS(w)  GTK_WIDGET_CLASS (GTK_OBJECT (w)->klass)
35 #define INIT_PATH_SIZE  (512)
36
37
38 enum {
39   SHOW,
40   HIDE,
41   MAP,
42   UNMAP,
43   REALIZE,
44   UNREALIZE,
45   DRAW,
46   DRAW_FOCUS,
47   DRAW_DEFAULT,
48   SIZE_REQUEST,
49   SIZE_ALLOCATE,
50   STATE_CHANGED,
51   PARENT_SET,
52   STYLE_SET,
53   ADD_ACCELERATOR,
54   REMOVE_ACCELERATOR,
55   GRAB_FOCUS,
56   EVENT,
57   BUTTON_PRESS_EVENT,
58   BUTTON_RELEASE_EVENT,
59   MOTION_NOTIFY_EVENT,
60   DELETE_EVENT,
61   DESTROY_EVENT,
62   EXPOSE_EVENT,
63   KEY_PRESS_EVENT,
64   KEY_RELEASE_EVENT,
65   ENTER_NOTIFY_EVENT,
66   LEAVE_NOTIFY_EVENT,
67   CONFIGURE_EVENT,
68   FOCUS_IN_EVENT,
69   FOCUS_OUT_EVENT,
70   MAP_EVENT,
71   UNMAP_EVENT,
72   PROPERTY_NOTIFY_EVENT,
73   SELECTION_CLEAR_EVENT,
74   SELECTION_REQUEST_EVENT,
75   SELECTION_NOTIFY_EVENT,
76   SELECTION_GET,
77   SELECTION_RECEIVED,
78   PROXIMITY_IN_EVENT,
79   PROXIMITY_OUT_EVENT,
80   DRAG_BEGIN,
81   DRAG_END,
82   DRAG_DATA_DELETE,
83   DRAG_LEAVE,
84   DRAG_MOTION,
85   DRAG_DROP,
86   DRAG_DATA_GET,
87   DRAG_DATA_RECEIVED,
88   CLIENT_EVENT,
89   NO_EXPOSE_EVENT,
90   VISIBILITY_NOTIFY_EVENT,
91   DEBUG_MSG,
92   LAST_SIGNAL
93 };
94
95 enum {
96   ARG_0,
97   ARG_NAME,
98   ARG_PARENT,
99   ARG_X,
100   ARG_Y,
101   ARG_WIDTH,
102   ARG_HEIGHT,
103   ARG_VISIBLE,
104   ARG_SENSITIVE,
105   ARG_CAN_FOCUS,
106   ARG_HAS_FOCUS,
107   ARG_CAN_DEFAULT,
108   ARG_HAS_DEFAULT,
109   ARG_COMPOSITE_CHILD,
110   ARG_STYLE,
111   ARG_EVENTS,
112   ARG_EXTENSION_EVENTS
113 };
114
115 typedef struct  _GtkStateData    GtkStateData;
116
117 struct _GtkStateData
118 {
119   GtkStateType  state;
120   guint         state_restoration : 1;
121   guint         parent_sensitive : 1;
122   guint         use_forall : 1;
123 };
124
125 static void gtk_widget_class_init                (GtkWidgetClass    *klass);
126 static void gtk_widget_init                      (GtkWidget         *widget);
127 static void gtk_widget_set_arg                   (GtkObject         *object,
128                                                   GtkArg            *arg,
129                                                   guint              arg_id);
130 static void gtk_widget_get_arg                   (GtkObject         *object,
131                                                   GtkArg            *arg,
132                                                   guint              arg_id);
133 static void gtk_widget_shutdown                  (GtkObject         *object);
134 static void gtk_widget_real_destroy              (GtkObject         *object);
135 static void gtk_widget_finalize                  (GtkObject         *object);
136 static void gtk_widget_real_show                 (GtkWidget         *widget);
137 static void gtk_widget_real_hide                 (GtkWidget         *widget);
138 static void gtk_widget_real_map                  (GtkWidget         *widget);
139 static void gtk_widget_real_unmap                (GtkWidget         *widget);
140 static void gtk_widget_real_realize              (GtkWidget         *widget);
141 static void gtk_widget_real_unrealize            (GtkWidget         *widget);
142 static void gtk_widget_real_draw                 (GtkWidget         *widget,
143                                                   GdkRectangle      *area);
144 static void gtk_widget_real_size_request         (GtkWidget         *widget,
145                                                   GtkRequisition    *requisition);
146 static void gtk_widget_real_size_allocate        (GtkWidget         *widget,
147                                                   GtkAllocation     *allocation);
148 static gint gtk_widget_real_key_press_event      (GtkWidget         *widget,
149                                                   GdkEventKey       *event);
150 static gint gtk_widget_real_key_release_event    (GtkWidget         *widget,
151                                                   GdkEventKey       *event);
152 static void gtk_widget_style_set                 (GtkWidget         *widget,
153                                                   GtkStyle          *previous_style);
154 static void gtk_widget_real_grab_focus           (GtkWidget         *focus_widget);
155
156 static void  gtk_widget_redraw_queue_remove       (GtkWidget         *widget);
157
158      
159 static GdkColormap* gtk_widget_peek_colormap (void);
160 static GdkVisual*   gtk_widget_peek_visual   (void);
161 static GtkStyle*    gtk_widget_peek_style    (void);
162
163 static void gtk_widget_reparent_container_child  (GtkWidget     *widget,
164                                                   gpointer       client_data);
165 static void gtk_widget_propagate_state           (GtkWidget     *widget,
166                                                   GtkStateData  *data);
167 static void gtk_widget_set_style_internal        (GtkWidget     *widget,
168                                                   GtkStyle      *style,
169                                                   gboolean       initial_emission);
170 static void gtk_widget_set_style_recurse         (GtkWidget     *widget,
171                                                   gpointer       client_data);
172
173 static GtkWidgetAuxInfo* gtk_widget_aux_info_new     (void);
174 static void              gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info);
175
176 static GtkObjectClass *parent_class = NULL;
177 static guint widget_signals[LAST_SIGNAL] = { 0 };
178
179 static GMemChunk *aux_info_mem_chunk = NULL;
180
181 static GdkColormap *default_colormap = NULL;
182 static GdkVisual *default_visual = NULL;
183 static GtkStyle *gtk_default_style = NULL;
184
185 static GSList *colormap_stack = NULL;
186 static GSList *visual_stack = NULL;
187 static GSList *style_stack = NULL;
188 static guint   composite_child_stack = 0;
189 static GSList *gtk_widget_redraw_queue = NULL;
190
191 static const gchar *aux_info_key = "gtk-aux-info";
192 static guint        aux_info_key_id = 0;
193 static const gchar *event_key = "gtk-event-mask";
194 static guint        event_key_id = 0;
195 static const gchar *extension_event_key = "gtk-extension-event-mode";
196 static guint        extension_event_key_id = 0;
197 static const gchar *parent_window_key = "gtk-parent-window";
198 static guint        parent_window_key_id = 0;
199 static const gchar *saved_default_style_key = "gtk-saved-default-style";
200 static guint        saved_default_style_key_id = 0;
201 static const gchar *shape_info_key = "gtk-shape-info";
202 static const gchar *colormap_key = "gtk-colormap";
203 static const gchar *visual_key = "gtk-visual";
204
205 static const gchar *rc_style_key = "gtk-rc-style";
206 static guint        rc_style_key_id = 0;
207
208 /*****************************************
209  * gtk_widget_get_type:
210  *
211  *   arguments:
212  *
213  *   results:
214  *****************************************/
215
216 GtkType
217 gtk_widget_get_type (void)
218 {
219   static GtkType widget_type = 0;
220   
221   if (!widget_type)
222     {
223       static const GtkTypeInfo widget_info =
224       {
225         "GtkWidget",
226         sizeof (GtkWidget),
227         sizeof (GtkWidgetClass),
228         (GtkClassInitFunc) gtk_widget_class_init,
229         (GtkObjectInitFunc) gtk_widget_init,
230         /* reserved_1 */ NULL,
231         /* reserved_2 */ NULL,
232         (GtkClassInitFunc) NULL,
233       };
234       
235       widget_type = gtk_type_unique (gtk_object_get_type (), &widget_info);
236     }
237   
238   return widget_type;
239 }
240
241 /*****************************************
242  * gtk_widget_class_init:
243  *
244  *   arguments:
245  *
246  *   results:
247  *****************************************/
248 #include "stdio.h"
249 static void
250 gtk_widget_debug_msg (GtkWidget          *widget,
251                       const gchar        *string)
252 {
253   fprintf (stderr, "Gtk-DEBUG: %s\n", string);
254 }
255
256 static void
257 gtk_widget_class_init (GtkWidgetClass *klass)
258 {
259   GtkObjectClass *object_class;
260   
261   object_class = (GtkObjectClass*) klass;
262   
263   parent_class = gtk_type_class (gtk_object_get_type ());
264   
265   gtk_object_add_arg_type ("GtkWidget::name", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_NAME);
266   gtk_object_add_arg_type ("GtkWidget::parent", GTK_TYPE_CONTAINER, GTK_ARG_READWRITE, ARG_PARENT);
267   gtk_object_add_arg_type ("GtkWidget::x", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_X);
268   gtk_object_add_arg_type ("GtkWidget::y", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_Y);
269   gtk_object_add_arg_type ("GtkWidget::width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_WIDTH);
270   gtk_object_add_arg_type ("GtkWidget::height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_HEIGHT);
271   gtk_object_add_arg_type ("GtkWidget::visible", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBLE);
272   gtk_object_add_arg_type ("GtkWidget::sensitive", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SENSITIVE);
273   gtk_object_add_arg_type ("GtkWidget::can_focus", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CAN_FOCUS);
274   gtk_object_add_arg_type ("GtkWidget::has_focus", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HAS_FOCUS);
275   gtk_object_add_arg_type ("GtkWidget::can_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CAN_DEFAULT);
276   gtk_object_add_arg_type ("GtkWidget::has_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HAS_DEFAULT);
277   gtk_object_add_arg_type ("GtkWidget::composite_child", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_COMPOSITE_CHILD);
278   gtk_object_add_arg_type ("GtkWidget::style", GTK_TYPE_STYLE, GTK_ARG_READWRITE, ARG_STYLE);
279   gtk_object_add_arg_type ("GtkWidget::events", GTK_TYPE_GDK_EVENT_MASK, GTK_ARG_READWRITE, ARG_EVENTS);
280   gtk_object_add_arg_type ("GtkWidget::extension_events", GTK_TYPE_GDK_EVENT_MASK, GTK_ARG_READWRITE, ARG_EXTENSION_EVENTS);
281   
282   widget_signals[SHOW] =
283     gtk_signal_new ("show",
284                     GTK_RUN_FIRST,
285                     object_class->type,
286                     GTK_SIGNAL_OFFSET (GtkWidgetClass, show),
287                     gtk_marshal_NONE__NONE,
288                     GTK_TYPE_NONE, 0);
289   widget_signals[HIDE] =
290     gtk_signal_new ("hide",
291                     GTK_RUN_FIRST,
292                     object_class->type,
293                     GTK_SIGNAL_OFFSET (GtkWidgetClass, hide),
294                     gtk_marshal_NONE__NONE,
295                     GTK_TYPE_NONE, 0);
296   widget_signals[MAP] =
297     gtk_signal_new ("map",
298                     GTK_RUN_FIRST,
299                     object_class->type,
300                     GTK_SIGNAL_OFFSET (GtkWidgetClass, map),
301                     gtk_marshal_NONE__NONE,
302                     GTK_TYPE_NONE, 0);
303   widget_signals[UNMAP] =
304     gtk_signal_new ("unmap",
305                     GTK_RUN_FIRST,
306                     object_class->type,
307                     GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap),
308                     gtk_marshal_NONE__NONE,
309                     GTK_TYPE_NONE, 0);
310   widget_signals[REALIZE] =
311     gtk_signal_new ("realize",
312                     GTK_RUN_FIRST,
313                     object_class->type,
314                     GTK_SIGNAL_OFFSET (GtkWidgetClass, realize),
315                     gtk_marshal_NONE__NONE,
316                     GTK_TYPE_NONE, 0);
317   widget_signals[UNREALIZE] =
318     gtk_signal_new ("unrealize",
319                     GTK_RUN_FIRST,
320                     object_class->type,
321                     GTK_SIGNAL_OFFSET (GtkWidgetClass, unrealize),
322                     gtk_marshal_NONE__NONE,
323                     GTK_TYPE_NONE, 0);
324   widget_signals[DRAW] =
325     gtk_signal_new ("draw",
326                     GTK_RUN_FIRST,
327                     object_class->type,
328                     GTK_SIGNAL_OFFSET (GtkWidgetClass, draw),
329                     gtk_marshal_NONE__POINTER,
330                     GTK_TYPE_NONE, 1,
331                     GTK_TYPE_POINTER);
332   widget_signals[DRAW_FOCUS] =
333     gtk_signal_new ("draw_focus",
334                     GTK_RUN_FIRST,
335                     object_class->type,
336                     GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_focus),
337                     gtk_marshal_NONE__NONE,
338                     GTK_TYPE_NONE, 0);
339   widget_signals[DRAW_DEFAULT] =
340     gtk_signal_new ("draw_default",
341                     GTK_RUN_FIRST,
342                     object_class->type,
343                     GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_default),
344                     gtk_marshal_NONE__NONE,
345                     GTK_TYPE_NONE, 0);
346   widget_signals[SIZE_REQUEST] =
347     gtk_signal_new ("size_request",
348                     GTK_RUN_FIRST,
349                     object_class->type,
350                     GTK_SIGNAL_OFFSET (GtkWidgetClass, size_request),
351                     gtk_marshal_NONE__POINTER,
352                     GTK_TYPE_NONE, 1,
353                     GTK_TYPE_POINTER);
354   widget_signals[SIZE_ALLOCATE] =
355     gtk_signal_new ("size_allocate",
356                     GTK_RUN_FIRST,
357                     object_class->type,
358                     GTK_SIGNAL_OFFSET (GtkWidgetClass, size_allocate),
359                     gtk_marshal_NONE__POINTER,
360                     GTK_TYPE_NONE, 1,
361                     GTK_TYPE_POINTER);
362   widget_signals[STATE_CHANGED] =
363     gtk_signal_new ("state_changed",
364                     GTK_RUN_FIRST,
365                     object_class->type,
366                     GTK_SIGNAL_OFFSET (GtkWidgetClass, state_changed),
367                     gtk_marshal_NONE__UINT,
368                     GTK_TYPE_NONE, 1,
369                     GTK_TYPE_STATE_TYPE);
370   widget_signals[PARENT_SET] =
371     gtk_signal_new ("parent_set",
372                     GTK_RUN_FIRST,
373                     object_class->type,
374                     GTK_SIGNAL_OFFSET (GtkWidgetClass, parent_set),
375                     gtk_marshal_NONE__OBJECT,
376                     GTK_TYPE_NONE, 1,
377                     GTK_TYPE_OBJECT);
378   widget_signals[STYLE_SET] =
379     gtk_signal_new ("style_set",
380                     GTK_RUN_FIRST,
381                     object_class->type,
382                     GTK_SIGNAL_OFFSET (GtkWidgetClass, style_set),
383                     gtk_marshal_NONE__POINTER,
384                     GTK_TYPE_NONE, 1,
385                     GTK_TYPE_STYLE);
386   widget_signals[ADD_ACCELERATOR] =
387     gtk_accel_group_create_add (object_class->type, GTK_RUN_LAST,
388                                 GTK_SIGNAL_OFFSET (GtkWidgetClass, add_accelerator));
389   widget_signals[REMOVE_ACCELERATOR] =
390     gtk_accel_group_create_remove (object_class->type, GTK_RUN_LAST,
391                                    GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator));
392   widget_signals[GRAB_FOCUS] =
393     gtk_signal_new ("grab_focus",
394                     GTK_RUN_LAST | GTK_RUN_ACTION,
395                     object_class->type,
396                     GTK_SIGNAL_OFFSET (GtkWidgetClass, grab_focus),
397                     gtk_marshal_NONE__NONE,
398                     GTK_TYPE_NONE, 0);
399   widget_signals[EVENT] =
400     gtk_signal_new ("event",
401                     GTK_RUN_LAST,
402                     object_class->type,
403                     GTK_SIGNAL_OFFSET (GtkWidgetClass, event),
404                     gtk_marshal_BOOL__POINTER,
405                     GTK_TYPE_BOOL, 1,
406                     GTK_TYPE_GDK_EVENT);
407   widget_signals[BUTTON_PRESS_EVENT] =
408     gtk_signal_new ("button_press_event",
409                     GTK_RUN_LAST,
410                     object_class->type,
411                     GTK_SIGNAL_OFFSET (GtkWidgetClass, button_press_event),
412                     gtk_marshal_BOOL__POINTER,
413                     GTK_TYPE_BOOL, 1,
414                     GTK_TYPE_GDK_EVENT);
415   widget_signals[BUTTON_RELEASE_EVENT] =
416     gtk_signal_new ("button_release_event",
417                     GTK_RUN_LAST,
418                     object_class->type,
419                     GTK_SIGNAL_OFFSET (GtkWidgetClass, button_release_event),
420                     gtk_marshal_BOOL__POINTER,
421                     GTK_TYPE_BOOL, 1,
422                     GTK_TYPE_GDK_EVENT);
423   widget_signals[MOTION_NOTIFY_EVENT] =
424     gtk_signal_new ("motion_notify_event",
425                     GTK_RUN_LAST,
426                     object_class->type,
427                     GTK_SIGNAL_OFFSET (GtkWidgetClass, motion_notify_event),
428                     gtk_marshal_BOOL__POINTER,
429                     GTK_TYPE_BOOL, 1,
430                     GTK_TYPE_GDK_EVENT);
431   widget_signals[DELETE_EVENT] =
432     gtk_signal_new ("delete_event",
433                     GTK_RUN_LAST,
434                     object_class->type,
435                     GTK_SIGNAL_OFFSET (GtkWidgetClass, delete_event),
436                     gtk_marshal_BOOL__POINTER,
437                     GTK_TYPE_BOOL, 1,
438                     GTK_TYPE_GDK_EVENT);
439   widget_signals[DESTROY_EVENT] =
440     gtk_signal_new ("destroy_event",
441                     GTK_RUN_LAST,
442                     object_class->type,
443                     GTK_SIGNAL_OFFSET (GtkWidgetClass, destroy_event),
444                     gtk_marshal_BOOL__POINTER,
445                     GTK_TYPE_BOOL, 1,
446                     GTK_TYPE_GDK_EVENT);
447   widget_signals[EXPOSE_EVENT] =
448     gtk_signal_new ("expose_event",
449                     GTK_RUN_LAST,
450                     object_class->type,
451                     GTK_SIGNAL_OFFSET (GtkWidgetClass, expose_event),
452                     gtk_marshal_BOOL__POINTER,
453                     GTK_TYPE_BOOL, 1,
454                     GTK_TYPE_GDK_EVENT);
455   widget_signals[KEY_PRESS_EVENT] =
456     gtk_signal_new ("key_press_event",
457                     GTK_RUN_LAST,
458                     object_class->type,
459                     GTK_SIGNAL_OFFSET (GtkWidgetClass, key_press_event),
460                     gtk_marshal_BOOL__POINTER,
461                     GTK_TYPE_BOOL, 1,
462                     GTK_TYPE_GDK_EVENT);
463   widget_signals[KEY_RELEASE_EVENT] =
464     gtk_signal_new ("key_release_event",
465                     GTK_RUN_LAST,
466                     object_class->type,
467                     GTK_SIGNAL_OFFSET (GtkWidgetClass, key_release_event),
468                     gtk_marshal_BOOL__POINTER,
469                     GTK_TYPE_BOOL, 1,
470                     GTK_TYPE_GDK_EVENT);
471   widget_signals[ENTER_NOTIFY_EVENT] =
472     gtk_signal_new ("enter_notify_event",
473                     GTK_RUN_LAST,
474                     object_class->type,
475                     GTK_SIGNAL_OFFSET (GtkWidgetClass, enter_notify_event),
476                     gtk_marshal_BOOL__POINTER,
477                     GTK_TYPE_BOOL, 1,
478                     GTK_TYPE_GDK_EVENT);
479   widget_signals[LEAVE_NOTIFY_EVENT] =
480     gtk_signal_new ("leave_notify_event",
481                     GTK_RUN_LAST,
482                     object_class->type,
483                     GTK_SIGNAL_OFFSET (GtkWidgetClass, leave_notify_event),
484                     gtk_marshal_BOOL__POINTER,
485                     GTK_TYPE_BOOL, 1,
486                     GTK_TYPE_GDK_EVENT);
487   widget_signals[CONFIGURE_EVENT] =
488     gtk_signal_new ("configure_event",
489                     GTK_RUN_LAST,
490                     object_class->type,
491                     GTK_SIGNAL_OFFSET (GtkWidgetClass, configure_event),
492                     gtk_marshal_BOOL__POINTER,
493                     GTK_TYPE_BOOL, 1,
494                     GTK_TYPE_GDK_EVENT);
495   widget_signals[FOCUS_IN_EVENT] =
496     gtk_signal_new ("focus_in_event",
497                     GTK_RUN_LAST,
498                     object_class->type,
499                     GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_in_event),
500                     gtk_marshal_BOOL__POINTER,
501                     GTK_TYPE_BOOL, 1,
502                     GTK_TYPE_GDK_EVENT);
503   widget_signals[FOCUS_OUT_EVENT] =
504     gtk_signal_new ("focus_out_event",
505                     GTK_RUN_LAST,
506                     object_class->type,
507                     GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_out_event),
508                     gtk_marshal_BOOL__POINTER,
509                     GTK_TYPE_BOOL, 1,
510                     GTK_TYPE_GDK_EVENT);
511   widget_signals[MAP_EVENT] =
512     gtk_signal_new ("map_event",
513                     GTK_RUN_LAST,
514                     object_class->type,
515                     GTK_SIGNAL_OFFSET (GtkWidgetClass, map_event),
516                     gtk_marshal_BOOL__POINTER,
517                     GTK_TYPE_BOOL, 1,
518                     GTK_TYPE_GDK_EVENT);
519   widget_signals[UNMAP_EVENT] =
520     gtk_signal_new ("unmap_event",
521                     GTK_RUN_LAST,
522                     object_class->type,
523                     GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap_event),
524                     gtk_marshal_BOOL__POINTER,
525                     GTK_TYPE_BOOL, 1,
526                     GTK_TYPE_GDK_EVENT);
527   widget_signals[PROPERTY_NOTIFY_EVENT] =
528     gtk_signal_new ("property_notify_event",
529                     GTK_RUN_LAST,
530                     object_class->type,
531                     GTK_SIGNAL_OFFSET (GtkWidgetClass, property_notify_event),
532                     gtk_marshal_BOOL__POINTER,
533                     GTK_TYPE_BOOL, 1,
534                     GTK_TYPE_GDK_EVENT);
535   widget_signals[SELECTION_CLEAR_EVENT] =
536     gtk_signal_new ("selection_clear_event",
537                     GTK_RUN_LAST,
538                     object_class->type,
539                     GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_clear_event),
540                     gtk_marshal_BOOL__POINTER,
541                     GTK_TYPE_BOOL, 1,
542                     GTK_TYPE_GDK_EVENT);
543   widget_signals[SELECTION_REQUEST_EVENT] =
544     gtk_signal_new ("selection_request_event",
545                     GTK_RUN_LAST,
546                     object_class->type,
547                     GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_request_event),
548                     gtk_marshal_BOOL__POINTER,
549                     GTK_TYPE_BOOL, 1,
550                     GTK_TYPE_GDK_EVENT);
551   widget_signals[SELECTION_NOTIFY_EVENT] =
552     gtk_signal_new ("selection_notify_event",
553                     GTK_RUN_LAST,
554                     object_class->type,
555                     GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_notify_event),
556                     gtk_marshal_BOOL__POINTER,
557                     GTK_TYPE_BOOL, 1,
558                     GTK_TYPE_GDK_EVENT);
559   widget_signals[SELECTION_RECEIVED] =
560     gtk_signal_new ("selection_received",
561                     GTK_RUN_LAST,
562                     object_class->type,
563                     GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_received),
564                     gtk_marshal_NONE__POINTER_UINT,
565                     GTK_TYPE_NONE, 2,
566                     GTK_TYPE_SELECTION_DATA,
567                     GTK_TYPE_UINT);
568   widget_signals[SELECTION_GET] =
569     gtk_signal_new ("selection_get",
570                     GTK_RUN_LAST,
571                     object_class->type,
572                     GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_get),
573                     gtk_marshal_NONE__POINTER_UINT_UINT,
574                     GTK_TYPE_NONE, 2,
575                     GTK_TYPE_SELECTION_DATA,
576                     GTK_TYPE_UINT,
577                     GTK_TYPE_UINT);
578   widget_signals[PROXIMITY_IN_EVENT] =
579     gtk_signal_new ("proximity_in_event",
580                     GTK_RUN_LAST,
581                     object_class->type,
582                     GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_in_event),
583                     gtk_marshal_BOOL__POINTER,
584                     GTK_TYPE_BOOL, 1,
585                     GTK_TYPE_GDK_EVENT);
586   widget_signals[PROXIMITY_OUT_EVENT] =
587     gtk_signal_new ("proximity_out_event",
588                     GTK_RUN_LAST,
589                     object_class->type,
590                     GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_out_event),
591                     gtk_marshal_BOOL__POINTER,
592                     GTK_TYPE_BOOL, 1,
593                     GTK_TYPE_GDK_EVENT);
594   widget_signals[DRAG_LEAVE] =
595     gtk_signal_new ("drag_leave",
596                     GTK_RUN_LAST,
597                     object_class->type,
598                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_leave),
599                     gtk_marshal_NONE__POINTER_UINT,
600                     GTK_TYPE_NONE, 2,
601                     GTK_TYPE_GDK_DRAG_CONTEXT,
602                     GTK_TYPE_UINT);
603   widget_signals[DRAG_BEGIN] =
604     gtk_signal_new ("drag_begin",
605                     GTK_RUN_LAST,
606                     object_class->type,
607                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_begin),
608                     gtk_marshal_NONE__POINTER,
609                     GTK_TYPE_NONE, 1,
610                     GTK_TYPE_GDK_DRAG_CONTEXT);
611   widget_signals[DRAG_END] =
612     gtk_signal_new ("drag_end",
613                     GTK_RUN_LAST,
614                     object_class->type,
615                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_end),
616                     gtk_marshal_NONE__POINTER,
617                     GTK_TYPE_NONE, 1,
618                     GTK_TYPE_GDK_DRAG_CONTEXT);
619   widget_signals[DRAG_DATA_DELETE] =
620     gtk_signal_new ("drag_data_delete",
621                     GTK_RUN_LAST,
622                     object_class->type,
623                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_delete),
624                     gtk_marshal_NONE__POINTER,
625                     GTK_TYPE_NONE, 1,
626                     GTK_TYPE_GDK_DRAG_CONTEXT);
627   widget_signals[DRAG_MOTION] =
628     gtk_signal_new ("drag_motion",
629                     GTK_RUN_LAST,
630                     object_class->type,
631                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_motion),
632                     gtk_marshal_BOOL__POINTER_INT_INT_UINT,
633                     GTK_TYPE_BOOL, 4,
634                     GTK_TYPE_GDK_DRAG_CONTEXT,
635                     GTK_TYPE_INT,
636                     GTK_TYPE_INT,
637                     GTK_TYPE_UINT);
638   widget_signals[DRAG_DROP] =
639     gtk_signal_new ("drag_drop",
640                     GTK_RUN_LAST,
641                     object_class->type,
642                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_drop),
643                     gtk_marshal_BOOL__POINTER_INT_INT_UINT,
644                     GTK_TYPE_BOOL, 4,
645                     GTK_TYPE_GDK_DRAG_CONTEXT,
646                     GTK_TYPE_INT,
647                     GTK_TYPE_INT,
648                     GTK_TYPE_UINT);
649   widget_signals[DRAG_DATA_GET] =
650     gtk_signal_new ("drag_data_get",
651                     GTK_RUN_LAST,
652                     object_class->type,
653                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_get),
654                     gtk_marshal_NONE__POINTER_POINTER_UINT_UINT,
655                     GTK_TYPE_NONE, 4,
656                     GTK_TYPE_GDK_DRAG_CONTEXT,
657                     GTK_TYPE_SELECTION_DATA,
658                     GTK_TYPE_UINT,
659                     GTK_TYPE_UINT);
660   widget_signals[DRAG_DATA_RECEIVED] =
661     gtk_signal_new ("drag_data_received",
662                     GTK_RUN_LAST,
663                     object_class->type,
664                     GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_received),
665                     gtk_marshal_NONE__POINTER_INT_INT_POINTER_UINT_UINT,
666                     GTK_TYPE_NONE, 6,
667                     GTK_TYPE_GDK_DRAG_CONTEXT,
668                     GTK_TYPE_INT,
669                     GTK_TYPE_INT,
670                     GTK_TYPE_SELECTION_DATA,
671                     GTK_TYPE_UINT,
672                     GTK_TYPE_UINT);
673   widget_signals[VISIBILITY_NOTIFY_EVENT] =
674     gtk_signal_new ("visibility_notify_event",
675                     GTK_RUN_LAST,
676                     object_class->type,
677                     GTK_SIGNAL_OFFSET (GtkWidgetClass, visibility_notify_event),
678                     gtk_marshal_BOOL__POINTER,
679                     GTK_TYPE_BOOL, 1,
680                     GTK_TYPE_GDK_EVENT);
681   widget_signals[CLIENT_EVENT] =
682     gtk_signal_new ("client_event",
683                     GTK_RUN_LAST,
684                     object_class->type,
685                     GTK_SIGNAL_OFFSET (GtkWidgetClass, client_event),
686                     gtk_marshal_BOOL__POINTER,
687                     GTK_TYPE_BOOL, 1,
688                     GTK_TYPE_GDK_EVENT);
689   widget_signals[NO_EXPOSE_EVENT] =
690     gtk_signal_new ("no_expose_event",
691                     GTK_RUN_LAST,
692                     object_class->type,
693                     GTK_SIGNAL_OFFSET (GtkWidgetClass, no_expose_event),
694                     gtk_marshal_BOOL__POINTER,
695                     GTK_TYPE_BOOL, 1,
696                     GTK_TYPE_GDK_EVENT);
697   widget_signals[DEBUG_MSG] =
698     gtk_signal_new ("debug_msg",
699                     GTK_RUN_LAST | GTK_RUN_ACTION,
700                     object_class->type,
701                     GTK_SIGNAL_OFFSET (GtkWidgetClass, debug_msg),
702                     gtk_marshal_NONE__STRING,
703                     GTK_TYPE_NONE, 1,
704                     GTK_TYPE_STRING);
705
706   gtk_object_class_add_signals (object_class, widget_signals, LAST_SIGNAL);
707
708   object_class->set_arg = gtk_widget_set_arg;
709   object_class->get_arg = gtk_widget_get_arg;
710   object_class->shutdown = gtk_widget_shutdown;
711   object_class->destroy = gtk_widget_real_destroy;
712   object_class->finalize = gtk_widget_finalize;
713   
714   klass->activate_signal = 0;
715   klass->set_scroll_adjustments_signal = 0;
716   klass->show = gtk_widget_real_show;
717   klass->show_all = gtk_widget_show;
718   klass->hide = gtk_widget_real_hide;
719   klass->hide_all = gtk_widget_hide;
720   klass->map = gtk_widget_real_map;
721   klass->unmap = gtk_widget_real_unmap;
722   klass->realize = gtk_widget_real_realize;
723   klass->unrealize = gtk_widget_real_unrealize;
724   klass->draw = gtk_widget_real_draw;
725   klass->draw_focus = NULL;
726   klass->size_request = gtk_widget_real_size_request;
727   klass->size_allocate = gtk_widget_real_size_allocate;
728   klass->state_changed = NULL;
729   klass->parent_set = NULL;
730   klass->style_set = gtk_widget_style_set;
731   klass->add_accelerator = (void*) gtk_accel_group_handle_add;
732   klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
733   klass->grab_focus = gtk_widget_real_grab_focus;
734   klass->event = NULL;
735   klass->button_press_event = NULL;
736   klass->button_release_event = NULL;
737   klass->motion_notify_event = NULL;
738   klass->delete_event = NULL;
739   klass->destroy_event = NULL;
740   klass->expose_event = NULL;
741   klass->key_press_event = gtk_widget_real_key_press_event;
742   klass->key_release_event = gtk_widget_real_key_release_event;
743   klass->enter_notify_event = NULL;
744   klass->leave_notify_event = NULL;
745   klass->configure_event = NULL;
746   klass->focus_in_event = NULL;
747   klass->focus_out_event = NULL;
748   klass->map_event = NULL;
749   klass->unmap_event = NULL;
750   klass->property_notify_event = gtk_selection_property_notify;
751   klass->selection_clear_event = gtk_selection_clear;
752   klass->selection_request_event = gtk_selection_request;
753   klass->selection_notify_event = gtk_selection_notify;
754   klass->selection_received = NULL;
755   klass->proximity_in_event = NULL;
756   klass->proximity_out_event = NULL;
757   klass->drag_begin = NULL;
758   klass->drag_end = NULL;
759   klass->drag_data_delete = NULL;
760   klass->drag_leave = NULL;
761   klass->drag_motion = NULL;
762   klass->drag_drop = NULL;
763   klass->drag_data_received = NULL;
764
765   klass->no_expose_event = NULL;
766
767   klass->debug_msg = gtk_widget_debug_msg;
768 }
769
770 static void
771 gtk_widget_set_arg (GtkObject   *object,
772                     GtkArg      *arg,
773                     guint        arg_id)
774 {
775   GtkWidget *widget;
776
777   widget = GTK_WIDGET (object);
778
779   switch (arg_id)
780     {
781       guint32 saved_flags;
782       
783     case ARG_NAME:
784       gtk_widget_set_name (widget, GTK_VALUE_STRING (*arg));
785       break;
786     case ARG_PARENT:
787       gtk_container_add (GTK_CONTAINER (GTK_VALUE_OBJECT (*arg)), widget);
788       break;
789     case ARG_X:
790       gtk_widget_set_uposition (widget, GTK_VALUE_INT (*arg), -2);
791       break;
792     case ARG_Y:
793       gtk_widget_set_uposition (widget, -2, GTK_VALUE_INT (*arg));
794       break;
795     case ARG_WIDTH:
796       gtk_widget_set_usize (widget, GTK_VALUE_INT (*arg), -2);
797       break;
798     case ARG_HEIGHT:
799       gtk_widget_set_usize (widget, -2, GTK_VALUE_INT (*arg));
800       break;
801     case ARG_VISIBLE:
802       if (GTK_VALUE_BOOL(*arg))
803         gtk_widget_show (widget);
804       else
805         gtk_widget_hide (widget);
806       break;
807     case ARG_SENSITIVE:
808       gtk_widget_set_sensitive (widget, GTK_VALUE_BOOL (*arg));
809       break;
810     case ARG_CAN_FOCUS:
811       saved_flags = GTK_WIDGET_FLAGS (widget);
812       if (GTK_VALUE_BOOL (*arg))
813         GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
814       else
815         GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
816       if (saved_flags != GTK_WIDGET_FLAGS (widget))
817         gtk_widget_queue_resize (widget);
818       break;
819     case ARG_HAS_FOCUS:
820       if (GTK_VALUE_BOOL (*arg))
821         gtk_widget_grab_focus (widget);
822       break;
823     case ARG_CAN_DEFAULT:
824       saved_flags = GTK_WIDGET_FLAGS (widget);
825       if (GTK_VALUE_BOOL (*arg))
826         GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT);
827       else
828         GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_DEFAULT);
829       if (saved_flags != GTK_WIDGET_FLAGS (widget))
830         gtk_widget_queue_resize (widget);
831       break;
832     case ARG_HAS_DEFAULT:
833       if (GTK_VALUE_BOOL (*arg))
834         gtk_widget_grab_default (widget);
835       break;
836     case ARG_COMPOSITE_CHILD:
837       if (GTK_VALUE_BOOL(*arg))
838         GTK_WIDGET_SET_FLAGS (widget, GTK_COMPOSITE_CHILD);
839       else
840         GTK_WIDGET_UNSET_FLAGS (widget, GTK_COMPOSITE_CHILD);
841       break;
842     case ARG_STYLE:
843       gtk_widget_set_style (widget, (GtkStyle*) GTK_VALUE_BOXED (*arg));
844       break;
845     case ARG_EVENTS:
846       if (!GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_NO_WINDOW (widget))
847         gtk_widget_set_events (widget, GTK_VALUE_FLAGS (*arg));
848       break;
849     case ARG_EXTENSION_EVENTS:
850       gtk_widget_set_extension_events (widget, GTK_VALUE_FLAGS (*arg));
851       break;
852     default:
853       break;
854     }
855 }
856
857 /*****************************************
858  * gtk_widget_get_arg:
859  *
860  *   arguments:
861  *
862  *   results:
863  *****************************************/
864
865 static void
866 gtk_widget_get_arg (GtkObject   *object,
867                     GtkArg      *arg,
868                     guint        arg_id)
869 {
870   GtkWidget *widget;
871
872   widget = GTK_WIDGET (object);
873   
874   switch (arg_id)
875     {
876       GtkWidgetAuxInfo *aux_info;
877       gint *eventp;
878       GdkExtensionMode *modep;
879
880     case ARG_NAME:
881       if (widget->name)
882         GTK_VALUE_STRING (*arg) = g_strdup (widget->name);
883       else
884         GTK_VALUE_STRING (*arg) = g_strdup ("");
885       break;
886     case ARG_PARENT:
887       GTK_VALUE_OBJECT (*arg) = (GtkObject*) widget->parent;
888       break;
889     case ARG_X:
890       aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
891       if (!aux_info)
892         GTK_VALUE_INT (*arg) = -1;
893       else
894         GTK_VALUE_INT (*arg) = aux_info->x;
895       break;
896     case ARG_Y:
897       aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
898       if (!aux_info)
899         GTK_VALUE_INT (*arg) = -1;
900       else
901         GTK_VALUE_INT (*arg) = aux_info->y;
902       break;
903     case ARG_WIDTH:
904       aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
905       if (!aux_info)
906         GTK_VALUE_INT (*arg) = -1;
907       else
908         GTK_VALUE_INT (*arg) = aux_info->width;
909       break;
910     case ARG_HEIGHT:
911       aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
912       if (!aux_info)
913         GTK_VALUE_INT (*arg) = -1;
914       else
915         GTK_VALUE_INT (*arg) = aux_info->height;
916       break;
917     case ARG_VISIBLE:
918       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_VISIBLE (widget) != FALSE);
919       break;
920     case ARG_SENSITIVE:
921       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_SENSITIVE (widget) != FALSE);
922       break;
923     case ARG_CAN_FOCUS:
924       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_CAN_FOCUS (widget) != FALSE);
925       break;
926     case ARG_HAS_FOCUS:
927       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_HAS_FOCUS (widget) != FALSE);
928       break;
929     case ARG_CAN_DEFAULT:
930       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_CAN_DEFAULT (widget) != FALSE);
931       break;
932     case ARG_HAS_DEFAULT:
933       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_HAS_DEFAULT (widget) != FALSE);
934       break;
935     case ARG_COMPOSITE_CHILD:
936       GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_COMPOSITE_CHILD (widget) != FALSE);
937       break;
938     case ARG_STYLE:
939       GTK_VALUE_BOXED (*arg) = (gpointer) gtk_widget_get_style (widget);
940       break;
941     case ARG_EVENTS:
942       eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id);
943       if (!eventp)
944         GTK_VALUE_FLAGS (*arg) = 0;
945       else
946         GTK_VALUE_FLAGS (*arg) = *eventp;
947       break;
948     case ARG_EXTENSION_EVENTS:
949       modep = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id);
950       if (!modep)
951         GTK_VALUE_FLAGS (*arg) = 0;
952       else
953         GTK_VALUE_FLAGS (*arg) = *modep;
954       break;
955     default:
956       arg->type = GTK_TYPE_INVALID;
957       break;
958     }
959 }
960
961 /*****************************************
962  * gtk_widget_init:
963  *
964  *   arguments:
965  *
966  *   results:
967  *****************************************/
968
969 static void
970 gtk_widget_init (GtkWidget *widget)
971 {
972   GdkColormap *colormap;
973   GdkVisual *visual;
974   
975   GTK_PRIVATE_FLAGS (widget) = 0;
976   widget->state = GTK_STATE_NORMAL;
977   widget->saved_state = GTK_STATE_NORMAL;
978   widget->name = NULL;
979   widget->requisition.width = 0;
980   widget->requisition.height = 0;
981   widget->allocation.x = -1;
982   widget->allocation.y = -1;
983   widget->allocation.width = 1;
984   widget->allocation.height = 1;
985   widget->window = NULL;
986   widget->parent = NULL;
987
988   GTK_WIDGET_SET_FLAGS (widget,
989                         GTK_SENSITIVE |
990                         GTK_PARENT_SENSITIVE |
991                         (composite_child_stack ? GTK_COMPOSITE_CHILD : 0));
992
993   widget->style = gtk_widget_peek_style ();
994   gtk_style_ref (widget->style);
995   
996   colormap = gtk_widget_peek_colormap ();
997   visual = gtk_widget_peek_visual ();
998   
999   /* XXX - should we ref the colormap and visual, too? */
1000
1001   if (colormap != gtk_widget_get_default_colormap ())
1002     {
1003       /* gdk_colormap_ref (colormap); */
1004       gtk_object_set_data (GTK_OBJECT (widget), colormap_key, colormap);
1005     }
1006
1007   if (visual != gtk_widget_get_default_visual ())
1008     {
1009       /* gdk_visual_ref (visual); */
1010       gtk_object_set_data (GTK_OBJECT (widget), visual_key, visual);
1011     }
1012 }
1013
1014 /*****************************************
1015  * gtk_widget_new:
1016  *
1017  *   arguments:
1018  *
1019  *   results:
1020  *****************************************/
1021
1022 GtkWidget*
1023 gtk_widget_new (GtkType      widget_type,
1024                 const gchar *first_arg_name,
1025                 ...)
1026 {
1027   GtkObject *object;
1028   va_list var_args;
1029   GSList *arg_list = NULL;
1030   GSList *info_list = NULL;
1031   gchar *error;
1032   
1033   g_return_val_if_fail (gtk_type_is_a (widget_type, GTK_TYPE_WIDGET), NULL);
1034   
1035   object = gtk_type_new (widget_type);
1036   
1037   va_start (var_args, first_arg_name);
1038   error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
1039                                    &arg_list,
1040                                    &info_list,
1041                                    first_arg_name,
1042                                    var_args);
1043   va_end (var_args);
1044   
1045   if (error)
1046     {
1047       g_warning ("gtk_widget_new(): %s", error);
1048       g_free (error);
1049     }
1050   else
1051     {
1052       GSList *slist_arg;
1053       GSList *slist_info;
1054       
1055       slist_arg = arg_list;
1056       slist_info = info_list;
1057       while (slist_arg)
1058         {
1059           gtk_object_arg_set (object, slist_arg->data, slist_info->data);
1060           slist_arg = slist_arg->next;
1061           slist_info = slist_info->next;
1062         }
1063       gtk_args_collect_cleanup (arg_list, info_list);
1064     }
1065   
1066   if (!GTK_OBJECT_CONSTRUCTED (object))
1067     gtk_object_default_construct (object);
1068
1069   return GTK_WIDGET (object);
1070 }
1071
1072 /*****************************************
1073  * gtk_widget_newv:
1074  *
1075  *   arguments:
1076  *
1077  *   results:
1078  *****************************************/
1079
1080 GtkWidget*
1081 gtk_widget_newv (GtkType type,
1082                  guint   nargs,
1083                  GtkArg *args)
1084 {
1085   g_return_val_if_fail (gtk_type_is_a (type, GTK_TYPE_WIDGET), NULL);
1086   
1087   return GTK_WIDGET (gtk_object_newv (type, nargs, args));
1088 }
1089
1090 /*****************************************
1091  * gtk_widget_get:
1092  *
1093  *   arguments:
1094  *
1095  *   results:
1096  *****************************************/
1097
1098 void
1099 gtk_widget_get (GtkWidget       *widget,
1100                 GtkArg          *arg)
1101 {
1102   g_return_if_fail (widget != NULL);
1103   g_return_if_fail (GTK_IS_WIDGET (widget));
1104   g_return_if_fail (arg != NULL);
1105   
1106   gtk_object_getv (GTK_OBJECT (widget), 1, arg);
1107 }
1108
1109 /*****************************************
1110  * gtk_widget_getv:
1111  *
1112  *   arguments:
1113  *
1114  *   results:
1115  *****************************************/
1116
1117 void
1118 gtk_widget_getv (GtkWidget      *widget,
1119                  guint           nargs,
1120                  GtkArg         *args)
1121 {
1122   g_return_if_fail (widget != NULL);
1123   g_return_if_fail (GTK_IS_WIDGET (widget));
1124
1125   gtk_object_getv (GTK_OBJECT (widget), nargs, args);
1126 }
1127
1128 /*****************************************
1129  * gtk_widget_set:
1130  *
1131  *   arguments:
1132  *
1133  *   results:
1134  *****************************************/
1135
1136 void
1137 gtk_widget_set (GtkWidget   *widget,
1138                 const gchar *first_arg_name,
1139                 ...)
1140 {
1141   GtkObject *object;
1142   va_list var_args;
1143   GSList *arg_list = NULL;
1144   GSList *info_list = NULL;
1145   gchar *error;
1146
1147   g_return_if_fail (widget != NULL);
1148   g_return_if_fail (GTK_IS_WIDGET (widget));
1149
1150   object = GTK_OBJECT (widget);
1151
1152   va_start (var_args, first_arg_name);
1153   error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
1154                                    &arg_list,
1155                                    &info_list,
1156                                    first_arg_name,
1157                                    var_args);
1158   va_end (var_args);
1159
1160   if (error)
1161     {
1162       g_warning ("gtk_widget_set(): %s", error);
1163       g_free (error);
1164     }
1165   else
1166     {
1167       GSList *slist_arg;
1168       GSList *slist_info;
1169
1170       slist_arg = arg_list;
1171       slist_info = info_list;
1172       while (slist_arg)
1173         {
1174           gtk_object_arg_set (object, slist_arg->data, slist_info->data);
1175           slist_arg = slist_arg->next;
1176           slist_info = slist_info->next;
1177         }
1178       gtk_args_collect_cleanup (arg_list, info_list);
1179     }
1180 }
1181
1182 /*****************************************
1183  * gtk_widget_setv:
1184  *
1185  *   arguments:
1186  *
1187  *   results:
1188  *****************************************/
1189
1190 void
1191 gtk_widget_setv (GtkWidget *widget,
1192                  guint      nargs,
1193                  GtkArg    *args)
1194 {
1195   g_return_if_fail (widget != NULL);
1196   g_return_if_fail (GTK_IS_WIDGET (widget));
1197
1198   gtk_object_setv (GTK_OBJECT (widget), nargs, args);
1199 }
1200
1201 /*****************************************
1202  * gtk_widget_unparent:
1203  *   do any cleanup necessary necessary
1204  *   for setting parent = NULL.
1205  *
1206  *   arguments:
1207  *
1208  *   results:
1209  *****************************************/
1210
1211 void
1212 gtk_widget_unparent (GtkWidget *widget)
1213 {
1214   GtkWidget *toplevel;
1215   GtkWidget *old_parent;
1216   
1217   g_return_if_fail (widget != NULL);
1218   g_return_if_fail (GTK_IS_WIDGET (widget));
1219   if (widget->parent == NULL)
1220     return;
1221   
1222   /* keep this function in sync with gtk_menu_detach()
1223    */
1224
1225   /* unset focused and default children properly, this code
1226    * should eventually move into some gtk_window_unparent_branch() or
1227    * similar function.
1228    */
1229   
1230   toplevel = gtk_widget_get_toplevel (widget);
1231   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
1232     {
1233       gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), NULL);
1234
1235       if (GTK_IS_WINDOW (toplevel))
1236         {
1237           GtkWidget *child;
1238       
1239           child = GTK_WINDOW (toplevel)->focus_widget;
1240           
1241           while (child && child != widget)
1242             child = child->parent;
1243           
1244           if (child == widget)
1245             gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
1246         }
1247     }
1248   if (GTK_IS_WINDOW (toplevel))
1249     {
1250       GtkWidget *child;
1251       
1252       child = GTK_WINDOW (toplevel)->default_widget;
1253       
1254       while (child && child != widget)
1255         child = child->parent;
1256       
1257       if (child == widget)
1258         gtk_window_set_default (GTK_WINDOW (toplevel), NULL);
1259     }
1260
1261   if (GTK_WIDGET_REDRAW_PENDING (widget))
1262     gtk_widget_redraw_queue_remove (widget);
1263
1264   if (GTK_IS_RESIZE_CONTAINER (widget))
1265     gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
1266   
1267   /* Remove the widget and all its children from any ->resize_widgets list
1268    * of all the parents in our branch. This code should move into gtkcontainer.c
1269    * somwhen, since we mess around with ->resize_widgets, which is
1270    * actually not of our business.
1271    *
1272    * Two ways to make this prettier:
1273    *   Write a g_slist_conditional_remove (GSList, gboolean (*)(gpointer))
1274    *   Change resize_widgets to a GList
1275    */
1276   toplevel = widget->parent;
1277   while (toplevel)
1278     {
1279       GSList *slist;
1280       GSList *prev;
1281
1282       if (!GTK_CONTAINER (toplevel)->resize_widgets)
1283         {
1284           toplevel = toplevel->parent;
1285           continue;
1286         }
1287
1288       prev = NULL;
1289       slist = GTK_CONTAINER (toplevel)->resize_widgets;
1290       while (slist)
1291         {
1292           GtkWidget *child;
1293           GtkWidget *parent;
1294           GSList *last;
1295
1296           last = slist;
1297           slist = last->next;
1298           child = last->data;
1299           
1300           parent = child;
1301           while (parent && (parent != widget))
1302             parent = parent->parent;
1303           
1304           if (parent == widget)
1305             {
1306               GTK_PRIVATE_UNSET_FLAG (child, GTK_RESIZE_NEEDED);
1307               
1308               if (prev)
1309                 prev->next = slist;
1310               else
1311                 {
1312                   /* it is really messy to have this signal disconnection
1313                    * in gtkwidget.c, the resize_widgets invariants should
1314                    * all be taken care off by gtkcontainer.c exclusively.
1315                    */
1316                   if (!slist)
1317                     gtk_signal_disconnect_by_func (GTK_OBJECT (toplevel),
1318                                                    GTK_SIGNAL_FUNC (gtk_container_clear_resize_widgets),
1319                                                    NULL);
1320                   GTK_CONTAINER (toplevel)->resize_widgets = slist;
1321                 }
1322               
1323               g_slist_free_1 (last);
1324             }
1325           else
1326             prev = last;
1327         }
1328
1329       toplevel = toplevel->parent;
1330     }
1331   if (widget->window &&
1332       GTK_WIDGET_NO_WINDOW (widget) &&
1333       GTK_WIDGET_DRAWABLE (widget))
1334     gtk_widget_queue_clear (widget);
1335
1336   /* Reset the width and height here, to force reallocation if we
1337    * get added back to a new parent. This won't work if our new
1338    * allocation is smaller than 1x1 and we actually want a size of 1x1...
1339    * (would 0x0 be OK here?)
1340    */
1341   widget->allocation.width = 1;
1342   widget->allocation.height = 1;
1343   
1344   if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_IN_REPARENT (widget))
1345     gtk_widget_unrealize (widget);
1346
1347   old_parent = widget->parent;
1348   widget->parent = NULL;
1349   gtk_widget_set_parent_window (widget, NULL);
1350   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], old_parent);
1351   
1352   gtk_widget_unref (widget);
1353 }
1354
1355 /*****************************************
1356  * gtk_widget_destroy:
1357  *
1358  *   arguments:
1359  *
1360  *   results:
1361  *****************************************/
1362
1363 void
1364 gtk_widget_destroy (GtkWidget *widget)
1365 {
1366   g_return_if_fail (widget != NULL);
1367   g_return_if_fail (GTK_IS_WIDGET (widget));
1368   g_return_if_fail (GTK_OBJECT_CONSTRUCTED (widget));
1369
1370   gtk_object_destroy ((GtkObject*) widget);
1371 }
1372
1373 /*****************************************
1374  * gtk_widget_destroyed:
1375  *   Utility function: sets widget_pointer 
1376  *   to NULL when widget is destroyed.
1377  *
1378  *   arguments:
1379  *
1380  *   results:
1381  *****************************************/
1382
1383 void
1384 gtk_widget_destroyed (GtkWidget      *widget,
1385                       GtkWidget      **widget_pointer)
1386 {
1387   /* Don't make any assumptions about the
1388    *  value of widget!
1389    *  Even check widget_pointer.
1390    */
1391   if (widget_pointer)
1392     *widget_pointer = NULL;
1393 }
1394
1395 /*****************************************
1396  * gtk_widget_show:
1397  *
1398  *   arguments:
1399  *
1400  *   results:
1401  *****************************************/
1402
1403 void
1404 gtk_widget_show (GtkWidget *widget)
1405 {
1406   g_return_if_fail (widget != NULL);
1407   g_return_if_fail (GTK_IS_WIDGET (widget));
1408   
1409   if (!GTK_WIDGET_VISIBLE (widget))
1410     gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SHOW]);
1411 }
1412
1413
1414 /*************************************************************
1415  * gtk_widget_show_now:
1416  *   Show a widget, and if it is an unmapped toplevel widget
1417  *   wait for the map_event before returning
1418  *
1419  *   Warning: This routine will call the main loop recursively.
1420  *       
1421  *   arguments:
1422  *     
1423  *   results:
1424  *************************************************************/
1425
1426 static void
1427 gtk_widget_show_map_callback (GtkWidget *widget, GdkEvent *event, gint *flag)
1428 {
1429   *flag = TRUE;
1430   gtk_signal_disconnect_by_data (GTK_OBJECT (widget), flag);
1431 }
1432
1433 void
1434 gtk_widget_show_now (GtkWidget *widget)
1435 {
1436   gint flag = FALSE;
1437   
1438   g_return_if_fail (widget != NULL);
1439   g_return_if_fail (GTK_IS_WIDGET (widget));
1440
1441   /* make sure we will get event */
1442   if (!GTK_WIDGET_MAPPED (widget) &&
1443       GTK_WIDGET_TOPLEVEL (widget))
1444     {
1445       gtk_widget_show (widget);
1446
1447       gtk_signal_connect (GTK_OBJECT (widget), "map_event",
1448                           GTK_SIGNAL_FUNC (gtk_widget_show_map_callback), 
1449                           &flag);
1450
1451       while (!flag)
1452         gtk_main_iteration();
1453     }
1454   else
1455     gtk_widget_show (widget);
1456 }
1457
1458 /*****************************************
1459  * gtk_widget_hide:
1460  *
1461  *   arguments:
1462  *
1463  *   results:
1464  *****************************************/
1465
1466 void
1467 gtk_widget_hide (GtkWidget *widget)
1468 {
1469   g_return_if_fail (widget != NULL);
1470   g_return_if_fail (GTK_IS_WIDGET (widget));
1471   
1472   if (GTK_WIDGET_VISIBLE (widget))
1473     gtk_signal_emit (GTK_OBJECT (widget), widget_signals[HIDE]);
1474 }
1475
1476 gint
1477 gtk_widget_hide_on_delete (GtkWidget      *widget)
1478 {
1479   g_return_val_if_fail (widget != NULL, FALSE);
1480   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1481   
1482   gtk_widget_hide (widget);
1483   
1484   return TRUE;
1485 }
1486
1487 void
1488 gtk_widget_show_all (GtkWidget *widget)
1489 {
1490   GtkWidgetClass *class;
1491
1492   g_return_if_fail (widget != NULL);
1493   g_return_if_fail (GTK_IS_WIDGET (widget));
1494
1495   class = GTK_WIDGET_CLASS (GTK_OBJECT (widget)->klass);
1496
1497   if (class->show_all)
1498     class->show_all (widget);
1499 }
1500
1501 void
1502 gtk_widget_hide_all (GtkWidget *widget)
1503 {
1504   GtkWidgetClass *class;
1505
1506   g_return_if_fail (widget != NULL);
1507   g_return_if_fail (GTK_IS_WIDGET (widget));
1508
1509   class = GTK_WIDGET_CLASS (GTK_OBJECT (widget)->klass);
1510
1511   if (class->hide_all)
1512     class->hide_all (widget);
1513 }
1514
1515 /*****************************************
1516  * gtk_widget_map:
1517  *
1518  *   arguments:
1519  *
1520  *   results:
1521  *****************************************/
1522
1523 void
1524 gtk_widget_map (GtkWidget *widget)
1525 {
1526   g_return_if_fail (widget != NULL);
1527   g_return_if_fail (GTK_IS_WIDGET (widget));
1528   
1529   if (!GTK_WIDGET_MAPPED (widget))
1530     {
1531       if (!GTK_WIDGET_REALIZED (widget))
1532         gtk_widget_realize (widget);
1533       
1534       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[MAP]);
1535     }
1536 }
1537
1538 /*****************************************
1539  * gtk_widget_unmap:
1540  *
1541  *   arguments:
1542  *
1543  *   results:
1544  *****************************************/
1545
1546 void
1547 gtk_widget_unmap (GtkWidget *widget)
1548 {
1549   g_return_if_fail (widget != NULL);
1550   g_return_if_fail (GTK_IS_WIDGET (widget));
1551   
1552   if (GTK_WIDGET_MAPPED (widget))
1553     gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNMAP]);
1554 }
1555
1556 /*****************************************
1557  * gtk_widget_realize:
1558  *
1559  *   arguments:
1560  *
1561  *   results:
1562  *****************************************/
1563
1564 void
1565 gtk_widget_realize (GtkWidget *widget)
1566 {
1567   gint events;
1568   GdkExtensionMode mode;
1569   GtkWidgetShapeInfo *shape_info;
1570   
1571   g_return_if_fail (widget != NULL);
1572   g_return_if_fail (GTK_IS_WIDGET (widget));
1573   
1574   if (!GTK_WIDGET_REALIZED (widget))
1575     {
1576       /*
1577         if (GTK_IS_CONTAINER (widget) && !GTK_WIDGET_NO_WINDOW (widget))
1578           g_message ("gtk_widget_realize(%s)", gtk_type_name (GTK_WIDGET_TYPE (widget)));
1579       */
1580       
1581       if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
1582         gtk_widget_realize (widget->parent);
1583
1584       gtk_widget_ensure_style (widget);
1585       
1586       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[REALIZE]);
1587       
1588       if (GTK_WIDGET_HAS_SHAPE_MASK (widget))
1589         {
1590           shape_info = gtk_object_get_data (GTK_OBJECT (widget),
1591                                             shape_info_key);
1592           gdk_window_shape_combine_mask (widget->window,
1593                                          shape_info->shape_mask,
1594                                          shape_info->offset_x,
1595                                          shape_info->offset_y);
1596         }
1597       
1598       if (!GTK_WIDGET_NO_WINDOW (widget))
1599         {
1600           mode = gtk_widget_get_extension_events (widget);
1601           if (mode != GDK_EXTENSION_EVENTS_NONE)
1602             {
1603               events = gtk_widget_get_events (widget);
1604               gdk_input_set_extension_events (widget->window, events, mode);
1605             }
1606         }
1607       
1608     }
1609 }
1610
1611 /*****************************************
1612  * gtk_widget_unrealize:
1613  *
1614  *   arguments:
1615  *
1616  *   results:
1617  *****************************************/
1618
1619 void
1620 gtk_widget_unrealize (GtkWidget *widget)
1621 {
1622   g_return_if_fail (widget != NULL);
1623   g_return_if_fail (GTK_IS_WIDGET (widget));
1624
1625   if (GTK_WIDGET_REDRAW_PENDING (widget))
1626     gtk_widget_redraw_queue_remove (widget);
1627   
1628   if (GTK_WIDGET_HAS_SHAPE_MASK (widget))
1629     gtk_widget_shape_combine_mask (widget, NULL, -1, -1);
1630
1631   if (GTK_WIDGET_REALIZED (widget))
1632     {
1633       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNREALIZE]);
1634       GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
1635     }
1636 }
1637
1638 /*****************************************
1639  * gtk_widget_queue_draw:
1640  *
1641  *   arguments:
1642  *
1643  *   results:
1644  *****************************************/
1645
1646 typedef struct _GtkDrawData GtkDrawData;
1647 struct _GtkDrawData {
1648   GdkRectangle rect;
1649   GdkWindow *window;
1650 };
1651
1652 static GMemChunk   *draw_data_mem_chunk = NULL;
1653 static GSList      *draw_data_free_list = NULL;
1654 static const gchar *draw_data_key  = "gtk-draw-data";
1655 static GQuark       draw_data_key_id = 0;
1656
1657 static gint gtk_widget_idle_draw (gpointer data);
1658
1659 static void
1660 gtk_widget_queue_draw_data (GtkWidget *widget,
1661                             gint       x,
1662                             gint       y,
1663                             gint       width,
1664                             gint       height,
1665                             GdkWindow *window)
1666 {
1667   GSList      *node;
1668   GtkDrawData *data;
1669   
1670   g_return_if_fail (widget != NULL);
1671
1672   if ((width != 0) && (height != 0) && GTK_WIDGET_DRAWABLE (widget))
1673     {
1674       if (!draw_data_key_id)
1675         draw_data_key_id = g_quark_from_static_string (draw_data_key);
1676       
1677       if (draw_data_free_list)
1678         {
1679           node = draw_data_free_list;
1680           data = node->data;
1681           draw_data_free_list = draw_data_free_list->next;
1682         }
1683       else
1684         {
1685           if (!draw_data_mem_chunk)
1686             draw_data_mem_chunk = g_mem_chunk_create (GtkDrawData, 64,
1687                                                       G_ALLOC_ONLY);
1688           data = g_chunk_new (GtkDrawData, draw_data_mem_chunk);
1689           node = g_slist_alloc();
1690           node->data = data;
1691         }
1692
1693       data->rect.x = x;
1694       data->rect.y = y;
1695
1696       if ((width < 0) || (height < 0))
1697         {
1698           data->rect.width = 0;
1699           data->rect.height = 0;
1700         }
1701       else
1702         {
1703           data->rect.width = width;
1704           data->rect.height = height;
1705         }
1706       data->window = window;
1707       
1708       if ((width < 0) || (height < 0))
1709         {
1710           GSList *draw_data_list = 
1711             gtk_object_get_data_by_id (GTK_OBJECT (widget),
1712                                        draw_data_key_id);
1713           if (draw_data_list)
1714             draw_data_free_list = g_slist_concat (draw_data_list,
1715                                                   draw_data_free_list);
1716           node->next = NULL;
1717         }
1718       else
1719         node->next = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1720                                                 draw_data_key_id);
1721
1722       if (!GTK_WIDGET_REDRAW_PENDING (widget))
1723         {
1724           GTK_PRIVATE_SET_FLAG (widget, GTK_REDRAW_PENDING);
1725           if (gtk_widget_redraw_queue == NULL)
1726             gtk_idle_add_priority (GTK_PRIORITY_INTERNAL,
1727                                    gtk_widget_idle_draw,
1728                                    NULL);
1729           gtk_widget_redraw_queue = g_slist_prepend (gtk_widget_redraw_queue, widget);
1730         }
1731
1732       gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_key_id, node);
1733     }
1734 }
1735
1736 void       
1737 gtk_widget_queue_draw_area (GtkWidget *widget,
1738                             gint       x,
1739                             gint       y,
1740                             gint       width,
1741                             gint       height)
1742 {
1743   g_return_if_fail (widget != NULL);
1744   g_return_if_fail (GTK_IS_WIDGET (widget));
1745
1746   gtk_widget_queue_draw_data (widget, x, y, width, height, NULL);
1747 }
1748
1749 void       
1750 gtk_widget_queue_draw (GtkWidget *widget)
1751 {
1752   g_return_if_fail (widget != NULL);
1753   g_return_if_fail (GTK_IS_WIDGET (widget));
1754
1755   gtk_widget_queue_draw_data (widget, 0, 0, -1, -1, NULL);
1756 }
1757
1758 void       
1759 gtk_widget_queue_clear_area (GtkWidget *widget,
1760                              gint       x,
1761                              gint       y,
1762                              gint       width,
1763                              gint       height)
1764 {
1765   GtkWidget *parent;
1766   
1767   g_return_if_fail (widget != NULL);
1768   g_return_if_fail (GTK_IS_WIDGET (widget));
1769
1770   /* Find the correct widget */
1771
1772   if (GTK_WIDGET_NO_WINDOW (widget))
1773     {
1774       parent = widget;
1775       while (parent && GTK_WIDGET_NO_WINDOW (parent))
1776         parent = parent->parent;
1777       
1778       if (parent)
1779         gtk_widget_queue_draw_data (parent, x, y, width, height, widget->window);
1780     }
1781   else
1782     {
1783       gint wx, wy, wwidth, wheight;
1784       /* Translate widget relative to window-relative */
1785
1786       gdk_window_get_position (widget->window, &wx, &wy);
1787       x -= wx - widget->allocation.x;
1788       y -= wy - widget->allocation.y;
1789
1790       gdk_window_get_size (widget->window, &wwidth, &wheight);
1791
1792       if (x < 0)
1793         {
1794           width += x;  x = 0;
1795         }
1796       if (y < 0)
1797         {
1798           height += y; y = 0;
1799         }
1800       if (x + width > wwidth)
1801         width = wwidth - x;
1802       if (y + height > wheight)
1803         height = wheight - y;
1804
1805       gtk_widget_queue_draw_data (widget, x, y, width, height, NULL);
1806     }
1807 }
1808
1809 static void
1810 gtk_widget_redraw_queue_remove (GtkWidget *widget)
1811 {
1812   GSList *draw_data_list;
1813   GSList *tmp_list;
1814
1815   g_return_if_fail (GTK_WIDGET_REDRAW_PENDING (widget));
1816
1817   gtk_widget_redraw_queue = g_slist_remove (gtk_widget_redraw_queue, widget);
1818
1819   draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1820                                               draw_data_key_id);
1821   tmp_list = g_slist_last (draw_data_list);
1822   if (tmp_list)
1823     {
1824       tmp_list->next = draw_data_free_list;
1825       draw_data_free_list = draw_data_list;
1826     }
1827
1828   gtk_object_set_data_by_id (GTK_OBJECT (widget),
1829                              draw_data_key_id,
1830                              NULL);
1831   
1832   GTK_PRIVATE_UNSET_FLAG (widget, GTK_REDRAW_PENDING);
1833 }
1834
1835 void       
1836 gtk_widget_queue_clear    (GtkWidget *widget)
1837 {
1838   g_return_if_fail (widget != NULL);
1839   g_return_if_fail (GTK_IS_WIDGET (widget));
1840
1841   if (GTK_WIDGET_NO_WINDOW (widget))
1842     gtk_widget_queue_clear_area (widget, widget->allocation.x,
1843                                  widget->allocation.y,
1844                                  widget->allocation.width, 
1845                                  widget->allocation.height);
1846   else
1847     gtk_widget_queue_clear_area (widget, 0, 0, 
1848                                  widget->allocation.width, 
1849                                  widget->allocation.height);
1850 }
1851
1852 static gint
1853 gtk_widget_draw_data_combine (GtkDrawData *parent, GtkDrawData *child)
1854 {
1855   gint parent_x2, parent_y2;
1856   gint child_x2, child_y2;
1857
1858   /* Check for intersection */
1859
1860   parent_x2 = parent->rect.x + parent->rect.width;
1861   child_x2 = child->rect.x + child->rect.width;
1862   parent_y2 = parent->rect.y + parent->rect.height;
1863   child_y2 = child->rect.y + child->rect.height;
1864
1865   if ((child->rect.x > parent_x2) || (parent->rect.x > child_x2) ||
1866       (child->rect.y > parent_y2) || (parent->rect.y > child_y2))
1867     return FALSE;
1868   else
1869     {
1870       parent->rect.x = MIN (parent->rect.x, child->rect.x);
1871       parent->rect.y = MIN (parent->rect.y, child->rect.y);
1872       parent->rect.width = MAX (parent_x2, child_x2) - parent->rect.x;
1873       parent->rect.height = MAX (parent_y2, child_y2) - parent->rect.y;
1874     }
1875
1876   return TRUE;
1877 }
1878
1879 /* Take a rectangle with respect to window, and translate it
1880  * to coordinates relative to widget's allocation, clipping through
1881  * intermediate windows. Returns whether translation failed. If the
1882  * translation failed, we have something like a handlebox, where
1883  * the child widget's GdkWindow is not a child of the parents GdkWindow.
1884  */
1885 static gboolean
1886 gtk_widget_clip_rect (GtkWidget *widget,
1887                       GdkWindow *window,
1888                       GdkRectangle *rect,
1889                       gint      *x_offset,
1890                       gint      *y_offset)
1891 {
1892   gint x,y, width, height;
1893
1894   while (window && (window != widget->window))
1895     {
1896       gdk_window_get_position (window, &x, &y);
1897       rect->x += x;
1898       if (x_offset)
1899         *x_offset += x;
1900       rect->y += y;
1901       if (y_offset)
1902         *y_offset += y;
1903       
1904       window = gdk_window_get_parent (window);
1905       if (!window)
1906         return FALSE;
1907
1908       gdk_window_get_size (window, &width, &height);
1909       
1910       if (rect->x < 0)
1911         {
1912           rect->width += rect->x;
1913           rect->x = 0;
1914         }
1915       if (rect->y < 0)
1916         {
1917           rect->height += rect->y;
1918           rect->y = 0;
1919         }
1920       if (rect->x + rect->width > width)
1921         rect->width = width - rect->x;
1922       if (rect->y + rect->height > height)
1923         rect->height = height - rect->y;
1924     }
1925
1926   if (!window)
1927     return FALSE;
1928
1929   if (!GTK_WIDGET_NO_WINDOW (widget))
1930     {
1931       if (gdk_window_get_toplevel (window) != window)
1932         {
1933           gdk_window_get_position (window, &x, &y);
1934           rect->x += x - widget->allocation.x;
1935           if (x_offset)
1936             *x_offset += x - widget->allocation.x;
1937           rect->y += y - widget->allocation.y;
1938           if (y_offset)
1939             *y_offset += y - widget->allocation.y;
1940         }
1941     }
1942
1943   return TRUE;
1944 }
1945
1946 static gint
1947 gtk_widget_idle_draw (gpointer data)
1948 {
1949   GSList *widget_list;
1950   GSList *draw_data_list;
1951   GtkWidget *widget;
1952   
1953   /* Translate all draw requests to be allocation-relative */
1954   widget_list = gtk_widget_redraw_queue;
1955   while (widget_list)
1956     {
1957       widget = widget_list->data;
1958       draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1959                                                   draw_data_key_id);
1960
1961       while (draw_data_list)
1962         {
1963           gboolean full_allocation = FALSE;
1964           GtkDrawData *data = draw_data_list->data;
1965
1966           if (data->window)
1967             {
1968               /* If the translation fails, we have a handlebox,
1969                * so redraw the whole widget. Could be done better?
1970                */
1971               full_allocation = !gtk_widget_clip_rect (widget, 
1972                                                        data->window, 
1973                                                        &data->rect,
1974                                                        NULL, NULL);
1975               data->window = NULL;
1976             }
1977           else
1978             {
1979               if ((data->rect.width == 0) && (data->rect.height == 0))
1980                 {
1981                   if (GTK_WIDGET_NO_WINDOW (widget))
1982                     {
1983                       data->rect.x = widget->allocation.x;
1984                       data->rect.y = widget->allocation.y;
1985                     }
1986                   else
1987                     {
1988                       data->rect.x = 0;
1989                       data->rect.y = 0;
1990                     }
1991                   data->rect.width = widget->allocation.width;
1992                   data->rect.height = widget->allocation.height;
1993                 }
1994             }
1995
1996           draw_data_list = draw_data_list->next;
1997         }
1998
1999       widget_list = widget_list->next;
2000     }
2001
2002   /* Coalesce redraws
2003    */
2004   widget_list = gtk_widget_redraw_queue;
2005   while (widget_list)
2006     {
2007       GSList *prev_node = NULL;
2008       widget = widget_list->data;
2009       draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
2010                                                   draw_data_key_id);
2011
2012       while (draw_data_list)
2013         {
2014           gint x_offset, y_offset;
2015           GtkDrawData *data = draw_data_list->data;
2016           GSList *parent_list = draw_data_list->next;
2017           GtkWidget *parent;
2018           GdkWindow *window;
2019
2020           x_offset = 0;
2021           y_offset = 0;
2022           
2023           parent = widget;
2024           while (parent)
2025             {
2026               while (parent_list)
2027                 {
2028                   if (gtk_widget_draw_data_combine (parent_list->data, data))
2029                     {
2030                       GSList *tmp;
2031                       if (prev_node)
2032                         prev_node->next = draw_data_list->next;
2033                       else
2034                         gtk_object_set_data_by_id (GTK_OBJECT (widget),
2035                                                    draw_data_key_id,
2036                                                    draw_data_list->next);
2037
2038                       tmp = draw_data_list->next;
2039                       draw_data_list->next = draw_data_free_list;
2040                       draw_data_free_list = draw_data_list;
2041                       draw_data_list = tmp;
2042
2043                       goto next_rect;
2044                     }
2045                   
2046                   parent_list = parent_list->next;
2047                 }
2048
2049               window = parent->window;
2050
2051               if (parent->parent && parent->parent->window != window)
2052                 {
2053                   if (!GTK_WIDGET_NO_WINDOW (parent))
2054                     {
2055                       gint x, y;
2056                       gdk_window_get_position (window, &x, &y);
2057                       data->rect.x -= x - parent->allocation.x;
2058                       x_offset -=  x - parent->allocation.x;
2059                       data->rect.y -= y - parent->allocation.y;
2060                       y_offset -=  y - parent->allocation.y;
2061                     }
2062                   /* If we can't translate the rectangle, stop trying to
2063                    * merge. (This occurs for a handlebox)
2064                    */
2065                   if (!gtk_widget_clip_rect (parent->parent, window, &data->rect,
2066                                              &x_offset, &y_offset))
2067                     parent = NULL;
2068                 }
2069
2070               if (parent)
2071                 parent = parent->parent;
2072               
2073               if (parent && GTK_WIDGET_REDRAW_PENDING (parent))
2074                 parent_list = gtk_object_get_data_by_id (GTK_OBJECT (parent),
2075                                                          draw_data_key_id);
2076               else
2077                 parent_list = NULL;
2078             }
2079
2080           /* OK, this rectangle stays around. But take advantage
2081            * of the work we've done to clip it to the visible area -
2082            * rect.width/height have already been appropriately 
2083            * decreased
2084            */
2085           data->rect.x -= x_offset;
2086           data->rect.y -= y_offset;
2087
2088
2089           prev_node = draw_data_list;
2090
2091           draw_data_list = draw_data_list->next;
2092         next_rect:
2093           continue;
2094         }
2095       widget_list = widget_list->next;
2096     }
2097
2098   /* Process the draws */
2099   
2100   widget_list = gtk_widget_redraw_queue;
2101
2102   while (widget_list)
2103     {
2104       widget = widget_list->data;
2105       draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
2106                                                   draw_data_key_id);
2107       gtk_object_set_data_by_id (GTK_OBJECT (widget),
2108                                  draw_data_key_id,
2109                                  NULL);
2110
2111       GTK_PRIVATE_UNSET_FLAG (widget, GTK_REDRAW_PENDING);
2112
2113       while (draw_data_list)
2114         {
2115           GtkDrawData *data = draw_data_list->data;
2116           gtk_widget_draw (widget, &data->rect);
2117           
2118           if (draw_data_list->next)
2119             draw_data_list = draw_data_list->next;
2120           else
2121             {
2122               draw_data_list->next = draw_data_free_list;
2123               draw_data_free_list = draw_data_list;
2124               break;
2125             }
2126         }
2127
2128       widget_list = widget_list->next;
2129     }
2130
2131   g_slist_free (gtk_widget_redraw_queue);
2132   gtk_widget_redraw_queue = NULL;
2133
2134   return FALSE;
2135 }
2136
2137 void
2138 gtk_widget_queue_resize (GtkWidget *widget)
2139 {
2140   g_return_if_fail (widget != NULL);
2141   g_return_if_fail (GTK_IS_WIDGET (widget));
2142
2143   if (GTK_IS_RESIZE_CONTAINER (widget))
2144     gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
2145
2146   if (widget->parent)
2147     gtk_container_queue_resize (GTK_CONTAINER (widget->parent));
2148   else if (GTK_WIDGET_TOPLEVEL (widget))
2149     gtk_container_queue_resize (GTK_CONTAINER (widget));
2150 }
2151
2152 /*****************************************
2153  * gtk_widget_draw:
2154  *
2155  *   arguments:
2156  *
2157  *   results:
2158  *****************************************/
2159
2160 void
2161 gtk_widget_draw (GtkWidget    *widget,
2162                  GdkRectangle *area)
2163 {
2164   GdkRectangle temp_area;
2165
2166   g_return_if_fail (widget != NULL);
2167   g_return_if_fail (GTK_IS_WIDGET (widget));
2168
2169   if (GTK_WIDGET_DRAWABLE (widget))
2170     {
2171       if (!area)
2172         {
2173           if (GTK_WIDGET_NO_WINDOW (widget))
2174             {
2175               temp_area.x = widget->allocation.x;
2176               temp_area.y = widget->allocation.y;
2177             }
2178           else
2179             {
2180               temp_area.x = 0;
2181               temp_area.y = 0;
2182             }
2183
2184           temp_area.width = widget->allocation.width;
2185           temp_area.height = widget->allocation.height;
2186           area = &temp_area;
2187         }
2188
2189       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area);
2190     }
2191 }
2192
2193 /*****************************************
2194  * gtk_widget_draw_focus:
2195  *
2196  *   arguments:
2197  *
2198  *   results:
2199  *****************************************/
2200
2201 void
2202 gtk_widget_draw_focus (GtkWidget *widget)
2203 {
2204   g_return_if_fail (widget != NULL);
2205   g_return_if_fail (GTK_IS_WIDGET (widget));
2206   
2207   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_FOCUS]);
2208 }
2209
2210 /*****************************************
2211  * gtk_widget_draw_default:
2212  *
2213  *   arguments:
2214  *
2215  *   results:
2216  *****************************************/
2217
2218 void
2219 gtk_widget_draw_default (GtkWidget *widget)
2220 {
2221   g_return_if_fail (widget != NULL);
2222   g_return_if_fail (GTK_IS_WIDGET (widget));
2223   
2224   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_DEFAULT]);
2225 }
2226
2227 /*****************************************
2228  * gtk_widget_size_request:
2229  *
2230  *   arguments:
2231  *
2232  *   results:
2233  *****************************************/
2234
2235 void
2236 gtk_widget_size_request (GtkWidget      *widget,
2237                          GtkRequisition *requisition)
2238 {
2239   GtkWidgetAuxInfo *aux_info;
2240
2241   g_return_if_fail (widget != NULL);
2242   g_return_if_fail (GTK_IS_WIDGET (widget));
2243
2244   gtk_widget_ref (widget);
2245   gtk_widget_ensure_style (widget);
2246   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_REQUEST],
2247                    requisition);
2248   aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
2249   if (aux_info)
2250     {
2251       if (aux_info->width > 0)
2252         requisition->width = aux_info->width;
2253       if (aux_info->height > 0)
2254         requisition->height = aux_info->height;
2255     }
2256   gtk_widget_unref (widget);
2257 }
2258
2259 /*****************************************
2260  * gtk_widget_size_allocate:
2261  *
2262  *   arguments:
2263  *
2264  *   results:
2265  *****************************************/
2266
2267 void
2268 gtk_widget_size_allocate (GtkWidget     *widget,
2269                           GtkAllocation *allocation)
2270 {
2271   GtkWidgetAuxInfo *aux_info;
2272   GtkAllocation real_allocation;
2273   
2274   g_return_if_fail (widget != NULL);
2275   g_return_if_fail (GTK_IS_WIDGET (widget));
2276   
2277   real_allocation = *allocation;
2278   aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
2279   
2280   if (aux_info)
2281     {
2282       if (aux_info->x != -1)
2283         real_allocation.x = aux_info->x;
2284       if (aux_info->y != -1)
2285         real_allocation.y = aux_info->y;
2286     }
2287   
2288   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_ALLOCATE], &real_allocation);
2289 }
2290
2291 static void
2292 gtk_widget_stop_add_accelerator (GtkWidget *widget)
2293 {
2294   g_return_if_fail (widget != NULL);
2295   g_return_if_fail (GTK_IS_WIDGET (widget));
2296
2297   gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[ADD_ACCELERATOR]);
2298 }
2299
2300 static void
2301 gtk_widget_stop_remove_accelerator (GtkWidget *widget)
2302 {
2303   g_return_if_fail (widget != NULL);
2304   g_return_if_fail (GTK_IS_WIDGET (widget));
2305
2306   gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[REMOVE_ACCELERATOR]);
2307 }
2308
2309 void
2310 gtk_widget_lock_accelerators (GtkWidget *widget)
2311 {
2312   g_return_if_fail (widget != NULL);
2313   g_return_if_fail (GTK_IS_WIDGET (widget));
2314
2315   if (gtk_signal_handler_pending_by_func (GTK_OBJECT (widget),
2316                                           widget_signals[ADD_ACCELERATOR],
2317                                           TRUE,
2318                                           GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
2319                                           NULL) == 0)
2320     {
2321       gtk_signal_connect (GTK_OBJECT (widget),
2322                           "add_accelerator",
2323                           GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
2324                           NULL);
2325       gtk_signal_connect (GTK_OBJECT (widget),
2326                           "remove_accelerator",
2327                           GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
2328                           NULL);
2329     }
2330 }
2331
2332 void
2333 gtk_widget_unlock_accelerators (GtkWidget *widget)
2334 {
2335   g_return_if_fail (widget != NULL);
2336   g_return_if_fail (GTK_IS_WIDGET (widget));
2337
2338   if (gtk_signal_handler_pending_by_func (GTK_OBJECT (widget),
2339                                           widget_signals[ADD_ACCELERATOR],
2340                                           TRUE,
2341                                           GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
2342                                           NULL) > 0)
2343     {
2344       gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
2345                                      GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
2346                                      NULL);
2347       gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
2348                                      GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
2349                                      NULL);
2350     }
2351 }
2352
2353 void
2354 gtk_widget_thaw_accelerators (GtkWidget *widget)
2355 {
2356   g_message ("gtk_widget_thaw_accelerators() is deprecated");
2357
2358   gtk_widget_unlock_accelerators (widget);
2359 }
2360
2361 void
2362 gtk_widget_freeze_accelerators (GtkWidget *widget)
2363 {
2364   g_message ("gtk_widget_freeze_accelerators() is deprecated");
2365
2366   gtk_widget_lock_accelerators (widget);
2367 }
2368
2369 void
2370 gtk_widget_add_accelerator (GtkWidget           *widget,
2371                             const gchar         *accel_signal,
2372                             GtkAccelGroup       *accel_group,
2373                             guint                accel_key,
2374                             guint                accel_mods,
2375                             GtkAccelFlags        accel_flags)
2376 {
2377   g_return_if_fail (widget != NULL);
2378   g_return_if_fail (GTK_IS_WIDGET (widget));
2379   g_return_if_fail (accel_group != NULL);
2380
2381   gtk_accel_group_add (accel_group,
2382                        accel_key,
2383                        accel_mods,
2384                        accel_flags,
2385                        (GtkObject*) widget,
2386                        accel_signal);
2387 }
2388
2389 void
2390 gtk_widget_remove_accelerator (GtkWidget           *widget,
2391                                GtkAccelGroup       *accel_group,
2392                                guint                accel_key,
2393                                guint                accel_mods)
2394 {
2395   g_return_if_fail (widget != NULL);
2396   g_return_if_fail (GTK_IS_WIDGET (widget));
2397   g_return_if_fail (accel_group != NULL);
2398
2399   gtk_accel_group_remove (accel_group,
2400                           accel_key,
2401                           accel_mods,
2402                           (GtkObject*) widget);
2403 }
2404
2405 void
2406 gtk_widget_remove_accelerators (GtkWidget           *widget,
2407                                 const gchar         *accel_signal,
2408                                 gboolean             visible_only)
2409 {
2410   GSList *slist;
2411   guint signal_id;
2412   
2413   g_return_if_fail (widget != NULL);
2414   g_return_if_fail (GTK_IS_WIDGET (widget));
2415   g_return_if_fail (accel_signal != NULL);
2416   
2417   signal_id = gtk_signal_lookup (accel_signal, GTK_OBJECT_TYPE (widget));
2418   g_return_if_fail (signal_id != 0);
2419   
2420   slist = gtk_accel_group_entries_from_object (GTK_OBJECT (widget));
2421   while (slist)
2422     {
2423       GtkAccelEntry *ac_entry;
2424       
2425       ac_entry = slist->data;
2426       slist = slist->next;
2427       if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
2428           ac_entry->signal_id == signal_id)
2429         gtk_widget_remove_accelerator (GTK_WIDGET (widget),
2430                                        ac_entry->accel_group,
2431                                        ac_entry->accelerator_key,
2432                                        ac_entry->accelerator_mods);
2433     }
2434 }
2435
2436 guint
2437 gtk_widget_accelerator_signal (GtkWidget           *widget,
2438                                GtkAccelGroup       *accel_group,
2439                                guint                accel_key,
2440                                guint                accel_mods)
2441 {
2442   GtkAccelEntry *ac_entry;
2443
2444   g_return_val_if_fail (widget != NULL, 0);
2445   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
2446   g_return_val_if_fail (accel_group != NULL, 0);
2447
2448   ac_entry = gtk_accel_group_get_entry (accel_group, accel_key, accel_mods);
2449
2450   if (ac_entry && ac_entry->object == (GtkObject*) widget)
2451     return ac_entry->signal_id;
2452   return 0;
2453 }
2454
2455 static gint
2456 gtk_widget_real_key_press_event (GtkWidget         *widget,
2457                                  GdkEventKey       *event)
2458 {
2459   gboolean handled = FALSE;
2460
2461   g_return_val_if_fail (widget != NULL, handled);
2462   g_return_val_if_fail (GTK_IS_WIDGET (widget), handled);
2463   g_return_val_if_fail (event != NULL, handled);
2464
2465   if (!handled)
2466     handled = gtk_bindings_activate (GTK_OBJECT (widget),
2467                                      event->keyval,
2468                                      event->state);
2469
2470   return handled;
2471 }
2472
2473 static gint
2474 gtk_widget_real_key_release_event (GtkWidget         *widget,
2475                                    GdkEventKey       *event)
2476 {
2477   gboolean handled = FALSE;
2478
2479   g_return_val_if_fail (widget != NULL, handled);
2480   g_return_val_if_fail (GTK_IS_WIDGET (widget), handled);
2481   g_return_val_if_fail (event != NULL, handled);
2482
2483   if (!handled)
2484     handled = gtk_bindings_activate (GTK_OBJECT (widget),
2485                                      event->keyval,
2486                                      event->state | GDK_RELEASE_MASK);
2487
2488   return handled;
2489 }
2490
2491 /*****************************************
2492  * gtk_widget_event:
2493  *
2494  *   arguments:
2495  *
2496  *   results:
2497  *****************************************/
2498
2499 gint
2500 gtk_widget_event (GtkWidget *widget,
2501                   GdkEvent  *event)
2502 {
2503   gint return_val;
2504   gint signal_num;
2505
2506   g_return_val_if_fail (widget != NULL, TRUE);
2507   g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
2508
2509   gtk_widget_ref (widget);
2510   return_val = FALSE;
2511   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event,
2512                    &return_val);
2513   if (return_val || GTK_OBJECT_DESTROYED (widget))
2514     {
2515       gtk_widget_unref (widget);
2516       return TRUE;
2517     }
2518
2519   switch (event->type)
2520     {
2521     case GDK_NOTHING:
2522       signal_num = -1;
2523       break;
2524     case GDK_BUTTON_PRESS:
2525     case GDK_2BUTTON_PRESS:
2526     case GDK_3BUTTON_PRESS:
2527       signal_num = BUTTON_PRESS_EVENT;
2528       break;
2529     case GDK_BUTTON_RELEASE:
2530       signal_num = BUTTON_RELEASE_EVENT;
2531       break;
2532     case GDK_MOTION_NOTIFY:
2533       signal_num = MOTION_NOTIFY_EVENT;
2534       break;
2535     case GDK_DELETE:
2536       signal_num = DELETE_EVENT;
2537       break;
2538     case GDK_DESTROY:
2539       signal_num = DESTROY_EVENT;
2540       break;
2541     case GDK_KEY_PRESS:
2542       signal_num = KEY_PRESS_EVENT;
2543       break;
2544     case GDK_KEY_RELEASE:
2545       signal_num = KEY_RELEASE_EVENT;
2546       break;
2547     case GDK_ENTER_NOTIFY:
2548       signal_num = ENTER_NOTIFY_EVENT;
2549       break;
2550     case GDK_LEAVE_NOTIFY:
2551       signal_num = LEAVE_NOTIFY_EVENT;
2552       break;
2553     case GDK_FOCUS_CHANGE:
2554       if (event->focus_change.in)
2555         signal_num = FOCUS_IN_EVENT;
2556       else
2557         signal_num = FOCUS_OUT_EVENT;
2558       break;
2559     case GDK_CONFIGURE:
2560       signal_num = CONFIGURE_EVENT;
2561       break;
2562     case GDK_MAP:
2563       signal_num = MAP_EVENT;
2564       break;
2565     case GDK_UNMAP:
2566       signal_num = UNMAP_EVENT;
2567       break;
2568     case GDK_PROPERTY_NOTIFY:
2569       signal_num = PROPERTY_NOTIFY_EVENT;
2570       break;
2571     case GDK_SELECTION_CLEAR:
2572       signal_num = SELECTION_CLEAR_EVENT;
2573       break;
2574     case GDK_SELECTION_REQUEST:
2575       signal_num = SELECTION_REQUEST_EVENT;
2576       break;
2577     case GDK_SELECTION_NOTIFY:
2578       signal_num = SELECTION_NOTIFY_EVENT;
2579       break;
2580     case GDK_PROXIMITY_IN:
2581       signal_num = PROXIMITY_IN_EVENT;
2582       break;
2583     case GDK_PROXIMITY_OUT:
2584       signal_num = PROXIMITY_OUT_EVENT;
2585       break;
2586     case GDK_NO_EXPOSE:
2587       signal_num = NO_EXPOSE_EVENT;
2588       break;
2589     case GDK_CLIENT_EVENT:
2590       signal_num = CLIENT_EVENT;
2591       break;
2592     case GDK_EXPOSE:
2593       /* there is no sense in providing a widget with bogus expose events.
2594        * Widgets that are going to be resized don't need to be
2595        * exposed, since they will be redrawn anyways.
2596        */
2597       if (!event->any.window ||
2598           GTK_WIDGET_RESIZE_NEEDED (widget) ||
2599           (widget->parent && GTK_WIDGET_RESIZE_NEEDED (widget->parent)))
2600         {
2601           gtk_widget_unref (widget);
2602           return TRUE;
2603         }
2604       signal_num = EXPOSE_EVENT;
2605       break;
2606     case GDK_VISIBILITY_NOTIFY:
2607       signal_num = VISIBILITY_NOTIFY_EVENT;
2608       break;
2609     default:
2610       g_warning ("could not determine signal number for event: %d", event->type);
2611       gtk_widget_unref (widget);
2612       return TRUE;
2613     }
2614   
2615   if (signal_num != -1)
2616     gtk_signal_emit (GTK_OBJECT (widget), widget_signals[signal_num], event, &return_val);
2617
2618   return_val |= GTK_OBJECT_DESTROYED (widget);
2619
2620   gtk_widget_unref (widget);
2621
2622   return return_val;
2623 }
2624
2625 /*****************************************
2626  * gtk_widget_activate:
2627  *
2628  *   arguments:
2629  *
2630  *   results:
2631  *****************************************/
2632
2633 gboolean
2634 gtk_widget_activate (GtkWidget *widget)
2635 {
2636   g_return_val_if_fail (widget != NULL, FALSE);
2637   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2638   
2639   if (WIDGET_CLASS (widget)->activate_signal)
2640     {
2641       /* FIXME: we should eventually check the signals signature here */
2642       gtk_signal_emit (GTK_OBJECT (widget), WIDGET_CLASS (widget)->activate_signal);
2643
2644       return TRUE;
2645     }
2646   else
2647     return FALSE;
2648 }
2649
2650 gboolean
2651 gtk_widget_set_scroll_adjustments (GtkWidget     *widget,
2652                                    GtkAdjustment *hadjustment,
2653                                    GtkAdjustment *vadjustment)
2654 {
2655   g_return_val_if_fail (widget != NULL, FALSE);
2656   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2657   if (hadjustment)
2658     g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), FALSE);
2659   if (vadjustment)
2660     g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), FALSE);
2661
2662   if (WIDGET_CLASS (widget)->set_scroll_adjustments_signal)
2663     {
2664       /* FIXME: we should eventually check the signals signature here */
2665       gtk_signal_emit (GTK_OBJECT (widget),
2666                        WIDGET_CLASS (widget)->set_scroll_adjustments_signal,
2667                        hadjustment, vadjustment);
2668       return TRUE;
2669     }
2670   else
2671     return FALSE;
2672 }
2673
2674 /*****************************************
2675  * gtk_widget_reparent_container_child:
2676  *   assistent function to gtk_widget_reparent
2677  *
2678  *   arguments:
2679  *
2680  *   results:
2681  *****************************************/
2682
2683 static void
2684 gtk_widget_reparent_container_child (GtkWidget *widget,
2685                                      gpointer   client_data)
2686 {
2687   g_return_if_fail (widget != NULL);
2688   g_return_if_fail (GTK_IS_WIDGET (widget));
2689   g_return_if_fail (client_data != NULL);
2690   
2691   if (GTK_WIDGET_NO_WINDOW (widget))
2692     {
2693       if (widget->window)
2694         gdk_window_unref (widget->window);
2695       widget->window = (GdkWindow*) client_data;
2696       if (widget->window)
2697         gdk_window_ref (widget->window);
2698
2699       if (GTK_IS_CONTAINER (widget))
2700         gtk_container_forall (GTK_CONTAINER (widget),
2701                               gtk_widget_reparent_container_child,
2702                               client_data);
2703     }
2704   else
2705     gdk_window_reparent (widget->window, 
2706                          (GdkWindow*) client_data, 0, 0);
2707 }
2708
2709 /*****************************************
2710  * gtk_widget_reparent:
2711  *
2712  *   arguments:
2713  *
2714  *   results:
2715  *****************************************/
2716
2717 void
2718 gtk_widget_reparent (GtkWidget *widget,
2719                      GtkWidget *new_parent)
2720 {
2721   g_return_if_fail (widget != NULL);
2722   g_return_if_fail (GTK_IS_WIDGET (widget));
2723   g_return_if_fail (new_parent != NULL);
2724   g_return_if_fail (GTK_IS_CONTAINER (new_parent));
2725   g_return_if_fail (widget->parent != NULL);
2726   
2727   if (widget->parent != new_parent)
2728     {
2729       /* First try to see if we can get away without unrealizing
2730        * the widget as we reparent it. if so we set a flag so
2731        * that gtk_widget_unparent doesn't unrealize widget
2732        */
2733       if (GTK_WIDGET_REALIZED (widget) && GTK_WIDGET_REALIZED (new_parent))
2734         GTK_PRIVATE_SET_FLAG (widget, GTK_IN_REPARENT);
2735       
2736       gtk_widget_ref (widget);
2737       gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
2738       gtk_container_add (GTK_CONTAINER (new_parent), widget);
2739       gtk_widget_unref (widget);
2740       
2741       if (GTK_WIDGET_IN_REPARENT (widget))
2742         {
2743           GTK_PRIVATE_UNSET_FLAG (widget, GTK_IN_REPARENT);
2744           
2745           /* OK, now fix up the widget's window. (And that for any
2746            * children, if the widget is NO_WINDOW and a container) 
2747            */
2748           if (GTK_WIDGET_NO_WINDOW (widget))
2749             {
2750               if (GTK_IS_CONTAINER (widget))
2751                 gtk_container_forall (GTK_CONTAINER (widget),
2752                                       gtk_widget_reparent_container_child,
2753                                       gtk_widget_get_parent_window (widget));
2754               else
2755                 {
2756                   GdkWindow *parent_window;
2757                   
2758                   parent_window = gtk_widget_get_parent_window (widget);
2759                   if (parent_window != widget->window)
2760                     {
2761                       if (widget->window)
2762                         gdk_window_unref (widget->window);
2763                       widget->window = parent_window;
2764                       if (widget->window)
2765                         gdk_window_ref (widget->window);
2766                     }
2767                 }
2768             }
2769           else
2770             gdk_window_reparent (widget->window, gtk_widget_get_parent_window (widget), 0, 0);
2771         }
2772     }
2773 }
2774
2775 /*****************************************
2776  * gtk_widget_popup:
2777  *
2778  *   arguments:
2779  *
2780  *   results:
2781  *****************************************/
2782
2783 void
2784 gtk_widget_popup (GtkWidget *widget,
2785                   gint       x,
2786                   gint       y)
2787 {
2788   g_return_if_fail (widget != NULL);
2789   g_return_if_fail (GTK_IS_WIDGET (widget));
2790   
2791   if (!GTK_WIDGET_VISIBLE (widget))
2792     {
2793       if (!GTK_WIDGET_REALIZED (widget))
2794         gtk_widget_realize (widget);
2795       if (!GTK_WIDGET_NO_WINDOW (widget))
2796         gdk_window_move (widget->window, x, y);
2797       gtk_widget_show (widget);
2798     }
2799 }
2800
2801 /*****************************************
2802  * gtk_widget_intersect:
2803  *
2804  *   arguments:
2805  *
2806  *   results:
2807  *****************************************/
2808
2809 gint
2810 gtk_widget_intersect (GtkWidget    *widget,
2811                       GdkRectangle *area,
2812                       GdkRectangle *intersection)
2813 {
2814   GdkRectangle *dest;
2815   GdkRectangle tmp;
2816   gint return_val;
2817   
2818   g_return_val_if_fail (widget != NULL, FALSE);
2819   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
2820   g_return_val_if_fail (area != NULL, FALSE);
2821   
2822   if (intersection)
2823     dest = intersection;
2824   else
2825     dest = &tmp;
2826   
2827   return_val = gdk_rectangle_intersect ((GdkRectangle*) &widget->allocation, area, dest);
2828   
2829   if (return_val && intersection && !GTK_WIDGET_NO_WINDOW (widget))
2830     {
2831       intersection->x -= widget->allocation.x;
2832       intersection->y -= widget->allocation.y;
2833     }
2834   
2835   return return_val;
2836 }
2837
2838 /*****************************************
2839  * gtk_widget_grab_focus:
2840  *
2841  *   arguments:
2842  *
2843  *   results:
2844  *****************************************/
2845
2846 void
2847 gtk_widget_grab_focus (GtkWidget *widget)
2848 {
2849   g_return_if_fail (widget != NULL);
2850   g_return_if_fail (GTK_IS_WIDGET (widget));
2851
2852   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[GRAB_FOCUS]);
2853 }
2854
2855 static void
2856 reset_focus_recurse (GtkWidget *widget,
2857                      gpointer   data)
2858 {
2859   if (GTK_IS_CONTAINER (widget))
2860     {
2861       GtkContainer *container;
2862
2863       container = GTK_CONTAINER (widget);
2864       gtk_container_set_focus_child (container, NULL);
2865
2866       gtk_container_foreach (container,
2867                              reset_focus_recurse,
2868                              NULL);
2869     }
2870 }
2871
2872 static void
2873 gtk_widget_real_grab_focus (GtkWidget *focus_widget)
2874 {
2875   g_return_if_fail (focus_widget != NULL);
2876   g_return_if_fail (GTK_IS_WIDGET (focus_widget));
2877   
2878   if (GTK_WIDGET_CAN_FOCUS (focus_widget))
2879     {
2880       GtkWidget *toplevel;
2881       GtkWidget *widget;
2882       
2883       /* clear the current focus setting, break if the current widget
2884        * is the focus widget's parent, since containers above that will
2885        * be set by the next loop.
2886        */
2887       toplevel = gtk_widget_get_toplevel (focus_widget);
2888       if (GTK_IS_WINDOW (toplevel))
2889         {
2890           widget = GTK_WINDOW (toplevel)->focus_widget;
2891           
2892           if (widget == focus_widget)
2893             return;
2894           
2895           if (widget)
2896             {
2897               while (widget->parent && widget->parent != focus_widget->parent)
2898                 {
2899                   widget = widget->parent;
2900                   gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
2901                 }
2902             }
2903         }
2904       else if (toplevel != focus_widget)
2905         {
2906           /* gtk_widget_grab_focus() operates on a tree without window...
2907            * actually, this is very questionable behaviour.
2908            */
2909           
2910           gtk_container_foreach (GTK_CONTAINER (toplevel),
2911                                  reset_focus_recurse,
2912                                  NULL);
2913         }
2914
2915       /* now propagate the new focus up the widget tree and finally
2916        * set it on the window
2917        */
2918       widget = focus_widget;
2919       while (widget->parent)
2920         {
2921           gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), widget);
2922           widget = widget->parent;
2923         }
2924       if (GTK_IS_WINDOW (widget))
2925         gtk_window_set_focus (GTK_WINDOW (widget), focus_widget);
2926     }
2927 }
2928
2929 /*****************************************
2930  * gtk_widget_grab_default:
2931  *
2932  *   arguments:
2933  *
2934  *   results:
2935  *****************************************/
2936
2937 void
2938 gtk_widget_grab_default (GtkWidget *widget)
2939 {
2940   GtkWidget *window;
2941   GtkType window_type;
2942   
2943   g_return_if_fail (widget != NULL);
2944   g_return_if_fail (GTK_IS_WIDGET (widget));
2945   g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (widget));
2946   
2947   window_type = gtk_window_get_type ();
2948   window = widget->parent;
2949   
2950   while (window && !gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
2951     window = window->parent;
2952   
2953   if (window && gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
2954     gtk_window_set_default (GTK_WINDOW (window), widget);
2955 }
2956
2957 /*****************************************
2958  * gtk_widget_set_name:
2959  *
2960  *   arguments:
2961  *
2962  *   results:
2963  *****************************************/
2964
2965 void
2966 gtk_widget_set_name (GtkWidget   *widget,
2967                      const gchar *name)
2968 {
2969   g_return_if_fail (widget != NULL);
2970   g_return_if_fail (GTK_IS_WIDGET (widget));
2971   
2972   if (widget->name)
2973     g_free (widget->name);
2974   widget->name = g_strdup (name);
2975
2976   if (!GTK_WIDGET_USER_STYLE (widget))
2977     gtk_widget_set_rc_style (widget);
2978 }
2979
2980 /*****************************************
2981  * gtk_widget_get_name:
2982  *
2983  *   arguments:
2984  *
2985  *   results:
2986  *****************************************/
2987
2988 gchar*
2989 gtk_widget_get_name (GtkWidget *widget)
2990 {
2991   g_return_val_if_fail (widget != NULL, NULL);
2992   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
2993   
2994   if (widget->name)
2995     return widget->name;
2996   return gtk_type_name (GTK_WIDGET_TYPE (widget));
2997 }
2998
2999 /*****************************************
3000  * gtk_widget_set_state:
3001  *
3002  *   arguments:
3003  *     widget
3004  *     state
3005  *
3006  *   results:
3007  *****************************************/
3008
3009 void
3010 gtk_widget_set_state (GtkWidget           *widget,
3011                       GtkStateType         state)
3012 {
3013   g_return_if_fail (widget != NULL);
3014   g_return_if_fail (GTK_IS_WIDGET (widget));
3015
3016   if (state == GTK_WIDGET_STATE (widget))
3017     return;
3018
3019   if (state == GTK_STATE_INSENSITIVE)
3020     gtk_widget_set_sensitive (widget, FALSE);
3021   else
3022     {
3023       GtkStateData data;
3024
3025       data.state = state;
3026       data.state_restoration = FALSE;
3027       data.use_forall = FALSE;
3028       if (widget->parent)
3029         data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget->parent) != FALSE);
3030       else
3031         data.parent_sensitive = TRUE;
3032
3033       gtk_widget_propagate_state (widget, &data);
3034   
3035       if (GTK_WIDGET_DRAWABLE (widget))
3036         gtk_widget_queue_clear (widget);
3037     }
3038 }
3039
3040 /*****************************************
3041  * gtk_widget_set_sensitive:
3042  *
3043  *   arguments:
3044  *     widget
3045  *     boolean value for sensitivity
3046  *
3047  *   results:
3048  *****************************************/
3049
3050 void
3051 gtk_widget_set_sensitive (GtkWidget *widget,
3052                           gint       sensitive)
3053 {
3054   GtkStateData data;
3055
3056   g_return_if_fail (widget != NULL);
3057   g_return_if_fail (GTK_IS_WIDGET (widget));
3058
3059   sensitive = (sensitive != FALSE);
3060
3061   if (sensitive == (GTK_WIDGET_SENSITIVE (widget) != FALSE))
3062     return;
3063
3064   if (sensitive)
3065     {
3066       GTK_WIDGET_SET_FLAGS (widget, GTK_SENSITIVE);
3067       data.state = GTK_WIDGET_SAVED_STATE (widget);
3068     }
3069   else
3070     {
3071       GTK_WIDGET_UNSET_FLAGS (widget, GTK_SENSITIVE);
3072       data.state = GTK_WIDGET_STATE (widget);
3073     }
3074   data.state_restoration = TRUE;
3075   data.use_forall = TRUE;
3076
3077   if (widget->parent)
3078     data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget->parent) != FALSE);
3079   else
3080     data.parent_sensitive = TRUE;
3081
3082   gtk_widget_propagate_state (widget, &data);
3083   if (GTK_WIDGET_DRAWABLE (widget))
3084     gtk_widget_queue_clear (widget);
3085 }
3086
3087 /*****************************************
3088  * gtk_widget_set_parent:
3089  *
3090  *   arguments:
3091  *
3092  *   results:
3093  *****************************************/
3094
3095 void
3096 gtk_widget_set_parent (GtkWidget *widget,
3097                        GtkWidget *parent)
3098 {
3099   GtkStateData data;
3100   
3101   g_return_if_fail (widget != NULL);
3102   g_return_if_fail (GTK_IS_WIDGET (widget));
3103   g_return_if_fail (widget->parent == NULL);
3104   g_return_if_fail (!GTK_WIDGET_TOPLEVEL (widget));
3105   g_return_if_fail (parent != NULL);
3106   g_return_if_fail (GTK_IS_WIDGET (parent));
3107   g_return_if_fail (widget != parent);
3108
3109   /* keep this function in sync with gtk_menu_attach_to_widget()
3110    */
3111
3112   gtk_widget_ref (widget);
3113   gtk_object_sink (GTK_OBJECT (widget));
3114   widget->parent = parent;
3115
3116   if (GTK_WIDGET_STATE (parent) != GTK_STATE_NORMAL)
3117     data.state = GTK_WIDGET_STATE (parent);
3118   else
3119     data.state = GTK_WIDGET_STATE (widget);
3120   data.state_restoration = FALSE;
3121   data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (parent) != FALSE);
3122   data.use_forall = GTK_WIDGET_IS_SENSITIVE (parent) != GTK_WIDGET_IS_SENSITIVE (widget);
3123
3124   gtk_widget_propagate_state (widget, &data);
3125   
3126   gtk_widget_set_style_recurse (widget, NULL);
3127
3128   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], NULL);
3129 }
3130
3131 /*****************************************
3132  * Widget styles
3133  * see docs/styles.txt
3134  *****************************************/
3135 void
3136 gtk_widget_set_style (GtkWidget *widget,
3137                       GtkStyle  *style)
3138 {
3139   GtkStyle *default_style;
3140   gboolean initial_emission;
3141
3142   g_return_if_fail (widget != NULL);
3143   g_return_if_fail (GTK_IS_WIDGET (widget));
3144   g_return_if_fail (style != NULL);
3145
3146   initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget);
3147
3148   GTK_WIDGET_UNSET_FLAGS (widget, GTK_RC_STYLE);
3149   GTK_PRIVATE_SET_FLAG (widget, GTK_USER_STYLE);
3150
3151   default_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id);
3152   if (!default_style)
3153     {
3154       gtk_style_ref (widget->style);
3155       if (!saved_default_style_key_id)
3156         saved_default_style_key_id = g_quark_from_static_string (saved_default_style_key);
3157       gtk_object_set_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id, widget->style);
3158     }
3159
3160   gtk_widget_set_style_internal (widget, style, initial_emission);
3161 }
3162
3163 void
3164 gtk_widget_ensure_style (GtkWidget *widget)
3165 {
3166   g_return_if_fail (widget != NULL);
3167   g_return_if_fail (GTK_IS_WIDGET (widget));
3168
3169   if (!GTK_WIDGET_USER_STYLE (widget) &&
3170       !GTK_WIDGET_RC_STYLE (widget))
3171     gtk_widget_set_rc_style (widget);
3172 }
3173
3174 void
3175 gtk_widget_set_rc_style (GtkWidget *widget)
3176 {
3177   GtkStyle *saved_style;
3178   GtkStyle *new_style;
3179   gboolean initial_emission;
3180   
3181   g_return_if_fail (widget != NULL);
3182   g_return_if_fail (GTK_IS_WIDGET (widget));
3183
3184   initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget);
3185
3186   GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE);
3187   GTK_WIDGET_SET_FLAGS (widget, GTK_RC_STYLE);
3188
3189   saved_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id);
3190   new_style = gtk_rc_get_style (widget);
3191   if (new_style)
3192     {
3193       if (!saved_style)
3194         {
3195           gtk_style_ref (widget->style);
3196           if (!saved_default_style_key_id)
3197             saved_default_style_key_id = g_quark_from_static_string (saved_default_style_key);
3198           gtk_object_set_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id, widget->style);
3199         }
3200       gtk_widget_set_style_internal (widget, new_style, initial_emission);
3201     }
3202   else
3203     {
3204       if (saved_style)
3205         {
3206           g_assert (initial_emission == FALSE); /* FIXME: remove this line */
3207
3208           gtk_object_remove_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id);
3209           gtk_widget_set_style_internal (widget, saved_style, initial_emission);
3210           gtk_style_unref (saved_style);
3211         }
3212       else
3213         {
3214           if (initial_emission)
3215             gtk_widget_set_style_internal (widget, widget->style, TRUE);
3216         }
3217     }
3218 }
3219
3220 void
3221 gtk_widget_restore_default_style (GtkWidget *widget)
3222 {
3223   GtkStyle *default_style;
3224
3225   g_return_if_fail (widget != NULL);
3226   g_return_if_fail (GTK_IS_WIDGET (widget));
3227
3228   GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE);
3229
3230   default_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id);
3231   if (default_style)
3232     {
3233       gtk_object_remove_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id);
3234       gtk_widget_set_style_internal (widget, default_style, FALSE);
3235       gtk_style_unref (default_style);
3236     }
3237 }
3238
3239 GtkStyle*
3240 gtk_widget_get_style (GtkWidget *widget)
3241 {
3242   g_return_val_if_fail (widget != NULL, NULL);
3243   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3244   
3245   return widget->style;
3246 }
3247
3248 void       
3249 gtk_widget_modify_style (GtkWidget      *widget,
3250                          GtkRcStyle     *style)
3251 {
3252   GtkRcStyle *old_style;
3253   
3254   if (!rc_style_key_id)
3255     rc_style_key_id = g_quark_from_static_string (rc_style_key);
3256
3257   old_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), rc_style_key_id);
3258
3259   if (style != old_style)
3260     gtk_object_set_data_by_id_full (GTK_OBJECT (widget),
3261                                     rc_style_key_id,
3262                                     style,
3263                                     (GtkDestroyNotify)gtk_rc_style_unref);
3264 }
3265
3266 static void
3267 gtk_widget_style_set (GtkWidget *widget,
3268                       GtkStyle  *previous_style)
3269 {
3270   if (GTK_WIDGET_REALIZED (widget) &&
3271       !GTK_WIDGET_NO_WINDOW (widget))
3272     {
3273       gtk_style_set_background (widget->style, widget->window, widget->state);
3274       if (GTK_WIDGET_DRAWABLE (widget))
3275         gdk_window_clear (widget->window);
3276     }
3277 }
3278
3279 static void
3280 gtk_widget_set_style_internal (GtkWidget *widget,
3281                                GtkStyle  *style,
3282                                gboolean   initial_emission)
3283 {
3284   g_return_if_fail (widget != NULL);
3285   g_return_if_fail (GTK_IS_WIDGET (widget));
3286   g_return_if_fail (style != NULL);
3287   
3288   if (widget->style != style)
3289     {
3290       GtkStyle *previous_style;
3291
3292       if (GTK_WIDGET_REALIZED (widget))
3293         {
3294           gtk_widget_reset_shapes (widget);
3295           gtk_style_detach (widget->style);
3296         }
3297       
3298       previous_style = widget->style;
3299       widget->style = style;
3300       gtk_style_ref (widget->style);
3301       
3302       if (GTK_WIDGET_REALIZED (widget))
3303         widget->style = gtk_style_attach (widget->style, widget->window);
3304
3305       gtk_signal_emit (GTK_OBJECT (widget),
3306                        widget_signals[STYLE_SET],
3307                        initial_emission ? NULL : previous_style);
3308       gtk_style_unref (previous_style);
3309
3310       if (widget->parent && !initial_emission)
3311         {
3312           GtkRequisition old_requisition;
3313           
3314           old_requisition = widget->requisition;
3315           gtk_widget_size_request (widget, &widget->requisition);
3316           
3317           if ((old_requisition.width != widget->requisition.width) ||
3318               (old_requisition.height != widget->requisition.height))
3319             gtk_widget_queue_resize (widget);
3320           else if (GTK_WIDGET_DRAWABLE (widget))
3321             gtk_widget_queue_clear (widget);
3322         }
3323     }
3324   else if (initial_emission)
3325     {
3326       gtk_signal_emit (GTK_OBJECT (widget),
3327                        widget_signals[STYLE_SET],
3328                        NULL);
3329     }
3330 }
3331
3332 static void
3333 gtk_widget_set_style_recurse (GtkWidget *widget,
3334                               gpointer   client_data)
3335 {
3336   if (GTK_WIDGET_RC_STYLE (widget))
3337     gtk_widget_set_rc_style (widget);
3338   
3339   if (GTK_IS_CONTAINER (widget))
3340     gtk_container_forall (GTK_CONTAINER (widget),
3341                           gtk_widget_set_style_recurse,
3342                           NULL);
3343 }
3344
3345 void
3346 gtk_widget_reset_rc_styles (GtkWidget *widget)
3347 {
3348   g_return_if_fail (widget != NULL);
3349   g_return_if_fail (GTK_IS_WIDGET (widget));
3350
3351   gtk_widget_set_style_recurse (widget, NULL);
3352 }
3353
3354 void
3355 gtk_widget_set_default_style (GtkStyle *style)
3356 {
3357   if (style != gtk_default_style)
3358      {
3359        if (gtk_default_style)
3360          gtk_style_unref (gtk_default_style);
3361        gtk_default_style = style;
3362        if (gtk_default_style)
3363          gtk_style_ref (gtk_default_style);
3364      }
3365 }
3366
3367 GtkStyle*
3368 gtk_widget_get_default_style (void)
3369 {
3370   if (!gtk_default_style)
3371     {
3372       gtk_default_style = gtk_style_new ();
3373       gtk_style_ref (gtk_default_style);
3374     }
3375   
3376   return gtk_default_style;
3377 }
3378
3379 void
3380 gtk_widget_push_style (GtkStyle *style)
3381 {
3382   g_return_if_fail (style != NULL);
3383
3384   gtk_style_ref (style);
3385   style_stack = g_slist_prepend (style_stack, style);
3386 }
3387
3388 static GtkStyle*
3389 gtk_widget_peek_style (void)
3390 {
3391   if (style_stack)
3392     return (GtkStyle*) style_stack->data;
3393   else
3394     return gtk_widget_get_default_style ();
3395 }
3396
3397 void
3398 gtk_widget_pop_style (void)
3399 {
3400   GSList *tmp;
3401   
3402   if (style_stack)
3403     {
3404       tmp = style_stack;
3405       style_stack = style_stack->next;
3406       gtk_style_unref ((GtkStyle*) tmp->data);
3407       g_slist_free_1 (tmp);
3408     }
3409 }
3410
3411 /*************************************************************
3412  * gtk_widget_set_parent_window:
3413  *     Set a non default parent window for widget
3414  *
3415  *   arguments:
3416  *     widget:
3417  *     parent_window 
3418  *     
3419  *   results:
3420  *************************************************************/
3421
3422 void
3423 gtk_widget_set_parent_window   (GtkWidget           *widget,
3424                                 GdkWindow           *parent_window)
3425 {
3426   GdkWindow *old_parent_window;
3427
3428   g_return_if_fail (widget != NULL);
3429   g_return_if_fail (GTK_IS_WIDGET (widget));
3430   
3431   old_parent_window = gtk_object_get_data_by_id (GTK_OBJECT (widget),
3432                                                  parent_window_key_id);
3433
3434   if (parent_window != old_parent_window)
3435     {
3436       if (!parent_window_key_id)
3437         parent_window_key_id = g_quark_from_static_string (parent_window_key);
3438       gtk_object_set_data_by_id (GTK_OBJECT (widget), parent_window_key_id, 
3439                                  parent_window);
3440       if (old_parent_window)
3441         gdk_window_unref (old_parent_window);
3442       if (parent_window)
3443         gdk_window_ref (parent_window);
3444     }
3445 }
3446
3447 /*************************************************************
3448  * gtk_widget_get_parent_window:
3449  *     Get widget's parent window
3450  *
3451  *   arguments:
3452  *     widget:
3453  *     
3454  *   results:
3455  *     parent window
3456  *************************************************************/
3457
3458 GdkWindow *
3459 gtk_widget_get_parent_window   (GtkWidget           *widget)
3460 {
3461   GdkWindow *parent_window;
3462
3463   g_return_val_if_fail (widget != NULL, NULL);
3464   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3465   g_return_val_if_fail (widget->parent != NULL, NULL);
3466   
3467   parent_window = gtk_object_get_data_by_id (GTK_OBJECT (widget),
3468                                              parent_window_key_id);
3469
3470   return (parent_window != NULL) ? parent_window : widget->parent->window;
3471 }
3472
3473 /*****************************************
3474  * gtk_widget_set_uposition:
3475  *
3476  *   arguments:
3477  *
3478  *   results:
3479  *****************************************/
3480
3481 void
3482 gtk_widget_set_uposition (GtkWidget *widget,
3483                           gint       x,
3484                           gint       y)
3485 {
3486   GtkWidgetAuxInfo *aux_info;
3487   
3488   g_return_if_fail (widget != NULL);
3489   g_return_if_fail (GTK_IS_WIDGET (widget));
3490   
3491   aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
3492   if (!aux_info)
3493     {
3494       if (!aux_info_key_id)
3495         aux_info_key_id = g_quark_from_static_string (aux_info_key);
3496       aux_info = gtk_widget_aux_info_new ();
3497       gtk_object_set_data_by_id (GTK_OBJECT (widget), aux_info_key_id, aux_info);
3498     }
3499   
3500   if (x > -2)
3501     aux_info->x = x;
3502   if (y > -2)
3503     aux_info->y = y;
3504   
3505   if (GTK_WIDGET_REALIZED (widget) && GTK_IS_WINDOW (widget) &&
3506       (aux_info->x != -1) && (aux_info->y != -1))
3507     {
3508       gdk_window_set_hints (widget->window, aux_info->x, aux_info->y, 0, 0, 0, 0, GDK_HINT_POS);
3509       gdk_window_move (widget->window, aux_info->x, aux_info->y);
3510     }
3511   
3512   if (GTK_WIDGET_VISIBLE (widget) && widget->parent)
3513     gtk_widget_size_allocate (widget, &widget->allocation);
3514 }
3515
3516 /*****************************************
3517  * gtk_widget_set_usize:
3518  *
3519  *   arguments:
3520  *
3521  *   results:
3522  *****************************************/
3523
3524 void
3525 gtk_widget_set_usize (GtkWidget *widget,
3526                       gint       width,
3527                       gint       height)
3528 {
3529   GtkWidgetAuxInfo *aux_info;
3530   
3531   g_return_if_fail (widget != NULL);
3532   g_return_if_fail (GTK_IS_WIDGET (widget));
3533   
3534   aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
3535   if (!aux_info)
3536     {
3537       if (!aux_info_key_id)
3538         aux_info_key_id = g_quark_from_static_string (aux_info_key);
3539       aux_info = gtk_widget_aux_info_new ();
3540       gtk_object_set_data_by_id (GTK_OBJECT (widget), aux_info_key_id, aux_info);
3541     }
3542   
3543   if (width > -2)
3544     aux_info->width = width;
3545   if (height > -2)
3546     aux_info->height = height;
3547   
3548   if (GTK_WIDGET_VISIBLE (widget))
3549     gtk_widget_queue_resize (widget);
3550 }
3551
3552 /*****************************************
3553  * gtk_widget_set_events:
3554  *
3555  *   arguments:
3556  *
3557  *   results:
3558  *****************************************/
3559
3560 void
3561 gtk_widget_set_events (GtkWidget *widget,
3562                        gint       events)
3563 {
3564   gint *eventp;
3565   
3566   g_return_if_fail (widget != NULL);
3567   g_return_if_fail (GTK_IS_WIDGET (widget));
3568   g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
3569   g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3570   
3571   eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id);
3572   
3573   if (events)
3574     {
3575       if (!eventp)
3576         eventp = g_new (gint, 1);
3577       
3578       *eventp = events;
3579       if (!event_key_id)
3580         event_key_id = g_quark_from_static_string (event_key);
3581       gtk_object_set_data_by_id (GTK_OBJECT (widget), event_key_id, eventp);
3582     }
3583   else if (eventp)
3584     {
3585       g_free (eventp);
3586       gtk_object_remove_data_by_id (GTK_OBJECT (widget), event_key_id);
3587     }
3588 }
3589
3590 /*****************************************
3591  * gtk_widget_add_events:
3592  *
3593  *   arguments:
3594  *
3595  *   results:
3596  *****************************************/
3597
3598 void
3599 gtk_widget_add_events (GtkWidget *widget,
3600                        gint       events)
3601 {
3602   gint *eventp;
3603   
3604   g_return_if_fail (widget != NULL);
3605   g_return_if_fail (GTK_IS_WIDGET (widget));
3606   g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
3607   
3608   eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id);
3609   
3610   if (events)
3611     {
3612       if (!eventp)
3613         {
3614           eventp = g_new (gint, 1);
3615           *eventp = 0;
3616         }
3617       
3618       *eventp |= events;
3619       if (!event_key_id)
3620         event_key_id = g_quark_from_static_string (event_key);
3621       gtk_object_set_data_by_id (GTK_OBJECT (widget), event_key_id, eventp);
3622     }
3623   else if (eventp)
3624     {
3625       g_free (eventp);
3626       gtk_object_remove_data_by_id (GTK_OBJECT (widget), event_key_id);
3627     }
3628
3629   if (GTK_WIDGET_REALIZED (widget))
3630     {
3631       gdk_window_set_events (widget->window,
3632                              gdk_window_get_events (widget->window) | events);
3633     }
3634 }
3635
3636 /*****************************************
3637  * gtk_widget_set_extension_events:
3638  *
3639  *   arguments:
3640  *
3641  *   results:
3642  *****************************************/
3643
3644 void
3645 gtk_widget_set_extension_events (GtkWidget *widget,
3646                                  GdkExtensionMode mode)
3647 {
3648   GdkExtensionMode *modep;
3649   
3650   g_return_if_fail (widget != NULL);
3651   g_return_if_fail (GTK_IS_WIDGET (widget));
3652   
3653   modep = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id);
3654   
3655   if (!modep)
3656     modep = g_new (GdkExtensionMode, 1);
3657   
3658   *modep = mode;
3659   if (!extension_event_key_id)
3660     extension_event_key_id = g_quark_from_static_string (extension_event_key);
3661   gtk_object_set_data_by_id (GTK_OBJECT (widget), extension_event_key_id, modep);
3662 }
3663
3664 /*****************************************
3665  * gtk_widget_get_toplevel:
3666  *
3667  *   arguments:
3668  *
3669  *   results:
3670  *****************************************/
3671
3672 GtkWidget*
3673 gtk_widget_get_toplevel (GtkWidget *widget)
3674 {
3675   g_return_val_if_fail (widget != NULL, NULL);
3676   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3677   
3678   while (widget->parent)
3679     widget = widget->parent;
3680   
3681   return widget;
3682 }
3683
3684 /*****************************************
3685  * gtk_widget_get_ancestor:
3686  *
3687  *   arguments:
3688  *
3689  *   results:
3690  *****************************************/
3691
3692 GtkWidget*
3693 gtk_widget_get_ancestor (GtkWidget *widget,
3694                          GtkType    widget_type)
3695 {
3696   g_return_val_if_fail (widget != NULL, NULL);
3697   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3698   
3699   while (widget && !gtk_type_is_a (GTK_WIDGET_TYPE (widget), widget_type))
3700     widget = widget->parent;
3701   
3702   if (!(widget && gtk_type_is_a (GTK_WIDGET_TYPE (widget), widget_type)))
3703     return NULL;
3704   
3705   return widget;
3706 }
3707
3708 /*****************************************
3709  * gtk_widget_get_colormap:
3710  *
3711  *   arguments:
3712  *
3713  *   results:
3714  *****************************************/
3715
3716 GdkColormap*
3717 gtk_widget_get_colormap (GtkWidget *widget)
3718 {
3719   GdkColormap *colormap;
3720   
3721   g_return_val_if_fail (widget != NULL, NULL);
3722   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3723   
3724   if (widget->window)
3725     {
3726       colormap = gdk_window_get_colormap (widget->window);
3727       /* If window was destroyed previously, we'll get NULL here */
3728       if (colormap)
3729         return colormap;
3730     }
3731   
3732   colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key);
3733   if (colormap)
3734     return colormap;
3735
3736   return gtk_widget_get_default_colormap ();
3737 }
3738
3739 /*****************************************
3740  * gtk_widget_get_visual:
3741  *
3742  *   arguments:
3743  *
3744  *   results:
3745  *****************************************/
3746
3747 GdkVisual*
3748 gtk_widget_get_visual (GtkWidget *widget)
3749 {
3750   GdkVisual *visual;
3751   
3752   g_return_val_if_fail (widget != NULL, NULL);
3753   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3754   
3755   if (widget->window)
3756     {
3757       visual = gdk_window_get_visual (widget->window);
3758       /* If window was destroyed previously, we'll get NULL here */
3759       if (visual)
3760         return visual;
3761     }
3762   
3763   visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key);
3764   if (visual)
3765     return visual;
3766
3767   return gtk_widget_get_default_visual ();
3768 }
3769
3770 /*****************************************
3771  * gtk_widget_get_events:
3772  *
3773  *   arguments:
3774  *
3775  *   results:
3776  *****************************************/
3777
3778 gint
3779 gtk_widget_get_events (GtkWidget *widget)
3780 {
3781   gint *events;
3782   
3783   g_return_val_if_fail (widget != NULL, 0);
3784   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
3785   
3786   events = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id);
3787   if (events)
3788     return *events;
3789   
3790   return 0;
3791 }
3792
3793 /*****************************************
3794  * gtk_widget_get_extension_events:
3795  *
3796  *   arguments:
3797  *
3798  *   results:
3799  *****************************************/
3800
3801 GdkExtensionMode
3802 gtk_widget_get_extension_events (GtkWidget *widget)
3803 {
3804   GdkExtensionMode *mode;
3805   
3806   g_return_val_if_fail (widget != NULL, 0);
3807   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
3808   
3809   mode = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id);
3810   if (mode)
3811     return *mode;
3812   
3813   return 0;
3814 }
3815
3816 /*****************************************
3817  * gtk_widget_get_pointer:
3818  *
3819  *   arguments:
3820  *
3821  *   results:
3822  *****************************************/
3823
3824 void
3825 gtk_widget_get_pointer (GtkWidget *widget,
3826                         gint      *x,
3827                         gint      *y)
3828 {
3829   g_return_if_fail (widget != NULL);
3830   g_return_if_fail (GTK_IS_WIDGET (widget));
3831   
3832   if (x)
3833     *x = -1;
3834   if (y)
3835     *y = -1;
3836   
3837   if (GTK_WIDGET_REALIZED (widget))
3838     {
3839       gdk_window_get_pointer (widget->window, x, y, NULL);
3840       
3841       if (GTK_WIDGET_NO_WINDOW (widget))
3842         {
3843           if (x)
3844             *x -= widget->allocation.x;
3845           if (y)
3846             *y -= widget->allocation.y;
3847         }
3848     }
3849 }
3850
3851 /*****************************************
3852  * gtk_widget_is_ancestor:
3853  *
3854  *   arguments:
3855  *
3856  *   results:
3857  *****************************************/
3858
3859 gint
3860 gtk_widget_is_ancestor (GtkWidget *widget,
3861                         GtkWidget *ancestor)
3862 {
3863   g_return_val_if_fail (widget != NULL, FALSE);
3864   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
3865   g_return_val_if_fail (ancestor != NULL, FALSE);
3866   
3867   while (widget)
3868     {
3869       if (widget->parent == ancestor)
3870         return TRUE;
3871       widget = widget->parent;
3872     }
3873   
3874   return FALSE;
3875 }
3876
3877 static GQuark quark_composite_name = 0;
3878
3879 void
3880 gtk_widget_set_composite_name (GtkWidget *widget,
3881                                gchar     *name)
3882 {
3883   g_return_if_fail (widget != NULL);
3884   g_return_if_fail (GTK_IS_WIDGET (widget));
3885   g_return_if_fail (GTK_WIDGET_COMPOSITE_CHILD (widget));
3886   g_return_if_fail (name != NULL);
3887
3888   if (!quark_composite_name)
3889     quark_composite_name = g_quark_from_static_string ("gtk-composite-name");
3890
3891   gtk_object_set_data_by_id_full (GTK_OBJECT (widget),
3892                                   quark_composite_name,
3893                                   g_strdup (name),
3894                                   g_free);
3895 }
3896
3897 gchar*
3898 gtk_widget_get_composite_name (GtkWidget *widget)
3899 {
3900   g_return_val_if_fail (widget != NULL, NULL);
3901   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3902
3903   if (GTK_WIDGET_COMPOSITE_CHILD (widget) && widget->parent)
3904     return gtk_container_child_composite_name (GTK_CONTAINER (widget->parent),
3905                                                widget);
3906   else
3907     return NULL;
3908 }
3909
3910 void
3911 gtk_widget_push_composite_child (void)
3912 {
3913   composite_child_stack++;
3914 }
3915
3916 void
3917 gtk_widget_pop_composite_child (void)
3918 {
3919   if (composite_child_stack)
3920     composite_child_stack--;
3921 }
3922
3923 /*****************************************
3924  * gtk_widget_push_colormap:
3925  *
3926  *   arguments:
3927  *
3928  *   results:
3929  *****************************************/
3930
3931 void
3932 gtk_widget_push_colormap (GdkColormap *cmap)
3933 {
3934   g_return_if_fail (cmap != NULL);
3935
3936   colormap_stack = g_slist_prepend (colormap_stack, cmap);
3937 }
3938
3939 /*****************************************
3940  * gtk_widget_push_visual:
3941  *
3942  *   arguments:
3943  *
3944  *   results:
3945  *****************************************/
3946
3947 void
3948 gtk_widget_push_visual (GdkVisual *visual)
3949 {
3950   g_return_if_fail (visual != NULL);
3951
3952   visual_stack = g_slist_prepend (visual_stack, visual);
3953 }
3954
3955 /*****************************************
3956  * gtk_widget_pop_colormap:
3957  *
3958  *   arguments:
3959  *
3960  *   results:
3961  *****************************************/
3962
3963 void
3964 gtk_widget_pop_colormap (void)
3965 {
3966   GSList *tmp;
3967   
3968   if (colormap_stack)
3969     {
3970       tmp = colormap_stack;
3971       colormap_stack = colormap_stack->next;
3972       g_slist_free_1 (tmp);
3973     }
3974 }
3975
3976 /*****************************************
3977  * gtk_widget_pop_visual:
3978  *
3979  *   arguments:
3980  *
3981  *   results:
3982  *****************************************/
3983
3984 void
3985 gtk_widget_pop_visual (void)
3986 {
3987   GSList *tmp;
3988   
3989   if (visual_stack)
3990     {
3991       tmp = visual_stack;
3992       visual_stack = visual_stack->next;
3993       g_slist_free_1 (tmp);
3994     }
3995 }
3996
3997 /*****************************************
3998  * gtk_widget_set_default_colormap:
3999  *
4000  *   arguments:
4001  *
4002  *   results:
4003  *****************************************/
4004
4005 void
4006 gtk_widget_set_default_colormap (GdkColormap *colormap)
4007 {
4008   if (default_colormap != colormap)
4009     {
4010       if (default_colormap)
4011         gdk_colormap_unref (default_colormap);
4012       default_colormap = colormap;
4013       if (default_colormap)
4014         gdk_colormap_ref (default_colormap);
4015     }
4016 }
4017
4018 /*****************************************
4019  * gtk_widget_set_default_visual:
4020  *
4021  *   arguments:
4022  *
4023  *   results:
4024  *****************************************/
4025
4026 void
4027 gtk_widget_set_default_visual (GdkVisual *visual)
4028 {
4029   default_visual = visual;
4030 }
4031
4032 /*****************************************
4033  * gtk_widget_get_default_colormap:
4034  *
4035  *   arguments:
4036  *
4037  *   results:
4038  *****************************************/
4039
4040 GdkColormap*
4041 gtk_widget_get_default_colormap (void)
4042 {
4043   if (!default_colormap)
4044     default_colormap = gdk_colormap_get_system ();
4045   
4046   return default_colormap;
4047 }
4048
4049 /*****************************************
4050  * gtk_widget_get_default_visual:
4051  *
4052  *   arguments:
4053  *
4054  *   results:
4055  *****************************************/
4056
4057 GdkVisual*
4058 gtk_widget_get_default_visual (void)
4059 {
4060   if (!default_visual)
4061     default_visual = gdk_visual_get_system ();
4062   
4063   return default_visual;
4064 }
4065
4066 static void
4067 gtk_widget_shutdown (GtkObject *object)
4068 {
4069   GtkWidget *widget;
4070   
4071   /* gtk_object_destroy() will already hold a refcount on object
4072    */
4073   widget = GTK_WIDGET (object);
4074
4075   if (widget->parent)
4076     gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
4077
4078   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4079   if (GTK_WIDGET_REALIZED (widget))
4080     gtk_widget_unrealize (widget);
4081   
4082   parent_class->shutdown (object);
4083 }
4084
4085 static void
4086 gtk_widget_real_destroy (GtkObject *object)
4087 {
4088   GtkWidget *widget;
4089   GtkStyle *saved_style;
4090
4091   /* gtk_object_destroy() will already hold a refcount on object
4092    */
4093   widget = GTK_WIDGET (object);
4094
4095   gtk_grab_remove (widget);
4096   gtk_selection_remove_all (widget);
4097   
4098   saved_style = gtk_object_get_data_by_id (object, saved_default_style_key_id);
4099   if (saved_style)
4100     {
4101       gtk_style_unref (saved_style);
4102       gtk_object_remove_data_by_id (object, saved_default_style_key_id);
4103     }
4104
4105   gtk_style_unref (widget->style);
4106   widget->style = NULL;
4107
4108   parent_class->destroy (object);
4109 }
4110
4111 static void
4112 gtk_widget_finalize (GtkObject *object)
4113 {
4114   GtkWidget *widget;
4115   GtkWidgetAuxInfo *aux_info;
4116   gint *events;
4117   GdkExtensionMode *mode;
4118   
4119   widget = GTK_WIDGET (object);
4120   
4121   if (widget->name)
4122     g_free (widget->name);
4123   
4124   aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id);
4125   if (aux_info)
4126     gtk_widget_aux_info_destroy (aux_info);
4127   
4128   events = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id);
4129   if (events)
4130     g_free (events);
4131   
4132   mode = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id);
4133   if (mode)
4134     g_free (mode);
4135
4136   parent_class->finalize (object);
4137 }
4138
4139 /*****************************************
4140  * gtk_widget_real_show:
4141  *
4142  *   arguments:
4143  *
4144  *   results:
4145  *****************************************/
4146
4147 static void
4148 gtk_widget_real_show (GtkWidget *widget)
4149 {
4150   g_return_if_fail (widget != NULL);
4151   g_return_if_fail (GTK_IS_WIDGET (widget));
4152   
4153   if (!GTK_WIDGET_VISIBLE (widget))
4154     {
4155       GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4156       
4157       if (widget->parent)
4158         {
4159           gtk_widget_queue_resize (widget->parent);
4160           
4161           if (GTK_WIDGET_MAPPED (widget->parent))
4162             gtk_widget_map (widget);
4163         }
4164     }
4165 }
4166
4167 /*****************************************
4168  * gtk_widget_real_hide:
4169  *
4170  *   arguments:
4171  *
4172  *   results:
4173  *****************************************/
4174
4175 static void
4176 gtk_widget_real_hide (GtkWidget *widget)
4177 {
4178   g_return_if_fail (widget != NULL);
4179   g_return_if_fail (GTK_IS_WIDGET (widget));
4180   
4181   if (GTK_WIDGET_VISIBLE (widget))
4182     {
4183       GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4184       
4185       if (GTK_WIDGET_MAPPED (widget))
4186         gtk_widget_unmap (widget);
4187       
4188       if (widget->parent)
4189         gtk_widget_queue_resize (widget->parent);
4190     }
4191 }
4192
4193 /*****************************************
4194  * gtk_widget_real_map:
4195  *
4196  *   arguments:
4197  *
4198  *   results:
4199  *****************************************/
4200
4201 static void
4202 gtk_widget_real_map (GtkWidget *widget)
4203 {
4204   g_return_if_fail (widget != NULL);
4205   g_return_if_fail (GTK_IS_WIDGET (widget));
4206   
4207   if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget))
4208     {
4209       GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4210       
4211       if (!GTK_WIDGET_NO_WINDOW (widget))
4212         gdk_window_show (widget->window);
4213       else
4214         gtk_widget_queue_draw (widget);
4215     }
4216 }
4217
4218 /*****************************************
4219  * gtk_widget_real_unmap:
4220  *
4221  *   arguments:
4222  *
4223  *   results:
4224  *****************************************/
4225
4226 static void
4227 gtk_widget_real_unmap (GtkWidget *widget)
4228 {
4229   g_return_if_fail (widget != NULL);
4230   g_return_if_fail (GTK_IS_WIDGET (widget));
4231   
4232   if (GTK_WIDGET_MAPPED (widget))
4233     {
4234       GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4235       
4236       if (GTK_WIDGET_NO_WINDOW (widget))
4237         gtk_widget_queue_clear (widget);
4238       else
4239         gdk_window_hide (widget->window);
4240     }
4241 }
4242
4243 /*****************************************
4244  * gtk_widget_real_realize:
4245  *
4246  *   arguments:
4247  *
4248  *   results:
4249  *****************************************/
4250
4251 static void
4252 gtk_widget_real_realize (GtkWidget *widget)
4253 {
4254   g_return_if_fail (widget != NULL);
4255   g_return_if_fail (GTK_IS_WIDGET (widget));
4256   g_return_if_fail (GTK_WIDGET_NO_WINDOW (widget));
4257   
4258   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4259   if (widget->parent)
4260     {
4261       widget->window = gtk_widget_get_parent_window (widget);
4262       gdk_window_ref (widget->window);
4263     }
4264   widget->style = gtk_style_attach (widget->style, widget->window);
4265 }
4266
4267 /*****************************************
4268  * gtk_widget_real_unrealize:
4269  *
4270  *   arguments:
4271  *
4272  *   results:
4273  *****************************************/
4274
4275 static void
4276 gtk_widget_real_unrealize (GtkWidget *widget)
4277 {
4278   g_return_if_fail (widget != NULL);
4279   g_return_if_fail (GTK_IS_WIDGET (widget));
4280
4281   if (GTK_WIDGET_MAPPED (widget))
4282     gtk_widget_real_unmap (widget);
4283
4284   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4285
4286   /* printf ("unrealizing %s\n", gtk_type_name (GTK_OBJECT(widget)->klass->type));
4287    */
4288
4289    /* We must do unrealize child widget BEFORE container widget.
4290     * gdk_window_destroy() destroys specified xwindow and it's sub-xwindows.
4291     * So, unrealizing container widget bofore it's children causes the problem 
4292     * (for example, gdk_ic_destroy () with destroyed window causes crash. )
4293     */
4294
4295   if (GTK_IS_CONTAINER (widget))
4296     gtk_container_foreach (GTK_CONTAINER (widget),
4297                            (GtkCallback) gtk_widget_unrealize,
4298                            NULL);
4299
4300   gtk_style_detach (widget->style);
4301   if (!GTK_WIDGET_NO_WINDOW (widget))
4302     {
4303       gdk_window_set_user_data (widget->window, NULL);
4304       gdk_window_destroy (widget->window);
4305       widget->window = NULL;
4306     }
4307   else
4308     {
4309       gdk_window_unref (widget->window);
4310       widget->window = NULL;
4311     }
4312
4313   GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
4314 }
4315
4316 /*****************************************
4317  * gtk_widget_real_draw:
4318  *
4319  *   arguments:
4320  *
4321  *   results:
4322  *****************************************/
4323
4324 static void
4325 gtk_widget_real_draw (GtkWidget    *widget,
4326                       GdkRectangle *area)
4327 {
4328   GdkEventExpose event;
4329   
4330   g_return_if_fail (widget != NULL);
4331   g_return_if_fail (GTK_IS_WIDGET (widget));
4332   g_return_if_fail (area != NULL);
4333   
4334   if (GTK_WIDGET_DRAWABLE (widget))
4335     {
4336       event.type = GDK_EXPOSE;
4337       event.send_event = TRUE;
4338       event.window = widget->window;
4339       event.area = *area;
4340       event.count = 0;
4341       
4342       gdk_window_ref (event.window);
4343       gtk_widget_event (widget, (GdkEvent*) &event);
4344       gdk_window_unref (event.window);
4345     }
4346 }
4347
4348 static void
4349 gtk_widget_real_size_request (GtkWidget         *widget,
4350                               GtkRequisition    *requisition)
4351 {
4352   g_return_if_fail (widget != NULL);
4353   g_return_if_fail (GTK_IS_WIDGET (widget));
4354
4355   requisition->width = widget->requisition.width;
4356   requisition->height = widget->requisition.height;
4357 }
4358
4359 static void
4360 gtk_widget_real_size_allocate (GtkWidget     *widget,
4361                                GtkAllocation *allocation)
4362 {
4363   g_return_if_fail (widget != NULL);
4364   g_return_if_fail (GTK_IS_WIDGET (widget));
4365
4366   if (GTK_WIDGET_NO_WINDOW (widget) &&
4367       GTK_WIDGET_MAPPED (widget) &&
4368       ((widget->allocation.x != allocation->x) ||
4369        (widget->allocation.y != allocation->y) ||
4370        (widget->allocation.width != allocation->width) ||
4371        (widget->allocation.height != allocation->height)) &&
4372       (widget->allocation.width != 0) &&
4373       (widget->allocation.height != 0))
4374     gtk_widget_queue_clear (widget);
4375   
4376   widget->allocation = *allocation;
4377   
4378   if (GTK_WIDGET_REALIZED (widget) &&
4379       !GTK_WIDGET_NO_WINDOW (widget))
4380      {
4381         gdk_window_move_resize (widget->window,
4382                                 allocation->x, allocation->y,
4383                                 allocation->width, allocation->height);
4384      }
4385 }
4386
4387 /*****************************************
4388  * gtk_widget_peek_colormap:
4389  *
4390  *   arguments:
4391  *
4392  *   results:
4393  *****************************************/
4394
4395 static GdkColormap*
4396 gtk_widget_peek_colormap (void)
4397 {
4398   if (colormap_stack)
4399     return (GdkColormap*) colormap_stack->data;
4400   return gtk_widget_get_default_colormap ();
4401 }
4402
4403 /*****************************************
4404  * gtk_widget_peek_visual:
4405  *
4406  *   arguments:
4407  *
4408  *   results:
4409  *****************************************/
4410
4411 static GdkVisual*
4412 gtk_widget_peek_visual (void)
4413 {
4414   if (visual_stack)
4415     return (GdkVisual*) visual_stack->data;
4416   return gtk_widget_get_default_visual ();
4417 }
4418
4419 static void
4420 gtk_widget_propagate_state (GtkWidget           *widget,
4421                             GtkStateData        *data)
4422 {
4423   guint8 old_state;
4424
4425   /* don't call this function with state==GTK_STATE_INSENSITIVE,
4426    * parent_sensitive==TRUE on a sensitive widget
4427    */
4428
4429   old_state = GTK_WIDGET_STATE (widget);
4430
4431   if (data->parent_sensitive)
4432     {
4433       GTK_WIDGET_SET_FLAGS (widget, GTK_PARENT_SENSITIVE);
4434
4435       if (GTK_WIDGET_IS_SENSITIVE (widget))
4436         {
4437           if (data->state_restoration)
4438             GTK_WIDGET_STATE (widget) = GTK_WIDGET_SAVED_STATE (widget);
4439           else
4440             GTK_WIDGET_STATE (widget) = data->state;
4441         }
4442       else
4443         {
4444           GTK_WIDGET_STATE (widget) = GTK_STATE_INSENSITIVE;
4445           if (!data->state_restoration &&
4446               data->state != GTK_STATE_INSENSITIVE)
4447             GTK_WIDGET_SAVED_STATE (widget) = data->state;
4448         }
4449     }
4450   else
4451     {
4452       GTK_WIDGET_UNSET_FLAGS (widget, GTK_PARENT_SENSITIVE);
4453       if (!data->state_restoration)
4454         {
4455           if (data->state != GTK_STATE_INSENSITIVE)
4456             GTK_WIDGET_SAVED_STATE (widget) = data->state;
4457         }
4458       else if (GTK_WIDGET_STATE (widget) != GTK_STATE_INSENSITIVE)
4459         GTK_WIDGET_SAVED_STATE (widget) = GTK_WIDGET_STATE (widget);
4460       GTK_WIDGET_STATE (widget) = GTK_STATE_INSENSITIVE;
4461     }
4462
4463   if (GTK_WIDGET_HAS_FOCUS (widget) && !GTK_WIDGET_IS_SENSITIVE (widget))
4464     {
4465       GtkWidget *window;
4466
4467       window = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
4468       if (window)
4469         gtk_window_set_focus (GTK_WINDOW (window), NULL);
4470     }
4471
4472   if (old_state != GTK_WIDGET_STATE (widget))
4473     {
4474       gtk_widget_ref (widget);
4475       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[STATE_CHANGED], old_state);
4476       
4477       if (GTK_IS_CONTAINER (widget))
4478         {
4479           data->parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget) != FALSE);
4480           data->state = GTK_WIDGET_STATE (widget);
4481           if (data->use_forall)
4482             gtk_container_forall (GTK_CONTAINER (widget),
4483                                   (GtkCallback) gtk_widget_propagate_state,
4484                                   data);
4485           else
4486             gtk_container_foreach (GTK_CONTAINER (widget),
4487                                    (GtkCallback) gtk_widget_propagate_state,
4488                                    data);
4489         }
4490       gtk_widget_unref (widget);
4491     }
4492 }
4493
4494 /*****************************************
4495  * gtk_widget_aux_info_new:
4496  *
4497  *   arguments:
4498  *
4499  *   results:
4500  *****************************************/
4501
4502 static GtkWidgetAuxInfo*
4503 gtk_widget_aux_info_new (void)
4504 {
4505   GtkWidgetAuxInfo *aux_info;
4506   
4507   if (!aux_info_mem_chunk)
4508     aux_info_mem_chunk = g_mem_chunk_new ("widget aux info mem chunk",
4509                                           sizeof (GtkWidgetAuxInfo),
4510                                           1024, G_ALLOC_AND_FREE);
4511   
4512   aux_info = g_chunk_new (GtkWidgetAuxInfo, aux_info_mem_chunk);
4513   
4514   aux_info->x = -1;
4515   aux_info->y = -1;
4516   aux_info->width = 0;
4517   aux_info->height = 0;
4518   
4519   return aux_info;
4520 }
4521
4522 /*****************************************
4523  * gtk_widget_aux_info_destroy:
4524  *
4525  *   arguments:
4526  *
4527  *   results:
4528  *****************************************/
4529
4530 static void
4531 gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info)
4532 {
4533   g_return_if_fail (aux_info != NULL);
4534   
4535   g_mem_chunk_free (aux_info_mem_chunk, aux_info);
4536 }
4537
4538 /*****************************************
4539  * gtk_widget_shape_combine_mask: 
4540  *   set a shape for this widgets' gdk window, this allows for
4541  *   transparent windows etc., see gdk_window_shape_combine_mask
4542  *   for more information
4543  *
4544  *   arguments:
4545  *
4546  *   results:
4547  *****************************************/
4548 void
4549 gtk_widget_shape_combine_mask (GtkWidget *widget,
4550                                GdkBitmap *shape_mask,
4551                                gint       offset_x,
4552                                gint       offset_y)
4553 {
4554   GtkWidgetShapeInfo* shape_info;
4555   
4556   g_return_if_fail (widget != NULL);
4557   g_return_if_fail (GTK_IS_WIDGET (widget));
4558   /*  set_shape doesn't work on widgets without gdk window */
4559   g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
4560
4561   if (!shape_mask)
4562     {
4563       GTK_PRIVATE_UNSET_FLAG (widget, GTK_HAS_SHAPE_MASK);
4564       
4565       if (widget->window)
4566         gdk_window_shape_combine_mask (widget->window, NULL, 0, 0);
4567       
4568       shape_info = gtk_object_get_data (GTK_OBJECT (widget), shape_info_key);
4569       gtk_object_remove_data (GTK_OBJECT (widget), shape_info_key);
4570       g_free (shape_info);
4571     }
4572   else
4573     {
4574       GTK_PRIVATE_SET_FLAG (widget, GTK_HAS_SHAPE_MASK);
4575       
4576       shape_info = gtk_object_get_data (GTK_OBJECT (widget), shape_info_key);
4577       if (!shape_info)
4578         {
4579           shape_info = g_new (GtkWidgetShapeInfo, 1);
4580           gtk_object_set_data (GTK_OBJECT (widget), shape_info_key, shape_info);
4581         }
4582       shape_info->shape_mask = shape_mask;
4583       shape_info->offset_x = offset_x;
4584       shape_info->offset_y = offset_y;
4585       
4586       /* set shape if widget has a gdk window allready.
4587        * otherwise the shape is scheduled to be set by gtk_widget_realize.
4588        */
4589       if (widget->window)
4590         gdk_window_shape_combine_mask (widget->window, shape_mask,
4591                                        offset_x, offset_y);
4592     }
4593 }
4594
4595 static void
4596 gtk_reset_shapes_recurse (GtkWidget *widget,
4597                           GdkWindow *window)
4598 {
4599   GdkWindowPrivate *private;
4600   gpointer data;
4601   GList *list;
4602
4603   private = (GdkWindowPrivate*) window;
4604
4605   if (private->destroyed)
4606     return;
4607   gdk_window_get_user_data (window, &data);
4608   if (data != widget)
4609     return;
4610
4611   gdk_window_shape_combine_mask (window, NULL, 0, 0);
4612   for (list = private->children; list; list = list->next)
4613     gtk_reset_shapes_recurse (widget, list->data);
4614 }
4615
4616 void
4617 gtk_widget_reset_shapes (GtkWidget *widget)
4618 {
4619   g_return_if_fail (widget != NULL);
4620   g_return_if_fail (GTK_IS_WIDGET (widget));
4621   g_return_if_fail (GTK_WIDGET_REALIZED (widget));
4622
4623   if (!GTK_WIDGET_HAS_SHAPE_MASK (widget))
4624     gtk_reset_shapes_recurse (widget, widget->window);
4625 }
4626
4627 void
4628 gtk_widget_ref (GtkWidget *widget)
4629 {
4630   g_return_if_fail (widget != NULL);
4631   g_return_if_fail (GTK_IS_WIDGET (widget));
4632
4633   gtk_object_ref ((GtkObject*) widget);
4634 }
4635
4636 void
4637 gtk_widget_unref (GtkWidget *widget)
4638 {
4639   g_return_if_fail (widget != NULL);
4640   g_return_if_fail (GTK_IS_WIDGET (widget));
4641
4642   gtk_object_unref ((GtkObject*) widget);
4643 }
4644
4645 void
4646 gtk_widget_path (GtkWidget *widget,
4647                  guint     *path_length_p,
4648                  gchar    **path_p,
4649                  gchar    **path_reversed_p)
4650 {
4651   static gchar *rev_path = NULL;
4652   static guint  path_len = 0;
4653   guint len;
4654   
4655   g_return_if_fail (widget != NULL);
4656   g_return_if_fail (GTK_IS_WIDGET (widget));
4657   
4658   len = 0;
4659   do
4660     {
4661       gchar *string;
4662       gchar *d, *s;
4663       guint l;
4664       
4665       string = gtk_widget_get_name (widget);
4666       l = strlen (string);
4667       while (path_len <= len + l + 1)
4668         {
4669           path_len += INIT_PATH_SIZE;
4670           rev_path = g_realloc (rev_path, path_len);
4671         }
4672       s = string + l - 1;
4673       d = rev_path + len;
4674       while (s >= string)
4675         *(d++) = *(s--);
4676       len += l;
4677       
4678       widget = widget->parent;
4679       
4680       if (widget)
4681         rev_path[len++] = '.';
4682       else
4683         rev_path[len++] = 0;
4684     }
4685   while (widget);
4686   
4687   if (path_length_p)
4688     *path_length_p = len - 1;
4689   if (path_reversed_p)
4690     *path_reversed_p = g_strdup (rev_path);
4691   if (path_p)
4692     {
4693       *path_p = g_strdup (rev_path);
4694       g_strreverse (*path_p);
4695     }
4696 }
4697
4698 void
4699 gtk_widget_class_path (GtkWidget *widget,
4700                        guint     *path_length_p,
4701                        gchar    **path_p,
4702                        gchar    **path_reversed_p)
4703 {
4704   static gchar *rev_path = NULL;
4705   static guint  path_len = 0;
4706   guint len;
4707   
4708   g_return_if_fail (widget != NULL);
4709   g_return_if_fail (GTK_IS_WIDGET (widget));
4710   
4711   len = 0;
4712   do
4713     {
4714       gchar *string;
4715       gchar *d, *s;
4716       guint l;
4717       
4718       string = gtk_type_name (GTK_WIDGET_TYPE (widget));
4719       l = strlen (string);
4720       while (path_len <= len + l + 1)
4721         {
4722           path_len += INIT_PATH_SIZE;
4723           rev_path = g_realloc (rev_path, path_len);
4724         }
4725       s = string + l - 1;
4726       d = rev_path + len;
4727       while (s >= string)
4728         *(d++) = *(s--);
4729       len += l;
4730       
4731       widget = widget->parent;
4732       
4733       if (widget)
4734         rev_path[len++] = '.';
4735       else
4736         rev_path[len++] = 0;
4737     }
4738   while (widget);
4739   
4740   if (path_length_p)
4741     *path_length_p = len - 1;
4742   if (path_reversed_p)
4743     *path_reversed_p = g_strdup (rev_path);
4744   if (path_p)
4745     {
4746       *path_p = g_strdup (rev_path);
4747       g_strreverse (*path_p);
4748     }
4749 }