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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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-2000.  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 "config.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include "gdk/gdk.h"
33 #include "gdk/gdkkeysyms.h"
34 
35 #include "gtkintl.h"
36 
37 #include "gtkprivate.h"
38 #include "gtkrc.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
43 #include "gtkmain.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
49 #include "gtkplug.h"
50 #include "gtkbuildable.h"
51 #include "gtkalias.h"
52 
53 #ifdef GDK_WINDOWING_X11
54 #include "x11/gdkx.h"
55 #endif
56 
57 enum {
58   SET_FOCUS,
59   FRAME_EVENT,
60   ACTIVATE_FOCUS,
61   ACTIVATE_DEFAULT,
62   KEYS_CHANGED,
63   LAST_SIGNAL
64 };
65 
66 enum {
67   PROP_0,
68 
69   /* Construct */
70   PROP_TYPE,
71 
72   /* Normal Props */
73   PROP_TITLE,
74   PROP_ROLE,
75   PROP_ALLOW_SHRINK,
76   PROP_ALLOW_GROW,
77   PROP_RESIZABLE,
78   PROP_MODAL,
79   PROP_WIN_POS,
80   PROP_DEFAULT_WIDTH,
81   PROP_DEFAULT_HEIGHT,
82   PROP_DESTROY_WITH_PARENT,
83   PROP_ICON,
84   PROP_ICON_NAME,
85   PROP_SCREEN,
86   PROP_TYPE_HINT,
87   PROP_SKIP_TASKBAR_HINT,
88   PROP_SKIP_PAGER_HINT,
89   PROP_URGENCY_HINT,
90   PROP_ACCEPT_FOCUS,
91   PROP_FOCUS_ON_MAP,
92   PROP_DECORATED,
93   PROP_DELETABLE,
94   PROP_GRAVITY,
95   PROP_TRANSIENT_FOR,
96   PROP_OPACITY,
97 
98   /* Readonly properties */
99   PROP_IS_ACTIVE,
100   PROP_HAS_TOPLEVEL_FOCUS,
101 
102   /* Writeonly properties */
103   PROP_STARTUP_ID,
104 
105   PROP_MNEMONICS_VISIBLE,
106 
107   LAST_ARG
108 };
109 
110 typedef struct
111 {
112   GList     *icon_list;
113   GdkPixmap *icon_pixmap;
114   GdkPixmap *icon_mask;
115   gchar     *icon_name;
116   guint      realized : 1;
117   guint      using_default_icon : 1;
118   guint      using_parent_icon : 1;
119   guint      using_themed_icon : 1;
120 } GtkWindowIconInfo;
121 
122 typedef struct {
123   GdkGeometry    geometry; /* Last set of geometry hints we set */
124   GdkWindowHints flags;
125   GdkRectangle   configure_request;
126 } GtkWindowLastGeometryInfo;
127 
128 struct _GtkWindowGeometryInfo
129 {
130   /* Properties that the app has set on the window
131    */
132   GdkGeometry    geometry;	/* Geometry hints */
133   GdkWindowHints mask;
134   GtkWidget     *widget;	/* subwidget to which hints apply */
135   /* from last gtk_window_resize () - if > 0, indicates that
136    * we should resize to this size.
137    */
138   gint           resize_width;
139   gint           resize_height;
140 
141   /* From last gtk_window_move () prior to mapping -
142    * only used if initial_pos_set
143    */
144   gint           initial_x;
145   gint           initial_y;
146 
147   /* Default size - used only the FIRST time we map a window,
148    * only if > 0.
149    */
150   gint           default_width;
151   gint           default_height;
152   /* whether to use initial_x, initial_y */
153   guint          initial_pos_set : 1;
154   /* CENTER_ALWAYS or other position constraint changed since
155    * we sent the last configure request.
156    */
157   guint          position_constraints_changed : 1;
158 
159   /* if true, default_width, height come from gtk_window_parse_geometry,
160    * and thus should be multiplied by the increments and affect the
161    * geometry widget only
162    */
163   guint          default_is_geometry : 1;
164 
165   GtkWindowLastGeometryInfo last;
166 };
167 
168 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
169 
170 typedef struct _GtkWindowPrivate GtkWindowPrivate;
171 
172 struct _GtkWindowPrivate
173 {
174   GtkMnemonicHash *mnemonic_hash;
175 
176   guint above_initially : 1;
177   guint below_initially : 1;
178   guint fullscreen_initially : 1;
179   guint skips_taskbar : 1;
180   guint skips_pager : 1;
181   guint urgent : 1;
182   guint accept_focus : 1;
183   guint focus_on_map : 1;
184   guint deletable : 1;
185   guint transient_parent_group : 1;
186 
187   guint reset_type_hint : 1;
188   guint opacity_set : 1;
189   guint builder_visible : 1;
190 
191   guint mnemonics_visible : 1;
192   guint mnemonics_visible_set : 1;
193 
194   GdkWindowTypeHint type_hint;
195 
196   gdouble opacity;
197 
198   gchar *startup_id;
199 };
200 
201 static void gtk_window_dispose            (GObject           *object);
202 static void gtk_window_destroy            (GtkObject         *object);
203 static void gtk_window_finalize           (GObject           *object);
204 static void gtk_window_show               (GtkWidget         *widget);
205 static void gtk_window_hide               (GtkWidget         *widget);
206 static void gtk_window_map                (GtkWidget         *widget);
207 static void gtk_window_unmap              (GtkWidget         *widget);
208 static void gtk_window_realize            (GtkWidget         *widget);
209 static void gtk_window_unrealize          (GtkWidget         *widget);
210 static void gtk_window_size_request       (GtkWidget         *widget,
211 					   GtkRequisition    *requisition);
212 static void gtk_window_size_allocate      (GtkWidget         *widget,
213 					   GtkAllocation     *allocation);
214 static gint gtk_window_event              (GtkWidget *widget,
215 					   GdkEvent *event);
216 static gboolean gtk_window_map_event      (GtkWidget         *widget,
217                                            GdkEventAny       *event);
218 static gboolean gtk_window_frame_event    (GtkWindow *window,
219 					   GdkEvent *event);
220 static gint gtk_window_configure_event    (GtkWidget         *widget,
221 					   GdkEventConfigure *event);
222 static gint gtk_window_key_press_event    (GtkWidget         *widget,
223 					   GdkEventKey       *event);
224 static gint gtk_window_key_release_event  (GtkWidget         *widget,
225 					   GdkEventKey       *event);
226 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
227 					   GdkEventCrossing  *event);
228 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
229 					   GdkEventCrossing  *event);
230 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
231 					   GdkEventFocus     *event);
232 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
233 					   GdkEventFocus     *event);
234 static gint gtk_window_client_event	  (GtkWidget	     *widget,
235 					   GdkEventClient    *event);
236 static void gtk_window_check_resize       (GtkContainer      *container);
237 static gint gtk_window_focus              (GtkWidget        *widget,
238 				           GtkDirectionType  direction);
239 static void gtk_window_real_set_focus     (GtkWindow         *window,
240 					   GtkWidget         *focus);
241 
242 static void gtk_window_real_activate_default (GtkWindow         *window);
243 static void gtk_window_real_activate_focus   (GtkWindow         *window);
244 static void gtk_window_move_focus            (GtkWindow         *window,
245                                               GtkDirectionType   dir);
246 static void gtk_window_keys_changed          (GtkWindow         *window);
247 static void gtk_window_paint                 (GtkWidget         *widget,
248 					      GdkRectangle      *area);
249 static gint gtk_window_expose                (GtkWidget         *widget,
250 					      GdkEventExpose    *event);
251 static void gtk_window_unset_transient_for         (GtkWindow  *window);
252 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
253 						    GtkWidget  *window);
254 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
255 						    GtkWidget  *window);
256 
257 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
258 
259 static GtkWindowGeometryInfo* gtk_window_get_geometry_info         (GtkWindow    *window,
260                                                                     gboolean      create);
261 
262 static void     gtk_window_move_resize               (GtkWindow    *window);
263 static gboolean gtk_window_compare_hints             (GdkGeometry  *geometry_a,
264                                                       guint         flags_a,
265                                                       GdkGeometry  *geometry_b,
266                                                       guint         flags_b);
267 static void     gtk_window_constrain_size            (GtkWindow    *window,
268                                                       GdkGeometry  *geometry,
269                                                       guint         flags,
270                                                       gint          width,
271                                                       gint          height,
272                                                       gint         *new_width,
273                                                       gint         *new_height);
274 static void     gtk_window_constrain_position        (GtkWindow    *window,
275                                                       gint          new_width,
276                                                       gint          new_height,
277                                                       gint         *x,
278                                                       gint         *y);
279 static void     gtk_window_compute_hints             (GtkWindow    *window,
280                                                       GdkGeometry  *new_geometry,
281                                                       guint        *new_flags);
282 static void     gtk_window_compute_configure_request (GtkWindow    *window,
283                                                       GdkRectangle *request,
284                                                       GdkGeometry  *geometry,
285                                                       guint        *flags);
286 
287 static void     gtk_window_set_default_size_internal (GtkWindow    *window,
288                                                       gboolean      change_width,
289                                                       gint          width,
290                                                       gboolean      change_height,
291                                                       gint          height,
292 						      gboolean      is_geometry);
293 
294 static void     update_themed_icon                    (GtkIconTheme *theme,
295 				                       GtkWindow    *window);
296 static GList   *icon_list_from_theme                  (GtkWidget    *widget,
297 						       const gchar  *name);
298 static void     gtk_window_realize_icon               (GtkWindow    *window);
299 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
300 
301 static void        gtk_window_notify_keys_changed (GtkWindow   *window);
302 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
303 static void        gtk_window_free_key_hash       (GtkWindow   *window);
304 static void	   gtk_window_on_composited_changed (GdkScreen *screen,
305 						     GtkWindow *window);
306 
307 static GSList      *toplevel_list = NULL;
308 static guint        window_signals[LAST_SIGNAL] = { 0 };
309 static GList       *default_icon_list = NULL;
310 static gchar       *default_icon_name = NULL;
311 static guint        default_icon_serial = 0;
312 static gboolean     disable_startup_notification = FALSE;
313 static gboolean     sent_startup_notification = FALSE;
314 
315 static GQuark       quark_gtk_embedded = 0;
316 static GQuark       quark_gtk_window_key_hash = 0;
317 static GQuark       quark_gtk_window_default_icon_pixmap = 0;
318 static GQuark       quark_gtk_window_icon_info = 0;
319 static GQuark       quark_gtk_buildable_accels = 0;
320 
321 static GtkBuildableIface *parent_buildable_iface;
322 
323 static void gtk_window_set_property (GObject         *object,
324 				     guint            prop_id,
325 				     const GValue    *value,
326 				     GParamSpec      *pspec);
327 static void gtk_window_get_property (GObject         *object,
328 				     guint            prop_id,
329 				     GValue          *value,
330 				     GParamSpec      *pspec);
331 
332 /* GtkBuildable */
333 static void gtk_window_buildable_interface_init  (GtkBuildableIface *iface);
334 static void gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
335 							 GtkBuilder          *builder,
336 							 const gchar         *name,
337 							 const GValue        *value);
338 static void gtk_window_buildable_parser_finished (GtkBuildable     *buildable,
339 						  GtkBuilder       *builder);
340 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
341 						       GtkBuilder    *builder,
342 						       GObject       *child,
343 						       const gchar   *tagname,
344 						       GMarkupParser *parser,
345 						       gpointer      *data);
346 static void gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
347 						      GtkBuilder    *builder,
348 						      GObject       *child,
349 						      const gchar   *tagname,
350 						      gpointer       user_data);
351 
352 
G_DEFINE_TYPE_WITH_CODE(GtkWindow,gtk_window,GTK_TYPE_BIN,G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,gtk_window_buildable_interface_init))353 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
354                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
355 						gtk_window_buildable_interface_init))
356 
357 static void
358 add_tab_bindings (GtkBindingSet    *binding_set,
359 		  GdkModifierType   modifiers,
360 		  GtkDirectionType  direction)
361 {
362   gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
363                                 "move-focus", 1,
364                                 GTK_TYPE_DIRECTION_TYPE, direction);
365   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
366                                 "move-focus", 1,
367                                 GTK_TYPE_DIRECTION_TYPE, direction);
368 }
369 
370 static void
add_arrow_bindings(GtkBindingSet * binding_set,guint keysym,GtkDirectionType direction)371 add_arrow_bindings (GtkBindingSet    *binding_set,
372 		    guint             keysym,
373 		    GtkDirectionType  direction)
374 {
375   guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
376 
377   gtk_binding_entry_add_signal (binding_set, keysym, 0,
378                                 "move-focus", 1,
379                                 GTK_TYPE_DIRECTION_TYPE, direction);
380   gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
381                                 "move-focus", 1,
382                                 GTK_TYPE_DIRECTION_TYPE, direction);
383   gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
384                                 "move-focus", 1,
385                                 GTK_TYPE_DIRECTION_TYPE, direction);
386   gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
387                                 "move-focus", 1,
388                                 GTK_TYPE_DIRECTION_TYPE, direction);
389 }
390 
391 static guint32
extract_time_from_startup_id(const gchar * startup_id)392 extract_time_from_startup_id (const gchar* startup_id)
393 {
394   gchar *timestr = g_strrstr (startup_id, "_TIME");
395   guint32 retval = GDK_CURRENT_TIME;
396 
397   if (timestr)
398     {
399       gchar *end;
400       guint32 timestamp;
401 
402       /* Skip past the "_TIME" part */
403       timestr += 5;
404 
405       errno = 0;
406       timestamp = strtoul (timestr, &end, 0);
407       if (end != timestr && errno == 0)
408         retval = timestamp;
409     }
410 
411   return retval;
412 }
413 
414 static gboolean
startup_id_is_fake(const gchar * startup_id)415 startup_id_is_fake (const gchar* startup_id)
416 {
417   return strncmp (startup_id, "_TIME", 5) == 0;
418 }
419 
420 static void
gtk_window_class_init(GtkWindowClass * klass)421 gtk_window_class_init (GtkWindowClass *klass)
422 {
423   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
424   GtkObjectClass *object_class;
425   GtkWidgetClass *widget_class;
426   GtkContainerClass *container_class;
427   GtkBindingSet *binding_set;
428 
429   object_class = (GtkObjectClass*) klass;
430   widget_class = (GtkWidgetClass*) klass;
431   container_class = (GtkContainerClass*) klass;
432 
433   quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
434   quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
435   quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
436   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
437   quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
438 
439   gobject_class->dispose = gtk_window_dispose;
440   gobject_class->finalize = gtk_window_finalize;
441 
442   gobject_class->set_property = gtk_window_set_property;
443   gobject_class->get_property = gtk_window_get_property;
444 
445   object_class->destroy = gtk_window_destroy;
446 
447   widget_class->show = gtk_window_show;
448   widget_class->hide = gtk_window_hide;
449   widget_class->map = gtk_window_map;
450   widget_class->map_event = gtk_window_map_event;
451   widget_class->unmap = gtk_window_unmap;
452   widget_class->realize = gtk_window_realize;
453   widget_class->unrealize = gtk_window_unrealize;
454   widget_class->size_request = gtk_window_size_request;
455   widget_class->size_allocate = gtk_window_size_allocate;
456   widget_class->configure_event = gtk_window_configure_event;
457   widget_class->key_press_event = gtk_window_key_press_event;
458   widget_class->key_release_event = gtk_window_key_release_event;
459   widget_class->enter_notify_event = gtk_window_enter_notify_event;
460   widget_class->leave_notify_event = gtk_window_leave_notify_event;
461   widget_class->focus_in_event = gtk_window_focus_in_event;
462   widget_class->focus_out_event = gtk_window_focus_out_event;
463   widget_class->client_event = gtk_window_client_event;
464   widget_class->focus = gtk_window_focus;
465   widget_class->expose_event = gtk_window_expose;
466 
467   container_class->check_resize = gtk_window_check_resize;
468 
469   klass->set_focus = gtk_window_real_set_focus;
470   klass->frame_event = gtk_window_frame_event;
471 
472   klass->activate_default = gtk_window_real_activate_default;
473   klass->activate_focus = gtk_window_real_activate_focus;
474   klass->move_focus = gtk_window_move_focus;
475   klass->keys_changed = gtk_window_keys_changed;
476 
477   g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
478 
479   /* Construct */
480   g_object_class_install_property (gobject_class,
481                                    PROP_TYPE,
482                                    g_param_spec_enum ("type",
483 						      P_("Window Type"),
484 						      P_("The type of the window"),
485 						      GTK_TYPE_WINDOW_TYPE,
486 						      GTK_WINDOW_TOPLEVEL,
487 						      GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
488   /* Regular Props */
489   g_object_class_install_property (gobject_class,
490                                    PROP_TITLE,
491                                    g_param_spec_string ("title",
492                                                         P_("Window Title"),
493                                                         P_("The title of the window"),
494                                                         NULL,
495                                                         GTK_PARAM_READWRITE));
496 
497   g_object_class_install_property (gobject_class,
498                                    PROP_ROLE,
499                                    g_param_spec_string ("role",
500 							P_("Window Role"),
501 							P_("Unique identifier for the window to be used when restoring a session"),
502 							NULL,
503 							GTK_PARAM_READWRITE));
504 
505   /**
506    * GtkWindow:startup-id:
507    *
508    * The :startup-id is a write-only property for setting window's
509    * startup notification identifier. See gtk_window_set_startup_id()
510    * for more details.
511    *
512    * Since: 2.12
513    */
514   g_object_class_install_property (gobject_class,
515                                    PROP_STARTUP_ID,
516                                    g_param_spec_string ("startup-id",
517 							P_("Startup ID"),
518 							P_("Unique startup identifier for the window used by startup-notification"),
519 							NULL,
520 							GTK_PARAM_WRITABLE));
521 
522   /**
523    * GtkWindow:allow-shrink:
524    *
525    * If %TRUE, the window has no mimimum size. Setting this to %TRUE is
526    * 99&percnt; of the time a bad idea.
527    *
528    * Deprecated: 2.22: Use GtkWindow:resizable property instead.
529    */
530   g_object_class_install_property (gobject_class,
531                                    PROP_ALLOW_SHRINK,
532                                    g_param_spec_boolean ("allow-shrink",
533 							 P_("Allow Shrink"),
534 							 /* xgettext:no-c-format */
535 							 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
536 							 FALSE,
537 							 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
538 
539   /**
540    * GtkWindow:allow-grow:
541    *
542    * If %TRUE, users can expand the window beyond its minimum size.
543    *
544    * Deprecated: 2.22: Use GtkWindow:resizable property instead.
545    */
546   g_object_class_install_property (gobject_class,
547                                    PROP_ALLOW_GROW,
548                                    g_param_spec_boolean ("allow-grow",
549 							 P_("Allow Grow"),
550 							 P_("If TRUE, users can expand the window beyond its minimum size"),
551 							 TRUE,
552 							 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
553 
554   g_object_class_install_property (gobject_class,
555                                    PROP_RESIZABLE,
556                                    g_param_spec_boolean ("resizable",
557 							 P_("Resizable"),
558 							 P_("If TRUE, users can resize the window"),
559 							 TRUE,
560 							 GTK_PARAM_READWRITE));
561 
562   g_object_class_install_property (gobject_class,
563                                    PROP_MODAL,
564                                    g_param_spec_boolean ("modal",
565 							 P_("Modal"),
566 							 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
567 							 FALSE,
568 							 GTK_PARAM_READWRITE));
569 
570   g_object_class_install_property (gobject_class,
571                                    PROP_WIN_POS,
572                                    g_param_spec_enum ("window-position",
573 						      P_("Window Position"),
574 						      P_("The initial position of the window"),
575 						      GTK_TYPE_WINDOW_POSITION,
576 						      GTK_WIN_POS_NONE,
577 						      GTK_PARAM_READWRITE));
578 
579   g_object_class_install_property (gobject_class,
580                                    PROP_DEFAULT_WIDTH,
581                                    g_param_spec_int ("default-width",
582 						     P_("Default Width"),
583 						     P_("The default width of the window, used when initially showing the window"),
584 						     -1,
585 						     G_MAXINT,
586 						     -1,
587 						     GTK_PARAM_READWRITE));
588 
589   g_object_class_install_property (gobject_class,
590                                    PROP_DEFAULT_HEIGHT,
591                                    g_param_spec_int ("default-height",
592 						     P_("Default Height"),
593 						     P_("The default height of the window, used when initially showing the window"),
594 						     -1,
595 						     G_MAXINT,
596 						     -1,
597 						     GTK_PARAM_READWRITE));
598 
599   g_object_class_install_property (gobject_class,
600                                    PROP_DESTROY_WITH_PARENT,
601                                    g_param_spec_boolean ("destroy-with-parent",
602 							 P_("Destroy with Parent"),
603 							 P_("If this window should be destroyed when the parent is destroyed"),
604                                                          FALSE,
605 							 GTK_PARAM_READWRITE));
606 
607   g_object_class_install_property (gobject_class,
608                                    PROP_ICON,
609                                    g_param_spec_object ("icon",
610                                                         P_("Icon"),
611                                                         P_("Icon for this window"),
612                                                         GDK_TYPE_PIXBUF,
613                                                         GTK_PARAM_READWRITE));
614   g_object_class_install_property (gobject_class,
615                                    PROP_MNEMONICS_VISIBLE,
616                                    g_param_spec_boolean ("mnemonics-visible",
617                                                          P_("Mnemonics Visible"),
618                                                          P_("Whether mnemonics are currently visible in this window"),
619                                                          TRUE,
620                                                          GTK_PARAM_READWRITE));
621 
622   /**
623    * GtkWindow:icon-name:
624    *
625    * The :icon-name property specifies the name of the themed icon to
626    * use as the window icon. See #GtkIconTheme for more details.
627    *
628    * Since: 2.6
629    */
630   g_object_class_install_property (gobject_class,
631                                    PROP_ICON_NAME,
632                                    g_param_spec_string ("icon-name",
633                                                         P_("Icon Name"),
634                                                         P_("Name of the themed icon for this window"),
635 							NULL,
636                                                         GTK_PARAM_READWRITE));
637 
638   g_object_class_install_property (gobject_class,
639 				   PROP_SCREEN,
640 				   g_param_spec_object ("screen",
641  							P_("Screen"),
642  							P_("The screen where this window will be displayed"),
643 							GDK_TYPE_SCREEN,
644  							GTK_PARAM_READWRITE));
645 
646   g_object_class_install_property (gobject_class,
647                                    PROP_IS_ACTIVE,
648                                    g_param_spec_boolean ("is-active",
649 							 P_("Is Active"),
650 							 P_("Whether the toplevel is the current active window"),
651 							 FALSE,
652 							 GTK_PARAM_READABLE));
653 
654   g_object_class_install_property (gobject_class,
655                                    PROP_HAS_TOPLEVEL_FOCUS,
656                                    g_param_spec_boolean ("has-toplevel-focus",
657 							 P_("Focus in Toplevel"),
658 							 P_("Whether the input focus is within this GtkWindow"),
659 							 FALSE,
660 							 GTK_PARAM_READABLE));
661 
662   g_object_class_install_property (gobject_class,
663 				   PROP_TYPE_HINT,
664 				   g_param_spec_enum ("type-hint",
665                                                       P_("Type hint"),
666                                                       P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
667                                                       GDK_TYPE_WINDOW_TYPE_HINT,
668                                                       GDK_WINDOW_TYPE_HINT_NORMAL,
669                                                       GTK_PARAM_READWRITE));
670 
671   g_object_class_install_property (gobject_class,
672 				   PROP_SKIP_TASKBAR_HINT,
673 				   g_param_spec_boolean ("skip-taskbar-hint",
674                                                          P_("Skip taskbar"),
675                                                          P_("TRUE if the window should not be in the task bar."),
676                                                          FALSE,
677                                                          GTK_PARAM_READWRITE));
678 
679   g_object_class_install_property (gobject_class,
680 				   PROP_SKIP_PAGER_HINT,
681 				   g_param_spec_boolean ("skip-pager-hint",
682                                                          P_("Skip pager"),
683                                                          P_("TRUE if the window should not be in the pager."),
684                                                          FALSE,
685                                                          GTK_PARAM_READWRITE));
686 
687   g_object_class_install_property (gobject_class,
688 				   PROP_URGENCY_HINT,
689 				   g_param_spec_boolean ("urgency-hint",
690                                                          P_("Urgent"),
691                                                          P_("TRUE if the window should be brought to the user's attention."),
692                                                          FALSE,
693                                                          GTK_PARAM_READWRITE));
694 
695   /**
696    * GtkWindow:accept-focus:
697    *
698    * Whether the window should receive the input focus.
699    *
700    * Since: 2.4
701    */
702   g_object_class_install_property (gobject_class,
703 				   PROP_ACCEPT_FOCUS,
704 				   g_param_spec_boolean ("accept-focus",
705                                                          P_("Accept focus"),
706                                                          P_("TRUE if the window should receive the input focus."),
707                                                          TRUE,
708                                                          GTK_PARAM_READWRITE));
709 
710   /**
711    * GtkWindow:focus-on-map:
712    *
713    * Whether the window should receive the input focus when mapped.
714    *
715    * Since: 2.6
716    */
717   g_object_class_install_property (gobject_class,
718 				   PROP_FOCUS_ON_MAP,
719 				   g_param_spec_boolean ("focus-on-map",
720                                                          P_("Focus on map"),
721                                                          P_("TRUE if the window should receive the input focus when mapped."),
722                                                          TRUE,
723                                                          GTK_PARAM_READWRITE));
724 
725   /**
726    * GtkWindow:decorated:
727    *
728    * Whether the window should be decorated by the window manager.
729    *
730    * Since: 2.4
731    */
732   g_object_class_install_property (gobject_class,
733                                    PROP_DECORATED,
734                                    g_param_spec_boolean ("decorated",
735 							 P_("Decorated"),
736 							 P_("Whether the window should be decorated by the window manager"),
737 							 TRUE,
738 							 GTK_PARAM_READWRITE));
739 
740   /**
741    * GtkWindow:deletable:
742    *
743    * Whether the window frame should have a close button.
744    *
745    * Since: 2.10
746    */
747   g_object_class_install_property (gobject_class,
748                                    PROP_DELETABLE,
749                                    g_param_spec_boolean ("deletable",
750 							 P_("Deletable"),
751 							 P_("Whether the window frame should have a close button"),
752 							 TRUE,
753 							 GTK_PARAM_READWRITE));
754 
755 
756   /**
757    * GtkWindow:gravity:
758    *
759    * The window gravity of the window. See gtk_window_move() and #GdkGravity for
760    * more details about window gravity.
761    *
762    * Since: 2.4
763    */
764   g_object_class_install_property (gobject_class,
765                                    PROP_GRAVITY,
766                                    g_param_spec_enum ("gravity",
767 						      P_("Gravity"),
768 						      P_("The window gravity of the window"),
769 						      GDK_TYPE_GRAVITY,
770 						      GDK_GRAVITY_NORTH_WEST,
771 						      GTK_PARAM_READWRITE));
772 
773 
774   /**
775    * GtkWindow:transient-for:
776    *
777    * The transient parent of the window. See gtk_window_set_transient_for() for
778    * more details about transient windows.
779    *
780    * Since: 2.10
781    */
782   g_object_class_install_property (gobject_class,
783 				   PROP_TRANSIENT_FOR,
784 				   g_param_spec_object ("transient-for",
785 							P_("Transient for Window"),
786 							P_("The transient parent of the dialog"),
787 							GTK_TYPE_WINDOW,
788 							GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
789 
790   /**
791    * GtkWindow:opacity:
792    *
793    * The requested opacity of the window. See gtk_window_set_opacity() for
794    * more details about window opacity.
795    *
796    * Since: 2.12
797    */
798   g_object_class_install_property (gobject_class,
799 				   PROP_OPACITY,
800 				   g_param_spec_double ("opacity",
801 							P_("Opacity for Window"),
802 							P_("The opacity of the window, from 0 to 1"),
803 							0.0,
804 							1.0,
805 							1.0,
806 							GTK_PARAM_READWRITE));
807 
808   window_signals[SET_FOCUS] =
809     g_signal_new (I_("set-focus"),
810                   G_TYPE_FROM_CLASS (gobject_class),
811                   G_SIGNAL_RUN_LAST,
812                   G_STRUCT_OFFSET (GtkWindowClass, set_focus),
813                   NULL, NULL,
814                   _gtk_marshal_VOID__OBJECT,
815                   G_TYPE_NONE, 1,
816                   GTK_TYPE_WIDGET);
817 
818   window_signals[FRAME_EVENT] =
819     g_signal_new (I_("frame-event"),
820                   G_TYPE_FROM_CLASS (gobject_class),
821                   G_SIGNAL_RUN_LAST,
822                   G_STRUCT_OFFSET(GtkWindowClass, frame_event),
823                   _gtk_boolean_handled_accumulator, NULL,
824                   _gtk_marshal_BOOLEAN__BOXED,
825                   G_TYPE_BOOLEAN, 1,
826                   GDK_TYPE_EVENT);
827 
828   /**
829    * GtkWindow::activate-focus:
830    * @window: the window which received the signal
831    *
832    * The ::activate-focus signal is a
833    * <link linkend="keybinding-signals">keybinding signal</link>
834    * which gets emitted when the user activates the currently
835    * focused widget of @window.
836    */
837   window_signals[ACTIVATE_FOCUS] =
838     g_signal_new (I_("activate-focus"),
839                   G_TYPE_FROM_CLASS (gobject_class),
840                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
841                   G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
842                   NULL, NULL,
843                   _gtk_marshal_VOID__VOID,
844                   G_TYPE_NONE,
845                   0);
846 
847   /**
848    * GtkWindow::activate-default:
849    * @window: the window which received the signal
850    *
851    * The ::activate-default signal is a
852    * <link linkend="keybinding-signals">keybinding signal</link>
853    * which gets emitted when the user activates the default widget
854    * of @window.
855    */
856   window_signals[ACTIVATE_DEFAULT] =
857     g_signal_new (I_("activate-default"),
858                   G_TYPE_FROM_CLASS (gobject_class),
859                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
860                   G_STRUCT_OFFSET (GtkWindowClass, activate_default),
861                   NULL, NULL,
862                   _gtk_marshal_VOID__VOID,
863                   G_TYPE_NONE,
864                   0);
865 
866   /**
867    * GtkWindow::keys-changed:
868    * @window: the window which received the signal
869    *
870    * The ::keys-changed signal gets emitted when the set of accelerators
871    * or mnemonics that are associated with @window changes.
872    */
873   window_signals[KEYS_CHANGED] =
874     g_signal_new (I_("keys-changed"),
875                   G_TYPE_FROM_CLASS (gobject_class),
876                   G_SIGNAL_RUN_FIRST,
877                   G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
878                   NULL, NULL,
879                   _gtk_marshal_VOID__VOID,
880                   G_TYPE_NONE,
881                   0);
882 
883   /*
884    * Key bindings
885    */
886 
887   binding_set = gtk_binding_set_by_class (klass);
888 
889   gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
890                                 "activate-focus", 0);
891   gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
892                                 "activate-focus", 0);
893 
894   gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
895                                 "activate-default", 0);
896   gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
897                                 "activate-default", 0);
898   gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
899                                 "activate-default", 0);
900 
901   add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
902   add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
903   add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
904   add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
905 
906   add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
907   add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
908   add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
909   add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
910 }
911 
912 static void
gtk_window_init(GtkWindow * window)913 gtk_window_init (GtkWindow *window)
914 {
915   GdkColormap *colormap;
916   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
917 
918   gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
919   _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
920 
921   GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
922 
923   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
924 
925   window->title = NULL;
926   window->wmclass_name = g_strdup (g_get_prgname ());
927   window->wmclass_class = g_strdup (gdk_get_program_class ());
928   window->wm_role = NULL;
929   window->geometry_info = NULL;
930   window->type = GTK_WINDOW_TOPLEVEL;
931   window->focus_widget = NULL;
932   window->default_widget = NULL;
933   window->configure_request_count = 0;
934   window->allow_shrink = FALSE;
935   window->allow_grow = TRUE;
936   window->configure_notify_received = FALSE;
937   window->position = GTK_WIN_POS_NONE;
938   window->need_default_size = TRUE;
939   window->need_default_position = TRUE;
940   window->modal = FALSE;
941   window->frame = NULL;
942   window->has_frame = FALSE;
943   window->frame_left = 0;
944   window->frame_right = 0;
945   window->frame_top = 0;
946   window->frame_bottom = 0;
947   window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
948   window->gravity = GDK_GRAVITY_NORTH_WEST;
949   window->decorated = TRUE;
950   window->mnemonic_modifier = GDK_MOD1_MASK;
951   window->screen = gdk_screen_get_default ();
952 
953   priv->accept_focus = TRUE;
954   priv->focus_on_map = TRUE;
955   priv->deletable = TRUE;
956   priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
957   priv->opacity = 1.0;
958   priv->startup_id = NULL;
959   priv->mnemonics_visible = TRUE;
960 
961   colormap = _gtk_widget_peek_colormap ();
962   if (colormap)
963     gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
964 
965   g_object_ref_sink (window);
966   window->has_user_ref_count = TRUE;
967   toplevel_list = g_slist_prepend (toplevel_list, window);
968 
969   gtk_decorated_window_init (window);
970 
971   g_signal_connect (window->screen, "composited-changed",
972 		    G_CALLBACK (gtk_window_on_composited_changed), window);
973 }
974 
975 static void
gtk_window_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)976 gtk_window_set_property (GObject      *object,
977 			 guint         prop_id,
978 			 const GValue *value,
979 			 GParamSpec   *pspec)
980 {
981   GtkWindow  *window;
982   GtkWindowPrivate *priv;
983 
984   window = GTK_WINDOW (object);
985 
986   priv = GTK_WINDOW_GET_PRIVATE (window);
987 
988   switch (prop_id)
989     {
990     case PROP_TYPE:
991       window->type = g_value_get_enum (value);
992       break;
993     case PROP_TITLE:
994       gtk_window_set_title (window, g_value_get_string (value));
995       break;
996     case PROP_ROLE:
997       gtk_window_set_role (window, g_value_get_string (value));
998       break;
999     case PROP_STARTUP_ID:
1000       gtk_window_set_startup_id (window, g_value_get_string (value));
1001       break;
1002     case PROP_ALLOW_SHRINK:
1003       window->allow_shrink = g_value_get_boolean (value);
1004       gtk_widget_queue_resize (GTK_WIDGET (window));
1005       break;
1006     case PROP_ALLOW_GROW:
1007       window->allow_grow = g_value_get_boolean (value);
1008       gtk_widget_queue_resize (GTK_WIDGET (window));
1009       g_object_notify (G_OBJECT (window), "resizable");
1010       break;
1011     case PROP_RESIZABLE:
1012       window->allow_grow = g_value_get_boolean (value);
1013       gtk_widget_queue_resize (GTK_WIDGET (window));
1014       g_object_notify (G_OBJECT (window), "allow-grow");
1015       break;
1016     case PROP_MODAL:
1017       gtk_window_set_modal (window, g_value_get_boolean (value));
1018       break;
1019     case PROP_WIN_POS:
1020       gtk_window_set_position (window, g_value_get_enum (value));
1021       break;
1022     case PROP_DEFAULT_WIDTH:
1023       gtk_window_set_default_size_internal (window,
1024                                             TRUE, g_value_get_int (value),
1025                                             FALSE, -1, FALSE);
1026       break;
1027     case PROP_DEFAULT_HEIGHT:
1028       gtk_window_set_default_size_internal (window,
1029                                             FALSE, -1,
1030                                             TRUE, g_value_get_int (value), FALSE);
1031       break;
1032     case PROP_DESTROY_WITH_PARENT:
1033       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1034       break;
1035     case PROP_ICON:
1036       gtk_window_set_icon (window,
1037                            g_value_get_object (value));
1038       break;
1039     case PROP_ICON_NAME:
1040       gtk_window_set_icon_name (window, g_value_get_string (value));
1041       break;
1042     case PROP_SCREEN:
1043       gtk_window_set_screen (window, g_value_get_object (value));
1044       break;
1045     case PROP_TYPE_HINT:
1046       gtk_window_set_type_hint (window,
1047                                 g_value_get_enum (value));
1048       break;
1049     case PROP_SKIP_TASKBAR_HINT:
1050       gtk_window_set_skip_taskbar_hint (window,
1051                                         g_value_get_boolean (value));
1052       break;
1053     case PROP_SKIP_PAGER_HINT:
1054       gtk_window_set_skip_pager_hint (window,
1055                                       g_value_get_boolean (value));
1056       break;
1057     case PROP_URGENCY_HINT:
1058       gtk_window_set_urgency_hint (window,
1059 				   g_value_get_boolean (value));
1060       break;
1061     case PROP_ACCEPT_FOCUS:
1062       gtk_window_set_accept_focus (window,
1063 				   g_value_get_boolean (value));
1064       break;
1065     case PROP_FOCUS_ON_MAP:
1066       gtk_window_set_focus_on_map (window,
1067 				   g_value_get_boolean (value));
1068       break;
1069     case PROP_DECORATED:
1070       gtk_window_set_decorated (window, g_value_get_boolean (value));
1071       break;
1072     case PROP_DELETABLE:
1073       gtk_window_set_deletable (window, g_value_get_boolean (value));
1074       break;
1075     case PROP_GRAVITY:
1076       gtk_window_set_gravity (window, g_value_get_enum (value));
1077       break;
1078     case PROP_TRANSIENT_FOR:
1079       gtk_window_set_transient_for (window, g_value_get_object (value));
1080       break;
1081     case PROP_OPACITY:
1082       gtk_window_set_opacity (window, g_value_get_double (value));
1083       break;
1084     case PROP_MNEMONICS_VISIBLE:
1085       gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1086       break;
1087     default:
1088       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1089       break;
1090     }
1091 }
1092 
1093 static void
gtk_window_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1094 gtk_window_get_property (GObject      *object,
1095 			 guint         prop_id,
1096 			 GValue       *value,
1097 			 GParamSpec   *pspec)
1098 {
1099   GtkWindow  *window;
1100   GtkWindowPrivate *priv;
1101 
1102   window = GTK_WINDOW (object);
1103   priv = GTK_WINDOW_GET_PRIVATE (window);
1104 
1105   switch (prop_id)
1106     {
1107       GtkWindowGeometryInfo *info;
1108     case PROP_TYPE:
1109       g_value_set_enum (value, window->type);
1110       break;
1111     case PROP_ROLE:
1112       g_value_set_string (value, window->wm_role);
1113       break;
1114     case PROP_TITLE:
1115       g_value_set_string (value, window->title);
1116       break;
1117     case PROP_ALLOW_SHRINK:
1118       g_value_set_boolean (value, window->allow_shrink);
1119       break;
1120     case PROP_ALLOW_GROW:
1121       g_value_set_boolean (value, window->allow_grow);
1122       break;
1123     case PROP_RESIZABLE:
1124       g_value_set_boolean (value, window->allow_grow);
1125       break;
1126     case PROP_MODAL:
1127       g_value_set_boolean (value, window->modal);
1128       break;
1129     case PROP_WIN_POS:
1130       g_value_set_enum (value, window->position);
1131       break;
1132     case PROP_DEFAULT_WIDTH:
1133       info = gtk_window_get_geometry_info (window, FALSE);
1134       if (!info)
1135 	g_value_set_int (value, -1);
1136       else
1137 	g_value_set_int (value, info->default_width);
1138       break;
1139     case PROP_DEFAULT_HEIGHT:
1140       info = gtk_window_get_geometry_info (window, FALSE);
1141       if (!info)
1142 	g_value_set_int (value, -1);
1143       else
1144 	g_value_set_int (value, info->default_height);
1145       break;
1146     case PROP_DESTROY_WITH_PARENT:
1147       g_value_set_boolean (value, window->destroy_with_parent);
1148       break;
1149     case PROP_ICON:
1150       g_value_set_object (value, gtk_window_get_icon (window));
1151       break;
1152     case PROP_ICON_NAME:
1153       g_value_set_string (value, gtk_window_get_icon_name (window));
1154       break;
1155     case PROP_SCREEN:
1156       g_value_set_object (value, window->screen);
1157       break;
1158     case PROP_IS_ACTIVE:
1159       g_value_set_boolean (value, window->is_active);
1160       break;
1161     case PROP_HAS_TOPLEVEL_FOCUS:
1162       g_value_set_boolean (value, window->has_toplevel_focus);
1163       break;
1164     case PROP_TYPE_HINT:
1165       g_value_set_enum (value, priv->type_hint);
1166       break;
1167     case PROP_SKIP_TASKBAR_HINT:
1168       g_value_set_boolean (value,
1169                            gtk_window_get_skip_taskbar_hint (window));
1170       break;
1171     case PROP_SKIP_PAGER_HINT:
1172       g_value_set_boolean (value,
1173                            gtk_window_get_skip_pager_hint (window));
1174       break;
1175     case PROP_URGENCY_HINT:
1176       g_value_set_boolean (value,
1177                            gtk_window_get_urgency_hint (window));
1178       break;
1179     case PROP_ACCEPT_FOCUS:
1180       g_value_set_boolean (value,
1181                            gtk_window_get_accept_focus (window));
1182       break;
1183     case PROP_FOCUS_ON_MAP:
1184       g_value_set_boolean (value,
1185                            gtk_window_get_focus_on_map (window));
1186       break;
1187     case PROP_DECORATED:
1188       g_value_set_boolean (value, gtk_window_get_decorated (window));
1189       break;
1190     case PROP_DELETABLE:
1191       g_value_set_boolean (value, gtk_window_get_deletable (window));
1192       break;
1193     case PROP_GRAVITY:
1194       g_value_set_enum (value, gtk_window_get_gravity (window));
1195       break;
1196     case PROP_TRANSIENT_FOR:
1197       g_value_set_object (value, gtk_window_get_transient_for (window));
1198       break;
1199     case PROP_OPACITY:
1200       g_value_set_double (value, gtk_window_get_opacity (window));
1201       break;
1202     case PROP_MNEMONICS_VISIBLE:
1203       g_value_set_boolean (value, priv->mnemonics_visible);
1204       break;
1205     default:
1206       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1207       break;
1208     }
1209 }
1210 
1211 static void
gtk_window_buildable_interface_init(GtkBuildableIface * iface)1212 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1213 {
1214   parent_buildable_iface = g_type_interface_peek_parent (iface);
1215   iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1216   iface->parser_finished = gtk_window_buildable_parser_finished;
1217   iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1218   iface->custom_finished = gtk_window_buildable_custom_finished;
1219 }
1220 
1221 static void
gtk_window_buildable_set_buildable_property(GtkBuildable * buildable,GtkBuilder * builder,const gchar * name,const GValue * value)1222 gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
1223 					     GtkBuilder          *builder,
1224 					     const gchar         *name,
1225 					     const GValue        *value)
1226 {
1227   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1228 
1229   if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1230     priv->builder_visible = TRUE;
1231   else
1232     parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1233 }
1234 
1235 static void
gtk_window_buildable_parser_finished(GtkBuildable * buildable,GtkBuilder * builder)1236 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1237 				      GtkBuilder   *builder)
1238 {
1239   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1240   GObject *object;
1241   GSList *accels, *l;
1242 
1243   if (priv->builder_visible)
1244     gtk_widget_show (GTK_WIDGET (buildable));
1245 
1246   accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1247   for (l = accels; l; l = l->next)
1248     {
1249       object = gtk_builder_get_object (builder, l->data);
1250       if (!object)
1251 	{
1252 	  g_warning ("Unknown accel group %s specified in window %s",
1253 		     (const gchar*)l->data, gtk_buildable_get_name (buildable));
1254 	  continue;
1255 	}
1256       gtk_window_add_accel_group (GTK_WINDOW (buildable),
1257 				  GTK_ACCEL_GROUP (object));
1258       g_free (l->data);
1259     }
1260 
1261   g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1262 
1263   parent_buildable_iface->parser_finished (buildable, builder);
1264 }
1265 
1266 typedef struct {
1267   GObject *object;
1268   GSList *items;
1269 } GSListSubParserData;
1270 
1271 static void
window_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** names,const gchar ** values,gpointer user_data,GError ** error)1272 window_start_element (GMarkupParseContext *context,
1273 			  const gchar         *element_name,
1274 			  const gchar        **names,
1275 			  const gchar        **values,
1276 			  gpointer            user_data,
1277 			  GError            **error)
1278 {
1279   guint i;
1280   GSListSubParserData *data = (GSListSubParserData*)user_data;
1281 
1282   if (strcmp (element_name, "group") == 0)
1283     {
1284       for (i = 0; names[i]; i++)
1285 	{
1286 	  if (strcmp (names[i], "name") == 0)
1287 	    data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1288 	}
1289     }
1290   else if (strcmp (element_name, "accel-groups") == 0)
1291     return;
1292   else
1293     g_warning ("Unsupported tag type for GtkWindow: %s\n",
1294 	       element_name);
1295 
1296 }
1297 
1298 static const GMarkupParser window_parser =
1299   {
1300     window_start_element
1301   };
1302 
1303 static gboolean
gtk_window_buildable_custom_tag_start(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const gchar * tagname,GMarkupParser * parser,gpointer * data)1304 gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
1305 				       GtkBuilder    *builder,
1306 				       GObject       *child,
1307 				       const gchar   *tagname,
1308 				       GMarkupParser *parser,
1309 				       gpointer      *data)
1310 {
1311   GSListSubParserData *parser_data;
1312 
1313   if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1314 						tagname, parser, data))
1315     return TRUE;
1316 
1317   if (strcmp (tagname, "accel-groups") == 0)
1318     {
1319       parser_data = g_slice_new0 (GSListSubParserData);
1320       parser_data->items = NULL;
1321       parser_data->object = G_OBJECT (buildable);
1322 
1323       *parser = window_parser;
1324       *data = parser_data;
1325       return TRUE;
1326     }
1327 
1328   return FALSE;
1329 }
1330 
1331 static void
gtk_window_buildable_custom_finished(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const gchar * tagname,gpointer user_data)1332 gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
1333 					  GtkBuilder    *builder,
1334 					  GObject       *child,
1335 					  const gchar   *tagname,
1336 					  gpointer       user_data)
1337 {
1338   GSListSubParserData *data;
1339 
1340   parent_buildable_iface->custom_finished (buildable, builder, child,
1341 					   tagname, user_data);
1342 
1343   if (strcmp (tagname, "accel-groups") != 0)
1344     return;
1345 
1346   data = (GSListSubParserData*)user_data;
1347 
1348   g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1349 			   data->items, (GDestroyNotify) g_slist_free);
1350 
1351   g_slice_free (GSListSubParserData, data);
1352 }
1353 
1354 /**
1355  * gtk_window_new:
1356  * @type: type of window
1357  *
1358  * Creates a new #GtkWindow, which is a toplevel window that can
1359  * contain other widgets. Nearly always, the type of the window should
1360  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1361  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1362  * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1363  * dialogs, though in some other toolkits dialogs are called "popups".
1364  * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1365  * On X11, popup windows are not controlled by the <link
1366  * linkend="gtk-X11-arch">window manager</link>.
1367  *
1368  * If you simply want an undecorated window (no window borders), use
1369  * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1370  *
1371  * Return value: a new #GtkWindow.
1372  **/
1373 GtkWidget*
gtk_window_new(GtkWindowType type)1374 gtk_window_new (GtkWindowType type)
1375 {
1376   GtkWindow *window;
1377 
1378   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1379 
1380   window = g_object_new (GTK_TYPE_WINDOW, NULL);
1381 
1382   window->type = type;
1383 
1384   return GTK_WIDGET (window);
1385 }
1386 
1387 /**
1388  * gtk_window_set_title:
1389  * @window: a #GtkWindow
1390  * @title: title of the window
1391  *
1392  * Sets the title of the #GtkWindow. The title of a window will be
1393  * displayed in its title bar; on the X Window System, the title bar
1394  * is rendered by the <link linkend="gtk-X11-arch">window
1395  * manager</link>, so exactly how the title appears to users may vary
1396  * according to a user's exact configuration. The title should help a
1397  * user distinguish this window from other windows they may have
1398  * open. A good title might include the application name and current
1399  * document filename, for example.
1400  *
1401  **/
1402 void
gtk_window_set_title(GtkWindow * window,const gchar * title)1403 gtk_window_set_title (GtkWindow   *window,
1404 		      const gchar *title)
1405 {
1406   char *new_title;
1407 
1408   g_return_if_fail (GTK_IS_WINDOW (window));
1409 
1410   new_title = g_strdup (title);
1411   g_free (window->title);
1412   window->title = new_title;
1413 
1414   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1415     {
1416       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1417 
1418       gtk_decorated_window_set_title (window, title);
1419     }
1420 
1421   g_object_notify (G_OBJECT (window), "title");
1422 }
1423 
1424 /**
1425  * gtk_window_get_title:
1426  * @window: a #GtkWindow
1427  *
1428  * Retrieves the title of the window. See gtk_window_set_title().
1429  *
1430  * Return value: the title of the window, or %NULL if none has
1431  *    been set explicitely. The returned string is owned by the widget
1432  *    and must not be modified or freed.
1433  **/
1434 const gchar *
gtk_window_get_title(GtkWindow * window)1435 gtk_window_get_title (GtkWindow *window)
1436 {
1437   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1438 
1439   return window->title;
1440 }
1441 
1442 /**
1443  * gtk_window_set_wmclass:
1444  * @window: a #GtkWindow
1445  * @wmclass_name: window name hint
1446  * @wmclass_class: window class hint
1447  *
1448  * Don't use this function. It sets the X Window System "class" and
1449  * "name" hints for a window.  According to the ICCCM, you should
1450  * always set these to the same value for all windows in an
1451  * application, and GTK+ sets them to that value by default, so calling
1452  * this function is sort of pointless. However, you may want to call
1453  * gtk_window_set_role() on each window in your application, for the
1454  * benefit of the session manager. Setting the role allows the window
1455  * manager to restore window positions when loading a saved session.
1456  *
1457  **/
1458 void
gtk_window_set_wmclass(GtkWindow * window,const gchar * wmclass_name,const gchar * wmclass_class)1459 gtk_window_set_wmclass (GtkWindow *window,
1460 			const gchar *wmclass_name,
1461 			const gchar *wmclass_class)
1462 {
1463   g_return_if_fail (GTK_IS_WINDOW (window));
1464 
1465   g_free (window->wmclass_name);
1466   window->wmclass_name = g_strdup (wmclass_name);
1467 
1468   g_free (window->wmclass_class);
1469   window->wmclass_class = g_strdup (wmclass_class);
1470 
1471   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1472     g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1473 }
1474 
1475 /**
1476  * gtk_window_set_role:
1477  * @window: a #GtkWindow
1478  * @role: unique identifier for the window to be used when restoring a session
1479  *
1480  * This function is only useful on X11, not with other GTK+ targets.
1481  *
1482  * In combination with the window title, the window role allows a
1483  * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1484  * same" window when an application is restarted. So for example you
1485  * might set the "toolbox" role on your app's toolbox window, so that
1486  * when the user restarts their session, the window manager can put
1487  * the toolbox back in the same place.
1488  *
1489  * If a window already has a unique title, you don't need to set the
1490  * role, since the WM can use the title to identify the window when
1491  * restoring the session.
1492  *
1493  **/
1494 void
gtk_window_set_role(GtkWindow * window,const gchar * role)1495 gtk_window_set_role (GtkWindow   *window,
1496                      const gchar *role)
1497 {
1498   char *new_role;
1499 
1500   g_return_if_fail (GTK_IS_WINDOW (window));
1501 
1502   new_role = g_strdup (role);
1503   g_free (window->wm_role);
1504   window->wm_role = new_role;
1505 
1506   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1507     gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1508 
1509   g_object_notify (G_OBJECT (window), "role");
1510 }
1511 
1512 /**
1513  * gtk_window_set_startup_id:
1514  * @window: a #GtkWindow
1515  * @startup_id: a string with startup-notification identifier
1516  *
1517  * Startup notification identifiers are used by desktop environment to
1518  * track application startup, to provide user feedback and other
1519  * features. This function changes the corresponding property on the
1520  * underlying GdkWindow. Normally, startup identifier is managed
1521  * automatically and you should only use this function in special cases
1522  * like transferring focus from other processes. You should use this
1523  * function before calling gtk_window_present() or any equivalent
1524  * function generating a window map event.
1525  *
1526  * This function is only useful on X11, not with other GTK+ targets.
1527  *
1528  * Since: 2.12
1529  **/
1530 void
gtk_window_set_startup_id(GtkWindow * window,const gchar * startup_id)1531 gtk_window_set_startup_id (GtkWindow   *window,
1532                            const gchar *startup_id)
1533 {
1534   GtkWindowPrivate *priv;
1535 
1536   g_return_if_fail (GTK_IS_WINDOW (window));
1537 
1538   priv = GTK_WINDOW_GET_PRIVATE (window);
1539 
1540   g_free (priv->startup_id);
1541   priv->startup_id = g_strdup (startup_id);
1542 
1543   if (gtk_widget_get_realized (GTK_WIDGET (window)))
1544     {
1545       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1546 
1547 #ifdef GDK_WINDOWING_X11
1548       if (timestamp != GDK_CURRENT_TIME)
1549 	gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, timestamp);
1550 #endif
1551 
1552       /* Here we differentiate real and "fake" startup notification IDs,
1553        * constructed on purpose just to pass interaction timestamp
1554        */
1555       if (startup_id_is_fake (priv->startup_id))
1556 	gtk_window_present_with_time (window, timestamp);
1557       else
1558         {
1559           gdk_window_set_startup_id (GTK_WIDGET (window)->window,
1560                                      priv->startup_id);
1561 
1562           /* If window is mapped, terminate the startup-notification too */
1563           if (gtk_widget_get_mapped (GTK_WIDGET (window)) &&
1564               !disable_startup_notification)
1565             gdk_notify_startup_complete_with_id (priv->startup_id);
1566         }
1567     }
1568 
1569   g_object_notify (G_OBJECT (window), "startup-id");
1570 }
1571 
1572 /**
1573  * gtk_window_get_role:
1574  * @window: a #GtkWindow
1575  *
1576  * Returns the role of the window. See gtk_window_set_role() for
1577  * further explanation.
1578  *
1579  * Return value: the role of the window if set, or %NULL. The
1580  *   returned is owned by the widget and must not be modified
1581  *   or freed.
1582  **/
1583 const gchar *
gtk_window_get_role(GtkWindow * window)1584 gtk_window_get_role (GtkWindow *window)
1585 {
1586   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1587 
1588   return window->wm_role;
1589 }
1590 
1591 /**
1592  * gtk_window_set_focus:
1593  * @window: a #GtkWindow
1594  * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1595  *   any focus widget for the toplevel window.
1596  *
1597  * If @focus is not the current focus widget, and is focusable, sets
1598  * it as the focus widget for the window. If @focus is %NULL, unsets
1599  * the focus widget for this window. To set the focus to a particular
1600  * widget in the toplevel, it is usually more convenient to use
1601  * gtk_widget_grab_focus() instead of this function.
1602  **/
1603 void
gtk_window_set_focus(GtkWindow * window,GtkWidget * focus)1604 gtk_window_set_focus (GtkWindow *window,
1605 		      GtkWidget *focus)
1606 {
1607   g_return_if_fail (GTK_IS_WINDOW (window));
1608   if (focus)
1609     {
1610       g_return_if_fail (GTK_IS_WIDGET (focus));
1611       g_return_if_fail (gtk_widget_get_can_focus (focus));
1612     }
1613 
1614   if (focus)
1615     gtk_widget_grab_focus (focus);
1616   else
1617     {
1618       /* Clear the existing focus chain, so that when we focus into
1619        * the window again, we start at the beginnning.
1620        */
1621       GtkWidget *widget = window->focus_widget;
1622       if (widget)
1623 	{
1624 	  while (widget->parent)
1625 	    {
1626 	      widget = widget->parent;
1627 	      gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1628 	    }
1629 	}
1630 
1631       _gtk_window_internal_set_focus (window, NULL);
1632     }
1633 }
1634 
1635 void
_gtk_window_internal_set_focus(GtkWindow * window,GtkWidget * focus)1636 _gtk_window_internal_set_focus (GtkWindow *window,
1637 				GtkWidget *focus)
1638 {
1639   g_return_if_fail (GTK_IS_WINDOW (window));
1640 
1641   if ((window->focus_widget != focus) ||
1642       (focus && !gtk_widget_has_focus (focus)))
1643     g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1644 }
1645 
1646 /**
1647  * gtk_window_set_default:
1648  * @window: a #GtkWindow
1649  * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1650  *                  default widget for the toplevel.
1651  *
1652  * The default widget is the widget that's activated when the user
1653  * presses Enter in a dialog (for example). This function sets or
1654  * unsets the default widget for a #GtkWindow about. When setting
1655  * (rather than unsetting) the default widget it's generally easier to
1656  * call gtk_widget_grab_focus() on the widget. Before making a widget
1657  * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1658  * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1659  **/
1660 void
gtk_window_set_default(GtkWindow * window,GtkWidget * default_widget)1661 gtk_window_set_default (GtkWindow *window,
1662 			GtkWidget *default_widget)
1663 {
1664   g_return_if_fail (GTK_IS_WINDOW (window));
1665 
1666   if (default_widget)
1667     g_return_if_fail (gtk_widget_get_can_default (default_widget));
1668 
1669   if (window->default_widget != default_widget)
1670     {
1671       GtkWidget *old_default_widget = NULL;
1672 
1673       if (default_widget)
1674 	g_object_ref (default_widget);
1675 
1676       if (window->default_widget)
1677 	{
1678 	  old_default_widget = window->default_widget;
1679 
1680 	  if (window->focus_widget != window->default_widget ||
1681 	      !gtk_widget_get_receives_default (window->default_widget))
1682             _gtk_widget_set_has_default (window->default_widget, FALSE);
1683 	  gtk_widget_queue_draw (window->default_widget);
1684 	}
1685 
1686       window->default_widget = default_widget;
1687 
1688       if (window->default_widget)
1689 	{
1690 	  if (window->focus_widget == NULL ||
1691 	      !gtk_widget_get_receives_default (window->focus_widget))
1692             _gtk_widget_set_has_default (window->default_widget, TRUE);
1693 	  gtk_widget_queue_draw (window->default_widget);
1694 	}
1695 
1696       if (old_default_widget)
1697 	g_object_notify (G_OBJECT (old_default_widget), "has-default");
1698 
1699       if (default_widget)
1700 	{
1701 	  g_object_notify (G_OBJECT (default_widget), "has-default");
1702 	  g_object_unref (default_widget);
1703 	}
1704     }
1705 }
1706 
1707 /**
1708  * gtk_window_get_default_widget:
1709  * @window: a #GtkWindow
1710  *
1711  * Returns the default widget for @window. See gtk_window_set_default()
1712  * for more details.
1713  *
1714  * Returns: (transfer none): the default widget, or %NULL if there is none.
1715  *
1716  * Since: 2.14
1717  **/
1718 GtkWidget *
gtk_window_get_default_widget(GtkWindow * window)1719 gtk_window_get_default_widget (GtkWindow *window)
1720 {
1721   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1722 
1723   return window->default_widget;
1724 }
1725 
1726 static void
gtk_window_set_policy_internal(GtkWindow * window,gboolean allow_shrink,gboolean allow_grow,gboolean auto_shrink)1727 gtk_window_set_policy_internal (GtkWindow *window,
1728                                 gboolean   allow_shrink,
1729                                 gboolean   allow_grow,
1730                                 gboolean   auto_shrink)
1731 {
1732   window->allow_shrink = (allow_shrink != FALSE);
1733   window->allow_grow = (allow_grow != FALSE);
1734 
1735   g_object_freeze_notify (G_OBJECT (window));
1736   g_object_notify (G_OBJECT (window), "allow-shrink");
1737   g_object_notify (G_OBJECT (window), "allow-grow");
1738   g_object_notify (G_OBJECT (window), "resizable");
1739   g_object_thaw_notify (G_OBJECT (window));
1740 
1741   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1742 }
1743 
1744 void
gtk_window_set_policy(GtkWindow * window,gboolean allow_shrink,gboolean allow_grow,gboolean auto_shrink)1745 gtk_window_set_policy (GtkWindow *window,
1746 		       gboolean   allow_shrink,
1747 		       gboolean   allow_grow,
1748 		       gboolean   auto_shrink)
1749 {
1750   g_return_if_fail (GTK_IS_WINDOW (window));
1751 
1752   gtk_window_set_policy_internal (window, allow_shrink, allow_grow, auto_shrink);
1753 }
1754 
1755 static gboolean
handle_keys_changed(gpointer data)1756 handle_keys_changed (gpointer data)
1757 {
1758   GtkWindow *window;
1759 
1760   window = GTK_WINDOW (data);
1761 
1762   if (window->keys_changed_handler)
1763     {
1764       g_source_remove (window->keys_changed_handler);
1765       window->keys_changed_handler = 0;
1766     }
1767 
1768   g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1769 
1770   return FALSE;
1771 }
1772 
1773 static void
gtk_window_notify_keys_changed(GtkWindow * window)1774 gtk_window_notify_keys_changed (GtkWindow *window)
1775 {
1776   if (!window->keys_changed_handler)
1777     window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1778 }
1779 
1780 /**
1781  * gtk_window_add_accel_group:
1782  * @window: window to attach accelerator group to
1783  * @accel_group: a #GtkAccelGroup
1784  *
1785  * Associate @accel_group with @window, such that calling
1786  * gtk_accel_groups_activate() on @window will activate accelerators
1787  * in @accel_group.
1788  **/
1789 void
gtk_window_add_accel_group(GtkWindow * window,GtkAccelGroup * accel_group)1790 gtk_window_add_accel_group (GtkWindow     *window,
1791 			    GtkAccelGroup *accel_group)
1792 {
1793   g_return_if_fail (GTK_IS_WINDOW (window));
1794   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1795 
1796   _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1797   g_signal_connect_object (accel_group, "accel-changed",
1798 			   G_CALLBACK (gtk_window_notify_keys_changed),
1799 			   window, G_CONNECT_SWAPPED);
1800   gtk_window_notify_keys_changed (window);
1801 }
1802 
1803 /**
1804  * gtk_window_remove_accel_group:
1805  * @window: a #GtkWindow
1806  * @accel_group: a #GtkAccelGroup
1807  *
1808  * Reverses the effects of gtk_window_add_accel_group().
1809  **/
1810 void
gtk_window_remove_accel_group(GtkWindow * window,GtkAccelGroup * accel_group)1811 gtk_window_remove_accel_group (GtkWindow     *window,
1812 			       GtkAccelGroup *accel_group)
1813 {
1814   g_return_if_fail (GTK_IS_WINDOW (window));
1815   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1816 
1817   g_signal_handlers_disconnect_by_func (accel_group,
1818 					gtk_window_notify_keys_changed,
1819 					window);
1820   _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1821   gtk_window_notify_keys_changed (window);
1822 }
1823 
1824 static GtkMnemonicHash *
gtk_window_get_mnemonic_hash(GtkWindow * window,gboolean create)1825 gtk_window_get_mnemonic_hash (GtkWindow *window,
1826 			      gboolean   create)
1827 {
1828   GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1829   if (!private->mnemonic_hash && create)
1830     private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1831 
1832   return private->mnemonic_hash;
1833 }
1834 
1835 /**
1836  * gtk_window_add_mnemonic:
1837  * @window: a #GtkWindow
1838  * @keyval: the mnemonic
1839  * @target: the widget that gets activated by the mnemonic
1840  *
1841  * Adds a mnemonic to this window.
1842  */
1843 void
gtk_window_add_mnemonic(GtkWindow * window,guint keyval,GtkWidget * target)1844 gtk_window_add_mnemonic (GtkWindow *window,
1845 			 guint      keyval,
1846 			 GtkWidget *target)
1847 {
1848   g_return_if_fail (GTK_IS_WINDOW (window));
1849   g_return_if_fail (GTK_IS_WIDGET (target));
1850 
1851   _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1852 			  keyval, target);
1853   gtk_window_notify_keys_changed (window);
1854 }
1855 
1856 /**
1857  * gtk_window_remove_mnemonic:
1858  * @window: a #GtkWindow
1859  * @keyval: the mnemonic
1860  * @target: the widget that gets activated by the mnemonic
1861  *
1862  * Removes a mnemonic from this window.
1863  */
1864 void
gtk_window_remove_mnemonic(GtkWindow * window,guint keyval,GtkWidget * target)1865 gtk_window_remove_mnemonic (GtkWindow *window,
1866 			    guint      keyval,
1867 			    GtkWidget *target)
1868 {
1869   g_return_if_fail (GTK_IS_WINDOW (window));
1870   g_return_if_fail (GTK_IS_WIDGET (target));
1871 
1872   _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1873 			     keyval, target);
1874   gtk_window_notify_keys_changed (window);
1875 }
1876 
1877 /**
1878  * gtk_window_mnemonic_activate:
1879  * @window: a #GtkWindow
1880  * @keyval: the mnemonic
1881  * @modifier: the modifiers
1882  * @returns: %TRUE if the activation is done.
1883  *
1884  * Activates the targets associated with the mnemonic.
1885  */
1886 gboolean
gtk_window_mnemonic_activate(GtkWindow * window,guint keyval,GdkModifierType modifier)1887 gtk_window_mnemonic_activate (GtkWindow      *window,
1888 			      guint           keyval,
1889 			      GdkModifierType modifier)
1890 {
1891   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1892 
1893   if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1894       {
1895 	GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1896 	if (mnemonic_hash)
1897 	  return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1898       }
1899 
1900   return FALSE;
1901 }
1902 
1903 /**
1904  * gtk_window_set_mnemonic_modifier:
1905  * @window: a #GtkWindow
1906  * @modifier: the modifier mask used to activate
1907  *               mnemonics on this window.
1908  *
1909  * Sets the mnemonic modifier for this window.
1910  **/
1911 void
gtk_window_set_mnemonic_modifier(GtkWindow * window,GdkModifierType modifier)1912 gtk_window_set_mnemonic_modifier (GtkWindow      *window,
1913 				  GdkModifierType modifier)
1914 {
1915   g_return_if_fail (GTK_IS_WINDOW (window));
1916   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1917 
1918   window->mnemonic_modifier = modifier;
1919   gtk_window_notify_keys_changed (window);
1920 }
1921 
1922 /**
1923  * gtk_window_get_mnemonic_modifier:
1924  * @window: a #GtkWindow
1925  *
1926  * Returns the mnemonic modifier for this window. See
1927  * gtk_window_set_mnemonic_modifier().
1928  *
1929  * Return value: the modifier mask used to activate
1930  *               mnemonics on this window.
1931  **/
1932 GdkModifierType
gtk_window_get_mnemonic_modifier(GtkWindow * window)1933 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1934 {
1935   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1936 
1937   return window->mnemonic_modifier;
1938 }
1939 
1940 /**
1941  * gtk_window_set_position:
1942  * @window: a #GtkWindow.
1943  * @position: a position constraint.
1944  *
1945  * Sets a position constraint for this window. If the old or new
1946  * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1947  * the window to be repositioned to satisfy the new constraint.
1948  **/
1949 void
gtk_window_set_position(GtkWindow * window,GtkWindowPosition position)1950 gtk_window_set_position (GtkWindow         *window,
1951 			 GtkWindowPosition  position)
1952 {
1953   g_return_if_fail (GTK_IS_WINDOW (window));
1954 
1955   if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1956       window->position == GTK_WIN_POS_CENTER_ALWAYS)
1957     {
1958       GtkWindowGeometryInfo *info;
1959 
1960       info = gtk_window_get_geometry_info (window, TRUE);
1961 
1962       /* this flag causes us to re-request the CENTER_ALWAYS
1963        * constraint in gtk_window_move_resize(), see
1964        * comment in that function.
1965        */
1966       info->position_constraints_changed = TRUE;
1967 
1968       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1969     }
1970 
1971   window->position = position;
1972 
1973   g_object_notify (G_OBJECT (window), "window-position");
1974 }
1975 
1976 /**
1977  * gtk_window_activate_focus:
1978  * @window: a #GtkWindow
1979  *
1980  * Activates the current focused widget within the window.
1981  *
1982  * Return value: %TRUE if a widget got activated.
1983  **/
1984 gboolean
gtk_window_activate_focus(GtkWindow * window)1985 gtk_window_activate_focus (GtkWindow *window)
1986 {
1987   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1988 
1989   if (window->focus_widget && gtk_widget_is_sensitive (window->focus_widget))
1990     return gtk_widget_activate (window->focus_widget);
1991 
1992   return FALSE;
1993 }
1994 
1995 /**
1996  * gtk_window_get_focus:
1997  * @window: a #GtkWindow
1998  *
1999  * Retrieves the current focused widget within the window.
2000  * Note that this is the widget that would have the focus
2001  * if the toplevel window focused; if the toplevel window
2002  * is not focused then  <literal>gtk_widget_has_focus (widget)</literal> will
2003  * not be %TRUE for the widget.
2004  *
2005  * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2006  **/
2007 GtkWidget *
gtk_window_get_focus(GtkWindow * window)2008 gtk_window_get_focus (GtkWindow *window)
2009 {
2010   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2011 
2012   return window->focus_widget;
2013 }
2014 
2015 /**
2016  * gtk_window_activate_default:
2017  * @window: a #GtkWindow
2018  *
2019  * Activates the default widget for the window, unless the current
2020  * focused widget has been configured to receive the default action
2021  * (see gtk_widget_set_receives_default()), in which case the
2022  * focused widget is activated.
2023  *
2024  * Return value: %TRUE if a widget got activated.
2025  **/
2026 gboolean
gtk_window_activate_default(GtkWindow * window)2027 gtk_window_activate_default (GtkWindow *window)
2028 {
2029   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2030 
2031   if (window->default_widget && gtk_widget_is_sensitive (window->default_widget) &&
2032       (!window->focus_widget || !gtk_widget_get_receives_default (window->focus_widget)))
2033     return gtk_widget_activate (window->default_widget);
2034   else if (window->focus_widget && gtk_widget_is_sensitive (window->focus_widget))
2035     return gtk_widget_activate (window->focus_widget);
2036 
2037   return FALSE;
2038 }
2039 
2040 /**
2041  * gtk_window_set_modal:
2042  * @window: a #GtkWindow
2043  * @modal: whether the window is modal
2044  *
2045  * Sets a window modal or non-modal. Modal windows prevent interaction
2046  * with other windows in the same application. To keep modal dialogs
2047  * on top of main application windows, use
2048  * gtk_window_set_transient_for() to make the dialog transient for the
2049  * parent; most <link linkend="gtk-X11-arch">window managers</link>
2050  * will then disallow lowering the dialog below the parent.
2051  *
2052  *
2053  **/
2054 void
gtk_window_set_modal(GtkWindow * window,gboolean modal)2055 gtk_window_set_modal (GtkWindow *window,
2056 		      gboolean   modal)
2057 {
2058   GtkWidget *widget;
2059 
2060   g_return_if_fail (GTK_IS_WINDOW (window));
2061 
2062   modal = modal != FALSE;
2063   if (window->modal == modal)
2064     return;
2065 
2066   window->modal = modal;
2067   widget = GTK_WIDGET (window);
2068 
2069   /* adjust desired modality state */
2070   if (gtk_widget_get_realized (widget))
2071     {
2072       if (window->modal)
2073 	gdk_window_set_modal_hint (widget->window, TRUE);
2074       else
2075 	gdk_window_set_modal_hint (widget->window, FALSE);
2076     }
2077 
2078   if (gtk_widget_get_visible (widget))
2079     {
2080       if (window->modal)
2081 	gtk_grab_add (widget);
2082       else
2083 	gtk_grab_remove (widget);
2084     }
2085 
2086   g_object_notify (G_OBJECT (window), "modal");
2087 }
2088 
2089 /**
2090  * gtk_window_get_modal:
2091  * @window: a #GtkWindow
2092  *
2093  * Returns whether the window is modal. See gtk_window_set_modal().
2094  *
2095  * Return value: %TRUE if the window is set to be modal and
2096  *               establishes a grab when shown
2097  **/
2098 gboolean
gtk_window_get_modal(GtkWindow * window)2099 gtk_window_get_modal (GtkWindow *window)
2100 {
2101   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2102 
2103   return window->modal;
2104 }
2105 
2106 /**
2107  * gtk_window_list_toplevels:
2108  *
2109  * Returns a list of all existing toplevel windows. The widgets
2110  * in the list are not individually referenced. If you want
2111  * to iterate through the list and perform actions involving
2112  * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2113  * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2114  * then unref all the widgets afterwards.
2115  *
2116  * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2117  **/
2118 GList*
gtk_window_list_toplevels(void)2119 gtk_window_list_toplevels (void)
2120 {
2121   GList *list = NULL;
2122   GSList *slist;
2123 
2124   for (slist = toplevel_list; slist; slist = slist->next)
2125     list = g_list_prepend (list, slist->data);
2126 
2127   return list;
2128 }
2129 
2130 void
gtk_window_add_embedded_xid(GtkWindow * window,GdkNativeWindow xid)2131 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2132 {
2133   GList *embedded_windows;
2134 
2135   g_return_if_fail (GTK_IS_WINDOW (window));
2136 
2137   embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2138   if (embedded_windows)
2139     g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2140   embedded_windows = g_list_prepend (embedded_windows,
2141 				     GUINT_TO_POINTER (xid));
2142 
2143   g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2144 			   embedded_windows,
2145 			   embedded_windows ?
2146 			   (GDestroyNotify) g_list_free : NULL);
2147 }
2148 
2149 void
gtk_window_remove_embedded_xid(GtkWindow * window,GdkNativeWindow xid)2150 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2151 {
2152   GList *embedded_windows;
2153   GList *node;
2154 
2155   g_return_if_fail (GTK_IS_WINDOW (window));
2156 
2157   embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2158   if (embedded_windows)
2159     g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2160 
2161   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2162   if (node)
2163     {
2164       embedded_windows = g_list_remove_link (embedded_windows, node);
2165       g_list_free_1 (node);
2166     }
2167 
2168   g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2169 			   embedded_windows,
2170 			   embedded_windows ?
2171 			   (GDestroyNotify) g_list_free : NULL);
2172 }
2173 
2174 void
_gtk_window_reposition(GtkWindow * window,gint x,gint y)2175 _gtk_window_reposition (GtkWindow *window,
2176 			gint       x,
2177 			gint       y)
2178 {
2179   g_return_if_fail (GTK_IS_WINDOW (window));
2180 
2181   gtk_window_move (window, x, y);
2182 }
2183 
2184 static void
gtk_window_dispose(GObject * object)2185 gtk_window_dispose (GObject *object)
2186 {
2187   GtkWindow *window = GTK_WINDOW (object);
2188 
2189   gtk_window_set_focus (window, NULL);
2190   gtk_window_set_default (window, NULL);
2191 
2192   G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2193 }
2194 
2195 static void
parent_destroyed_callback(GtkWindow * parent,GtkWindow * child)2196 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2197 {
2198   gtk_widget_destroy (GTK_WIDGET (child));
2199 }
2200 
2201 static void
connect_parent_destroyed(GtkWindow * window)2202 connect_parent_destroyed (GtkWindow *window)
2203 {
2204   if (window->transient_parent)
2205     {
2206       g_signal_connect (window->transient_parent,
2207                         "destroy",
2208                         G_CALLBACK (parent_destroyed_callback),
2209                         window);
2210     }
2211 }
2212 
2213 static void
disconnect_parent_destroyed(GtkWindow * window)2214 disconnect_parent_destroyed (GtkWindow *window)
2215 {
2216   if (window->transient_parent)
2217     {
2218       g_signal_handlers_disconnect_by_func (window->transient_parent,
2219 					    parent_destroyed_callback,
2220 					    window);
2221     }
2222 }
2223 
2224 static void
gtk_window_transient_parent_realized(GtkWidget * parent,GtkWidget * window)2225 gtk_window_transient_parent_realized (GtkWidget *parent,
2226 				      GtkWidget *window)
2227 {
2228   if (gtk_widget_get_realized (GTK_WIDGET (window)))
2229     gdk_window_set_transient_for (window->window, parent->window);
2230 }
2231 
2232 static void
gtk_window_transient_parent_unrealized(GtkWidget * parent,GtkWidget * window)2233 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2234 					GtkWidget *window)
2235 {
2236   if (gtk_widget_get_realized (GTK_WIDGET (window)))
2237     gdk_property_delete (window->window,
2238 			 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2239 }
2240 
2241 static void
gtk_window_transient_parent_screen_changed(GtkWindow * parent,GParamSpec * pspec,GtkWindow * window)2242 gtk_window_transient_parent_screen_changed (GtkWindow	*parent,
2243 					    GParamSpec	*pspec,
2244 					    GtkWindow   *window)
2245 {
2246   gtk_window_set_screen (window, parent->screen);
2247 }
2248 
2249 static void
gtk_window_unset_transient_for(GtkWindow * window)2250 gtk_window_unset_transient_for  (GtkWindow *window)
2251 {
2252   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2253 
2254   if (window->transient_parent)
2255     {
2256       g_signal_handlers_disconnect_by_func (window->transient_parent,
2257 					    gtk_window_transient_parent_realized,
2258 					    window);
2259       g_signal_handlers_disconnect_by_func (window->transient_parent,
2260 					    gtk_window_transient_parent_unrealized,
2261 					    window);
2262       g_signal_handlers_disconnect_by_func (window->transient_parent,
2263 					    gtk_window_transient_parent_screen_changed,
2264 					    window);
2265       g_signal_handlers_disconnect_by_func (window->transient_parent,
2266 					    gtk_widget_destroyed,
2267 					    &window->transient_parent);
2268 
2269       if (window->destroy_with_parent)
2270         disconnect_parent_destroyed (window);
2271 
2272       window->transient_parent = NULL;
2273 
2274       if (priv->transient_parent_group)
2275 	{
2276 	  priv->transient_parent_group = FALSE;
2277 	  gtk_window_group_remove_window (window->group,
2278 					  window);
2279 	}
2280     }
2281 }
2282 
2283 /**
2284  * gtk_window_set_transient_for:
2285  * @window: a #GtkWindow
2286  * @parent: (allow-none): parent window, or %NULL
2287  *
2288  * Dialog windows should be set transient for the main application
2289  * window they were spawned from. This allows <link
2290  * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2291  * dialog on top of the main window, or center the dialog over the
2292  * main window. gtk_dialog_new_with_buttons() and other convenience
2293  * functions in GTK+ will sometimes call
2294  * gtk_window_set_transient_for() on your behalf.
2295  *
2296  * Passing %NULL for @parent unsets the current transient window.
2297  *
2298  * On Windows, this function puts the child window on top of the parent,
2299  * much as the window manager would have done on X.
2300  */
2301 void
gtk_window_set_transient_for(GtkWindow * window,GtkWindow * parent)2302 gtk_window_set_transient_for  (GtkWindow *window,
2303 			       GtkWindow *parent)
2304 {
2305   GtkWindowPrivate *priv;
2306 
2307   g_return_if_fail (GTK_IS_WINDOW (window));
2308   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2309   g_return_if_fail (window != parent);
2310 
2311   priv = GTK_WINDOW_GET_PRIVATE (window);
2312 
2313   if (window->transient_parent)
2314     {
2315       if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2316           gtk_widget_get_realized (GTK_WIDGET (window->transient_parent)) &&
2317           (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2318 	gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2319 						GTK_WIDGET (window));
2320 
2321       gtk_window_unset_transient_for (window);
2322     }
2323 
2324   window->transient_parent = parent;
2325 
2326   if (parent)
2327     {
2328       g_signal_connect (parent, "destroy",
2329 			G_CALLBACK (gtk_widget_destroyed),
2330 			&window->transient_parent);
2331       g_signal_connect (parent, "realize",
2332 			G_CALLBACK (gtk_window_transient_parent_realized),
2333 			window);
2334       g_signal_connect (parent, "unrealize",
2335 			G_CALLBACK (gtk_window_transient_parent_unrealized),
2336 			window);
2337       g_signal_connect (parent, "notify::screen",
2338 			G_CALLBACK (gtk_window_transient_parent_screen_changed),
2339 			window);
2340 
2341       gtk_window_set_screen (window, parent->screen);
2342 
2343       if (window->destroy_with_parent)
2344         connect_parent_destroyed (window);
2345 
2346       if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2347 	  gtk_widget_get_realized (GTK_WIDGET (parent)))
2348 	gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2349 					      GTK_WIDGET (window));
2350 
2351       if (parent->group)
2352 	{
2353 	  gtk_window_group_add_window (parent->group, window);
2354 	  priv->transient_parent_group = TRUE;
2355 	}
2356     }
2357 }
2358 
2359 /**
2360  * gtk_window_get_transient_for:
2361  * @window: a #GtkWindow
2362  *
2363  * Fetches the transient parent for this window. See
2364  * gtk_window_set_transient_for().
2365  *
2366  * Return value: (transfer none): the transient parent for this window, or %NULL
2367  *    if no transient parent has been set.
2368  **/
2369 GtkWindow *
gtk_window_get_transient_for(GtkWindow * window)2370 gtk_window_get_transient_for (GtkWindow *window)
2371 {
2372   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2373 
2374   return window->transient_parent;
2375 }
2376 
2377 /**
2378  * gtk_window_set_opacity:
2379  * @window: a #GtkWindow
2380  * @opacity: desired opacity, between 0 and 1
2381  *
2382  * Request the windowing system to make @window partially transparent,
2383  * with opacity 0 being fully transparent and 1 fully opaque. (Values
2384  * of the opacity parameter are clamped to the [0,1] range.) On X11
2385  * this has any effect only on X screens with a compositing manager
2386  * running. See gtk_widget_is_composited(). On Windows it should work
2387  * always.
2388  *
2389  * Note that setting a window's opacity after the window has been
2390  * shown causes it to flicker once on Windows.
2391  *
2392  * Since: 2.12
2393  **/
2394 void
gtk_window_set_opacity(GtkWindow * window,gdouble opacity)2395 gtk_window_set_opacity  (GtkWindow *window,
2396 			 gdouble    opacity)
2397 {
2398   GtkWindowPrivate *priv;
2399 
2400   g_return_if_fail (GTK_IS_WINDOW (window));
2401 
2402   priv = GTK_WINDOW_GET_PRIVATE (window);
2403 
2404   if (opacity < 0.0)
2405     opacity = 0.0;
2406   else if (opacity > 1.0)
2407     opacity = 1.0;
2408 
2409   priv->opacity_set = TRUE;
2410   priv->opacity = opacity;
2411 
2412   if (gtk_widget_get_realized (GTK_WIDGET (window)))
2413     gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2414 }
2415 
2416 /**
2417  * gtk_window_get_opacity:
2418  * @window: a #GtkWindow
2419  *
2420  * Fetches the requested opacity for this window. See
2421  * gtk_window_set_opacity().
2422  *
2423  * Return value: the requested opacity for this window.
2424  *
2425  * Since: 2.12
2426  **/
2427 gdouble
gtk_window_get_opacity(GtkWindow * window)2428 gtk_window_get_opacity (GtkWindow *window)
2429 {
2430   GtkWindowPrivate *priv;
2431 
2432   g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2433 
2434   priv = GTK_WINDOW_GET_PRIVATE (window);
2435 
2436   return priv->opacity;
2437 }
2438 
2439 /**
2440  * gtk_window_set_type_hint:
2441  * @window: a #GtkWindow
2442  * @hint: the window type
2443  *
2444  * By setting the type hint for the window, you allow the window
2445  * manager to decorate and handle the window in a way which is
2446  * suitable to the function of the window in your application.
2447  *
2448  * This function should be called before the window becomes visible.
2449  *
2450  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2451  * will sometimes call gtk_window_set_type_hint() on your behalf.
2452  *
2453  **/
2454 void
gtk_window_set_type_hint(GtkWindow * window,GdkWindowTypeHint hint)2455 gtk_window_set_type_hint (GtkWindow           *window,
2456 			  GdkWindowTypeHint    hint)
2457 {
2458   GtkWindowPrivate *priv;
2459 
2460   g_return_if_fail (GTK_IS_WINDOW (window));
2461   g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2462 
2463   priv = GTK_WINDOW_GET_PRIVATE (window);
2464 
2465   if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2466     window->type_hint = hint;
2467   else
2468     window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2469 
2470   priv->reset_type_hint = TRUE;
2471   priv->type_hint = hint;
2472 }
2473 
2474 /**
2475  * gtk_window_get_type_hint:
2476  * @window: a #GtkWindow
2477  *
2478  * Gets the type hint for this window. See gtk_window_set_type_hint().
2479  *
2480  * Return value: the type hint for @window.
2481  **/
2482 GdkWindowTypeHint
gtk_window_get_type_hint(GtkWindow * window)2483 gtk_window_get_type_hint (GtkWindow *window)
2484 {
2485   GtkWindowPrivate *priv;
2486 
2487   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2488 
2489   priv = GTK_WINDOW_GET_PRIVATE (window);
2490 
2491   return priv->type_hint;
2492 }
2493 
2494 /**
2495  * gtk_window_set_skip_taskbar_hint:
2496  * @window: a #GtkWindow
2497  * @setting: %TRUE to keep this window from appearing in the task bar
2498  *
2499  * Windows may set a hint asking the desktop environment not to display
2500  * the window in the task bar. This function sets this hint.
2501  *
2502  * Since: 2.2
2503  **/
2504 void
gtk_window_set_skip_taskbar_hint(GtkWindow * window,gboolean setting)2505 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2506                                   gboolean   setting)
2507 {
2508   GtkWindowPrivate *priv;
2509 
2510   g_return_if_fail (GTK_IS_WINDOW (window));
2511 
2512   priv = GTK_WINDOW_GET_PRIVATE (window);
2513 
2514   setting = setting != FALSE;
2515 
2516   if (priv->skips_taskbar != setting)
2517     {
2518       priv->skips_taskbar = setting;
2519       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2520         gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2521                                           priv->skips_taskbar);
2522       g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2523     }
2524 }
2525 
2526 /**
2527  * gtk_window_get_skip_taskbar_hint:
2528  * @window: a #GtkWindow
2529  *
2530  * Gets the value set by gtk_window_set_skip_taskbar_hint()
2531  *
2532  * Return value: %TRUE if window shouldn't be in taskbar
2533  *
2534  * Since: 2.2
2535  **/
2536 gboolean
gtk_window_get_skip_taskbar_hint(GtkWindow * window)2537 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2538 {
2539   GtkWindowPrivate *priv;
2540 
2541   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2542 
2543   priv = GTK_WINDOW_GET_PRIVATE (window);
2544 
2545   return priv->skips_taskbar;
2546 }
2547 
2548 /**
2549  * gtk_window_set_skip_pager_hint:
2550  * @window: a #GtkWindow
2551  * @setting: %TRUE to keep this window from appearing in the pager
2552  *
2553  * Windows may set a hint asking the desktop environment not to display
2554  * the window in the pager. This function sets this hint.
2555  * (A "pager" is any desktop navigation tool such as a workspace
2556  * switcher that displays a thumbnail representation of the windows
2557  * on the screen.)
2558  *
2559  * Since: 2.2
2560  **/
2561 void
gtk_window_set_skip_pager_hint(GtkWindow * window,gboolean setting)2562 gtk_window_set_skip_pager_hint (GtkWindow *window,
2563                                 gboolean   setting)
2564 {
2565   GtkWindowPrivate *priv;
2566 
2567   g_return_if_fail (GTK_IS_WINDOW (window));
2568 
2569   priv = GTK_WINDOW_GET_PRIVATE (window);
2570 
2571   setting = setting != FALSE;
2572 
2573   if (priv->skips_pager != setting)
2574     {
2575       priv->skips_pager = setting;
2576       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2577         gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2578                                         priv->skips_pager);
2579       g_object_notify (G_OBJECT (window), "skip-pager-hint");
2580     }
2581 }
2582 
2583 /**
2584  * gtk_window_get_skip_pager_hint:
2585  * @window: a #GtkWindow
2586  *
2587  * Gets the value set by gtk_window_set_skip_pager_hint().
2588  *
2589  * Return value: %TRUE if window shouldn't be in pager
2590  *
2591  * Since: 2.2
2592  **/
2593 gboolean
gtk_window_get_skip_pager_hint(GtkWindow * window)2594 gtk_window_get_skip_pager_hint (GtkWindow *window)
2595 {
2596   GtkWindowPrivate *priv;
2597 
2598   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2599 
2600   priv = GTK_WINDOW_GET_PRIVATE (window);
2601 
2602   return priv->skips_pager;
2603 }
2604 
2605 /**
2606  * gtk_window_set_urgency_hint:
2607  * @window: a #GtkWindow
2608  * @setting: %TRUE to mark this window as urgent
2609  *
2610  * Windows may set a hint asking the desktop environment to draw
2611  * the users attention to the window. This function sets this hint.
2612  *
2613  * Since: 2.8
2614  **/
2615 void
gtk_window_set_urgency_hint(GtkWindow * window,gboolean setting)2616 gtk_window_set_urgency_hint (GtkWindow *window,
2617 			     gboolean   setting)
2618 {
2619   GtkWindowPrivate *priv;
2620 
2621   g_return_if_fail (GTK_IS_WINDOW (window));
2622 
2623   priv = GTK_WINDOW_GET_PRIVATE (window);
2624 
2625   setting = setting != FALSE;
2626 
2627   if (priv->urgent != setting)
2628     {
2629       priv->urgent = setting;
2630       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2631         gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2632 				     priv->urgent);
2633       g_object_notify (G_OBJECT (window), "urgency-hint");
2634     }
2635 }
2636 
2637 /**
2638  * gtk_window_get_urgency_hint:
2639  * @window: a #GtkWindow
2640  *
2641  * Gets the value set by gtk_window_set_urgency_hint()
2642  *
2643  * Return value: %TRUE if window is urgent
2644  *
2645  * Since: 2.8
2646  **/
2647 gboolean
gtk_window_get_urgency_hint(GtkWindow * window)2648 gtk_window_get_urgency_hint (GtkWindow *window)
2649 {
2650   GtkWindowPrivate *priv;
2651 
2652   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2653 
2654   priv = GTK_WINDOW_GET_PRIVATE (window);
2655 
2656   return priv->urgent;
2657 }
2658 
2659 /**
2660  * gtk_window_set_accept_focus:
2661  * @window: a #GtkWindow
2662  * @setting: %TRUE to let this window receive input focus
2663  *
2664  * Windows may set a hint asking the desktop environment not to receive
2665  * the input focus. This function sets this hint.
2666  *
2667  * Since: 2.4
2668  **/
2669 void
gtk_window_set_accept_focus(GtkWindow * window,gboolean setting)2670 gtk_window_set_accept_focus (GtkWindow *window,
2671 			     gboolean   setting)
2672 {
2673   GtkWindowPrivate *priv;
2674 
2675   g_return_if_fail (GTK_IS_WINDOW (window));
2676 
2677   priv = GTK_WINDOW_GET_PRIVATE (window);
2678 
2679   setting = setting != FALSE;
2680 
2681   if (priv->accept_focus != setting)
2682     {
2683       priv->accept_focus = setting;
2684       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2685         gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2686 				     priv->accept_focus);
2687       g_object_notify (G_OBJECT (window), "accept-focus");
2688     }
2689 }
2690 
2691 /**
2692  * gtk_window_get_accept_focus:
2693  * @window: a #GtkWindow
2694  *
2695  * Gets the value set by gtk_window_set_accept_focus().
2696  *
2697  * Return value: %TRUE if window should receive the input focus
2698  *
2699  * Since: 2.4
2700  **/
2701 gboolean
gtk_window_get_accept_focus(GtkWindow * window)2702 gtk_window_get_accept_focus (GtkWindow *window)
2703 {
2704   GtkWindowPrivate *priv;
2705 
2706   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2707 
2708   priv = GTK_WINDOW_GET_PRIVATE (window);
2709 
2710   return priv->accept_focus;
2711 }
2712 
2713 /**
2714  * gtk_window_set_focus_on_map:
2715  * @window: a #GtkWindow
2716  * @setting: %TRUE to let this window receive input focus on map
2717  *
2718  * Windows may set a hint asking the desktop environment not to receive
2719  * the input focus when the window is mapped.  This function sets this
2720  * hint.
2721  *
2722  * Since: 2.6
2723  **/
2724 void
gtk_window_set_focus_on_map(GtkWindow * window,gboolean setting)2725 gtk_window_set_focus_on_map (GtkWindow *window,
2726 			     gboolean   setting)
2727 {
2728   GtkWindowPrivate *priv;
2729 
2730   g_return_if_fail (GTK_IS_WINDOW (window));
2731 
2732   priv = GTK_WINDOW_GET_PRIVATE (window);
2733 
2734   setting = setting != FALSE;
2735 
2736   if (priv->focus_on_map != setting)
2737     {
2738       priv->focus_on_map = setting;
2739       if (gtk_widget_get_realized (GTK_WIDGET (window)))
2740         gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2741 				     priv->focus_on_map);
2742       g_object_notify (G_OBJECT (window), "focus-on-map");
2743     }
2744 }
2745 
2746 /**
2747  * gtk_window_get_focus_on_map:
2748  * @window: a #GtkWindow
2749  *
2750  * Gets the value set by gtk_window_set_focus_on_map().
2751  *
2752  * Return value: %TRUE if window should receive the input focus when
2753  * mapped.
2754  *
2755  * Since: 2.6
2756  **/
2757 gboolean
gtk_window_get_focus_on_map(GtkWindow * window)2758 gtk_window_get_focus_on_map (GtkWindow *window)
2759 {
2760   GtkWindowPrivate *priv;
2761 
2762   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2763 
2764   priv = GTK_WINDOW_GET_PRIVATE (window);
2765 
2766   return priv->focus_on_map;
2767 }
2768 
2769 /**
2770  * gtk_window_set_destroy_with_parent:
2771  * @window: a #GtkWindow
2772  * @setting: whether to destroy @window with its transient parent
2773  *
2774  * If @setting is %TRUE, then destroying the transient parent of @window
2775  * will also destroy @window itself. This is useful for dialogs that
2776  * shouldn't persist beyond the lifetime of the main window they're
2777  * associated with, for example.
2778  **/
2779 void
gtk_window_set_destroy_with_parent(GtkWindow * window,gboolean setting)2780 gtk_window_set_destroy_with_parent  (GtkWindow *window,
2781                                      gboolean   setting)
2782 {
2783   g_return_if_fail (GTK_IS_WINDOW (window));
2784 
2785   if (window->destroy_with_parent == (setting != FALSE))
2786     return;
2787 
2788   if (window->destroy_with_parent)
2789     {
2790       disconnect_parent_destroyed (window);
2791     }
2792   else
2793     {
2794       connect_parent_destroyed (window);
2795     }
2796 
2797   window->destroy_with_parent = setting;
2798 
2799   g_object_notify (G_OBJECT (window), "destroy-with-parent");
2800 }
2801 
2802 /**
2803  * gtk_window_get_destroy_with_parent:
2804  * @window: a #GtkWindow
2805  *
2806  * Returns whether the window will be destroyed with its transient parent. See
2807  * gtk_window_set_destroy_with_parent ().
2808  *
2809  * Return value: %TRUE if the window will be destroyed with its transient parent.
2810  **/
2811 gboolean
gtk_window_get_destroy_with_parent(GtkWindow * window)2812 gtk_window_get_destroy_with_parent (GtkWindow *window)
2813 {
2814   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2815 
2816   return window->destroy_with_parent;
2817 }
2818 
2819 static GtkWindowGeometryInfo*
gtk_window_get_geometry_info(GtkWindow * window,gboolean create)2820 gtk_window_get_geometry_info (GtkWindow *window,
2821 			      gboolean   create)
2822 {
2823   GtkWindowGeometryInfo *info;
2824 
2825   info = window->geometry_info;
2826   if (!info && create)
2827     {
2828       info = g_new0 (GtkWindowGeometryInfo, 1);
2829 
2830       info->default_width = -1;
2831       info->default_height = -1;
2832       info->resize_width = -1;
2833       info->resize_height = -1;
2834       info->initial_x = 0;
2835       info->initial_y = 0;
2836       info->initial_pos_set = FALSE;
2837       info->default_is_geometry = FALSE;
2838       info->position_constraints_changed = FALSE;
2839       info->last.configure_request.x = 0;
2840       info->last.configure_request.y = 0;
2841       info->last.configure_request.width = -1;
2842       info->last.configure_request.height = -1;
2843       info->widget = NULL;
2844       info->mask = 0;
2845       window->geometry_info = info;
2846     }
2847 
2848   return info;
2849 }
2850 
2851 /**
2852  * gtk_window_set_geometry_hints:
2853  * @window: a #GtkWindow
2854  * @geometry_widget: widget the geometry hints will be applied to
2855  * @geometry: struct containing geometry information
2856  * @geom_mask: mask indicating which struct fields should be paid attention to
2857  *
2858  * This function sets up hints about how a window can be resized by
2859  * the user.  You can set a minimum and maximum size; allowed resize
2860  * increments (e.g. for xterm, you can only resize by the size of a
2861  * character); aspect ratios; and more. See the #GdkGeometry struct.
2862  *
2863  **/
2864 void
gtk_window_set_geometry_hints(GtkWindow * window,GtkWidget * geometry_widget,GdkGeometry * geometry,GdkWindowHints geom_mask)2865 gtk_window_set_geometry_hints (GtkWindow       *window,
2866 			       GtkWidget       *geometry_widget,
2867 			       GdkGeometry     *geometry,
2868 			       GdkWindowHints   geom_mask)
2869 {
2870   GtkWindowGeometryInfo *info;
2871 
2872   g_return_if_fail (GTK_IS_WINDOW (window));
2873   g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2874 
2875   info = gtk_window_get_geometry_info (window, TRUE);
2876 
2877   if (info->widget)
2878     g_signal_handlers_disconnect_by_func (info->widget,
2879 					  gtk_widget_destroyed,
2880 					  &info->widget);
2881 
2882   info->widget = geometry_widget;
2883   if (info->widget)
2884     g_signal_connect (geometry_widget, "destroy",
2885 		      G_CALLBACK (gtk_widget_destroyed),
2886 		      &info->widget);
2887 
2888   if (geometry)
2889     info->geometry = *geometry;
2890 
2891   /* We store gravity in window->gravity not in the hints. */
2892   info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2893 
2894   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2895     {
2896       gtk_window_set_gravity (window, geometry->win_gravity);
2897     }
2898 
2899   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2900 }
2901 
2902 /**
2903  * gtk_window_set_decorated:
2904  * @window: a #GtkWindow
2905  * @setting: %TRUE to decorate the window
2906  *
2907  * By default, windows are decorated with a title bar, resize
2908  * controls, etc.  Some <link linkend="gtk-X11-arch">window
2909  * managers</link> allow GTK+ to disable these decorations, creating a
2910  * borderless window. If you set the decorated property to %FALSE
2911  * using this function, GTK+ will do its best to convince the window
2912  * manager not to decorate the window. Depending on the system, this
2913  * function may not have any effect when called on a window that is
2914  * already visible, so you should call it before calling gtk_window_show().
2915  *
2916  * On Windows, this function always works, since there's no window manager
2917  * policy involved.
2918  *
2919  **/
2920 void
gtk_window_set_decorated(GtkWindow * window,gboolean setting)2921 gtk_window_set_decorated (GtkWindow *window,
2922                           gboolean   setting)
2923 {
2924   g_return_if_fail (GTK_IS_WINDOW (window));
2925 
2926   setting = setting != FALSE;
2927 
2928   if (setting == window->decorated)
2929     return;
2930 
2931   window->decorated = setting;
2932 
2933   if (GTK_WIDGET (window)->window)
2934     {
2935       if (window->decorated)
2936         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2937                                     GDK_DECOR_ALL);
2938       else
2939         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2940                                     0);
2941     }
2942 
2943   g_object_notify (G_OBJECT (window), "decorated");
2944 }
2945 
2946 /**
2947  * gtk_window_get_decorated:
2948  * @window: a #GtkWindow
2949  *
2950  * Returns whether the window has been set to have decorations
2951  * such as a title bar via gtk_window_set_decorated().
2952  *
2953  * Return value: %TRUE if the window has been set to have decorations
2954  **/
2955 gboolean
gtk_window_get_decorated(GtkWindow * window)2956 gtk_window_get_decorated (GtkWindow *window)
2957 {
2958   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2959 
2960   return window->decorated;
2961 }
2962 
2963 /**
2964  * gtk_window_set_deletable:
2965  * @window: a #GtkWindow
2966  * @setting: %TRUE to decorate the window as deletable
2967  *
2968  * By default, windows have a close button in the window frame. Some
2969  * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2970  * disable this button. If you set the deletable property to %FALSE
2971  * using this function, GTK+ will do its best to convince the window
2972  * manager not to show a close button. Depending on the system, this
2973  * function may not have any effect when called on a window that is
2974  * already visible, so you should call it before calling gtk_window_show().
2975  *
2976  * On Windows, this function always works, since there's no window manager
2977  * policy involved.
2978  *
2979  * Since: 2.10
2980  */
2981 void
gtk_window_set_deletable(GtkWindow * window,gboolean setting)2982 gtk_window_set_deletable (GtkWindow *window,
2983 			  gboolean   setting)
2984 {
2985   GtkWindowPrivate *priv;
2986 
2987   g_return_if_fail (GTK_IS_WINDOW (window));
2988 
2989   priv = GTK_WINDOW_GET_PRIVATE (window);
2990 
2991   setting = setting != FALSE;
2992 
2993   if (setting == priv->deletable)
2994     return;
2995 
2996   priv->deletable = setting;
2997 
2998   if (GTK_WIDGET (window)->window)
2999     {
3000       if (priv->deletable)
3001         gdk_window_set_functions (GTK_WIDGET (window)->window,
3002 				  GDK_FUNC_ALL);
3003       else
3004         gdk_window_set_functions (GTK_WIDGET (window)->window,
3005 				  GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3006     }
3007 
3008   g_object_notify (G_OBJECT (window), "deletable");
3009 }
3010 
3011 /**
3012  * gtk_window_get_deletable:
3013  * @window: a #GtkWindow
3014  *
3015  * Returns whether the window has been set to have a close button
3016  * via gtk_window_set_deletable().
3017  *
3018  * Return value: %TRUE if the window has been set to have a close button
3019  *
3020  * Since: 2.10
3021  **/
3022 gboolean
gtk_window_get_deletable(GtkWindow * window)3023 gtk_window_get_deletable (GtkWindow *window)
3024 {
3025   GtkWindowPrivate *priv;
3026 
3027   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3028 
3029   priv = GTK_WINDOW_GET_PRIVATE (window);
3030 
3031   return priv->deletable;
3032 }
3033 
3034 static GtkWindowIconInfo*
get_icon_info(GtkWindow * window)3035 get_icon_info (GtkWindow *window)
3036 {
3037   return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3038 }
3039 
3040 static void
free_icon_info(GtkWindowIconInfo * info)3041 free_icon_info (GtkWindowIconInfo *info)
3042 {
3043   g_free (info->icon_name);
3044   g_slice_free (GtkWindowIconInfo, info);
3045 }
3046 
3047 
3048 static GtkWindowIconInfo*
ensure_icon_info(GtkWindow * window)3049 ensure_icon_info (GtkWindow *window)
3050 {
3051   GtkWindowIconInfo *info;
3052 
3053   info = get_icon_info (window);
3054 
3055   if (info == NULL)
3056     {
3057       info = g_slice_new0 (GtkWindowIconInfo);
3058       g_object_set_qdata_full (G_OBJECT (window),
3059                               quark_gtk_window_icon_info,
3060                               info,
3061                               (GDestroyNotify)free_icon_info);
3062     }
3063 
3064   return info;
3065 }
3066 
3067 typedef struct {
3068   guint serial;
3069   GdkPixmap *pixmap;
3070   GdkPixmap *mask;
3071 } ScreenIconInfo;
3072 
3073 static ScreenIconInfo *
get_screen_icon_info(GdkScreen * screen)3074 get_screen_icon_info (GdkScreen *screen)
3075 {
3076   ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
3077 					     quark_gtk_window_default_icon_pixmap);
3078   if (!info)
3079     {
3080       info = g_slice_new0 (ScreenIconInfo);
3081       g_object_set_qdata (G_OBJECT (screen),
3082 			  quark_gtk_window_default_icon_pixmap, info);
3083     }
3084 
3085   if (info->serial != default_icon_serial)
3086     {
3087       if (info->pixmap)
3088 	{
3089 	  g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3090 	  info->pixmap = NULL;
3091 	}
3092 
3093       if (info->mask)
3094 	{
3095 	  g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3096 	  info->mask = NULL;
3097 	}
3098 
3099       info->serial = default_icon_serial;
3100     }
3101 
3102   return info;
3103 }
3104 
3105 static void
get_pixmap_and_mask(GdkWindow * window,GtkWindowIconInfo * parent_info,gboolean is_default_list,GList * icon_list,GdkPixmap ** pmap_return,GdkBitmap ** mask_return)3106 get_pixmap_and_mask (GdkWindow		*window,
3107 		     GtkWindowIconInfo  *parent_info,
3108                      gboolean            is_default_list,
3109                      GList              *icon_list,
3110                      GdkPixmap         **pmap_return,
3111                      GdkBitmap         **mask_return)
3112 {
3113   GdkScreen *screen = gdk_window_get_screen (window);
3114   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3115   GdkPixbuf *best_icon;
3116   GList *tmp_list;
3117   int best_size;
3118 
3119   *pmap_return = NULL;
3120   *mask_return = NULL;
3121 
3122   if (is_default_list &&
3123       default_icon_info->pixmap != NULL)
3124     {
3125       /* Use shared icon pixmap for all windows on this screen.
3126        */
3127       if (default_icon_info->pixmap)
3128         g_object_ref (default_icon_info->pixmap);
3129       if (default_icon_info->mask)
3130         g_object_ref (default_icon_info->mask);
3131 
3132       *pmap_return = default_icon_info->pixmap;
3133       *mask_return = default_icon_info->mask;
3134     }
3135   else if (parent_info && parent_info->icon_pixmap)
3136     {
3137       if (parent_info->icon_pixmap)
3138         g_object_ref (parent_info->icon_pixmap);
3139       if (parent_info->icon_mask)
3140         g_object_ref (parent_info->icon_mask);
3141 
3142       *pmap_return = parent_info->icon_pixmap;
3143       *mask_return = parent_info->icon_mask;
3144     }
3145   else
3146     {
3147 #define IDEAL_SIZE 48
3148 
3149       best_size = G_MAXINT;
3150       best_icon = NULL;
3151       tmp_list = icon_list;
3152       while (tmp_list != NULL)
3153         {
3154           GdkPixbuf *pixbuf = tmp_list->data;
3155           int this;
3156 
3157           /* average width and height - if someone passes in a rectangular
3158            * icon they deserve what they get.
3159            */
3160           this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3161           this /= 2;
3162 
3163           if (best_icon == NULL)
3164             {
3165               best_icon = pixbuf;
3166               best_size = this;
3167             }
3168           else
3169             {
3170               /* icon is better if it's 32 pixels or larger, and closer to
3171                * the ideal size than the current best.
3172                */
3173               if (this >= 32 &&
3174                   (ABS (best_size - IDEAL_SIZE) <
3175                    ABS (this - IDEAL_SIZE)))
3176                 {
3177                   best_icon = pixbuf;
3178                   best_size = this;
3179                 }
3180             }
3181 
3182           tmp_list = tmp_list->next;
3183         }
3184 
3185       if (best_icon)
3186         gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3187 							gdk_screen_get_system_colormap (screen),
3188 							pmap_return,
3189 							mask_return,
3190 							128);
3191 
3192       /* Save pmap/mask for others to use if appropriate */
3193       if (parent_info)
3194         {
3195           parent_info->icon_pixmap = *pmap_return;
3196           parent_info->icon_mask = *mask_return;
3197 
3198           if (parent_info->icon_pixmap)
3199             g_object_ref (parent_info->icon_pixmap);
3200           if (parent_info->icon_mask)
3201             g_object_ref (parent_info->icon_mask);
3202         }
3203       else if (is_default_list)
3204         {
3205           default_icon_info->pixmap = *pmap_return;
3206           default_icon_info->mask = *mask_return;
3207 
3208           if (default_icon_info->pixmap)
3209 	    g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3210 				       (gpointer*)&default_icon_info->pixmap);
3211           if (default_icon_info->mask)
3212 	    g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3213 				       (gpointer*)&default_icon_info->mask);
3214         }
3215     }
3216 }
3217 
3218 static GList *
icon_list_from_theme(GtkWidget * widget,const gchar * name)3219 icon_list_from_theme (GtkWidget    *widget,
3220 		      const gchar  *name)
3221 {
3222   GList *list;
3223 
3224   GtkIconTheme *icon_theme;
3225   GdkPixbuf *icon;
3226   gint *sizes;
3227   gint i;
3228 
3229   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3230 
3231   sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3232 
3233   list = NULL;
3234   for (i = 0; sizes[i]; i++)
3235     {
3236       /* FIXME
3237        * We need an EWMH extension to handle scalable icons
3238        * by passing their name to the WM. For now just use a
3239        * fixed size of 48.
3240        */
3241       if (sizes[i] == -1)
3242 	icon = gtk_icon_theme_load_icon (icon_theme, name,
3243 					 48, 0, NULL);
3244       else
3245 	icon = gtk_icon_theme_load_icon (icon_theme, name,
3246 					 sizes[i], 0, NULL);
3247       if (icon)
3248 	list = g_list_append (list, icon);
3249     }
3250 
3251   g_free (sizes);
3252 
3253   return list;
3254 }
3255 
3256 
3257 static void
gtk_window_realize_icon(GtkWindow * window)3258 gtk_window_realize_icon (GtkWindow *window)
3259 {
3260   GtkWidget *widget;
3261   GtkWindowIconInfo *info;
3262   GList *icon_list;
3263 
3264   widget = GTK_WIDGET (window);
3265 
3266   g_return_if_fail (widget->window != NULL);
3267 
3268   /* no point setting an icon on override-redirect */
3269   if (window->type == GTK_WINDOW_POPUP)
3270     return;
3271 
3272   icon_list = NULL;
3273 
3274   info = ensure_icon_info (window);
3275 
3276   if (info->realized)
3277     return;
3278 
3279   g_return_if_fail (info->icon_pixmap == NULL);
3280   g_return_if_fail (info->icon_mask == NULL);
3281 
3282   info->using_default_icon = FALSE;
3283   info->using_parent_icon = FALSE;
3284   info->using_themed_icon = FALSE;
3285 
3286   icon_list = info->icon_list;
3287 
3288   /* Look up themed icon */
3289   if (icon_list == NULL && info->icon_name)
3290     {
3291       icon_list = icon_list_from_theme (widget, info->icon_name);
3292       if (icon_list)
3293 	info->using_themed_icon = TRUE;
3294     }
3295 
3296   /* Inherit from transient parent */
3297   if (icon_list == NULL && window->transient_parent)
3298     {
3299       icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3300       if (icon_list)
3301         info->using_parent_icon = TRUE;
3302     }
3303 
3304   /* Inherit from default */
3305   if (icon_list == NULL)
3306     {
3307       icon_list = default_icon_list;
3308       if (icon_list)
3309         info->using_default_icon = TRUE;
3310     }
3311 
3312   /* Look up themed icon */
3313   if (icon_list == NULL && default_icon_name)
3314     {
3315       icon_list = icon_list_from_theme (widget, default_icon_name);
3316       info->using_default_icon = TRUE;
3317       info->using_themed_icon = TRUE;
3318     }
3319 
3320   gdk_window_set_icon_list (widget->window, icon_list);
3321 
3322   get_pixmap_and_mask (widget->window,
3323 		       info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3324                        info->using_default_icon,
3325                        icon_list,
3326                        &info->icon_pixmap,
3327                        &info->icon_mask);
3328 
3329   /* This is a slight ICCCM violation since it's a color pixmap not
3330    * a bitmap, but everyone does it.
3331    */
3332   gdk_window_set_icon (widget->window,
3333                        NULL,
3334                        info->icon_pixmap,
3335                        info->icon_mask);
3336 
3337   info->realized = TRUE;
3338 
3339   if (info->using_themed_icon)
3340     {
3341       GtkIconTheme *icon_theme;
3342 
3343       g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3344       g_list_free (icon_list);
3345 
3346       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3347       g_signal_connect (icon_theme, "changed",
3348 			G_CALLBACK (update_themed_icon), window);
3349     }
3350 }
3351 
3352 static void
gtk_window_unrealize_icon(GtkWindow * window)3353 gtk_window_unrealize_icon (GtkWindow *window)
3354 {
3355   GtkWindowIconInfo *info;
3356 
3357   info = get_icon_info (window);
3358 
3359   if (info == NULL)
3360     return;
3361 
3362   if (info->icon_pixmap)
3363     g_object_unref (info->icon_pixmap);
3364 
3365   if (info->icon_mask)
3366     g_object_unref (info->icon_mask);
3367 
3368   info->icon_pixmap = NULL;
3369   info->icon_mask = NULL;
3370 
3371   if (info->using_themed_icon)
3372     {
3373       GtkIconTheme *icon_theme;
3374 
3375       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3376 
3377       g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3378     }
3379 
3380   /* We don't clear the properties on the window, just figure the
3381    * window is going away.
3382    */
3383 
3384   info->realized = FALSE;
3385 
3386 }
3387 
3388 /**
3389  * gtk_window_set_icon_list:
3390  * @window: a #GtkWindow
3391  * @list: list of #GdkPixbuf
3392  *
3393  * Sets up the icon representing a #GtkWindow. The icon is used when
3394  * the window is minimized (also known as iconified).  Some window
3395  * managers or desktop environments may also place it in the window
3396  * frame, or display it in other contexts.
3397  *
3398  * gtk_window_set_icon_list() allows you to pass in the same icon in
3399  * several hand-drawn sizes. The list should contain the natural sizes
3400  * your icon is available in; that is, don't scale the image before
3401  * passing it to GTK+. Scaling is postponed until the last minute,
3402  * when the desired final size is known, to allow best quality.
3403  *
3404  * By passing several sizes, you may improve the final image quality
3405  * of the icon, by reducing or eliminating automatic image scaling.
3406  *
3407  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3408  * larger images (64x64, 128x128) if you have them.
3409  *
3410  * See also gtk_window_set_default_icon_list() to set the icon
3411  * for all windows in your application in one go.
3412  *
3413  * Note that transient windows (those who have been set transient for another
3414  * window using gtk_window_set_transient_for()) will inherit their
3415  * icon from their transient parent. So there's no need to explicitly
3416  * set the icon on transient windows.
3417  **/
3418 void
gtk_window_set_icon_list(GtkWindow * window,GList * list)3419 gtk_window_set_icon_list (GtkWindow  *window,
3420                           GList      *list)
3421 {
3422   GtkWindowIconInfo *info;
3423 
3424   g_return_if_fail (GTK_IS_WINDOW (window));
3425 
3426   info = ensure_icon_info (window);
3427 
3428   if (info->icon_list == list) /* check for NULL mostly */
3429     return;
3430 
3431   g_list_foreach (list,
3432                   (GFunc) g_object_ref, NULL);
3433 
3434   g_list_foreach (info->icon_list,
3435                   (GFunc) g_object_unref, NULL);
3436 
3437   g_list_free (info->icon_list);
3438 
3439   info->icon_list = g_list_copy (list);
3440 
3441   g_object_notify (G_OBJECT (window), "icon");
3442 
3443   gtk_window_unrealize_icon (window);
3444 
3445   if (gtk_widget_get_realized (GTK_WIDGET (window)))
3446     gtk_window_realize_icon (window);
3447 
3448   /* We could try to update our transient children, but I don't think
3449    * it's really worth it. If we did it, the best way would probably
3450    * be to have children connect to notify::icon-list
3451    */
3452 }
3453 
3454 /**
3455  * gtk_window_get_icon_list:
3456  * @window: a #GtkWindow
3457  *
3458  * Retrieves the list of icons set by gtk_window_set_icon_list().
3459  * The list is copied, but the reference count on each
3460  * member won't be incremented.
3461  *
3462  * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3463  **/
3464 GList*
gtk_window_get_icon_list(GtkWindow * window)3465 gtk_window_get_icon_list (GtkWindow  *window)
3466 {
3467   GtkWindowIconInfo *info;
3468 
3469   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3470 
3471   info = get_icon_info (window);
3472 
3473   if (info)
3474     return g_list_copy (info->icon_list);
3475   else
3476     return NULL;
3477 }
3478 
3479 /**
3480  * gtk_window_set_icon:
3481  * @window: a #GtkWindow
3482  * @icon: (allow-none): icon image, or %NULL
3483  *
3484  * Sets up the icon representing a #GtkWindow. This icon is used when
3485  * the window is minimized (also known as iconified).  Some window
3486  * managers or desktop environments may also place it in the window
3487  * frame, or display it in other contexts.
3488  *
3489  * The icon should be provided in whatever size it was naturally
3490  * drawn; that is, don't scale the image before passing it to
3491  * GTK+. Scaling is postponed until the last minute, when the desired
3492  * final size is known, to allow best quality.
3493  *
3494  * If you have your icon hand-drawn in multiple sizes, use
3495  * gtk_window_set_icon_list(). Then the best size will be used.
3496  *
3497  * This function is equivalent to calling gtk_window_set_icon_list()
3498  * with a 1-element list.
3499  *
3500  * See also gtk_window_set_default_icon_list() to set the icon
3501  * for all windows in your application in one go.
3502  **/
3503 void
gtk_window_set_icon(GtkWindow * window,GdkPixbuf * icon)3504 gtk_window_set_icon (GtkWindow  *window,
3505                      GdkPixbuf  *icon)
3506 {
3507   GList *list;
3508 
3509   g_return_if_fail (GTK_IS_WINDOW (window));
3510   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3511 
3512   list = NULL;
3513 
3514   if (icon)
3515     list = g_list_append (list, icon);
3516 
3517   gtk_window_set_icon_list (window, list);
3518   g_list_free (list);
3519 }
3520 
3521 
3522 static void
update_themed_icon(GtkIconTheme * icon_theme,GtkWindow * window)3523 update_themed_icon (GtkIconTheme *icon_theme,
3524 		    GtkWindow    *window)
3525 {
3526   g_object_notify (G_OBJECT (window), "icon");
3527 
3528   gtk_window_unrealize_icon (window);
3529 
3530   if (gtk_widget_get_realized (GTK_WIDGET (window)))
3531     gtk_window_realize_icon (window);
3532 }
3533 
3534 /**
3535  * gtk_window_set_icon_name:
3536  * @window: a #GtkWindow
3537  * @name: (allow-none): the name of the themed icon
3538  *
3539  * Sets the icon for the window from a named themed icon. See
3540  * the docs for #GtkIconTheme for more details.
3541  *
3542  * Note that this has nothing to do with the WM_ICON_NAME
3543  * property which is mentioned in the ICCCM.
3544  *
3545  * Since: 2.6
3546  */
3547 void
gtk_window_set_icon_name(GtkWindow * window,const gchar * name)3548 gtk_window_set_icon_name (GtkWindow   *window,
3549 			  const gchar *name)
3550 {
3551   GtkWindowIconInfo *info;
3552   gchar *tmp;
3553 
3554   g_return_if_fail (GTK_IS_WINDOW (window));
3555 
3556   info = ensure_icon_info (window);
3557 
3558   if (g_strcmp0 (info->icon_name, name) == 0)
3559     return;
3560 
3561   tmp = info->icon_name;
3562   info->icon_name = g_strdup (name);
3563   g_free (tmp);
3564 
3565   g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3566   g_list_free (info->icon_list);
3567   info->icon_list = NULL;
3568 
3569   update_themed_icon (NULL, window);
3570 
3571   g_object_notify (G_OBJECT (window), "icon-name");
3572 }
3573 
3574 /**
3575  * gtk_window_get_icon_name:
3576  * @window: a #GtkWindow
3577  *
3578  * Returns the name of the themed icon for the window,
3579  * see gtk_window_set_icon_name().
3580  *
3581  * Returns: the icon name or %NULL if the window has
3582  * no themed icon
3583  *
3584  * Since: 2.6
3585  */
3586 const gchar *
gtk_window_get_icon_name(GtkWindow * window)3587 gtk_window_get_icon_name (GtkWindow *window)
3588 {
3589   GtkWindowIconInfo *info;
3590 
3591   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3592 
3593   info = ensure_icon_info (window);
3594 
3595   return info->icon_name;
3596 }
3597 
3598 /**
3599  * gtk_window_get_icon:
3600  * @window: a #GtkWindow
3601  *
3602  * Gets the value set by gtk_window_set_icon() (or if you've
3603  * called gtk_window_set_icon_list(), gets the first icon in
3604  * the icon list).
3605  *
3606  * Return value: (transfer none): icon for window
3607  **/
3608 GdkPixbuf*
gtk_window_get_icon(GtkWindow * window)3609 gtk_window_get_icon (GtkWindow  *window)
3610 {
3611   GtkWindowIconInfo *info;
3612 
3613   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3614 
3615   info = get_icon_info (window);
3616   if (info && info->icon_list)
3617     return GDK_PIXBUF (info->icon_list->data);
3618   else
3619     return NULL;
3620 }
3621 
3622 /* Load pixbuf, printing warning on failure if error == NULL
3623  */
3624 static GdkPixbuf *
load_pixbuf_verbosely(const char * filename,GError ** err)3625 load_pixbuf_verbosely (const char *filename,
3626 		       GError    **err)
3627 {
3628   GError *local_err = NULL;
3629   GdkPixbuf *pixbuf;
3630 
3631   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3632 
3633   if (!pixbuf)
3634     {
3635       if (err)
3636 	*err = local_err;
3637       else
3638 	{
3639 	  g_warning ("Error loading icon from file '%s':\n\t%s",
3640 		     filename, local_err->message);
3641 	  g_error_free (local_err);
3642 	}
3643     }
3644 
3645   return pixbuf;
3646 }
3647 
3648 /**
3649  * gtk_window_set_icon_from_file:
3650  * @window: a #GtkWindow
3651  * @filename: location of icon file
3652  * @err: (allow-none): location to store error, or %NULL.
3653  *
3654  * Sets the icon for @window.
3655  * Warns on failure if @err is %NULL.
3656  *
3657  * This function is equivalent to calling gtk_window_set_icon()
3658  * with a pixbuf created by loading the image from @filename.
3659  *
3660  * Returns: %TRUE if setting the icon succeeded.
3661  *
3662  * Since: 2.2
3663  **/
3664 gboolean
gtk_window_set_icon_from_file(GtkWindow * window,const gchar * filename,GError ** err)3665 gtk_window_set_icon_from_file (GtkWindow   *window,
3666 			       const gchar *filename,
3667 			       GError     **err)
3668 {
3669   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3670 
3671   if (pixbuf)
3672     {
3673       gtk_window_set_icon (window, pixbuf);
3674       g_object_unref (pixbuf);
3675 
3676       return TRUE;
3677     }
3678   else
3679     return FALSE;
3680 }
3681 
3682 /**
3683  * gtk_window_set_default_icon_list:
3684  * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3685  *
3686  * Sets an icon list to be used as fallback for windows that haven't
3687  * had gtk_window_set_icon_list() called on them to set up a
3688  * window-specific icon list. This function allows you to set up the
3689  * icon for all windows in your app at once.
3690  *
3691  * See gtk_window_set_icon_list() for more details.
3692  *
3693  **/
3694 void
gtk_window_set_default_icon_list(GList * list)3695 gtk_window_set_default_icon_list (GList *list)
3696 {
3697   GList *toplevels;
3698   GList *tmp_list;
3699   if (list == default_icon_list)
3700     return;
3701 
3702   /* Update serial so we don't used cached pixmaps/masks
3703    */
3704   default_icon_serial++;
3705 
3706   g_list_foreach (list,
3707                   (GFunc) g_object_ref, NULL);
3708 
3709   g_list_foreach (default_icon_list,
3710                   (GFunc) g_object_unref, NULL);
3711 
3712   g_list_free (default_icon_list);
3713 
3714   default_icon_list = g_list_copy (list);
3715 
3716   /* Update all toplevels */
3717   toplevels = gtk_window_list_toplevels ();
3718   tmp_list = toplevels;
3719   while (tmp_list != NULL)
3720     {
3721       GtkWindowIconInfo *info;
3722       GtkWindow *w = tmp_list->data;
3723 
3724       info = get_icon_info (w);
3725       if (info && info->using_default_icon)
3726         {
3727           gtk_window_unrealize_icon (w);
3728           if (gtk_widget_get_realized (GTK_WIDGET (w)))
3729             gtk_window_realize_icon (w);
3730         }
3731 
3732       tmp_list = tmp_list->next;
3733     }
3734   g_list_free (toplevels);
3735 }
3736 
3737 /**
3738  * gtk_window_set_default_icon:
3739  * @icon: the icon
3740  *
3741  * Sets an icon to be used as fallback for windows that haven't
3742  * had gtk_window_set_icon() called on them from a pixbuf.
3743  *
3744  * Since: 2.4
3745  **/
3746 void
gtk_window_set_default_icon(GdkPixbuf * icon)3747 gtk_window_set_default_icon (GdkPixbuf *icon)
3748 {
3749   GList *list;
3750 
3751   g_return_if_fail (GDK_IS_PIXBUF (icon));
3752 
3753   list = g_list_prepend (NULL, icon);
3754   gtk_window_set_default_icon_list (list);
3755   g_list_free (list);
3756 }
3757 
3758 /**
3759  * gtk_window_set_default_icon_name:
3760  * @name: the name of the themed icon
3761  *
3762  * Sets an icon to be used as fallback for windows that haven't
3763  * had gtk_window_set_icon_list() called on them from a named
3764  * themed icon, see gtk_window_set_icon_name().
3765  *
3766  * Since: 2.6
3767  **/
3768 void
gtk_window_set_default_icon_name(const gchar * name)3769 gtk_window_set_default_icon_name (const gchar *name)
3770 {
3771   GList *tmp_list;
3772   GList *toplevels;
3773 
3774   /* Update serial so we don't used cached pixmaps/masks
3775    */
3776   default_icon_serial++;
3777 
3778   g_free (default_icon_name);
3779   default_icon_name = g_strdup (name);
3780 
3781   g_list_foreach (default_icon_list,
3782                   (GFunc) g_object_unref, NULL);
3783 
3784   g_list_free (default_icon_list);
3785   default_icon_list = NULL;
3786 
3787   /* Update all toplevels */
3788   toplevels = gtk_window_list_toplevels ();
3789   tmp_list = toplevels;
3790   while (tmp_list != NULL)
3791     {
3792       GtkWindowIconInfo *info;
3793       GtkWindow *w = tmp_list->data;
3794 
3795       info = get_icon_info (w);
3796       if (info && info->using_default_icon && info->using_themed_icon)
3797         {
3798           gtk_window_unrealize_icon (w);
3799           if (gtk_widget_get_realized (GTK_WIDGET (w)))
3800             gtk_window_realize_icon (w);
3801         }
3802 
3803       tmp_list = tmp_list->next;
3804     }
3805   g_list_free (toplevels);
3806 }
3807 
3808 /**
3809  * gtk_window_get_default_icon_name:
3810  *
3811  * Returns the fallback icon name for windows that has been set
3812  * with gtk_window_set_default_icon_name(). The returned
3813  * string is owned by GTK+ and should not be modified. It
3814  * is only valid until the next call to
3815  * gtk_window_set_default_icon_name().
3816  *
3817  * Returns: the fallback icon name for windows
3818  *
3819  * Since: 2.16
3820  */
3821 const gchar *
gtk_window_get_default_icon_name(void)3822 gtk_window_get_default_icon_name (void)
3823 {
3824   return default_icon_name;
3825 }
3826 
3827 /**
3828  * gtk_window_set_default_icon_from_file:
3829  * @filename: location of icon file
3830  * @err: (allow-none): location to store error, or %NULL.
3831  *
3832  * Sets an icon to be used as fallback for windows that haven't
3833  * had gtk_window_set_icon_list() called on them from a file
3834  * on disk. Warns on failure if @err is %NULL.
3835  *
3836  * Returns: %TRUE if setting the icon succeeded.
3837  *
3838  * Since: 2.2
3839  **/
3840 gboolean
gtk_window_set_default_icon_from_file(const gchar * filename,GError ** err)3841 gtk_window_set_default_icon_from_file (const gchar *filename,
3842 				       GError     **err)
3843 {
3844   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3845 
3846   if (pixbuf)
3847     {
3848       gtk_window_set_default_icon (pixbuf);
3849       g_object_unref (pixbuf);
3850 
3851       return TRUE;
3852     }
3853   else
3854     return FALSE;
3855 }
3856 
3857 /**
3858  * gtk_window_get_default_icon_list:
3859  *
3860  * Gets the value set by gtk_window_set_default_icon_list().
3861  * The list is a copy and should be freed with g_list_free(),
3862  * but the pixbufs in the list have not had their reference count
3863  * incremented.
3864  *
3865  * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3866  **/
3867 GList*
gtk_window_get_default_icon_list(void)3868 gtk_window_get_default_icon_list (void)
3869 {
3870   return g_list_copy (default_icon_list);
3871 }
3872 
3873 static void
gtk_window_set_default_size_internal(GtkWindow * window,gboolean change_width,gint width,gboolean change_height,gint height,gboolean is_geometry)3874 gtk_window_set_default_size_internal (GtkWindow    *window,
3875                                       gboolean      change_width,
3876                                       gint          width,
3877                                       gboolean      change_height,
3878                                       gint          height,
3879 				      gboolean      is_geometry)
3880 {
3881   GtkWindowGeometryInfo *info;
3882 
3883   g_return_if_fail (change_width == FALSE || width >= -1);
3884   g_return_if_fail (change_height == FALSE || height >= -1);
3885 
3886   info = gtk_window_get_geometry_info (window, TRUE);
3887 
3888   g_object_freeze_notify (G_OBJECT (window));
3889 
3890   info->default_is_geometry = is_geometry != FALSE;
3891 
3892   if (change_width)
3893     {
3894       if (width == 0)
3895         width = 1;
3896 
3897       if (width < 0)
3898         width = -1;
3899 
3900       info->default_width = width;
3901 
3902       g_object_notify (G_OBJECT (window), "default-width");
3903     }
3904 
3905   if (change_height)
3906     {
3907       if (height == 0)
3908         height = 1;
3909 
3910       if (height < 0)
3911         height = -1;
3912 
3913       info->default_height = height;
3914 
3915       g_object_notify (G_OBJECT (window), "default-height");
3916     }
3917 
3918   g_object_thaw_notify (G_OBJECT (window));
3919 
3920   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3921 }
3922 
3923 /**
3924  * gtk_window_set_default_size:
3925  * @window: a #GtkWindow
3926  * @width: width in pixels, or -1 to unset the default width
3927  * @height: height in pixels, or -1 to unset the default height
3928  *
3929  * Sets the default size of a window. If the window's "natural" size
3930  * (its size request) is larger than the default, the default will be
3931  * ignored. More generally, if the default size does not obey the
3932  * geometry hints for the window (gtk_window_set_geometry_hints() can
3933  * be used to set these explicitly), the default size will be clamped
3934  * to the nearest permitted size.
3935  *
3936  * Unlike gtk_widget_set_size_request(), which sets a size request for
3937  * a widget and thus would keep users from shrinking the window, this
3938  * function only sets the initial size, just as if the user had
3939  * resized the window themselves. Users can still shrink the window
3940  * again as they normally would. Setting a default size of -1 means to
3941  * use the "natural" default size (the size request of the window).
3942  *
3943  * For more control over a window's initial size and how resizing works,
3944  * investigate gtk_window_set_geometry_hints().
3945  *
3946  * For some uses, gtk_window_resize() is a more appropriate function.
3947  * gtk_window_resize() changes the current size of the window, rather
3948  * than the size to be used on initial display. gtk_window_resize() always
3949  * affects the window itself, not the geometry widget.
3950  *
3951  * The default size of a window only affects the first time a window is
3952  * shown; if a window is hidden and re-shown, it will remember the size
3953  * it had prior to hiding, rather than using the default size.
3954  *
3955  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3956  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3957  **/
3958 void
gtk_window_set_default_size(GtkWindow * window,gint width,gint height)3959 gtk_window_set_default_size (GtkWindow   *window,
3960 			     gint         width,
3961 			     gint         height)
3962 {
3963   g_return_if_fail (GTK_IS_WINDOW (window));
3964   g_return_if_fail (width >= -1);
3965   g_return_if_fail (height >= -1);
3966 
3967   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3968 }
3969 
3970 /**
3971  * gtk_window_get_default_size:
3972  * @window: a #GtkWindow
3973  * @width: (allow-none): location to store the default width, or %NULL
3974  * @height: (allow-none): location to store the default height, or %NULL
3975  *
3976  * Gets the default size of the window. A value of -1 for the width or
3977  * height indicates that a default size has not been explicitly set
3978  * for that dimension, so the "natural" size of the window will be
3979  * used.
3980  *
3981  **/
3982 void
gtk_window_get_default_size(GtkWindow * window,gint * width,gint * height)3983 gtk_window_get_default_size (GtkWindow *window,
3984 			     gint      *width,
3985 			     gint      *height)
3986 {
3987   GtkWindowGeometryInfo *info;
3988 
3989   g_return_if_fail (GTK_IS_WINDOW (window));
3990 
3991   info = gtk_window_get_geometry_info (window, FALSE);
3992 
3993   if (width)
3994     *width = info ? info->default_width : -1;
3995 
3996   if (height)
3997     *height = info ? info->default_height : -1;
3998 }
3999 
4000 /**
4001  * gtk_window_resize:
4002  * @window: a #GtkWindow
4003  * @width: width in pixels to resize the window to
4004  * @height: height in pixels to resize the window to
4005  *
4006  * Resizes the window as if the user had done so, obeying geometry
4007  * constraints. The default geometry constraint is that windows may
4008  * not be smaller than their size request; to override this
4009  * constraint, call gtk_widget_set_size_request() to set the window's
4010  * request to a smaller value.
4011  *
4012  * If gtk_window_resize() is called before showing a window for the
4013  * first time, it overrides any default size set with
4014  * gtk_window_set_default_size().
4015  *
4016  * Windows may not be resized smaller than 1 by 1 pixels.
4017  *
4018  **/
4019 void
gtk_window_resize(GtkWindow * window,gint width,gint height)4020 gtk_window_resize (GtkWindow *window,
4021                    gint       width,
4022                    gint       height)
4023 {
4024   GtkWindowGeometryInfo *info;
4025 
4026   g_return_if_fail (GTK_IS_WINDOW (window));
4027   g_return_if_fail (width > 0);
4028   g_return_if_fail (height > 0);
4029 
4030   info = gtk_window_get_geometry_info (window, TRUE);
4031 
4032   info->resize_width = width;
4033   info->resize_height = height;
4034 
4035   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4036 }
4037 
4038 /**
4039  * gtk_window_get_size:
4040  * @window: a #GtkWindow
4041  * @width: (out) (allow-none): return location for width, or %NULL
4042  * @height: (out) (allow-none): return location for height, or %NULL
4043  *
4044  * Obtains the current size of @window. If @window is not onscreen,
4045  * it returns the size GTK+ will suggest to the <link
4046  * linkend="gtk-X11-arch">window manager</link> for the initial window
4047  * size (but this is not reliably the same as the size the window
4048  * manager will actually select). The size obtained by
4049  * gtk_window_get_size() is the last size received in a
4050  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4051  * rather than querying the X server for the size. As a result, if you
4052  * call gtk_window_resize() then immediately call
4053  * gtk_window_get_size(), the size won't have taken effect yet. After
4054  * the window manager processes the resize request, GTK+ receives
4055  * notification that the size has changed via a configure event, and
4056  * the size of the window gets updated.
4057  *
4058  * Note 1: Nearly any use of this function creates a race condition,
4059  * because the size of the window may change between the time that you
4060  * get the size and the time that you perform some action assuming
4061  * that size is the current size. To avoid race conditions, connect to
4062  * "configure-event" on the window and adjust your size-dependent
4063  * state to match the size delivered in the #GdkEventConfigure.
4064  *
4065  * Note 2: The returned size does <emphasis>not</emphasis> include the
4066  * size of the window manager decorations (aka the window frame or
4067  * border). Those are not drawn by GTK+ and GTK+ has no reliable
4068  * method of determining their size.
4069  *
4070  * Note 3: If you are getting a window size in order to position
4071  * the window onscreen, there may be a better way. The preferred
4072  * way is to simply set the window's semantic type with
4073  * gtk_window_set_type_hint(), which allows the window manager to
4074  * e.g. center dialogs. Also, if you set the transient parent of
4075  * dialogs with gtk_window_set_transient_for() window managers
4076  * will often center the dialog over its parent window. It's
4077  * much preferred to let the window manager handle these
4078  * things rather than doing it yourself, because all apps will
4079  * behave consistently and according to user prefs if the window
4080  * manager handles it. Also, the window manager can take the size
4081  * of the window decorations/border into account, while your
4082  * application cannot.
4083  *
4084  * In any case, if you insist on application-specified window
4085  * positioning, there's <emphasis>still</emphasis> a better way than
4086  * doing it yourself - gtk_window_set_position() will frequently
4087  * handle the details for you.
4088  *
4089  **/
4090 void
gtk_window_get_size(GtkWindow * window,gint * width,gint * height)4091 gtk_window_get_size (GtkWindow *window,
4092                      gint      *width,
4093                      gint      *height)
4094 {
4095   gint w, h;
4096 
4097   g_return_if_fail (GTK_IS_WINDOW (window));
4098 
4099   if (width == NULL && height == NULL)
4100     return;
4101 
4102   if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4103     {
4104       w = gdk_window_get_width (GTK_WIDGET (window)->window);
4105       h = gdk_window_get_height (GTK_WIDGET (window)->window);
4106     }
4107   else
4108     {
4109       GdkRectangle configure_request;
4110 
4111       gtk_window_compute_configure_request (window,
4112                                             &configure_request,
4113                                             NULL, NULL);
4114 
4115       w = configure_request.width;
4116       h = configure_request.height;
4117     }
4118 
4119   if (width)
4120     *width = w;
4121   if (height)
4122     *height = h;
4123 }
4124 
4125 /**
4126  * gtk_window_move:
4127  * @window: a #GtkWindow
4128  * @x: X coordinate to move window to
4129  * @y: Y coordinate to move window to
4130  *
4131  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4132  * @window to the given position.  Window managers are free to ignore
4133  * this; most window managers ignore requests for initial window
4134  * positions (instead using a user-defined placement algorithm) and
4135  * honor requests after the window has already been shown.
4136  *
4137  * Note: the position is the position of the gravity-determined
4138  * reference point for the window. The gravity determines two things:
4139  * first, the location of the reference point in root window
4140  * coordinates; and second, which point on the window is positioned at
4141  * the reference point.
4142  *
4143  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4144  * point is simply the @x, @y supplied to gtk_window_move(). The
4145  * top-left corner of the window decorations (aka window frame or
4146  * border) will be placed at @x, @y.  Therefore, to position a window
4147  * at the top left of the screen, you want to use the default gravity
4148  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4149  *
4150  * To position a window at the bottom right corner of the screen, you
4151  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4152  * point is at @x + the window width and @y + the window height, and
4153  * the bottom-right corner of the window border will be placed at that
4154  * reference point. So, to place a window in the bottom right corner
4155  * you would first set gravity to south east, then write:
4156  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4157  * gdk_screen_height () - window_height)</literal> (note that this
4158  * example does not take multi-head scenarios into account).
4159  *
4160  * The Extended Window Manager Hints specification at <ulink
4161  * url="http://www.freedesktop.org/Standards/wm-spec">
4162  * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4163  * nice table of gravities in the "implementation notes" section.
4164  *
4165  * The gtk_window_get_position() documentation may also be relevant.
4166  */
4167 void
gtk_window_move(GtkWindow * window,gint x,gint y)4168 gtk_window_move (GtkWindow *window,
4169                  gint       x,
4170                  gint       y)
4171 {
4172   GtkWindowGeometryInfo *info;
4173   GtkWidget *widget;
4174 
4175   g_return_if_fail (GTK_IS_WINDOW (window));
4176 
4177   widget = GTK_WIDGET (window);
4178 
4179   info = gtk_window_get_geometry_info (window, TRUE);
4180 
4181   if (gtk_widget_get_mapped (widget))
4182     {
4183       /* we have now sent a request with this position
4184        * with currently-active constraints, so toggle flag.
4185        */
4186       info->position_constraints_changed = FALSE;
4187 
4188       /* we only constrain if mapped - if not mapped,
4189        * then gtk_window_compute_configure_request()
4190        * will apply the constraints later, and we
4191        * don't want to lose information about
4192        * what position the user set before then.
4193        * i.e. if you do a move() then turn off POS_CENTER
4194        * then show the window, your move() will work.
4195        */
4196       gtk_window_constrain_position (window,
4197                                      widget->allocation.width,
4198                                      widget->allocation.height,
4199                                      &x, &y);
4200 
4201       /* Note that this request doesn't go through our standard request
4202        * framework, e.g. doesn't increment configure_request_count,
4203        * doesn't set info->last, etc.; that's because
4204        * we don't save the info needed to arrive at this same request
4205        * again.
4206        *
4207        * To gtk_window_move_resize(), this will end up looking exactly
4208        * the same as the position being changed by the window
4209        * manager.
4210        */
4211 
4212       /* FIXME are we handling gravity properly for framed windows? */
4213       if (window->frame)
4214         gdk_window_move (window->frame,
4215                          x - window->frame_left,
4216                          y - window->frame_top);
4217       else
4218         gdk_window_move (GTK_WIDGET (window)->window,
4219                          x, y);
4220     }
4221   else
4222     {
4223       /* Save this position to apply on mapping */
4224       info->initial_x = x;
4225       info->initial_y = y;
4226       info->initial_pos_set = TRUE;
4227     }
4228 }
4229 
4230 /**
4231  * gtk_window_get_position:
4232  * @window: a #GtkWindow
4233  * @root_x: (out) (allow-none): return location for X coordinate of gravity-determined reference point
4234  * @root_y: (out) (allow-none): return location for Y coordinate of gravity-determined reference point
4235  *
4236  * This function returns the position you need to pass to
4237  * gtk_window_move() to keep @window in its current position.  This
4238  * means that the meaning of the returned value varies with window
4239  * gravity. See gtk_window_move() for more details.
4240  *
4241  * If you haven't changed the window gravity, its gravity will be
4242  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4243  * gets the position of the top-left corner of the window manager
4244  * frame for the window. gtk_window_move() sets the position of this
4245  * same top-left corner.
4246  *
4247  * gtk_window_get_position() is not 100% reliable because the X Window System
4248  * does not specify a way to obtain the geometry of the
4249  * decorations placed on a window by the window manager.
4250  * Thus GTK+ is using a "best guess" that works with most
4251  * window managers.
4252  *
4253  * Moreover, nearly all window managers are historically broken with
4254  * respect to their handling of window gravity. So moving a window to
4255  * its current position as returned by gtk_window_get_position() tends
4256  * to result in moving the window slightly. Window managers are
4257  * slowly getting better over time.
4258  *
4259  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4260  * frame is not relevant, and thus gtk_window_get_position() will
4261  * always produce accurate results. However you can't use static
4262  * gravity to do things like place a window in a corner of the screen,
4263  * because static gravity ignores the window manager decorations.
4264  *
4265  * If you are saving and restoring your application's window
4266  * positions, you should know that it's impossible for applications to
4267  * do this without getting it somewhat wrong because applications do
4268  * not have sufficient knowledge of window manager state. The Correct
4269  * Mechanism is to support the session management protocol (see the
4270  * "GnomeClient" object in the GNOME libraries for example) and allow
4271  * the window manager to save your window sizes and positions.
4272  *
4273  **/
4274 
4275 void
gtk_window_get_position(GtkWindow * window,gint * root_x,gint * root_y)4276 gtk_window_get_position (GtkWindow *window,
4277                          gint      *root_x,
4278                          gint      *root_y)
4279 {
4280   GtkWidget *widget;
4281 
4282   g_return_if_fail (GTK_IS_WINDOW (window));
4283 
4284   widget = GTK_WIDGET (window);
4285 
4286   if (window->gravity == GDK_GRAVITY_STATIC)
4287     {
4288       if (gtk_widget_get_mapped (widget))
4289         {
4290           /* This does a server round-trip, which is sort of wrong;
4291            * but a server round-trip is inevitable for
4292            * gdk_window_get_frame_extents() in the usual
4293            * NorthWestGravity case below, so not sure what else to
4294            * do. We should likely be consistent about whether we get
4295            * the client-side info or the server-side info.
4296            */
4297           gdk_window_get_origin (widget->window, root_x, root_y);
4298         }
4299       else
4300         {
4301           GdkRectangle configure_request;
4302 
4303           gtk_window_compute_configure_request (window,
4304                                                 &configure_request,
4305                                                 NULL, NULL);
4306 
4307           *root_x = configure_request.x;
4308           *root_y = configure_request.y;
4309         }
4310     }
4311   else
4312     {
4313       GdkRectangle frame_extents;
4314 
4315       gint x, y;
4316       gint w, h;
4317 
4318       if (gtk_widget_get_mapped (widget))
4319         {
4320 	  if (window->frame)
4321 	    gdk_window_get_frame_extents (window->frame, &frame_extents);
4322 	  else
4323 	    gdk_window_get_frame_extents (widget->window, &frame_extents);
4324           x = frame_extents.x;
4325           y = frame_extents.y;
4326           gtk_window_get_size (window, &w, &h);
4327         }
4328       else
4329         {
4330           /* We just say the frame has 0 size on all sides.
4331            * Not sure what else to do.
4332            */
4333           gtk_window_compute_configure_request (window,
4334                                                 &frame_extents,
4335                                                 NULL, NULL);
4336           x = frame_extents.x;
4337           y = frame_extents.y;
4338           w = frame_extents.width;
4339           h = frame_extents.height;
4340         }
4341 
4342       switch (window->gravity)
4343         {
4344         case GDK_GRAVITY_NORTH:
4345         case GDK_GRAVITY_CENTER:
4346         case GDK_GRAVITY_SOUTH:
4347           /* Find center of frame. */
4348           x += frame_extents.width / 2;
4349           /* Center client window on that point. */
4350           x -= w / 2;
4351           break;
4352 
4353         case GDK_GRAVITY_SOUTH_EAST:
4354         case GDK_GRAVITY_EAST:
4355         case GDK_GRAVITY_NORTH_EAST:
4356           /* Find right edge of frame */
4357           x += frame_extents.width;
4358           /* Align left edge of client at that point. */
4359           x -= w;
4360           break;
4361         default:
4362           break;
4363         }
4364 
4365       switch (window->gravity)
4366         {
4367         case GDK_GRAVITY_WEST:
4368         case GDK_GRAVITY_CENTER:
4369         case GDK_GRAVITY_EAST:
4370           /* Find center of frame. */
4371           y += frame_extents.height / 2;
4372           /* Center client window there. */
4373           y -= h / 2;
4374           break;
4375         case GDK_GRAVITY_SOUTH_WEST:
4376         case GDK_GRAVITY_SOUTH:
4377         case GDK_GRAVITY_SOUTH_EAST:
4378           /* Find south edge of frame */
4379           y += frame_extents.height;
4380           /* Place bottom edge of client there */
4381           y -= h;
4382           break;
4383         default:
4384           break;
4385         }
4386 
4387       if (root_x)
4388         *root_x = x;
4389       if (root_y)
4390         *root_y = y;
4391     }
4392 }
4393 
4394 /**
4395  * gtk_window_reshow_with_initial_size:
4396  * @window: a #GtkWindow
4397  *
4398  * Hides @window, then reshows it, resetting the
4399  * default size and position of the window. Used
4400  * by GUI builders only.
4401  **/
4402 void
gtk_window_reshow_with_initial_size(GtkWindow * window)4403 gtk_window_reshow_with_initial_size (GtkWindow *window)
4404 {
4405   GtkWidget *widget;
4406 
4407   g_return_if_fail (GTK_IS_WINDOW (window));
4408 
4409   widget = GTK_WIDGET (window);
4410 
4411   gtk_widget_hide (widget);
4412   gtk_widget_unrealize (widget);
4413   gtk_widget_show (widget);
4414 }
4415 
4416 static void
gtk_window_destroy(GtkObject * object)4417 gtk_window_destroy (GtkObject *object)
4418 {
4419   GtkWindow *window = GTK_WINDOW (object);
4420 
4421   toplevel_list = g_slist_remove (toplevel_list, window);
4422 
4423   if (window->transient_parent)
4424     gtk_window_set_transient_for (window, NULL);
4425 
4426   /* frees the icons */
4427   gtk_window_set_icon_list (window, NULL);
4428 
4429   if (window->has_user_ref_count)
4430     {
4431       window->has_user_ref_count = FALSE;
4432       g_object_unref (window);
4433     }
4434 
4435   if (window->group)
4436     gtk_window_group_remove_window (window->group, window);
4437 
4438    gtk_window_free_key_hash (window);
4439 
4440    GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4441 }
4442 
4443 static void
gtk_window_finalize(GObject * object)4444 gtk_window_finalize (GObject *object)
4445 {
4446   GtkWindow *window = GTK_WINDOW (object);
4447   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4448   GtkMnemonicHash *mnemonic_hash;
4449 
4450   g_free (window->title);
4451   g_free (window->wmclass_name);
4452   g_free (window->wmclass_class);
4453   g_free (window->wm_role);
4454 
4455   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4456   if (mnemonic_hash)
4457     _gtk_mnemonic_hash_free (mnemonic_hash);
4458 
4459   if (window->geometry_info)
4460     {
4461       if (window->geometry_info->widget)
4462 	g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4463 					      gtk_widget_destroyed,
4464 					      &window->geometry_info->widget);
4465       g_free (window->geometry_info);
4466     }
4467 
4468   if (window->keys_changed_handler)
4469     {
4470       g_source_remove (window->keys_changed_handler);
4471       window->keys_changed_handler = 0;
4472     }
4473 
4474   if (window->screen)
4475     g_signal_handlers_disconnect_by_func (window->screen,
4476                                           gtk_window_on_composited_changed, window);
4477 
4478   g_free (priv->startup_id);
4479 
4480   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4481 }
4482 
4483 static void
gtk_window_show(GtkWidget * widget)4484 gtk_window_show (GtkWidget *widget)
4485 {
4486   GtkWindow *window = GTK_WINDOW (widget);
4487   GtkContainer *container = GTK_CONTAINER (window);
4488   gboolean need_resize;
4489 
4490   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4491 
4492   need_resize = container->need_resize || !gtk_widget_get_realized (widget);
4493   container->need_resize = FALSE;
4494 
4495   if (need_resize)
4496     {
4497       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4498       GtkAllocation allocation = { 0, 0 };
4499       GdkRectangle configure_request;
4500       GdkGeometry new_geometry;
4501       guint new_flags;
4502       gboolean was_realized;
4503 
4504       /* We are going to go ahead and perform this configure request
4505        * and then emulate a configure notify by going ahead and
4506        * doing a size allocate. Sort of a synchronous
4507        * mini-copy of gtk_window_move_resize() here.
4508        */
4509       gtk_window_compute_configure_request (window,
4510                                             &configure_request,
4511                                             &new_geometry,
4512                                             &new_flags);
4513 
4514       /* We update this because we are going to go ahead
4515        * and gdk_window_resize() below, rather than
4516        * queuing it.
4517        */
4518       info->last.configure_request.width = configure_request.width;
4519       info->last.configure_request.height = configure_request.height;
4520 
4521       /* and allocate the window - this is normally done
4522        * in move_resize in response to configure notify
4523        */
4524       allocation.width  = configure_request.width;
4525       allocation.height = configure_request.height;
4526       gtk_widget_size_allocate (widget, &allocation);
4527 
4528       /* Then we guarantee we have a realize */
4529       was_realized = FALSE;
4530       if (!gtk_widget_get_realized (widget))
4531 	{
4532 	  gtk_widget_realize (widget);
4533 	  was_realized = TRUE;
4534 	}
4535 
4536       /* Must be done after the windows are realized,
4537        * so that the decorations can be read
4538        */
4539       gtk_decorated_window_calculate_frame_size (window);
4540 
4541       /* We only send configure request if we didn't just finish
4542        * creating the window; if we just created the window
4543        * then we created it with widget->allocation anyhow.
4544        */
4545       if (!was_realized)
4546 	gdk_window_move_resize (widget->window,
4547 				configure_request.x,
4548 				configure_request.y,
4549 				configure_request.width,
4550 				configure_request.height);
4551     }
4552 
4553   gtk_container_check_resize (container);
4554 
4555   gtk_widget_map (widget);
4556 
4557   /* Try to make sure that we have some focused widget
4558    */
4559   if (!window->focus_widget && !GTK_IS_PLUG (window))
4560     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4561 
4562   if (window->modal)
4563     gtk_grab_add (widget);
4564 }
4565 
4566 static void
gtk_window_hide(GtkWidget * widget)4567 gtk_window_hide (GtkWidget *widget)
4568 {
4569   GtkWindow *window = GTK_WINDOW (widget);
4570 
4571   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4572   gtk_widget_unmap (widget);
4573 
4574   if (window->modal)
4575     gtk_grab_remove (widget);
4576 }
4577 
4578 static void
gtk_window_map(GtkWidget * widget)4579 gtk_window_map (GtkWidget *widget)
4580 {
4581   GtkWindow *window = GTK_WINDOW (widget);
4582   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4583   GdkWindow *toplevel;
4584   gboolean auto_mnemonics;
4585 
4586   gtk_widget_set_mapped (widget, TRUE);
4587 
4588   if (window->bin.child &&
4589       gtk_widget_get_visible (window->bin.child) &&
4590       !gtk_widget_get_mapped (window->bin.child))
4591     gtk_widget_map (window->bin.child);
4592 
4593   if (window->frame)
4594     toplevel = window->frame;
4595   else
4596     toplevel = widget->window;
4597 
4598   if (window->maximize_initially)
4599     gdk_window_maximize (toplevel);
4600   else
4601     gdk_window_unmaximize (toplevel);
4602 
4603   if (window->stick_initially)
4604     gdk_window_stick (toplevel);
4605   else
4606     gdk_window_unstick (toplevel);
4607 
4608   if (window->iconify_initially)
4609     gdk_window_iconify (toplevel);
4610   else
4611     gdk_window_deiconify (toplevel);
4612 
4613   if (priv->fullscreen_initially)
4614     gdk_window_fullscreen (toplevel);
4615   else
4616     gdk_window_unfullscreen (toplevel);
4617 
4618   gdk_window_set_keep_above (toplevel, priv->above_initially);
4619 
4620   gdk_window_set_keep_below (toplevel, priv->below_initially);
4621 
4622   /* No longer use the default settings */
4623   window->need_default_size = FALSE;
4624   window->need_default_position = FALSE;
4625 
4626   if (priv->reset_type_hint)
4627     {
4628       /* We should only reset the type hint when the application
4629        * used gtk_window_set_type_hint() to change the hint.
4630        * Some applications use X directly to change the properties;
4631        * in that case, we shouldn't overwrite what they did.
4632        */
4633       gdk_window_set_type_hint (widget->window, priv->type_hint);
4634       priv->reset_type_hint = FALSE;
4635     }
4636 
4637   gdk_window_show (widget->window);
4638 
4639   if (window->frame)
4640     gdk_window_show (window->frame);
4641 
4642   if (!disable_startup_notification)
4643     {
4644       /* Do we have a custom startup-notification id? */
4645       if (priv->startup_id != NULL)
4646         {
4647           /* Make sure we have a "real" id */
4648           if (!startup_id_is_fake (priv->startup_id))
4649             gdk_notify_startup_complete_with_id (priv->startup_id);
4650 
4651           g_free (priv->startup_id);
4652           priv->startup_id = NULL;
4653         }
4654       else if (!sent_startup_notification)
4655         {
4656           sent_startup_notification = TRUE;
4657           gdk_notify_startup_complete ();
4658         }
4659     }
4660 
4661   /* if auto-mnemonics is enabled and mnemonics visible is not already set
4662    * (as in the case of popup menus), then hide mnemonics initially
4663    */
4664   g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4665                 &auto_mnemonics, NULL);
4666   if (auto_mnemonics && !priv->mnemonics_visible_set)
4667     gtk_window_set_mnemonics_visible (window, FALSE);
4668 }
4669 
4670 static gboolean
gtk_window_map_event(GtkWidget * widget,GdkEventAny * event)4671 gtk_window_map_event (GtkWidget   *widget,
4672                       GdkEventAny *event)
4673 {
4674   if (!gtk_widget_get_mapped (widget))
4675     {
4676       /* we should be be unmapped, but are getting a MapEvent, this may happen
4677        * to toplevel XWindows if mapping was intercepted by a window manager
4678        * and an unmap request occoured while the MapRequestEvent was still
4679        * being handled. we work around this situaiton here by re-requesting
4680        * the window being unmapped. more details can be found in:
4681        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4682        */
4683       gdk_window_hide (widget->window);
4684     }
4685   return FALSE;
4686 }
4687 
4688 static void
gtk_window_unmap(GtkWidget * widget)4689 gtk_window_unmap (GtkWidget *widget)
4690 {
4691   GtkWindow *window = GTK_WINDOW (widget);
4692   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4693   GtkWindowGeometryInfo *info;
4694   GdkWindowState state;
4695 
4696   gtk_widget_set_mapped (widget, FALSE);
4697   if (window->frame)
4698     gdk_window_withdraw (window->frame);
4699   else
4700     gdk_window_withdraw (widget->window);
4701 
4702   window->configure_request_count = 0;
4703   window->configure_notify_received = FALSE;
4704 
4705   /* on unmap, we reset the default positioning of the window,
4706    * so it's placed again, but we don't reset the default
4707    * size of the window, so it's remembered.
4708    */
4709   window->need_default_position = TRUE;
4710 
4711   info = gtk_window_get_geometry_info (window, FALSE);
4712   if (info)
4713     {
4714       info->initial_pos_set = FALSE;
4715       info->position_constraints_changed = FALSE;
4716     }
4717 
4718   state = gdk_window_get_state (widget->window);
4719   window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4720   window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4721   window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4722   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4723   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4724 }
4725 
4726 static void
gtk_window_realize(GtkWidget * widget)4727 gtk_window_realize (GtkWidget *widget)
4728 {
4729   GtkWindow *window;
4730   GdkWindow *parent_window;
4731   GdkWindowAttr attributes;
4732   gint attributes_mask;
4733   GtkWindowPrivate *priv;
4734 
4735   window = GTK_WINDOW (widget);
4736   priv = GTK_WINDOW_GET_PRIVATE (window);
4737 
4738   /* ensure widget tree is properly size allocated */
4739   if (widget->allocation.x == -1 &&
4740       widget->allocation.y == -1 &&
4741       widget->allocation.width == 1 &&
4742       widget->allocation.height == 1)
4743     {
4744       GtkRequisition requisition;
4745       GtkAllocation allocation = { 0, 0, 200, 200 };
4746 
4747       gtk_widget_size_request (widget, &requisition);
4748       if (requisition.width || requisition.height)
4749 	{
4750 	  /* non-empty window */
4751 	  allocation.width = requisition.width;
4752 	  allocation.height = requisition.height;
4753 	}
4754       gtk_widget_size_allocate (widget, &allocation);
4755 
4756       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4757 
4758       g_return_if_fail (!gtk_widget_get_realized (widget));
4759     }
4760 
4761   gtk_widget_set_realized (widget, TRUE);
4762 
4763   switch (window->type)
4764     {
4765     case GTK_WINDOW_TOPLEVEL:
4766       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4767       break;
4768     case GTK_WINDOW_POPUP:
4769       attributes.window_type = GDK_WINDOW_TEMP;
4770       break;
4771     default:
4772       g_warning (G_STRLOC": Unknown window type %d!", window->type);
4773       break;
4774     }
4775 
4776   attributes.title = window->title;
4777   attributes.wmclass_name = window->wmclass_name;
4778   attributes.wmclass_class = window->wmclass_class;
4779   attributes.wclass = GDK_INPUT_OUTPUT;
4780   attributes.visual = gtk_widget_get_visual (widget);
4781   attributes.colormap = gtk_widget_get_colormap (widget);
4782 
4783   if (window->has_frame)
4784     {
4785       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4786       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4787       attributes.event_mask = (GDK_EXPOSURE_MASK |
4788 			       GDK_KEY_PRESS_MASK |
4789 			       GDK_ENTER_NOTIFY_MASK |
4790 			       GDK_LEAVE_NOTIFY_MASK |
4791 			       GDK_FOCUS_CHANGE_MASK |
4792 			       GDK_STRUCTURE_MASK |
4793 			       GDK_BUTTON_MOTION_MASK |
4794 			       GDK_POINTER_MOTION_HINT_MASK |
4795 			       GDK_BUTTON_PRESS_MASK |
4796 			       GDK_BUTTON_RELEASE_MASK);
4797 
4798       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4799 
4800       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4801 				      &attributes, attributes_mask);
4802 
4803       if (priv->opacity_set)
4804 	gdk_window_set_opacity (window->frame, priv->opacity);
4805 
4806       gdk_window_set_user_data (window->frame, widget);
4807 
4808       attributes.window_type = GDK_WINDOW_CHILD;
4809       attributes.x = window->frame_left;
4810       attributes.y = window->frame_top;
4811 
4812       attributes_mask = GDK_WA_X | GDK_WA_Y;
4813 
4814       parent_window = window->frame;
4815 
4816       g_signal_connect (window,
4817 			"event",
4818 			G_CALLBACK (gtk_window_event),
4819 			NULL);
4820     }
4821   else
4822     {
4823       attributes_mask = 0;
4824       parent_window = gtk_widget_get_root_window (widget);
4825     }
4826 
4827   attributes.width = widget->allocation.width;
4828   attributes.height = widget->allocation.height;
4829   attributes.event_mask = gtk_widget_get_events (widget);
4830   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4831 			    GDK_KEY_PRESS_MASK |
4832 			    GDK_KEY_RELEASE_MASK |
4833 			    GDK_ENTER_NOTIFY_MASK |
4834 			    GDK_LEAVE_NOTIFY_MASK |
4835 			    GDK_FOCUS_CHANGE_MASK |
4836 			    GDK_STRUCTURE_MASK);
4837   attributes.type_hint = priv->type_hint;
4838 
4839   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4840   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4841   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4842 
4843   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4844 
4845   if (!window->has_frame && priv->opacity_set)
4846     gdk_window_set_opacity (widget->window, priv->opacity);
4847 
4848   gdk_window_enable_synchronized_configure (widget->window);
4849 
4850   gdk_window_set_user_data (widget->window, window);
4851 
4852   widget->style = gtk_style_attach (widget->style, widget->window);
4853   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4854   if (window->frame)
4855     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4856 
4857   /* This is a bad hack to set the window background. */
4858   gtk_window_paint (widget, NULL);
4859 
4860   if (window->transient_parent &&
4861       gtk_widget_get_realized (GTK_WIDGET (window->transient_parent)))
4862     gdk_window_set_transient_for (widget->window,
4863 				  GTK_WIDGET (window->transient_parent)->window);
4864 
4865   if (window->wm_role)
4866     gdk_window_set_role (widget->window, window->wm_role);
4867 
4868   if (!window->decorated)
4869     gdk_window_set_decorations (widget->window, 0);
4870 
4871   if (!priv->deletable)
4872     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4873 
4874   if (gtk_window_get_skip_pager_hint (window))
4875     gdk_window_set_skip_pager_hint (widget->window, TRUE);
4876 
4877   if (gtk_window_get_skip_taskbar_hint (window))
4878     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4879 
4880   if (gtk_window_get_accept_focus (window))
4881     gdk_window_set_accept_focus (widget->window, TRUE);
4882   else
4883     gdk_window_set_accept_focus (widget->window, FALSE);
4884 
4885   if (gtk_window_get_focus_on_map (window))
4886     gdk_window_set_focus_on_map (widget->window, TRUE);
4887   else
4888     gdk_window_set_focus_on_map (widget->window, FALSE);
4889 
4890   if (window->modal)
4891     gdk_window_set_modal_hint (widget->window, TRUE);
4892   else
4893     gdk_window_set_modal_hint (widget->window, FALSE);
4894 
4895   if (priv->startup_id)
4896     {
4897 #ifdef GDK_WINDOWING_X11
4898       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4899       if (timestamp != GDK_CURRENT_TIME)
4900         gdk_x11_window_set_user_time (widget->window, timestamp);
4901 #endif
4902       if (!startup_id_is_fake (priv->startup_id))
4903         gdk_window_set_startup_id (widget->window, priv->startup_id);
4904     }
4905 
4906   /* Icons */
4907   gtk_window_realize_icon (window);
4908 }
4909 
4910 static void
gtk_window_unrealize(GtkWidget * widget)4911 gtk_window_unrealize (GtkWidget *widget)
4912 {
4913   GtkWindow *window;
4914   GtkWindowGeometryInfo *info;
4915 
4916   window = GTK_WINDOW (widget);
4917 
4918   /* On unrealize, we reset the size of the window such
4919    * that we will re-apply the default sizing stuff
4920    * next time we show the window.
4921    *
4922    * Default positioning is reset on unmap, instead of unrealize.
4923    */
4924   window->need_default_size = TRUE;
4925   info = gtk_window_get_geometry_info (window, FALSE);
4926   if (info)
4927     {
4928       info->resize_width = -1;
4929       info->resize_height = -1;
4930       info->last.configure_request.x = 0;
4931       info->last.configure_request.y = 0;
4932       info->last.configure_request.width = -1;
4933       info->last.configure_request.height = -1;
4934       /* be sure we reset geom hints on re-realize */
4935       info->last.flags = 0;
4936     }
4937 
4938   if (window->frame)
4939     {
4940       gdk_window_set_user_data (window->frame, NULL);
4941       gdk_window_destroy (window->frame);
4942       window->frame = NULL;
4943     }
4944 
4945   /* Icons */
4946   gtk_window_unrealize_icon (window);
4947 
4948   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4949 }
4950 
4951 static void
gtk_window_size_request(GtkWidget * widget,GtkRequisition * requisition)4952 gtk_window_size_request (GtkWidget      *widget,
4953 			 GtkRequisition *requisition)
4954 {
4955   GtkWindow *window;
4956   GtkBin *bin;
4957 
4958   window = GTK_WINDOW (widget);
4959   bin = GTK_BIN (window);
4960 
4961   requisition->width = GTK_CONTAINER (window)->border_width * 2;
4962   requisition->height = GTK_CONTAINER (window)->border_width * 2;
4963 
4964   if (bin->child && gtk_widget_get_visible (bin->child))
4965     {
4966       GtkRequisition child_requisition;
4967 
4968       gtk_widget_size_request (bin->child, &child_requisition);
4969 
4970       requisition->width += child_requisition.width;
4971       requisition->height += child_requisition.height;
4972     }
4973 }
4974 
4975 static void
gtk_window_size_allocate(GtkWidget * widget,GtkAllocation * allocation)4976 gtk_window_size_allocate (GtkWidget     *widget,
4977 			  GtkAllocation *allocation)
4978 {
4979   GtkWindow *window;
4980   GtkAllocation child_allocation;
4981 
4982   window = GTK_WINDOW (widget);
4983   widget->allocation = *allocation;
4984 
4985   if (window->bin.child && gtk_widget_get_visible (window->bin.child))
4986     {
4987       child_allocation.x = GTK_CONTAINER (window)->border_width;
4988       child_allocation.y = GTK_CONTAINER (window)->border_width;
4989       child_allocation.width =
4990 	MAX (1, (gint)allocation->width - child_allocation.x * 2);
4991       child_allocation.height =
4992 	MAX (1, (gint)allocation->height - child_allocation.y * 2);
4993 
4994       gtk_widget_size_allocate (window->bin.child, &child_allocation);
4995     }
4996 
4997   if (gtk_widget_get_realized (widget) && window->frame)
4998     {
4999       gdk_window_resize (window->frame,
5000 			 allocation->width + window->frame_left + window->frame_right,
5001 			 allocation->height + window->frame_top + window->frame_bottom);
5002     }
5003 }
5004 
5005 static gint
gtk_window_event(GtkWidget * widget,GdkEvent * event)5006 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5007 {
5008   GtkWindow *window;
5009   gboolean return_val;
5010 
5011   window = GTK_WINDOW (widget);
5012 
5013   if (window->frame && (event->any.window == window->frame))
5014     {
5015       if ((event->type != GDK_KEY_PRESS) &&
5016 	  (event->type != GDK_KEY_RELEASE) &&
5017 	  (event->type != GDK_FOCUS_CHANGE))
5018 	{
5019 	  g_signal_stop_emission_by_name (widget, "event");
5020 	  return_val = FALSE;
5021 	  g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5022 	  return TRUE;
5023 	}
5024       else
5025 	{
5026 	  g_object_unref (event->any.window);
5027 	  event->any.window = g_object_ref (widget->window);
5028 	}
5029     }
5030 
5031   return FALSE;
5032 }
5033 
5034 static gboolean
gtk_window_frame_event(GtkWindow * window,GdkEvent * event)5035 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5036 {
5037   GdkEventConfigure *configure_event;
5038   GdkRectangle rect;
5039 
5040   switch (event->type)
5041     {
5042     case GDK_CONFIGURE:
5043       configure_event = (GdkEventConfigure *)event;
5044 
5045       /* Invalidate the decorations */
5046       rect.x = 0;
5047       rect.y = 0;
5048       rect.width = configure_event->width;
5049       rect.height = configure_event->height;
5050 
5051       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
5052 
5053       /* Pass on the (modified) configure event */
5054       configure_event->width -= window->frame_left + window->frame_right;
5055       configure_event->height -= window->frame_top + window->frame_bottom;
5056       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5057       break;
5058     default:
5059       break;
5060     }
5061   return FALSE;
5062 }
5063 
5064 static gint
gtk_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)5065 gtk_window_configure_event (GtkWidget         *widget,
5066 			    GdkEventConfigure *event)
5067 {
5068   GtkWindow *window = GTK_WINDOW (widget);
5069   gboolean expected_reply = window->configure_request_count > 0;
5070 
5071   /* window->configure_request_count incremented for each
5072    * configure request, and decremented to a min of 0 for
5073    * each configure notify.
5074    *
5075    * All it means is that we know we will get at least
5076    * window->configure_request_count more configure notifies.
5077    * We could get more configure notifies than that; some
5078    * of the configure notifies we get may be unrelated to
5079    * the configure requests. But we will get at least
5080    * window->configure_request_count notifies.
5081    */
5082 
5083   if (window->configure_request_count > 0)
5084     {
5085       window->configure_request_count -= 1;
5086       gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5087     }
5088 
5089   /* As an optimization, we avoid a resize when possible.
5090    *
5091    * The only times we can avoid a resize are:
5092    *   - we know only the position changed, not the size
5093    *   - we know we have made more requests and so will get more
5094    *     notifies and can wait to resize when we get them
5095    */
5096 
5097   if (!expected_reply &&
5098       (widget->allocation.width == event->width &&
5099        widget->allocation.height == event->height))
5100     {
5101       gdk_window_configure_finished (widget->window);
5102       return TRUE;
5103     }
5104 
5105   /*
5106    * If we do need to resize, we do that by:
5107    *   - filling in widget->allocation with the new size
5108    *   - setting configure_notify_received to TRUE
5109    *     for use in gtk_window_move_resize()
5110    *   - queueing a resize, leading to invocation of
5111    *     gtk_window_move_resize() in an idle handler
5112    *
5113    */
5114 
5115   window->configure_notify_received = TRUE;
5116 
5117   widget->allocation.width = event->width;
5118   widget->allocation.height = event->height;
5119 
5120   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5121 
5122   return TRUE;
5123 }
5124 
5125 /* the accel_key and accel_mods fields of the key have to be setup
5126  * upon calling this function. it'll then return whether that key
5127  * is at all used as accelerator, and if so will OR in the
5128  * accel_flags member of the key.
5129  */
5130 gboolean
_gtk_window_query_nonaccels(GtkWindow * window,guint accel_key,GdkModifierType accel_mods)5131 _gtk_window_query_nonaccels (GtkWindow      *window,
5132 			     guint           accel_key,
5133 			     GdkModifierType accel_mods)
5134 {
5135   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5136 
5137   /* movement keys are considered locked accels */
5138   if (!accel_mods)
5139     {
5140       static const guint bindings[] = {
5141 	GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5142 	GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5143       };
5144       guint i;
5145 
5146       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5147 	if (bindings[i] == accel_key)
5148 	  return TRUE;
5149     }
5150 
5151   /* mnemonics are considered locked accels */
5152   if (accel_mods == window->mnemonic_modifier)
5153     {
5154       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5155       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5156 	return TRUE;
5157     }
5158 
5159   return FALSE;
5160 }
5161 
5162 /**
5163  * gtk_window_propagate_key_event:
5164  * @window:  a #GtkWindow
5165  * @event:   a #GdkEventKey
5166  *
5167  * Propagate a key press or release event to the focus widget and
5168  * up the focus container chain until a widget handles @event.
5169  * This is normally called by the default ::key_press_event and
5170  * ::key_release_event handlers for toplevel windows,
5171  * however in some cases it may be useful to call this directly when
5172  * overriding the standard key handling for a toplevel window.
5173  *
5174  * Return value: %TRUE if a widget in the focus chain handled the event.
5175  *
5176  * Since: 2.4
5177  */
5178 gboolean
gtk_window_propagate_key_event(GtkWindow * window,GdkEventKey * event)5179 gtk_window_propagate_key_event (GtkWindow        *window,
5180                                 GdkEventKey      *event)
5181 {
5182   gboolean handled = FALSE;
5183   GtkWidget *widget, *focus;
5184 
5185   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5186 
5187   widget = GTK_WIDGET (window);
5188   focus = window->focus_widget;
5189   if (focus)
5190     g_object_ref (focus);
5191 
5192   while (!handled &&
5193          focus && focus != widget &&
5194          gtk_widget_get_toplevel (focus) == widget)
5195     {
5196       GtkWidget *parent;
5197 
5198       if (gtk_widget_is_sensitive (focus))
5199         handled = gtk_widget_event (focus, (GdkEvent*) event);
5200 
5201       parent = focus->parent;
5202       if (parent)
5203         g_object_ref (parent);
5204 
5205       g_object_unref (focus);
5206 
5207       focus = parent;
5208     }
5209 
5210   if (focus)
5211     g_object_unref (focus);
5212 
5213   return handled;
5214 }
5215 
5216 static gint
gtk_window_key_press_event(GtkWidget * widget,GdkEventKey * event)5217 gtk_window_key_press_event (GtkWidget   *widget,
5218 			    GdkEventKey *event)
5219 {
5220   GtkWindow *window = GTK_WINDOW (widget);
5221   gboolean handled = FALSE;
5222 
5223   /* handle mnemonics and accelerators */
5224   if (!handled)
5225     handled = gtk_window_activate_key (window, event);
5226 
5227   /* handle focus widget key events */
5228   if (!handled)
5229     handled = gtk_window_propagate_key_event (window, event);
5230 
5231   /* Chain up, invokes binding set */
5232   if (!handled)
5233     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5234 
5235   return handled;
5236 }
5237 
5238 static gint
gtk_window_key_release_event(GtkWidget * widget,GdkEventKey * event)5239 gtk_window_key_release_event (GtkWidget   *widget,
5240 			      GdkEventKey *event)
5241 {
5242   GtkWindow *window = GTK_WINDOW (widget);
5243   gboolean handled = FALSE;
5244 
5245   /* handle focus widget key events */
5246   if (!handled)
5247     handled = gtk_window_propagate_key_event (window, event);
5248 
5249   /* Chain up, invokes binding set */
5250   if (!handled)
5251     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5252 
5253   return handled;
5254 }
5255 
5256 static void
gtk_window_real_activate_default(GtkWindow * window)5257 gtk_window_real_activate_default (GtkWindow *window)
5258 {
5259   gtk_window_activate_default (window);
5260 }
5261 
5262 static void
gtk_window_real_activate_focus(GtkWindow * window)5263 gtk_window_real_activate_focus (GtkWindow *window)
5264 {
5265   gtk_window_activate_focus (window);
5266 }
5267 
5268 static void
gtk_window_move_focus(GtkWindow * window,GtkDirectionType dir)5269 gtk_window_move_focus (GtkWindow       *window,
5270                        GtkDirectionType dir)
5271 {
5272   gtk_widget_child_focus (GTK_WIDGET (window), dir);
5273 
5274   if (!GTK_CONTAINER (window)->focus_child)
5275     gtk_window_set_focus (window, NULL);
5276 }
5277 
5278 static gint
gtk_window_enter_notify_event(GtkWidget * widget,GdkEventCrossing * event)5279 gtk_window_enter_notify_event (GtkWidget        *widget,
5280 			       GdkEventCrossing *event)
5281 {
5282   return FALSE;
5283 }
5284 
5285 static gint
gtk_window_leave_notify_event(GtkWidget * widget,GdkEventCrossing * event)5286 gtk_window_leave_notify_event (GtkWidget        *widget,
5287 			       GdkEventCrossing *event)
5288 {
5289   return FALSE;
5290 }
5291 
5292 static void
do_focus_change(GtkWidget * widget,gboolean in)5293 do_focus_change (GtkWidget *widget,
5294 		 gboolean   in)
5295 {
5296   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5297 
5298   fevent->focus_change.type = GDK_FOCUS_CHANGE;
5299   fevent->focus_change.window = widget->window;
5300   fevent->focus_change.in = in;
5301   if (widget->window)
5302     g_object_ref (widget->window);
5303 
5304   gtk_widget_send_focus_change (widget, fevent);
5305 
5306   gdk_event_free (fevent);
5307 }
5308 
5309 static gint
gtk_window_focus_in_event(GtkWidget * widget,GdkEventFocus * event)5310 gtk_window_focus_in_event (GtkWidget     *widget,
5311 			   GdkEventFocus *event)
5312 {
5313   GtkWindow *window = GTK_WINDOW (widget);
5314 
5315   /* It appears spurious focus in events can occur when
5316    *  the window is hidden. So we'll just check to see if
5317    *  the window is visible before actually handling the
5318    *  event
5319    */
5320   if (gtk_widget_get_visible (widget))
5321     {
5322       _gtk_window_set_has_toplevel_focus (window, TRUE);
5323       _gtk_window_set_is_active (window, TRUE);
5324     }
5325 
5326   return FALSE;
5327 }
5328 
5329 static gint
gtk_window_focus_out_event(GtkWidget * widget,GdkEventFocus * event)5330 gtk_window_focus_out_event (GtkWidget     *widget,
5331 			    GdkEventFocus *event)
5332 {
5333   GtkWindow *window = GTK_WINDOW (widget);
5334   gboolean auto_mnemonics;
5335 
5336   _gtk_window_set_has_toplevel_focus (window, FALSE);
5337   _gtk_window_set_is_active (window, FALSE);
5338 
5339   /* set the mnemonic-visible property to false */
5340   g_object_get (gtk_widget_get_settings (widget),
5341                 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5342   if (auto_mnemonics)
5343     gtk_window_set_mnemonics_visible (window, FALSE);
5344 
5345   return FALSE;
5346 }
5347 
5348 static GdkAtom atom_rcfiles = GDK_NONE;
5349 static GdkAtom atom_iconthemes = GDK_NONE;
5350 
5351 static void
send_client_message_to_embedded_windows(GtkWidget * widget,GdkAtom message_type)5352 send_client_message_to_embedded_windows (GtkWidget *widget,
5353 					 GdkAtom    message_type)
5354 {
5355   GList *embedded_windows;
5356 
5357   embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5358   if (embedded_windows)
5359     {
5360       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5361       int i;
5362 
5363       for (i = 0; i < 5; i++)
5364 	send_event->client.data.l[i] = 0;
5365       send_event->client.data_format = 32;
5366       send_event->client.message_type = message_type;
5367 
5368       while (embedded_windows)
5369 	{
5370 	  GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5371 	  gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5372 	  embedded_windows = embedded_windows->next;
5373 	}
5374 
5375       gdk_event_free (send_event);
5376     }
5377 }
5378 
5379 static gint
gtk_window_client_event(GtkWidget * widget,GdkEventClient * event)5380 gtk_window_client_event (GtkWidget	*widget,
5381 			 GdkEventClient	*event)
5382 {
5383   if (!atom_rcfiles)
5384     {
5385       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5386       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5387     }
5388 
5389   if (event->message_type == atom_rcfiles)
5390     {
5391       send_client_message_to_embedded_windows (widget, atom_rcfiles);
5392       gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5393     }
5394 
5395   if (event->message_type == atom_iconthemes)
5396     {
5397       send_client_message_to_embedded_windows (widget, atom_iconthemes);
5398       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5399     }
5400 
5401   return FALSE;
5402 }
5403 
5404 static void
gtk_window_check_resize(GtkContainer * container)5405 gtk_window_check_resize (GtkContainer *container)
5406 {
5407   if (gtk_widget_get_visible (GTK_WIDGET (container)))
5408     gtk_window_move_resize (GTK_WINDOW (container));
5409 }
5410 
5411 static gboolean
gtk_window_focus(GtkWidget * widget,GtkDirectionType direction)5412 gtk_window_focus (GtkWidget        *widget,
5413 		  GtkDirectionType  direction)
5414 {
5415   GtkBin *bin;
5416   GtkWindow *window;
5417   GtkContainer *container;
5418   GtkWidget *old_focus_child;
5419   GtkWidget *parent;
5420 
5421   container = GTK_CONTAINER (widget);
5422   window = GTK_WINDOW (widget);
5423   bin = GTK_BIN (widget);
5424 
5425   old_focus_child = container->focus_child;
5426 
5427   /* We need a special implementation here to deal properly with wrapping
5428    * around in the tab chain without the danger of going into an
5429    * infinite loop.
5430    */
5431   if (old_focus_child)
5432     {
5433       if (gtk_widget_child_focus (old_focus_child, direction))
5434 	return TRUE;
5435     }
5436 
5437   if (window->focus_widget)
5438     {
5439       if (direction == GTK_DIR_LEFT ||
5440 	  direction == GTK_DIR_RIGHT ||
5441 	  direction == GTK_DIR_UP ||
5442 	  direction == GTK_DIR_DOWN)
5443 	{
5444 	  return FALSE;
5445 	}
5446 
5447       /* Wrapped off the end, clear the focus setting for the toplpevel */
5448       parent = window->focus_widget->parent;
5449       while (parent)
5450 	{
5451 	  gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5452 	  parent = GTK_WIDGET (parent)->parent;
5453 	}
5454 
5455       gtk_window_set_focus (GTK_WINDOW (container), NULL);
5456     }
5457 
5458   /* Now try to focus the first widget in the window */
5459   if (bin->child)
5460     {
5461       if (gtk_widget_child_focus (bin->child, direction))
5462         return TRUE;
5463     }
5464 
5465   return FALSE;
5466 }
5467 
5468 static void
gtk_window_real_set_focus(GtkWindow * window,GtkWidget * focus)5469 gtk_window_real_set_focus (GtkWindow *window,
5470 			   GtkWidget *focus)
5471 {
5472   GtkWidget *old_focus = window->focus_widget;
5473   gboolean had_default = FALSE;
5474   gboolean focus_had_default = FALSE;
5475   gboolean old_focus_had_default = FALSE;
5476 
5477   if (old_focus)
5478     {
5479       g_object_ref (old_focus);
5480       g_object_freeze_notify (G_OBJECT (old_focus));
5481       old_focus_had_default = gtk_widget_has_default (old_focus);
5482     }
5483   if (focus)
5484     {
5485       g_object_ref (focus);
5486       g_object_freeze_notify (G_OBJECT (focus));
5487       focus_had_default = gtk_widget_has_default (focus);
5488     }
5489 
5490   if (window->default_widget)
5491     had_default = gtk_widget_has_default (window->default_widget);
5492 
5493   if (window->focus_widget)
5494     {
5495       if (gtk_widget_get_receives_default (window->focus_widget) &&
5496 	  (window->focus_widget != window->default_widget))
5497         {
5498           _gtk_widget_set_has_default (window->focus_widget, FALSE);
5499 	  gtk_widget_queue_draw (window->focus_widget);
5500 
5501 	  if (window->default_widget)
5502             _gtk_widget_set_has_default (window->default_widget, TRUE);
5503 	}
5504 
5505       window->focus_widget = NULL;
5506 
5507       if (window->has_focus)
5508 	do_focus_change (old_focus, FALSE);
5509 
5510       g_object_notify (G_OBJECT (old_focus), "is-focus");
5511     }
5512 
5513   /* The above notifications may have set a new focus widget,
5514    * if so, we don't want to override it.
5515    */
5516   if (focus && !window->focus_widget)
5517     {
5518       window->focus_widget = focus;
5519 
5520       if (gtk_widget_get_receives_default (window->focus_widget) &&
5521 	  (window->focus_widget != window->default_widget))
5522 	{
5523 	  if (gtk_widget_get_can_default (window->focus_widget))
5524             _gtk_widget_set_has_default (window->focus_widget, TRUE);
5525 
5526 	  if (window->default_widget)
5527             _gtk_widget_set_has_default (window->default_widget, FALSE);
5528 	}
5529 
5530       if (window->has_focus)
5531 	do_focus_change (window->focus_widget, TRUE);
5532 
5533       g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5534     }
5535 
5536   /* If the default widget changed, a redraw will have been queued
5537    * on the old and new default widgets by gtk_window_set_default(), so
5538    * we only have to worry about the case where it didn't change.
5539    * We'll sometimes queue a draw twice on the new widget but that
5540    * is harmless.
5541    */
5542   if (window->default_widget &&
5543       (had_default != gtk_widget_has_default (window->default_widget)))
5544     gtk_widget_queue_draw (window->default_widget);
5545 
5546   if (old_focus)
5547     {
5548       if (old_focus_had_default != gtk_widget_has_default (old_focus))
5549 	gtk_widget_queue_draw (old_focus);
5550 
5551       g_object_thaw_notify (G_OBJECT (old_focus));
5552       g_object_unref (old_focus);
5553     }
5554   if (focus)
5555     {
5556       if (focus_had_default != gtk_widget_has_default (focus))
5557 	gtk_widget_queue_draw (focus);
5558 
5559       g_object_thaw_notify (G_OBJECT (focus));
5560       g_object_unref (focus);
5561     }
5562 }
5563 
5564 /**
5565  * _gtk_window_unset_focus_and_default:
5566  * @window: a #GtkWindow
5567  * @widget: a widget inside of @window
5568  *
5569  * Checks whether the focus and default widgets of @window are
5570  * @widget or a descendent of @widget, and if so, unset them.
5571  **/
5572 void
_gtk_window_unset_focus_and_default(GtkWindow * window,GtkWidget * widget)5573 _gtk_window_unset_focus_and_default (GtkWindow *window,
5574 				     GtkWidget *widget)
5575 
5576 {
5577   GtkWidget *child;
5578 
5579   g_object_ref (window);
5580   g_object_ref (widget);
5581 
5582   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5583     {
5584       child = window->focus_widget;
5585 
5586       while (child && child != widget)
5587 	child = child->parent;
5588 
5589       if (child == widget)
5590 	gtk_window_set_focus (GTK_WINDOW (window), NULL);
5591     }
5592 
5593   child = window->default_widget;
5594 
5595   while (child && child != widget)
5596     child = child->parent;
5597 
5598   if (child == widget)
5599     gtk_window_set_default (window, NULL);
5600 
5601   g_object_unref (widget);
5602   g_object_unref (window);
5603 }
5604 
5605 /*********************************
5606  * Functions related to resizing *
5607  *********************************/
5608 
5609 /* This function doesn't constrain to geometry hints */
5610 static void
gtk_window_compute_configure_request_size(GtkWindow * window,guint * width,guint * height)5611 gtk_window_compute_configure_request_size (GtkWindow *window,
5612                                            guint     *width,
5613                                            guint     *height)
5614 {
5615   GtkRequisition requisition;
5616   GtkWindowGeometryInfo *info;
5617   GtkWidget *widget;
5618 
5619   /* Preconditions:
5620    *  - we've done a size request
5621    */
5622 
5623   widget = GTK_WIDGET (window);
5624 
5625   info = gtk_window_get_geometry_info (window, FALSE);
5626 
5627   if (window->need_default_size)
5628     {
5629       gtk_widget_get_child_requisition (widget, &requisition);
5630 
5631       /* Default to requisition */
5632       *width = requisition.width;
5633       *height = requisition.height;
5634 
5635       /* If window is empty so requests 0, default to random nonzero size */
5636        if (*width == 0 && *height == 0)
5637          {
5638            *width = 200;
5639            *height = 200;
5640          }
5641 
5642        /* Override requisition with default size */
5643 
5644        if (info)
5645          {
5646 	   gint base_width = 0;
5647 	   gint base_height = 0;
5648 	   gint min_width = 0;
5649 	   gint min_height = 0;
5650 	   gint width_inc = 1;
5651 	   gint height_inc = 1;
5652 
5653 	   if (info->default_is_geometry &&
5654 	       (info->default_width > 0 || info->default_height > 0))
5655 	     {
5656 	       GdkGeometry geometry;
5657 	       guint flags;
5658 
5659 	       gtk_window_compute_hints (window, &geometry, &flags);
5660 
5661 	       if (flags & GDK_HINT_BASE_SIZE)
5662 		 {
5663 		   base_width = geometry.base_width;
5664 		   base_height = geometry.base_height;
5665 		 }
5666 	       if (flags & GDK_HINT_MIN_SIZE)
5667 		 {
5668 		   min_width = geometry.min_width;
5669 		   min_height = geometry.min_height;
5670 		 }
5671 	       if (flags & GDK_HINT_RESIZE_INC)
5672 		 {
5673 		   width_inc = geometry.width_inc;
5674 		   height_inc = geometry.height_inc;
5675 		 }
5676 	     }
5677 
5678 	   if (info->default_width > 0)
5679 	     *width = MAX (info->default_width * width_inc + base_width, min_width);
5680 
5681 	   if (info->default_height > 0)
5682 	     *height = MAX (info->default_height * height_inc + base_height, min_height);
5683          }
5684     }
5685   else
5686     {
5687       /* Default to keeping current size */
5688       *width = widget->allocation.width;
5689       *height = widget->allocation.height;
5690     }
5691 
5692   /* Override any size with gtk_window_resize() values */
5693   if (info)
5694     {
5695       if (info->resize_width > 0)
5696         *width = info->resize_width;
5697 
5698       if (info->resize_height > 0)
5699         *height = info->resize_height;
5700     }
5701 
5702   /* Don't ever request zero width or height, its not supported by
5703      gdk. The size allocation code will round it to 1 anyway but if
5704      we do it then the value returned from this function will is
5705      not comparable to the size allocation read from the GtkWindow. */
5706   *width = MAX (*width, 1);
5707   *height = MAX (*height, 1);
5708 }
5709 
5710 static GtkWindowPosition
get_effective_position(GtkWindow * window)5711 get_effective_position (GtkWindow *window)
5712 {
5713   GtkWindowPosition pos = window->position;
5714 
5715   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5716       (window->transient_parent == NULL ||
5717        !gtk_widget_get_mapped (GTK_WIDGET (window->transient_parent))))
5718     pos = GTK_WIN_POS_NONE;
5719 
5720   return pos;
5721 }
5722 
5723 static int
get_center_monitor_of_window(GtkWindow * window)5724 get_center_monitor_of_window (GtkWindow *window)
5725 {
5726   /* We could try to sort out the relative positions of the monitors and
5727    * stuff, or we could just be losers and assume you have a row
5728    * or column of monitors.
5729    */
5730   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5731 }
5732 
5733 static int
get_monitor_containing_pointer(GtkWindow * window)5734 get_monitor_containing_pointer (GtkWindow *window)
5735 {
5736   gint px, py;
5737   gint monitor_num;
5738   GdkScreen *window_screen;
5739   GdkScreen *pointer_screen;
5740 
5741   window_screen = gtk_window_check_screen (window);
5742   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5743                            &pointer_screen,
5744                            &px, &py, NULL);
5745 
5746   if (pointer_screen == window_screen)
5747     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5748   else
5749     monitor_num = -1;
5750 
5751   return monitor_num;
5752 }
5753 
5754 static void
center_window_on_monitor(GtkWindow * window,gint w,gint h,gint * x,gint * y)5755 center_window_on_monitor (GtkWindow *window,
5756                           gint       w,
5757                           gint       h,
5758                           gint      *x,
5759                           gint      *y)
5760 {
5761   GdkRectangle monitor;
5762   int monitor_num;
5763 
5764   monitor_num = get_monitor_containing_pointer (window);
5765 
5766   if (monitor_num == -1)
5767     monitor_num = get_center_monitor_of_window (window);
5768 
5769   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5770 				   monitor_num, &monitor);
5771 
5772   *x = (monitor.width - w) / 2 + monitor.x;
5773   *y = (monitor.height - h) / 2 + monitor.y;
5774 
5775   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5776    * and WM decorations.
5777    */
5778   if (*x < monitor.x)
5779     *x = monitor.x;
5780   if (*y < monitor.y)
5781     *y = monitor.y;
5782 }
5783 
5784 static void
clamp(gint * base,gint extent,gint clamp_base,gint clamp_extent)5785 clamp (gint *base,
5786        gint  extent,
5787        gint  clamp_base,
5788        gint  clamp_extent)
5789 {
5790   if (extent > clamp_extent)
5791     /* Center */
5792     *base = clamp_base + clamp_extent/2 - extent/2;
5793   else if (*base < clamp_base)
5794     *base = clamp_base;
5795   else if (*base + extent > clamp_base + clamp_extent)
5796     *base = clamp_base + clamp_extent - extent;
5797 }
5798 
5799 static void
clamp_window_to_rectangle(gint * x,gint * y,gint w,gint h,const GdkRectangle * rect)5800 clamp_window_to_rectangle (gint               *x,
5801                            gint               *y,
5802                            gint                w,
5803                            gint                h,
5804                            const GdkRectangle *rect)
5805 {
5806 #ifdef DEBUGGING_OUTPUT
5807   g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", G_STRFUNC, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
5808 #endif
5809 
5810   /* If it is too large, center it. If it fits on the monitor but is
5811    * partially outside, move it to the closest edge. Do this
5812    * separately in x and y directions.
5813    */
5814   clamp (x, w, rect->x, rect->width);
5815   clamp (y, h, rect->y, rect->height);
5816 #ifdef DEBUGGING_OUTPUT
5817   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5818 #endif
5819 }
5820 
5821 
5822 static void
gtk_window_compute_configure_request(GtkWindow * window,GdkRectangle * request,GdkGeometry * geometry,guint * flags)5823 gtk_window_compute_configure_request (GtkWindow    *window,
5824                                       GdkRectangle *request,
5825                                       GdkGeometry  *geometry,
5826                                       guint        *flags)
5827 {
5828   GdkGeometry new_geometry;
5829   guint new_flags;
5830   int w, h;
5831   GtkWidget *widget;
5832   GtkWindowPosition pos;
5833   GtkWidget *parent_widget;
5834   GtkWindowGeometryInfo *info;
5835   GdkScreen *screen;
5836   int x, y;
5837 
5838   widget = GTK_WIDGET (window);
5839 
5840   screen = gtk_window_check_screen (window);
5841 
5842   gtk_widget_size_request (widget, NULL);
5843   gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5844 
5845   gtk_window_compute_hints (window, &new_geometry, &new_flags);
5846   gtk_window_constrain_size (window,
5847                              &new_geometry, new_flags,
5848                              w, h,
5849                              &w, &h);
5850 
5851   parent_widget = (GtkWidget*) window->transient_parent;
5852 
5853   pos = get_effective_position (window);
5854   info = gtk_window_get_geometry_info (window, FALSE);
5855 
5856   /* by default, don't change position requested */
5857   if (info)
5858     {
5859       x = info->last.configure_request.x;
5860       y = info->last.configure_request.y;
5861     }
5862   else
5863     {
5864       x = 0;
5865       y = 0;
5866     }
5867 
5868 
5869   if (window->need_default_position)
5870     {
5871 
5872       /* FIXME this all interrelates with window gravity.
5873        * For most of them I think we want to set GRAVITY_CENTER.
5874        *
5875        * Not sure how to go about that.
5876        */
5877 
5878       switch (pos)
5879         {
5880           /* here we are only handling CENTER_ALWAYS
5881            * as it relates to default positioning,
5882            * where it's equivalent to simply CENTER
5883            */
5884         case GTK_WIN_POS_CENTER_ALWAYS:
5885         case GTK_WIN_POS_CENTER:
5886           center_window_on_monitor (window, w, h, &x, &y);
5887           break;
5888 
5889         case GTK_WIN_POS_CENTER_ON_PARENT:
5890           {
5891             gint monitor_num;
5892             GdkRectangle monitor;
5893             gint ox, oy;
5894 
5895             g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
5896 
5897             if (parent_widget->window != NULL)
5898               monitor_num = gdk_screen_get_monitor_at_window (screen,
5899                                                               parent_widget->window);
5900             else
5901               monitor_num = -1;
5902 
5903             gdk_window_get_origin (parent_widget->window,
5904                                    &ox, &oy);
5905 
5906             x = ox + (parent_widget->allocation.width - w) / 2;
5907             y = oy + (parent_widget->allocation.height - h) / 2;
5908 
5909             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5910              * WM decorations. If parent wasn't on a monitor, just
5911              * give up.
5912              */
5913             if (monitor_num >= 0)
5914               {
5915                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5916                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5917               }
5918           }
5919           break;
5920 
5921         case GTK_WIN_POS_MOUSE:
5922           {
5923             gint screen_width = gdk_screen_get_width (screen);
5924             gint screen_height = gdk_screen_get_height (screen);
5925 	    gint monitor_num;
5926 	    GdkRectangle monitor;
5927             GdkScreen *pointer_screen;
5928             gint px, py;
5929 
5930             gdk_display_get_pointer (gdk_screen_get_display (screen),
5931                                      &pointer_screen,
5932                                      &px, &py, NULL);
5933 
5934             if (pointer_screen == screen)
5935               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5936             else
5937               monitor_num = -1;
5938 
5939             x = px - w / 2;
5940             y = py - h / 2;
5941             x = CLAMP (x, 0, screen_width - w);
5942             y = CLAMP (y, 0, screen_height - h);
5943 
5944             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5945              * WM decorations. Don't try to figure out what's going
5946              * on if the mouse wasn't inside a monitor.
5947              */
5948             if (monitor_num >= 0)
5949               {
5950                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5951                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5952               }
5953           }
5954           break;
5955 
5956         default:
5957           break;
5958         }
5959     } /* if (window->need_default_position) */
5960 
5961   if (window->need_default_position && info &&
5962       info->initial_pos_set)
5963     {
5964       x = info->initial_x;
5965       y = info->initial_y;
5966       gtk_window_constrain_position (window, w, h, &x, &y);
5967     }
5968 
5969   request->x = x;
5970   request->y = y;
5971   request->width = w;
5972   request->height = h;
5973 
5974   if (geometry)
5975     *geometry = new_geometry;
5976   if (flags)
5977     *flags = new_flags;
5978 }
5979 
5980 static void
gtk_window_constrain_position(GtkWindow * window,gint new_width,gint new_height,gint * x,gint * y)5981 gtk_window_constrain_position (GtkWindow    *window,
5982                                gint          new_width,
5983                                gint          new_height,
5984                                gint         *x,
5985                                gint         *y)
5986 {
5987   /* See long comments in gtk_window_move_resize()
5988    * on when it's safe to call this function.
5989    */
5990   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5991     {
5992       gint center_x, center_y;
5993 
5994       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
5995 
5996       *x = center_x;
5997       *y = center_y;
5998     }
5999 }
6000 
6001 static void
gtk_window_move_resize(GtkWindow * window)6002 gtk_window_move_resize (GtkWindow *window)
6003 {
6004   /* Overview:
6005    *
6006    * First we determine whether any information has changed that would
6007    * cause us to revise our last configure request.  If we would send
6008    * a different configure request from last time, then
6009    * configure_request_size_changed = TRUE or
6010    * configure_request_pos_changed = TRUE. configure_request_size_changed
6011    * may be true due to new hints, a gtk_window_resize(), or whatever.
6012    * configure_request_pos_changed may be true due to gtk_window_set_position()
6013    * or gtk_window_move().
6014    *
6015    * If the configure request has changed, we send off a new one.  To
6016    * ensure GTK+ invariants are maintained (resize queue does what it
6017    * should), we go ahead and size_allocate the requested size in this
6018    * function.
6019    *
6020    * If the configure request has not changed, we don't ever resend
6021    * it, because it could mean fighting the user or window manager.
6022    *
6023    *
6024    *   To prepare the configure request, we come up with a base size/pos:
6025    *      - the one from gtk_window_move()/gtk_window_resize()
6026    *      - else default_width, default_height if we haven't ever
6027    *        been mapped
6028    *      - else the size request if we haven't ever been mapped,
6029    *        as a substitute default size
6030    *      - else the current size of the window, as received from
6031    *        configure notifies (i.e. the current allocation)
6032    *
6033    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6034    *   the position request to be centered.
6035    */
6036   GtkWidget *widget;
6037   GtkContainer *container;
6038   GtkWindowGeometryInfo *info;
6039   GdkGeometry new_geometry;
6040   guint new_flags;
6041   GdkRectangle new_request;
6042   gboolean configure_request_size_changed;
6043   gboolean configure_request_pos_changed;
6044   gboolean hints_changed; /* do we need to send these again */
6045   GtkWindowLastGeometryInfo saved_last_info;
6046 
6047   widget = GTK_WIDGET (window);
6048   container = GTK_CONTAINER (widget);
6049   info = gtk_window_get_geometry_info (window, TRUE);
6050 
6051   configure_request_size_changed = FALSE;
6052   configure_request_pos_changed = FALSE;
6053 
6054   gtk_window_compute_configure_request (window, &new_request,
6055                                         &new_geometry, &new_flags);
6056 
6057   /* This check implies the invariant that we never set info->last
6058    * without setting the hints and sending off a configure request.
6059    *
6060    * If we change info->last without sending the request, we may
6061    * miss a request.
6062    */
6063   if (info->last.configure_request.x != new_request.x ||
6064       info->last.configure_request.y != new_request.y)
6065     configure_request_pos_changed = TRUE;
6066 
6067   if ((info->last.configure_request.width != new_request.width ||
6068        info->last.configure_request.height != new_request.height))
6069     configure_request_size_changed = TRUE;
6070 
6071   hints_changed = FALSE;
6072 
6073   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6074 				 &new_geometry, new_flags))
6075     {
6076       hints_changed = TRUE;
6077     }
6078 
6079   /* Position Constraints
6080    * ====================
6081    *
6082    * POS_CENTER_ALWAYS is conceptually a constraint rather than
6083    * a default. The other POS_ values are used only when the
6084    * window is shown, not after that.
6085    *
6086    * However, we can't implement a position constraint as
6087    * "anytime the window size changes, center the window"
6088    * because this may well end up fighting the WM or user.  In
6089    * fact it gets in an infinite loop with at least one WM.
6090    *
6091    * Basically, applications are in no way in a position to
6092    * constrain the position of a window, with one exception:
6093    * override redirect windows. (Really the intended purpose
6094    * of CENTER_ALWAYS anyhow, I would think.)
6095    *
6096    * So the way we implement this "constraint" is to say that when WE
6097    * cause a move or resize, i.e. we make a configure request changing
6098    * window size, we recompute the CENTER_ALWAYS position to reflect
6099    * the new window size, and include it in our request.  Also, if we
6100    * just turned on CENTER_ALWAYS we snap to center with a new
6101    * request.  Otherwise, if we are just NOTIFIED of a move or resize
6102    * done by someone else e.g. the window manager, we do NOT send a
6103    * new configure request.
6104    *
6105    * For override redirect windows, this works fine; all window
6106    * sizes are from our configure requests. For managed windows,
6107    * it is at least semi-sane, though who knows what the
6108    * app author is thinking.
6109    */
6110 
6111   /* This condition should be kept in sync with the condition later on
6112    * that determines whether we send a configure request.  i.e. we
6113    * should do this position constraining anytime we were going to
6114    * send a configure request anyhow, plus when constraints have
6115    * changed.
6116    */
6117   if (configure_request_pos_changed ||
6118       configure_request_size_changed ||
6119       hints_changed ||
6120       info->position_constraints_changed)
6121     {
6122       /* We request the constrained position if:
6123        *  - we were changing position, and need to clamp
6124        *    the change to the constraint
6125        *  - we're changing the size anyway
6126        *  - set_position() was called to toggle CENTER_ALWAYS on
6127        */
6128 
6129       gtk_window_constrain_position (window,
6130                                      new_request.width,
6131                                      new_request.height,
6132                                      &new_request.x,
6133                                      &new_request.y);
6134 
6135       /* Update whether we need to request a move */
6136       if (info->last.configure_request.x != new_request.x ||
6137           info->last.configure_request.y != new_request.y)
6138         configure_request_pos_changed = TRUE;
6139       else
6140         configure_request_pos_changed = FALSE;
6141     }
6142 
6143 #if 0
6144   if (window->type == GTK_WINDOW_TOPLEVEL)
6145     {
6146       int notify_x, notify_y;
6147 
6148       /* this is the position from the last configure notify */
6149       gdk_window_get_position (widget->window, &notify_x, &notify_y);
6150 
6151       g_message ("--- %s ---\n"
6152 		 "last  : %d,%d\t%d x %d\n"
6153 		 "this  : %d,%d\t%d x %d\n"
6154 		 "alloc : %d,%d\t%d x %d\n"
6155 		 "req   :      \t%d x %d\n"
6156 		 "resize:      \t%d x %d\n"
6157 		 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6158 		 "configure_notify_received: %d\n"
6159 		 "configure_request_count: %d\n"
6160 		 "position_constraints_changed: %d\n",
6161 		 window->title ? window->title : "(no title)",
6162 		 info->last.configure_request.x,
6163 		 info->last.configure_request.y,
6164 		 info->last.configure_request.width,
6165 		 info->last.configure_request.height,
6166 		 new_request.x,
6167 		 new_request.y,
6168 		 new_request.width,
6169 		 new_request.height,
6170 		 notify_x, notify_y,
6171 		 widget->allocation.width,
6172 		 widget->allocation.height,
6173 		 widget->requisition.width,
6174 		 widget->requisition.height,
6175 		 info->resize_width,
6176 		 info->resize_height,
6177 		 configure_request_pos_changed,
6178 		 configure_request_size_changed,
6179 		 hints_changed,
6180 		 window->configure_notify_received,
6181 		 window->configure_request_count,
6182 		 info->position_constraints_changed);
6183     }
6184 #endif
6185 
6186   saved_last_info = info->last;
6187   info->last.geometry = new_geometry;
6188   info->last.flags = new_flags;
6189   info->last.configure_request = new_request;
6190 
6191   /* need to set PPosition so the WM will look at our position,
6192    * but we don't want to count PPosition coming and going as a hints
6193    * change for future iterations. So we saved info->last prior to
6194    * this.
6195    */
6196 
6197   /* Also, if the initial position was explicitly set, then we always
6198    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6199    * work.
6200    */
6201 
6202   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6203    * this is an initial map
6204    */
6205 
6206   if ((configure_request_pos_changed ||
6207        info->initial_pos_set ||
6208        (window->need_default_position &&
6209         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6210       (new_flags & GDK_HINT_POS) == 0)
6211     {
6212       new_flags |= GDK_HINT_POS;
6213       hints_changed = TRUE;
6214     }
6215 
6216   /* Set hints if necessary
6217    */
6218   if (hints_changed)
6219     gdk_window_set_geometry_hints (widget->window,
6220 				   &new_geometry,
6221 				   new_flags);
6222 
6223   /* handle resizing/moving and widget tree allocation
6224    */
6225   if (window->configure_notify_received)
6226     {
6227       GtkAllocation allocation;
6228 
6229       /* If we have received a configure event since
6230        * the last time in this function, we need to
6231        * accept our new size and size_allocate child widgets.
6232        * (see gtk_window_configure_event() for more details).
6233        *
6234        * 1 or more configure notifies may have been received.
6235        * Also, configure_notify_received will only be TRUE
6236        * if all expected configure notifies have been received
6237        * (one per configure request), as an optimization.
6238        *
6239        */
6240       window->configure_notify_received = FALSE;
6241 
6242       /* gtk_window_configure_event() filled in widget->allocation */
6243       allocation = widget->allocation;
6244       gtk_widget_size_allocate (widget, &allocation);
6245 
6246       gdk_window_process_updates (widget->window, TRUE);
6247 
6248       gdk_window_configure_finished (widget->window);
6249 
6250       /* If the configure request changed, it means that
6251        * we either:
6252        *   1) coincidentally changed hints or widget properties
6253        *      impacting the configure request before getting
6254        *      a configure notify, or
6255        *   2) some broken widget is changing its size request
6256        *      during size allocation, resulting in
6257        *      a false appearance of changed configure request.
6258        *
6259        * For 1), we could just go ahead and ask for the
6260        * new size right now, but doing that for 2)
6261        * might well be fighting the user (and can even
6262        * trigger a loop). Since we really don't want to
6263        * do that, we requeue a resize in hopes that
6264        * by the time it gets handled, the child has seen
6265        * the light and is willing to go along with the
6266        * new size. (this happens for the zvt widget, since
6267        * the size_allocate() above will have stored the
6268        * requisition corresponding to the new size in the
6269        * zvt widget)
6270        *
6271        * This doesn't buy us anything for 1), but it shouldn't
6272        * hurt us too badly, since it is what would have
6273        * happened if we had gotten the configure event before
6274        * the new size had been set.
6275        */
6276 
6277       if (configure_request_size_changed ||
6278           configure_request_pos_changed)
6279         {
6280           /* Don't change the recorded last info after all, because we
6281            * haven't actually updated to the new info yet - we decided
6282            * to postpone our configure request until later.
6283            */
6284 	  info->last = saved_last_info;
6285 
6286 	  gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6287 	}
6288 
6289       return;			/* Bail out, we didn't really process the move/resize */
6290     }
6291   else if ((configure_request_size_changed || hints_changed) &&
6292 	   (widget->allocation.width != new_request.width ||
6293 	    widget->allocation.height != new_request.height))
6294 
6295     {
6296       /* We are in one of the following situations:
6297        * A. configure_request_size_changed
6298        *    our requisition has changed and we need a different window size,
6299        *    so we request it from the window manager.
6300        * B. !configure_request_size_changed && hints_changed
6301        *    the window manager rejects our size, but we have just changed the
6302        *    window manager hints, so there's a chance our request will
6303        *    be honoured this time, so we try again.
6304        *
6305        * However, if the new requisition is the same as the current allocation,
6306        * we don't request it again, since we won't get a ConfigureNotify back from
6307        * the window manager unless it decides to change our requisition. If
6308        * we don't get the ConfigureNotify back, the resize queue will never be run.
6309        */
6310 
6311       /* Now send the configure request */
6312       if (configure_request_pos_changed)
6313 	{
6314 	  if (window->frame)
6315 	    {
6316 	      gdk_window_move_resize (window->frame,
6317 				      new_request.x - window->frame_left,
6318                                       new_request.y - window->frame_top,
6319 				      new_request.width + window->frame_left + window->frame_right,
6320 				      new_request.height + window->frame_top + window->frame_bottom);
6321 	      gdk_window_resize (widget->window,
6322                                  new_request.width, new_request.height);
6323 	    }
6324 	  else
6325 	    gdk_window_move_resize (widget->window,
6326 				    new_request.x, new_request.y,
6327 				    new_request.width, new_request.height);
6328 	}
6329       else  /* only size changed */
6330 	{
6331 	  if (window->frame)
6332 	    gdk_window_resize (window->frame,
6333 			       new_request.width + window->frame_left + window->frame_right,
6334 			       new_request.height + window->frame_top + window->frame_bottom);
6335 	  gdk_window_resize (widget->window,
6336 			     new_request.width, new_request.height);
6337 	}
6338 
6339       if (window->type == GTK_WINDOW_POPUP)
6340         {
6341 	  GtkAllocation allocation;
6342 
6343 	  /* Directly size allocate for override redirect (popup) windows. */
6344           allocation.x = 0;
6345 	  allocation.y = 0;
6346 	  allocation.width = new_request.width;
6347 	  allocation.height = new_request.height;
6348 
6349 	  gtk_widget_size_allocate (widget, &allocation);
6350 
6351 	  gdk_window_process_updates (widget->window, TRUE);
6352 
6353 	  if (container->resize_mode == GTK_RESIZE_QUEUE)
6354 	    gtk_widget_queue_draw (widget);
6355 	}
6356       else
6357         {
6358 	  /* Increment the number of have-not-yet-received-notify requests */
6359 	  window->configure_request_count += 1;
6360 	  gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6361 
6362 	  /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6363 	   * configure event in response to our resizing request.
6364 	   * the configure event will cause a new resize with
6365 	   * ->configure_notify_received=TRUE.
6366 	   * until then, we want to
6367 	   * - discard expose events
6368 	   * - coalesce resizes for our children
6369 	   * - defer any window resizes until the configure event arrived
6370 	   * to achieve this, we queue a resize for the window, but remove its
6371 	   * resizing handler, so resizing will not be handled from the next
6372 	   * idle handler but when the configure event arrives.
6373 	   *
6374 	   * FIXME: we should also dequeue the pending redraws here, since
6375 	   * we handle those ourselves upon ->configure_notify_received==TRUE.
6376 	   */
6377 	  if (container->resize_mode == GTK_RESIZE_QUEUE)
6378 	    {
6379 	      gtk_widget_queue_resize_no_redraw (widget);
6380 	      _gtk_container_dequeue_resize_handler (container);
6381 	    }
6382 	}
6383     }
6384   else
6385     {
6386       /* Handle any position changes.
6387        */
6388       if (configure_request_pos_changed)
6389 	{
6390 	  if (window->frame)
6391 	    {
6392 	      gdk_window_move (window->frame,
6393 			       new_request.x - window->frame_left,
6394 			       new_request.y - window->frame_top);
6395 	    }
6396 	  else
6397 	    gdk_window_move (widget->window,
6398 			     new_request.x, new_request.y);
6399 	}
6400 
6401       /* And run the resize queue.
6402        */
6403       gtk_container_resize_children (container);
6404     }
6405 
6406   /* We have now processed a move/resize since the last position
6407    * constraint change, setting of the initial position, or resize.
6408    * (Not resetting these flags here can lead to infinite loops for
6409    * GTK_RESIZE_IMMEDIATE containers)
6410    */
6411   info->position_constraints_changed = FALSE;
6412   info->initial_pos_set = FALSE;
6413   info->resize_width = -1;
6414   info->resize_height = -1;
6415 }
6416 
6417 /* Compare two sets of Geometry hints for equality.
6418  */
6419 static gboolean
gtk_window_compare_hints(GdkGeometry * geometry_a,guint flags_a,GdkGeometry * geometry_b,guint flags_b)6420 gtk_window_compare_hints (GdkGeometry *geometry_a,
6421 			  guint        flags_a,
6422 			  GdkGeometry *geometry_b,
6423 			  guint        flags_b)
6424 {
6425   if (flags_a != flags_b)
6426     return FALSE;
6427 
6428   if ((flags_a & GDK_HINT_MIN_SIZE) &&
6429       (geometry_a->min_width != geometry_b->min_width ||
6430        geometry_a->min_height != geometry_b->min_height))
6431     return FALSE;
6432 
6433   if ((flags_a & GDK_HINT_MAX_SIZE) &&
6434       (geometry_a->max_width != geometry_b->max_width ||
6435        geometry_a->max_height != geometry_b->max_height))
6436     return FALSE;
6437 
6438   if ((flags_a & GDK_HINT_BASE_SIZE) &&
6439       (geometry_a->base_width != geometry_b->base_width ||
6440        geometry_a->base_height != geometry_b->base_height))
6441     return FALSE;
6442 
6443   if ((flags_a & GDK_HINT_ASPECT) &&
6444       (geometry_a->min_aspect != geometry_b->min_aspect ||
6445        geometry_a->max_aspect != geometry_b->max_aspect))
6446     return FALSE;
6447 
6448   if ((flags_a & GDK_HINT_RESIZE_INC) &&
6449       (geometry_a->width_inc != geometry_b->width_inc ||
6450        geometry_a->height_inc != geometry_b->height_inc))
6451     return FALSE;
6452 
6453   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6454       geometry_a->win_gravity != geometry_b->win_gravity)
6455     return FALSE;
6456 
6457   return TRUE;
6458 }
6459 
6460 void
_gtk_window_constrain_size(GtkWindow * window,gint width,gint height,gint * new_width,gint * new_height)6461 _gtk_window_constrain_size (GtkWindow   *window,
6462 			    gint         width,
6463 			    gint         height,
6464 			    gint        *new_width,
6465 			    gint        *new_height)
6466 {
6467   GtkWindowGeometryInfo *info;
6468 
6469   g_return_if_fail (GTK_IS_WINDOW (window));
6470 
6471   info = window->geometry_info;
6472   if (info)
6473     {
6474       GdkWindowHints flags = info->last.flags;
6475       GdkGeometry *geometry = &info->last.geometry;
6476 
6477       gtk_window_constrain_size (window,
6478 				 geometry,
6479 				 flags,
6480 				 width,
6481 				 height,
6482 				 new_width,
6483 				 new_height);
6484     }
6485 }
6486 
6487 static void
gtk_window_constrain_size(GtkWindow * window,GdkGeometry * geometry,guint flags,gint width,gint height,gint * new_width,gint * new_height)6488 gtk_window_constrain_size (GtkWindow   *window,
6489 			   GdkGeometry *geometry,
6490 			   guint        flags,
6491 			   gint         width,
6492 			   gint         height,
6493 			   gint        *new_width,
6494 			   gint        *new_height)
6495 {
6496   gdk_window_constrain_size (geometry, flags, width, height,
6497                              new_width, new_height);
6498 }
6499 
6500 /* Compute the set of geometry hints and flags for a window
6501  * based on the application set geometry, and requisiition
6502  * of the window. gtk_widget_size_request() must have been
6503  * called first.
6504  */
6505 static void
gtk_window_compute_hints(GtkWindow * window,GdkGeometry * new_geometry,guint * new_flags)6506 gtk_window_compute_hints (GtkWindow   *window,
6507 			  GdkGeometry *new_geometry,
6508 			  guint       *new_flags)
6509 {
6510   GtkWidget *widget;
6511   gint extra_width = 0;
6512   gint extra_height = 0;
6513   GtkWindowGeometryInfo *geometry_info;
6514   GtkRequisition requisition;
6515 
6516   widget = GTK_WIDGET (window);
6517 
6518   gtk_widget_get_child_requisition (widget, &requisition);
6519   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6520 
6521   if (geometry_info)
6522     {
6523       *new_flags = geometry_info->mask;
6524       *new_geometry = geometry_info->geometry;
6525     }
6526   else
6527     {
6528       *new_flags = 0;
6529     }
6530 
6531   if (geometry_info && geometry_info->widget)
6532     {
6533       GtkRequisition child_requisition;
6534 
6535       /* FIXME: This really isn't right. It gets the min size wrong and forces
6536        * callers to do horrible hacks like set a huge usize on the child requisition
6537        * to get the base size right. We really want to find the answers to:
6538        *
6539        *  - If the geometry widget was infinitely big, how much extra space
6540        *    would be needed for the stuff around it.
6541        *
6542        *  - If the geometry widget was infinitely small, how big would the
6543        *    window still have to be.
6544        *
6545        * Finding these answers would be a bit of a mess here. (Bug #68668)
6546        */
6547       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6548 
6549       extra_width = widget->requisition.width - child_requisition.width;
6550       extra_height = widget->requisition.height - child_requisition.height;
6551     }
6552 
6553   /* We don't want to set GDK_HINT_POS in here, we just set it
6554    * in gtk_window_move_resize() when we want the position
6555    * honored.
6556    */
6557 
6558   if (*new_flags & GDK_HINT_BASE_SIZE)
6559     {
6560       new_geometry->base_width += extra_width;
6561       new_geometry->base_height += extra_height;
6562     }
6563   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6564 	   (*new_flags & GDK_HINT_RESIZE_INC) &&
6565 	   ((extra_width != 0) || (extra_height != 0)))
6566     {
6567       *new_flags |= GDK_HINT_BASE_SIZE;
6568 
6569       new_geometry->base_width = extra_width;
6570       new_geometry->base_height = extra_height;
6571     }
6572 
6573   if (*new_flags & GDK_HINT_MIN_SIZE)
6574     {
6575       if (new_geometry->min_width < 0)
6576 	new_geometry->min_width = requisition.width;
6577       else
6578         new_geometry->min_width += extra_width;
6579 
6580       if (new_geometry->min_height < 0)
6581 	new_geometry->min_height = requisition.height;
6582       else
6583 	new_geometry->min_height += extra_height;
6584     }
6585   else if (!window->allow_shrink)
6586     {
6587       *new_flags |= GDK_HINT_MIN_SIZE;
6588 
6589       new_geometry->min_width = requisition.width;
6590       new_geometry->min_height = requisition.height;
6591     }
6592 
6593   if (*new_flags & GDK_HINT_MAX_SIZE)
6594     {
6595       if (new_geometry->max_width < 0)
6596 	new_geometry->max_width = requisition.width;
6597       else
6598 	new_geometry->max_width += extra_width;
6599 
6600       if (new_geometry->max_height < 0)
6601 	new_geometry->max_height = requisition.height;
6602       else
6603 	new_geometry->max_height += extra_height;
6604     }
6605   else if (!window->allow_grow)
6606     {
6607       *new_flags |= GDK_HINT_MAX_SIZE;
6608 
6609       new_geometry->max_width = requisition.width;
6610       new_geometry->max_height = requisition.height;
6611     }
6612 
6613   *new_flags |= GDK_HINT_WIN_GRAVITY;
6614   new_geometry->win_gravity = window->gravity;
6615 }
6616 
6617 /***********************
6618  * Redrawing functions *
6619  ***********************/
6620 
6621 static void
gtk_window_paint(GtkWidget * widget,GdkRectangle * area)6622 gtk_window_paint (GtkWidget     *widget,
6623 		  GdkRectangle *area)
6624 {
6625   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6626 		      GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6627 }
6628 
6629 static gint
gtk_window_expose(GtkWidget * widget,GdkEventExpose * event)6630 gtk_window_expose (GtkWidget      *widget,
6631 		   GdkEventExpose *event)
6632 {
6633   if (!gtk_widget_get_app_paintable (widget))
6634     gtk_window_paint (widget, &event->area);
6635 
6636   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6637     return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6638 
6639   return FALSE;
6640 }
6641 
6642 /**
6643  * gtk_window_set_has_frame:
6644  * @window: a #GtkWindow
6645  * @setting: a boolean
6646  *
6647  * (Note: this is a special-purpose function for the framebuffer port,
6648  *  that causes GTK+ to draw its own window border. For most applications,
6649  *  you want gtk_window_set_decorated() instead, which tells the window
6650  *  manager whether to draw the window border.)
6651  *
6652  * If this function is called on a window with setting of %TRUE, before
6653  * it is realized or showed, it will have a "frame" window around
6654  * @window->window, accessible in @window->frame. Using the signal
6655  * frame_event you can receive all events targeted at the frame.
6656  *
6657  * This function is used by the linux-fb port to implement managed
6658  * windows, but it could conceivably be used by X-programs that
6659  * want to do their own window decorations.
6660  *
6661  * Deprecated: 2.24: This function will be removed in GTK+ 3
6662  **/
6663 void
gtk_window_set_has_frame(GtkWindow * window,gboolean setting)6664 gtk_window_set_has_frame (GtkWindow *window,
6665 			  gboolean   setting)
6666 {
6667   g_return_if_fail (GTK_IS_WINDOW (window));
6668   g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
6669 
6670   window->has_frame = setting != FALSE;
6671 }
6672 
6673 /**
6674  * gtk_window_get_has_frame:
6675  * @window: a #GtkWindow
6676  *
6677  * Accessor for whether the window has a frame window exterior to
6678  * @window->window. Gets the value set by gtk_window_set_has_frame ().
6679  *
6680  * Return value: %TRUE if a frame has been added to the window
6681  *   via gtk_window_set_has_frame().
6682  *
6683  * Deprecated: 2.24: This function will be removed in GTK+ 3
6684  **/
6685 gboolean
gtk_window_get_has_frame(GtkWindow * window)6686 gtk_window_get_has_frame (GtkWindow *window)
6687 {
6688   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6689 
6690   return window->has_frame;
6691 }
6692 
6693 /**
6694  * gtk_window_set_frame_dimensions:
6695  * @window: a #GtkWindow that has a frame
6696  * @left: The width of the left border
6697  * @top: The height of the top border
6698  * @right: The width of the right border
6699  * @bottom: The height of the bottom border
6700  *
6701  * (Note: this is a special-purpose function intended for the framebuffer
6702  *  port; see gtk_window_set_has_frame(). It will have no effect on the
6703  *  window border drawn by the window manager, which is the normal
6704  *  case when using the X Window system.)
6705  *
6706  * For windows with frames (see gtk_window_set_has_frame()) this function
6707  * can be used to change the size of the frame border.
6708  *
6709  * Deprecated: 2.24: This function will be removed in GTK+ 3
6710  **/
6711 void
gtk_window_set_frame_dimensions(GtkWindow * window,gint left,gint top,gint right,gint bottom)6712 gtk_window_set_frame_dimensions (GtkWindow *window,
6713 				 gint       left,
6714 				 gint       top,
6715 				 gint       right,
6716 				 gint       bottom)
6717 {
6718   GtkWidget *widget;
6719 
6720   g_return_if_fail (GTK_IS_WINDOW (window));
6721 
6722   widget = GTK_WIDGET (window);
6723 
6724   if (window->frame_left == left &&
6725       window->frame_top == top &&
6726       window->frame_right == right &&
6727       window->frame_bottom == bottom)
6728     return;
6729 
6730   window->frame_left = left;
6731   window->frame_top = top;
6732   window->frame_right = right;
6733   window->frame_bottom = bottom;
6734 
6735   if (gtk_widget_get_realized (widget) && window->frame)
6736     {
6737       gint width = widget->allocation.width + left + right;
6738       gint height = widget->allocation.height + top + bottom;
6739       gdk_window_resize (window->frame, width, height);
6740       gtk_decorated_window_move_resize_window (window,
6741 					       left, top,
6742 					       widget->allocation.width,
6743 					       widget->allocation.height);
6744     }
6745 }
6746 
6747 /**
6748  * gtk_window_present:
6749  * @window: a #GtkWindow
6750  *
6751  * Presents a window to the user. This may mean raising the window
6752  * in the stacking order, deiconifying it, moving it to the current
6753  * desktop, and/or giving it the keyboard focus, possibly dependent
6754  * on the user's platform, window manager, and preferences.
6755  *
6756  * If @window is hidden, this function calls gtk_widget_show()
6757  * as well.
6758  *
6759  * This function should be used when the user tries to open a window
6760  * that's already open. Say for example the preferences dialog is
6761  * currently open, and the user chooses Preferences from the menu
6762  * a second time; use gtk_window_present() to move the already-open dialog
6763  * where the user can see it.
6764  *
6765  * If you are calling this function in response to a user interaction,
6766  * it is preferable to use gtk_window_present_with_time().
6767  *
6768  **/
6769 void
gtk_window_present(GtkWindow * window)6770 gtk_window_present (GtkWindow *window)
6771 {
6772   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6773 }
6774 
6775 /**
6776  * gtk_window_present_with_time:
6777  * @window: a #GtkWindow
6778  * @timestamp: the timestamp of the user interaction (typically a
6779  *   button or key press event) which triggered this call
6780  *
6781  * Presents a window to the user in response to a user interaction.
6782  * If you need to present a window without a timestamp, use
6783  * gtk_window_present(). See gtk_window_present() for details.
6784  *
6785  * Since: 2.8
6786  **/
6787 void
gtk_window_present_with_time(GtkWindow * window,guint32 timestamp)6788 gtk_window_present_with_time (GtkWindow *window,
6789 			      guint32    timestamp)
6790 {
6791   GtkWidget *widget;
6792 
6793   g_return_if_fail (GTK_IS_WINDOW (window));
6794 
6795   widget = GTK_WIDGET (window);
6796 
6797   if (gtk_widget_get_visible (widget))
6798     {
6799       g_assert (widget->window != NULL);
6800 
6801       gdk_window_show (widget->window);
6802 
6803       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6804       if (timestamp == GDK_CURRENT_TIME)
6805         {
6806 #ifdef GDK_WINDOWING_X11
6807           GdkDisplay *display;
6808 
6809           display = gtk_widget_get_display (GTK_WIDGET (window));
6810           timestamp = gdk_x11_display_get_user_time (display);
6811 #else
6812           timestamp = gtk_get_current_event_time ();
6813 #endif
6814         }
6815 
6816       gdk_window_focus (widget->window, timestamp);
6817     }
6818   else
6819     {
6820       gtk_widget_show (widget);
6821     }
6822 }
6823 
6824 /**
6825  * gtk_window_iconify:
6826  * @window: a #GtkWindow
6827  *
6828  * Asks to iconify (i.e. minimize) the specified @window. Note that
6829  * you shouldn't assume the window is definitely iconified afterward,
6830  * because other entities (e.g. the user or <link
6831  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6832  * again, or there may not be a window manager in which case
6833  * iconification isn't possible, etc. But normally the window will end
6834  * up iconified. Just don't write code that crashes if not.
6835  *
6836  * It's permitted to call this function before showing a window,
6837  * in which case the window will be iconified before it ever appears
6838  * onscreen.
6839  *
6840  * You can track iconification via the "window-state-event" signal
6841  * on #GtkWidget.
6842  *
6843  **/
6844 void
gtk_window_iconify(GtkWindow * window)6845 gtk_window_iconify (GtkWindow *window)
6846 {
6847   GtkWidget *widget;
6848   GdkWindow *toplevel;
6849 
6850   g_return_if_fail (GTK_IS_WINDOW (window));
6851 
6852   widget = GTK_WIDGET (window);
6853 
6854   window->iconify_initially = TRUE;
6855 
6856   if (window->frame)
6857     toplevel = window->frame;
6858   else
6859     toplevel = widget->window;
6860 
6861   if (toplevel != NULL)
6862     gdk_window_iconify (toplevel);
6863 }
6864 
6865 /**
6866  * gtk_window_deiconify:
6867  * @window: a #GtkWindow
6868  *
6869  * Asks to deiconify (i.e. unminimize) the specified @window. Note
6870  * that you shouldn't assume the window is definitely deiconified
6871  * afterward, because other entities (e.g. the user or <link
6872  * linkend="gtk-X11-arch">window manager</link>) could iconify it
6873  * again before your code which assumes deiconification gets to run.
6874  *
6875  * You can track iconification via the "window-state-event" signal
6876  * on #GtkWidget.
6877  **/
6878 void
gtk_window_deiconify(GtkWindow * window)6879 gtk_window_deiconify (GtkWindow *window)
6880 {
6881   GtkWidget *widget;
6882   GdkWindow *toplevel;
6883 
6884   g_return_if_fail (GTK_IS_WINDOW (window));
6885 
6886   widget = GTK_WIDGET (window);
6887 
6888   window->iconify_initially = FALSE;
6889 
6890   if (window->frame)
6891     toplevel = window->frame;
6892   else
6893     toplevel = widget->window;
6894 
6895   if (toplevel != NULL)
6896     gdk_window_deiconify (toplevel);
6897 }
6898 
6899 /**
6900  * gtk_window_stick:
6901  * @window: a #GtkWindow
6902  *
6903  * Asks to stick @window, which means that it will appear on all user
6904  * desktops. Note that you shouldn't assume the window is definitely
6905  * stuck afterward, because other entities (e.g. the user or <link
6906  * linkend="gtk-X11-arch">window manager</link>) could unstick it
6907  * again, and some window managers do not support sticking
6908  * windows. But normally the window will end up stuck. Just don't
6909  * write code that crashes if not.
6910  *
6911  * It's permitted to call this function before showing a window.
6912  *
6913  * You can track stickiness via the "window-state-event" signal
6914  * on #GtkWidget.
6915  *
6916  **/
6917 void
gtk_window_stick(GtkWindow * window)6918 gtk_window_stick (GtkWindow *window)
6919 {
6920   GtkWidget *widget;
6921   GdkWindow *toplevel;
6922 
6923   g_return_if_fail (GTK_IS_WINDOW (window));
6924 
6925   widget = GTK_WIDGET (window);
6926 
6927   window->stick_initially = TRUE;
6928 
6929   if (window->frame)
6930     toplevel = window->frame;
6931   else
6932     toplevel = widget->window;
6933 
6934   if (toplevel != NULL)
6935     gdk_window_stick (toplevel);
6936 }
6937 
6938 /**
6939  * gtk_window_unstick:
6940  * @window: a #GtkWindow
6941  *
6942  * Asks to unstick @window, which means that it will appear on only
6943  * one of the user's desktops. Note that you shouldn't assume the
6944  * window is definitely unstuck afterward, because other entities
6945  * (e.g. the user or <link linkend="gtk-X11-arch">window
6946  * manager</link>) could stick it again. But normally the window will
6947  * end up stuck. Just don't write code that crashes if not.
6948  *
6949  * You can track stickiness via the "window-state-event" signal
6950  * on #GtkWidget.
6951  *
6952  **/
6953 void
gtk_window_unstick(GtkWindow * window)6954 gtk_window_unstick (GtkWindow *window)
6955 {
6956   GtkWidget *widget;
6957   GdkWindow *toplevel;
6958 
6959   g_return_if_fail (GTK_IS_WINDOW (window));
6960 
6961   widget = GTK_WIDGET (window);
6962 
6963   window->stick_initially = FALSE;
6964 
6965   if (window->frame)
6966     toplevel = window->frame;
6967   else
6968     toplevel = widget->window;
6969 
6970   if (toplevel != NULL)
6971     gdk_window_unstick (toplevel);
6972 }
6973 
6974 /**
6975  * gtk_window_maximize:
6976  * @window: a #GtkWindow
6977  *
6978  * Asks to maximize @window, so that it becomes full-screen. Note that
6979  * you shouldn't assume the window is definitely maximized afterward,
6980  * because other entities (e.g. the user or <link
6981  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6982  * again, and not all window managers support maximization. But
6983  * normally the window will end up maximized. Just don't write code
6984  * that crashes if not.
6985  *
6986  * It's permitted to call this function before showing a window,
6987  * in which case the window will be maximized when it appears onscreen
6988  * initially.
6989  *
6990  * You can track maximization via the "window-state-event" signal
6991  * on #GtkWidget.
6992  *
6993  **/
6994 void
gtk_window_maximize(GtkWindow * window)6995 gtk_window_maximize (GtkWindow *window)
6996 {
6997   GtkWidget *widget;
6998   GdkWindow *toplevel;
6999 
7000   g_return_if_fail (GTK_IS_WINDOW (window));
7001 
7002   widget = GTK_WIDGET (window);
7003 
7004   window->maximize_initially = TRUE;
7005 
7006   if (window->frame)
7007     toplevel = window->frame;
7008   else
7009     toplevel = widget->window;
7010 
7011   if (toplevel != NULL)
7012     gdk_window_maximize (toplevel);
7013 }
7014 
7015 /**
7016  * gtk_window_unmaximize:
7017  * @window: a #GtkWindow
7018  *
7019  * Asks to unmaximize @window. Note that you shouldn't assume the
7020  * window is definitely unmaximized afterward, because other entities
7021  * (e.g. the user or <link linkend="gtk-X11-arch">window
7022  * manager</link>) could maximize it again, and not all window
7023  * managers honor requests to unmaximize. But normally the window will
7024  * end up unmaximized. Just don't write code that crashes if not.
7025  *
7026  * You can track maximization via the "window-state-event" signal
7027  * on #GtkWidget.
7028  *
7029  **/
7030 void
gtk_window_unmaximize(GtkWindow * window)7031 gtk_window_unmaximize (GtkWindow *window)
7032 {
7033   GtkWidget *widget;
7034   GdkWindow *toplevel;
7035 
7036   g_return_if_fail (GTK_IS_WINDOW (window));
7037 
7038   widget = GTK_WIDGET (window);
7039 
7040   window->maximize_initially = FALSE;
7041 
7042   if (window->frame)
7043     toplevel = window->frame;
7044   else
7045     toplevel = widget->window;
7046 
7047   if (toplevel != NULL)
7048     gdk_window_unmaximize (toplevel);
7049 }
7050 
7051 /**
7052  * gtk_window_fullscreen:
7053  * @window: a #GtkWindow
7054  *
7055  * Asks to place @window in the fullscreen state. Note that you
7056  * shouldn't assume the window is definitely full screen afterward,
7057  * because other entities (e.g. the user or <link
7058  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7059  * again, and not all window managers honor requests to fullscreen
7060  * windows. But normally the window will end up fullscreen. Just
7061  * don't write code that crashes if not.
7062  *
7063  * You can track the fullscreen state via the "window-state-event" signal
7064  * on #GtkWidget.
7065  *
7066  * Since: 2.2
7067  **/
7068 void
gtk_window_fullscreen(GtkWindow * window)7069 gtk_window_fullscreen (GtkWindow *window)
7070 {
7071   GtkWidget *widget;
7072   GdkWindow *toplevel;
7073   GtkWindowPrivate *priv;
7074 
7075   g_return_if_fail (GTK_IS_WINDOW (window));
7076 
7077   widget = GTK_WIDGET (window);
7078   priv = GTK_WINDOW_GET_PRIVATE (window);
7079 
7080   priv->fullscreen_initially = TRUE;
7081 
7082   if (window->frame)
7083     toplevel = window->frame;
7084   else
7085     toplevel = widget->window;
7086 
7087   if (toplevel != NULL)
7088     gdk_window_fullscreen (toplevel);
7089 }
7090 
7091 /**
7092  * gtk_window_unfullscreen:
7093  * @window: a #GtkWindow
7094  *
7095  * Asks to toggle off the fullscreen state for @window. Note that you
7096  * shouldn't assume the window is definitely not full screen
7097  * afterward, because other entities (e.g. the user or <link
7098  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7099  * again, and not all window managers honor requests to unfullscreen
7100  * windows. But normally the window will end up restored to its normal
7101  * state. Just don't write code that crashes if not.
7102  *
7103  * You can track the fullscreen state via the "window-state-event" signal
7104  * on #GtkWidget.
7105  *
7106  * Since: 2.2
7107  **/
7108 void
gtk_window_unfullscreen(GtkWindow * window)7109 gtk_window_unfullscreen (GtkWindow *window)
7110 {
7111   GtkWidget *widget;
7112   GdkWindow *toplevel;
7113   GtkWindowPrivate *priv;
7114 
7115   g_return_if_fail (GTK_IS_WINDOW (window));
7116 
7117   widget = GTK_WIDGET (window);
7118   priv = GTK_WINDOW_GET_PRIVATE (window);
7119 
7120   priv->fullscreen_initially = FALSE;
7121 
7122   if (window->frame)
7123     toplevel = window->frame;
7124   else
7125     toplevel = widget->window;
7126 
7127   if (toplevel != NULL)
7128     gdk_window_unfullscreen (toplevel);
7129 }
7130 
7131 /**
7132  * gtk_window_set_keep_above:
7133  * @window: a #GtkWindow
7134  * @setting: whether to keep @window above other windows
7135  *
7136  * Asks to keep @window above, so that it stays on top. Note that
7137  * you shouldn't assume the window is definitely above afterward,
7138  * because other entities (e.g. the user or <link
7139  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7140  * and not all window managers support keeping windows above. But
7141  * normally the window will end kept above. Just don't write code
7142  * that crashes if not.
7143  *
7144  * It's permitted to call this function before showing a window,
7145  * in which case the window will be kept above when it appears onscreen
7146  * initially.
7147  *
7148  * You can track the above state via the "window-state-event" signal
7149  * on #GtkWidget.
7150  *
7151  * Note that, according to the <ulink
7152  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7153  * Manager Hints</ulink> specification, the above state is mainly meant
7154  * for user preferences and should not be used by applications e.g. for
7155  * drawing attention to their dialogs.
7156  *
7157  * Since: 2.4
7158  **/
7159 void
gtk_window_set_keep_above(GtkWindow * window,gboolean setting)7160 gtk_window_set_keep_above (GtkWindow *window,
7161 			   gboolean   setting)
7162 {
7163   GtkWidget *widget;
7164   GtkWindowPrivate *priv;
7165   GdkWindow *toplevel;
7166 
7167   g_return_if_fail (GTK_IS_WINDOW (window));
7168 
7169   widget = GTK_WIDGET (window);
7170   priv = GTK_WINDOW_GET_PRIVATE (window);
7171 
7172   priv->above_initially = setting != FALSE;
7173   if (setting)
7174     priv->below_initially = FALSE;
7175 
7176   if (window->frame)
7177     toplevel = window->frame;
7178   else
7179     toplevel = widget->window;
7180 
7181   if (toplevel != NULL)
7182     gdk_window_set_keep_above (toplevel, setting);
7183 }
7184 
7185 /**
7186  * gtk_window_set_keep_below:
7187  * @window: a #GtkWindow
7188  * @setting: whether to keep @window below other windows
7189  *
7190  * Asks to keep @window below, so that it stays in bottom. Note that
7191  * you shouldn't assume the window is definitely below afterward,
7192  * because other entities (e.g. the user or <link
7193  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7194  * and not all window managers support putting windows below. But
7195  * normally the window will be kept below. Just don't write code
7196  * that crashes if not.
7197  *
7198  * It's permitted to call this function before showing a window,
7199  * in which case the window will be kept below when it appears onscreen
7200  * initially.
7201  *
7202  * You can track the below state via the "window-state-event" signal
7203  * on #GtkWidget.
7204  *
7205  * Note that, according to the <ulink
7206  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7207  * Manager Hints</ulink> specification, the above state is mainly meant
7208  * for user preferences and should not be used by applications e.g. for
7209  * drawing attention to their dialogs.
7210  *
7211  * Since: 2.4
7212  **/
7213 void
gtk_window_set_keep_below(GtkWindow * window,gboolean setting)7214 gtk_window_set_keep_below (GtkWindow *window,
7215 			   gboolean   setting)
7216 {
7217   GtkWidget *widget;
7218   GtkWindowPrivate *priv;
7219   GdkWindow *toplevel;
7220 
7221   g_return_if_fail (GTK_IS_WINDOW (window));
7222 
7223   widget = GTK_WIDGET (window);
7224   priv = GTK_WINDOW_GET_PRIVATE (window);
7225 
7226   priv->below_initially = setting != FALSE;
7227   if (setting)
7228     priv->above_initially = FALSE;
7229 
7230   if (window->frame)
7231     toplevel = window->frame;
7232   else
7233     toplevel = widget->window;
7234 
7235   if (toplevel != NULL)
7236     gdk_window_set_keep_below (toplevel, setting);
7237 }
7238 
7239 /**
7240  * gtk_window_set_resizable:
7241  * @window: a #GtkWindow
7242  * @resizable: %TRUE if the user can resize this window
7243  *
7244  * Sets whether the user can resize a window. Windows are user resizable
7245  * by default.
7246  **/
7247 void
gtk_window_set_resizable(GtkWindow * window,gboolean resizable)7248 gtk_window_set_resizable (GtkWindow *window,
7249                           gboolean   resizable)
7250 {
7251   g_return_if_fail (GTK_IS_WINDOW (window));
7252 
7253   gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7254 }
7255 
7256 /**
7257  * gtk_window_get_resizable:
7258  * @window: a #GtkWindow
7259  *
7260  * Gets the value set by gtk_window_set_resizable().
7261  *
7262  * Return value: %TRUE if the user can resize the window
7263  **/
7264 gboolean
gtk_window_get_resizable(GtkWindow * window)7265 gtk_window_get_resizable (GtkWindow *window)
7266 {
7267   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7268 
7269   /* allow_grow is most likely to indicate the semantic concept we
7270    * mean by "resizable" (and will be a reliable indicator if
7271    * set_policy() hasn't been called)
7272    */
7273   return window->allow_grow;
7274 }
7275 
7276 /**
7277  * gtk_window_set_gravity:
7278  * @window: a #GtkWindow
7279  * @gravity: window gravity
7280  *
7281  * Window gravity defines the meaning of coordinates passed to
7282  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7283  * more details.
7284  *
7285  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7286  * typically "do what you mean."
7287  *
7288  **/
7289 void
gtk_window_set_gravity(GtkWindow * window,GdkGravity gravity)7290 gtk_window_set_gravity (GtkWindow *window,
7291 			GdkGravity gravity)
7292 {
7293   g_return_if_fail (GTK_IS_WINDOW (window));
7294 
7295   if (gravity != window->gravity)
7296     {
7297       window->gravity = gravity;
7298 
7299       /* gtk_window_move_resize() will adapt gravity
7300        */
7301       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7302 
7303       g_object_notify (G_OBJECT (window), "gravity");
7304     }
7305 }
7306 
7307 /**
7308  * gtk_window_get_gravity:
7309  * @window: a #GtkWindow
7310  *
7311  * Gets the value set by gtk_window_set_gravity().
7312  *
7313  * Return value: (transfer none): window gravity
7314  **/
7315 GdkGravity
gtk_window_get_gravity(GtkWindow * window)7316 gtk_window_get_gravity (GtkWindow *window)
7317 {
7318   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7319 
7320   return window->gravity;
7321 }
7322 
7323 /**
7324  * gtk_window_begin_resize_drag:
7325  * @window: a #GtkWindow
7326  * @button: mouse button that initiated the drag
7327  * @edge: position of the resize control
7328  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7329  * @root_y: Y position where the user clicked to initiate the drag
7330  * @timestamp: timestamp from the click event that initiated the drag
7331  *
7332  * Starts resizing a window. This function is used if an application
7333  * has window resizing controls. When GDK can support it, the resize
7334  * will be done using the standard mechanism for the <link
7335  * linkend="gtk-X11-arch">window manager</link> or windowing
7336  * system. Otherwise, GDK will try to emulate window resizing,
7337  * potentially not all that well, depending on the windowing system.
7338  *
7339  **/
7340 void
gtk_window_begin_resize_drag(GtkWindow * window,GdkWindowEdge edge,gint button,gint root_x,gint root_y,guint32 timestamp)7341 gtk_window_begin_resize_drag  (GtkWindow    *window,
7342                                GdkWindowEdge edge,
7343                                gint          button,
7344                                gint          root_x,
7345                                gint          root_y,
7346                                guint32       timestamp)
7347 {
7348   GtkWidget *widget;
7349   GdkWindow *toplevel;
7350 
7351   g_return_if_fail (GTK_IS_WINDOW (window));
7352   widget = GTK_WIDGET (window);
7353   g_return_if_fail (gtk_widget_get_visible (widget));
7354 
7355   if (window->frame)
7356     toplevel = window->frame;
7357   else
7358     toplevel = widget->window;
7359 
7360   gdk_window_begin_resize_drag (toplevel,
7361                                 edge, button,
7362                                 root_x, root_y,
7363                                 timestamp);
7364 }
7365 
7366 /**
7367  * gtk_window_get_frame_dimensions:
7368  * @window: a #GtkWindow
7369  * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
7370  * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
7371  * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
7372  * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
7373  *
7374  * (Note: this is a special-purpose function intended for the
7375  *  framebuffer port; see gtk_window_set_has_frame(). It will not
7376  *  return the size of the window border drawn by the <link
7377  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
7378  *  case when using a windowing system.  See
7379  *  gdk_window_get_frame_extents() to get the standard window border
7380  *  extents.)
7381  *
7382  * Retrieves the dimensions of the frame window for this toplevel.
7383  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7384  *
7385  * Deprecated: 2.24: This function will be removed in GTK+ 3
7386  **/
7387 void
gtk_window_get_frame_dimensions(GtkWindow * window,gint * left,gint * top,gint * right,gint * bottom)7388 gtk_window_get_frame_dimensions (GtkWindow *window,
7389 				 gint      *left,
7390 				 gint      *top,
7391 				 gint      *right,
7392 				 gint      *bottom)
7393 {
7394   g_return_if_fail (GTK_IS_WINDOW (window));
7395 
7396   if (left)
7397     *left = window->frame_left;
7398   if (top)
7399     *top = window->frame_top;
7400   if (right)
7401     *right = window->frame_right;
7402   if (bottom)
7403     *bottom = window->frame_bottom;
7404 }
7405 
7406 /**
7407  * gtk_window_begin_move_drag:
7408  * @window: a #GtkWindow
7409  * @button: mouse button that initiated the drag
7410  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7411  * @root_y: Y position where the user clicked to initiate the drag
7412  * @timestamp: timestamp from the click event that initiated the drag
7413  *
7414  * Starts moving a window. This function is used if an application has
7415  * window movement grips. When GDK can support it, the window movement
7416  * will be done using the standard mechanism for the <link
7417  * linkend="gtk-X11-arch">window manager</link> or windowing
7418  * system. Otherwise, GDK will try to emulate window movement,
7419  * potentially not all that well, depending on the windowing system.
7420  *
7421  **/
7422 void
gtk_window_begin_move_drag(GtkWindow * window,gint button,gint root_x,gint root_y,guint32 timestamp)7423 gtk_window_begin_move_drag  (GtkWindow *window,
7424                              gint       button,
7425                              gint       root_x,
7426                              gint       root_y,
7427                              guint32    timestamp)
7428 {
7429   GtkWidget *widget;
7430   GdkWindow *toplevel;
7431 
7432   g_return_if_fail (GTK_IS_WINDOW (window));
7433   widget = GTK_WIDGET (window);
7434   g_return_if_fail (gtk_widget_get_visible (widget));
7435 
7436   if (window->frame)
7437     toplevel = window->frame;
7438   else
7439     toplevel = widget->window;
7440 
7441   gdk_window_begin_move_drag (toplevel,
7442                               button,
7443                               root_x, root_y,
7444                               timestamp);
7445 }
7446 
7447 /**
7448  * gtk_window_set_screen:
7449  * @window: a #GtkWindow.
7450  * @screen: a #GdkScreen.
7451  *
7452  * Sets the #GdkScreen where the @window is displayed; if
7453  * the window is already mapped, it will be unmapped, and
7454  * then remapped on the new screen.
7455  *
7456  * Since: 2.2
7457  */
7458 void
gtk_window_set_screen(GtkWindow * window,GdkScreen * screen)7459 gtk_window_set_screen (GtkWindow *window,
7460 		       GdkScreen *screen)
7461 {
7462   GtkWidget *widget;
7463   GdkScreen *previous_screen;
7464   gboolean was_mapped;
7465 
7466   g_return_if_fail (GTK_IS_WINDOW (window));
7467   g_return_if_fail (GDK_IS_SCREEN (screen));
7468 
7469   if (screen == window->screen)
7470     return;
7471 
7472   widget = GTK_WIDGET (window);
7473 
7474   previous_screen = window->screen;
7475   was_mapped = gtk_widget_get_mapped (widget);
7476 
7477   if (was_mapped)
7478     gtk_widget_unmap (widget);
7479   if (gtk_widget_get_realized (widget))
7480     gtk_widget_unrealize (widget);
7481 
7482   gtk_window_free_key_hash (window);
7483   window->screen = screen;
7484   gtk_widget_reset_rc_styles (widget);
7485   if (screen != previous_screen)
7486     {
7487       g_signal_handlers_disconnect_by_func (previous_screen,
7488 					    gtk_window_on_composited_changed, window);
7489       g_signal_connect (screen, "composited-changed",
7490 			G_CALLBACK (gtk_window_on_composited_changed), window);
7491 
7492       _gtk_widget_propagate_screen_changed (widget, previous_screen);
7493       _gtk_widget_propagate_composited_changed (widget);
7494     }
7495   g_object_notify (G_OBJECT (window), "screen");
7496 
7497   if (was_mapped)
7498     gtk_widget_map (widget);
7499 }
7500 
7501 static void
gtk_window_on_composited_changed(GdkScreen * screen,GtkWindow * window)7502 gtk_window_on_composited_changed (GdkScreen *screen,
7503 				  GtkWindow *window)
7504 {
7505   gtk_widget_queue_draw (GTK_WIDGET (window));
7506 
7507   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7508 }
7509 
7510 static GdkScreen *
gtk_window_check_screen(GtkWindow * window)7511 gtk_window_check_screen (GtkWindow *window)
7512 {
7513   if (window->screen)
7514     return window->screen;
7515   else
7516     {
7517       g_warning ("Screen for GtkWindow not set; you must always set\n"
7518 		 "a screen for a GtkWindow before using the window");
7519       return NULL;
7520     }
7521 }
7522 
7523 /**
7524  * gtk_window_get_screen:
7525  * @window: a #GtkWindow.
7526  *
7527  * Returns the #GdkScreen associated with @window.
7528  *
7529  * Return value: (transfer none): a #GdkScreen.
7530  *
7531  * Since: 2.2
7532  */
7533 GdkScreen*
gtk_window_get_screen(GtkWindow * window)7534 gtk_window_get_screen (GtkWindow *window)
7535 {
7536   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7537 
7538   return window->screen;
7539 }
7540 
7541 /**
7542  * gtk_window_is_active:
7543  * @window: a #GtkWindow
7544  *
7545  * Returns whether the window is part of the current active toplevel.
7546  * (That is, the toplevel window receiving keystrokes.)
7547  * The return value is %TRUE if the window is active toplevel
7548  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7549  * You might use this function if you wanted to draw a widget
7550  * differently in an active window from a widget in an inactive window.
7551  * See gtk_window_has_toplevel_focus()
7552  *
7553  * Return value: %TRUE if the window part of the current active window.
7554  *
7555  * Since: 2.4
7556  **/
7557 gboolean
gtk_window_is_active(GtkWindow * window)7558 gtk_window_is_active (GtkWindow *window)
7559 {
7560   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7561 
7562   return window->is_active;
7563 }
7564 
7565 /**
7566  * gtk_window_has_toplevel_focus:
7567  * @window: a #GtkWindow
7568  *
7569  * Returns whether the input focus is within this GtkWindow.
7570  * For real toplevel windows, this is identical to gtk_window_is_active(),
7571  * but for embedded windows, like #GtkPlug, the results will differ.
7572  *
7573  * Return value: %TRUE if the input focus is within this GtkWindow
7574  *
7575  * Since: 2.4
7576  **/
7577 gboolean
gtk_window_has_toplevel_focus(GtkWindow * window)7578 gtk_window_has_toplevel_focus (GtkWindow *window)
7579 {
7580   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7581 
7582   return window->has_toplevel_focus;
7583 }
7584 
7585 static void
gtk_window_group_class_init(GtkWindowGroupClass * klass)7586 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7587 {
7588 }
7589 
7590 GType
gtk_window_group_get_type(void)7591 gtk_window_group_get_type (void)
7592 {
7593   static GType window_group_type = 0;
7594 
7595   if (!window_group_type)
7596     {
7597       const GTypeInfo window_group_info =
7598       {
7599 	sizeof (GtkWindowGroupClass),
7600 	NULL,		/* base_init */
7601 	NULL,		/* base_finalize */
7602 	(GClassInitFunc) gtk_window_group_class_init,
7603 	NULL,		/* class_finalize */
7604 	NULL,		/* class_data */
7605 	sizeof (GtkWindowGroup),
7606 	0,		/* n_preallocs */
7607 	(GInstanceInitFunc) NULL,
7608       };
7609 
7610       window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7611 						  &window_group_info, 0);
7612     }
7613 
7614   return window_group_type;
7615 }
7616 
7617 /**
7618  * gtk_window_group_new:
7619  *
7620  * Creates a new #GtkWindowGroup object. Grabs added with
7621  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7622  *
7623  * Return value: a new #GtkWindowGroup.
7624  **/
7625 GtkWindowGroup *
gtk_window_group_new(void)7626 gtk_window_group_new (void)
7627 {
7628   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7629 }
7630 
7631 static void
window_group_cleanup_grabs(GtkWindowGroup * group,GtkWindow * window)7632 window_group_cleanup_grabs (GtkWindowGroup *group,
7633 			    GtkWindow      *window)
7634 {
7635   GSList *tmp_list;
7636   GSList *to_remove = NULL;
7637 
7638   tmp_list = group->grabs;
7639   while (tmp_list)
7640     {
7641       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7642 	to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7643       tmp_list = tmp_list->next;
7644     }
7645 
7646   while (to_remove)
7647     {
7648       gtk_grab_remove (to_remove->data);
7649       g_object_unref (to_remove->data);
7650       to_remove = g_slist_delete_link (to_remove, to_remove);
7651     }
7652 }
7653 
7654 /**
7655  * gtk_window_group_add_window:
7656  * @window_group: a #GtkWindowGroup
7657  * @window: the #GtkWindow to add
7658  *
7659  * Adds a window to a #GtkWindowGroup.
7660  **/
7661 void
gtk_window_group_add_window(GtkWindowGroup * window_group,GtkWindow * window)7662 gtk_window_group_add_window (GtkWindowGroup *window_group,
7663 			     GtkWindow      *window)
7664 {
7665   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7666   g_return_if_fail (GTK_IS_WINDOW (window));
7667 
7668   if (window->group != window_group)
7669     {
7670       g_object_ref (window);
7671       g_object_ref (window_group);
7672 
7673       if (window->group)
7674 	gtk_window_group_remove_window (window->group, window);
7675       else
7676 	window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7677 
7678       window->group = window_group;
7679 
7680       g_object_unref (window);
7681     }
7682 }
7683 
7684 /**
7685  * gtk_window_group_remove_window:
7686  * @window_group: a #GtkWindowGroup
7687  * @window: the #GtkWindow to remove
7688  *
7689  * Removes a window from a #GtkWindowGroup.
7690  **/
7691 void
gtk_window_group_remove_window(GtkWindowGroup * window_group,GtkWindow * window)7692 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7693 				GtkWindow      *window)
7694 {
7695   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7696   g_return_if_fail (GTK_IS_WINDOW (window));
7697   g_return_if_fail (window->group == window_group);
7698 
7699   g_object_ref (window);
7700 
7701   window_group_cleanup_grabs (window_group, window);
7702   window->group = NULL;
7703 
7704   g_object_unref (window_group);
7705   g_object_unref (window);
7706 }
7707 
7708 /**
7709  * gtk_window_group_list_windows:
7710  * @window_group: a #GtkWindowGroup
7711  *
7712  * Returns a list of the #GtkWindows that belong to @window_group.
7713  *
7714  * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
7715  *   windows inside the group.
7716  *
7717  * Since: 2.14
7718  **/
7719 GList *
gtk_window_group_list_windows(GtkWindowGroup * window_group)7720 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7721 {
7722   GList *toplevels, *toplevel, *group_windows;
7723 
7724   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7725 
7726   group_windows = NULL;
7727   toplevels = gtk_window_list_toplevels ();
7728 
7729   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7730     {
7731       GtkWindow *window = toplevel->data;
7732 
7733       if (window_group == window->group)
7734 	group_windows = g_list_prepend (group_windows, window);
7735     }
7736 
7737   return g_list_reverse (group_windows);
7738 }
7739 
7740 /**
7741  * gtk_window_get_group:
7742  * @window: (allow-none): a #GtkWindow, or %NULL
7743  *
7744  * Returns the group for @window or the default group, if
7745  * @window is %NULL or if @window does not have an explicit
7746  * window group.
7747  *
7748  * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
7749  *
7750  * Since: 2.10
7751  */
7752 GtkWindowGroup *
gtk_window_get_group(GtkWindow * window)7753 gtk_window_get_group (GtkWindow *window)
7754 {
7755   if (window && window->group)
7756     return window->group;
7757   else
7758     {
7759       static GtkWindowGroup *default_group = NULL;
7760 
7761       if (!default_group)
7762 	default_group = gtk_window_group_new ();
7763 
7764       return default_group;
7765     }
7766 }
7767 
7768 /**
7769  * gtk_window_has_group:
7770  * @window: a #GtkWindow
7771  *
7772  * Returns whether @window has an explicit window group.
7773  *
7774  * Return value: %TRUE if @window has an explicit window group.
7775  *
7776  * Since 2.22
7777  **/
7778 gboolean
gtk_window_has_group(GtkWindow * window)7779 gtk_window_has_group (GtkWindow *window)
7780 {
7781   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7782 
7783   return window->group != NULL;
7784 }
7785 
7786 /**
7787  * gtk_window_group_get_current_current_grab:
7788  * @window_group: a #GtkWindowGroup
7789  *
7790  * Gets the current grab widget of the given group,
7791  * see gtk_grab_add().
7792  *
7793  * Returns: (transfer none): the current grab widget of the group
7794  *
7795  * Since: 2.22
7796  */
7797 GtkWidget *
gtk_window_group_get_current_grab(GtkWindowGroup * window_group)7798 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7799 {
7800   if (window_group->grabs)
7801     return GTK_WIDGET (window_group->grabs->data);
7802   return NULL;
7803 }
7804 
7805 /*
7806   Derived from XParseGeometry() in XFree86
7807 
7808   Copyright 1985, 1986, 1987,1998  The Open Group
7809 
7810   All Rights Reserved.
7811 
7812   The above copyright notice and this permission notice shall be included
7813   in all copies or substantial portions of the Software.
7814 
7815   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7816   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7817   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7818   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7819   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7820   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7821   OTHER DEALINGS IN THE SOFTWARE.
7822 
7823   Except as contained in this notice, the name of The Open Group shall
7824   not be used in advertising or otherwise to promote the sale, use or
7825   other dealings in this Software without prior written authorization
7826   from The Open Group.
7827 */
7828 
7829 
7830 /*
7831  *    XParseGeometry parses strings of the form
7832  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7833  *   width, height, xoffset, and yoffset are unsigned integers.
7834  *   Example:  "=80x24+300-49"
7835  *   The equal sign is optional.
7836  *   It returns a bitmask that indicates which of the four values
7837  *   were actually found in the string.  For each value found,
7838  *   the corresponding argument is updated;  for each value
7839  *   not found, the corresponding argument is left unchanged.
7840  */
7841 
7842 /* The following code is from Xlib, and is minimally modified, so we
7843  * can track any upstream changes if required.  Don't change this
7844  * code. Or if you do, put in a huge comment marking which thing
7845  * changed.
7846  */
7847 
7848 static int
read_int(gchar * string,gchar ** next)7849 read_int (gchar   *string,
7850           gchar  **next)
7851 {
7852   int result = 0;
7853   int sign = 1;
7854 
7855   if (*string == '+')
7856     string++;
7857   else if (*string == '-')
7858     {
7859       string++;
7860       sign = -1;
7861     }
7862 
7863   for (; (*string >= '0') && (*string <= '9'); string++)
7864     {
7865       result = (result * 10) + (*string - '0');
7866     }
7867 
7868   *next = string;
7869 
7870   if (sign >= 0)
7871     return (result);
7872   else
7873     return (-result);
7874 }
7875 
7876 /*
7877  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
7878  * value (x, y, width, height) was found in the parsed string.
7879  */
7880 #define NoValue         0x0000
7881 #define XValue          0x0001
7882 #define YValue          0x0002
7883 #define WidthValue      0x0004
7884 #define HeightValue     0x0008
7885 #define AllValues       0x000F
7886 #define XNegative       0x0010
7887 #define YNegative       0x0020
7888 
7889 /* Try not to reformat/modify, so we can compare/sync with X sources */
7890 static int
gtk_XParseGeometry(const char * string,int * x,int * y,unsigned int * width,unsigned int * height)7891 gtk_XParseGeometry (const char   *string,
7892                     int          *x,
7893                     int          *y,
7894                     unsigned int *width,
7895                     unsigned int *height)
7896 {
7897   int mask = NoValue;
7898   char *strind;
7899   unsigned int tempWidth, tempHeight;
7900   int tempX, tempY;
7901   char *nextCharacter;
7902 
7903   /* These initializations are just to silence gcc */
7904   tempWidth = 0;
7905   tempHeight = 0;
7906   tempX = 0;
7907   tempY = 0;
7908 
7909   if ( (string == NULL) || (*string == '\0')) return(mask);
7910   if (*string == '=')
7911     string++;  /* ignore possible '=' at beg of geometry spec */
7912 
7913   strind = (char *)string;
7914   if (*strind != '+' && *strind != '-' && *strind != 'x') {
7915     tempWidth = read_int(strind, &nextCharacter);
7916     if (strind == nextCharacter)
7917       return (0);
7918     strind = nextCharacter;
7919     mask |= WidthValue;
7920   }
7921 
7922   if (*strind == 'x' || *strind == 'X') {
7923     strind++;
7924     tempHeight = read_int(strind, &nextCharacter);
7925     if (strind == nextCharacter)
7926       return (0);
7927     strind = nextCharacter;
7928     mask |= HeightValue;
7929   }
7930 
7931   if ((*strind == '+') || (*strind == '-')) {
7932     if (*strind == '-') {
7933       strind++;
7934       tempX = -read_int(strind, &nextCharacter);
7935       if (strind == nextCharacter)
7936         return (0);
7937       strind = nextCharacter;
7938       mask |= XNegative;
7939 
7940     }
7941     else
7942       {	strind++;
7943       tempX = read_int(strind, &nextCharacter);
7944       if (strind == nextCharacter)
7945         return(0);
7946       strind = nextCharacter;
7947       }
7948     mask |= XValue;
7949     if ((*strind == '+') || (*strind == '-')) {
7950       if (*strind == '-') {
7951         strind++;
7952         tempY = -read_int(strind, &nextCharacter);
7953         if (strind == nextCharacter)
7954           return(0);
7955         strind = nextCharacter;
7956         mask |= YNegative;
7957 
7958       }
7959       else
7960         {
7961           strind++;
7962           tempY = read_int(strind, &nextCharacter);
7963           if (strind == nextCharacter)
7964             return(0);
7965           strind = nextCharacter;
7966         }
7967       mask |= YValue;
7968     }
7969   }
7970 
7971   /* If strind isn't at the end of the string the it's an invalid
7972 		geometry specification. */
7973 
7974   if (*strind != '\0') return (0);
7975 
7976   if (mask & XValue)
7977     *x = tempX;
7978   if (mask & YValue)
7979     *y = tempY;
7980   if (mask & WidthValue)
7981     *width = tempWidth;
7982   if (mask & HeightValue)
7983     *height = tempHeight;
7984   return (mask);
7985 }
7986 
7987 /**
7988  * gtk_window_parse_geometry:
7989  * @window: a #GtkWindow
7990  * @geometry: geometry string
7991  *
7992  * Parses a standard X Window System geometry string - see the
7993  * manual page for X (type 'man X') for details on this.
7994  * gtk_window_parse_geometry() does work on all GTK+ ports
7995  * including Win32 but is primarily intended for an X environment.
7996  *
7997  * If either a size or a position can be extracted from the
7998  * geometry string, gtk_window_parse_geometry() returns %TRUE
7999  * and calls gtk_window_set_default_size() and/or gtk_window_move()
8000  * to resize/move the window.
8001  *
8002  * If gtk_window_parse_geometry() returns %TRUE, it will also
8003  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8004  * indicating to the window manager that the size/position of
8005  * the window was user-specified. This causes most window
8006  * managers to honor the geometry.
8007  *
8008  * Note that for gtk_window_parse_geometry() to work as expected, it has
8009  * to be called when the window has its "final" size, i.e. after calling
8010  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8011  * on the window.
8012  * |[
8013  * #include <gtk/gtk.h>
8014  *
8015  * static void
8016  * fill_with_content (GtkWidget *vbox)
8017  * {
8018  *   /&ast; fill with content... &ast;/
8019  * }
8020  *
8021  * int
8022  * main (int argc, char *argv[])
8023  * {
8024  *   GtkWidget *window, *vbox;
8025  *   GdkGeometry size_hints = {
8026  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8027  *   };
8028  *
8029  *   gtk_init (&argc, &argv);
8030  *
8031  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8032  *   vbox = gtk_vbox_new (FALSE, 0);
8033  *
8034  *   gtk_container_add (GTK_CONTAINER (window), vbox);
8035  *   fill_with_content (vbox);
8036  *   gtk_widget_show_all (vbox);
8037  *
8038  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8039  * 	  			    window,
8040  * 				    &size_hints,
8041  * 				    GDK_HINT_MIN_SIZE |
8042  * 				    GDK_HINT_BASE_SIZE |
8043  * 				    GDK_HINT_RESIZE_INC);
8044  *
8045  *   if (argc &gt; 1)
8046  *     {
8047  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8048  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8049  *     }
8050  *
8051  *   gtk_widget_show_all (window);
8052  *   gtk_main ();
8053  *
8054  *   return 0;
8055  * }
8056  * ]|
8057  *
8058  * Return value: %TRUE if string was parsed successfully
8059  **/
8060 gboolean
gtk_window_parse_geometry(GtkWindow * window,const gchar * geometry)8061 gtk_window_parse_geometry (GtkWindow   *window,
8062                            const gchar *geometry)
8063 {
8064   gint result, x = 0, y = 0;
8065   guint w, h;
8066   GdkGravity grav;
8067   gboolean size_set, pos_set;
8068   GdkScreen *screen;
8069 
8070   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8071   g_return_val_if_fail (geometry != NULL, FALSE);
8072 
8073   screen = gtk_window_check_screen (window);
8074 
8075   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8076 
8077   size_set = FALSE;
8078   if ((result & WidthValue) || (result & HeightValue))
8079     {
8080       gtk_window_set_default_size_internal (window,
8081 					    TRUE, result & WidthValue ? w : -1,
8082 					    TRUE, result & HeightValue ? h : -1,
8083 					    TRUE);
8084       size_set = TRUE;
8085     }
8086 
8087   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8088 
8089   grav = GDK_GRAVITY_NORTH_WEST;
8090 
8091   if ((result & XNegative) && (result & YNegative))
8092     grav = GDK_GRAVITY_SOUTH_EAST;
8093   else if (result & XNegative)
8094     grav = GDK_GRAVITY_NORTH_EAST;
8095   else if (result & YNegative)
8096     grav = GDK_GRAVITY_SOUTH_WEST;
8097 
8098   if ((result & XValue) == 0)
8099     x = 0;
8100 
8101   if ((result & YValue) == 0)
8102     y = 0;
8103 
8104   if (grav == GDK_GRAVITY_SOUTH_WEST ||
8105       grav == GDK_GRAVITY_SOUTH_EAST)
8106     y = gdk_screen_get_height (screen) - h + y;
8107 
8108   if (grav == GDK_GRAVITY_SOUTH_EAST ||
8109       grav == GDK_GRAVITY_NORTH_EAST)
8110     x = gdk_screen_get_width (screen) - w + x;
8111 
8112   /* we don't let you put a window offscreen; maybe some people would
8113    * prefer to be able to, but it's kind of a bogus thing to do.
8114    */
8115   if (y < 0)
8116     y = 0;
8117 
8118   if (x < 0)
8119     x = 0;
8120 
8121   pos_set = FALSE;
8122   if ((result & XValue) || (result & YValue))
8123     {
8124       gtk_window_set_gravity (window, grav);
8125       gtk_window_move (window, x, y);
8126       pos_set = TRUE;
8127     }
8128 
8129   if (size_set || pos_set)
8130     {
8131       /* Set USSize, USPosition hints */
8132       GtkWindowGeometryInfo *info;
8133 
8134       info = gtk_window_get_geometry_info (window, TRUE);
8135 
8136       if (pos_set)
8137         info->mask |= GDK_HINT_USER_POS;
8138       if (size_set)
8139         info->mask |= GDK_HINT_USER_SIZE;
8140     }
8141 
8142   return result != 0;
8143 }
8144 
8145 static void
gtk_window_mnemonic_hash_foreach(guint keyval,GSList * targets,gpointer data)8146 gtk_window_mnemonic_hash_foreach (guint      keyval,
8147 				  GSList    *targets,
8148 				  gpointer   data)
8149 {
8150   struct {
8151     GtkWindow *window;
8152     GtkWindowKeysForeachFunc func;
8153     gpointer func_data;
8154   } *info = data;
8155 
8156   (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8157 }
8158 
8159 void
_gtk_window_keys_foreach(GtkWindow * window,GtkWindowKeysForeachFunc func,gpointer func_data)8160 _gtk_window_keys_foreach (GtkWindow                *window,
8161 			  GtkWindowKeysForeachFunc func,
8162 			  gpointer                 func_data)
8163 {
8164   GSList *groups;
8165   GtkMnemonicHash *mnemonic_hash;
8166 
8167   struct {
8168     GtkWindow *window;
8169     GtkWindowKeysForeachFunc func;
8170     gpointer func_data;
8171   } info;
8172 
8173   info.window = window;
8174   info.func = func;
8175   info.func_data = func_data;
8176 
8177   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8178   if (mnemonic_hash)
8179     _gtk_mnemonic_hash_foreach (mnemonic_hash,
8180 				gtk_window_mnemonic_hash_foreach, &info);
8181 
8182   groups = gtk_accel_groups_from_object (G_OBJECT (window));
8183   while (groups)
8184     {
8185       GtkAccelGroup *group = groups->data;
8186       gint i;
8187 
8188       for (i = 0; i < group->n_accels; i++)
8189 	{
8190 	  GtkAccelKey *key = &group->priv_accels[i].key;
8191 
8192 	  if (key->accel_key)
8193 	    (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8194 	}
8195 
8196       groups = groups->next;
8197     }
8198 }
8199 
8200 static void
gtk_window_keys_changed(GtkWindow * window)8201 gtk_window_keys_changed (GtkWindow *window)
8202 {
8203   gtk_window_free_key_hash (window);
8204   gtk_window_get_key_hash (window);
8205 }
8206 
8207 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8208 
8209 struct _GtkWindowKeyEntry
8210 {
8211   guint keyval;
8212   guint modifiers;
8213   guint is_mnemonic : 1;
8214 };
8215 
8216 static void
window_key_entry_destroy(gpointer data)8217 window_key_entry_destroy (gpointer data)
8218 {
8219   g_slice_free (GtkWindowKeyEntry, data);
8220 }
8221 
8222 static void
add_to_key_hash(GtkWindow * window,guint keyval,GdkModifierType modifiers,gboolean is_mnemonic,gpointer data)8223 add_to_key_hash (GtkWindow      *window,
8224 		 guint           keyval,
8225 		 GdkModifierType modifiers,
8226 		 gboolean        is_mnemonic,
8227 		 gpointer        data)
8228 {
8229   GtkKeyHash *key_hash = data;
8230 
8231   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8232 
8233   entry->keyval = keyval;
8234   entry->modifiers = modifiers;
8235   entry->is_mnemonic = is_mnemonic;
8236 
8237   /* GtkAccelGroup stores lowercased accelerators. To deal
8238    * with this, if <Shift> was specified, uppercase.
8239    */
8240   if (modifiers & GDK_SHIFT_MASK)
8241     {
8242       if (keyval == GDK_Tab)
8243 	keyval = GDK_ISO_Left_Tab;
8244       else
8245 	keyval = gdk_keyval_to_upper (keyval);
8246     }
8247 
8248   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8249 }
8250 
8251 static GtkKeyHash *
gtk_window_get_key_hash(GtkWindow * window)8252 gtk_window_get_key_hash (GtkWindow *window)
8253 {
8254   GdkScreen *screen = gtk_window_check_screen (window);
8255   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8256 
8257   if (key_hash)
8258     return key_hash;
8259 
8260   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8261 				(GDestroyNotify)window_key_entry_destroy);
8262   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8263   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8264 
8265   return key_hash;
8266 }
8267 
8268 static void
gtk_window_free_key_hash(GtkWindow * window)8269 gtk_window_free_key_hash (GtkWindow *window)
8270 {
8271   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8272   if (key_hash)
8273     {
8274       _gtk_key_hash_free (key_hash);
8275       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8276     }
8277 }
8278 
8279 /**
8280  * gtk_window_activate_key:
8281  * @window:  a #GtkWindow
8282  * @event:   a #GdkEventKey
8283  *
8284  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8285  * called by the default ::key_press_event handler for toplevel windows,
8286  * however in some cases it may be useful to call this directly when
8287  * overriding the standard key handling for a toplevel window.
8288  *
8289  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8290  *
8291  * Since: 2.4
8292  */
8293 gboolean
gtk_window_activate_key(GtkWindow * window,GdkEventKey * event)8294 gtk_window_activate_key (GtkWindow   *window,
8295 			 GdkEventKey *event)
8296 {
8297   GtkKeyHash *key_hash;
8298   GtkWindowKeyEntry *found_entry = NULL;
8299   gboolean enable_mnemonics;
8300   gboolean enable_accels;
8301 
8302   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8303   g_return_val_if_fail (event != NULL, FALSE);
8304 
8305   key_hash = gtk_window_get_key_hash (window);
8306 
8307   if (key_hash)
8308     {
8309       GSList *tmp_list;
8310       GSList *entries = _gtk_key_hash_lookup (key_hash,
8311 					      event->hardware_keycode,
8312 					      event->state,
8313 					      gtk_accelerator_get_default_mod_mask (),
8314 					      event->group);
8315 
8316       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8317                     "gtk-enable-mnemonics", &enable_mnemonics,
8318                     "gtk-enable-accels", &enable_accels,
8319                     NULL);
8320 
8321       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8322 	{
8323 	  GtkWindowKeyEntry *entry = tmp_list->data;
8324 	  if (entry->is_mnemonic)
8325             {
8326               if (enable_mnemonics)
8327 	        {
8328 	          found_entry = entry;
8329 	          break;
8330 	        }
8331             }
8332           else
8333             {
8334               if (enable_accels && !found_entry)
8335                 {
8336 	          found_entry = entry;
8337                 }
8338             }
8339 	}
8340 
8341       g_slist_free (entries);
8342     }
8343 
8344   if (found_entry)
8345     {
8346       if (found_entry->is_mnemonic)
8347         {
8348           if (enable_mnemonics)
8349             return gtk_window_mnemonic_activate (window, found_entry->keyval,
8350                                                  found_entry->modifiers);
8351         }
8352       else
8353         {
8354           if (enable_accels)
8355             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8356                                               found_entry->modifiers);
8357         }
8358     }
8359 
8360   return FALSE;
8361 }
8362 
8363 static void
window_update_has_focus(GtkWindow * window)8364 window_update_has_focus (GtkWindow *window)
8365 {
8366   GtkWidget *widget = GTK_WIDGET (window);
8367   gboolean has_focus = window->has_toplevel_focus && window->is_active;
8368 
8369   if (has_focus != window->has_focus)
8370     {
8371       window->has_focus = has_focus;
8372 
8373       if (has_focus)
8374 	{
8375 	  if (window->focus_widget &&
8376 	      window->focus_widget != widget &&
8377 	      !gtk_widget_has_focus (window->focus_widget))
8378 	    do_focus_change (window->focus_widget, TRUE);
8379 	}
8380       else
8381 	{
8382 	  if (window->focus_widget &&
8383 	      window->focus_widget != widget &&
8384 	      gtk_widget_has_focus (window->focus_widget))
8385 	    do_focus_change (window->focus_widget, FALSE);
8386 	}
8387     }
8388 }
8389 
8390 /**
8391  * _gtk_window_set_is_active:
8392  * @window: a #GtkWindow
8393  * @is_active: %TRUE if the window is in the currently active toplevel
8394  *
8395  * Internal function that sets whether the #GtkWindow is part
8396  * of the currently active toplevel window (taking into account inter-process
8397  * embedding.)
8398  **/
8399 void
_gtk_window_set_is_active(GtkWindow * window,gboolean is_active)8400 _gtk_window_set_is_active (GtkWindow *window,
8401 			   gboolean   is_active)
8402 {
8403   g_return_if_fail (GTK_IS_WINDOW (window));
8404 
8405   is_active = is_active != FALSE;
8406 
8407   if (is_active != window->is_active)
8408     {
8409       window->is_active = is_active;
8410       window_update_has_focus (window);
8411 
8412       g_object_notify (G_OBJECT (window), "is-active");
8413     }
8414 }
8415 
8416 /**
8417  * _gtk_window_set_is_toplevel:
8418  * @window: a #GtkWindow
8419  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8420  * parent of the root window); %FALSE if it is not (for example, for an
8421  * in-process, parented GtkPlug)
8422  *
8423  * Internal function used by #GtkPlug when it gets parented/unparented by a
8424  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8425  * global list of toplevel windows.
8426  */
8427 void
_gtk_window_set_is_toplevel(GtkWindow * window,gboolean is_toplevel)8428 _gtk_window_set_is_toplevel (GtkWindow *window,
8429 			     gboolean   is_toplevel)
8430 {
8431   GtkWidget *widget;
8432 
8433   widget = GTK_WIDGET (window);
8434 
8435   if (gtk_widget_is_toplevel (widget))
8436     g_assert (g_slist_find (toplevel_list, window) != NULL);
8437   else
8438     g_assert (g_slist_find (toplevel_list, window) == NULL);
8439 
8440   if (is_toplevel == gtk_widget_is_toplevel (widget))
8441     return;
8442 
8443   if (is_toplevel)
8444     {
8445       _gtk_widget_set_is_toplevel (widget, TRUE);
8446       toplevel_list = g_slist_prepend (toplevel_list, window);
8447     }
8448   else
8449     {
8450       _gtk_widget_set_is_toplevel (widget, FALSE);
8451       toplevel_list = g_slist_remove (toplevel_list, window);
8452     }
8453 }
8454 
8455 /**
8456  * _gtk_window_set_has_toplevel_focus:
8457  * @window: a #GtkWindow
8458  * @has_toplevel_focus: %TRUE if the in
8459  *
8460  * Internal function that sets whether the keyboard focus for the
8461  * toplevel window (taking into account inter-process embedding.)
8462  **/
8463 void
_gtk_window_set_has_toplevel_focus(GtkWindow * window,gboolean has_toplevel_focus)8464 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8465 				   gboolean   has_toplevel_focus)
8466 {
8467   g_return_if_fail (GTK_IS_WINDOW (window));
8468 
8469   has_toplevel_focus = has_toplevel_focus != FALSE;
8470 
8471   if (has_toplevel_focus != window->has_toplevel_focus)
8472     {
8473       window->has_toplevel_focus = has_toplevel_focus;
8474       window_update_has_focus (window);
8475 
8476       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8477     }
8478 }
8479 
8480 /**
8481  * gtk_window_set_auto_startup_notification:
8482  * @setting: %TRUE to automatically do startup notification
8483  *
8484  * By default, after showing the first #GtkWindow, GTK+ calls
8485  * gdk_notify_startup_complete().  Call this function to disable
8486  * the automatic startup notification. You might do this if your
8487  * first window is a splash screen, and you want to delay notification
8488  * until after your real main window has been shown, for example.
8489  *
8490  * In that example, you would disable startup notification
8491  * temporarily, show your splash screen, then re-enable it so that
8492  * showing the main window would automatically result in notification.
8493  *
8494  * Since: 2.2
8495  **/
8496 void
gtk_window_set_auto_startup_notification(gboolean setting)8497 gtk_window_set_auto_startup_notification (gboolean setting)
8498 {
8499   disable_startup_notification = !setting;
8500 }
8501 
8502 /**
8503  * gtk_window_get_window_type:
8504  * @window: a #GtkWindow
8505  *
8506  * Gets the type of the window. See #GtkWindowType.
8507  *
8508  * Return value: the type of the window
8509  *
8510  * Since: 2.20
8511  **/
8512 GtkWindowType
gtk_window_get_window_type(GtkWindow * window)8513 gtk_window_get_window_type (GtkWindow *window)
8514 {
8515   g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
8516 
8517   return window->type;
8518 }
8519 
8520 /* gtk_window_get_mnemonics_visible:
8521  * @window: a #GtkWindow
8522  *
8523  * Gets the value of the #GtkWindow:mnemonics-visible property.
8524  *
8525  * Returns: %TRUE if mnemonics are supposed to be visible
8526  * in this window.
8527  *
8528  * Since: 2.20
8529  */
8530 gboolean
gtk_window_get_mnemonics_visible(GtkWindow * window)8531 gtk_window_get_mnemonics_visible (GtkWindow *window)
8532 {
8533   GtkWindowPrivate *priv;
8534 
8535   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8536 
8537   priv = GTK_WINDOW_GET_PRIVATE (window);
8538 
8539   return priv->mnemonics_visible;
8540 }
8541 
8542 /**
8543  * gtk_window_set_mnemonics_visible:
8544  * @window: a #GtkWindow
8545  * @setting: the new value
8546  *
8547  * Sets the #GtkWindow:mnemonics-visible property.
8548  *
8549  * Since: 2.20
8550  */
8551 void
gtk_window_set_mnemonics_visible(GtkWindow * window,gboolean setting)8552 gtk_window_set_mnemonics_visible (GtkWindow *window,
8553                                   gboolean   setting)
8554 {
8555   GtkWindowPrivate *priv;
8556 
8557   g_return_if_fail (GTK_IS_WINDOW (window));
8558 
8559   priv = GTK_WINDOW_GET_PRIVATE (window);
8560 
8561   setting = setting != FALSE;
8562 
8563   if (priv->mnemonics_visible != setting)
8564     {
8565       priv->mnemonics_visible = setting;
8566       g_object_notify (G_OBJECT (window), "mnemonics-visible");
8567     }
8568 
8569   priv->mnemonics_visible_set = TRUE;
8570 }
8571 
8572 #if defined (G_OS_WIN32) && !defined (_WIN64)
8573 
8574 #undef gtk_window_set_icon_from_file
8575 
8576 gboolean
gtk_window_set_icon_from_file(GtkWindow * window,const gchar * filename,GError ** err)8577 gtk_window_set_icon_from_file (GtkWindow   *window,
8578 			       const gchar *filename,
8579 			       GError     **err)
8580 {
8581   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8582   gboolean retval;
8583 
8584   if (utf8_filename == NULL)
8585     return FALSE;
8586 
8587   retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8588 
8589   g_free (utf8_filename);
8590 
8591   return retval;
8592 }
8593 
8594 #undef gtk_window_set_default_icon_from_file
8595 
8596 gboolean
gtk_window_set_default_icon_from_file(const gchar * filename,GError ** err)8597 gtk_window_set_default_icon_from_file (const gchar *filename,
8598 				       GError     **err)
8599 {
8600   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8601   gboolean retval;
8602 
8603   if (utf8_filename == NULL)
8604     return FALSE;
8605 
8606   retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8607 
8608   g_free (utf8_filename);
8609 
8610   return retval;
8611 }
8612 
8613 #endif
8614 
8615 #define __GTK_WINDOW_C__
8616 #include "gtkaliasdef.c"
8617