]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
cleanups for color changing stuff
[~andy/gtk] / gtk / gtkwindow.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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <string.h>
19 #include <limits.h>
20 #include "gdk/gdk.h"
21 #include "gdk/gdkkeysyms.h"
22 #include "gdk/gdkx.h"
23 #include "gtksignal.h"
24 #include "gtkwindow.h"
25
26 enum {
27   MOVE_RESIZE,
28   LAST_SIGNAL
29 };
30
31
32 typedef gint (*GtkWindowSignal1) (GtkObject *object,
33                                   gpointer   arg1,
34                                   gpointer   arg2,
35                                   gint       arg3,
36                                   gint       arg4,
37                                   gpointer   data);
38
39
40 static void gtk_window_marshal_signal_1 (GtkObject      *object,
41                                          GtkSignalFunc   func,
42                                          gpointer        func_data,
43                                          GtkArg         *args);
44
45 static void gtk_window_class_init         (GtkWindowClass    *klass);
46 static void gtk_window_init               (GtkWindow         *window);
47 static void gtk_window_arg                (GtkWindow         *window,
48                                            GtkArg            *arg);
49 static void gtk_window_destroy            (GtkObject         *object);
50 static void gtk_window_show               (GtkWidget         *widget);
51 static void gtk_window_hide               (GtkWidget         *widget);
52 static void gtk_window_map                (GtkWidget         *widget);
53 static void gtk_window_unmap              (GtkWidget         *widget);
54 static void gtk_window_realize            (GtkWidget         *widget);
55 static void gtk_window_size_request       (GtkWidget         *widget,
56                                            GtkRequisition    *requisition);
57 static void gtk_window_size_allocate      (GtkWidget         *widget,
58                                            GtkAllocation     *allocation);
59 static gint gtk_window_expose_event       (GtkWidget         *widget,
60                                            GdkEventExpose    *event);
61 static gint gtk_window_configure_event    (GtkWidget         *widget,
62                                            GdkEventConfigure *event);
63 static gint gtk_window_key_press_event    (GtkWidget         *widget,
64                                            GdkEventKey       *event);
65 static gint gtk_window_key_release_event  (GtkWidget         *widget,
66                                            GdkEventKey       *event);
67 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
68                                            GdkEventCrossing  *event);
69 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
70                                            GdkEventCrossing  *event);
71 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
72                                            GdkEventFocus     *event);
73 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
74                                            GdkEventFocus     *event);
75 static gint gtk_window_client_event       (GtkWidget         *widget,
76                                            GdkEventClient    *event);
77 static gint gtk_window_need_resize        (GtkContainer      *container);
78 static gint gtk_real_window_move_resize   (GtkWindow         *window,
79                                            gint              *x,
80                                            gint              *y,
81                                            gint               width,
82                                            gint               height);
83 static gint gtk_window_move_resize        (GtkWidget         *widget);
84 static void gtk_window_set_hints          (GtkWidget         *widget,
85                                            GtkRequisition    *requisition);
86 static gint gtk_window_check_accelerator  (GtkWindow         *window,
87                                            gint               key,
88                                            guint              mods);
89
90
91 static GtkBinClass *parent_class = NULL;
92 static gint window_signals[LAST_SIGNAL] = { 0 };
93
94
95 guint
96 gtk_window_get_type ()
97 {
98   static guint window_type = 0;
99
100   if (!window_type)
101     {
102       GtkTypeInfo window_info =
103       {
104         "GtkWindow",
105         sizeof (GtkWindow),
106         sizeof (GtkWindowClass),
107         (GtkClassInitFunc) gtk_window_class_init,
108         (GtkObjectInitFunc) gtk_window_init,
109         (GtkArgFunc) gtk_window_arg,
110       };
111
112       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
113     }
114
115   return window_type;
116 }
117
118 static void
119 gtk_window_class_init (GtkWindowClass *klass)
120 {
121   GtkObjectClass *object_class;
122   GtkWidgetClass *widget_class;
123   GtkContainerClass *container_class;
124
125   object_class = (GtkObjectClass*) klass;
126   widget_class = (GtkWidgetClass*) klass;
127   container_class = (GtkContainerClass*) klass;
128
129   parent_class = gtk_type_class (gtk_bin_get_type ());
130
131   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE);
132   gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING);
133   gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL);
134   gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL);
135   gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL);
136
137   window_signals[MOVE_RESIZE] =
138     gtk_signal_new ("move_resize",
139                     GTK_RUN_LAST,
140                     object_class->type,
141                     GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
142                     gtk_window_marshal_signal_1,
143                     GTK_TYPE_BOOL, 4,
144                     GTK_TYPE_POINTER, GTK_TYPE_POINTER,
145                     GTK_TYPE_INT, GTK_TYPE_INT);
146
147   gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
148
149   object_class->destroy = gtk_window_destroy;
150
151   widget_class->show = gtk_window_show;
152   widget_class->hide = gtk_window_hide;
153   widget_class->map = gtk_window_map;
154   widget_class->unmap = gtk_window_unmap;
155   widget_class->realize = gtk_window_realize;
156   widget_class->size_request = gtk_window_size_request;
157   widget_class->size_allocate = gtk_window_size_allocate;
158   widget_class->expose_event = gtk_window_expose_event;
159   widget_class->configure_event = gtk_window_configure_event;
160   widget_class->key_press_event = gtk_window_key_press_event;
161   widget_class->key_release_event = gtk_window_key_release_event;
162   widget_class->enter_notify_event = gtk_window_enter_notify_event;
163   widget_class->leave_notify_event = gtk_window_leave_notify_event;
164   widget_class->focus_in_event = gtk_window_focus_in_event;
165   widget_class->focus_out_event = gtk_window_focus_out_event;
166   widget_class->client_event = gtk_window_client_event;
167
168   container_class->need_resize = gtk_window_need_resize;
169
170   klass->move_resize = gtk_real_window_move_resize;
171 }
172
173 static void
174 gtk_window_init (GtkWindow *window)
175 {
176   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
177   GTK_WIDGET_SET_FLAGS (window, GTK_ANCHORED);
178
179   window->title = NULL;
180   window->wmclass_name = NULL;
181   window->wmclass_class = NULL;
182   window->type = GTK_WINDOW_TOPLEVEL;
183   window->accelerator_tables = NULL;
184   window->focus_widget = NULL;
185   window->default_widget = NULL;
186   window->resize_count = 0;
187   window->need_resize = FALSE;
188   window->allow_shrink = FALSE;
189   window->allow_grow = TRUE;
190   window->auto_shrink = FALSE;
191   window->handling_resize = FALSE;
192   window->position = GTK_WIN_POS_NONE;
193   window->use_uposition = TRUE;
194 }
195
196 static void
197 gtk_window_arg (GtkWindow *window,
198                 GtkArg    *arg)
199 {
200   if (strcmp (arg->name, "type") == 0)
201     {
202       window->type = GTK_VALUE_ENUM(*arg);
203     }
204   else if (strcmp (arg->name, "title") == 0)
205     {
206       gtk_window_set_title (window, GTK_VALUE_STRING(*arg));
207     }
208   else if (strcmp (arg->name, "auto_shrink") == 0)
209     {
210       window->auto_shrink = (GTK_VALUE_BOOL(*arg) != FALSE);
211     }
212   else if (strcmp (arg->name, "allow_shrink") == 0)
213     {
214       window->allow_shrink = (GTK_VALUE_BOOL(*arg) != FALSE);
215     }
216   else if (strcmp (arg->name, "allow_grow") == 0)
217     {
218       window->allow_grow = (GTK_VALUE_BOOL(*arg) != FALSE);
219     }
220 }
221
222 GtkWidget*
223 gtk_window_new (GtkWindowType type)
224 {
225   GtkWindow *window;
226
227   window = gtk_type_new (gtk_window_get_type ());
228
229   window->type = type;
230
231   return GTK_WIDGET (window);
232 }
233
234 void
235 gtk_window_set_title (GtkWindow   *window,
236                       const gchar *title)
237 {
238   g_return_if_fail (window != NULL);
239   g_return_if_fail (GTK_IS_WINDOW (window));
240
241   if (window->title)
242     g_free (window->title);
243   window->title = g_strdup (title);
244
245   if (GTK_WIDGET_REALIZED (window))
246     gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
247 }
248
249 void
250 gtk_window_set_wmclass (GtkWindow *window,
251                         gchar     *wmclass_name,
252                         gchar     *wmclass_class)
253 {
254   g_return_if_fail (window != NULL);
255   g_return_if_fail (GTK_IS_WINDOW (window));
256
257   if (window->wmclass_name)
258     g_free (window->wmclass_name);
259   window->wmclass_name = g_strdup (wmclass_name);
260
261   if (window->wmclass_class)
262     g_free (window->wmclass_class);
263   window->wmclass_class = g_strdup (wmclass_class);
264
265   if (GTK_WIDGET_REALIZED (window))
266     g_warning ("shouldn't set wmclass after window is realized!\n");
267 }
268
269 void
270 gtk_window_set_focus (GtkWindow *window,
271                       GtkWidget *focus)
272 {
273   GdkEventFocus event;
274
275   g_return_if_fail (window != NULL);
276   g_return_if_fail (GTK_IS_WINDOW (window));
277
278   if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
279     return;
280
281   if (window->focus_widget != focus)
282     {
283       if (window->focus_widget)
284         {
285           event.type = GDK_FOCUS_CHANGE;
286           event.window = window->focus_widget->window;
287           event.in = FALSE;
288
289           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
290         }
291
292       window->focus_widget = focus;
293
294       if (window->focus_widget)
295         {
296           event.type = GDK_FOCUS_CHANGE;
297           event.window = window->focus_widget->window;
298           event.in = TRUE;
299
300           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
301         }
302     }
303 }
304
305 void
306 gtk_window_set_default (GtkWindow *window,
307                         GtkWidget *defaultw)
308 {
309   g_return_if_fail (window != NULL);
310   g_return_if_fail (GTK_IS_WINDOW (window));
311   g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (defaultw));
312
313   if (window->default_widget != defaultw)
314     {
315       if (window->default_widget)
316         {
317           GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
318           gtk_widget_draw_default (window->default_widget);
319         }
320
321       window->default_widget = defaultw;
322
323       if (window->default_widget)
324         {
325           GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
326           gtk_widget_draw_default (window->default_widget);
327         }
328     }
329 }
330
331 void
332 gtk_window_set_policy (GtkWindow *window,
333                        gint       allow_shrink,
334                        gint       allow_grow,
335                        gint       auto_shrink)
336 {
337   g_return_if_fail (window != NULL);
338   g_return_if_fail (GTK_IS_WINDOW (window));
339
340   window->allow_shrink = (allow_shrink != FALSE);
341   window->allow_grow = (allow_grow != FALSE);
342   window->auto_shrink = (auto_shrink != FALSE);
343 }
344
345 void
346 gtk_window_add_accelerator_table (GtkWindow           *window,
347                                   GtkAcceleratorTable *table)
348 {
349   g_return_if_fail (window != NULL);
350   g_return_if_fail (GTK_IS_WINDOW (window));
351
352   gtk_accelerator_table_ref (table);
353   window->accelerator_tables = g_list_prepend (window->accelerator_tables, table);
354 }
355
356 void
357 gtk_window_remove_accelerator_table (GtkWindow           *window,
358                                      GtkAcceleratorTable *table)
359 {
360   g_return_if_fail (window != NULL);
361   g_return_if_fail (GTK_IS_WINDOW (window));
362
363   window->accelerator_tables = g_list_remove (window->accelerator_tables, table);
364   gtk_accelerator_table_unref (table);
365 }
366
367 void
368 gtk_window_position (GtkWindow         *window,
369                      GtkWindowPosition  position)
370 {
371   g_return_if_fail (window != NULL);
372   g_return_if_fail (GTK_IS_WINDOW (window));
373
374   window->position = position;
375 }
376
377 static void
378 gtk_window_marshal_signal_1 (GtkObject      *object,
379                              GtkSignalFunc   func,
380                              gpointer        func_data,
381                              GtkArg         *args)
382 {
383   GtkWindowSignal1 rfunc;
384   gint *return_val;
385
386   rfunc = (GtkWindowSignal1) func;
387   return_val = GTK_RETLOC_BOOL (args[4]);
388
389   *return_val = (* rfunc) (object,
390                            GTK_VALUE_POINTER (args[0]),
391                            GTK_VALUE_POINTER (args[1]),
392                            GTK_VALUE_INT (args[2]),
393                            GTK_VALUE_INT (args[3]),
394                            func_data);
395 }
396
397 static void
398 gtk_window_destroy (GtkObject *object)
399 {
400   GtkWindow *window;
401
402   g_return_if_fail (object != NULL);
403   g_return_if_fail (GTK_IS_WINDOW (object));
404
405   window = GTK_WINDOW (object);
406   g_free (window->title);
407
408   if (GTK_OBJECT_CLASS (parent_class)->destroy)
409     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
410 }
411
412 static void
413 gtk_window_show (GtkWidget *widget)
414 {
415   g_return_if_fail (widget != NULL);
416   g_return_if_fail (GTK_IS_WINDOW (widget));
417
418   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
419   gtk_widget_map (widget);
420 }
421
422 static void
423 gtk_window_hide (GtkWidget *widget)
424 {
425   g_return_if_fail (widget != NULL);
426   g_return_if_fail (GTK_IS_WINDOW (widget));
427
428   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
429   gtk_widget_unmap (widget);
430 }
431
432 static void
433 gtk_window_map (GtkWidget *widget)
434 {
435   GtkWindow *window;
436
437   g_return_if_fail (widget != NULL);
438   g_return_if_fail (GTK_IS_WINDOW (widget));
439
440   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
441   GTK_WIDGET_UNSET_FLAGS (widget, GTK_UNMAPPED);
442
443   gtk_window_move_resize (widget);
444   window = GTK_WINDOW (widget);
445
446   if (window->bin.child &&
447       GTK_WIDGET_VISIBLE (window->bin.child) &&
448       !GTK_WIDGET_MAPPED (window->bin.child))
449     gtk_widget_map (window->bin.child);
450
451   gtk_window_set_hints (widget, &widget->requisition);
452   gdk_window_show (widget->window);
453 }
454
455 static void
456 gtk_window_unmap (GtkWidget *widget)
457 {
458   GtkWindow *window;
459
460   g_return_if_fail (widget != NULL);
461   g_return_if_fail (GTK_IS_WINDOW (widget));
462
463   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
464   GTK_WIDGET_SET_FLAGS (widget, GTK_UNMAPPED);
465   gdk_window_hide (widget->window);
466
467   window = GTK_WINDOW (widget);
468   window->use_uposition = TRUE;
469 }
470
471 static void
472 gtk_window_realize (GtkWidget *widget)
473 {
474   GtkWindow *window;
475   GdkWindowAttr attributes;
476   gint attributes_mask;
477
478   g_return_if_fail (widget != NULL);
479   g_return_if_fail (GTK_IS_WINDOW (widget));
480
481   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
482   window = GTK_WINDOW (widget);
483
484   switch (window->type)
485     {
486     case GTK_WINDOW_TOPLEVEL:
487       attributes.window_type = GDK_WINDOW_TOPLEVEL;
488       break;
489     case GTK_WINDOW_DIALOG:
490       attributes.window_type = GDK_WINDOW_DIALOG;
491       break;
492     case GTK_WINDOW_POPUP:
493       attributes.window_type = GDK_WINDOW_TEMP;
494       break;
495     }
496
497   attributes.title = window->title;
498   attributes.wmclass_name = window->wmclass_name;
499   attributes.wmclass_class = window->wmclass_class;
500   attributes.width = widget->allocation.width;
501   attributes.height = widget->allocation.height;
502   attributes.wclass = GDK_INPUT_OUTPUT;
503   attributes.visual = gtk_widget_get_visual (widget);
504   attributes.colormap = gtk_widget_get_colormap (widget);
505   attributes.event_mask = gtk_widget_get_events (widget);
506   attributes.event_mask |= (GDK_EXPOSURE_MASK |
507                             GDK_KEY_PRESS_MASK |
508                             GDK_ENTER_NOTIFY_MASK |
509                             GDK_LEAVE_NOTIFY_MASK |
510                             GDK_FOCUS_CHANGE_MASK |
511                             GDK_STRUCTURE_MASK);
512
513   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
514   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
515   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
516
517   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
518   gdk_window_set_user_data (widget->window, window);
519
520   widget->style = gtk_style_attach (widget->style, widget->window);
521   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
522 }
523
524 static void
525 gtk_window_size_request (GtkWidget      *widget,
526                          GtkRequisition *requisition)
527 {
528   GtkWindow *window;
529
530   g_return_if_fail (widget != NULL);
531   g_return_if_fail (GTK_IS_WINDOW (widget));
532   g_return_if_fail (requisition != NULL);
533
534   window = GTK_WINDOW (widget);
535
536   if (window->bin.child)
537     {
538       requisition->width = GTK_CONTAINER (window)->border_width * 2;
539       requisition->height = GTK_CONTAINER (window)->border_width * 2;
540
541       gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
542
543       requisition->width += window->bin.child->requisition.width;
544       requisition->height += window->bin.child->requisition.height;
545     }
546   else
547     {
548       if (!GTK_WIDGET_VISIBLE (window))
549         window->need_resize = TRUE;
550     }
551 }
552
553 static void
554 gtk_window_size_allocate (GtkWidget     *widget,
555                           GtkAllocation *allocation)
556 {
557   GtkWindow *window;
558   GtkAllocation child_allocation;
559
560   g_return_if_fail (widget != NULL);
561   g_return_if_fail (GTK_IS_WINDOW (widget));
562   g_return_if_fail (allocation != NULL);
563
564   window = GTK_WINDOW (widget);
565   widget->allocation = *allocation;
566
567   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
568     {
569       child_allocation.x = GTK_CONTAINER (window)->border_width;
570       child_allocation.y = GTK_CONTAINER (window)->border_width;
571       child_allocation.width = allocation->width - child_allocation.x * 2;
572       child_allocation.height = allocation->height - child_allocation.y * 2;
573
574       gtk_widget_size_allocate (window->bin.child, &child_allocation);
575     }
576 }
577
578 static gint
579 gtk_window_expose_event (GtkWidget      *widget,
580                          GdkEventExpose *event)
581 {
582   g_return_val_if_fail (widget != NULL, FALSE);
583   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
584   g_return_val_if_fail (event != NULL, FALSE);
585
586   if (!GTK_WIDGET_UNMAPPED (widget))
587     GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
588
589   if (GTK_WIDGET_DRAWABLE (widget))
590     if (GTK_WIDGET_CLASS (parent_class)->expose_event)
591       return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
592
593   return FALSE;
594 }
595
596 static gint
597 gtk_window_configure_event (GtkWidget         *widget,
598                             GdkEventConfigure *event)
599 {
600   GtkWindow *window;
601   GtkAllocation allocation;
602
603   g_return_val_if_fail (widget != NULL, FALSE);
604   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
605   g_return_val_if_fail (event != NULL, FALSE);
606
607   window = GTK_WINDOW (widget);
608   window->handling_resize = TRUE;
609
610   allocation.x = 0;
611   allocation.y = 0;
612   allocation.width = event->width;
613   allocation.height = event->height;
614
615   gtk_widget_size_allocate (widget, &allocation);
616
617   if (window->bin.child &&
618       GTK_WIDGET_VISIBLE (window->bin.child) &&
619       !GTK_WIDGET_MAPPED (window->bin.child))
620     gtk_widget_map (window->bin.child);
621
622   window->resize_count -= 1;
623   if (window->resize_count == 0)
624     {
625       if ((event->width != widget->requisition.width) ||
626           (event->height != widget->requisition.height))
627         {
628           window->resize_count += 1;
629           gdk_window_resize (widget->window,
630                              widget->requisition.width,
631                              widget->requisition.height);
632         }
633     }
634   else if (window->resize_count < 0)
635     {
636       window->resize_count = 0;
637     }
638
639   window->handling_resize = FALSE;
640
641   return FALSE;
642 }
643
644 static gint
645 gtk_window_key_press_event (GtkWidget   *widget,
646                             GdkEventKey *event)
647 {
648   GtkWindow *window;
649   GtkDirectionType direction = 0;
650   gint return_val;
651
652   g_return_val_if_fail (widget != NULL, FALSE);
653   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
654   g_return_val_if_fail (event != NULL, FALSE);
655
656   window = GTK_WINDOW (widget);
657
658   return_val = FALSE;
659   if (window->focus_widget)
660     return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
661
662   if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
663     return_val = TRUE;
664
665   if (!return_val)
666     {
667       switch (event->keyval)
668         {
669         case GDK_space:
670           if (window->focus_widget)
671             {
672               gtk_widget_activate (window->focus_widget);
673               return_val = TRUE;
674             }
675           break;
676         case GDK_Return:
677         case GDK_KP_Enter:
678           if (window->default_widget)
679             {
680               gtk_widget_activate (window->default_widget);
681               return_val = TRUE;
682             }
683           else if (window->focus_widget)
684             {
685               gtk_widget_activate (window->focus_widget);
686               return_val = TRUE;
687             }
688           break;
689         case GDK_Up:
690         case GDK_Down:
691         case GDK_Left:
692         case GDK_Right:
693         case GDK_Tab:
694           switch (event->keyval)
695             {
696             case GDK_Up:
697               direction = GTK_DIR_UP;
698               break;
699             case GDK_Down:
700               direction = GTK_DIR_DOWN;
701               break;
702             case GDK_Left:
703               direction = GTK_DIR_LEFT;
704               break;
705             case GDK_Right:
706               direction = GTK_DIR_RIGHT;
707               break;
708             case GDK_Tab:
709               if (event->state & GDK_SHIFT_MASK)
710                 direction = GTK_DIR_TAB_BACKWARD;
711               else
712                 direction = GTK_DIR_TAB_FORWARD;
713               break;
714             default :
715               direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
716             }
717
718           gtk_container_focus (GTK_CONTAINER (widget), direction);
719
720           if (!GTK_CONTAINER (window)->focus_child)
721             gtk_window_set_focus (GTK_WINDOW (widget), NULL);
722           else
723             return_val = TRUE;
724           break;
725         }
726     }
727
728   return return_val;
729 }
730
731 static gint
732 gtk_window_key_release_event (GtkWidget   *widget,
733                               GdkEventKey *event)
734 {
735   GtkWindow *window;
736   gint return_val;
737
738   g_return_val_if_fail (widget != NULL, FALSE);
739   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
740   g_return_val_if_fail (event != NULL, FALSE);
741
742   window = GTK_WINDOW (widget);
743   if (window->focus_widget)
744     return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
745
746   return return_val;
747 }
748
749 static gint
750 gtk_window_enter_notify_event (GtkWidget        *widget,
751                                GdkEventCrossing *event)
752 {
753   g_return_val_if_fail (widget != NULL, FALSE);
754   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
755   g_return_val_if_fail (event != NULL, FALSE);
756
757   return FALSE;
758 }
759
760 static gint
761 gtk_window_leave_notify_event (GtkWidget        *widget,
762                                GdkEventCrossing *event)
763 {
764   g_return_val_if_fail (widget != NULL, FALSE);
765   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
766   g_return_val_if_fail (event != NULL, FALSE);
767
768   return FALSE;
769 }
770
771 static gint
772 gtk_window_focus_in_event (GtkWidget     *widget,
773                            GdkEventFocus *event)
774 {
775   GtkWindow *window;
776   GdkEventFocus fevent;
777
778   g_return_val_if_fail (widget != NULL, FALSE);
779   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
780   g_return_val_if_fail (event != NULL, FALSE);
781
782   /* It appears spurious focus in events can occur when
783    *  the window is hidden. So we'll just check to see if
784    *  the window is visible before actually handling the
785    *  event
786    */
787   if (GTK_WIDGET_VISIBLE (widget))
788     {
789       window = GTK_WINDOW (widget);
790       if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
791         {
792           fevent.type = GDK_FOCUS_CHANGE;
793           fevent.window = window->focus_widget->window;
794           fevent.in = TRUE;
795
796           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
797         }
798     }
799
800   return FALSE;
801 }
802
803 static gint
804 gtk_window_focus_out_event (GtkWidget     *widget,
805                             GdkEventFocus *event)
806 {
807   GtkWindow *window;
808   GdkEventFocus fevent;
809
810   g_return_val_if_fail (widget != NULL, FALSE);
811   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
812   g_return_val_if_fail (event != NULL, FALSE);
813
814   window = GTK_WINDOW (widget);
815   if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
816     {
817       fevent.type = GDK_FOCUS_CHANGE;
818       fevent.window = window->focus_widget->window;
819       fevent.in = FALSE;
820
821       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
822     }
823
824   return FALSE;
825 }
826
827 static void
828 gtk_window_style_set_event (GtkWidget *widget,
829                             GdkEventClient *event)
830 {
831   GdkAtom atom_default_colors;
832   GtkStyle *style_newdefault;
833   GdkAtom realtype;
834   gint retfmt, retlen;
835   GdkColor *data, *stylecolors;
836   int i = 0, j;
837   GdkColormap *widget_cmap;
838   
839   atom_default_colors = gdk_atom_intern("_GTK_DEFAULT_COLORS", FALSE);
840   
841   if(gdk_property_get (GDK_ROOT_PARENT(),
842                        atom_default_colors,
843                        GDK_NONE,
844                        0,
845                        sizeof(GdkColor) * GTK_STYLE_NUM_STYLECOLORS(),
846                        FALSE,
847                        &realtype,
848                        &retfmt,
849                        &retlen,
850                        (guchar **)&data) != TRUE
851      || retfmt != sizeof(gushort)) {
852     g_warning("gdk_property_get() failed in _GTK_STYLE_CHANGED\n");
853     return;
854   }
855   /* We have the color data, now let's interpret it */
856   style_newdefault = gtk_widget_get_default_style();
857   gtk_style_ref(style_newdefault);
858   stylecolors = (GdkColor *) style_newdefault;
859
860   widget_cmap = gtk_widget_get_colormap(widget);
861   for(i = 0; i < GTK_STYLE_NUM_STYLECOLORS(); i++) {
862     stylecolors[i] = data[i];
863     gdk_color_alloc(widget_cmap, &stylecolors[i]);
864   }
865
866   gtk_widget_set_default_style(style_newdefault);
867   gtk_style_unref(style_newdefault);
868
869   /* Now we need to redraw everything */
870   gtk_widget_draw(widget, NULL);
871   gtk_widget_draw_children(widget);
872 }
873
874 static gint
875 gtk_window_client_event (GtkWidget      *widget,
876                          GdkEventClient *event)
877 {
878   GdkAtom atom_styleset;
879   g_return_val_if_fail (widget != NULL, FALSE);
880   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
881   g_return_val_if_fail (event != NULL, FALSE);
882
883   atom_styleset = gdk_atom_intern("_GTK_STYLE_CHANGED", FALSE);
884
885   if(event->message_type == atom_styleset) {
886     gtk_window_style_set_event(widget, event);    
887   }
888   return FALSE;
889 }
890
891 static gint
892 gtk_window_need_resize (GtkContainer *container)
893 {
894   GtkWindow *window;
895   gint return_val;
896
897   g_return_val_if_fail (container != NULL, FALSE);
898   g_return_val_if_fail (GTK_IS_WINDOW (container), FALSE);
899
900   return_val = FALSE;
901
902   window = GTK_WINDOW (container);
903   if (window->handling_resize)
904     return return_val;
905
906   if (GTK_WIDGET_VISIBLE (container))
907     {
908       window->need_resize = TRUE;
909       return_val = gtk_window_move_resize (GTK_WIDGET (window));
910       window->need_resize = FALSE;
911     }
912
913   return return_val;
914 }
915
916 static gint
917 gtk_real_window_move_resize (GtkWindow *window,
918                              gint      *x,
919                              gint      *y,
920                              gint       width,
921                              gint       height)
922 {
923   GtkWidget *widget;
924   GtkWidget *resize_container;
925   GSList *resize_widgets;
926   GSList *resize_containers;
927   GSList *tmp_list;
928   gint return_val;
929
930   g_return_val_if_fail (window != NULL, FALSE);
931   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
932   g_return_val_if_fail ((x != NULL) || (y != NULL), FALSE);
933
934   return_val = FALSE;
935
936   widget = GTK_WIDGET (window);
937
938   if ((*x != -1) && (*y != -1))
939     gdk_window_move (widget->window, *x, *y);
940
941   if ((widget->requisition.width == 0) ||
942       (widget->requisition.height == 0))
943     {
944       widget->requisition.width = 200;
945       widget->requisition.height = 200;
946     }
947
948   gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
949   
950   resize_containers = NULL;
951
952   if ((window->auto_shrink &&
953        ((width != widget->requisition.width) ||
954         (height != widget->requisition.height))) ||
955       (width < widget->requisition.width) ||
956       (height < widget->requisition.height))
957     {
958       if (window->resize_count == 0)
959         {
960           window->resize_count += 1;
961           gdk_window_resize (widget->window,
962                              widget->requisition.width,
963                              widget->requisition.height);
964         }
965     }
966   else
967     {
968       /* The window hasn't changed size but one of its children
969        *  queued a resize request. Which means that the allocation
970        *  is not sufficient for the requisition of some child.
971        *  We've already performed a size request at this point,
972        *  so we simply need to run through the list of resize
973        *  widgets and reallocate their sizes appropriately. We
974        *  make the optimization of not performing reallocation
975        *  for a widget who also has a parent in the resize widgets
976        *  list.
977        */
978       resize_widgets = gtk_object_get_data (GTK_OBJECT (window), "resize_widgets");
979       gtk_object_set_data (GTK_OBJECT (window), "resize_widgets", NULL);
980
981       tmp_list = resize_widgets;
982       while (tmp_list)
983        {
984          widget = tmp_list->data;
985          tmp_list = tmp_list->next;
986          
987          /* referencing needed? */
988          GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
989          gtk_object_unref (GTK_OBJECT (widget));
990          
991          widget = widget->parent;
992
993          while (widget &&
994                 ((widget->allocation.width < widget->requisition.width) ||
995                  (widget->allocation.height < widget->requisition.height)))
996            widget = widget->parent;
997          
998          if (widget)
999            GTK_WIDGET_SET_FLAGS (widget, GTK_RESIZE_NEEDED);
1000        }
1001
1002       tmp_list = resize_widgets;
1003       while (tmp_list)
1004        {
1005          widget = tmp_list->data;
1006          tmp_list = tmp_list->next;
1007
1008          resize_container = widget->parent;
1009          while (resize_container &&
1010                 !GTK_WIDGET_RESIZE_NEEDED (resize_container))
1011            resize_container = resize_container->parent;
1012
1013          if (resize_container)
1014            widget = resize_container->parent;
1015          else
1016            widget = NULL;
1017          
1018          while (widget)
1019            {
1020              if (GTK_WIDGET_RESIZE_NEEDED (widget))
1021                {
1022                  GTK_WIDGET_UNSET_FLAGS (resize_container, GTK_RESIZE_NEEDED);
1023                  resize_container = widget;
1024                }
1025              widget = widget->parent;
1026            }
1027
1028          if (resize_container &&
1029              !g_slist_find (resize_containers, resize_container))
1030            resize_containers = g_slist_prepend (resize_containers, resize_container);
1031        }
1032
1033       g_slist_free (resize_widgets);
1034
1035       tmp_list = resize_containers;
1036       while (tmp_list)
1037        {
1038          widget = tmp_list->data;
1039          tmp_list = tmp_list->next;
1040
1041          GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
1042          gtk_widget_size_allocate (widget, &widget->allocation);
1043          gtk_widget_queue_draw (widget);
1044        }
1045
1046       g_slist_free (resize_containers);
1047     }
1048
1049   return return_val;
1050 }
1051
1052 static gint
1053 gtk_window_move_resize (GtkWidget *widget)
1054 {
1055   GtkWindow *window;
1056   gint x, y;
1057   gint width, height;
1058   gint screen_width;
1059   gint screen_height;
1060   gint return_val;
1061
1062   g_return_val_if_fail (widget != NULL, FALSE);
1063   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1064
1065   return_val = FALSE;
1066
1067   if (GTK_WIDGET_REALIZED (widget))
1068     {
1069       window = GTK_WINDOW (widget);
1070
1071       /* Remember old size, to know if we have to reset hints */
1072       width = widget->requisition.width;
1073       height = widget->requisition.height;
1074       gtk_widget_size_request (widget, &widget->requisition);
1075
1076       if (GTK_WIDGET_MAPPED (widget) &&
1077           (width != widget->requisition.width ||
1078            height != widget->requisition.height))
1079         gtk_window_set_hints (widget, &widget->requisition);
1080
1081       x = -1;
1082       y = -1;
1083       width = widget->requisition.width;
1084       height = widget->requisition.height;
1085
1086       if (window->use_uposition)
1087         switch (window->position)
1088           {
1089           case GTK_WIN_POS_CENTER:
1090             x = (gdk_screen_width () - width) / 2;
1091             y = (gdk_screen_height () - height) / 2;
1092             gtk_widget_set_uposition (widget, x, y);
1093             break;
1094           case GTK_WIN_POS_MOUSE:
1095             gdk_window_get_pointer (NULL, &x, &y, NULL);
1096
1097             x -= width / 2;
1098             y -= height / 2;
1099
1100             screen_width = gdk_screen_width ();
1101             screen_height = gdk_screen_height ();
1102
1103             if (x < 0)
1104               x = 0;
1105             else if (x > (screen_width - width))
1106               x = screen_width - width;
1107
1108             if (y < 0)
1109               y = 0;
1110             else if (y > (screen_height - height))
1111               y = screen_height - height;
1112
1113             gtk_widget_set_uposition (widget, x, y);
1114             break;
1115           }
1116
1117       gtk_signal_emit (GTK_OBJECT (widget), window_signals[MOVE_RESIZE],
1118                        &x, &y, width, height, &return_val);
1119     }
1120
1121   return return_val;
1122 }
1123
1124 static void
1125 gtk_window_set_hints (GtkWidget      *widget,
1126                       GtkRequisition *requisition)
1127 {
1128   GtkWindow *window;
1129   GtkWidgetAuxInfo *aux_info;
1130   gint flags;
1131   gint ux, uy;
1132
1133   g_return_if_fail (widget != NULL);
1134   g_return_if_fail (GTK_IS_WINDOW (widget));
1135   g_return_if_fail (requisition != NULL);
1136
1137   if (GTK_WIDGET_REALIZED (widget))
1138     {
1139       window = GTK_WINDOW (widget);
1140
1141       flags = 0;
1142       ux = 0;
1143       uy = 0;
1144
1145       aux_info = gtk_object_get_data (GTK_OBJECT (widget), "aux_info");
1146       if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1147         {
1148           ux = aux_info->x;
1149           uy = aux_info->y;
1150           flags |= GDK_HINT_POS;
1151         }
1152       if (!window->allow_shrink)
1153         flags |= GDK_HINT_MIN_SIZE;
1154       if (!window->allow_grow)
1155         flags |= GDK_HINT_MAX_SIZE;
1156
1157       gdk_window_set_hints (widget->window, ux, uy,
1158                             requisition->width, requisition->height,
1159                             requisition->width, requisition->height,
1160                             flags);
1161
1162       if (window->use_uposition && (flags & GDK_HINT_POS))
1163         {
1164           window->use_uposition = FALSE;
1165           gdk_window_move (widget->window, ux, uy);
1166         }
1167     }
1168 }
1169
1170 static gint
1171 gtk_window_check_accelerator (GtkWindow *window,
1172                               gint       key,
1173                               guint      mods)
1174 {
1175   GtkAcceleratorTable *table;
1176   GList *tmp;
1177
1178   if ((key >= 0x20) && (key <= 0xFF))
1179     {
1180       tmp = window->accelerator_tables;
1181       while (tmp)
1182         {
1183           table = tmp->data;
1184           tmp = tmp->next;
1185
1186           if (gtk_accelerator_table_check (table, key, mods))
1187             return TRUE;
1188         }
1189
1190       if (gtk_accelerator_table_check (NULL, key, mods))
1191         return TRUE;
1192     }
1193
1194   return FALSE;
1195 }