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, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25#include "config.h"
26
27#include "gtkwindow.h"
28
29#include <string.h>
30#include <stdlib.h>
31#include <errno.h>
32#include <limits.h>
33
34#include "gtkprivate.h"
35#include "gtkwindowprivate.h"
36#include "gtkaccelgroupprivate.h"
37#include "gtkbindings.h"
38#include "gtkcsscornervalueprivate.h"
39#include "gtkcssiconthemevalueprivate.h"
40#include "gtkcssrgbavalueprivate.h"
41#include "gtkcssshadowsvalueprivate.h"
42#include "gtkkeyhash.h"
43#include "gtkmain.h"
44#include "gtkmnemonichash.h"
45#include "gtkmenubar.h"
46#include "gtkmenushellprivate.h"
47#include "gtkicontheme.h"
48#include "gtkmarshalers.h"
49#include "gtkplug.h"
50#include "gtkbuildable.h"
51#include "gtkbuilderprivate.h"
52#include "gtkwidgetprivate.h"
53#include "gtkcontainerprivate.h"
54#include "gtkintl.h"
55#include "gtkstylecontextprivate.h"
56#include "gtktypebuiltins.h"
57#include "gtkbox.h"
58#include "gtkbutton.h"
59#include "gtkheaderbar.h"
60#include "gtkheaderbarprivate.h"
61#include "gtkpopoverprivate.h"
62#include "a11y/gtkwindowaccessible.h"
63#include "a11y/gtkcontaineraccessibleprivate.h"
64#include "gtkapplicationprivate.h"
65#include "gtkgestureprivate.h"
66#include "inspector/init.h"
67#include "inspector/window.h"
68#include "gtkcssstylepropertyprivate.h"
69
70#include "gdk/gdk-private.h"
71
72#ifdef GDK_WINDOWING_X11
73#include "x11/gdkx.h"
74#endif
75
76#ifdef GDK_WINDOWING_WIN32
77#include "win32/gdkwin32.h"
78#endif
79
80#ifdef GDK_WINDOWING_WAYLAND
81#include "wayland/gdkwayland.h"
82#endif
83
84#ifdef GDK_WINDOWING_BROADWAY
85#include "broadway/gdkbroadway.h"
86#endif
87
88#ifdef GDK_WINDOWING_MIR
89#include "mir/gdkmir.h"
90#endif
91
92/**
93 * SECTION:gtkwindow
94 * @title: GtkWindow
95 * @short_description: Toplevel which can contain other widgets
96 *
97 * A GtkWindow is a toplevel window which can contain other widgets.
98 * Windows normally have decorations that are under the control
99 * of the windowing system and allow the user to manipulate the window
100 * (resize it, move it, close it,...).
101 *
102 * # GtkWindow as GtkBuildable
103 *
104 * The GtkWindow implementation of the GtkBuildable interface supports a
105 * custom <accel-groups> element, which supports any number of <group>
106 * elements representing the #GtkAccelGroup objects you want to add to
107 * your window (synonymous with gtk_window_add_accel_group().
108 *
109 * It also supports the <initial-focus> element, whose name property names
110 * the widget to receive the focus when the window is mapped.
111 *
112 * An example of a UI definition fragment with accel groups:
113 * |[
114 * <object class="GtkWindow">
115 * <accel-groups>
116 * <group name="accelgroup1"/>
117 * </accel-groups>
118 * <initial-focus name="thunderclap"/>
119 * </object>
120 *
121 * ...
122 *
123 * <object class="GtkAccelGroup" id="accelgroup1"/>
124 * ]|
125 *
126 * The GtkWindow implementation of the GtkBuildable interface supports
127 * setting a child as the titlebar by specifying “titlebar” as the “type”
128 * attribute of a <child> element.
129 *
130 * # CSS nodes
131 *
132 * |[<!-- language="plain" -->
133 * window
134 * ├── decoration
135 * ╰── <child>
136 * ]|
137 *
138 * GtkWindow has a main CSS node with name window and style class .background,
139 * and a subnode with name decoration.
140 *
141 * Style classes that are typically used with the main CSS node are .csd (when
142 * client-side decorations are in use), .solid-csd (for client-side decorations
143 * without invisible borders), .ssd (used by mutter when rendering server-side
144 * decorations). GtkWindow also represents window states with the following
145 * style classes on the main node: .tiled, .maximized, .fullscreen. Specialized
146 * types of window often add their own discriminating style classes, such as
147 * .popup or .tooltip.
148 *
149 * GtkWindow adds the .titlebar and .default-decoration style classes to the
150 * widget that is added as a titlebar child.
151 */
152
153#define MNEMONICS_DELAY 300 /* ms */
154#define NO_CONTENT_CHILD_NAT 200
155/* In case the content (excluding header bar and shadows) of the window
156 * would be empty, either because there is no visible child widget or only an
157 * empty container widget, we use NO_CONTENT_CHILD_NAT as natural width/height
158 * instead.
159 */
160
161typedef struct _GtkWindowPopover GtkWindowPopover;
162
163struct _GtkWindowPopover
164{
165 GtkWidget *widget;
166 GtkWidget *parent;
167 GdkWindow *window;
168 GtkPositionType pos;
169 cairo_rectangle_int_t rect;
170 gulong unmap_id;
171 guint clamp_allocation : 1;
172};
173
174struct _GtkWindowPrivate
175{
176 GtkMnemonicHash *mnemonic_hash;
177
178 GtkWidget *attach_widget;
179 GtkWidget *default_widget;
180 GtkWidget *initial_focus;
181 GtkWidget *focus_widget;
182 GtkWindow *transient_parent;
183 GtkWindowGeometryInfo *geometry_info;
184 GtkWindowGroup *group;
185 GdkScreen *screen;
186 GdkDisplay *display;
187 GtkApplication *application;
188
189 GList *popovers;
190
191 GdkModifierType mnemonic_modifier;
192
193 gchar *startup_id;
194 gchar *title;
195 gchar *wmclass_class;
196 gchar *wmclass_name;
197 gchar *wm_role;
198
199 guint keys_changed_handler;
200 guint delete_event_handler;
201
202 guint32 initial_timestamp;
203
204 guint16 configure_request_count;
205
206 guint mnemonics_display_timeout_id;
207
208 gint scale;
209
210 gint title_height;
211 GtkWidget *title_box;
212 GtkWidget *titlebar;
213 GtkWidget *popup_menu;
214
215 GdkWindow *border_window[8];
216 gint initial_fullscreen_monitor;
217
218 /* The following flags are initially TRUE (before a window is mapped).
219 * They cause us to compute a configure request that involves
220 * default-only parameters. Once mapped, we set them to FALSE.
221 * Then we set them to TRUE again on unmap (for position)
222 * and on unrealize (for size).
223 */
224 guint need_default_position : 1;
225 guint need_default_size : 1;
226
227 guint above_initially : 1;
228 guint accept_focus : 1;
229 guint below_initially : 1;
230 guint builder_visible : 1;
231 guint configure_notify_received : 1;
232 guint decorated : 1;
233 guint deletable : 1;
234 guint destroy_with_parent : 1;
235 guint focus_on_map : 1;
236 guint fullscreen_initially : 1;
237 guint has_focus : 1;
238 guint has_user_ref_count : 1;
239 guint has_toplevel_focus : 1;
240 guint hide_titlebar_when_maximized : 1;
241 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
242 guint is_active : 1;
243 guint maximize_initially : 1;
244 guint mnemonics_visible : 1;
245 guint mnemonics_visible_set : 1;
246 guint focus_visible : 1;
247 guint modal : 1;
248 guint position : 3;
249 guint resizable : 1;
250 guint skips_pager : 1;
251 guint skips_taskbar : 1;
252 guint stick_initially : 1;
253 guint transient_parent_group : 1;
254 guint type : 4; /* GtkWindowType */
255 guint urgent : 1;
256 guint gravity : 5; /* GdkGravity */
257 guint csd_requested : 1;
258 guint client_decorated : 1; /* Decorations drawn client-side */
259 guint use_client_shadow : 1; /* Decorations use client-side shadows */
260 guint maximized : 1;
261 guint fullscreen : 1;
262 guint tiled : 1;
263
264 guint use_subsurface : 1;
265
266 GdkWindowTypeHint type_hint;
267
268 GtkGesture *multipress_gesture;
269 GtkGesture *drag_gesture;
270
271 GdkWindow *hardcoded_window;
272
273 GtkCssNode *decoration_node;
274};
275
276static const GtkTargetEntry dnd_dest_targets [] = {
277 { "application/x-rootwindow-drop", 0, 0 },
278};
279
280enum {
281 SET_FOCUS,
282 FRAME_EVENT,
283 ACTIVATE_FOCUS,
284 ACTIVATE_DEFAULT,
285 KEYS_CHANGED,
286 ENABLE_DEBUGGING,
287 LAST_SIGNAL
288};
289
290enum {
291 PROP_0,
292
293 /* Construct */
294 PROP_TYPE,
295
296 /* Normal Props */
297 PROP_TITLE,
298 PROP_ROLE,
299 PROP_RESIZABLE,
300 PROP_MODAL,
301 PROP_WIN_POS,
302 PROP_DEFAULT_WIDTH,
303 PROP_DEFAULT_HEIGHT,
304 PROP_DESTROY_WITH_PARENT,
305 PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED,
306 PROP_ICON,
307 PROP_ICON_NAME,
308 PROP_SCREEN,
309 PROP_TYPE_HINT,
310 PROP_SKIP_TASKBAR_HINT,
311 PROP_SKIP_PAGER_HINT,
312 PROP_URGENCY_HINT,
313 PROP_ACCEPT_FOCUS,
314 PROP_FOCUS_ON_MAP,
315 PROP_DECORATED,
316 PROP_DELETABLE,
317 PROP_GRAVITY,
318 PROP_TRANSIENT_FOR,
319 PROP_ATTACHED_TO,
320 PROP_HAS_RESIZE_GRIP,
321 PROP_RESIZE_GRIP_VISIBLE,
322 PROP_APPLICATION,
323 /* Readonly properties */
324 PROP_IS_ACTIVE,
325 PROP_HAS_TOPLEVEL_FOCUS,
326
327 /* Writeonly properties */
328 PROP_STARTUP_ID,
329
330 PROP_MNEMONICS_VISIBLE,
331 PROP_FOCUS_VISIBLE,
332
333 PROP_IS_MAXIMIZED,
334
335 LAST_ARG
336};
337
338static GParamSpec *window_props[LAST_ARG] = { NULL, };
339
340/* Must be kept in sync with GdkWindowEdge ! */
341typedef enum
342{
343 GTK_WINDOW_REGION_EDGE_NW,
344 GTK_WINDOW_REGION_EDGE_N,
345 GTK_WINDOW_REGION_EDGE_NE,
346 GTK_WINDOW_REGION_EDGE_W,
347 GTK_WINDOW_REGION_EDGE_E,
348 GTK_WINDOW_REGION_EDGE_SW,
349 GTK_WINDOW_REGION_EDGE_S,
350 GTK_WINDOW_REGION_EDGE_SE,
351 GTK_WINDOW_REGION_CONTENT,
352 GTK_WINDOW_REGION_TITLE,
353} GtkWindowRegion;
354
355typedef struct
356{
357 GList *icon_list;
358 gchar *icon_name;
359 guint realized : 1;
360 guint using_default_icon : 1;
361 guint using_parent_icon : 1;
362 guint using_themed_icon : 1;
363} GtkWindowIconInfo;
364
365typedef struct {
366 GdkGeometry geometry; /* Last set of geometry hints we set */
367 GdkWindowHints flags;
368 GdkRectangle configure_request;
369} GtkWindowLastGeometryInfo;
370
371struct _GtkWindowGeometryInfo
372{
373 /* Properties that the app has set on the window
374 */
375 GdkGeometry geometry; /* Geometry hints */
376 GdkWindowHints mask;
377 /* from last gtk_window_resize () - if > 0, indicates that
378 * we should resize to this size.
379 */
380 gint resize_width;
381 gint resize_height;
382
383 /* From last gtk_window_move () prior to mapping -
384 * only used if initial_pos_set
385 */
386 gint initial_x;
387 gint initial_y;
388
389 /* Default size - used only the FIRST time we map a window,
390 * only if > 0.
391 */
392 gint default_width;
393 gint default_height;
394 /* whether to use initial_x, initial_y */
395 guint initial_pos_set : 1;
396 /* CENTER_ALWAYS or other position constraint changed since
397 * we sent the last configure request.
398 */
399 guint position_constraints_changed : 1;
400
401 /* if true, default_width, height should be multiplied by the
402 * increments and affect the geometry widget only
403 */
404 guint default_is_geometry : 1;
405
406 GtkWindowLastGeometryInfo last;
407};
408
409
410static void gtk_window_constructed (GObject *object);
411static void gtk_window_dispose (GObject *object);
412static void gtk_window_finalize (GObject *object);
413static void gtk_window_destroy (GtkWidget *widget);
414static void gtk_window_show (GtkWidget *widget);
415static void gtk_window_hide (GtkWidget *widget);
416static void gtk_window_map (GtkWidget *widget);
417static void gtk_window_unmap (GtkWidget *widget);
418static void gtk_window_realize (GtkWidget *widget);
419static void gtk_window_unrealize (GtkWidget *widget);
420static void gtk_window_size_allocate (GtkWidget *widget,
421 GtkAllocation *allocation);
422static gboolean gtk_window_map_event (GtkWidget *widget,
423 GdkEventAny *event);
424static gint gtk_window_configure_event (GtkWidget *widget,
425 GdkEventConfigure *event);
426static gboolean gtk_window_event (GtkWidget *widget,
427 GdkEvent *event);
428static gint gtk_window_key_press_event (GtkWidget *widget,
429 GdkEventKey *event);
430static gint gtk_window_key_release_event (GtkWidget *widget,
431 GdkEventKey *event);
432static gint gtk_window_focus_in_event (GtkWidget *widget,
433 GdkEventFocus *event);
434static gint gtk_window_focus_out_event (GtkWidget *widget,
435 GdkEventFocus *event);
436static gboolean gtk_window_state_event (GtkWidget *widget,
437 GdkEventWindowState *event);
438static void gtk_window_remove (GtkContainer *container,
439 GtkWidget *widget);
440static void gtk_window_check_resize (GtkContainer *container);
441static void gtk_window_forall (GtkContainer *container,
442 gboolean include_internals,
443 GtkCallback callback,
444 gpointer callback_data);
445static gint gtk_window_focus (GtkWidget *widget,
446 GtkDirectionType direction);
447static void gtk_window_move_focus (GtkWidget *widget,
448 GtkDirectionType dir);
449static void gtk_window_real_set_focus (GtkWindow *window,
450 GtkWidget *focus);
451
452static void gtk_window_real_activate_default (GtkWindow *window);
453static void gtk_window_real_activate_focus (GtkWindow *window);
454static void gtk_window_keys_changed (GtkWindow *window);
455static gboolean gtk_window_enable_debugging (GtkWindow *window,
456 gboolean toggle);
457static gint gtk_window_draw (GtkWidget *widget,
458 cairo_t *cr);
459static void gtk_window_unset_transient_for (GtkWindow *window);
460static void gtk_window_transient_parent_realized (GtkWidget *parent,
461 GtkWidget *window);
462static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
463 GtkWidget *window);
464
465static GdkScreen *gtk_window_check_screen (GtkWindow *window);
466
467static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
468 gboolean create);
469
470static void gtk_window_move_resize (GtkWindow *window);
471static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
472 guint flags_a,
473 GdkGeometry *geometry_b,
474 guint flags_b);
475static void gtk_window_constrain_size (GtkWindow *window,
476 GdkGeometry *geometry,
477 guint flags,
478 gint width,
479 gint height,
480 gint *new_width,
481 gint *new_height);
482static void gtk_window_constrain_position (GtkWindow *window,
483 gint new_width,
484 gint new_height,
485 gint *x,
486 gint *y);
487static void gtk_window_update_fixed_size (GtkWindow *window,
488 GdkGeometry *new_geometry,
489 gint new_width,
490 gint new_height);
491static void gtk_window_compute_hints (GtkWindow *window,
492 GdkGeometry *new_geometry,
493 guint *new_flags);
494static void gtk_window_compute_configure_request (GtkWindow *window,
495 GdkRectangle *request,
496 GdkGeometry *geometry,
497 guint *flags);
498
499static void gtk_window_set_default_size_internal (GtkWindow *window,
500 gboolean change_width,
501 gint width,
502 gboolean change_height,
503 gint height,
504 gboolean is_geometry);
505
506static void update_themed_icon (GtkWindow *window);
507static GList *icon_list_from_theme (GtkWindow *window,
508 const gchar *name);
509static void gtk_window_realize_icon (GtkWindow *window);
510static void gtk_window_unrealize_icon (GtkWindow *window);
511static void update_window_buttons (GtkWindow *window);
512static void get_shadow_width (GtkWindow *window,
513 GtkBorder *shadow_width);
514
515static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
516static void gtk_window_free_key_hash (GtkWindow *window);
517static void gtk_window_on_composited_changed (GdkScreen *screen,
518 GtkWindow *window);
519#ifdef GDK_WINDOWING_X11
520static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
521 GParamSpec *pspec,
522 GtkWindow *window);
523#endif
524static void gtk_window_set_theme_variant (GtkWindow *window);
525
526static void gtk_window_do_popup (GtkWindow *window,
527 GdkEventButton *event);
528
529static void gtk_window_get_preferred_width (GtkWidget *widget,
530 gint *minimum_size,
531 gint *natural_size);
532static void gtk_window_get_preferred_width_for_height (GtkWidget *widget,
533 gint height,
534 gint *minimum_size,
535 gint *natural_size);
536
537static void gtk_window_get_preferred_height (GtkWidget *widget,
538 gint *minimum_size,
539 gint *natural_size);
540static void gtk_window_get_preferred_height_for_width (GtkWidget *widget,
541 gint width,
542 gint *minimum_size,
543 gint *natural_size);
544static void gtk_window_style_updated (GtkWidget *widget);
545static void gtk_window_state_flags_changed (GtkWidget *widget,
546 GtkStateFlags previous_state);
547
548static GSList *toplevel_list = NULL;
549static guint window_signals[LAST_SIGNAL] = { 0 };
550static GList *default_icon_list = NULL;
551static gchar *default_icon_name = NULL;
552static guint default_icon_serial = 0;
553static gboolean disable_startup_notification = FALSE;
554
555static GQuark quark_gtk_embedded = 0;
556static GQuark quark_gtk_window_key_hash = 0;
557static GQuark quark_gtk_window_icon_info = 0;
558static GQuark quark_gtk_buildable_accels = 0;
559
560static GtkBuildableIface *parent_buildable_iface;
561
562static void gtk_window_set_property (GObject *object,
563 guint prop_id,
564 const GValue *value,
565 GParamSpec *pspec);
566static void gtk_window_get_property (GObject *object,
567 guint prop_id,
568 GValue *value,
569 GParamSpec *pspec);
570
571/* GtkBuildable */
572static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
573static void gtk_window_buildable_add_child (GtkBuildable *buildable,
574 GtkBuilder *builder,
575 GObject *child,
576 const gchar *type);
577static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
578 GtkBuilder *builder,
579 const gchar *name,
580 const GValue *value);
581static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
582 GtkBuilder *builder);
583static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
584 GtkBuilder *builder,
585 GObject *child,
586 const gchar *tagname,
587 GMarkupParser *parser,
588 gpointer *data);
589static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
590 GtkBuilder *builder,
591 GObject *child,
592 const gchar *tagname,
593 gpointer user_data);
594
595static void ensure_state_flag_backdrop (GtkWidget *widget);
596static void unset_titlebar (GtkWindow *window);
597static void on_titlebar_title_notify (GtkHeaderBar *titlebar,
598 GParamSpec *pspec,
599 GtkWindow *self);
600static GtkWindowRegion get_active_region_type (GtkWindow *window,
601 GdkEventAny *event,
602 gint x,
603 gint y);
604
605static void gtk_window_update_debugging (void);
606
607G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
608 G_ADD_PRIVATE (GtkWindow)
609 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
610 gtk_window_buildable_interface_init))
611
612static void
613add_tab_bindings (GtkBindingSet *binding_set,
614 GdkModifierType modifiers,
615 GtkDirectionType direction)
616{
617 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
618 "move-focus", 1,
619 GTK_TYPE_DIRECTION_TYPE, direction);
620 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
621 "move-focus", 1,
622 GTK_TYPE_DIRECTION_TYPE, direction);
623}
624
625static void
626add_arrow_bindings (GtkBindingSet *binding_set,
627 guint keysym,
628 GtkDirectionType direction)
629{
630 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
631
632 gtk_binding_entry_add_signal (binding_set, keysym, 0,
633 "move-focus", 1,
634 GTK_TYPE_DIRECTION_TYPE, direction);
635 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
636 "move-focus", 1,
637 GTK_TYPE_DIRECTION_TYPE, direction);
638 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
639 "move-focus", 1,
640 GTK_TYPE_DIRECTION_TYPE, direction);
641 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
642 "move-focus", 1,
643 GTK_TYPE_DIRECTION_TYPE, direction);
644}
645
646static guint32
647extract_time_from_startup_id (const gchar* startup_id)
648{
649 gchar *timestr = g_strrstr (startup_id, "_TIME");
650 guint32 retval = GDK_CURRENT_TIME;
651
652 if (timestr)
653 {
654 gchar *end;
655 guint32 timestamp;
656
657 /* Skip past the "_TIME" part */
658 timestr += 5;
659
660 end = NULL;
661 errno = 0;
662 timestamp = g_ascii_strtoull (timestr, &end, 0);
663 if (errno == 0 && end != timestr)
664 retval = timestamp;
665 }
666
667 return retval;
668}
669
670static gboolean
671startup_id_is_fake (const gchar* startup_id)
672{
673 return strncmp (startup_id, "_TIME", 5) == 0;
674}
675
676static void
677gtk_window_class_init (GtkWindowClass *klass)
678{
679 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
680 GtkWidgetClass *widget_class;
681 GtkContainerClass *container_class;
682 GtkBindingSet *binding_set;
683
684 widget_class = (GtkWidgetClass*) klass;
685 container_class = (GtkContainerClass*) klass;
686
687 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
688 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
689 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
690 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
691
692 gobject_class->constructed = gtk_window_constructed;
693 gobject_class->dispose = gtk_window_dispose;
694 gobject_class->finalize = gtk_window_finalize;
695
696 gobject_class->set_property = gtk_window_set_property;
697 gobject_class->get_property = gtk_window_get_property;
698
699 widget_class->destroy = gtk_window_destroy;
700 widget_class->show = gtk_window_show;
701 widget_class->hide = gtk_window_hide;
702 widget_class->map = gtk_window_map;
703 widget_class->map_event = gtk_window_map_event;
704 widget_class->unmap = gtk_window_unmap;
705 widget_class->realize = gtk_window_realize;
706 widget_class->unrealize = gtk_window_unrealize;
707 widget_class->size_allocate = gtk_window_size_allocate;
708 widget_class->configure_event = gtk_window_configure_event;
709 widget_class->event = gtk_window_event;
710 widget_class->key_press_event = gtk_window_key_press_event;
711 widget_class->key_release_event = gtk_window_key_release_event;
712 widget_class->focus_in_event = gtk_window_focus_in_event;
713 widget_class->focus_out_event = gtk_window_focus_out_event;
714 widget_class->focus = gtk_window_focus;
715 widget_class->move_focus = gtk_window_move_focus;
716 widget_class->draw = gtk_window_draw;
717 widget_class->window_state_event = gtk_window_state_event;
718 widget_class->get_preferred_width = gtk_window_get_preferred_width;
719 widget_class->get_preferred_width_for_height = gtk_window_get_preferred_width_for_height;
720 widget_class->get_preferred_height = gtk_window_get_preferred_height;
721 widget_class->get_preferred_height_for_width = gtk_window_get_preferred_height_for_width;
722 widget_class->state_flags_changed = gtk_window_state_flags_changed;
723 widget_class->style_updated = gtk_window_style_updated;
724
725 container_class->remove = gtk_window_remove;
726 container_class->check_resize = gtk_window_check_resize;
727 container_class->forall = gtk_window_forall;
728
729 klass->set_focus = gtk_window_real_set_focus;
730
731 klass->activate_default = gtk_window_real_activate_default;
732 klass->activate_focus = gtk_window_real_activate_focus;
733 klass->keys_changed = gtk_window_keys_changed;
734 klass->enable_debugging = gtk_window_enable_debugging;
735
736 window_props[PROP_TYPE] =
737 g_param_spec_enum ("type",
738 P_("Window Type"),
739 P_("The type of the window"),
740 GTK_TYPE_WINDOW_TYPE,
741 GTK_WINDOW_TOPLEVEL,
742 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
743
744 window_props[PROP_TITLE] =
745 g_param_spec_string ("title",
746 P_("Window Title"),
747 P_("The title of the window"),
748 NULL,
749 GTK_PARAM_READWRITE);
750
751 window_props[PROP_ROLE] =
752 g_param_spec_string ("role",
753 P_("Window Role"),
754 P_("Unique identifier for the window to be used when restoring a session"),
755 NULL,
756 GTK_PARAM_READWRITE);
757
758 /**
759 * GtkWindow:startup-id:
760 *
761 * The :startup-id is a write-only property for setting window's
762 * startup notification identifier. See gtk_window_set_startup_id()
763 * for more details.
764 *
765 * Since: 2.12
766 */
767 window_props[PROP_STARTUP_ID] =
768 g_param_spec_string ("startup-id",
769 P_("Startup ID"),
770 P_("Unique startup identifier for the window used by startup-notification"),
771 NULL,
772 GTK_PARAM_WRITABLE);
773
774 window_props[PROP_RESIZABLE] =
775 g_param_spec_boolean ("resizable",
776 P_("Resizable"),
777 P_("If TRUE, users can resize the window"),
778 TRUE,
779 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
780
781 window_props[PROP_MODAL] =
782 g_param_spec_boolean ("modal",
783 P_("Modal"),
784 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
785 FALSE,
786 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
787
788 window_props[PROP_WIN_POS] =
789 g_param_spec_enum ("window-position",
790 P_("Window Position"),
791 P_("The initial position of the window"),
792 GTK_TYPE_WINDOW_POSITION,
793 GTK_WIN_POS_NONE,
794 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
795
796 window_props[PROP_DEFAULT_WIDTH] =
797 g_param_spec_int ("default-width",
798 P_("Default Width"),
799 P_("The default width of the window, used when initially showing the window"),
800 -1, G_MAXINT,
801 -1,
802 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
803
804 window_props[PROP_DEFAULT_HEIGHT] =
805 g_param_spec_int ("default-height",
806 P_("Default Height"),
807 P_("The default height of the window, used when initially showing the window"),
808 -1, G_MAXINT,
809 -1,
810 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
811
812 window_props[PROP_DESTROY_WITH_PARENT] =
813 g_param_spec_boolean ("destroy-with-parent",
814 P_("Destroy with Parent"),
815 P_("If this window should be destroyed when the parent is destroyed"),
816 FALSE,
817 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
818
819 /**
820 * GtkWindow:hide-titlebar-when-maximized:
821 *
822 * Whether the titlebar should be hidden during maximization.
823 *
824 * Since: 3.4
825 */
826 window_props[PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED] =
827 g_param_spec_boolean ("hide-titlebar-when-maximized",
828 P_("Hide the titlebar during maximization"),
829 P_("If this window's titlebar should be hidden when the window is maximized"),
830 FALSE,
831 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
832
833 window_props[PROP_ICON] =
834 g_param_spec_object ("icon",
835 P_("Icon"),
836 P_("Icon for this window"),
837 GDK_TYPE_PIXBUF,
838 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
839
840 /**
841 * GtkWindow:mnemonics-visible:
842 *
843 * Whether mnemonics are currently visible in this window.
844 *
845 * This property is maintained by GTK+ based on user input,
846 * and should not be set by applications.
847 *
848 * Since: 2.20
849 */
850 window_props[PROP_MNEMONICS_VISIBLE] =
851 g_param_spec_boolean ("mnemonics-visible",
852 P_("Mnemonics Visible"),
853 P_("Whether mnemonics are currently visible in this window"),
854 TRUE,
855 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
856
857 /**
858 * GtkWindow:focus-visible:
859 *
860 * Whether 'focus rectangles' are currently visible in this window.
861 *
862 * This property is maintained by GTK+ based on user input
863 * and should not be set by applications.
864 *
865 * Since: 2.20
866 */
867 window_props[PROP_FOCUS_VISIBLE] =
868 g_param_spec_boolean ("focus-visible",
869 P_("Focus Visible"),
870 P_("Whether focus rectangles are currently visible in this window"),
871 TRUE,
872 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
873
874 /**
875 * GtkWindow:icon-name:
876 *
877 * The :icon-name property specifies the name of the themed icon to
878 * use as the window icon. See #GtkIconTheme for more details.
879 *
880 * Since: 2.6
881 */
882 window_props[PROP_ICON_NAME] =
883 g_param_spec_string ("icon-name",
884 P_("Icon Name"),
885 P_("Name of the themed icon for this window"),
886 NULL,
887 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
888
889 window_props[PROP_SCREEN] =
890 g_param_spec_object ("screen",
891 P_("Screen"),
892 P_("The screen where this window will be displayed"),
893 GDK_TYPE_SCREEN,
894 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
895
896 window_props[PROP_IS_ACTIVE] =
897 g_param_spec_boolean ("is-active",
898 P_("Is Active"),
899 P_("Whether the toplevel is the current active window"),
900 FALSE,
901 GTK_PARAM_READABLE);
902
903 window_props[PROP_HAS_TOPLEVEL_FOCUS] =
904 g_param_spec_boolean ("has-toplevel-focus",
905 P_("Focus in Toplevel"),
906 P_("Whether the input focus is within this GtkWindow"),
907 FALSE,
908 GTK_PARAM_READABLE);
909
910 window_props[PROP_TYPE_HINT] =
911 g_param_spec_enum ("type-hint",
912 P_("Type hint"),
913 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
914 GDK_TYPE_WINDOW_TYPE_HINT,
915 GDK_WINDOW_TYPE_HINT_NORMAL,
916 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
917
918 window_props[PROP_SKIP_TASKBAR_HINT] =
919 g_param_spec_boolean ("skip-taskbar-hint",
920 P_("Skip taskbar"),
921 P_("TRUE if the window should not be in the task bar."),
922 FALSE,
923 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
924
925 window_props[PROP_SKIP_PAGER_HINT] =
926 g_param_spec_boolean ("skip-pager-hint",
927 P_("Skip pager"),
928 P_("TRUE if the window should not be in the pager."),
929 FALSE,
930 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
931
932 window_props[PROP_URGENCY_HINT] =
933 g_param_spec_boolean ("urgency-hint",
934 P_("Urgent"),
935 P_("TRUE if the window should be brought to the user's attention."),
936 FALSE,
937 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
938
939 /**
940 * GtkWindow:accept-focus:
941 *
942 * Whether the window should receive the input focus.
943 *
944 * Since: 2.4
945 */
946 window_props[PROP_ACCEPT_FOCUS] =
947 g_param_spec_boolean ("accept-focus",
948 P_("Accept focus"),
949 P_("TRUE if the window should receive the input focus."),
950 TRUE,
951 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
952
953 /**
954 * GtkWindow:focus-on-map:
955 *
956 * Whether the window should receive the input focus when mapped.
957 *
958 * Since: 2.6
959 */
960 window_props[PROP_FOCUS_ON_MAP] =
961 g_param_spec_boolean ("focus-on-map",
962 P_("Focus on map"),
963 P_("TRUE if the window should receive the input focus when mapped."),
964 TRUE,
965 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
966
967 /**
968 * GtkWindow:decorated:
969 *
970 * Whether the window should be decorated by the window manager.
971 *
972 * Since: 2.4
973 */
974 window_props[PROP_DECORATED] =
975 g_param_spec_boolean ("decorated",
976 P_("Decorated"),
977 P_("Whether the window should be decorated by the window manager"),
978 TRUE,
979 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
980
981 /**
982 * GtkWindow:deletable:
983 *
984 * Whether the window frame should have a close button.
985 *
986 * Since: 2.10
987 */
988 window_props[PROP_DELETABLE] =
989 g_param_spec_boolean ("deletable",
990 P_("Deletable"),
991 P_("Whether the window frame should have a close button"),
992 TRUE,
993 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
994
995 /**
996 * GtkWindow:has-resize-grip:
997 *
998 * Whether the window has a corner resize grip.
999 *
1000 * Note that the resize grip is only shown if the window is
1001 * actually resizable and not maximized. Use
1002 * #GtkWindow:resize-grip-visible to find out if the resize
1003 * grip is currently shown.
1004 *
1005 * Deprecated: 3.14: Resize grips have been removed.
1006 *
1007 * Since: 3.0
1008 */
1009 window_props[PROP_HAS_RESIZE_GRIP] =
1010 g_param_spec_boolean ("has-resize-grip",
1011 P_("Resize grip"),
1012 P_("Specifies whether the window should have a resize grip"),
1013 FALSE,
1014 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1015
1016 /**
1017 * GtkWindow:resize-grip-visible:
1018 *
1019 * Whether a corner resize grip is currently shown.
1020 *
1021 * Deprecated: 3.14: Resize grips have been removed.
1022 *
1023 * Since: 3.0
1024 */
1025 window_props[PROP_RESIZE_GRIP_VISIBLE] =
1026 g_param_spec_boolean ("resize-grip-visible",
1027 P_("Resize grip is visible"),
1028 P_("Specifies whether the window's resize grip is visible."),
1029 FALSE,
1030 GTK_PARAM_READABLE|G_PARAM_DEPRECATED);
1031
1032 /**
1033 * GtkWindow:gravity:
1034 *
1035 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
1036 * more details about window gravity.
1037 *
1038 * Since: 2.4
1039 */
1040 window_props[PROP_GRAVITY] =
1041 g_param_spec_enum ("gravity",
1042 P_("Gravity"),
1043 P_("The window gravity of the window"),
1044 GDK_TYPE_GRAVITY,
1045 GDK_GRAVITY_NORTH_WEST,
1046 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1047
1048 /**
1049 * GtkWindow:transient-for:
1050 *
1051 * The transient parent of the window. See gtk_window_set_transient_for() for
1052 * more details about transient windows.
1053 *
1054 * Since: 2.10
1055 */
1056 window_props[PROP_TRANSIENT_FOR] =
1057 g_param_spec_object ("transient-for",
1058 P_("Transient for Window"),
1059 P_("The transient parent of the dialog"),
1060 GTK_TYPE_WINDOW,
1061 GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY);
1062
1063 /**
1064 * GtkWindow:attached-to:
1065 *
1066 * The widget to which this window is attached.
1067 * See gtk_window_set_attached_to().
1068 *
1069 * Examples of places where specifying this relation is useful are
1070 * for instance a #GtkMenu created by a #GtkComboBox, a completion
1071 * popup window created by #GtkEntry or a typeahead search entry
1072 * created by #GtkTreeView.
1073 *
1074 * Since: 3.4
1075 */
1076 window_props[PROP_ATTACHED_TO] =
1077 g_param_spec_object ("attached-to",
1078 P_("Attached to Widget"),
1079 P_("The widget where the window is attached"),
1080 GTK_TYPE_WIDGET,
1081 GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY);
1082
1083 window_props[PROP_IS_MAXIMIZED] =
1084 g_param_spec_boolean ("is-maximized",
1085 P_("Is maximized"),
1086 P_("Whether the window is maximized"),
1087 FALSE,
1088 GTK_PARAM_READABLE);
1089
1090 /**
1091 * GtkWindow:application:
1092 *
1093 * The #GtkApplication associated with the window.
1094 *
1095 * The application will be kept alive for at least as long as it
1096 * has any windows associated with it (see g_application_hold()
1097 * for a way to keep it alive without windows).
1098 *
1099 * Normally, the connection between the application and the window
1100 * will remain until the window is destroyed, but you can explicitly
1101 * remove it by setting the :application property to %NULL.
1102 *
1103 * Since: 3.0
1104 */
1105 window_props[PROP_APPLICATION] =
1106 g_param_spec_object ("application",
1107 P_("GtkApplication"),
1108 P_("The GtkApplication for the window"),
1109 GTK_TYPE_APPLICATION,
1110 GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
1111
1112 g_object_class_install_properties (gobject_class, LAST_ARG, window_props);
1113
1114 /* Style properties.
1115 */
1116 gtk_widget_class_install_style_property (widget_class,
1117 g_param_spec_string ("decoration-button-layout",
1118 P_("Decorated button layout"),
1119 P_("Decorated button layout"),
1120 "menu:close",
1121 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
1122
1123 gtk_widget_class_install_style_property (widget_class,
1124 g_param_spec_int ("decoration-resize-handle",
1125 P_("Decoration resize handle size"),
1126 P_("Decoration resize handle size"),
1127 0, G_MAXINT,
1128 20, GTK_PARAM_READWRITE));
1129
1130 /**
1131 * GtkWindow:set-focus:
1132 * @window: the window which received the signal
1133 * @widget: (nullable): the newly focused widget (or %NULL for no focus)
1134 *
1135 * This signal is emitted whenever the currently focused widget in
1136 * this window changes.
1137 *
1138 * Since: 2.24
1139 */
1140 window_signals[SET_FOCUS] =
1141 g_signal_new (I_("set-focus"),
1142 G_TYPE_FROM_CLASS (gobject_class),
1143 G_SIGNAL_RUN_LAST,
1144 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
1145 NULL, NULL,
1146 _gtk_marshal_VOID__OBJECT,
1147 G_TYPE_NONE, 1,
1148 GTK_TYPE_WIDGET);
1149
1150 /**
1151 * GtkWindow::activate-focus:
1152 * @window: the window which received the signal
1153 *
1154 * The ::activate-focus signal is a
1155 * [keybinding signal][GtkBindingSignal]
1156 * which gets emitted when the user activates the currently
1157 * focused widget of @window.
1158 */
1159 window_signals[ACTIVATE_FOCUS] =
1160 g_signal_new (I_("activate-focus"),
1161 G_TYPE_FROM_CLASS (gobject_class),
1162 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1163 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1164 NULL, NULL,
1165 _gtk_marshal_VOID__VOID,
1166 G_TYPE_NONE,
1167 0);
1168
1169 /**
1170 * GtkWindow::activate-default:
1171 * @window: the window which received the signal
1172 *
1173 * The ::activate-default signal is a
1174 * [keybinding signal][GtkBindingSignal]
1175 * which gets emitted when the user activates the default widget
1176 * of @window.
1177 */
1178 window_signals[ACTIVATE_DEFAULT] =
1179 g_signal_new (I_("activate-default"),
1180 G_TYPE_FROM_CLASS (gobject_class),
1181 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1182 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1183 NULL, NULL,
1184 _gtk_marshal_VOID__VOID,
1185 G_TYPE_NONE,
1186 0);
1187
1188 /**
1189 * GtkWindow::keys-changed:
1190 * @window: the window which received the signal
1191 *
1192 * The ::keys-changed signal gets emitted when the set of accelerators
1193 * or mnemonics that are associated with @window changes.
1194 */
1195 window_signals[KEYS_CHANGED] =
1196 g_signal_new (I_("keys-changed"),
1197 G_TYPE_FROM_CLASS (gobject_class),
1198 G_SIGNAL_RUN_FIRST,
1199 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1200 NULL, NULL,
1201 _gtk_marshal_VOID__VOID,
1202 G_TYPE_NONE,
1203 0);
1204
1205 /**
1206 * GtkWindow::enable-debugging:
1207 * @window: the window on which the signal is emitted
1208 * @toggle: toggle the debugger
1209 *
1210 * The ::enable-debugging signal is a [keybinding signal][GtkBindingSignal]
1211 * which gets emitted when the user enables or disables interactive
1212 * debugging. When @toggle is %TRUE, interactive debugging is toggled
1213 * on or off, when it is %FALSE, the debugger will be pointed at the
1214 * widget under the pointer.
1215 *
1216 * The default bindings for this signal are Ctrl-Shift-I
1217 * and Ctrl-Shift-D.
1218 *
1219 * Return: %TRUE if the key binding was handled
1220 */
1221 window_signals[ENABLE_DEBUGGING] =
1222 g_signal_new (I_("enable-debugging"),
1223 G_TYPE_FROM_CLASS (gobject_class),
1224 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1225 G_STRUCT_OFFSET (GtkWindowClass, enable_debugging),
1226 NULL, NULL,
1227 _gtk_marshal_BOOLEAN__BOOLEAN,
1228 G_TYPE_BOOLEAN,
1229 1, G_TYPE_BOOLEAN);
1230
1231 /*
1232 * Key bindings
1233 */
1234
1235 binding_set = gtk_binding_set_by_class (klass);
1236
1237 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1238 "activate-focus", 0);
1239 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1240 "activate-focus", 0);
1241
1242 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1243 "activate-default", 0);
1244 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1245 "activate-default", 0);
1246 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1247 "activate-default", 0);
1248
1249 gtk_binding_entry_add_signal (binding_set, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
1250 "enable-debugging", 1,
1251 G_TYPE_BOOLEAN, FALSE);
1252 gtk_binding_entry_add_signal (binding_set, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
1253 "enable-debugging", 1,
1254 G_TYPE_BOOLEAN, TRUE);
1255
1256 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1257 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1258 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1259 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1260
1261 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1262 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1263 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1264 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1265
1266 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
1267 gtk_widget_class_set_css_name (widget_class, "window");
1268}
1269
1270/**
1271 * gtk_window_is_maximized:
1272 * @window: a #GtkWindow
1273 *
1274 * Retrieves the current maximized state of @window.
1275 *
1276 * Note that since maximization is ultimately handled by the window
1277 * manager and happens asynchronously to an application request, you
1278 * shouldn’t assume the return value of this function changing
1279 * immediately (or at all), as an effect of calling
1280 * gtk_window_maximize() or gtk_window_unmaximize().
1281 *
1282 * Returns: whether the window has a maximized state.
1283 *
1284 * Since: 3.12
1285 */
1286gboolean
1287gtk_window_is_maximized (GtkWindow *window)
1288{
1289 GtkWindowPrivate *priv = window->priv;
1290
1291 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1292
1293 return priv->maximized;
1294}
1295
1296void
1297_gtk_window_toggle_maximized (GtkWindow *window)
1298{
1299 GtkWindowPrivate *priv = window->priv;
1300
1301 if (priv->maximized)
1302 gtk_window_unmaximize (window);
1303 else
1304 gtk_window_maximize (window);
1305}
1306
1307static gboolean
1308send_delete_event (gpointer data)
1309{
1310 GtkWidget *window = data;
1311 GtkWindowPrivate *priv = GTK_WINDOW (window)->priv;
1312
1313 GdkEvent *event;
1314
1315 event = gdk_event_new (GDK_DELETE);
1316
1317 event->any.window = g_object_ref (_gtk_widget_get_window (window));
1318 event->any.send_event = TRUE;
1319 priv->delete_event_handler = 0;
1320
1321 gtk_main_do_event (event);
1322 gdk_event_free (event);
1323
1324 return G_SOURCE_REMOVE;
1325}
1326
1327/**
1328 * gtk_window_close:
1329 * @window: a #GtkWindow
1330 *
1331 * Requests that the window is closed, similar to what happens
1332 * when a window manager close button is clicked.
1333 *
1334 * This function can be used with close buttons in custom
1335 * titlebars.
1336 *
1337 * Since: 3.10
1338 */
1339void
1340gtk_window_close (GtkWindow *window)
1341{
1342 if (!_gtk_widget_get_realized (GTK_WIDGET (window)))
1343 return;
1344
1345 window->priv->delete_event_handler = gdk_threads_add_idle (send_delete_event, window);
1346 g_source_set_name_by_id (window->priv->delete_event_handler, "[gtk+] send_delete_event");
1347}
1348
1349static void
1350popover_destroy (GtkWindowPopover *popover)
1351{
1352 if (popover->unmap_id)
1353 {
1354 g_signal_handler_disconnect (popover->widget, popover->unmap_id);
1355 popover->unmap_id = 0;
1356 }
1357
1358 if (popover->widget && _gtk_widget_get_parent (popover->widget))
1359 gtk_widget_unparent (popover->widget);
1360
1361 if (popover->window)
1362 gdk_window_destroy (popover->window);
1363
1364 g_free (popover);
1365}
1366
1367static gboolean
1368gtk_window_titlebar_action (GtkWindow *window,
1369 const GdkEvent *event,
1370 guint button,
1371 gint n_press)
1372{
1373 GtkSettings *settings;
1374 gchar *action = NULL;
1375 gboolean retval = TRUE;
1376
1377 settings = gtk_widget_get_settings (GTK_WIDGET (window));
1378 switch (button)
1379 {
1380 case GDK_BUTTON_PRIMARY:
1381 if (n_press == 2)
1382 g_object_get (settings, "gtk-titlebar-double-click", &action, NULL);
1383 break;
1384 case GDK_BUTTON_MIDDLE:
1385 g_object_get (settings, "gtk-titlebar-middle-click", &action, NULL);
1386 break;
1387 case GDK_BUTTON_SECONDARY:
1388 g_object_get (settings, "gtk-titlebar-right-click", &action, NULL);
1389 break;
1390 }
1391
1392 if (action == NULL)
1393 retval = FALSE;
1394 else if (g_str_equal (action, "none"))
1395 retval = FALSE;
1396 /* treat all maximization variants the same */
1397 else if (g_str_has_prefix (action, "toggle-maximize"))
1398 {
1399 /*
1400 * gtk header bar won't show the maximize button if the following
1401 * properties are not met, apply the same to title bar actions for
1402 * consistency.
1403 */
1404 if (gtk_window_get_resizable (window) &&
1405 gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL)
1406 _gtk_window_toggle_maximized (window);
1407 }
1408 else if (g_str_equal (action, "lower"))
1409 gdk_window_lower (_gtk_widget_get_window (GTK_WIDGET (window)));
1410 else if (g_str_equal (action, "minimize"))
1411 gdk_window_iconify (_gtk_widget_get_window (GTK_WIDGET (window)));
1412 else if (g_str_equal (action, "menu"))
1413 gtk_window_do_popup (window, (GdkEventButton*) event);
1414 else
1415 {
1416 g_warning ("Unsupported titlebar action %s", action);
1417 retval = FALSE;
1418 }
1419
1420 g_free (action);
1421
1422 return retval;
1423}
1424
1425static void
1426multipress_gesture_pressed_cb (GtkGestureMultiPress *gesture,
1427 gint n_press,
1428 gdouble x,
1429 gdouble y,
1430 GtkWindow *window)
1431{
1432 GtkWidget *event_widget, *widget;
1433 gboolean window_drag = FALSE;
1434 GdkEventSequence *sequence;
1435 GtkWindowRegion region;
1436 GtkWindowPrivate *priv;
1437 const GdkEvent *event;
1438 guint button;
1439
1440 widget = GTK_WIDGET (window);
1441 priv = gtk_window_get_instance_private (window);
1442 sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
1443 button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
1444 event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
1445
1446 if (!event)
1447 return;
1448
1449 if (n_press > 1)
1450 gtk_gesture_set_state (priv->drag_gesture, GTK_EVENT_SEQUENCE_DENIED);
1451
1452 region = get_active_region_type (window, (GdkEventAny*) event, x, y);
1453
1454 if (gdk_display_device_is_grabbed (gtk_widget_get_display (widget),
1455 gtk_gesture_get_device (GTK_GESTURE (gesture))))
1456 {
1457 gtk_gesture_set_state (priv->drag_gesture, GTK_EVENT_SEQUENCE_DENIED);
1458 return;
1459 }
1460
1461 if (button == GDK_BUTTON_SECONDARY && region == GTK_WINDOW_REGION_TITLE)
1462 {
1463 if (gtk_window_titlebar_action (window, event, button, n_press))
1464 gtk_gesture_set_sequence_state (GTK_GESTURE (gesture),
1465 sequence, GTK_EVENT_SEQUENCE_CLAIMED);
1466
1467 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
1468 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (priv->drag_gesture));
1469 return;
1470 }
1471 else if (button == GDK_BUTTON_MIDDLE && region == GTK_WINDOW_REGION_TITLE)
1472 {
1473 if (gtk_window_titlebar_action (window, event, button, n_press))
1474 gtk_gesture_set_sequence_state (GTK_GESTURE (gesture),
1475 sequence, GTK_EVENT_SEQUENCE_CLAIMED);
1476 return;
1477 }
1478 else if (button != GDK_BUTTON_PRIMARY)
1479 return;
1480
1481 event_widget = gtk_get_event_widget ((GdkEvent*) event);
1482
1483 if (region == GTK_WINDOW_REGION_TITLE)
1484 gdk_window_raise (_gtk_widget_get_window (widget));
1485
1486 switch (region)
1487 {
1488 case GTK_WINDOW_REGION_CONTENT:
1489 if (event_widget != widget)
1490 gtk_widget_style_get (event_widget, "window-dragging", &window_drag, NULL);
1491
1492 if (!window_drag)
1493 {
1494 gtk_gesture_set_sequence_state (GTK_GESTURE (gesture),
1495 sequence, GTK_EVENT_SEQUENCE_DENIED);
1496 return;
1497 }
1498 /* fall thru */
1499 case GTK_WINDOW_REGION_TITLE:
1500 if (n_press == 2)
1501 gtk_window_titlebar_action (window, event, button, n_press);
1502
1503 if (gtk_widget_has_grab (widget))
1504 gtk_gesture_set_sequence_state (GTK_GESTURE (gesture),
1505 sequence, GTK_EVENT_SEQUENCE_CLAIMED);
1506 break;
1507 default:
1508 if (!priv->maximized)
1509 {
1510 gdouble x_root, y_root;
1511
1512 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
1513
1514 gdk_event_get_root_coords (event, &x_root, &y_root);
1515 gdk_window_begin_resize_drag_for_device (_gtk_widget_get_window (widget),
1516 (GdkWindowEdge) region,
1517 gdk_event_get_device ((GdkEvent *) event),
1518 GDK_BUTTON_PRIMARY,
1519 x_root, y_root,
1520 gdk_event_get_time (event));
1521
1522 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
1523 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (priv->drag_gesture));
1524 }
1525
1526 break;
1527 }
1528}
1529
1530static void
1531drag_gesture_begin_cb (GtkGestureDrag *gesture,
1532 gdouble x,
1533 gdouble y,
1534 GtkWindow *window)
1535{
1536 GdkEventSequence *sequence;
1537 GtkWindowRegion region;
1538 const GdkEvent *event;
1539
1540 sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
1541 event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
1542
1543 if (!event)
1544 return;
1545
1546 region = get_active_region_type (window, (GdkEventAny*) event, x, y);
1547
1548 if (region != GTK_WINDOW_REGION_TITLE)
1549 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
1550}
1551
1552static void
1553drag_gesture_update_cb (GtkGestureDrag *gesture,
1554 gdouble offset_x,
1555 gdouble offset_y,
1556 GtkWindow *window)
1557{
1558 GtkWindowPrivate *priv = window->priv;
1559 gint double_click_distance;
1560 GtkSettings *settings;
1561
1562 settings = gtk_widget_get_settings (GTK_WIDGET (window));
1563 g_object_get (settings,
1564 "gtk-double-click-distance", &double_click_distance,
1565 NULL);
1566
1567 if (ABS (offset_x) > double_click_distance ||
1568 ABS (offset_y) > double_click_distance)
1569 {
1570 GdkEventSequence *sequence;
1571 gdouble start_x, start_y;
1572 gint x_root, y_root;
1573 const GdkEvent *event;
1574 GtkWidget *event_widget;
1575
1576 sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
1577 event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
1578 event_widget = gtk_get_event_widget ((GdkEvent *) event);
1579
1580 /* Check whether the target widget should be left alone at handling
1581 * the sequence, this is better done late to give room for gestures
1582 * there to go denied.
1583 *
1584 * Besides claiming gestures, we must bail out too if there's gestures
1585 * in the "none" state at this point, as those are still handling events
1586 * and can potentially go claimed, and we don't want to stop the target
1587 * widget from doing anything.
1588 */
1589 if (event_widget != GTK_WIDGET (window) &&
1590 !gtk_widget_has_grab (event_widget) &&
1591 _gtk_widget_consumes_motion (event_widget, sequence))
1592 {
1593 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
1594 return;
1595 }
1596
1597 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
1598
1599 gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
1600 gdk_window_get_root_coords (_gtk_widget_get_window (GTK_WIDGET (window)),
1601 start_x, start_y, &x_root, &y_root);
1602
1603 gdk_window_begin_move_drag_for_device (_gtk_widget_get_window (GTK_WIDGET (window)),
1604 gtk_gesture_get_device (GTK_GESTURE (gesture)),
1605 gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)),
1606 x_root, y_root,
1607 gtk_get_current_event_time ());
1608
1609 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
1610 gtk_event_controller_reset (GTK_EVENT_CONTROLLER (priv->multipress_gesture));
1611 }
1612}
1613
1614static void
1615node_style_changed_cb (GtkCssNode *node,
1616 GtkCssStyleChange *change,
1617 GtkWidget *widget)
1618{
1619 if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP))
1620 gtk_widget_queue_resize (widget);
1621 else
1622 gtk_widget_queue_draw (widget);
1623}
1624
1625static void
1626gtk_window_init (GtkWindow *window)
1627{
1628 GtkWindowPrivate *priv;
1629 GtkWidget *widget;
1630 GtkCssNode *widget_node;
1631
1632 widget = GTK_WIDGET (window);
1633
1634 window->priv = gtk_window_get_instance_private (window);
1635 priv = window->priv;
1636
1637 gtk_widget_set_has_window (widget, TRUE);
1638 _gtk_widget_set_is_toplevel (widget, TRUE);
1639 _gtk_widget_set_anchored (widget, TRUE);
1640
1641 gtk_container_set_default_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1642
1643 priv->title = NULL;
1644 priv->wmclass_name = g_strdup (g_get_prgname ());
1645 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1646 priv->wm_role = NULL;
1647 priv->geometry_info = NULL;
1648 priv->type = GTK_WINDOW_TOPLEVEL;
1649 priv->focus_widget = NULL;
1650 priv->default_widget = NULL;
1651 priv->configure_request_count = 0;
1652 priv->resizable = TRUE;
1653 priv->configure_notify_received = FALSE;
1654 priv->position = GTK_WIN_POS_NONE;
1655 priv->need_default_size = TRUE;
1656 priv->need_default_position = TRUE;
1657 priv->modal = FALSE;
1658 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1659 priv->decorated = TRUE;
1660 priv->mnemonic_modifier = GDK_MOD1_MASK;
1661 priv->screen = gdk_screen_get_default ();
1662
1663 priv->accept_focus = TRUE;
1664 priv->focus_on_map = TRUE;
1665 priv->deletable = TRUE;
1666 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1667 priv->startup_id = NULL;
1668 priv->initial_timestamp = GDK_CURRENT_TIME;
1669 priv->mnemonics_visible = TRUE;
1670 priv->focus_visible = TRUE;
1671 priv->initial_fullscreen_monitor = -1;
1672
1673 g_object_ref_sink (window);
1674 priv->has_user_ref_count = TRUE;
1675 toplevel_list = g_slist_prepend (toplevel_list, window);
1676 gtk_window_update_debugging ();
1677
1678 if (priv->screen)
1679 g_signal_connect_object (priv->screen, "composited-changed",
1680 G_CALLBACK (gtk_window_on_composited_changed), window, 0);
1681
1682#ifdef GDK_WINDOWING_X11
1683 g_signal_connect_object (gtk_settings_get_for_screen (priv->screen),
1684 "notify::gtk-application-prefer-dark-theme",
1685 G_CALLBACK (gtk_window_on_theme_variant_changed), window, 0);
1686#endif
1687
1688 widget_node = gtk_widget_get_css_node (GTK_WIDGET (window));
1689 priv->decoration_node = gtk_css_node_new ();
1690 gtk_css_node_set_name (priv->decoration_node, I_("decoration"));
1691 gtk_css_node_set_parent (priv->decoration_node, widget_node);
1692 gtk_css_node_set_state (priv->decoration_node, gtk_css_node_get_state (widget_node));
1693 g_signal_connect_object (priv->decoration_node, "style-changed", G_CALLBACK (node_style_changed_cb), window, 0);
1694 g_object_unref (priv->decoration_node);
1695
1696 gtk_css_node_add_class (widget_node, g_quark_from_static_string (GTK_STYLE_CLASS_BACKGROUND));
1697
1698 priv->scale = gtk_widget_get_scale_factor (widget);
1699
1700 gtk_drag_dest_set (GTK_WIDGET (window),
1701 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
1702 dnd_dest_targets, G_N_ELEMENTS (dnd_dest_targets),
1703 GDK_ACTION_MOVE);
1704}
1705
1706static void
1707gtk_window_constructed (GObject *object)
1708{
1709 GtkWindow *window = GTK_WINDOW (object);
1710 GtkWindowPrivate *priv = window->priv;
1711 gboolean is_plug;
1712
1713 G_OBJECT_CLASS (gtk_window_parent_class)->constructed (object);
1714
1715#ifdef GDK_WINDOWING_X11
1716 is_plug = GTK_IS_PLUG (window);
1717#else
1718 is_plug = FALSE;
1719#endif
1720
1721 if (priv->type == GTK_WINDOW_TOPLEVEL && !is_plug)
1722 {
1723 priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (object));
1724 gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture), 0);
1725 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
1726 GTK_PHASE_NONE);
1727 g_signal_connect (priv->multipress_gesture, "pressed",
1728 G_CALLBACK (multipress_gesture_pressed_cb), object);
1729
1730 priv->drag_gesture = gtk_gesture_drag_new (GTK_WIDGET (object));
1731 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->drag_gesture),
1732 GTK_PHASE_CAPTURE);
1733 g_signal_connect (priv->drag_gesture, "drag-begin",
1734 G_CALLBACK (drag_gesture_begin_cb), object);
1735 g_signal_connect (priv->drag_gesture, "drag-update",
1736 G_CALLBACK (drag_gesture_update_cb), object);
1737 }
1738}
1739
1740static void
1741gtk_window_set_property (GObject *object,
1742 guint prop_id,
1743 const GValue *value,
1744 GParamSpec *pspec)
1745{
1746 GtkWindow *window = GTK_WINDOW (object);
1747 GtkWindowPrivate *priv = window->priv;
1748
1749 switch (prop_id)
1750 {
1751 case PROP_TYPE:
1752 priv->type = g_value_get_enum (value);
1753 break;
1754 case PROP_TITLE:
1755 gtk_window_set_title (window, g_value_get_string (value));
1756 break;
1757 case PROP_ROLE:
1758 gtk_window_set_role (window, g_value_get_string (value));
1759 break;
1760 case PROP_STARTUP_ID:
1761 gtk_window_set_startup_id (window, g_value_get_string (value));
1762 break;
1763 case PROP_RESIZABLE:
1764 gtk_window_set_resizable (window, g_value_get_boolean (value));
1765 break;
1766 case PROP_MODAL:
1767 gtk_window_set_modal (window, g_value_get_boolean (value));
1768 break;
1769 case PROP_WIN_POS:
1770 gtk_window_set_position (window, g_value_get_enum (value));
1771 break;
1772 case PROP_DEFAULT_WIDTH:
1773 gtk_window_set_default_size_internal (window,
1774 TRUE, g_value_get_int (value),
1775 FALSE, -1, FALSE);
1776 break;
1777 case PROP_DEFAULT_HEIGHT:
1778 gtk_window_set_default_size_internal (window,
1779 FALSE, -1,
1780 TRUE, g_value_get_int (value), FALSE);
1781 break;
1782 case PROP_DESTROY_WITH_PARENT:
1783 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1784 break;
1785 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1786 gtk_window_set_hide_titlebar_when_maximized (window, g_value_get_boolean (value));
1787 break;
1788 case PROP_ICON:
1789 gtk_window_set_icon (window,
1790 g_value_get_object (value));
1791 break;
1792 case PROP_ICON_NAME:
1793 gtk_window_set_icon_name (window, g_value_get_string (value));
1794 break;
1795 case PROP_SCREEN:
1796 gtk_window_set_screen (window, g_value_get_object (value));
1797 break;
1798 case PROP_TYPE_HINT:
1799 gtk_window_set_type_hint (window,
1800 g_value_get_enum (value));
1801 break;
1802 case PROP_SKIP_TASKBAR_HINT:
1803 gtk_window_set_skip_taskbar_hint (window,
1804 g_value_get_boolean (value));
1805 break;
1806 case PROP_SKIP_PAGER_HINT:
1807 gtk_window_set_skip_pager_hint (window,
1808 g_value_get_boolean (value));
1809 break;
1810 case PROP_URGENCY_HINT:
1811 gtk_window_set_urgency_hint (window,
1812 g_value_get_boolean (value));
1813 break;
1814 case PROP_ACCEPT_FOCUS:
1815 gtk_window_set_accept_focus (window,
1816 g_value_get_boolean (value));
1817 break;
1818 case PROP_FOCUS_ON_MAP:
1819 gtk_window_set_focus_on_map (window,
1820 g_value_get_boolean (value));
1821 break;
1822 case PROP_DECORATED:
1823 gtk_window_set_decorated (window, g_value_get_boolean (value));
1824 break;
1825 case PROP_DELETABLE:
1826 gtk_window_set_deletable (window, g_value_get_boolean (value));
1827 break;
1828 case PROP_GRAVITY:
1829 gtk_window_set_gravity (window, g_value_get_enum (value));
1830 break;
1831 case PROP_TRANSIENT_FOR:
1832 gtk_window_set_transient_for (window, g_value_get_object (value));
1833 break;
1834 case PROP_ATTACHED_TO:
1835 gtk_window_set_attached_to (window, g_value_get_object (value));
1836 break;
1837 case PROP_HAS_RESIZE_GRIP:
1838 /* Do nothing. */
1839 break;
1840 case PROP_APPLICATION:
1841 gtk_window_set_application (window, g_value_get_object (value));
1842 break;
1843 case PROP_MNEMONICS_VISIBLE:
1844 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1845 break;
1846 case PROP_FOCUS_VISIBLE:
1847 gtk_window_set_focus_visible (window, g_value_get_boolean (value));
1848 break;
1849 default:
1850 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1851 break;
1852 }
1853}
1854
1855static void
1856gtk_window_get_property (GObject *object,
1857 guint prop_id,
1858 GValue *value,
1859 GParamSpec *pspec)
1860{
1861 GtkWindow *window = GTK_WINDOW (object);
1862 GtkWindowPrivate *priv = window->priv;
1863
1864 switch (prop_id)
1865 {
1866 GtkWindowGeometryInfo *info;
1867 case PROP_TYPE:
1868 g_value_set_enum (value, priv->type);
1869 break;
1870 case PROP_ROLE:
1871 g_value_set_string (value, priv->wm_role);
1872 break;
1873 case PROP_TITLE:
1874 g_value_set_string (value, priv->title);
1875 break;
1876 case PROP_RESIZABLE:
1877 g_value_set_boolean (value, priv->resizable);
1878 break;
1879 case PROP_MODAL:
1880 g_value_set_boolean (value, priv->modal);
1881 break;
1882 case PROP_WIN_POS:
1883 g_value_set_enum (value, priv->position);
1884 break;
1885 case PROP_DEFAULT_WIDTH:
1886 info = gtk_window_get_geometry_info (window, FALSE);
1887 if (!info)
1888 g_value_set_int (value, -1);
1889 else
1890 g_value_set_int (value, info->default_width);
1891 break;
1892 case PROP_DEFAULT_HEIGHT:
1893 info = gtk_window_get_geometry_info (window, FALSE);
1894 if (!info)
1895 g_value_set_int (value, -1);
1896 else
1897 g_value_set_int (value, info->default_height);
1898 break;
1899 case PROP_DESTROY_WITH_PARENT:
1900 g_value_set_boolean (value, priv->destroy_with_parent);
1901 break;
1902 case PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED:
1903 g_value_set_boolean (value, priv->hide_titlebar_when_maximized);
1904 break;
1905 case PROP_ICON:
1906 g_value_set_object (value, gtk_window_get_icon (window));
1907 break;
1908 case PROP_ICON_NAME:
1909 g_value_set_string (value, gtk_window_get_icon_name (window));
1910 break;
1911 case PROP_SCREEN:
1912 g_value_set_object (value, priv->screen);
1913 break;
1914 case PROP_IS_ACTIVE:
1915 g_value_set_boolean (value, priv->is_active);
1916 break;
1917 case PROP_HAS_TOPLEVEL_FOCUS:
1918 g_value_set_boolean (value, priv->has_toplevel_focus);
1919 break;
1920 case PROP_TYPE_HINT:
1921 g_value_set_enum (value, priv->type_hint);
1922 break;
1923 case PROP_SKIP_TASKBAR_HINT:
1924 g_value_set_boolean (value,
1925 gtk_window_get_skip_taskbar_hint (window));
1926 break;
1927 case PROP_SKIP_PAGER_HINT:
1928 g_value_set_boolean (value,
1929 gtk_window_get_skip_pager_hint (window));
1930 break;
1931 case PROP_URGENCY_HINT:
1932 g_value_set_boolean (value,
1933 gtk_window_get_urgency_hint (window));
1934 break;
1935 case PROP_ACCEPT_FOCUS:
1936 g_value_set_boolean (value,
1937 gtk_window_get_accept_focus (window));
1938 break;
1939 case PROP_FOCUS_ON_MAP:
1940 g_value_set_boolean (value,
1941 gtk_window_get_focus_on_map (window));
1942 break;
1943 case PROP_DECORATED:
1944 g_value_set_boolean (value, gtk_window_get_decorated (window));
1945 break;
1946 case PROP_DELETABLE:
1947 g_value_set_boolean (value, gtk_window_get_deletable (window));
1948 break;
1949 case PROP_GRAVITY:
1950 g_value_set_enum (value, gtk_window_get_gravity (window));
1951 break;
1952 case PROP_TRANSIENT_FOR:
1953 g_value_set_object (value, gtk_window_get_transient_for (window));
1954 break;
1955 case PROP_ATTACHED_TO:
1956 g_value_set_object (value, gtk_window_get_attached_to (window));
1957 break;
1958 case PROP_HAS_RESIZE_GRIP:
1959 g_value_set_boolean (value, FALSE);
1960 break;
1961 case PROP_RESIZE_GRIP_VISIBLE:
1962 g_value_set_boolean (value, FALSE);
1963 break;
1964 case PROP_APPLICATION:
1965 g_value_set_object (value, gtk_window_get_application (window));
1966 break;
1967 case PROP_MNEMONICS_VISIBLE:
1968 g_value_set_boolean (value, priv->mnemonics_visible);
1969 break;
1970 case PROP_FOCUS_VISIBLE:
1971 g_value_set_boolean (value, priv->focus_visible);
1972 break;
1973 case PROP_IS_MAXIMIZED:
1974 g_value_set_boolean (value, gtk_window_is_maximized (window));
1975 break;
1976 default:
1977 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1978 break;
1979 }
1980}
1981
1982static void
1983gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1984{
1985 parent_buildable_iface = g_type_interface_peek_parent (iface);
1986 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1987 iface->parser_finished = gtk_window_buildable_parser_finished;
1988 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1989 iface->custom_finished = gtk_window_buildable_custom_finished;
1990 iface->add_child = gtk_window_buildable_add_child;
1991}
1992
1993static void
1994gtk_window_buildable_add_child (GtkBuildable *buildable,
1995 GtkBuilder *builder,
1996 GObject *child,
1997 const gchar *type)
1998{
1999 if (type && strcmp (type, "titlebar") == 0)
2000 gtk_window_set_titlebar (GTK_WINDOW (buildable), GTK_WIDGET (child));
2001 else if (!type)
2002 gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
2003 else
2004 GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
2005}
2006
2007static void
2008gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
2009 GtkBuilder *builder,
2010 const gchar *name,
2011 const GValue *value)
2012{
2013 GtkWindow *window = GTK_WINDOW (buildable);
2014 GtkWindowPrivate *priv = window->priv;
2015
2016 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
2017 priv->builder_visible = TRUE;
2018 else
2019 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
2020}
2021
2022typedef struct {
2023 gchar *name;
2024 gint line;
2025 gint col;
2026} ItemData;
2027
2028static void
2029item_data_free (gpointer data)
2030{
2031 ItemData *item_data = data;
2032
2033 g_free (item_data->name);
2034 g_free (item_data);
2035}
2036
2037static void
2038item_list_free (gpointer data)
2039{
2040 GSList *list = data;
2041
2042 g_slist_free_full (list, item_data_free);
2043}
2044
2045static void
2046gtk_window_buildable_parser_finished (GtkBuildable *buildable,
2047 GtkBuilder *builder)
2048{
2049 GtkWindow *window = GTK_WINDOW (buildable);
2050 GtkWindowPrivate *priv = window->priv;
2051 GObject *object;
2052 GSList *accels, *l;
2053
2054 if (priv->builder_visible)
2055 gtk_widget_show (GTK_WIDGET (buildable));
2056
2057 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
2058 for (l = accels; l; l = l->next)
2059 {
2060 ItemData *data = l->data;
2061
2062 object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col);
2063 if (!object)
2064 continue;
2065 gtk_window_add_accel_group (GTK_WINDOW (buildable), GTK_ACCEL_GROUP (object));
2066 }
2067
2068 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
2069
2070 parent_buildable_iface->parser_finished (buildable, builder);
2071}
2072
2073typedef struct {
2074 GObject *object;
2075 GtkBuilder *builder;
2076 GSList *items;
2077} GSListSubParserData;
2078
2079static void
2080window_start_element (GMarkupParseContext *context,
2081 const gchar *element_name,
2082 const gchar **names,
2083 const gchar **values,
2084 gpointer user_data,
2085 GError **error)
2086{
2087 GSListSubParserData *data = (GSListSubParserData*)user_data;
2088
2089 if (strcmp (element_name, "group") == 0)
2090 {
2091 const gchar *name;
2092 ItemData *item_data;
2093
2094 if (!_gtk_builder_check_parent (data->builder, context, "accel-groups", error))
2095 return;
2096
2097 if (!g_markup_collect_attributes (element_name, names, values, error,
2098 G_MARKUP_COLLECT_STRING, "name", &name,
2099 G_MARKUP_COLLECT_INVALID))
2100 {
2101 _gtk_builder_prefix_error (data->builder, context, error);
2102 return;
2103 }
2104
2105 item_data = g_new (ItemData, 1);
2106 item_data->name = g_strdup (name);
2107 g_markup_parse_context_get_position (context, &item_data->line, &item_data->col);
2108 data->items = g_slist_prepend (data->items, item_data);
2109 }
2110 else if (strcmp (element_name, "accel-groups") == 0)
2111 {
2112 if (!_gtk_builder_check_parent (data->builder, context, "object", error))
2113 return;
2114
2115 if (!g_markup_collect_attributes (element_name, names, values, error,
2116 G_MARKUP_COLLECT_INVALID, NULL, NULL,
2117 G_MARKUP_COLLECT_INVALID))
2118 _gtk_builder_prefix_error (data->builder, context, error);
2119 }
2120 else
2121 {
2122 _gtk_builder_error_unhandled_tag (data->builder, context,
2123 "GtkWindow", element_name,
2124 error);
2125 }
2126}
2127
2128static const GMarkupParser window_parser =
2129 {
2130 window_start_element
2131 };
2132
2133typedef struct {
2134 GObject *object;
2135 GtkBuilder *builder;
2136 gchar *name;
2137 gint line;
2138 gint col;
2139} NameSubParserData;
2140
2141static void
2142focus_start_element (GMarkupParseContext *context,
2143 const gchar *element_name,
2144 const gchar **names,
2145 const gchar **values,
2146 gpointer user_data,
2147 GError **error)
2148{
2149 NameSubParserData *data = (NameSubParserData*)user_data;
2150
2151 if (strcmp (element_name, "initial-focus") == 0)
2152 {
2153 const gchar *name;
2154
2155 if (!_gtk_builder_check_parent (data->builder, context, "object", error))
2156 return;
2157
2158 if (!g_markup_collect_attributes (element_name, names, values, error,
2159 G_MARKUP_COLLECT_STRING, "name", &name,
2160 G_MARKUP_COLLECT_INVALID))
2161 {
2162 _gtk_builder_prefix_error (data->builder, context, error);
2163 return;
2164 }
2165
2166 data->name = g_strdup (name);
2167 g_markup_parse_context_get_position (context, &data->line, &data->col);
2168 }
2169 else
2170 {
2171 _gtk_builder_error_unhandled_tag (data->builder, context,
2172 "GtkWindow", element_name,
2173 error);
2174 }
2175}
2176
2177static const GMarkupParser focus_parser =
2178{
2179 focus_start_element
2180};
2181
2182static gboolean
2183gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
2184 GtkBuilder *builder,
2185 GObject *child,
2186 const gchar *tagname,
2187 GMarkupParser *parser,
2188 gpointer *parser_data)
2189{
2190 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
2191 tagname, parser, parser_data))
2192 return TRUE;
2193
2194 if (strcmp (tagname, "accel-groups") == 0)
2195 {
2196 GSListSubParserData *data;
2197
2198 data = g_slice_new0 (GSListSubParserData);
2199 data->items = NULL;
2200 data->object = G_OBJECT (buildable);
2201 data->builder = builder;
2202
2203 *parser = window_parser;
2204 *parser_data = data;
2205
2206 return TRUE;
2207 }
2208
2209 if (strcmp (tagname, "initial-focus") == 0)
2210 {
2211 NameSubParserData *data;
2212
2213 data = g_slice_new0 (NameSubParserData);
2214 data->name = NULL;
2215 data->object = G_OBJECT (buildable);
2216 data->builder = builder;
2217
2218 *parser = focus_parser;
2219 *parser_data = data;
2220
2221 return TRUE;
2222 }
2223
2224 return FALSE;
2225}
2226
2227static void
2228gtk_window_buildable_custom_finished (GtkBuildable *buildable,
2229 GtkBuilder *builder,
2230 GObject *child,
2231 const gchar *tagname,
2232 gpointer user_data)
2233{
2234 parent_buildable_iface->custom_finished (buildable, builder, child,
2235 tagname, user_data);
2236
2237 if (strcmp (tagname, "accel-groups") == 0)
2238 {
2239 GSListSubParserData *data = (GSListSubParserData*)user_data;
2240
2241 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
2242 data->items, (GDestroyNotify) item_list_free);
2243
2244 g_slice_free (GSListSubParserData, data);
2245 }
2246
2247 if (strcmp (tagname, "initial-focus") == 0)
2248 {
2249 NameSubParserData *data = (NameSubParserData*)user_data;
2250
2251 if (data->name)
2252 {
2253 GObject *object;
2254
2255 object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col);
2256 if (object)
2257 gtk_window_set_focus (GTK_WINDOW (buildable), GTK_WIDGET (object));
2258 g_free (data->name);
2259 }
2260
2261 g_slice_free (NameSubParserData, data);
2262 }
2263}
2264
2265/**
2266 * gtk_window_new:
2267 * @type: type of window
2268 *
2269 * Creates a new #GtkWindow, which is a toplevel window that can
2270 * contain other widgets. Nearly always, the type of the window should
2271 * be #GTK_WINDOW_TOPLEVEL. If you’re implementing something like a
2272 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
2273 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
2274 * dialogs, though in some other toolkits dialogs are called “popups”.
2275 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
2276 * On X11, popup windows are not controlled by the
2277 * [window manager][gtk-X11-arch].
2278 *
2279 * If you simply want an undecorated window (no window borders), use
2280 * gtk_window_set_decorated(), don’t use #GTK_WINDOW_POPUP.
2281 *
2282 * All top-level windows created by gtk_window_new() are stored in
2283 * an internal top-level window list. This list can be obtained from
2284 * gtk_window_list_toplevels(). Due to Gtk+ keeping a reference to
2285 * the window internally, gtk_window_new() does not return a reference
2286 * to the caller.
2287 *
2288 * To delete a #GtkWindow, call gtk_widget_destroy().
2289 *
2290 * Returns: a new #GtkWindow.
2291 **/
2292GtkWidget*
2293gtk_window_new (GtkWindowType type)
2294{
2295 GtkWindow *window;
2296
2297 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
2298
2299 window = g_object_new (GTK_TYPE_WINDOW, "type", type, NULL);
2300
2301 return GTK_WIDGET (window);
2302}
2303
2304static void
2305gtk_window_set_title_internal (GtkWindow *window,
2306 const gchar *title,
2307 gboolean update_titlebar)
2308{
2309 GtkWindowPrivate *priv;
2310 GtkWidget *widget;
2311 char *new_title;
2312
2313 g_return_if_fail (GTK_IS_WINDOW (window));
2314
2315 priv = window->priv;
2316 widget = GTK_WIDGET (window);
2317
2318 new_title = g_strdup (title);
2319 g_free (priv->title);
2320 priv->title = new_title;
2321
2322 if (new_title == NULL)
2323 new_title = "";
2324
2325 if (_gtk_widget_get_realized (widget))
2326 gdk_window_set_title (_gtk_widget_get_window (widget), new_title);
2327
2328 if (update_titlebar && GTK_IS_HEADER_BAR (priv->title_box))
2329 gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), new_title);
2330
2331 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_TITLE]);
2332}
2333
2334/**
2335 * gtk_window_set_title:
2336 * @window: a #GtkWindow
2337 * @title: title of the window
2338 *
2339 * Sets the title of the #GtkWindow. The title of a window will be
2340 * displayed in its title bar; on the X Window System, the title bar
2341 * is rendered by the [window manager][gtk-X11-arch],
2342 * so exactly how the title appears to users may vary
2343 * according to a user’s exact configuration. The title should help a
2344 * user distinguish this window from other windows they may have
2345 * open. A good title might include the application name and current
2346 * document filename, for example.
2347 *
2348 **/
2349void
2350gtk_window_set_title (GtkWindow *window,
2351 const gchar *title)
2352{
2353 g_return_if_fail (GTK_IS_WINDOW (window));
2354
2355 gtk_window_set_title_internal (window, title, TRUE);
2356}
2357
2358/**
2359 * gtk_window_get_title:
2360 * @window: a #GtkWindow
2361 *
2362 * Retrieves the title of the window. See gtk_window_set_title().
2363 *
2364 * Returns: (nullable): the title of the window, or %NULL if none has
2365 * been set explicitly. The returned string is owned by the widget
2366 * and must not be modified or freed.
2367 **/
2368const gchar *
2369gtk_window_get_title (GtkWindow *window)
2370{
2371 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2372
2373 return window->priv->title;
2374}
2375
2376/**
2377 * gtk_window_set_wmclass:
2378 * @window: a #GtkWindow
2379 * @wmclass_name: window name hint
2380 * @wmclass_class: window class hint
2381 *
2382 * Don’t use this function. It sets the X Window System “class” and
2383 * “name” hints for a window. According to the ICCCM, you should
2384 * always set these to the same value for all windows in an
2385 * application, and GTK+ sets them to that value by default, so calling
2386 * this function is sort of pointless. However, you may want to call
2387 * gtk_window_set_role() on each window in your application, for the
2388 * benefit of the session manager. Setting the role allows the window
2389 * manager to restore window positions when loading a saved session.
2390 *
2391 **/
2392void
2393gtk_window_set_wmclass (GtkWindow *window,
2394 const gchar *wmclass_name,
2395 const gchar *wmclass_class)
2396{
2397 GtkWindowPrivate *priv;
2398
2399 g_return_if_fail (GTK_IS_WINDOW (window));
2400
2401 priv = window->priv;
2402
2403 g_free (priv->wmclass_name);
2404 priv->wmclass_name = g_strdup (wmclass_name);
2405
2406 g_free (priv->wmclass_class);
2407 priv->wmclass_class = g_strdup (wmclass_class);
2408
2409 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
2410 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!");
2411}
2412
2413/**
2414 * gtk_window_set_role:
2415 * @window: a #GtkWindow
2416 * @role: unique identifier for the window to be used when restoring a session
2417 *
2418 * This function is only useful on X11, not with other GTK+ targets.
2419 *
2420 * In combination with the window title, the window role allows a
2421 * [window manager][gtk-X11-arch] to identify "the
2422 * same" window when an application is restarted. So for example you
2423 * might set the “toolbox” role on your app’s toolbox window, so that
2424 * when the user restarts their session, the window manager can put
2425 * the toolbox back in the same place.
2426 *
2427 * If a window already has a unique title, you don’t need to set the
2428 * role, since the WM can use the title to identify the window when
2429 * restoring the session.
2430 *
2431 **/
2432void
2433gtk_window_set_role (GtkWindow *window,
2434 const gchar *role)
2435{
2436 GtkWindowPrivate *priv;
2437 GtkWidget *widget;
2438 char *new_role;
2439
2440 g_return_if_fail (GTK_IS_WINDOW (window));
2441
2442 priv = window->priv;
2443 widget = GTK_WIDGET (window);
2444
2445 new_role = g_strdup (role);
2446 g_free (priv->wm_role);
2447 priv->wm_role = new_role;
2448
2449 if (_gtk_widget_get_realized (widget))
2450 gdk_window_set_role (_gtk_widget_get_window (widget), priv->wm_role);
2451
2452 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_ROLE]);
2453}
2454
2455/**
2456 * gtk_window_set_startup_id:
2457 * @window: a #GtkWindow
2458 * @startup_id: a string with startup-notification identifier
2459 *
2460 * Startup notification identifiers are used by desktop environment to
2461 * track application startup, to provide user feedback and other
2462 * features. This function changes the corresponding property on the
2463 * underlying GdkWindow. Normally, startup identifier is managed
2464 * automatically and you should only use this function in special cases
2465 * like transferring focus from other processes. You should use this
2466 * function before calling gtk_window_present() or any equivalent
2467 * function generating a window map event.
2468 *
2469 * This function is only useful on X11, not with other GTK+ targets.
2470 *
2471 * Since: 2.12
2472 **/
2473void
2474gtk_window_set_startup_id (GtkWindow *window,
2475 const gchar *startup_id)
2476{
2477 GtkWindowPrivate *priv;
2478 GtkWidget *widget;
2479
2480 g_return_if_fail (GTK_IS_WINDOW (window));
2481
2482 priv = window->priv;
2483 widget = GTK_WIDGET (window);
2484
2485 g_free (priv->startup_id);
2486 priv->startup_id = g_strdup (startup_id);
2487
2488 if (_gtk_widget_get_realized (widget))
2489 {
2490 GdkWindow *gdk_window;
2491 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
2492
2493 gdk_window = _gtk_widget_get_window (widget);
2494
2495#ifdef GDK_WINDOWING_X11
2496 if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
2497 gdk_x11_window_set_user_time (gdk_window, timestamp);
2498#endif
2499
2500 /* Here we differentiate real and "fake" startup notification IDs,
2501 * constructed on purpose just to pass interaction timestamp
2502 */
2503 if (startup_id_is_fake (priv->startup_id))
2504 gtk_window_present_with_time (window, timestamp);
2505 else
2506 {
2507 gdk_window_set_startup_id (gdk_window,
2508 priv->startup_id);
2509
2510 /* If window is mapped, terminate the startup-notification too */
2511 if (_gtk_widget_get_mapped (widget) &&
2512 !disable_startup_notification)
2513 gdk_notify_startup_complete_with_id (priv->startup_id);
2514 }
2515 }
2516
2517 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_STARTUP_ID]);
2518}
2519
2520/**
2521 * gtk_window_get_role:
2522 * @window: a #GtkWindow
2523 *
2524 * Returns the role of the window. See gtk_window_set_role() for
2525 * further explanation.
2526 *
2527 * Returns: (nullable): the role of the window if set, or %NULL. The
2528 * returned is owned by the widget and must not be modified or freed.
2529 **/
2530const gchar *
2531gtk_window_get_role (GtkWindow *window)
2532{
2533 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2534
2535 return window->priv->wm_role;
2536}
2537
2538/**
2539 * gtk_window_set_focus:
2540 * @window: a #GtkWindow
2541 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
2542 * any focus widget for the toplevel window.
2543 *
2544 * If @focus is not the current focus widget, and is focusable, sets
2545 * it as the focus widget for the window. If @focus is %NULL, unsets
2546 * the focus widget for this window. To set the focus to a particular
2547 * widget in the toplevel, it is usually more convenient to use
2548 * gtk_widget_grab_focus() instead of this function.
2549 **/
2550void
2551gtk_window_set_focus (GtkWindow *window,
2552 GtkWidget *focus)
2553{
2554 GtkWindowPrivate *priv;
2555 GtkWidget *parent;
2556
2557 g_return_if_fail (GTK_IS_WINDOW (window));
2558
2559 priv = window->priv;
2560
2561 if (focus)
2562 {
2563 g_return_if_fail (GTK_IS_WIDGET (focus));
2564 g_return_if_fail (gtk_widget_get_can_focus (focus));
2565 }
2566
2567 if (focus)
2568 {
2569 if (!gtk_widget_get_visible (GTK_WIDGET (window)))
2570 priv->initial_focus = focus;
2571 else
2572 gtk_widget_grab_focus (focus);
2573 }
2574 else
2575 {
2576 /* Clear the existing focus chain, so that when we focus into
2577 * the window again, we start at the beginnning.
2578 */
2579 GtkWidget *widget = priv->focus_widget;
2580 if (widget)
2581 {
2582 while ((parent = _gtk_widget_get_parent (widget)))
2583 {
2584 widget = parent;
2585 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
2586 }
2587 }
2588
2589 _gtk_window_internal_set_focus (window, NULL);
2590 }
2591}
2592
2593void
2594_gtk_window_internal_set_focus (GtkWindow *window,
2595 GtkWidget *focus)
2596{
2597 GtkWindowPrivate *priv;
2598
2599 g_return_if_fail (GTK_IS_WINDOW (window));
2600
2601 priv = window->priv;
2602
2603 priv->initial_focus = NULL;
2604 if ((priv->focus_widget != focus) ||
2605 (focus && !gtk_widget_has_focus (focus)))
2606 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
2607}
2608
2609/**
2610 * gtk_window_set_default:
2611 * @window: a #GtkWindow
2612 * @default_widget: (allow-none): widget to be the default, or %NULL
2613 * to unset the default widget for the toplevel
2614 *
2615 * The default widget is the widget that’s activated when the user
2616 * presses Enter in a dialog (for example). This function sets or
2617 * unsets the default widget for a #GtkWindow. When setting (rather
2618 * than unsetting) the default widget it’s generally easier to call
2619 * gtk_widget_grab_default() on the widget. Before making a widget
2620 * the default widget, you must call gtk_widget_set_can_default() on
2621 * the widget you’d like to make the default.
2622 */
2623void
2624gtk_window_set_default (GtkWindow *window,
2625 GtkWidget *default_widget)
2626{
2627 GtkWindowPrivate *priv;
2628
2629 g_return_if_fail (GTK_IS_WINDOW (window));
2630
2631 priv = window->priv;
2632
2633 if (default_widget)
2634 g_return_if_fail (gtk_widget_get_can_default (default_widget));
2635
2636 if (priv->default_widget != default_widget)
2637 {
2638 GtkWidget *old_default_widget = NULL;
2639
2640 if (default_widget)
2641 g_object_ref (default_widget);
2642
2643 if (priv->default_widget)
2644 {
2645 old_default_widget = priv->default_widget;
2646
2647 if (priv->focus_widget != priv->default_widget ||
2648 !gtk_widget_get_receives_default (priv->default_widget))
2649 _gtk_widget_set_has_default (priv->default_widget, FALSE);
2650
2651 gtk_widget_queue_draw (priv->default_widget);
2652 }
2653
2654 priv->default_widget = default_widget;
2655
2656 if (priv->default_widget)
2657 {
2658 if (priv->focus_widget == NULL ||
2659 !gtk_widget_get_receives_default (priv->focus_widget))
2660 _gtk_widget_set_has_default (priv->default_widget, TRUE);
2661
2662 gtk_widget_queue_draw (priv->default_widget);
2663 }
2664
2665 if (old_default_widget)
2666 g_object_notify (G_OBJECT (old_default_widget), "has-default");
2667
2668 if (default_widget)
2669 {
2670 g_object_notify (G_OBJECT (default_widget), "has-default");
2671 g_object_unref (default_widget);
2672 }
2673 }
2674}
2675
2676/**
2677 * gtk_window_get_default_widget:
2678 * @window: a #GtkWindow
2679 *
2680 * Returns the default widget for @window. See
2681 * gtk_window_set_default() for more details.
2682 *
2683 * Returns: (nullable) (transfer none): the default widget, or %NULL
2684 * if there is none.
2685 *
2686 * Since: 2.14
2687 **/
2688GtkWidget *
2689gtk_window_get_default_widget (GtkWindow *window)
2690{
2691 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2692
2693 return window->priv->default_widget;
2694}
2695
2696static gboolean
2697handle_keys_changed (gpointer data)
2698{
2699 GtkWindow *window = GTK_WINDOW (data);
2700 GtkWindowPrivate *priv = window->priv;
2701
2702 if (priv->keys_changed_handler)
2703 {
2704 g_source_remove (priv->keys_changed_handler);
2705 priv->keys_changed_handler = 0;
2706 }
2707
2708 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
2709
2710 return FALSE;
2711}
2712
2713void
2714_gtk_window_notify_keys_changed (GtkWindow *window)
2715{
2716 GtkWindowPrivate *priv = window->priv;
2717
2718 if (!priv->keys_changed_handler)
2719 {
2720 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
2721 g_source_set_name_by_id (priv->keys_changed_handler, "[gtk+] handle_keys_changed");
2722 }
2723}
2724
2725/**
2726 * gtk_window_add_accel_group:
2727 * @window: window to attach accelerator group to
2728 * @accel_group: a #GtkAccelGroup
2729 *
2730 * Associate @accel_group with @window, such that calling
2731 * gtk_accel_groups_activate() on @window will activate accelerators
2732 * in @accel_group.
2733 **/
2734void
2735gtk_window_add_accel_group (GtkWindow *window,
2736 GtkAccelGroup *accel_group)
2737{
2738 g_return_if_fail (GTK_IS_WINDOW (window));
2739 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2740
2741 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
2742 g_signal_connect_object (accel_group, "accel-changed",
2743 G_CALLBACK (_gtk_window_notify_keys_changed),
2744 window, G_CONNECT_SWAPPED);
2745 _gtk_window_notify_keys_changed (window);
2746}
2747
2748/**
2749 * gtk_window_remove_accel_group:
2750 * @window: a #GtkWindow
2751 * @accel_group: a #GtkAccelGroup
2752 *
2753 * Reverses the effects of gtk_window_add_accel_group().
2754 **/
2755void
2756gtk_window_remove_accel_group (GtkWindow *window,
2757 GtkAccelGroup *accel_group)
2758{
2759 g_return_if_fail (GTK_IS_WINDOW (window));
2760 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
2761
2762 g_signal_handlers_disconnect_by_func (accel_group,
2763 _gtk_window_notify_keys_changed,
2764 window);
2765 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
2766 _gtk_window_notify_keys_changed (window);
2767}
2768
2769static GtkMnemonicHash *
2770gtk_window_get_mnemonic_hash (GtkWindow *window,
2771 gboolean create)
2772{
2773 GtkWindowPrivate *private = window->priv;
2774
2775 if (!private->mnemonic_hash && create)
2776 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2777
2778 return private->mnemonic_hash;
2779}
2780
2781/**
2782 * gtk_window_add_mnemonic:
2783 * @window: a #GtkWindow
2784 * @keyval: the mnemonic
2785 * @target: the widget that gets activated by the mnemonic
2786 *
2787 * Adds a mnemonic to this window.
2788 */
2789void
2790gtk_window_add_mnemonic (GtkWindow *window,
2791 guint keyval,
2792 GtkWidget *target)
2793{
2794 g_return_if_fail (GTK_IS_WINDOW (window));
2795 g_return_if_fail (GTK_IS_WIDGET (target));
2796
2797 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2798 keyval, target);
2799 _gtk_window_notify_keys_changed (window);
2800}
2801
2802/**
2803 * gtk_window_remove_mnemonic:
2804 * @window: a #GtkWindow
2805 * @keyval: the mnemonic
2806 * @target: the widget that gets activated by the mnemonic
2807 *
2808 * Removes a mnemonic from this window.
2809 */
2810void
2811gtk_window_remove_mnemonic (GtkWindow *window,
2812 guint keyval,
2813 GtkWidget *target)
2814{
2815 g_return_if_fail (GTK_IS_WINDOW (window));
2816 g_return_if_fail (GTK_IS_WIDGET (target));
2817
2818 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2819 keyval, target);
2820 _gtk_window_notify_keys_changed (window);
2821}
2822
2823/**
2824 * gtk_window_mnemonic_activate:
2825 * @window: a #GtkWindow
2826 * @keyval: the mnemonic
2827 * @modifier: the modifiers
2828 *
2829 * Activates the targets associated with the mnemonic.
2830 *
2831 * Returns: %TRUE if the activation is done.
2832 */
2833gboolean
2834gtk_window_mnemonic_activate (GtkWindow *window,
2835 guint keyval,
2836 GdkModifierType modifier)
2837{
2838 GtkWindowPrivate *priv;
2839
2840 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2841
2842 priv = window->priv;
2843
2844 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2845 {
2846 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2847 if (mnemonic_hash)
2848 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2849 }
2850
2851 return FALSE;
2852}
2853
2854/**
2855 * gtk_window_set_mnemonic_modifier:
2856 * @window: a #GtkWindow
2857 * @modifier: the modifier mask used to activate
2858 * mnemonics on this window.
2859 *
2860 * Sets the mnemonic modifier for this window.
2861 **/
2862void
2863gtk_window_set_mnemonic_modifier (GtkWindow *window,
2864 GdkModifierType modifier)
2865{
2866 GtkWindowPrivate *priv;
2867
2868 g_return_if_fail (GTK_IS_WINDOW (window));
2869 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2870
2871 priv = window->priv;
2872
2873 priv->mnemonic_modifier = modifier;
2874 _gtk_window_notify_keys_changed (window);
2875}
2876
2877/**
2878 * gtk_window_get_mnemonic_modifier:
2879 * @window: a #GtkWindow
2880 *
2881 * Returns the mnemonic modifier for this window. See
2882 * gtk_window_set_mnemonic_modifier().
2883 *
2884 * Returns: the modifier mask used to activate
2885 * mnemonics on this window.
2886 **/
2887GdkModifierType
2888gtk_window_get_mnemonic_modifier (GtkWindow *window)
2889{
2890 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2891
2892 return window->priv->mnemonic_modifier;
2893}
2894
2895/**
2896 * gtk_window_set_position:
2897 * @window: a #GtkWindow.
2898 * @position: a position constraint.
2899 *
2900 * Sets a position constraint for this window. If the old or new
2901 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2902 * the window to be repositioned to satisfy the new constraint.
2903 **/
2904void
2905gtk_window_set_position (GtkWindow *window,
2906 GtkWindowPosition position)
2907{
2908 GtkWindowPrivate *priv;
2909
2910 g_return_if_fail (GTK_IS_WINDOW (window));
2911
2912 priv = window->priv;
2913
2914 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2915 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2916 {
2917 GtkWindowGeometryInfo *info;
2918
2919 info = gtk_window_get_geometry_info (window, TRUE);
2920
2921 /* this flag causes us to re-request the CENTER_ALWAYS
2922 * constraint in gtk_window_move_resize(), see
2923 * comment in that function.
2924 */
2925 info->position_constraints_changed = TRUE;
2926
2927 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2928 }
2929
2930 if (priv->position != position)
2931 {
2932 priv->position = position;
2933
2934 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_WIN_POS]);
2935 }
2936}
2937
2938/**
2939 * gtk_window_activate_focus:
2940 * @window: a #GtkWindow
2941 *
2942 * Activates the current focused widget within the window.
2943 *
2944 * Returns: %TRUE if a widget got activated.
2945 **/
2946gboolean
2947gtk_window_activate_focus (GtkWindow *window)
2948{
2949 GtkWindowPrivate *priv;
2950
2951 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2952
2953 priv = window->priv;
2954
2955 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2956 return gtk_widget_activate (priv->focus_widget);
2957
2958 return FALSE;
2959}
2960
2961/**
2962 * gtk_window_get_focus:
2963 * @window: a #GtkWindow
2964 *
2965 * Retrieves the current focused widget within the window.
2966 * Note that this is the widget that would have the focus
2967 * if the toplevel window focused; if the toplevel window
2968 * is not focused then `gtk_widget_has_focus (widget)` will
2969 * not be %TRUE for the widget.
2970 *
2971 * Returns: (nullable) (transfer none): the currently focused widget,
2972 * or %NULL if there is none.
2973 **/
2974GtkWidget *
2975gtk_window_get_focus (GtkWindow *window)
2976{
2977 GtkWindowPrivate *priv;
2978
2979 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2980
2981 priv = window->priv;
2982
2983 if (priv->initial_focus)
2984 return priv->initial_focus;
2985 else
2986 return priv->focus_widget;
2987}
2988
2989/**
2990 * gtk_window_activate_default:
2991 * @window: a #GtkWindow
2992 *
2993 * Activates the default widget for the window, unless the current
2994 * focused widget has been configured to receive the default action
2995 * (see gtk_widget_set_receives_default()), in which case the
2996 * focused widget is activated.
2997 *
2998 * Returns: %TRUE if a widget got activated.
2999 **/
3000gboolean
3001gtk_window_activate_default (GtkWindow *window)
3002{
3003 GtkWindowPrivate *priv;
3004
3005 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3006
3007 priv = window->priv;
3008
3009 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
3010 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
3011 return gtk_widget_activate (priv->default_widget);
3012 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
3013 return gtk_widget_activate (priv->focus_widget);
3014
3015 return FALSE;
3016}
3017
3018/**
3019 * gtk_window_set_modal:
3020 * @window: a #GtkWindow
3021 * @modal: whether the window is modal
3022 *
3023 * Sets a window modal or non-modal. Modal windows prevent interaction
3024 * with other windows in the same application. To keep modal dialogs
3025 * on top of main application windows, use
3026 * gtk_window_set_transient_for() to make the dialog transient for the
3027 * parent; most [window managers][gtk-X11-arch]
3028 * will then disallow lowering the dialog below the parent.
3029 *
3030 *
3031 **/
3032void
3033gtk_window_set_modal (GtkWindow *window,
3034 gboolean modal)
3035{
3036 GtkWindowPrivate *priv;
3037 GtkWidget *widget;
3038
3039 g_return_if_fail (GTK_IS_WINDOW (window));
3040
3041 priv = window->priv;
3042
3043 modal = modal != FALSE;
3044 if (priv->modal == modal)
3045 return;
3046
3047 priv->modal = modal;
3048 widget = GTK_WIDGET (window);
3049
3050 /* adjust desired modality state */
3051 if (_gtk_widget_get_realized (widget))
3052 gdk_window_set_modal_hint (_gtk_widget_get_window (widget), priv->modal);
3053
3054 if (gtk_widget_get_visible (widget))
3055 {
3056 if (priv->modal)
3057 gtk_grab_add (widget);
3058 else
3059 gtk_grab_remove (widget);
3060 }
3061
3062 update_window_buttons (window);
3063
3064 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_MODAL]);
3065}
3066
3067/**
3068 * gtk_window_get_modal:
3069 * @window: a #GtkWindow
3070 *
3071 * Returns whether the window is modal. See gtk_window_set_modal().
3072 *
3073 * Returns: %TRUE if the window is set to be modal and
3074 * establishes a grab when shown
3075 **/
3076gboolean
3077gtk_window_get_modal (GtkWindow *window)
3078{
3079 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3080
3081 return window->priv->modal;
3082}
3083
3084/**
3085 * gtk_window_list_toplevels:
3086 *
3087 * Returns a list of all existing toplevel windows. The widgets
3088 * in the list are not individually referenced. If you want
3089 * to iterate through the list and perform actions involving
3090 * callbacks that might destroy the widgets, you must call
3091 * `g_list_foreach (result, (GFunc)g_object_ref, NULL)` first, and
3092 * then unref all the widgets afterwards.
3093 *
3094 * Returns: (element-type GtkWidget) (transfer container): list of toplevel widgets
3095 **/
3096GList*
3097gtk_window_list_toplevels (void)
3098{
3099 GList *list = NULL;
3100 GSList *slist;
3101
3102 for (slist = toplevel_list; slist; slist = slist->next)
3103 list = g_list_prepend (list, slist->data);
3104
3105 return list;
3106}
3107
3108static void
3109remove_attach_widget (GtkWindow *window)
3110{
3111 GtkWindowPrivate *priv = window->priv;
3112
3113 if (priv->attach_widget)
3114 {
3115 _gtk_widget_remove_attached_window (priv->attach_widget, window);
3116
3117 priv->attach_widget = NULL;
3118 }
3119}
3120
3121static void
3122gtk_window_dispose (GObject *object)
3123{
3124 GtkWindow *window = GTK_WINDOW (object);
3125 GtkWindowPrivate *priv = window->priv;
3126
3127 gtk_window_set_focus (window, NULL);
3128 gtk_window_set_default (window, NULL);
3129 remove_attach_widget (window);
3130
3131 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
3132 unset_titlebar (window);
3133
3134 while (priv->popovers)
3135 {
3136 GtkWindowPopover *popover = priv->popovers->data;
3137 priv->popovers = g_list_delete_link (priv->popovers, priv->popovers);
3138 popover_destroy (popover);
3139 }
3140
3141}
3142
3143static void
3144parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
3145{
3146 gtk_widget_destroy (GTK_WIDGET (child));
3147}
3148
3149static void
3150connect_parent_destroyed (GtkWindow *window)
3151{
3152 GtkWindowPrivate *priv = window->priv;
3153
3154 if (priv->transient_parent)
3155 {
3156 g_signal_connect (priv->transient_parent,
3157 "destroy",
3158 G_CALLBACK (parent_destroyed_callback),
3159 window);
3160 }
3161}
3162
3163static void
3164disconnect_parent_destroyed (GtkWindow *window)
3165{
3166 GtkWindowPrivate *priv = window->priv;
3167
3168 if (priv->transient_parent)
3169 {
3170 g_signal_handlers_disconnect_by_func (priv->transient_parent,
3171 parent_destroyed_callback,
3172 window);
3173 }
3174}
3175
3176static void
3177gtk_window_transient_parent_realized (GtkWidget *parent,
3178 GtkWidget *window)
3179{
3180 if (_gtk_widget_get_realized (window))
3181 gdk_window_set_transient_for (_gtk_widget_get_window (window),
3182 _gtk_widget_get_window (parent));
3183}
3184
3185static void
3186gtk_window_transient_parent_unrealized (GtkWidget *parent,
3187 GtkWidget *window)
3188{
3189 if (_gtk_widget_get_realized (window))
3190 gdk_property_delete (_gtk_widget_get_window (window),
3191 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
3192}
3193
3194static void
3195gtk_window_transient_parent_screen_changed (GtkWindow *parent,
3196 GParamSpec *pspec,
3197 GtkWindow *window)
3198{
3199 gtk_window_set_screen (window, parent->priv->screen);
3200}
3201
3202static void
3203gtk_window_unset_transient_for (GtkWindow *window)
3204{
3205 GtkWindowPrivate *priv = window->priv;
3206
3207 if (priv->transient_parent)
3208 {
3209 g_signal_handlers_disconnect_by_func (priv->transient_parent,
3210 gtk_window_transient_parent_realized,
3211 window);
3212 g_signal_handlers_disconnect_by_func (priv->transient_parent,
3213 gtk_window_transient_parent_unrealized,
3214 window);
3215 g_signal_handlers_disconnect_by_func (priv->transient_parent,
3216 gtk_window_transient_parent_screen_changed,
3217 window);
3218 g_signal_handlers_disconnect_by_func (priv->transient_parent,
3219 gtk_widget_destroyed,
3220 &priv->transient_parent);
3221
3222 if (priv->destroy_with_parent)
3223 disconnect_parent_destroyed (window);
3224
3225 priv->transient_parent = NULL;
3226
3227 if (priv->transient_parent_group)
3228 {
3229 priv->transient_parent_group = FALSE;
3230 gtk_window_group_remove_window (priv->group,
3231 window);
3232 }
3233 }
3234}
3235
3236/**
3237 * gtk_window_set_transient_for:
3238 * @window: a #GtkWindow
3239 * @parent: (allow-none): parent window, or %NULL
3240 *
3241 * Dialog windows should be set transient for the main application
3242 * window they were spawned from. This allows
3243 * [window managers][gtk-X11-arch] to e.g. keep the
3244 * dialog on top of the main window, or center the dialog over the
3245 * main window. gtk_dialog_new_with_buttons() and other convenience
3246 * functions in GTK+ will sometimes call
3247 * gtk_window_set_transient_for() on your behalf.
3248 *
3249 * Passing %NULL for @parent unsets the current transient window.
3250 *
3251 * On Wayland, this function can also be used to attach a new
3252 * #GTK_WINDOW_POPUP to a #GTK_WINDOW_TOPLEVEL parent already mapped
3253 * on screen so that the #GTK_WINDOW_POPUP will be created as a
3254 * subsurface-based window #GDK_WINDOW_SUBSURFACE which can be
3255 * positioned at will relatively to the #GTK_WINDOW_TOPLEVEL surface.
3256 *
3257 * On Windows, this function puts the child window on top of the parent,
3258 * much as the window manager would have done on X.
3259 */
3260void
3261gtk_window_set_transient_for (GtkWindow *window,
3262 GtkWindow *parent)
3263{
3264 GtkWindowPrivate *priv;
3265
3266 g_return_if_fail (GTK_IS_WINDOW (window));
3267 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
3268 g_return_if_fail (window != parent);
3269
3270 priv = window->priv;
3271
3272 if (priv->transient_parent)
3273 {
3274 if (_gtk_widget_get_realized (GTK_WIDGET (window)) &&
3275 _gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
3276 (!parent || !_gtk_widget_get_realized (GTK_WIDGET (parent))))
3277 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
3278 GTK_WIDGET (window));
3279
3280 gtk_window_unset_transient_for (window);
3281 }
3282
3283 priv->transient_parent = parent;
3284
3285 if (parent)
3286 {
3287 g_signal_connect (parent, "destroy",
3288 G_CALLBACK (gtk_widget_destroyed),
3289 &priv->transient_parent);
3290 g_signal_connect (parent, "realize",
3291 G_CALLBACK (gtk_window_transient_parent_realized),
3292 window);
3293 g_signal_connect (parent, "unrealize",
3294 G_CALLBACK (gtk_window_transient_parent_unrealized),
3295 window);
3296 g_signal_connect (parent, "notify::screen",
3297 G_CALLBACK (gtk_window_transient_parent_screen_changed),
3298 window);
3299
3300 gtk_window_set_screen (window, parent->priv->screen);
3301
3302 if (priv->destroy_with_parent)
3303 connect_parent_destroyed (window);
3304
3305 if (_gtk_widget_get_realized (GTK_WIDGET (window)) &&
3306 _gtk_widget_get_realized (GTK_WIDGET (parent)))
3307 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
3308 GTK_WIDGET (window));
3309
3310 if (parent->priv->group)
3311 {
3312 gtk_window_group_add_window (parent->priv->group, window);
3313 priv->transient_parent_group = TRUE;
3314 }
3315 }
3316
3317 update_window_buttons (window);
3318}
3319
3320/**
3321 * gtk_window_get_transient_for:
3322 * @window: a #GtkWindow
3323 *
3324 * Fetches the transient parent for this window. See
3325 * gtk_window_set_transient_for().
3326 *
3327 * Returns: (nullable) (transfer none): the transient parent for this
3328 * window, or %NULL if no transient parent has been set.
3329 **/
3330GtkWindow *
3331gtk_window_get_transient_for (GtkWindow *window)
3332{
3333 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3334
3335 return window->priv->transient_parent;
3336}
3337
3338/**
3339 * gtk_window_set_attached_to:
3340 * @window: a #GtkWindow
3341 * @attach_widget: (allow-none): a #GtkWidget, or %NULL
3342 *
3343 * Marks @window as attached to @attach_widget. This creates a logical binding
3344 * between the window and the widget it belongs to, which is used by GTK+ to
3345 * propagate information such as styling or accessibility to @window as if it
3346 * was a children of @attach_widget.
3347 *
3348 * Examples of places where specifying this relation is useful are for instance
3349 * a #GtkMenu created by a #GtkComboBox, a completion popup window
3350 * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
3351 *
3352 * Note that this function should not be confused with
3353 * gtk_window_set_transient_for(), which specifies a window manager relation
3354 * between two toplevels instead.
3355 *
3356 * Passing %NULL for @attach_widget detaches the window.
3357 *
3358 * Since: 3.4
3359 **/
3360void
3361gtk_window_set_attached_to (GtkWindow *window,
3362 GtkWidget *attach_widget)
3363{
3364 GtkStyleContext *context;
3365 GtkWindowPrivate *priv;
3366
3367 g_return_if_fail (GTK_IS_WINDOW (window));
3368 g_return_if_fail (GTK_WIDGET (window) != attach_widget);
3369
3370 priv = window->priv;
3371
3372 if (priv->attach_widget == attach_widget)
3373 return;
3374
3375 remove_attach_widget (window);
3376
3377 priv->attach_widget = attach_widget;
3378
3379 if (priv->attach_widget)
3380 {
3381 _gtk_widget_add_attached_window (priv->attach_widget, window);
3382 }
3383
3384 /* Update the style, as the widget path might change. */
3385 context = gtk_widget_get_style_context (GTK_WIDGET (window));
3386 if (priv->attach_widget)
3387 gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
3388 else
3389 gtk_style_context_set_parent (context, NULL);
3390
3391 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_ATTACHED_TO]);
3392}
3393
3394/**
3395 * gtk_window_get_attached_to:
3396 * @window: a #GtkWindow
3397 *
3398 * Fetches the attach widget for this window. See
3399 * gtk_window_set_attached_to().
3400 *
3401 * Returns: (nullable) (transfer none): the widget where the window
3402 * is attached, or %NULL if the window is not attached to any widget.
3403 *
3404 * Since: 3.4
3405 **/
3406GtkWidget *
3407gtk_window_get_attached_to (GtkWindow *window)
3408{
3409 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3410
3411 return window->priv->attach_widget;
3412}
3413
3414/**
3415 * gtk_window_set_opacity:
3416 * @window: a #GtkWindow
3417 * @opacity: desired opacity, between 0 and 1
3418 *
3419 * Request the windowing system to make @window partially transparent,
3420 * with opacity 0 being fully transparent and 1 fully opaque. (Values
3421 * of the opacity parameter are clamped to the [0,1] range.) On X11
3422 * this has any effect only on X screens with a compositing manager
3423 * running. See gtk_widget_is_composited(). On Windows it should work
3424 * always.
3425 *
3426 * Note that setting a window’s opacity after the window has been
3427 * shown causes it to flicker once on Windows.
3428 *
3429 * Since: 2.12
3430 * Deprecated: 3.8: Use gtk_widget_set_opacity instead.
3431 **/
3432void
3433gtk_window_set_opacity (GtkWindow *window,
3434 gdouble opacity)
3435{
3436 gtk_widget_set_opacity (GTK_WIDGET (window), opacity);
3437}
3438
3439/**
3440 * gtk_window_get_opacity:
3441 * @window: a #GtkWindow
3442 *
3443 * Fetches the requested opacity for this window. See
3444 * gtk_window_set_opacity().
3445 *
3446 * Returns: the requested opacity for this window.
3447 *
3448 * Since: 2.12
3449 * Deprecated: 3.8: Use gtk_widget_get_opacity instead.
3450 **/
3451gdouble
3452gtk_window_get_opacity (GtkWindow *window)
3453{
3454 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
3455
3456 return gtk_widget_get_opacity (GTK_WIDGET (window));
3457}
3458
3459/**
3460 * gtk_window_get_application:
3461 * @window: a #GtkWindow
3462 *
3463 * Gets the #GtkApplication associated with the window (if any).
3464 *
3465 * Returns: (nullable) (transfer none): a #GtkApplication, or %NULL
3466 *
3467 * Since: 3.0
3468 **/
3469GtkApplication *
3470gtk_window_get_application (GtkWindow *window)
3471{
3472 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3473
3474 return window->priv->application;
3475}
3476
3477static void
3478gtk_window_release_application (GtkWindow *window)
3479{
3480 if (window->priv->application)
3481 {
3482 GtkApplication *application;
3483
3484 /* steal reference into temp variable */
3485 application = window->priv->application;
3486 window->priv->application = NULL;
3487
3488 gtk_application_remove_window (application, window);
3489 g_object_unref (application);
3490 }
3491}
3492
3493/**
3494 * gtk_window_set_application:
3495 * @window: a #GtkWindow
3496 * @application: (allow-none): a #GtkApplication, or %NULL
3497 *
3498 * Sets or unsets the #GtkApplication associated with the window.
3499 *
3500 * The application will be kept alive for at least as long as the window
3501 * is open.
3502 *
3503 * Since: 3.0
3504 **/
3505void
3506gtk_window_set_application (GtkWindow *window,
3507 GtkApplication *application)
3508{
3509 GtkWindowPrivate *priv;
3510
3511 g_return_if_fail (GTK_IS_WINDOW (window));
3512
3513 priv = window->priv;
3514 if (priv->application != application)
3515 {
3516 gtk_window_release_application (window);
3517
3518 priv->application = application;
3519
3520 if (priv->application != NULL)
3521 {
3522 g_object_ref (priv->application);
3523
3524 gtk_application_add_window (priv->application, window);
3525 }
3526
3527 _gtk_widget_update_parent_muxer (GTK_WIDGET (window));
3528
3529 _gtk_window_notify_keys_changed (window);
3530
3531 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_APPLICATION]);
3532 }
3533}
3534
3535/**
3536 * gtk_window_set_type_hint:
3537 * @window: a #GtkWindow
3538 * @hint: the window type
3539 *
3540 * By setting the type hint for the window, you allow the window
3541 * manager to decorate and handle the window in a way which is
3542 * suitable to the function of the window in your application.
3543 *
3544 * This function should be called before the window becomes visible.
3545 *
3546 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
3547 * will sometimes call gtk_window_set_type_hint() on your behalf.
3548 *
3549 **/
3550void
3551gtk_window_set_type_hint (GtkWindow *window,
3552 GdkWindowTypeHint hint)
3553{
3554 GtkWindowPrivate *priv;
3555 GdkWindow *gdk_window;
3556
3557 g_return_if_fail (GTK_IS_WINDOW (window));
3558
3559 priv = window->priv;
3560
3561 if (priv->type_hint == hint)
3562 return;
3563
3564 priv->type_hint = hint;
3565
3566 gdk_window = _gtk_widget_get_window (GTK_WIDGET (window));
3567 if (gdk_window)
3568 gdk_window_set_type_hint (gdk_window, hint);
3569
3570 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_TYPE_HINT]);
3571
3572 update_window_buttons (window);
3573}
3574
3575/**
3576 * gtk_window_get_type_hint:
3577 * @window: a #GtkWindow
3578 *
3579 * Gets the type hint for this window. See gtk_window_set_type_hint().
3580 *
3581 * Returns: the type hint for @window.
3582 **/
3583GdkWindowTypeHint
3584gtk_window_get_type_hint (GtkWindow *window)
3585{
3586 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3587
3588 return window->priv->type_hint;
3589}
3590
3591/**
3592 * gtk_window_set_skip_taskbar_hint:
3593 * @window: a #GtkWindow
3594 * @setting: %TRUE to keep this window from appearing in the task bar
3595 *
3596 * Windows may set a hint asking the desktop environment not to display
3597 * the window in the task bar. This function sets this hint.
3598 *
3599 * Since: 2.2
3600 **/
3601void
3602gtk_window_set_skip_taskbar_hint (GtkWindow *window,
3603 gboolean setting)
3604{
3605 GtkWindowPrivate *priv;
3606
3607 g_return_if_fail (GTK_IS_WINDOW (window));
3608
3609 priv = window->priv;
3610
3611 setting = setting != FALSE;
3612
3613 if (priv->skips_taskbar != setting)
3614 {
3615 priv->skips_taskbar = setting;
3616 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
3617 gdk_window_set_skip_taskbar_hint (_gtk_widget_get_window (GTK_WIDGET (window)),
3618 priv->skips_taskbar);
3619 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_SKIP_TASKBAR_HINT]);
3620 }
3621}
3622
3623/**
3624 * gtk_window_get_skip_taskbar_hint:
3625 * @window: a #GtkWindow
3626 *
3627 * Gets the value set by gtk_window_set_skip_taskbar_hint()
3628 *
3629 * Returns: %TRUE if window shouldn’t be in taskbar
3630 *
3631 * Since: 2.2
3632 **/
3633gboolean
3634gtk_window_get_skip_taskbar_hint (GtkWindow *window)
3635{
3636 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3637
3638 return window->priv->skips_taskbar;
3639}
3640
3641/**
3642 * gtk_window_set_skip_pager_hint:
3643 * @window: a #GtkWindow
3644 * @setting: %TRUE to keep this window from appearing in the pager
3645 *
3646 * Windows may set a hint asking the desktop environment not to display
3647 * the window in the pager. This function sets this hint.
3648 * (A "pager" is any desktop navigation tool such as a workspace
3649 * switcher that displays a thumbnail representation of the windows
3650 * on the screen.)
3651 *
3652 * Since: 2.2
3653 **/
3654void
3655gtk_window_set_skip_pager_hint (GtkWindow *window,
3656 gboolean setting)
3657{
3658 GtkWindowPrivate *priv;
3659
3660 g_return_if_fail (GTK_IS_WINDOW (window));
3661
3662 priv = window->priv;
3663
3664 setting = setting != FALSE;
3665
3666 if (priv->skips_pager != setting)
3667 {
3668 priv->skips_pager = setting;
3669 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
3670 gdk_window_set_skip_pager_hint (_gtk_widget_get_window (GTK_WIDGET (window)),
3671 priv->skips_pager);
3672 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_SKIP_PAGER_HINT]);
3673 }
3674}
3675
3676/**
3677 * gtk_window_get_skip_pager_hint:
3678 * @window: a #GtkWindow
3679 *
3680 * Gets the value set by gtk_window_set_skip_pager_hint().
3681 *
3682 * Returns: %TRUE if window shouldn’t be in pager
3683 *
3684 * Since: 2.2
3685 **/
3686gboolean
3687gtk_window_get_skip_pager_hint (GtkWindow *window)
3688{
3689 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3690
3691 return window->priv->skips_pager;
3692}
3693
3694/**
3695 * gtk_window_set_urgency_hint:
3696 * @window: a #GtkWindow
3697 * @setting: %TRUE to mark this window as urgent
3698 *
3699 * Windows may set a hint asking the desktop environment to draw
3700 * the users attention to the window. This function sets this hint.
3701 *
3702 * Since: 2.8
3703 **/
3704void
3705gtk_window_set_urgency_hint (GtkWindow *window,
3706 gboolean setting)
3707{
3708 GtkWindowPrivate *priv;
3709
3710 g_return_if_fail (GTK_IS_WINDOW (window));
3711
3712 priv = window->priv;
3713
3714 setting = setting != FALSE;
3715
3716 if (priv->urgent != setting)
3717 {
3718 priv->urgent = setting;
3719 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
3720 gdk_window_set_urgency_hint (_gtk_widget_get_window (GTK_WIDGET (window)),
3721 priv->urgent);
3722 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_URGENCY_HINT]);
3723 }
3724}
3725
3726/**
3727 * gtk_window_get_urgency_hint:
3728 * @window: a #GtkWindow
3729 *
3730 * Gets the value set by gtk_window_set_urgency_hint()
3731 *
3732 * Returns: %TRUE if window is urgent
3733 *
3734 * Since: 2.8
3735 **/
3736gboolean
3737gtk_window_get_urgency_hint (GtkWindow *window)
3738{
3739 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3740
3741 return window->priv->urgent;
3742}
3743
3744/**
3745 * gtk_window_set_accept_focus:
3746 * @window: a #GtkWindow
3747 * @setting: %TRUE to let this window receive input focus
3748 *
3749 * Windows may set a hint asking the desktop environment not to receive
3750 * the input focus. This function sets this hint.
3751 *
3752 * Since: 2.4
3753 **/
3754void
3755gtk_window_set_accept_focus (GtkWindow *window,
3756 gboolean setting)
3757{
3758 GtkWindowPrivate *priv;
3759
3760 g_return_if_fail (GTK_IS_WINDOW (window));
3761
3762 priv = window->priv;
3763
3764 setting = setting != FALSE;
3765
3766 if (priv->accept_focus != setting)
3767 {
3768 priv->accept_focus = setting;
3769 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
3770 gdk_window_set_accept_focus (_gtk_widget_get_window (GTK_WIDGET (window)),
3771 priv->accept_focus);
3772 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_ACCEPT_FOCUS]);
3773 }
3774}
3775
3776/**
3777 * gtk_window_get_accept_focus:
3778 * @window: a #GtkWindow
3779 *
3780 * Gets the value set by gtk_window_set_accept_focus().
3781 *
3782 * Returns: %TRUE if window should receive the input focus
3783 *
3784 * Since: 2.4
3785 **/
3786gboolean
3787gtk_window_get_accept_focus (GtkWindow *window)
3788{
3789 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3790
3791 return window->priv->accept_focus;
3792}
3793
3794/**
3795 * gtk_window_set_focus_on_map:
3796 * @window: a #GtkWindow
3797 * @setting: %TRUE to let this window receive input focus on map
3798 *
3799 * Windows may set a hint asking the desktop environment not to receive
3800 * the input focus when the window is mapped. This function sets this
3801 * hint.
3802 *
3803 * Since: 2.6
3804 **/
3805void
3806gtk_window_set_focus_on_map (GtkWindow *window,
3807 gboolean setting)
3808{
3809 GtkWindowPrivate *priv;
3810
3811 g_return_if_fail (GTK_IS_WINDOW (window));
3812
3813 priv = window->priv;
3814
3815 setting = setting != FALSE;
3816
3817 if (priv->focus_on_map != setting)
3818 {
3819 priv->focus_on_map = setting;
3820 if (_gtk_widget_get_realized (GTK_WIDGET (window)))
3821 gdk_window_set_focus_on_map (_gtk_widget_get_window (GTK_WIDGET (window)),
3822 priv->focus_on_map);
3823 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_FOCUS_ON_MAP]);
3824 }
3825}
3826
3827/**
3828 * gtk_window_get_focus_on_map:
3829 * @window: a #GtkWindow
3830 *
3831 * Gets the value set by gtk_window_set_focus_on_map().
3832 *
3833 * Returns: %TRUE if window should receive the input focus when
3834 * mapped.
3835 *
3836 * Since: 2.6
3837 **/
3838gboolean
3839gtk_window_get_focus_on_map (GtkWindow *window)
3840{
3841 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3842
3843 return window->priv->focus_on_map;
3844}
3845
3846/**
3847 * gtk_window_set_destroy_with_parent:
3848 * @window: a #GtkWindow
3849 * @setting: whether to destroy @window with its transient parent
3850 *
3851 * If @setting is %TRUE, then destroying the transient parent of @window
3852 * will also destroy @window itself. This is useful for dialogs that
3853 * shouldn’t persist beyond the lifetime of the main window they're
3854 * associated with, for example.
3855 **/
3856void
3857gtk_window_set_destroy_with_parent (GtkWindow *window,
3858 gboolean setting)
3859{
3860 GtkWindowPrivate *priv;
3861
3862 g_return_if_fail (GTK_IS_WINDOW (window));
3863
3864 priv = window->priv;
3865
3866 if (priv->destroy_with_parent == (setting != FALSE))
3867 return;
3868
3869 if (priv->destroy_with_parent)
3870 {
3871 disconnect_parent_destroyed (window);
3872 }
3873 else
3874 {
3875 connect_parent_destroyed (window);
3876 }
3877
3878 priv->destroy_with_parent = setting;
3879
3880 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DESTROY_WITH_PARENT]);
3881}
3882
3883/**
3884 * gtk_window_get_destroy_with_parent:
3885 * @window: a #GtkWindow
3886 *
3887 * Returns whether the window will be destroyed with its transient parent. See
3888 * gtk_window_set_destroy_with_parent ().
3889 *
3890 * Returns: %TRUE if the window will be destroyed with its transient parent.
3891 **/
3892gboolean
3893gtk_window_get_destroy_with_parent (GtkWindow *window)
3894{
3895 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3896
3897 return window->priv->destroy_with_parent;
3898}
3899
3900static void
3901gtk_window_apply_hide_titlebar_when_maximized (GtkWindow *window)
3902{
3903#ifdef GDK_WINDOWING_X11
3904 GdkWindow *gdk_window;
3905 gboolean setting;
3906
3907 setting = window->priv->hide_titlebar_when_maximized;
3908 gdk_window = _gtk_widget_get_window (GTK_WIDGET (window));
3909
3910 if (GDK_IS_X11_WINDOW (gdk_window))
3911 gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
3912#endif
3913}
3914
3915/**
3916 * gtk_window_set_hide_titlebar_when_maximized:
3917 * @window: a #GtkWindow
3918 * @setting: whether to hide the titlebar when @window is maximized
3919 *
3920 * If @setting is %TRUE, then @window will request that it’s titlebar
3921 * should be hidden when maximized.
3922 * This is useful for windows that don’t convey any information other
3923 * than the application name in the titlebar, to put the available
3924 * screen space to better use. If the underlying window system does not
3925 * support the request, the setting will not have any effect.
3926 *
3927 * Note that custom titlebars set with gtk_window_set_titlebar() are
3928 * not affected by this. The application is in full control of their
3929 * content and visibility anyway.
3930 *
3931 * Since: 3.4
3932 **/
3933void
3934gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
3935 gboolean setting)
3936{
3937 g_return_if_fail (GTK_IS_WINDOW (window));
3938
3939 if (window->priv->hide_titlebar_when_maximized == setting)
3940 return;
3941
3942 window->priv->hide_titlebar_when_maximized = setting;
3943 gtk_window_apply_hide_titlebar_when_maximized (window);
3944
3945 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_HIDE_TITLEBAR_WHEN_MAXIMIZED]);
3946}
3947
3948/**
3949 * gtk_window_get_hide_titlebar_when_maximized:
3950 * @window: a #GtkWindow
3951 *
3952 * Returns whether the window has requested to have its titlebar hidden
3953 * when maximized. See gtk_window_set_hide_titlebar_when_maximized ().
3954 *
3955 * Returns: %TRUE if the window has requested to have its titlebar
3956 * hidden when maximized
3957 *
3958 * Since: 3.4
3959 **/
3960gboolean
3961gtk_window_get_hide_titlebar_when_maximized (GtkWindow *window)
3962{
3963 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3964
3965 return window->priv->hide_titlebar_when_maximized;
3966}
3967
3968static GtkWindowGeometryInfo*
3969gtk_window_get_geometry_info (GtkWindow *window,
3970 gboolean create)
3971{
3972 GtkWindowPrivate *priv = window->priv;
3973 GtkWindowGeometryInfo *info;
3974
3975 info = priv->geometry_info;
3976 if (!info && create)
3977 {
3978 info = g_new0 (GtkWindowGeometryInfo, 1);
3979
3980 info->default_width = -1;
3981 info->default_height = -1;
3982 info->resize_width = -1;
3983 info->resize_height = -1;
3984 info->initial_x = 0;
3985 info->initial_y = 0;
3986 info->initial_pos_set = FALSE;
3987 info->default_is_geometry = FALSE;
3988 info->position_constraints_changed = FALSE;
3989 info->last.configure_request.x = 0;
3990 info->last.configure_request.y = 0;
3991 info->last.configure_request.width = -1;
3992 info->last.configure_request.height = -1;
3993 info->mask = 0;
3994 priv->geometry_info = info;
3995 }
3996
3997 return info;
3998}
3999
4000/**
4001 * gtk_window_set_geometry_hints:
4002 * @window: a #GtkWindow
4003 * @geometry_widget: (allow-none): widget the geometry hints used to be applied to
4004 * or %NULL. Since 3.20 this argument is ignored and GTK behaves as if %NULL was
4005 * set.
4006 * @geometry: (allow-none): struct containing geometry information or %NULL
4007 * @geom_mask: mask indicating which struct fields should be paid attention to
4008 *
4009 * This function sets up hints about how a window can be resized by
4010 * the user. You can set a minimum and maximum size; allowed resize
4011 * increments (e.g. for xterm, you can only resize by the size of a
4012 * character); aspect ratios; and more. See the #GdkGeometry struct.
4013 */
4014void
4015gtk_window_set_geometry_hints (GtkWindow *window,
4016 GtkWidget *geometry_widget,
4017 GdkGeometry *geometry,
4018 GdkWindowHints geom_mask)
4019{
4020 GtkWindowGeometryInfo *info;
4021
4022 g_return_if_fail (GTK_IS_WINDOW (window));
4023 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
4024
4025 info = gtk_window_get_geometry_info (window, TRUE);
4026
4027 if (geometry)
4028 info->geometry = *geometry;
4029
4030 /* We store gravity in priv->gravity not in the hints. */
4031 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
4032
4033 if (geometry_widget)
4034 info->mask &= ~(GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC);
4035
4036 if (geom_mask & GDK_HINT_WIN_GRAVITY)
4037 gtk_window_set_gravity (window, geometry->win_gravity);
4038
4039 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4040}
4041
4042static void
4043unset_titlebar (GtkWindow *window)
4044{
4045 GtkWindowPrivate *priv = window->priv;
4046
4047 if (priv->title_box != NULL)
4048 {
4049 g_signal_handlers_disconnect_by_func (priv->title_box,
4050 on_titlebar_title_notify,
4051 window);
4052 gtk_widget_unparent (priv->title_box);
4053 priv->title_box = NULL;
4054 priv->titlebar = NULL;
4055 }
4056}
4057
4058static gboolean
4059gtk_window_supports_client_shadow (GtkWindow *window)
4060{
4061 GdkDisplay *display;
4062 GdkScreen *screen;
4063 GdkVisual *visual;
4064
4065 screen = _gtk_window_get_screen (window);
4066 display = gdk_screen_get_display (screen);
4067
4068#ifdef GDK_WINDOWING_X11
4069 if (GDK_IS_X11_DISPLAY (display))
4070 {
4071 if (!gdk_screen_is_composited (screen))
4072 return FALSE;
4073
4074 if (!gdk_x11_screen_supports_net_wm_hint (screen, gdk_atom_intern_static_string ("_GTK_FRAME_EXTENTS")))
4075 return FALSE;
4076
4077 /* We need a visual with alpha */
4078 visual = gdk_screen_get_rgba_visual (screen);
4079 if (!visual)
4080 return FALSE;
4081 }
4082#endif
4083
4084#ifdef GDK_WINDOWING_WIN32
4085 if (GDK_IS_WIN32_DISPLAY (display))
4086 {
4087 if (!gdk_screen_is_composited (screen))
4088 return FALSE;
4089
4090 /* We need a visual with alpha */
4091 visual = gdk_screen_get_rgba_visual (screen);
4092 if (!visual)
4093 return FALSE;
4094 }
4095#endif
4096
4097 return TRUE;
4098}
4099
4100static void
4101gtk_window_enable_csd (GtkWindow *window)
4102{
4103 GtkWindowPrivate *priv = window->priv;
4104 GtkWidget *widget = GTK_WIDGET (window);
4105 GdkVisual *visual;
4106
4107 /* We need a visual with alpha for client shadows */
4108 if (priv->use_client_shadow)
4109 {
4110 visual = gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget));
4111 if (visual != NULL)
4112 gtk_widget_set_visual (widget, visual);
4113
4114 gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_CSD);
4115 }
4116 else
4117 {
4118 gtk_style_context_add_class (gtk_widget_get_style_context (widget), "solid-csd");
4119 }
4120
4121 priv->client_decorated = TRUE;
4122}
4123
4124static void
4125on_titlebar_title_notify (GtkHeaderBar *titlebar,
4126 GParamSpec *pspec,
4127 GtkWindow *self)
4128{
4129 const gchar *title;
4130
4131 title = gtk_header_bar_get_title (titlebar);
4132 gtk_window_set_title_internal (self, title, FALSE);
4133}
4134
4135/**
4136 * gtk_window_set_titlebar:
4137 * @window: a #GtkWindow
4138 * @titlebar: (allow-none): the widget to use as titlebar
4139 *
4140 * Sets a custom titlebar for @window.
4141 *
4142 * If you set a custom titlebar, GTK+ will do its best to convince
4143 * the window manager not to put its own titlebar on the window.
4144 * Depending on the system, this function may not work for a window
4145 * that is already visible, so you set the titlebar before calling
4146 * gtk_widget_show().
4147 *
4148 * Since: 3.10
4149 */
4150void
4151gtk_window_set_titlebar (GtkWindow *window,
4152 GtkWidget *titlebar)
4153{
4154 GtkWidget *widget = GTK_WIDGET (window);
4155 GtkWindowPrivate *priv = window->priv;
4156 gboolean was_mapped;
4157
4158 g_return_if_fail (GTK_IS_WINDOW (window));
4159
4160 if ((!priv->title_box && titlebar) || (priv->title_box && !titlebar))
4161 {
4162 was_mapped = _gtk_widget_get_mapped (widget);
4163 if (_gtk_widget_get_realized (widget))
4164 {
4165 g_warning ("gtk_window_set_titlebar() called on a realized window");
4166 gtk_widget_unrealize (widget);
4167 }
4168 }
4169 else
4170 was_mapped = FALSE;
4171
4172 unset_titlebar (window);
4173
4174 if (titlebar == NULL)
4175 {
4176 priv->client_decorated = FALSE;
4177 gtk_style_context_remove_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_CSD);
4178
4179 goto out;
4180 }
4181
4182 priv->use_client_shadow = gtk_window_supports_client_shadow (window);
4183
4184 gtk_window_enable_csd (window);
4185 priv->title_box = titlebar;
4186 gtk_widget_set_parent (priv->title_box, widget);
4187 if (GTK_IS_HEADER_BAR (titlebar))
4188 {
4189 g_signal_connect (titlebar, "notify::title",
4190 G_CALLBACK (on_titlebar_title_notify), window);
4191 on_titlebar_title_notify (GTK_HEADER_BAR (titlebar), NULL, window);
4192 }
4193
4194 gtk_style_context_add_class (gtk_widget_get_style_context (titlebar),
4195 GTK_STYLE_CLASS_TITLEBAR);
4196
4197out:
4198 if (was_mapped)
4199 gtk_widget_map (widget);
4200}
4201
4202/**
4203 * gtk_window_get_titlebar:
4204 * @window: a #GtkWindow
4205 *
4206 * Returns the custom titlebar that has been set with
4207 * gtk_window_set_titlebar().
4208 *
4209 * Returns: (nullable) (transfer none): the custom titlebar, or %NULL
4210 *
4211 * Since: 3.16
4212 */
4213GtkWidget *
4214gtk_window_get_titlebar (GtkWindow *window)
4215{
4216 GtkWindowPrivate *priv = window->priv;
4217
4218 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
4219
4220 /* Don't return the internal titlebar */
4221 if (priv->title_box == priv->titlebar)
4222 return NULL;
4223
4224 return priv->title_box;
4225}
4226
4227gboolean
4228_gtk_window_titlebar_shows_app_menu (GtkWindow *window)
4229{
4230 GtkWindowPrivate *priv = window->priv;
4231
4232 if (GTK_IS_HEADER_BAR (priv->title_box))
4233 return _gtk_header_bar_shows_app_menu (GTK_HEADER_BAR (priv->title_box));
4234
4235 return FALSE;
4236}
4237
4238/**
4239 * gtk_window_set_decorated:
4240 * @window: a #GtkWindow
4241 * @setting: %TRUE to decorate the window
4242 *
4243 * By default, windows are decorated with a title bar, resize
4244 * controls, etc. Some [window managers][gtk-X11-arch]
4245 * allow GTK+ to disable these decorations, creating a
4246 * borderless window. If you set the decorated property to %FALSE
4247 * using this function, GTK+ will do its best to convince the window
4248 * manager not to decorate the window. Depending on the system, this
4249 * function may not have any effect when called on a window that is
4250 * already visible, so you should call it before calling gtk_widget_show().
4251 *
4252 * On Windows, this function always works, since there’s no window manager
4253 * policy involved.
4254 *
4255 **/
4256void
4257gtk_window_set_decorated (GtkWindow *window,
4258 gboolean setting)
4259{
4260 GtkWindowPrivate *priv;
4261 GdkWindow *gdk_window;
4262
4263 g_return_if_fail (GTK_IS_WINDOW (window));
4264
4265 priv = window->priv;
4266
4267 setting = setting != FALSE;
4268
4269 if (setting == priv->decorated)
4270 return;
4271
4272 priv->decorated = setting;
4273
4274 gdk_window = _gtk_widget_get_window (GTK_WIDGET (window));
4275 if (gdk_window)
4276 {
4277 if (priv->decorated)
4278 {
4279 if (priv->client_decorated)
4280 gdk_window_set_decorations (gdk_window, 0);
4281 else
4282 gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL);
4283 }
4284 else
4285 gdk_window_set_decorations (gdk_window, 0);
4286 }
4287
4288 update_window_buttons (window);
4289 gtk_widget_queue_resize (GTK_WIDGET (window));
4290
4291 g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DECORATED]);
4292}
4293
4294/**
4295 * gtk_window_get_decorated:
4296 * @window: a #GtkWindow
4297 *
4298 * Returns whether the window has been set to have decorations
4299 * such as a title bar via gtk_window_set_decorated().
4300 *
4301 * Returns: %TRUE if the window has been set to have decorations
4302 **/
4303gboolean
4304gtk_window_get_decorated (GtkWindow *window)
4305{
4306 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
4307
4308 return window->priv->decorated;
4309}
4310
4311/**
4312 * gtk_window_set_deletable:
4313 * @window: a #GtkWindow
4314 * @setting: %TRUE to decorate the window as deletable
4315 *
4316 * By default, windows have a close button in the window frame. Some
4317 * [window managers][gtk-X11-arch] allow GTK+ to
4318 * disable this button. If you set the deletable property to %FALSE
4319 * using this function, GTK+ will do its best to convince the window
4320 * manager not to show a close button. Depending on the system, this
4321 * function may not have any effect when called on a window that is
4322 * already visible, so you should call it before calling gtk_widget_show().
4323 *
4324 * On Windows, this function always works, since there’s no window manager
4325 * policy involved.
4326 *
4327 * Since: 2.10
4328 */
4329void
4330gtk_window_set_deletable (GtkWindow *window,
4331 gboolean setting)
4332{
4333 GtkWindowPrivate *priv;
4334 GdkWindow *gdk_window;
4335
4336 g_return_if_fail (GTK_IS_WINDOW (window));
4337
4338 priv = window->