source: trunk/third/gtk/gtk/gtkwindow.c @ 17071

Revision 17071, 61.4 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17070, which included commits to RCS files with non-trunk default branches.
Line 
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
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include <string.h>
28#include <limits.h>
29#include "gdk/gdk.h"
30#include "gdk/gdkkeysyms.h"
31#include "gdk/gdkx.h"
32#include "gtkprivate.h"
33#include "gtkrc.h"
34#include "gtksignal.h"
35#include "gtkwindow.h"
36#include "gtkbindings.h"
37#include "gtkmain.h"
38
39/* TODO: remove this define and assorted code in 1.3 and fix up the
40 * real culprits.
41 */
42#define FIXME_ZVT_ME_HARDER
43
44enum {
45  SET_FOCUS,
46  LAST_SIGNAL
47};
48enum {
49  ARG_0,
50  ARG_TYPE,
51  ARG_TITLE,
52  ARG_AUTO_SHRINK,
53  ARG_ALLOW_SHRINK,
54  ARG_ALLOW_GROW,
55  ARG_MODAL,
56  ARG_WIN_POS,
57  ARG_DEFAULT_WIDTH,
58  ARG_DEFAULT_HEIGHT
59};
60
61typedef struct {
62  GdkGeometry    geometry; /* Last set of geometry hints we set */
63  GdkWindowHints flags;
64  gint           width;
65  gint           height;
66} GtkWindowLastGeometryInfo;
67
68typedef struct {
69  /* Properties that the app has set on the window
70   */
71  GdkGeometry    geometry;      /* Geometry hints */
72  GdkWindowHints mask;
73  GtkWidget     *widget;        /* subwidget to which hints apply */
74  gint           width;         /* Default size */
75  gint           height;
76
77  GtkWindowLastGeometryInfo last;
78} GtkWindowGeometryInfo;
79
80#define GTK_WINDOW_HAS_FOCUS(window)                           \
81  ((window)->window_has_focus || (window)->window_has_pointer_focus)
82
83static void gtk_window_class_init         (GtkWindowClass    *klass);
84static void gtk_window_init               (GtkWindow         *window);
85static void gtk_window_set_arg            (GtkObject         *object,
86                                           GtkArg            *arg,
87                                           guint              arg_id);
88static void gtk_window_get_arg            (GtkObject         *object,
89                                           GtkArg            *arg,
90                                           guint              arg_id);
91static void gtk_window_shutdown           (GtkObject         *object);
92static void gtk_window_destroy            (GtkObject         *object);
93static void gtk_window_finalize           (GtkObject         *object);
94static void gtk_window_show               (GtkWidget         *widget);
95static void gtk_window_hide               (GtkWidget         *widget);
96static void gtk_window_map                (GtkWidget         *widget);
97static void gtk_window_unmap              (GtkWidget         *widget);
98static void gtk_window_realize            (GtkWidget         *widget);
99static void gtk_window_size_request       (GtkWidget         *widget,
100                                           GtkRequisition    *requisition);
101static void gtk_window_size_allocate      (GtkWidget         *widget,
102                                           GtkAllocation     *allocation);
103static gint gtk_window_configure_event    (GtkWidget         *widget,
104                                           GdkEventConfigure *event);
105static gint gtk_window_key_press_event    (GtkWidget         *widget,
106                                           GdkEventKey       *event);
107static gint gtk_window_key_release_event  (GtkWidget         *widget,
108                                           GdkEventKey       *event);
109static gint gtk_window_enter_notify_event (GtkWidget         *widget,
110                                           GdkEventCrossing  *event);
111static gint gtk_window_leave_notify_event (GtkWidget         *widget,
112                                           GdkEventCrossing  *event);
113static gint gtk_window_focus_in_event     (GtkWidget         *widget,
114                                           GdkEventFocus     *event);
115static gint gtk_window_focus_out_event    (GtkWidget         *widget,
116                                           GdkEventFocus     *event);
117static gint gtk_window_client_event       (GtkWidget         *widget,
118                                           GdkEventClient    *event);
119static void gtk_window_check_resize       (GtkContainer      *container);
120static void gtk_window_real_set_focus     (GtkWindow         *window,
121                                           GtkWidget         *focus);
122
123static void gtk_window_move_resize        (GtkWindow         *window);
124static gboolean gtk_window_compare_hints  (GdkGeometry       *geometry_a,
125                                           guint              flags_a,
126                                           GdkGeometry       *geometry_b,
127                                           guint              flags_b);
128static void gtk_window_compute_default_size (GtkWindow       *window,
129                                             guint           *width,
130                                             guint           *height);
131static void  gtk_window_constrain_size      (GtkWindow       *window,
132                                             GdkGeometry     *geometry,
133                                             guint            flags,
134                                             gint             width,
135                                             gint             height,
136                                             gint            *new_width,
137                                             gint            *new_height);
138static void gtk_window_compute_hints      (GtkWindow         *window,
139                                           GdkGeometry       *new_geometry,
140                                           guint             *new_flags);
141static void gtk_window_compute_reposition (GtkWindow         *window,
142                                           gint               new_width,
143                                           gint               new_height,
144                                           gint              *x,
145                                           gint              *y);
146
147static void gtk_window_read_rcfiles       (GtkWidget         *widget,
148                                           GdkEventClient    *event);
149static void gtk_window_draw               (GtkWidget         *widget,
150                                           GdkRectangle      *area);
151static void gtk_window_paint              (GtkWidget         *widget,
152                                           GdkRectangle      *area);
153static gint gtk_window_expose             (GtkWidget         *widget,
154                                           GdkEventExpose    *event);
155static void gtk_window_unset_transient_for         (GtkWindow  *window);
156static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
157                                                    GtkWidget  *window);
158static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
159                                                    GtkWidget  *window);
160
161static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
162                                                            gboolean   create);
163static void gtk_window_geometry_destroy  (GtkWindowGeometryInfo *info);
164
165static GtkBinClass *parent_class = NULL;
166static guint window_signals[LAST_SIGNAL] = { 0 };
167
168
169GtkType
170gtk_window_get_type (void)
171{
172  static GtkType window_type = 0;
173
174  if (!window_type)
175    {
176      static const GtkTypeInfo window_info =
177      {
178        "GtkWindow",
179        sizeof (GtkWindow),
180        sizeof (GtkWindowClass),
181        (GtkClassInitFunc) gtk_window_class_init,
182        (GtkObjectInitFunc) gtk_window_init,
183        /* reserved_1 */ NULL,
184        /* reserved_2 */ NULL,
185        (GtkClassInitFunc) NULL,
186      };
187
188      window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
189    }
190
191  return window_type;
192}
193
194static void
195gtk_window_class_init (GtkWindowClass *klass)
196{
197  GtkObjectClass *object_class;
198  GtkWidgetClass *widget_class;
199  GtkContainerClass *container_class;
200
201  object_class = (GtkObjectClass*) klass;
202  widget_class = (GtkWidgetClass*) klass;
203  container_class = (GtkContainerClass*) klass;
204
205  parent_class = gtk_type_class (gtk_bin_get_type ());
206
207  gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
208  gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
209  gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
210  gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
211  gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
212  gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
213  gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
214  gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH);
215  gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT);
216 
217  window_signals[SET_FOCUS] =
218    gtk_signal_new ("set_focus",
219                    GTK_RUN_LAST,
220                    object_class->type,
221                    GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
222                    gtk_marshal_NONE__POINTER,
223                    GTK_TYPE_NONE, 1,
224                    GTK_TYPE_WIDGET);
225
226  gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
227
228  object_class->set_arg = gtk_window_set_arg;
229  object_class->get_arg = gtk_window_get_arg;
230  object_class->shutdown = gtk_window_shutdown;
231  object_class->destroy = gtk_window_destroy;
232  object_class->finalize = gtk_window_finalize;
233
234  widget_class->show = gtk_window_show;
235  widget_class->hide = gtk_window_hide;
236  widget_class->map = gtk_window_map;
237  widget_class->unmap = gtk_window_unmap;
238  widget_class->realize = gtk_window_realize;
239  widget_class->size_request = gtk_window_size_request;
240  widget_class->size_allocate = gtk_window_size_allocate;
241  widget_class->configure_event = gtk_window_configure_event;
242  widget_class->key_press_event = gtk_window_key_press_event;
243  widget_class->key_release_event = gtk_window_key_release_event;
244  widget_class->enter_notify_event = gtk_window_enter_notify_event;
245  widget_class->leave_notify_event = gtk_window_leave_notify_event;
246  widget_class->focus_in_event = gtk_window_focus_in_event;
247  widget_class->focus_out_event = gtk_window_focus_out_event;
248  widget_class->client_event = gtk_window_client_event;
249
250  widget_class->draw = gtk_window_draw;
251  widget_class->expose_event = gtk_window_expose;
252   
253  container_class->check_resize = gtk_window_check_resize;
254
255  klass->set_focus = gtk_window_real_set_focus;
256}
257
258static void
259gtk_window_init (GtkWindow *window)
260{
261  GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
262  GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
263
264  gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
265
266  window->title = NULL;
267  window->wmclass_name = g_strdup (g_get_prgname ());
268  window->wmclass_class = g_strdup (gdk_progclass);
269  window->type = GTK_WINDOW_TOPLEVEL;
270  window->focus_widget = NULL;
271  window->default_widget = NULL;
272  window->resize_count = 0;
273  window->allow_shrink = FALSE;
274  window->allow_grow = TRUE;
275  window->auto_shrink = FALSE;
276  window->handling_resize = FALSE;
277  window->position = GTK_WIN_POS_NONE;
278  window->use_uposition = TRUE;
279  window->modal = FALSE;
280 
281  gtk_container_register_toplevel (GTK_CONTAINER (window));
282}
283
284static void
285gtk_window_set_arg (GtkObject  *object,
286                    GtkArg     *arg,
287                    guint       arg_id)
288{
289  GtkWindow  *window;
290
291  window = GTK_WINDOW (object);
292
293  switch (arg_id)
294    {
295    case ARG_TYPE:
296      window->type = GTK_VALUE_ENUM (*arg);
297      break;
298    case ARG_TITLE:
299      gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
300      break;
301    case ARG_AUTO_SHRINK:
302      window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
303      gtk_widget_queue_resize (GTK_WIDGET (window));
304      break;
305    case ARG_ALLOW_SHRINK:
306      window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
307      gtk_widget_queue_resize (GTK_WIDGET (window));
308      break;
309    case ARG_ALLOW_GROW:
310      window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
311      gtk_widget_queue_resize (GTK_WIDGET (window));
312      break;
313    case ARG_MODAL:
314      gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
315      break;
316    case ARG_WIN_POS:
317      gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
318      break;
319    case ARG_DEFAULT_WIDTH:
320      gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
321      break;
322    case ARG_DEFAULT_HEIGHT:
323      gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
324      break;
325    default:
326      break;
327    }
328}
329
330static void
331gtk_window_get_arg (GtkObject  *object,
332                    GtkArg     *arg,
333                    guint       arg_id)
334{
335  GtkWindow  *window;
336
337  window = GTK_WINDOW (object);
338
339  switch (arg_id)
340    {
341      GtkWindowGeometryInfo *info;
342    case ARG_TYPE:
343      GTK_VALUE_ENUM (*arg) = window->type;
344      break;
345    case ARG_TITLE:
346      GTK_VALUE_STRING (*arg) = g_strdup (window->title);
347      break;
348    case ARG_AUTO_SHRINK:
349      GTK_VALUE_BOOL (*arg) = window->auto_shrink;
350      break;
351    case ARG_ALLOW_SHRINK:
352      GTK_VALUE_BOOL (*arg) = window->allow_shrink;
353      break;
354    case ARG_ALLOW_GROW:
355      GTK_VALUE_BOOL (*arg) = window->allow_grow;
356      break;
357    case ARG_MODAL:
358      GTK_VALUE_BOOL (*arg) = window->modal;
359      break;
360    case ARG_WIN_POS:
361      GTK_VALUE_ENUM (*arg) = window->position;
362      break;
363    case ARG_DEFAULT_WIDTH:
364      info = gtk_window_get_geometry_info (window, FALSE);
365      if (!info)
366        GTK_VALUE_INT (*arg) = -1;
367      else
368        GTK_VALUE_INT (*arg) = info->width;
369      break;
370    case ARG_DEFAULT_HEIGHT:
371      info = gtk_window_get_geometry_info (window, FALSE);
372      if (!info)
373        GTK_VALUE_INT (*arg) = -1;
374      else
375        GTK_VALUE_INT (*arg) = info->height;
376      break;
377    default:
378      arg->type = GTK_TYPE_INVALID;
379      break;
380    }
381}
382
383GtkWidget*
384gtk_window_new (GtkWindowType type)
385{
386  GtkWindow *window;
387
388  g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
389
390  window = gtk_type_new (GTK_TYPE_WINDOW);
391
392  window->type = type;
393
394  return GTK_WIDGET (window);
395}
396
397void
398gtk_window_set_title (GtkWindow   *window,
399                      const gchar *title)
400{
401  g_return_if_fail (window != NULL);
402  g_return_if_fail (GTK_IS_WINDOW (window));
403
404  if (window->title)
405    g_free (window->title);
406  window->title = g_strdup (title);
407
408  if (GTK_WIDGET_REALIZED (window))
409    gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
410}
411
412void
413gtk_window_set_wmclass (GtkWindow *window,
414                        const gchar *wmclass_name,
415                        const gchar *wmclass_class)
416{
417  g_return_if_fail (window != NULL);
418  g_return_if_fail (GTK_IS_WINDOW (window));
419
420  g_free (window->wmclass_name);
421  window->wmclass_name = g_strdup (wmclass_name);
422
423  g_free (window->wmclass_class);
424  window->wmclass_class = g_strdup (wmclass_class);
425
426  if (GTK_WIDGET_REALIZED (window))
427    g_warning ("shouldn't set wmclass after window is realized!\n");
428}
429
430void
431gtk_window_set_focus (GtkWindow *window,
432                      GtkWidget *focus)
433{
434  g_return_if_fail (window != NULL);
435  g_return_if_fail (GTK_IS_WINDOW (window));
436  if (focus)
437    {
438      g_return_if_fail (GTK_IS_WIDGET (focus));
439      g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
440    }
441
442  if ((window->focus_widget != focus) ||
443      (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
444    gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
445}
446
447void
448gtk_window_set_default (GtkWindow *window,
449                        GtkWidget *default_widget)
450{
451  g_return_if_fail (window != NULL);
452  g_return_if_fail (GTK_IS_WINDOW (window));
453
454  if (default_widget)
455    g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
456
457  if (window->default_widget != default_widget)
458    {
459      if (window->default_widget)
460        {
461          if (window->focus_widget != window->default_widget ||
462              !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
463            GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
464          gtk_widget_draw_default (window->default_widget);
465        }
466
467      window->default_widget = default_widget;
468
469      if (window->default_widget)
470        {
471          if (window->focus_widget == NULL ||
472              !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
473            GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
474          gtk_widget_draw_default (window->default_widget);
475        }
476    }
477}
478
479void
480gtk_window_set_policy (GtkWindow *window,
481                       gint       allow_shrink,
482                       gint       allow_grow,
483                       gint       auto_shrink)
484{
485  g_return_if_fail (window != NULL);
486  g_return_if_fail (GTK_IS_WINDOW (window));
487
488  window->allow_shrink = (allow_shrink != FALSE);
489  window->allow_grow = (allow_grow != FALSE);
490  window->auto_shrink = (auto_shrink != FALSE);
491
492  gtk_widget_queue_resize (GTK_WIDGET (window));
493}
494
495void
496gtk_window_add_accel_group (GtkWindow        *window,
497                            GtkAccelGroup    *accel_group)
498{
499  g_return_if_fail (window != NULL);
500  g_return_if_fail (GTK_IS_WINDOW (window));
501  g_return_if_fail (accel_group != NULL);
502
503  gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
504}
505
506void
507gtk_window_remove_accel_group (GtkWindow       *window,
508                               GtkAccelGroup   *accel_group)
509{
510  g_return_if_fail (window != NULL);
511  g_return_if_fail (GTK_IS_WINDOW (window));
512  g_return_if_fail (accel_group != NULL);
513
514  gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
515}
516
517void
518gtk_window_set_position (GtkWindow         *window,
519                         GtkWindowPosition  position)
520{
521  g_return_if_fail (window != NULL);
522  g_return_if_fail (GTK_IS_WINDOW (window));
523
524  window->position = position;
525}
526
527gint
528gtk_window_activate_focus (GtkWindow      *window)
529{
530  g_return_val_if_fail (window != NULL, FALSE);
531  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
532
533  if (window->focus_widget)
534    {
535      if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
536        gtk_widget_activate (window->focus_widget);
537      return TRUE;
538    }
539
540  return FALSE;
541}
542
543gint
544gtk_window_activate_default (GtkWindow      *window)
545{
546  g_return_val_if_fail (window != NULL, FALSE);
547  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
548
549  if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
550    {
551      gtk_widget_activate (window->default_widget);
552      return TRUE;
553    }
554
555  return FALSE;
556}
557
558void
559gtk_window_set_modal (GtkWindow *window,
560                      gboolean   modal)
561{
562  g_return_if_fail (window != NULL);
563  g_return_if_fail (GTK_IS_WINDOW (window));
564
565  window->modal = modal != FALSE;
566
567  /* adjust desired modality state */
568  if (GTK_WIDGET_VISIBLE (window) && window->modal)
569    gtk_grab_add (GTK_WIDGET (window));
570  else
571    gtk_grab_remove (GTK_WIDGET (window));
572}
573
574void
575gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
576{
577  GList *embedded_windows;
578
579  g_return_if_fail (window != NULL);
580  g_return_if_fail (GTK_IS_WINDOW (window));
581
582  embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
583  if (embedded_windows)
584    gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
585                                       g_quark_from_static_string ("gtk-embedded"));
586  embedded_windows = g_list_prepend (embedded_windows,
587                                     GUINT_TO_POINTER (xid));
588
589  gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
590                            embedded_windows,
591                            embedded_windows ?
592                              (GtkDestroyNotify) g_list_free : NULL);
593}
594
595void
596gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
597{
598  GList *embedded_windows;
599  GList *node;
600
601  g_return_if_fail (window != NULL);
602  g_return_if_fail (GTK_IS_WINDOW (window));
603 
604  embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
605  if (embedded_windows)
606    gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
607                                       g_quark_from_static_string ("gtk-embedded"));
608
609  node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
610  if (node)
611    {
612      embedded_windows = g_list_remove_link (embedded_windows, node);
613      g_list_free_1 (node);
614    }
615 
616  gtk_object_set_data_full (GTK_OBJECT (window),
617                            "gtk-embedded", embedded_windows,
618                            embedded_windows ?
619                              (GtkDestroyNotify) g_list_free : NULL);
620}
621
622void       
623gtk_window_reposition (GtkWindow *window,
624                       gint       x,
625                       gint       y)
626{
627  GtkWindowGeometryInfo *info;
628 
629  g_return_if_fail (window != NULL);
630  g_return_if_fail (GTK_IS_WINDOW (window));
631
632  /* keep this in sync with gtk_window_compute_reposition()
633   */
634  if (GTK_WIDGET_REALIZED (window))
635    {
636      info = gtk_window_get_geometry_info (window, TRUE);
637
638      if (!(info->last.flags & GDK_HINT_POS))
639        {
640          info->last.flags |= GDK_HINT_POS;
641          gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
642                                         &info->last.geometry,
643                                         info->last.flags);
644        }
645 
646      gdk_window_move (GTK_WIDGET (window)->window, x, y);
647    }
648}
649
650static void
651gtk_window_shutdown (GtkObject *object)
652{
653  GtkWindow *window;
654
655  g_return_if_fail (object != NULL);
656  g_return_if_fail (GTK_IS_WINDOW (object));
657
658  window = GTK_WINDOW (object);
659
660  gtk_window_set_focus (window, NULL);
661  gtk_window_set_default (window, NULL);
662
663  GTK_OBJECT_CLASS (parent_class)->shutdown (object);
664}
665
666static void
667gtk_window_transient_parent_realized (GtkWidget *parent,
668                                      GtkWidget *window)
669{
670  if (GTK_WIDGET_REALIZED (window))
671    gdk_window_set_transient_for (window->window, parent->window);
672}
673
674static void
675gtk_window_transient_parent_unrealized (GtkWidget *parent,
676                                        GtkWidget *window)
677{
678  if (GTK_WIDGET_REALIZED (window))
679    gdk_property_delete (window->window,
680                         gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
681}
682
683static void       
684gtk_window_unset_transient_for  (GtkWindow *window)
685{
686  if (window->transient_parent)
687    {
688      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
689                                     GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
690                                     window);
691      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
692                                     GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
693                                     window);
694      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
695                                     GTK_SIGNAL_FUNC (gtk_widget_destroyed),
696                                     &window->transient_parent);
697
698      window->transient_parent = NULL;
699    }
700}
701
702void       
703gtk_window_set_transient_for  (GtkWindow *window,
704                               GtkWindow *parent)
705{
706  g_return_if_fail (window != 0);
707
708  if (window->transient_parent)
709    {
710      if (GTK_WIDGET_REALIZED (window) &&
711          GTK_WIDGET_REALIZED (window->transient_parent) &&
712          (!parent || !GTK_WIDGET_REALIZED (parent)))
713        gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
714                                                GTK_WIDGET (window));
715
716      gtk_window_unset_transient_for (window);
717    }
718
719  window->transient_parent = parent;
720
721  if (parent)
722    {
723      gtk_signal_connect (GTK_OBJECT (parent), "destroy",
724                          GTK_SIGNAL_FUNC (gtk_widget_destroyed),
725                          &window->transient_parent);
726      gtk_signal_connect (GTK_OBJECT (parent), "realize",
727                          GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
728                          window);
729      gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
730                          GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
731                          window);
732
733      if (GTK_WIDGET_REALIZED (window) &&
734          GTK_WIDGET_REALIZED (parent))
735        gtk_window_transient_parent_realized (GTK_WIDGET (parent),
736                                              GTK_WIDGET (window));
737    }
738}
739
740static void
741gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
742{
743  if (info->widget)
744    gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
745                                   GTK_SIGNAL_FUNC (gtk_widget_destroyed),
746                                   &info->widget);
747  g_free (info);
748}
749
750static GtkWindowGeometryInfo*
751gtk_window_get_geometry_info (GtkWindow *window,
752                              gboolean   create)
753{
754  GtkWindowGeometryInfo *info;
755
756  info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
757
758  if (!info && create)
759    {
760      info = g_new0 (GtkWindowGeometryInfo, 1);
761
762      info->width = 0;
763      info->height = 0;
764      info->last.width = -1;
765      info->last.height = -1;
766      info->widget = NULL;
767      info->mask = 0;
768
769      gtk_object_set_data_full (GTK_OBJECT (window),
770                                "gtk-window-geometry",
771                                info,
772                                (GtkDestroyNotify) gtk_window_geometry_destroy);
773    }
774
775  return info;
776}
777
778void       
779gtk_window_set_geometry_hints (GtkWindow       *window,
780                               GtkWidget       *geometry_widget,
781                               GdkGeometry     *geometry,
782                               GdkWindowHints   geom_mask)
783{
784  GtkWindowGeometryInfo *info;
785
786  g_return_if_fail (window != NULL);
787
788  info = gtk_window_get_geometry_info (window, TRUE);
789 
790  if (info->widget)
791    gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
792                                   GTK_SIGNAL_FUNC (gtk_widget_destroyed),
793                                   &info->widget);
794 
795  info->widget = geometry_widget;
796  if (info->widget)
797    gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
798                        GTK_SIGNAL_FUNC (gtk_widget_destroyed),
799                        &info->widget);
800
801  if (geometry)
802    info->geometry = *geometry;
803
804  info->mask = geom_mask;
805
806  gtk_widget_queue_resize (GTK_WIDGET (window));
807}
808
809void       
810gtk_window_set_default_size (GtkWindow   *window,
811                             gint         width,
812                             gint         height)
813{
814  GtkWindowGeometryInfo *info;
815
816  g_return_if_fail (GTK_IS_WINDOW (window));
817
818  info = gtk_window_get_geometry_info (window, TRUE);
819
820  if (width >= 0)
821    info->width = width;
822  if (height >= 0)
823    info->height = height;
824
825  gtk_widget_queue_resize (GTK_WIDGET (window));
826}
827 
828static void
829gtk_window_destroy (GtkObject *object)
830{
831  GtkWindow *window;
832 
833  g_return_if_fail (object != NULL);
834  g_return_if_fail (GTK_IS_WINDOW (object));
835
836  window = GTK_WINDOW (object);
837 
838  gtk_container_unregister_toplevel (GTK_CONTAINER (object));
839
840  if (window->transient_parent)
841    gtk_window_unset_transient_for (window);
842
843  GTK_OBJECT_CLASS (parent_class)->destroy (object);
844}
845
846static void
847gtk_window_finalize (GtkObject *object)
848{
849  GtkWindow *window;
850
851  g_return_if_fail (object != NULL);
852  g_return_if_fail (GTK_IS_WINDOW (object));
853
854  window = GTK_WINDOW (object);
855  g_free (window->title);
856  g_free (window->wmclass_name);
857  g_free (window->wmclass_class);
858
859  GTK_OBJECT_CLASS(parent_class)->finalize (object);
860}
861
862static void
863gtk_window_show (GtkWidget *widget)
864{
865  GtkWindow *window = GTK_WINDOW (widget);
866  GtkContainer *container = GTK_CONTAINER (window);
867  gboolean need_resize;
868
869  GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
870
871  need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
872  container->need_resize = FALSE;
873
874  if (need_resize)
875    {
876      GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
877      GtkAllocation allocation = { 0, 0 };
878      GdkGeometry new_geometry;
879      guint width, height, new_flags;
880
881      /* determine default size to initially show the window with */
882      gtk_widget_size_request (widget, NULL);
883      gtk_window_compute_default_size (window, &width, &height);
884
885      /* save away the last default size for later comparisions */
886      info->last.width = width;
887      info->last.height = height;
888
889      /* constrain size to geometry */
890      gtk_window_compute_hints (window, &new_geometry, &new_flags);
891      gtk_window_constrain_size (window,
892                                 &new_geometry, new_flags,
893                                 width, height,
894                                 &width, &height);
895
896      /* and allocate the window */
897      allocation.width  = width;
898      allocation.height = height;
899      gtk_widget_size_allocate (widget, &allocation);
900     
901      if (GTK_WIDGET_REALIZED (widget))
902        gdk_window_resize (widget->window, width, height);
903      else
904        gtk_widget_realize (widget);
905    }
906 
907  gtk_container_check_resize (container);
908
909  gtk_widget_map (widget);
910
911  if (window->modal)
912    gtk_grab_add (widget);
913}
914
915static void
916gtk_window_hide (GtkWidget *widget)
917{
918  GtkWindow *window;
919
920  g_return_if_fail (widget != NULL);
921  g_return_if_fail (GTK_IS_WINDOW (widget));
922
923  window = GTK_WINDOW (widget);
924
925  GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
926  gtk_widget_unmap (widget);
927
928  if (window->modal)
929    gtk_grab_remove (widget);
930}
931
932/* The algorithm used for window_has_pointer_focus is taken
933 * from the XTerm code.
934 */
935static GdkFilterReturn
936gtk_window_focus_filter (GdkXEvent *xevent,
937                         GdkEvent  *event,
938                         gpointer   data)
939{
940  GtkWindow *window = GTK_WINDOW (data);
941  XEvent *xev = (XEvent *)xevent;
942  GdkEvent extra_event;
943
944  switch (xev->xany.type)
945    {
946    case FocusIn:
947      {
948        switch (xev->xfocus.detail)
949          {
950          case NotifyAncestor:
951          case NotifyNonlinear:
952          case NotifyVirtual:
953          case NotifyNonlinearVirtual:
954            window->window_has_focus = TRUE;
955            break;
956          case NotifyPointer:
957            window->window_has_pointer_focus = TRUE;
958            break;
959          case NotifyInferior:
960          case NotifyPointerRoot:
961          case NotifyDetailNone:
962            break;
963          }
964      }
965      break;
966    case FocusOut:
967      {
968        switch (xev->xfocus.detail)
969          {
970          case NotifyAncestor:
971          case NotifyNonlinear:
972          case NotifyVirtual:
973          case NotifyNonlinearVirtual:
974            window->window_has_focus = FALSE;
975            break;
976          case NotifyPointer:
977            window->window_has_pointer_focus = FALSE;
978            break;
979          case NotifyInferior:
980          case NotifyPointerRoot:
981          case NotifyDetailNone:
982            break;
983          }
984      }
985      break;
986    case EnterNotify:
987    case LeaveNotify:
988      if (xev->xcrossing.detail != NotifyInferior &&
989          xev->xcrossing.focus && !window->window_has_focus)
990        {
991          window->window_has_pointer_focus = (xev->xany.type == EnterNotify) ? TRUE : FALSE;
992
993          extra_event.type = GDK_FOCUS_CHANGE;
994          extra_event.focus_change.window = GTK_WIDGET (window)->window;
995          extra_event.focus_change.send_event = FALSE;
996          extra_event.focus_change.in = window->window_has_pointer_focus;
997
998          gdk_event_put (&extra_event);
999        }
1000      break;
1001    }
1002
1003  return GDK_FILTER_CONTINUE;
1004}
1005
1006static void
1007gtk_window_map (GtkWidget *widget)
1008{
1009  GtkWindow *window;
1010
1011  g_return_if_fail (widget != NULL);
1012  g_return_if_fail (GTK_IS_WINDOW (widget));
1013
1014  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1015
1016  window = GTK_WINDOW (widget);
1017
1018  if (window->bin.child &&
1019      GTK_WIDGET_VISIBLE (window->bin.child) &&
1020      !GTK_WIDGET_MAPPED (window->bin.child))
1021    gtk_widget_map (window->bin.child);
1022
1023  gdk_window_add_filter (widget->window, gtk_window_focus_filter, widget);
1024
1025  gdk_window_show (widget->window);
1026}
1027
1028static void
1029gtk_window_unmap (GtkWidget *widget)
1030{
1031  GtkWindow *window;
1032
1033  g_return_if_fail (widget != NULL);
1034  g_return_if_fail (GTK_IS_WINDOW (widget));
1035
1036  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1037  gdk_window_withdraw (widget->window);
1038
1039  window = GTK_WINDOW (widget);
1040  window->use_uposition = TRUE;
1041  window->resize_count = 0;
1042  window->handling_resize = FALSE;
1043}
1044
1045static void
1046gtk_window_realize (GtkWidget *widget)
1047{
1048  GtkWindow *window;
1049  GdkWindowAttr attributes;
1050  gint attributes_mask;
1051 
1052  g_return_if_fail (GTK_IS_WINDOW (widget));
1053
1054  window = GTK_WINDOW (widget);
1055
1056  /* ensure widget tree is properly size allocated */
1057  if (widget->allocation.x == -1 &&
1058      widget->allocation.y == -1 &&
1059      widget->allocation.width == 1 &&
1060      widget->allocation.height == 1)
1061    {
1062      GtkRequisition requisition;
1063      GtkAllocation allocation = { 0, 0, 200, 200 };
1064
1065      gtk_widget_size_request (widget, &requisition);
1066      if (requisition.width || requisition.height)
1067        {
1068          /* non-empty window */
1069          allocation.width = requisition.width;
1070          allocation.height = requisition.height;
1071        }
1072      gtk_widget_size_allocate (widget, &allocation);
1073     
1074      gtk_container_queue_resize (GTK_CONTAINER (widget));
1075
1076      g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
1077    }
1078 
1079  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1080 
1081  switch (window->type)
1082    {
1083    case GTK_WINDOW_TOPLEVEL:
1084      attributes.window_type = GDK_WINDOW_TOPLEVEL;
1085      break;
1086    case GTK_WINDOW_DIALOG:
1087      attributes.window_type = GDK_WINDOW_DIALOG;
1088      break;
1089    case GTK_WINDOW_POPUP:
1090      attributes.window_type = GDK_WINDOW_TEMP;
1091      break;
1092    }
1093   
1094  attributes.title = window->title;
1095  attributes.wmclass_name = window->wmclass_name;
1096  attributes.wmclass_class = window->wmclass_class;
1097  attributes.width = widget->allocation.width;
1098  attributes.height = widget->allocation.height;
1099  attributes.wclass = GDK_INPUT_OUTPUT;
1100  attributes.visual = gtk_widget_get_visual (widget);
1101  attributes.colormap = gtk_widget_get_colormap (widget);
1102  attributes.event_mask = gtk_widget_get_events (widget);
1103  attributes.event_mask |= (GDK_EXPOSURE_MASK |
1104                            GDK_KEY_PRESS_MASK |
1105                            GDK_ENTER_NOTIFY_MASK |
1106                            GDK_LEAVE_NOTIFY_MASK |
1107                            GDK_FOCUS_CHANGE_MASK |
1108                            GDK_STRUCTURE_MASK);
1109   
1110  attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1111  attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
1112  attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
1113   
1114  widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
1115  gdk_window_set_user_data (widget->window, window);
1116
1117  widget->style = gtk_style_attach (widget->style, widget->window);
1118  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1119  gtk_window_paint (widget, NULL);
1120
1121  if (window->transient_parent &&
1122      GTK_WIDGET_REALIZED (window->transient_parent))
1123    gdk_window_set_transient_for (widget->window,
1124                                  GTK_WIDGET (window->transient_parent)->window);
1125}
1126
1127static void
1128gtk_window_size_request (GtkWidget      *widget,
1129                         GtkRequisition *requisition)
1130{
1131  GtkWindow *window;
1132  GtkBin *bin;
1133
1134  g_return_if_fail (widget != NULL);
1135  g_return_if_fail (GTK_IS_WINDOW (widget));
1136  g_return_if_fail (requisition != NULL);
1137
1138  window = GTK_WINDOW (widget);
1139  bin = GTK_BIN (window);
1140 
1141  requisition->width = GTK_CONTAINER (window)->border_width * 2;
1142  requisition->height = GTK_CONTAINER (window)->border_width * 2;
1143
1144  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
1145    {
1146      GtkRequisition child_requisition;
1147     
1148      gtk_widget_size_request (bin->child, &child_requisition);
1149
1150      requisition->width += child_requisition.width;
1151      requisition->height += child_requisition.height;
1152    }
1153}
1154
1155static void
1156gtk_window_size_allocate (GtkWidget     *widget,
1157                          GtkAllocation *allocation)
1158{
1159  GtkWindow *window;
1160  GtkAllocation child_allocation;
1161
1162  g_return_if_fail (widget != NULL);
1163  g_return_if_fail (GTK_IS_WINDOW (widget));
1164  g_return_if_fail (allocation != NULL);
1165
1166  window = GTK_WINDOW (widget);
1167  widget->allocation = *allocation;
1168
1169  if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
1170    {
1171      child_allocation.x = GTK_CONTAINER (window)->border_width;
1172      child_allocation.y = GTK_CONTAINER (window)->border_width;
1173      child_allocation.width =
1174        MAX (1, (gint)allocation->width - child_allocation.x * 2);
1175      child_allocation.height =
1176        MAX (1, (gint)allocation->height - child_allocation.y * 2);
1177
1178      gtk_widget_size_allocate (window->bin.child, &child_allocation);
1179    }
1180}
1181
1182static gint
1183gtk_window_configure_event (GtkWidget         *widget,
1184                            GdkEventConfigure *event)
1185{
1186  GtkWindow *window;
1187 
1188  g_return_val_if_fail (widget != NULL, FALSE);
1189  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1190  g_return_val_if_fail (event != NULL, FALSE);
1191 
1192  window = GTK_WINDOW (widget);
1193
1194  /* we got a configure event specifying the new window size and position,
1195   * in principle we have to distinguish 4 cases here:
1196   * 1) the size didn't change and resize_count == 0
1197   *    -> the window was merely moved (sometimes not even that)
1198   * 2) the size didn't change and resize_count > 0
1199   *    -> we requested a new size, but didn't get it
1200   * 3) the size changed and resize_count > 0
1201   *    -> we asked for a new size and we got one
1202   * 4) the size changed and resize_count == 0
1203   *    -> we got resized from outside the toolkit, and have to
1204   *    accept that size since we don't want to fight neither the
1205   *    window manager nor the user
1206   * in the three latter cases we have to reallocate the widget tree,
1207   * which happens in gtk_window_move_resize(), so we set a flag for
1208   * that function and assign the new size. if resize_count > 1,
1209   * we simply do nothing and wait for more configure events.
1210   */
1211
1212  if (window->resize_count > 0 ||
1213      widget->allocation.width != event->width ||
1214      widget->allocation.height != event->height)
1215    {
1216      if (window->resize_count > 0)
1217        window->resize_count -= 1;
1218
1219      if (window->resize_count == 0)
1220        {
1221          window->handling_resize = TRUE;
1222         
1223          widget->allocation.width = event->width;
1224          widget->allocation.height = event->height;
1225         
1226          gtk_widget_queue_resize (widget);
1227        }
1228    }
1229
1230  return TRUE;
1231}
1232
1233static gint
1234gtk_window_key_press_event (GtkWidget   *widget,
1235                            GdkEventKey *event)
1236{
1237  GtkWindow *window;
1238  GtkDirectionType direction = 0;
1239  gboolean handled;
1240
1241  g_return_val_if_fail (widget != NULL, FALSE);
1242  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1243  g_return_val_if_fail (event != NULL, FALSE);
1244
1245  window = GTK_WINDOW (widget);
1246
1247  handled = FALSE;
1248 
1249  if (window->focus_widget &&
1250      window->focus_widget != widget &&
1251      GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1252    {
1253      handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1254    }
1255   
1256  if (!handled)
1257    handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1258
1259  if (!handled)
1260    {
1261      switch (event->keyval)
1262        {
1263        case GDK_space:
1264          if (window->focus_widget)
1265            {
1266              if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1267                gtk_widget_activate (window->focus_widget);
1268              handled = TRUE;
1269            }
1270          break;
1271        case GDK_Return:
1272        case GDK_KP_Enter:
1273          if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1274              (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1275            {
1276              gtk_widget_activate (window->default_widget);
1277              handled = TRUE;
1278            }
1279          else if (window->focus_widget)
1280            {
1281              if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1282                gtk_widget_activate (window->focus_widget);
1283              handled = TRUE;
1284            }
1285          break;
1286        case GDK_Up:
1287        case GDK_Down:
1288        case GDK_Left:
1289        case GDK_Right:
1290        case GDK_KP_Up:
1291        case GDK_KP_Down:
1292        case GDK_KP_Left:
1293        case GDK_KP_Right:
1294        case GDK_Tab:
1295        case GDK_ISO_Left_Tab:
1296          switch (event->keyval)
1297            {
1298            case GDK_Up:
1299            case GDK_KP_Up:
1300              direction = GTK_DIR_UP;
1301              break;
1302            case GDK_Down:
1303            case GDK_KP_Down:
1304              direction = GTK_DIR_DOWN;
1305              break;
1306            case GDK_Left:
1307            case GDK_KP_Left:
1308              direction = GTK_DIR_LEFT;
1309              break;
1310            case GDK_Right:
1311            case GDK_KP_Right:
1312              direction = GTK_DIR_RIGHT;
1313              break;
1314            case GDK_Tab:
1315            case GDK_ISO_Left_Tab:
1316              if (event->state & GDK_SHIFT_MASK)
1317                direction = GTK_DIR_TAB_BACKWARD;
1318              else
1319                direction = GTK_DIR_TAB_FORWARD;
1320              break;
1321            default :
1322              direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1323            }
1324
1325          gtk_container_focus (GTK_CONTAINER (widget), direction);
1326
1327          if (!GTK_CONTAINER (window)->focus_child)
1328            gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1329          else
1330            handled = TRUE;
1331          break;
1332        }
1333    }
1334
1335  if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1336    handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1337
1338  return handled;
1339}
1340
1341static gint
1342gtk_window_key_release_event (GtkWidget   *widget,
1343                              GdkEventKey *event)
1344{
1345  GtkWindow *window;
1346  gint handled;
1347 
1348  g_return_val_if_fail (widget != NULL, FALSE);
1349  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1350  g_return_val_if_fail (event != NULL, FALSE);
1351 
1352  window = GTK_WINDOW (widget);
1353  handled = FALSE;
1354  if (window->focus_widget &&
1355      window->focus_widget != widget &&
1356      GTK_WIDGET_SENSITIVE (window->focus_widget))
1357    {
1358      handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1359    }
1360
1361  if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1362    handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1363
1364  return handled;
1365}
1366
1367static gint
1368gtk_window_enter_notify_event (GtkWidget        *widget,
1369                               GdkEventCrossing *event)
1370{
1371  g_return_val_if_fail (widget != NULL, FALSE);
1372  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1373  g_return_val_if_fail (event != NULL, FALSE);
1374
1375  return FALSE;
1376}
1377
1378static gint
1379gtk_window_leave_notify_event (GtkWidget        *widget,
1380                               GdkEventCrossing *event)
1381{
1382  g_return_val_if_fail (widget != NULL, FALSE);
1383  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1384  g_return_val_if_fail (event != NULL, FALSE);
1385
1386  return FALSE;
1387}
1388
1389static gint
1390gtk_window_focus_in_event (GtkWidget     *widget,
1391                           GdkEventFocus *event)
1392{
1393  GtkWindow *window;
1394  GdkEventFocus fevent;
1395
1396  g_return_val_if_fail (widget != NULL, FALSE);
1397  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1398  g_return_val_if_fail (event != NULL, FALSE);
1399
1400  /* It appears spurious focus in events can occur when
1401   *  the window is hidden. So we'll just check to see if
1402   *  the window is visible before actually handling the
1403   *  event
1404   */
1405  if (GTK_WIDGET_VISIBLE (widget))
1406    {
1407      window = GTK_WINDOW (widget);
1408      if (window->focus_widget &&
1409          window->focus_widget != widget &&
1410          !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1411        {
1412          fevent.type = GDK_FOCUS_CHANGE;
1413          fevent.window = window->focus_widget->window;
1414          fevent.in = TRUE;
1415
1416          gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1417        }
1418    }
1419
1420  return FALSE;
1421}
1422
1423static gint
1424gtk_window_focus_out_event (GtkWidget     *widget,
1425                            GdkEventFocus *event)
1426{
1427  GtkWindow *window;
1428  GdkEventFocus fevent;
1429
1430  g_return_val_if_fail (widget != NULL, FALSE);
1431  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1432  g_return_val_if_fail (event != NULL, FALSE);
1433
1434  window = GTK_WINDOW (widget);
1435
1436  if (window->focus_widget &&
1437      window->focus_widget != widget &&
1438      GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1439    {
1440      fevent.type = GDK_FOCUS_CHANGE;
1441      fevent.window = window->focus_widget->window;
1442      fevent.in = FALSE;
1443
1444      gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1445    }
1446
1447  return FALSE;
1448}
1449
1450static GdkAtom atom_rcfiles = GDK_NONE;
1451
1452static void
1453gtk_window_read_rcfiles (GtkWidget *widget,
1454                         GdkEventClient *event)
1455{
1456  GList *embedded_windows;
1457
1458  embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1459  if (embedded_windows)
1460    {
1461      GdkEventClient sev;
1462      int i;
1463     
1464      for(i = 0; i < 5; i++)
1465        sev.data.l[i] = 0;
1466      sev.data_format = 32;
1467      sev.message_type = atom_rcfiles;
1468     
1469      while (embedded_windows)
1470        {
1471          guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1472          gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1473          embedded_windows = embedded_windows->next;
1474        }
1475    }
1476
1477  if (gtk_rc_reparse_all ())
1478    {
1479      /* If the above returned true, some of our RC files are out
1480       * of date, so we need to reset all our widgets. Our other
1481       * toplevel windows will also get the message, but by
1482       * then, the RC file will up to date, so we have to tell
1483       * them now.
1484       */
1485      GList *toplevels;
1486     
1487      toplevels = gtk_container_get_toplevels();
1488      while (toplevels)
1489        {
1490          gtk_widget_reset_rc_styles (toplevels->data);
1491          toplevels = toplevels->next;
1492        }
1493    }
1494}
1495
1496static gint
1497gtk_window_client_event (GtkWidget      *widget,
1498                         GdkEventClient *event)
1499{
1500  g_return_val_if_fail (widget != NULL, FALSE);
1501  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1502  g_return_val_if_fail (event != NULL, FALSE);
1503
1504  if (!atom_rcfiles)
1505    atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1506
1507  if(event->message_type == atom_rcfiles)
1508    gtk_window_read_rcfiles (widget, event);   
1509
1510  return FALSE;
1511}
1512
1513static void
1514gtk_window_check_resize (GtkContainer *container)
1515{
1516  GtkWindow *window;
1517
1518  g_return_if_fail (container != NULL);
1519  g_return_if_fail (GTK_IS_WINDOW (container));
1520
1521  window = GTK_WINDOW (container);
1522
1523  if (GTK_WIDGET_VISIBLE (container))
1524    gtk_window_move_resize (window);
1525}
1526
1527static void
1528gtk_window_real_set_focus (GtkWindow *window,
1529                           GtkWidget *focus)
1530{
1531  GdkEventFocus event;
1532  gboolean def_flags = 0;
1533
1534  g_return_if_fail (window != NULL);
1535  g_return_if_fail (GTK_IS_WINDOW (window));
1536 
1537  if (window->default_widget)
1538    def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1539 
1540  if (window->focus_widget)
1541    {
1542      if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1543          (window->focus_widget != window->default_widget))
1544        {
1545          GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1546
1547          if (window->default_widget)
1548            GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1549        }
1550
1551      if (GTK_WINDOW_HAS_FOCUS (window))
1552        {
1553          event.type = GDK_FOCUS_CHANGE;
1554          event.window = window->focus_widget->window;
1555          event.in = FALSE;
1556         
1557          gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1558        }
1559    }
1560 
1561  window->focus_widget = focus;
1562 
1563  if (window->focus_widget)
1564    {
1565      if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1566          (window->focus_widget != window->default_widget))
1567        {
1568          if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
1569            GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1570
1571          if (window->default_widget)
1572            GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1573        }
1574     
1575      if (GTK_WINDOW_HAS_FOCUS (window))
1576        {
1577          event.type = GDK_FOCUS_CHANGE;
1578          event.window = window->focus_widget->window;
1579          event.in = TRUE;
1580
1581          gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1582        }
1583    }
1584 
1585  if (window->default_widget &&
1586      (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
1587    gtk_widget_queue_draw (window->default_widget);
1588}
1589
1590/*********************************
1591 * Functions related to resizing *
1592 *********************************/
1593
1594static void
1595gtk_window_move_resize (GtkWindow *window)
1596{
1597  GtkWidget *widget;
1598  GtkContainer *container;
1599  GtkWindowGeometryInfo *info;
1600  GtkWindowLastGeometryInfo saved_last_info;
1601  GdkGeometry new_geometry;
1602  guint new_flags;
1603  gint x, y;
1604  gint width, height;
1605  gint new_width, new_height;
1606  gboolean default_size_changed = FALSE;
1607  gboolean hints_changed = FALSE;
1608
1609  g_return_if_fail (GTK_IS_WINDOW (window));
1610  g_return_if_fail (GTK_WIDGET_REALIZED (window));
1611
1612  widget = GTK_WIDGET (window);
1613  container = GTK_CONTAINER (widget);
1614  info = gtk_window_get_geometry_info (window, TRUE);
1615  saved_last_info = info->last;
1616
1617  gtk_widget_size_request (widget, NULL);
1618  gtk_window_compute_default_size (window, &new_width, &new_height);
1619 
1620  if (info->last.width < 0 ||
1621      info->last.width != new_width ||
1622      info->last.height != new_height)
1623    {
1624      default_size_changed = TRUE;
1625      info->last.width = new_width;
1626      info->last.height = new_height;
1627
1628      /* We need to force a reposition in this case
1629       */
1630      if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
1631        window->use_uposition = TRUE;
1632    }
1633 
1634  /* Compute new set of hints for the window
1635   */
1636  gtk_window_compute_hints (window, &new_geometry, &new_flags);
1637  if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
1638                                 &new_geometry, new_flags))
1639    {
1640      hints_changed = TRUE;
1641      info->last.geometry = new_geometry;
1642      info->last.flags = new_flags;
1643    }
1644
1645  /* From the default size and the allocation, figure out the size
1646   * the window should be.
1647   */
1648  if (!default_size_changed ||
1649      (!window->auto_shrink &&
1650       new_width <= widget->allocation.width &&
1651       new_height <= widget->allocation.height))
1652    {
1653      new_width = widget->allocation.width;
1654      new_height = widget->allocation.height;
1655    }
1656
1657  /* constrain the window size to the specified geometry */
1658  gtk_window_constrain_size (window,
1659                             &new_geometry, new_flags,
1660                             new_width, new_height,
1661                             &new_width, &new_height);
1662
1663  /* compute new window position if a move is required
1664   */
1665  gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
1666  if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
1667    {
1668      new_flags |= GDK_HINT_POS;
1669      hints_changed = TRUE;
1670    }
1671
1672
1673  /* handle actual resizing:
1674   * - handle reallocations due to configure events
1675   * - figure whether we need to request a new window size
1676   * - handle simple resizes within our widget tree
1677   * - reposition window if neccessary
1678   */
1679  width = widget->allocation.width;
1680  height = widget->allocation.height;
1681
1682  if (window->handling_resize)
1683    {
1684      GtkAllocation allocation;
1685     
1686      /* if we are just responding to a configure event, which
1687       * might be due to a resize by the window manager, the
1688       * user, or a response to a resizing request we made
1689       * earlier, we go ahead, allocate the new size and we're done
1690       * (see gtk_window_configure_event() for more details).
1691       */
1692     
1693      window->handling_resize = FALSE;
1694     
1695      allocation = widget->allocation;
1696     
1697      gtk_widget_size_allocate (widget, &allocation);
1698      gtk_widget_queue_draw (widget);
1699
1700#ifdef FIXME_ZVT_ME_HARDER
1701      if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
1702        {
1703          /* We could be here for two reasons
1704           *  1) We coincidentally got a resize while handling
1705           *     another resize.
1706           *  2) Our computation of default_size_changed was completely
1707           *     screwed up, probably because one of our children
1708           *     is broken (i.e. changes requisition during
1709           *     size allocation). It's probably a zvt widget.
1710           *
1711           * For 1), we could just go ahead and ask for the
1712           * new size right now, but doing that for 2)
1713           * might well be fighting the user (and can even
1714           * trigger a loop). Since we really don't want to
1715           * do that, we requeue a resize in hopes that
1716           * by the time it gets handled, the child has seen
1717           * the light and is willing to go along with the
1718           * new size. (this happens for the zvt widget, since
1719           * the size_allocate() above will have stored the
1720           * requisition corresponding to the new size in the
1721           * zvt widget)
1722           *
1723           * This doesn't buy us anything for 1), but it shouldn't
1724           * hurt us too badly, since it is what would have
1725           * happened if we had gotten the configure event before
1726           * the new size had been set.
1727           */
1728         
1729          if (x != -1 && y != -1)
1730            gdk_window_move (widget->window, x, y);
1731
1732          /* we have to preserve the values and flags that are used
1733           * for computation of default_size_changed and hints_changed
1734           */
1735
1736          info->last = saved_last_info;
1737         
1738          gtk_widget_queue_resize (widget);
1739
1740          return;
1741        }
1742#endif /* FIXME_ZVT_ME_HARDER */
1743    }
1744
1745  /* Now set hints if necessary
1746   */
1747  if (hints_changed)
1748    gdk_window_set_geometry_hints (widget->window,
1749                                   &new_geometry,
1750                                   new_flags);
1751
1752  if ((default_size_changed || hints_changed) &&
1753      (width != new_width || height != new_height))
1754    {
1755      /* given that (width != new_width || height != new_height), we are in one
1756       * of the following situations:
1757       *
1758       * default_size_changed
1759       *   our requisition has changed and we need a different window size,
1760       *   so we request it from the window manager.
1761       *
1762       * !default_size_changed
1763       *   the window manager wouldn't assign us the size we requested, in this
1764       *   case we don't try to request a new size with every resize.
1765       *
1766       * !default_size_changed && hints_changed
1767       *   the window manager rejects our size, but we have just changed the
1768       *   window manager hints, so there's a certain chance our request will
1769       *   be honoured this time, so we try again.
1770       */
1771     
1772      /* request a new window size */
1773      if (x != -1 && y != -1)
1774        gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
1775      else
1776        gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
1777      window->resize_count += 1;
1778     
1779      /* we are now awaiting the new configure event in response to our
1780       * resizing request. the configure event will cause a new resize
1781       * with ->handling_resize=TRUE.
1782       * until then, we want to
1783       * - discard expose events
1784       * - coalesce resizes for our children
1785       * - defer any window resizes until the configure event arrived
1786       * to achive this, we queue a resize for the window, but remove its
1787       * resizing handler, so resizing will not be handled from the next
1788       * idle handler but when the configure event arrives.
1789       *
1790       * FIXME: we should also dequeue the pending redraws here, since
1791       * we handle those ourselves in ->handling_resize==TRUE.
1792       */
1793      gtk_widget_queue_resize (GTK_WIDGET (container));
1794      if (container->resize_mode == GTK_RESIZE_QUEUE)
1795        gtk_container_dequeue_resize_handler (container);
1796    }
1797  else
1798    {
1799      if (x != -1 && y != -1)
1800        gdk_window_move (widget->window, x, y);
1801
1802      if (container->resize_widgets)
1803        gtk_container_resize_children (GTK_CONTAINER (window));
1804    }
1805}
1806
1807/* Compare two sets of Geometry hints for equality.
1808 */
1809static gboolean
1810gtk_window_compare_hints (GdkGeometry *geometry_a,
1811                          guint        flags_a,
1812                          GdkGeometry *geometry_b,
1813                          guint        flags_b)
1814{
1815  if (flags_a != flags_b)
1816    return FALSE;
1817 
1818  if ((flags_a & GDK_HINT_MIN_SIZE) &&
1819      (geometry_a->min_width != geometry_b->min_width ||
1820       geometry_a->min_height != geometry_b->min_height))
1821    return FALSE;
1822
1823  if ((flags_a & GDK_HINT_MAX_SIZE) &&
1824      (geometry_a->max_width != geometry_b->max_width ||
1825       geometry_a->max_height != geometry_b->max_height))
1826    return FALSE;
1827
1828  if ((flags_a & GDK_HINT_BASE_SIZE) &&
1829      (geometry_a->base_width != geometry_b->base_width ||
1830       geometry_a->base_height != geometry_b->base_height))
1831    return FALSE;
1832
1833  if ((flags_a & GDK_HINT_ASPECT) &&
1834      (geometry_a->min_aspect != geometry_b->min_aspect ||
1835       geometry_a->max_aspect != geometry_b->max_aspect))
1836    return FALSE;
1837
1838  if ((flags_a & GDK_HINT_RESIZE_INC) &&
1839      (geometry_a->width_inc != geometry_b->width_inc ||
1840       geometry_a->height_inc != geometry_b->height_inc))
1841    return FALSE;
1842
1843  return TRUE;
1844}
1845
1846/* Compute the default_size for a window. The result will
1847 * be stored in *width and *height. The default size is
1848 * the size the window should have when initially mapped.
1849 * This routine does not attempt to constrain the size
1850 * to obey the geometry hints - that must be done elsewhere.
1851 */
1852static void
1853gtk_window_compute_default_size (GtkWindow       *window,
1854                                 guint           *width,
1855                                 guint           *height)
1856{
1857  GtkRequisition requisition;
1858  GtkWindowGeometryInfo *info;
1859 
1860  gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
1861  *width = requisition.width;
1862  *height = requisition.height;
1863
1864  info = gtk_window_get_geometry_info (window, FALSE);
1865 
1866  if (*width == 0 && *height == 0)
1867    {
1868      /* empty window */
1869      *width = 200;
1870      *height = 200;
1871    }
1872 
1873  if (info)
1874    {
1875      *width = info->width > 0 ? info->width : *width;
1876      *height = info->height > 0 ? info->height : *height;
1877    }
1878}
1879
1880/* Constrain a window size to obey the hints passed in geometry
1881 * and flags. The result will be stored in *new_width and *new_height
1882 *
1883 * This routine is partially borrowed from fvwm.
1884 *
1885 * Copyright 1993, Robert Nation
1886 *     You may use this code for any purpose, as long as the original
1887 *     copyright remains in the source code and all documentation
1888 *
1889 * which in turn borrows parts of the algorithm from uwm
1890 */
1891static void
1892gtk_window_constrain_size (GtkWindow   *window,
1893                           GdkGeometry *geometry,
1894                           guint        flags,
1895                           gint         width,
1896                           gint         height,
1897                           gint        *new_width,
1898                           gint        *new_height)
1899{
1900  gint min_width = 0;
1901  gint min_height = 0;
1902  gint base_width = 0;
1903  gint base_height = 0;
1904  gint xinc = 1;
1905  gint yinc = 1;
1906  gint max_width = G_MAXINT;
1907  gint max_height = G_MAXINT;
1908 
1909#define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
1910
1911  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
1912    {
1913      base_width = geometry->base_width;
1914      base_height = geometry->base_height;
1915      min_width = geometry->min_width;
1916      min_height = geometry->min_height;
1917    }
1918  else if (flags & GDK_HINT_BASE_SIZE)
1919    {
1920      base_width = geometry->base_width;
1921      base_height = geometry->base_height;
1922      min_width = geometry->base_width;
1923      min_height = geometry->base_height;
1924    }
1925  else if (flags & GDK_HINT_MIN_SIZE)
1926    {
1927      base_width = geometry->min_width;
1928      base_height = geometry->min_height;
1929      min_width = geometry->min_width;
1930      min_height = geometry->min_height;
1931    }
1932
1933  if (flags & GDK_HINT_MAX_SIZE)
1934    {
1935      max_width = geometry->max_width ;
1936      max_height = geometry->max_height;
1937    }
1938
1939  if (flags & GDK_HINT_RESIZE_INC)
1940    {
1941      xinc = MAX (xinc, geometry->width_inc);
1942      yinc = MAX (yinc, geometry->height_inc);
1943    }
1944 
1945  /* clamp width and height to min and max values
1946   */
1947  width = CLAMP (width, min_width, max_width);
1948  height = CLAMP (height, min_height, max_height);
1949 
1950  /* shrink to base + N * inc
1951   */
1952  width = base_width + FLOOR (width - base_width, xinc);
1953  height = base_height + FLOOR (height - base_height, yinc);
1954
1955  /* constrain aspect ratio, according to:
1956   *
1957   *                width     
1958   * min_aspect <= -------- <= max_aspect
1959   *                height   
1960   */
1961 
1962  if (flags & GDK_HINT_ASPECT &&
1963      geometry->min_aspect > 0 &&
1964      geometry->max_aspect > 0)
1965    {
1966      gint delta;
1967
1968      if (geometry->min_aspect * height > width)
1969        {
1970          delta = FLOOR (height - width * geometry->min_aspect, yinc);
1971          if (height - delta >= min_height)
1972            height -= delta;
1973          else
1974            {
1975              delta = FLOOR (height * geometry->min_aspect - width, xinc);
1976              if (width + delta <= max_width)
1977                width += delta;
1978            }
1979        }
1980     
1981      if (geometry->max_aspect * height < width)
1982        {
1983          delta = FLOOR (width - height * geometry->max_aspect, xinc);
1984          if (width - delta >= min_width)
1985            width -= delta;
1986          else
1987            {
1988              delta = FLOOR (width / geometry->max_aspect - height, yinc);
1989              if (height + delta <= max_height)
1990                height += delta;
1991            }
1992        }
1993    }
1994
1995#undef FLOOR
1996 
1997  *new_width = width;
1998  *new_height = height;
1999}
2000
2001/* Compute the set of geometry hints and flags for a window
2002 * based on the application set geometry, and requisiition
2003 * of the window. gtk_widget_size_request() must have been
2004 * called first.
2005 */
2006static void
2007gtk_window_compute_hints (GtkWindow   *window,
2008                          GdkGeometry *new_geometry,
2009                          guint       *new_flags)
2010{
2011  GtkWidget *widget;
2012  GtkWidgetAuxInfo *aux_info;
2013  gint ux, uy;
2014  gint extra_width = 0;
2015  gint extra_height = 0;
2016  GtkWindowGeometryInfo *geometry_info;
2017  GtkRequisition requisition;
2018
2019  g_return_if_fail (GTK_IS_WINDOW (window));
2020
2021  widget = GTK_WIDGET (window);
2022 
2023  gtk_widget_get_child_requisition (widget, &requisition);
2024  geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
2025
2026  g_return_if_fail (geometry_info != NULL);
2027 
2028  *new_flags = geometry_info->mask;
2029  *new_geometry = geometry_info->geometry;
2030 
2031  if (geometry_info->widget)
2032    {
2033      extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
2034      extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
2035    }
2036 
2037  ux = 0;
2038  uy = 0;
2039 
2040  aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2041  if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
2042    {
2043      ux = aux_info->x;
2044      uy = aux_info->y;
2045      *new_flags |= GDK_HINT_POS;
2046    }
2047 
2048  if (*new_flags & GDK_HINT_BASE_SIZE)
2049    {
2050      new_geometry->base_width += extra_width;
2051      new_geometry->base_height += extra_height;
2052    }
2053  else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
2054           (*new_flags & GDK_HINT_RESIZE_INC) &&
2055           ((extra_width != 0) || (extra_height != 0)))
2056    {
2057      *new_flags |= GDK_HINT_BASE_SIZE;
2058     
2059      new_geometry->base_width = extra_width;
2060      new_geometry->base_height = extra_height;
2061    }
2062 
2063  if (*new_flags & GDK_HINT_MIN_SIZE)
2064    {
2065      new_geometry->min_width += extra_width;
2066      new_geometry->min_height += extra_height;
2067    }
2068  else if (!window->allow_shrink)
2069    {
2070      *new_flags |= GDK_HINT_MIN_SIZE;
2071     
2072      new_geometry->min_width = requisition.width;
2073      new_geometry->min_height = requisition.height;
2074    }
2075 
2076  if (*new_flags & GDK_HINT_MAX_SIZE)
2077    {
2078      new_geometry->max_width += extra_width;
2079      new_geometry->max_height += extra_height;
2080    }
2081  else if (!window->allow_grow)
2082    {
2083      *new_flags |= GDK_HINT_MAX_SIZE;
2084     
2085      new_geometry->max_width = requisition.width;
2086      new_geometry->max_height = requisition.height;
2087    }
2088}
2089
2090/* Compute a new position for the window based on a new
2091 * size. *x and *y will be set to the new coordinates, or to -1 if the
2092 * window does not need to be moved
2093 */
2094static void
2095gtk_window_compute_reposition (GtkWindow  *window,
2096                               gint        new_width,
2097                               gint        new_height,
2098                               gint       *x,
2099                               gint       *y)
2100{
2101  GtkWidget *widget;
2102
2103  widget = GTK_WIDGET (window);
2104
2105  *x = -1;
2106  *y = -1;
2107 
2108  switch (window->position)
2109    {
2110    case GTK_WIN_POS_CENTER:
2111    case GTK_WIN_POS_CENTER_ALWAYS:
2112      if (window->use_uposition)
2113        {
2114          gint screen_width = gdk_screen_width ();
2115          gint screen_height = gdk_screen_height ();
2116         
2117          *x = (screen_width - new_width) / 2;
2118          *y = (screen_height - new_height) / 2;
2119        }
2120      break;
2121    case GTK_WIN_POS_MOUSE:
2122      if (window->use_uposition)
2123        {
2124          gint screen_width = gdk_screen_width ();
2125          gint screen_height = gdk_screen_height ();
2126         
2127          gdk_window_get_pointer (NULL, x, y, NULL);
2128          *x -= new_width / 2;
2129          *y -= new_height / 2;
2130          *x = CLAMP (*x, 0, screen_width - new_width);
2131          *y = CLAMP (*y, 0, screen_height - new_height);
2132        }
2133      break;
2134    default:
2135      if (window->use_uposition)
2136        {
2137          GtkWidgetAuxInfo *aux_info;
2138         
2139          aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
2140          if (aux_info &&
2141              aux_info->x != -1 && aux_info->y != -1 &&
2142              aux_info->x != -2 && aux_info->y != -2)
2143            {
2144              *x = aux_info->x;
2145              *y = aux_info->y;
2146            }
2147        }
2148      break;
2149    }
2150
2151  if (*x != -1 && *y != -1)
2152    {
2153      GtkWidgetAuxInfo *aux_info;
2154     
2155      /* we handle necessary window positioning by hand here,
2156       * so we can coalesce the window movement with possible
2157       * resizes to get only one configure event.
2158       * keep this in sync with gtk_widget_set_uposition()
2159       * and gtk_window_reposition().
2160       */
2161      gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
2162     
2163      aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2164      aux_info->x = *x;
2165      aux_info->y = *y;
2166
2167      window->use_uposition = FALSE;
2168    }
2169}
2170
2171/***********************
2172 * Redrawing functions *
2173 ***********************/
2174
2175static void
2176gtk_window_paint (GtkWidget     *widget,
2177                  GdkRectangle *area)
2178{
2179  gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
2180                      GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
2181}
2182
2183static gint
2184gtk_window_expose (GtkWidget      *widget,
2185                   GdkEventExpose *event)
2186{
2187  g_return_val_if_fail (widget != NULL, FALSE);
2188  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2189  g_return_val_if_fail (event != NULL, FALSE);
2190
2191  if (!GTK_WIDGET_APP_PAINTABLE (widget))
2192    gtk_window_paint (widget, &event->area);
2193 
2194  if (GTK_WIDGET_CLASS (parent_class)->expose_event)
2195    return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
2196
2197  return TRUE;
2198}
2199
2200static void
2201gtk_window_draw (GtkWidget    *widget,
2202                 GdkRectangle *area)
2203{
2204  if (!GTK_WIDGET_APP_PAINTABLE (widget))
2205    gtk_window_paint (widget, area);
2206 
2207  if (GTK_WIDGET_CLASS (parent_class)->draw)
2208    (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
2209}
Note: See TracBrowser for help on using the repository browser.