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