~ubuntu-branches/ubuntu/precise/gtk+2.0/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/044_grips.patch/gtk/gtkwindow.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-02-23 22:24:09 UTC
  • Revision ID: package-import@ubuntu.com-20120223222409-p6e5zvz25r0q8cut
Tags: 2.24.10-0ubuntu4
* debian/patches/044_grips.patch:
  - revert dropping, there is a public api in there and we need to fix the
    rdepends before dropping it

Show diffs side-by-side

added added

removed removed

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