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

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