Bug Summary

File:ctk/ctkheaderbar.c
Warning:line 1170, column 24
Access of the memory returned by 'alloca' at index 0, while it holds only 0 'struct _CtkRequestedSize' element

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkheaderbar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/ctk -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-12-18-231748-43636-1 -x c ctkheaderbar.c
1/*
2 * Copyright (c) 2013 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20#include "config.h"
21
22#include "ctkheaderbar.h"
23#include "ctkheaderbarprivate.h"
24#include "ctkintl.h"
25#include "ctkprivate.h"
26#include "ctktypebuiltins.h"
27#include "ctkwidgetprivate.h"
28#include "ctkcssnodeprivate.h"
29#include "ctkcsscustomgadgetprivate.h"
30#include "ctkwindowprivate.h"
31#include "ctkwidgetprivate.h"
32#include "ctkcontainerprivate.h"
33#include "a11y/ctkheaderbaraccessible.h"
34
35#include <string.h>
36
37/**
38 * SECTION:ctkheaderbar
39 * @Short_description: A box with a centered child
40 * @Title: CtkHeaderBar
41 * @See_also: #CtkBox, #CtkActionBar
42 *
43 * CtkHeaderBar is similar to a horizontal #CtkBox. It allows children to
44 * be placed at the start or the end. In addition, it allows a title and
45 * subtitle to be displayed. The title will be centered with respect to
46 * the width of the box, even if the children at either side take up
47 * different amounts of space. The height of the titlebar will be
48 * set to provide sufficient space for the subtitle, even if none is
49 * currently set. If a subtitle is not needed, the space reservation
50 * can be turned off with ctk_header_bar_set_has_subtitle().
51 *
52 * CtkHeaderBar can add typical window frame controls, such as minimize,
53 * maximize and close buttons, or the window icon.
54 *
55 * For these reasons, CtkHeaderBar is the natural choice for use as the custom
56 * titlebar widget of a #CtkWindow (see ctk_window_set_titlebar()), as it gives
57 * features typical of titlebars while allowing the addition of child widgets.
58 */
59
60#define DEFAULT_SPACING6 6
61#define MIN_TITLE_CHARS5 5
62
63struct _CtkHeaderBarPrivate
64{
65 gchar *title;
66 gchar *subtitle;
67 CtkWidget *title_label;
68 CtkWidget *subtitle_label;
69 CtkWidget *label_box;
70 CtkWidget *label_sizing_box;
71 CtkWidget *subtitle_sizing_label;
72 CtkWidget *custom_title;
73 gint spacing;
74 gboolean has_subtitle;
75
76 GList *children;
77
78 gboolean shows_wm_decorations;
79 gchar *decoration_layout;
80 gboolean decoration_layout_set;
81
82 CtkWidget *titlebar_start_box;
83 CtkWidget *titlebar_end_box;
84
85 CtkWidget *titlebar_start_separator;
86 CtkWidget *titlebar_end_separator;
87
88 CtkWidget *titlebar_icon;
89
90 CtkCssGadget *gadget;
91};
92
93typedef struct _Child Child;
94struct _Child
95{
96 CtkWidget *widget;
97 CtkPackType pack_type;
98};
99
100enum {
101 PROP_0,
102 PROP_TITLE,
103 PROP_SUBTITLE,
104 PROP_HAS_SUBTITLE,
105 PROP_CUSTOM_TITLE,
106 PROP_SPACING,
107 PROP_SHOW_CLOSE_BUTTON,
108 PROP_DECORATION_LAYOUT,
109 PROP_DECORATION_LAYOUT_SET,
110 LAST_PROP
111};
112
113enum {
114 CHILD_PROP_0,
115 CHILD_PROP_PACK_TYPE,
116 CHILD_PROP_POSITION
117};
118
119static GParamSpec *header_bar_props[LAST_PROP] = { NULL((void*)0), };
120
121static void ctk_header_bar_buildable_init (CtkBuildableIface *iface);
122
123G_DEFINE_TYPE_WITH_CODE (CtkHeaderBar, ctk_header_bar, CTK_TYPE_CONTAINER,static void ctk_header_bar_init (CtkHeaderBar *self); static void
ctk_header_bar_class_init (CtkHeaderBarClass *klass); static
GType ctk_header_bar_get_type_once (void); static gpointer ctk_header_bar_parent_class
= ((void*)0); static gint CtkHeaderBar_private_offset; static
void ctk_header_bar_class_intern_init (gpointer klass) { ctk_header_bar_parent_class
= g_type_class_peek_parent (klass); if (CtkHeaderBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkHeaderBar_private_offset
); ctk_header_bar_class_init ((CtkHeaderBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_header_bar_get_instance_private
(CtkHeaderBar *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CtkHeaderBar_private_offset)))); } GType ctk_header_bar_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_header_bar_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_header_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkHeaderBar"
), sizeof (CtkHeaderBarClass), (GClassInitFunc)(void (*)(void
)) ctk_header_bar_class_intern_init, sizeof (CtkHeaderBar), (
GInstanceInitFunc)(void (*)(void)) ctk_header_bar_init, (GTypeFlags
) 0); { {{ CtkHeaderBar_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkHeaderBarPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_header_bar_buildable_init, ((void*)0), ((void*)0)
}; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
124 G_ADD_PRIVATE (CtkHeaderBar)static void ctk_header_bar_init (CtkHeaderBar *self); static void
ctk_header_bar_class_init (CtkHeaderBarClass *klass); static
GType ctk_header_bar_get_type_once (void); static gpointer ctk_header_bar_parent_class
= ((void*)0); static gint CtkHeaderBar_private_offset; static
void ctk_header_bar_class_intern_init (gpointer klass) { ctk_header_bar_parent_class
= g_type_class_peek_parent (klass); if (CtkHeaderBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkHeaderBar_private_offset
); ctk_header_bar_class_init ((CtkHeaderBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_header_bar_get_instance_private
(CtkHeaderBar *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CtkHeaderBar_private_offset)))); } GType ctk_header_bar_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_header_bar_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_header_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkHeaderBar"
), sizeof (CtkHeaderBarClass), (GClassInitFunc)(void (*)(void
)) ctk_header_bar_class_intern_init, sizeof (CtkHeaderBar), (
GInstanceInitFunc)(void (*)(void)) ctk_header_bar_init, (GTypeFlags
) 0); { {{ CtkHeaderBar_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkHeaderBarPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_header_bar_buildable_init, ((void*)0), ((void*)0)
}; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
125 G_IMPLEMENT_INTERFACE (CTK_TYPE_BUILDABLE,static void ctk_header_bar_init (CtkHeaderBar *self); static void
ctk_header_bar_class_init (CtkHeaderBarClass *klass); static
GType ctk_header_bar_get_type_once (void); static gpointer ctk_header_bar_parent_class
= ((void*)0); static gint CtkHeaderBar_private_offset; static
void ctk_header_bar_class_intern_init (gpointer klass) { ctk_header_bar_parent_class
= g_type_class_peek_parent (klass); if (CtkHeaderBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkHeaderBar_private_offset
); ctk_header_bar_class_init ((CtkHeaderBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_header_bar_get_instance_private
(CtkHeaderBar *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CtkHeaderBar_private_offset)))); } GType ctk_header_bar_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_header_bar_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_header_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkHeaderBar"
), sizeof (CtkHeaderBarClass), (GClassInitFunc)(void (*)(void
)) ctk_header_bar_class_intern_init, sizeof (CtkHeaderBar), (
GInstanceInitFunc)(void (*)(void)) ctk_header_bar_init, (GTypeFlags
) 0); { {{ CtkHeaderBar_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkHeaderBarPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_header_bar_buildable_init, ((void*)0), ((void*)0)
}; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
126 ctk_header_bar_buildable_init))static void ctk_header_bar_init (CtkHeaderBar *self); static void
ctk_header_bar_class_init (CtkHeaderBarClass *klass); static
GType ctk_header_bar_get_type_once (void); static gpointer ctk_header_bar_parent_class
= ((void*)0); static gint CtkHeaderBar_private_offset; static
void ctk_header_bar_class_intern_init (gpointer klass) { ctk_header_bar_parent_class
= g_type_class_peek_parent (klass); if (CtkHeaderBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkHeaderBar_private_offset
); ctk_header_bar_class_init ((CtkHeaderBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_header_bar_get_instance_private
(CtkHeaderBar *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CtkHeaderBar_private_offset)))); } GType ctk_header_bar_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_header_bar_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_header_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkHeaderBar"
), sizeof (CtkHeaderBarClass), (GClassInitFunc)(void (*)(void
)) ctk_header_bar_class_intern_init, sizeof (CtkHeaderBar), (
GInstanceInitFunc)(void (*)(void)) ctk_header_bar_init, (GTypeFlags
) 0); { {{ CtkHeaderBar_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkHeaderBarPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_header_bar_buildable_init, ((void*)0), ((void*)0)
}; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
;
127
128static void
129init_sizing_box (CtkHeaderBar *bar)
130{
131 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
132 CtkWidget *w;
133 CtkStyleContext *context;
134
135 /* We use this box to always request size for the two labels (title
136 * and subtitle) as if they were always visible, but then allocate
137 * the real label box with its actual size, to keep it center-aligned
138 * in case we have only the title.
139 */
140 w = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
141 ctk_widget_show (w);
142 priv->label_sizing_box = g_object_ref_sink (w)((__typeof__ (w)) (g_object_ref_sink) (w));
143
144 w = ctk_label_new (NULL((void*)0));
145 ctk_widget_show (w);
146 context = ctk_widget_get_style_context (w);
147 ctk_style_context_add_class (context, CTK_STYLE_CLASS_TITLE"title");
148 ctk_box_pack_start (CTK_BOX (priv->label_sizing_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label_sizing_box)), ((ctk_box_get_type ()))))))
, w, FALSE(0), FALSE(0), 0);
149 ctk_label_set_line_wrap (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, FALSE(0));
150 ctk_label_set_single_line_mode (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
151 ctk_label_set_ellipsize (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, PANGO_ELLIPSIZE_END);
152 ctk_label_set_width_chars (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, MIN_TITLE_CHARS5);
153
154 w = ctk_label_new (NULL((void*)0));
155 context = ctk_widget_get_style_context (w);
156 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SUBTITLE"subtitle");
157 ctk_box_pack_start (CTK_BOX (priv->label_sizing_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label_sizing_box)), ((ctk_box_get_type ()))))))
, w, FALSE(0), FALSE(0), 0);
158 ctk_label_set_line_wrap (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, FALSE(0));
159 ctk_label_set_single_line_mode (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
160 ctk_label_set_ellipsize (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, PANGO_ELLIPSIZE_END);
161 ctk_widget_set_visible (w, priv->has_subtitle || (priv->subtitle && priv->subtitle[0]));
162 priv->subtitle_sizing_label = w;
163}
164
165static CtkWidget *
166create_title_box (const char *title,
167 const char *subtitle,
168 CtkWidget **ret_title_label,
169 CtkWidget **ret_subtitle_label)
170{
171 CtkWidget *label_box;
172 CtkWidget *title_label;
173 CtkWidget *subtitle_label;
174 CtkStyleContext *context;
175
176 label_box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
177 ctk_widget_set_valign (label_box, CTK_ALIGN_CENTER);
178 ctk_widget_show (label_box);
179
180 title_label = ctk_label_new (title);
181 context = ctk_widget_get_style_context (title_label);
182 ctk_style_context_add_class (context, CTK_STYLE_CLASS_TITLE"title");
183 ctk_label_set_line_wrap (CTK_LABEL (title_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_label_get_type ()))))))
, FALSE(0));
184 ctk_label_set_single_line_mode (CTK_LABEL (title_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
185 ctk_label_set_ellipsize (CTK_LABEL (title_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_label_get_type ()))))))
, PANGO_ELLIPSIZE_END);
186 ctk_box_pack_start (CTK_BOX (label_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_box)), ((ctk_box_get_type ()))))))
, title_label, FALSE(0), FALSE(0), 0);
187 ctk_widget_show (title_label);
188 ctk_label_set_width_chars (CTK_LABEL (title_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_label_get_type ()))))))
, MIN_TITLE_CHARS5);
189
190 subtitle_label = ctk_label_new (subtitle);
191 context = ctk_widget_get_style_context (subtitle_label);
192 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SUBTITLE"subtitle");
193 ctk_label_set_line_wrap (CTK_LABEL (subtitle_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((subtitle_label)), ((ctk_label_get_type ()))))))
, FALSE(0));
194 ctk_label_set_single_line_mode (CTK_LABEL (subtitle_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((subtitle_label)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
195 ctk_label_set_ellipsize (CTK_LABEL (subtitle_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((subtitle_label)), ((ctk_label_get_type ()))))))
, PANGO_ELLIPSIZE_END);
196 ctk_box_pack_start (CTK_BOX (label_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_box)), ((ctk_box_get_type ()))))))
, subtitle_label, FALSE(0), FALSE(0), 0);
197 ctk_widget_set_no_show_all (subtitle_label, TRUE(!(0)));
198 ctk_widget_set_visible (subtitle_label, subtitle && subtitle[0]);
199
200 if (ret_title_label)
201 *ret_title_label = title_label;
202 if (ret_subtitle_label)
203 *ret_subtitle_label = subtitle_label;
204
205 return label_box;
206}
207
208gboolean
209_ctk_header_bar_update_window_icon (CtkHeaderBar *bar,
210 CtkWindow *window)
211{
212 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
213 GdkPixbuf *pixbuf;
214 gint scale;
215
216 if (priv->titlebar_icon == NULL((void*)0))
217 return FALSE(0);
218
219 scale = ctk_widget_get_scale_factor (priv->titlebar_icon);
220 if (CTK_IS_BUTTON (ctk_widget_get_parent (priv->titlebar_icon))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_parent (priv->titlebar_icon))); GType __t =
((ctk_button_get_type ())); gboolean __r; if (!__inst) __r =
(0); else if (__inst->g_class && __inst->g_class
->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; }))))
)
221 pixbuf = ctk_window_get_icon_for_size (window, scale * 16);
222 else
223 pixbuf = ctk_window_get_icon_for_size (window, scale * 20);
224
225 if (pixbuf)
226 {
227 cairo_surface_t *surface;
228
229 surface = cdk_cairo_surface_create_from_pixbuf (pixbuf, scale, ctk_widget_get_window (priv->titlebar_icon));
230
231 ctk_image_set_from_surface (CTK_IMAGE (priv->titlebar_icon)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->titlebar_icon)), ((ctk_image_get_type ()))))))
, surface);
232 cairo_surface_destroy (surface);
233 g_object_unref (pixbuf);
234 ctk_widget_show (priv->titlebar_icon);
235
236 return TRUE(!(0));
237 }
238
239 return FALSE(0);
240}
241
242static void
243_ctk_header_bar_update_separator_visibility (CtkHeaderBar *bar)
244{
245 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
246 gboolean have_visible_at_start = FALSE(0);
247 gboolean have_visible_at_end = FALSE(0);
248 GList *l;
249
250 for (l = priv->children; l != NULL((void*)0); l = l->next)
251 {
252 Child *child = l->data;
253
254 if (ctk_widget_get_visible (child->widget))
255 {
256 if (child->pack_type == CTK_PACK_START)
257 have_visible_at_start = TRUE(!(0));
258 else
259 have_visible_at_end = TRUE(!(0));
260 }
261 }
262
263 if (priv->titlebar_start_separator != NULL((void*)0))
264 ctk_widget_set_visible (priv->titlebar_start_separator, have_visible_at_start);
265
266 if (priv->titlebar_end_separator != NULL((void*)0))
267 ctk_widget_set_visible (priv->titlebar_end_separator, have_visible_at_end);
268}
269
270void
271_ctk_header_bar_update_window_buttons (CtkHeaderBar *bar)
272{
273 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
274 CtkWidget *widget = CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
, *toplevel;
275 CtkWindow *window;
276 CtkTextDirection direction;
277 gchar *layout_desc;
278 gchar **tokens, **t;
279 gint i, j;
280 GMenuModel *menu;
281 gboolean shown_by_shell;
282 gboolean is_sovereign_window;
283
284 toplevel = ctk_widget_get_toplevel (widget);
285 if (!ctk_widget_is_toplevel (toplevel))
286 return;
287
288 if (priv->titlebar_start_box)
289 {
290 ctk_widget_unparent (priv->titlebar_start_box);
291 priv->titlebar_start_box = NULL((void*)0);
292 priv->titlebar_start_separator = NULL((void*)0);
293 }
294 if (priv->titlebar_end_box)
295 {
296 ctk_widget_unparent (priv->titlebar_end_box);
297 priv->titlebar_end_box = NULL((void*)0);
298 priv->titlebar_end_separator = NULL((void*)0);
299 }
300
301 priv->titlebar_icon = NULL((void*)0);
302
303 if (!priv->shows_wm_decorations)
304 return;
305
306 direction = ctk_widget_get_direction (widget);
307
308 g_object_get (ctk_widget_get_settings (widget),
309 "ctk-shell-shows-app-menu", &shown_by_shell,
310 "ctk-decoration-layout", &layout_desc,
311 NULL((void*)0));
312
313 if (priv->decoration_layout_set)
314 {
315 g_free (layout_desc);
316 layout_desc = g_strdup (priv->decoration_layout)g_strdup_inline (priv->decoration_layout);
317 }
318
319 window = CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
;
320
321 if (!shown_by_shell && ctk_window_get_application (window))
322 menu = ctk_application_get_app_menu (ctk_window_get_application (window));
323 else
324 menu = NULL((void*)0);
325
326 is_sovereign_window = (!ctk_window_get_modal (window) &&
327 ctk_window_get_transient_for (window) == NULL((void*)0) &&
328 ctk_window_get_type_hint (window) == CDK_WINDOW_TYPE_HINT_NORMAL);
329
330 tokens = g_strsplit (layout_desc, ":", 2);
331 if (tokens)
332 {
333 for (i = 0; i < 2; i++)
334 {
335 CtkWidget *box;
336 CtkWidget *separator;
337 int n_children = 0;
338
339 if (tokens[i] == NULL((void*)0))
340 break;
341
342 t = g_strsplit (tokens[i], ",", -1);
343
344 separator = ctk_separator_new (CTK_ORIENTATION_VERTICAL);
345 ctk_widget_set_no_show_all (separator, TRUE(!(0)));
346 ctk_style_context_add_class (ctk_widget_get_style_context (separator), "titlebutton");
347
348 box = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, priv->spacing);
349
350 for (j = 0; t[j]; j++)
351 {
352 CtkWidget *button = NULL((void*)0);
353 CtkWidget *image = NULL((void*)0);
354 AtkObject *accessible;
355
356 if (strcmp (t[j], "icon") == 0 &&
357 is_sovereign_window)
358 {
359 button = ctk_image_new ();
360 ctk_widget_set_valign (button, CTK_ALIGN_CENTER);
361 priv->titlebar_icon = button;
362 ctk_style_context_add_class (ctk_widget_get_style_context (button), "titlebutton");
363 ctk_style_context_add_class (ctk_widget_get_style_context (button), "icon");
364 ctk_widget_set_size_request (button, 20, 20);
365 ctk_widget_show (button);
366
367 if (!_ctk_header_bar_update_window_icon (bar, window))
368 {
369 ctk_widget_destroy (button);
370 priv->titlebar_icon = NULL((void*)0);
371 button = NULL((void*)0);
372 }
373 }
374 else if (strcmp (t[j], "menu") == 0 &&
375 menu != NULL((void*)0) &&
376 is_sovereign_window)
377 {
378 button = ctk_menu_button_new ();
379 ctk_widget_set_valign (button, CTK_ALIGN_CENTER);
380 ctk_menu_button_set_menu_model (CTK_MENU_BUTTON (button)((((CtkMenuButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_menu_button_get_type ()))))))
, menu);
381 ctk_menu_button_set_use_popover (CTK_MENU_BUTTON (button)((((CtkMenuButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_menu_button_get_type ()))))))
, TRUE(!(0)));
382 ctk_style_context_add_class (ctk_widget_get_style_context (button), "titlebutton");
383 ctk_style_context_add_class (ctk_widget_get_style_context (button), "appmenu");
384 image = ctk_image_new ();
385 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, image);
386 ctk_widget_set_can_focus (button, FALSE(0));
387 ctk_widget_show_all (button);
388
389 accessible = ctk_widget_get_accessible (button);
390 if (CTK_IS_ACCESSIBLE (accessible)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(accessible)); GType __t = ((ctk_accessible_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
391 atk_object_set_name (accessible, _("Application menu")((char *) g_dgettext ("ctk30", "Application menu")));
392
393 priv->titlebar_icon = image;
394 if (!_ctk_header_bar_update_window_icon (bar, window))
395 ctk_image_set_from_icon_name (CTK_IMAGE (priv->titlebar_icon)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->titlebar_icon)), ((ctk_image_get_type ()))))))
,
396 "application-x-executable-symbolic", CTK_ICON_SIZE_MENU);
397 }
398 else if (strcmp (t[j], "minimize") == 0 &&
399 is_sovereign_window)
400 {
401 button = ctk_button_new ();
402 ctk_widget_set_valign (button, CTK_ALIGN_CENTER);
403 ctk_style_context_add_class (ctk_widget_get_style_context (button), "titlebutton");
404 ctk_style_context_add_class (ctk_widget_get_style_context (button), "minimize");
405 image = ctk_image_new_from_icon_name ("window-minimize-symbolic", CTK_ICON_SIZE_MENU);
406 g_object_set (image, "use-fallback", TRUE(!(0)), NULL((void*)0));
407 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, image);
408 ctk_widget_set_can_focus (button, FALSE(0));
409 ctk_widget_show_all (button);
410 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_window_iconify))), (window), ((void*)0), G_CONNECT_SWAPPED
)
411 G_CALLBACK (ctk_window_iconify), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_window_iconify))), (window), ((void*)0), G_CONNECT_SWAPPED
)
;
412
413 accessible = ctk_widget_get_accessible (button);
414 if (CTK_IS_ACCESSIBLE (accessible)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(accessible)); GType __t = ((ctk_accessible_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
415 atk_object_set_name (accessible, _("Minimize")((char *) g_dgettext ("ctk30", "Minimize")));
416 }
417 else if (strcmp (t[j], "maximize") == 0 &&
418 ctk_window_get_resizable (window) &&
419 is_sovereign_window)
420 {
421 const gchar *icon_name;
422 gboolean maximized = ctk_window_is_maximized (window);
423
424 icon_name = maximized ? "window-restore-symbolic" : "window-maximize-symbolic";
425 button = ctk_button_new ();
426 ctk_widget_set_valign (button, CTK_ALIGN_CENTER);
427 ctk_style_context_add_class (ctk_widget_get_style_context (button), "titlebutton");
428 ctk_style_context_add_class (ctk_widget_get_style_context (button), "maximize");
429 image = ctk_image_new_from_icon_name (icon_name, CTK_ICON_SIZE_MENU);
430 g_object_set (image, "use-fallback", TRUE(!(0)), NULL((void*)0));
431 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, image);
432 ctk_widget_set_can_focus (button, FALSE(0));
433 ctk_widget_show_all (button);
434 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
_ctk_window_toggle_maximized))), (window), ((void*)0), G_CONNECT_SWAPPED
)
435 G_CALLBACK (_ctk_window_toggle_maximized), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
_ctk_window_toggle_maximized))), (window), ((void*)0), G_CONNECT_SWAPPED
)
;
436
437 accessible = ctk_widget_get_accessible (button);
438 if (CTK_IS_ACCESSIBLE (accessible)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(accessible)); GType __t = ((ctk_accessible_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
439 atk_object_set_name (accessible, maximized ? _("Restore")((char *) g_dgettext ("ctk30", "Restore")) : _("Maximize")((char *) g_dgettext ("ctk30", "Maximize")));
440 }
441 else if (strcmp (t[j], "close") == 0 &&
442 ctk_window_get_deletable (window))
443 {
444 button = ctk_button_new ();
445 ctk_widget_set_valign (button, CTK_ALIGN_CENTER);
446 image = ctk_image_new_from_icon_name ("window-close-symbolic", CTK_ICON_SIZE_MENU);
447 ctk_style_context_add_class (ctk_widget_get_style_context (button), "titlebutton");
448 ctk_style_context_add_class (ctk_widget_get_style_context (button), "close");
449 g_object_set (image, "use-fallback", TRUE(!(0)), NULL((void*)0));
450 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, image);
451 ctk_widget_set_can_focus (button, FALSE(0));
452 ctk_widget_show_all (button);
453 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_window_close))), (window), ((void*)0), G_CONNECT_SWAPPED)
454 G_CALLBACK (ctk_window_close), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_window_close))), (window), ((void*)0), G_CONNECT_SWAPPED)
;
455
456 accessible = ctk_widget_get_accessible (button);
457 if (CTK_IS_ACCESSIBLE (accessible)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(accessible)); GType __t = ((ctk_accessible_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
458 atk_object_set_name (accessible, _("Close")((char *) g_dgettext ("ctk30", "Close")));
459 }
460
461 if (button)
462 {
463 ctk_box_pack_start (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_box_get_type ()))))))
, button, FALSE(0), FALSE(0), 0);
464 n_children ++;
465 }
466 }
467 g_strfreev (t);
468
469 if (n_children == 0)
470 {
471 g_object_ref_sink (box)((__typeof__ (box)) (g_object_ref_sink) (box));
472 g_object_unref (box);
473 g_object_ref_sink (separator)((__typeof__ (separator)) (g_object_ref_sink) (separator));
474 g_object_unref (separator);
475 continue;
476 }
477
478 ctk_box_pack_start (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_box_get_type ()))))))
, separator, FALSE(0), FALSE(0), 0);
479 if (i == 1)
480 ctk_box_reorder_child (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_box_get_type ()))))))
, separator, 0);
481
482 if ((direction == CTK_TEXT_DIR_LTR && i == 0) ||
483 (direction == CTK_TEXT_DIR_RTL && i == 1))
484 {
485 ctk_style_context_add_class (ctk_widget_get_style_context (box), CTK_STYLE_CLASS_LEFT"left");
486 ctk_css_node_insert_after (ctk_widget_get_css_node (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
),
487 ctk_widget_get_css_node (box),
488 NULL((void*)0));
489 }
490 else
491 {
492 ctk_style_context_add_class (ctk_widget_get_style_context (box), CTK_STYLE_CLASS_RIGHT"right");
493 ctk_css_node_insert_before (ctk_widget_get_css_node (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
),
494 ctk_widget_get_css_node (box),
495 NULL((void*)0));
496 }
497
498 ctk_widget_show (box);
499 ctk_widget_set_parent (box, CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
500
501 if (i == 0)
502 {
503 priv->titlebar_start_box = box;
504 priv->titlebar_start_separator = separator;
505 }
506 else
507 {
508 priv->titlebar_end_box = box;
509 priv->titlebar_end_separator = separator;
510 }
511 }
512 g_strfreev (tokens);
513 }
514 g_free (layout_desc);
515
516 _ctk_header_bar_update_separator_visibility (bar);
517}
518
519gboolean
520_ctk_header_bar_shows_app_menu (CtkHeaderBar *bar)
521{
522 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
523 CtkWindow *window;
524 gchar *layout_desc;
525 gboolean ret;
526
527 window = CTK_WINDOW (ctk_widget_get_toplevel (CTK_WIDGET (bar)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((bar)), ((ctk_widget_get_type ())))))))))
, ((ctk_window_get_type ()))))))
;
528 ctk_widget_style_get (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
,
529 "decoration-button-layout", &layout_desc,
530 NULL((void*)0));
531
532 ret = priv->shows_wm_decorations &&
533 (layout_desc && strstr (layout_desc, "menu"));
534
535 g_free (layout_desc);
536
537 return ret;
538}
539
540/* As an intended side effect, this function allows @child
541 * to be the title/label box */
542static void
543ctk_header_bar_reorder_css_node (CtkHeaderBar *bar,
544 CtkPackType pack_type,
545 CtkWidget *widget)
546{
547 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
548 CtkWidget *previous_widget;
549 GList *l;
550
551 if (pack_type == CTK_PACK_START)
552 previous_widget = priv->titlebar_start_box;
553 else
554 previous_widget = priv->titlebar_end_box;
555
556 for (l = priv->children; l; l = l->next)
557 {
558 Child *iter = l->data;
559
560 if (iter->widget == widget)
561 break;
562
563 if (iter->pack_type == pack_type)
564 previous_widget = iter->widget;
565 }
566
567 if ((pack_type == CTK_PACK_START)
568 ^ (ctk_widget_get_direction (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_LTR))
569 ctk_css_node_insert_after (ctk_widget_get_css_node (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
),
570 ctk_widget_get_css_node (widget),
571 previous_widget ? ctk_widget_get_css_node (previous_widget) : NULL((void*)0));
572 else
573 ctk_css_node_insert_before (ctk_widget_get_css_node (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
),
574 ctk_widget_get_css_node (widget),
575 previous_widget ? ctk_widget_get_css_node (previous_widget) : NULL((void*)0));
576}
577
578static void
579construct_label_box (CtkHeaderBar *bar)
580{
581 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
582
583 g_assert (priv->label_box == NULL)do { if (priv->label_box == ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkheaderbar.c", 583, ((const char*) (__func__)), "priv->label_box == NULL"
); } while (0)
;
584
585 priv->label_box = create_title_box (priv->title,
586 priv->subtitle,
587 &priv->title_label,
588 &priv->subtitle_label);
589 ctk_header_bar_reorder_css_node (bar, CTK_PACK_START, priv->label_box);
590 ctk_widget_set_parent (priv->label_box, CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
591}
592
593static gint
594count_visible_children (CtkHeaderBar *bar)
595{
596 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
597 GList *l;
598 Child *child;
599 gint n;
600
601 n = 0;
602 for (l = priv->children; l; l = l->next)
603 {
604 child = l->data;
605 if (ctk_widget_get_visible (child->widget))
606 n++;
607 }
608
609 return n;
610}
611
612static gboolean
613add_child_size (CtkWidget *child,
614 CtkOrientation orientation,
615 gint *minimum,
616 gint *natural)
617{
618 gint child_minimum, child_natural;
619
620 if (!ctk_widget_get_visible (child))
621 return FALSE(0);
622
623 if (orientation == CTK_ORIENTATION_HORIZONTAL)
624 ctk_widget_get_preferred_width (child, &child_minimum, &child_natural);
625 else
626 ctk_widget_get_preferred_height (child, &child_minimum, &child_natural);
627
628 if (CTK_ORIENTATION_HORIZONTAL == orientation)
629 {
630 *minimum += child_minimum;
631 *natural += child_natural;
632 }
633 else
634 {
635 *minimum = MAX (*minimum, child_minimum)(((*minimum) > (child_minimum)) ? (*minimum) : (child_minimum
))
;
636 *natural = MAX (*natural, child_natural)(((*natural) > (child_natural)) ? (*natural) : (child_natural
))
;
637 }
638
639 return TRUE(!(0));
640}
641
642static void
643ctk_header_bar_get_size (CtkWidget *widget,
644 CtkOrientation orientation,
645 gint *minimum_size,
646 gint *natural_size)
647{
648 CtkHeaderBar *bar = CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
;
649 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
650 GList *l;
651 gint nvis_children;
652 gint minimum, natural;
653 gint center_min, center_nat;
654
655 minimum = natural = 0;
656 nvis_children = 0;
657
658 for (l = priv->children; l; l = l->next)
659 {
660 Child *child = l->data;
661
662 if (add_child_size (child->widget, orientation, &minimum, &natural))
663 nvis_children += 1;
664 }
665
666 center_min = center_nat = 0;
667 if (priv->label_box != NULL((void*)0))
668 {
669 if (orientation == CTK_ORIENTATION_HORIZONTAL)
670 add_child_size (priv->label_box, orientation, &center_min, &center_nat);
671 else
672 add_child_size (priv->label_sizing_box, orientation, &center_min, &center_nat);
673
674 if (_ctk_widget_get_visible (priv->label_sizing_box))
675 nvis_children += 1;
676 }
677
678 if (priv->custom_title != NULL((void*)0))
679 {
680 if (add_child_size (priv->custom_title, orientation, &center_min, &center_nat))
681 nvis_children += 1;
682 }
683
684 if (priv->titlebar_start_box != NULL((void*)0))
685 {
686 if (add_child_size (priv->titlebar_start_box, orientation, &minimum, &natural))
687 nvis_children += 1;
688 }
689
690 if (priv->titlebar_end_box != NULL((void*)0))
691 {
692 if (add_child_size (priv->titlebar_end_box, orientation, &minimum, &natural))
693 nvis_children += 1;
694 }
695
696 if (orientation == CTK_ORIENTATION_HORIZONTAL)
697 {
698 minimum += center_min;
699 natural += center_nat;
700 }
701 else
702 {
703 minimum = MAX (minimum, center_min)(((minimum) > (center_min)) ? (minimum) : (center_min));
704 natural = MAX (natural, center_nat)(((natural) > (center_nat)) ? (natural) : (center_nat));
705 }
706
707 if (nvis_children > 0 && orientation == CTK_ORIENTATION_HORIZONTAL)
708 {
709 minimum += nvis_children * priv->spacing;
710 natural += nvis_children * priv->spacing;
711 }
712
713 *minimum_size = minimum;
714 *natural_size = natural;
715}
716
717static void
718ctk_header_bar_compute_size_for_orientation (CtkWidget *widget,
719 gint avail_size,
720 gint *minimum_size,
721 gint *natural_size)
722{
723 CtkHeaderBar *bar = CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
;
724 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
725 GList *children;
726 gint required_size = 0;
727 gint required_natural = 0;
728 gint child_size;
729 gint child_natural;
730 gint nvis_children;
731
732 nvis_children = 0;
733
734 for (children = priv->children; children != NULL((void*)0); children = children->next)
735 {
736 Child *child = children->data;
737
738 if (ctk_widget_get_visible (child->widget))
739 {
740 ctk_widget_get_preferred_width_for_height (child->widget,
741 avail_size, &child_size, &child_natural);
742
743 required_size += child_size;
744 required_natural += child_natural;
745
746 nvis_children += 1;
747 }
748 }
749
750 if (priv->label_box != NULL((void*)0))
751 {
752 ctk_widget_get_preferred_width (priv->label_sizing_box,
753 &child_size, &child_natural);
754 required_size += child_size;
755 required_natural += child_natural;
756 }
757
758 if (priv->custom_title != NULL((void*)0) &&
759 ctk_widget_get_visible (priv->custom_title))
760 {
761 ctk_widget_get_preferred_width (priv->custom_title,
762 &child_size, &child_natural);
763 required_size += child_size;
764 required_natural += child_natural;
765 }
766
767 if (priv->titlebar_start_box != NULL((void*)0))
768 {
769 ctk_widget_get_preferred_width (priv->titlebar_start_box,
770 &child_size, &child_natural);
771 required_size += child_size;
772 required_natural += child_natural;
773 nvis_children += 1;
774 }
775
776 if (priv->titlebar_end_box != NULL((void*)0))
777 {
778 ctk_widget_get_preferred_width (priv->titlebar_end_box,
779 &child_size, &child_natural);
780 required_size += child_size;
781 required_natural += child_natural;
782 nvis_children += 1;
783 }
784
785 if (nvis_children > 0)
786 {
787 required_size += nvis_children * priv->spacing;
788 required_natural += nvis_children * priv->spacing;
789 }
790
791 *minimum_size = required_size;
792 *natural_size = required_natural;
793}
794
795static void
796ctk_header_bar_compute_size_for_opposing_orientation (CtkWidget *widget,
797 gint avail_size,
798 gint *minimum_size,
799 gint *natural_size)
800{
801 CtkHeaderBar *bar = CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
;
802 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
803 Child *child;
804 GList *children;
805 gint nvis_children;
806 gint computed_minimum = 0;
807 gint computed_natural = 0;
808 CtkRequestedSize *sizes;
809 CtkPackType packing;
810 gint size = 0;
811 gint i;
812 gint child_size;
813 gint child_minimum;
814 gint child_natural;
815 gint center_min, center_nat;
816
817 nvis_children = count_visible_children (bar);
818
819 if (nvis_children <= 0)
820 return;
821
822 sizes = g_newa (CtkRequestedSize, nvis_children)((CtkRequestedSize*) __builtin_alloca (sizeof (CtkRequestedSize
) * (gsize) (nvis_children)))
;
823
824 /* Retrieve desired size for visible children */
825 for (i = 0, children = priv->children; children; children = children->next)
826 {
827 child = children->data;
828
829 if (ctk_widget_get_visible (child->widget))
830 {
831 ctk_widget_get_preferred_width (child->widget,
832 &sizes[i].minimum_size,
833 &sizes[i].natural_size);
834
835 size -= sizes[i].minimum_size;
836 sizes[i].data = child;
837 i += 1;
838 }
839 }
840
841 /* Bring children up to size first */
842 size = ctk_distribute_natural_allocation (MAX (0, avail_size)(((0) > (avail_size)) ? (0) : (avail_size)), nvis_children, sizes);
843
844 /* Allocate child positions. */
845 for (packing = CTK_PACK_START; packing <= CTK_PACK_END; ++packing)
846 {
847 for (i = 0, children = priv->children; children; children = children->next)
848 {
849 child = children->data;
850
851 /* If widget is not visible, skip it. */
852 if (!ctk_widget_get_visible (child->widget))
853 continue;
854
855 /* If widget is packed differently skip it, but still increment i,
856 * since widget is visible and will be handled in next loop
857 * iteration.
858 */
859 if (child->pack_type != packing)
860 {
861 i++;
862 continue;
863 }
864
865 child_size = sizes[i].minimum_size;
866
867 ctk_widget_get_preferred_height_for_width (child->widget,
868 child_size, &child_minimum, &child_natural);
869
870 computed_minimum = MAX (computed_minimum, child_minimum)(((computed_minimum) > (child_minimum)) ? (computed_minimum
) : (child_minimum))
;
871 computed_natural = MAX (computed_natural, child_natural)(((computed_natural) > (child_natural)) ? (computed_natural
) : (child_natural))
;
872 }
873 i += 1;
874 }
875
876 center_min = center_nat = 0;
877 if (priv->label_box != NULL((void*)0))
878 {
879 ctk_widget_get_preferred_height (priv->label_sizing_box,
880 &center_min, &center_nat);
881 }
882
883 if (priv->custom_title != NULL((void*)0) &&
884 ctk_widget_get_visible (priv->custom_title))
885 {
886 ctk_widget_get_preferred_height (priv->custom_title,
887 &center_min, &center_nat);
888 }
889
890 if (priv->titlebar_start_box != NULL((void*)0))
891 {
892 ctk_widget_get_preferred_height (priv->titlebar_start_box,
893 &child_minimum, &child_natural);
894 computed_minimum = MAX (computed_minimum, child_minimum)(((computed_minimum) > (child_minimum)) ? (computed_minimum
) : (child_minimum))
;
895 computed_natural = MAX (computed_natural, child_natural)(((computed_natural) > (child_natural)) ? (computed_natural
) : (child_natural))
;
896 }
897
898 if (priv->titlebar_end_box != NULL((void*)0))
899 {
900 ctk_widget_get_preferred_height (priv->titlebar_end_box,
901 &child_minimum, &child_natural);
902 computed_minimum = MAX (computed_minimum, child_minimum)(((computed_minimum) > (child_minimum)) ? (computed_minimum
) : (child_minimum))
;
903 computed_natural = MAX (computed_natural, child_natural)(((computed_natural) > (child_natural)) ? (computed_natural
) : (child_natural))
;
904 }
905
906 *minimum_size = computed_minimum;
907 *natural_size = computed_natural;
908}
909
910static void
911ctk_header_bar_get_content_size (CtkCssGadget *gadget,
912 CtkOrientation orientation,
913 gint for_size,
914 gint *minimum,
915 gint *natural,
916 gint *minimum_baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
917 gint *natural_baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
918 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
919{
920 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
921
922 if (for_size < 0)
923 ctk_header_bar_get_size (widget, orientation, minimum, natural);
924 else if (orientation == CTK_ORIENTATION_HORIZONTAL)
925 ctk_header_bar_compute_size_for_orientation (widget, for_size, minimum, natural);
926 else
927 ctk_header_bar_compute_size_for_opposing_orientation (widget, for_size, minimum, natural);
928}
929
930static void
931ctk_header_bar_get_preferred_width (CtkWidget *widget,
932 gint *minimum,
933 gint *natural)
934{
935 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
936
937 ctk_css_gadget_get_preferred_size (priv->gadget,
938 CTK_ORIENTATION_HORIZONTAL,
939 -1,
940 minimum, natural,
941 NULL((void*)0), NULL((void*)0));
942}
943
944static void
945ctk_header_bar_get_preferred_height (CtkWidget *widget,
946 gint *minimum,
947 gint *natural)
948{
949 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
950
951 ctk_css_gadget_get_preferred_size (priv->gadget,
952 CTK_ORIENTATION_VERTICAL,
953 -1,
954 minimum, natural,
955 NULL((void*)0), NULL((void*)0));
956}
957
958static void
959ctk_header_bar_get_preferred_width_for_height (CtkWidget *widget,
960 gint height,
961 gint *minimum,
962 gint *natural)
963{
964 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
965
966 ctk_css_gadget_get_preferred_size (priv->gadget,
967 CTK_ORIENTATION_HORIZONTAL,
968 height,
969 minimum, natural,
970 NULL((void*)0), NULL((void*)0));
971}
972
973static void
974ctk_header_bar_get_preferred_height_for_width (CtkWidget *widget,
975 gint width,
976 gint *minimum,
977 gint *natural)
978{
979 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
980
981 ctk_css_gadget_get_preferred_size (priv->gadget,
982 CTK_ORIENTATION_VERTICAL,
983 width,
984 minimum, natural,
985 NULL((void*)0), NULL((void*)0));
986}
987
988static void
989ctk_header_bar_size_allocate (CtkWidget *widget,
990 CtkAllocation *allocation)
991{
992 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
993 CtkAllocation clip;
994
995 ctk_widget_set_allocation (widget, allocation);
996
997 ctk_css_gadget_allocate (priv->gadget, allocation, ctk_widget_get_allocated_baseline (widget), &clip);
998
999 ctk_widget_set_clip (widget, &clip);
1000}
1001
1002static void
1003ctk_header_bar_allocate_contents (CtkCssGadget *gadget,
1004 const CtkAllocation *allocation,
1005 int baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
1006 CtkAllocation *out_clip,
1007 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
1008{
1009 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
1010 CtkWidget *title_widget;
1011 CtkHeaderBar *bar = CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
;
1012 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1013 CtkRequestedSize *sizes;
1014 gint width, height;
1015 gint nvis_children;
1016 gint title_minimum_size;
1017 gint title_natural_size;
1018 gboolean title_expands = FALSE(0);
1019 gint start_width, end_width;
1020 gint uniform_expand_bonus[2] = { 0 };
1021 gint leftover_expand_bonus[2] = { 0 };
1022 gint nexpand_children[2] = { 0 };
1023 gint side[2];
1024 GList *l;
1025 gint i;
1026 Child *child;
1027 CtkPackType packing;
1028 CtkAllocation child_allocation;
1029 gint x;
1030 gint child_size;
1031 CtkTextDirection direction;
1032
1033 direction = ctk_widget_get_direction (widget);
1034 nvis_children = count_visible_children (bar);
1035 sizes = g_newa (CtkRequestedSize, nvis_children)((CtkRequestedSize*) __builtin_alloca (sizeof (CtkRequestedSize
) * (gsize) (nvis_children)))
;
1036
1037 width = allocation->width - nvis_children * priv->spacing;
1038 height = allocation->height;
1039
1040 i = 0;
1041 for (l = priv->children; l; l = l->next)
1
Loop condition is true. Entering loop body
5
Loop condition is false. Execution continues on line 1058
1042 {
1043 child = l->data;
1044 if (!ctk_widget_get_visible (child->widget))
2
Assuming the condition is true
3
Taking true branch
1045 continue;
4
Execution continues on line 1041
1046
1047 if (ctk_widget_compute_expand (child->widget, CTK_ORIENTATION_HORIZONTAL))
1048 nexpand_children[child->pack_type]++;
1049
1050 ctk_widget_get_preferred_width_for_height (child->widget,
1051 height,
1052 &sizes[i].minimum_size,
1053 &sizes[i].natural_size);
1054 width -= sizes[i].minimum_size;
1055 i++;
1056 }
1057
1058 title_minimum_size = 0;
1059 title_natural_size = 0;
1060
1061 if (priv->custom_title != NULL((void*)0) &&
6
Assuming field 'custom_title' is not equal to NULL
8
Taking true branch
1062 ctk_widget_get_visible (priv->custom_title))
7
Assuming the condition is true
1063 title_widget = priv->custom_title;
1064 else if (priv->label_box != NULL((void*)0))
1065 title_widget = priv->label_box;
1066 else
1067 title_widget = NULL((void*)0);
1068
1069 if (title_widget
8.1
'title_widget' is non-null
)
9
Taking true branch
1070 {
1071 ctk_widget_get_preferred_width_for_height (title_widget,
1072 height,
1073 &title_minimum_size,
1074 &title_natural_size);
1075 width -= title_natural_size;
1076
1077 title_expands = ctk_widget_compute_expand (title_widget, CTK_ORIENTATION_HORIZONTAL);
1078 }
1079
1080 start_width = 0;
1081 if (priv->titlebar_start_box != NULL((void*)0))
10
Assuming field 'titlebar_start_box' is equal to NULL
11
Taking false branch
1082 {
1083 gint min, nat;
1084 ctk_widget_get_preferred_width_for_height (priv->titlebar_start_box,
1085 height,
1086 &min, &nat);
1087 start_width = nat + priv->spacing;
1088 }
1089 width -= start_width;
1090
1091 end_width = 0;
1092 if (priv->titlebar_end_box != NULL((void*)0))
12
Assuming field 'titlebar_end_box' is equal to NULL
13
Taking false branch
1093 {
1094 gint min, nat;
1095 ctk_widget_get_preferred_width_for_height (priv->titlebar_end_box,
1096 height,
1097 &min, &nat);
1098 end_width = nat + priv->spacing;
1099 }
1100 width -= end_width;
1101
1102 width = ctk_distribute_natural_allocation (MAX (0, width)(((0) > (width)) ? (0) : (width)), nvis_children, sizes);
14
Assuming 'width' is < 0
15
'?' condition is true
1103
1104 /* compute the nominal size of the children filling up each side of
1105 * the title in titlebar
1106 */
1107 side[0] = start_width;
1108 side[1] = end_width;
1109 for (packing = CTK_PACK_START; packing <= CTK_PACK_END; packing++)
16
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 1131
1110 {
1111 i = 0;
1112 for (l = priv->children; l
16.1
'l' is not equal to NULL
22.1
'l' is not equal to NULL
!= NULL((void*)0); l = l->next)
17
Loop condition is true. Entering loop body
21
Loop condition is false. Execution continues on line 1109
23
Loop condition is true. Entering loop body
27
Loop condition is false. Execution continues on line 1109
1113 {
1114 child = l->data;
1115 if (!ctk_widget_get_visible (child->widget))
18
Assuming the condition is true
19
Taking true branch
24
Assuming the condition is true
25
Taking true branch
1116 continue;
20
Execution continues on line 1112
26
Execution continues on line 1112
1117
1118 if (child->pack_type == packing)
1119 side[packing] += sizes[i].minimum_size + priv->spacing;
1120
1121 i++;
1122 }
1123 }
1124
1125 /* figure out how much space is left on each side of the title,
1126 * and earkmark that space for the expanded children.
1127 *
1128 * If the title itself is expanded, then it gets half the spoils
1129 * from each side.
1130 */
1131 for (packing = CTK_PACK_START; packing <= CTK_PACK_END; packing++)
29
Loop condition is true. Entering loop body
31
Loop condition is true. Entering loop body
32
Loop condition is false. Execution continues on line 1151
1132 {
1133 gint side_free_space;
1134
1135 side_free_space = allocation->width / 2 - title_natural_size / 2 - side[packing];
1136
1137 if (side_free_space
31.1
'side_free_space' is <= 0
> 0
&& nexpand_children[packing] > 0)
30
Assuming 'side_free_space' is <= 0
1138 {
1139 width -= side_free_space;
1140
1141 if (title_expands)
1142 side_free_space -= side_free_space / 2;
1143
1144 side[packing] += side_free_space;
1145 uniform_expand_bonus[packing] = side_free_space / nexpand_children[packing];
1146 leftover_expand_bonus[packing] = side_free_space % nexpand_children[packing];
1147 }
1148 }
1149
1150 /* allocate the children on both sides of the title */
1151 for (packing = CTK_PACK_START; packing <= CTK_PACK_END; packing++)
33
Loop condition is true. Entering loop body
1152 {
1153 child_allocation.y = allocation->y;
1154 child_allocation.height = height;
1155 if (packing
33.1
'packing' is equal to CTK_PACK_START
== CTK_PACK_START)
34
Taking true branch
1156 x = allocation->x + start_width;
1157 else
1158 x = allocation->x + allocation->width - end_width;
1159
1160 i = 0;
1161 for (l = priv->children; l
34.1
'l' is not equal to NULL
!= NULL((void*)0); l = l->next)
35
Loop condition is true. Entering loop body
1162 {
1163 child = l->data;
1164 if (!ctk_widget_get_visible (child->widget))
36
Assuming the condition is false
37
Taking false branch
1165 continue;
1166
1167 if (child->pack_type != packing)
38
Assuming 'packing' is equal to field 'pack_type'
39
Taking false branch
1168 goto next;
1169
1170 child_size = sizes[i].minimum_size;
40
Access of the memory returned by 'alloca' at index 0, while it holds only 0 'struct _CtkRequestedSize' element
1171
1172 /* if this child is expanded, give it extra space from the reserves */
1173 if (ctk_widget_compute_expand (child->widget, CTK_ORIENTATION_HORIZONTAL))
1174 {
1175 gint expand_bonus;
1176
1177 expand_bonus = uniform_expand_bonus[packing];
1178
1179 if (leftover_expand_bonus[packing] > 0)
1180 {
1181 expand_bonus++;
1182 leftover_expand_bonus[packing]--;
1183 }
1184
1185 child_size += expand_bonus;
1186 }
1187
1188 child_allocation.width = child_size;
1189
1190 if (packing == CTK_PACK_START)
1191 {
1192 child_allocation.x = x;
1193 x += child_size;
1194 x += priv->spacing;
1195 }
1196 else
1197 {
1198 x -= child_size;
1199 child_allocation.x = x;
1200 x -= priv->spacing;
1201 }
1202
1203 if (direction == CTK_TEXT_DIR_RTL)
1204 child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
1205
1206 ctk_widget_size_allocate (child->widget, &child_allocation);
1207
1208 next:
1209 i++;
1210 }
1211 }
1212
1213 /* We don't enforce css borders on the center widget, to make
1214 * title/subtitle combinations fit without growing the header
1215 */
1216 child_allocation.y = allocation->y;
1217 child_allocation.height = allocation->height;
1218
1219 child_size = MIN (allocation->width - side[0] - side[1], title_natural_size)(((allocation->width - side[0] - side[1]) < (title_natural_size
)) ? (allocation->width - side[0] - side[1]) : (title_natural_size
))
;
1220
1221 child_allocation.x = allocation->x + (allocation->width - child_size) / 2;
1222 child_allocation.width = child_size;
1223
1224 /* if the title widget is expanded, then grow it by all the available
1225 * free space, and recenter it
1226 */
1227 if (title_expands && width > 0)
1228 {
1229 child_allocation.width += width;
1230 child_allocation.x -= width / 2;
1231 }
1232
1233 if (allocation->x + side[0] > child_allocation.x)
1234 child_allocation.x = allocation->x + side[0];
1235 else if (allocation->x + allocation->width - side[1] < child_allocation.x + child_allocation.width)
1236 child_allocation.x = allocation->x + allocation->width - side[1] - child_allocation.width;
1237
1238 if (direction == CTK_TEXT_DIR_RTL)
1239 child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
1240
1241 if (title_widget != NULL((void*)0))
1242 ctk_widget_size_allocate (title_widget, &child_allocation);
1243
1244 child_allocation.y = allocation->y;
1245 child_allocation.height = height;
1246
1247 if (priv->titlebar_start_box)
1248 {
1249 gboolean left = (direction == CTK_TEXT_DIR_LTR);
1250 if (left)
1251 child_allocation.x = allocation->x;
1252 else
1253 child_allocation.x = allocation->x + allocation->width - start_width + priv->spacing;
1254 child_allocation.width = start_width - priv->spacing;
1255 ctk_widget_size_allocate (priv->titlebar_start_box, &child_allocation);
1256 }
1257
1258 if (priv->titlebar_end_box)
1259 {
1260 gboolean left = (direction != CTK_TEXT_DIR_LTR);
1261 if (left)
1262 child_allocation.x = allocation->x;
1263 else
1264 child_allocation.x = allocation->x + allocation->width - end_width + priv->spacing;
1265 child_allocation.width = end_width - priv->spacing;
1266 ctk_widget_size_allocate (priv->titlebar_end_box, &child_allocation);
1267 }
1268
1269 ctk_container_get_children_clip (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
, out_clip);
1270}
1271
1272/**
1273 * ctk_header_bar_set_title:
1274 * @bar: a #CtkHeaderBar
1275 * @title: (allow-none): a title, or %NULL
1276 *
1277 * Sets the title of the #CtkHeaderBar. The title should help a user
1278 * identify the current view. A good title should not include the
1279 * application name.
1280 *
1281 * Since: 3.10
1282 */
1283void
1284ctk_header_bar_set_title (CtkHeaderBar *bar,
1285 const gchar *title)
1286{
1287 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1288 gchar *new_title;
1289
1290 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
1291
1292 new_title = g_strdup (title)g_strdup_inline (title);
1293 g_free (priv->title);
1294 priv->title = new_title;
1295
1296 if (priv->title_label != NULL((void*)0))
1297 {
1298 ctk_label_set_label (CTK_LABEL (priv->title_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->title_label)), ((ctk_label_get_type ()))))))
, priv->title);
1299 ctk_widget_queue_resize (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1300 }
1301
1302 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_TITLE]);
1303}
1304
1305/**
1306 * ctk_header_bar_get_title:
1307 * @bar: a #CtkHeaderBar
1308 *
1309 * Retrieves the title of the header. See ctk_header_bar_set_title().
1310 *
1311 * Returns: (nullable): the title of the header, or %NULL if none has
1312 * been set explicitly. The returned string is owned by the widget
1313 * and must not be modified or freed.
1314 *
1315 * Since: 3.10
1316 */
1317const gchar *
1318ctk_header_bar_get_title (CtkHeaderBar *bar)
1319{
1320 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1321
1322 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return (((void*)0)); } } while
(0)
;
1323
1324 return priv->title;
1325}
1326
1327/**
1328 * ctk_header_bar_set_subtitle:
1329 * @bar: a #CtkHeaderBar
1330 * @subtitle: (allow-none): a subtitle, or %NULL
1331 *
1332 * Sets the subtitle of the #CtkHeaderBar. The title should give a user
1333 * an additional detail to help him identify the current view.
1334 *
1335 * Note that CtkHeaderBar by default reserves room for the subtitle,
1336 * even if none is currently set. If this is not desired, set the
1337 * #CtkHeaderBar:has-subtitle property to %FALSE.
1338 *
1339 * Since: 3.10
1340 */
1341void
1342ctk_header_bar_set_subtitle (CtkHeaderBar *bar,
1343 const gchar *subtitle)
1344{
1345 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1346 gchar *new_subtitle;
1347
1348 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
1349
1350 new_subtitle = g_strdup (subtitle)g_strdup_inline (subtitle);
1351 g_free (priv->subtitle);
1352 priv->subtitle = new_subtitle;
1353
1354 if (priv->subtitle_label != NULL((void*)0))
1355 {
1356 ctk_label_set_label (CTK_LABEL (priv->subtitle_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->subtitle_label)), ((ctk_label_get_type ()))))))
, priv->subtitle);
1357 ctk_widget_set_visible (priv->subtitle_label, priv->subtitle && priv->subtitle[0]);
1358 ctk_widget_queue_resize (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1359 }
1360
1361 ctk_widget_set_visible (priv->subtitle_sizing_label, priv->has_subtitle || (priv->subtitle && priv->subtitle[0]));
1362
1363 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_SUBTITLE]);
1364}
1365
1366/**
1367 * ctk_header_bar_get_subtitle:
1368 * @bar: a #CtkHeaderBar
1369 *
1370 * Retrieves the subtitle of the header. See ctk_header_bar_set_subtitle().
1371 *
1372 * Returns: (nullable): the subtitle of the header, or %NULL if none has
1373 * been set explicitly. The returned string is owned by the widget
1374 * and must not be modified or freed.
1375 *
1376 * Since: 3.10
1377 */
1378const gchar *
1379ctk_header_bar_get_subtitle (CtkHeaderBar *bar)
1380{
1381 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1382
1383 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return (((void*)0)); } } while
(0)
;
1384
1385 return priv->subtitle;
1386}
1387
1388/**
1389 * ctk_header_bar_set_custom_title:
1390 * @bar: a #CtkHeaderBar
1391 * @title_widget: (allow-none): a custom widget to use for a title
1392 *
1393 * Sets a custom title for the #CtkHeaderBar.
1394 *
1395 * The title should help a user identify the current view. This
1396 * supersedes any title set by ctk_header_bar_set_title() or
1397 * ctk_header_bar_set_subtitle(). To achieve the same style as
1398 * the builtin title and subtitle, use the “title” and “subtitle”
1399 * style classes.
1400 *
1401 * You should set the custom title to %NULL, for the header title
1402 * label to be visible again.
1403 *
1404 * Since: 3.10
1405 */
1406void
1407ctk_header_bar_set_custom_title (CtkHeaderBar *bar,
1408 CtkWidget *title_widget)
1409{
1410 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1411
1412 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
1413 if (title_widget)
1414 g_return_if_fail (CTK_IS_WIDGET (title_widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((title_widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (title_widget)"); return; } } while (0)
;
1415
1416 /* No need to do anything if the custom widget stays the same */
1417 if (priv->custom_title == title_widget)
1418 return;
1419
1420 if (priv->custom_title)
1421 {
1422 CtkWidget *custom = priv->custom_title;
1423
1424 priv->custom_title = NULL((void*)0);
1425 ctk_widget_unparent (custom);
1426 }
1427
1428 if (title_widget != NULL((void*)0))
1429 {
1430 priv->custom_title = title_widget;
1431
1432 ctk_header_bar_reorder_css_node (bar, CTK_PACK_START, priv->custom_title);
1433 ctk_widget_set_parent (priv->custom_title, CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1434 ctk_widget_set_valign (priv->custom_title, CTK_ALIGN_CENTER);
1435
1436 if (priv->label_box != NULL((void*)0))
1437 {
1438 CtkWidget *label_box = priv->label_box;
1439
1440 priv->label_box = NULL((void*)0);
1441 priv->title_label = NULL((void*)0);
1442 priv->subtitle_label = NULL((void*)0);
1443 ctk_widget_unparent (label_box);
1444 }
1445
1446 }
1447 else
1448 {
1449 if (priv->label_box == NULL((void*)0))
1450 construct_label_box (bar);
1451 }
1452
1453 ctk_widget_queue_resize (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1454
1455 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_CUSTOM_TITLE]);
1456}
1457
1458/**
1459 * ctk_header_bar_get_custom_title:
1460 * @bar: a #CtkHeaderBar
1461 *
1462 * Retrieves the custom title widget of the header. See
1463 * ctk_header_bar_set_custom_title().
1464 *
1465 * Returns: (nullable) (transfer none): the custom title widget
1466 * of the header, or %NULL if none has been set explicitly.
1467 *
1468 * Since: 3.10
1469 */
1470CtkWidget *
1471ctk_header_bar_get_custom_title (CtkHeaderBar *bar)
1472{
1473 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1474
1475 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return (((void*)0)); } } while
(0)
;
1476
1477 return priv->custom_title;
1478}
1479
1480static void
1481ctk_header_bar_destroy (CtkWidget *widget)
1482{
1483 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
1484
1485 if (priv->label_sizing_box)
1486 {
1487 ctk_widget_destroy (priv->label_sizing_box);
1488 g_clear_object (&priv->label_sizing_box)do { _Static_assert (sizeof *((&priv->label_sizing_box
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->label_sizing_box))) _pp = ((&priv->label_sizing_box
)); __typeof__ (*((&priv->label_sizing_box))) _ptr = *
_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while
(0)
;
1489 }
1490
1491 if (priv->custom_title)
1492 {
1493 ctk_widget_unparent (priv->custom_title);
1494 priv->custom_title = NULL((void*)0);
1495 }
1496
1497 if (priv->label_box)
1498 {
1499 ctk_widget_unparent (priv->label_box);
1500 priv->label_box = NULL((void*)0);
1501 }
1502
1503 if (priv->titlebar_start_box)
1504 {
1505 ctk_widget_unparent (priv->titlebar_start_box);
1506 priv->titlebar_start_box = NULL((void*)0);
1507 priv->titlebar_start_separator = NULL((void*)0);
1508 }
1509
1510 if (priv->titlebar_end_box)
1511 {
1512 ctk_widget_unparent (priv->titlebar_end_box);
1513 priv->titlebar_end_box = NULL((void*)0);
1514 priv->titlebar_end_separator = NULL((void*)0);
1515 }
1516
1517 CTK_WIDGET_CLASS (ctk_header_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), ((ctk_widget_get_type ())
)))))
->destroy (widget);
1518}
1519
1520static void
1521ctk_header_bar_finalize (GObject *object)
1522{
1523 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (object)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_header_bar_get_type ()))))))
);
1524
1525 g_free (priv->title);
1526 g_free (priv->subtitle);
1527 g_free (priv->decoration_layout);
1528
1529 g_clear_object (&priv->gadget)do { _Static_assert (sizeof *((&priv->gadget)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->gadget))) _pp = ((&priv->gadget)); __typeof__
(*((&priv->gadget))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
1530
1531 G_OBJECT_CLASS (ctk_header_bar_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), (((GType) ((20) << (
2))))))))
->finalize (object);
1532}
1533
1534static void
1535ctk_header_bar_get_property (GObject *object,
1536 guint prop_id,
1537 GValue *value,
1538 GParamSpec *pspec)
1539{
1540 CtkHeaderBar *bar = CTK_HEADER_BAR (object)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_header_bar_get_type ()))))))
;
1541 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1542
1543 switch (prop_id)
1544 {
1545 case PROP_TITLE:
1546 g_value_set_string (value, priv->title);
1547 break;
1548
1549 case PROP_SUBTITLE:
1550 g_value_set_string (value, priv->subtitle);
1551 break;
1552
1553 case PROP_CUSTOM_TITLE:
1554 g_value_set_object (value, priv->custom_title);
1555 break;
1556
1557 case PROP_SPACING:
1558 g_value_set_int (value, priv->spacing);
1559 break;
1560
1561 case PROP_SHOW_CLOSE_BUTTON:
1562 g_value_set_boolean (value, ctk_header_bar_get_show_close_button (bar));
1563 break;
1564
1565 case PROP_HAS_SUBTITLE:
1566 g_value_set_boolean (value, ctk_header_bar_get_has_subtitle (bar));
1567 break;
1568
1569 case PROP_DECORATION_LAYOUT:
1570 g_value_set_string (value, ctk_header_bar_get_decoration_layout (bar));
1571 break;
1572
1573 case PROP_DECORATION_LAYOUT_SET:
1574 g_value_set_boolean (value, priv->decoration_layout_set);
1575 break;
1576
1577 default:
1578 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkheaderbar.c", 1578, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1579 break;
1580 }
1581}
1582
1583static void
1584ctk_header_bar_set_property (GObject *object,
1585 guint prop_id,
1586 const GValue *value,
1587 GParamSpec *pspec)
1588{
1589 CtkHeaderBar *bar = CTK_HEADER_BAR (object)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_header_bar_get_type ()))))))
;
1590 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1591
1592 switch (prop_id)
1593 {
1594 case PROP_TITLE:
1595 ctk_header_bar_set_title (bar, g_value_get_string (value));
1596 break;
1597
1598 case PROP_SUBTITLE:
1599 ctk_header_bar_set_subtitle (bar, g_value_get_string (value));
1600 break;
1601
1602 case PROP_CUSTOM_TITLE:
1603 ctk_header_bar_set_custom_title (bar, g_value_get_object (value));
1604 break;
1605
1606 case PROP_SPACING:
1607 if (priv->spacing != g_value_get_int (value))
1608 {
1609 priv->spacing = g_value_get_int (value);
1610 ctk_widget_queue_resize (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1611 g_object_notify_by_pspec (object, pspec);
1612 }
1613 break;
1614
1615 case PROP_SHOW_CLOSE_BUTTON:
1616 ctk_header_bar_set_show_close_button (bar, g_value_get_boolean (value));
1617 break;
1618
1619 case PROP_HAS_SUBTITLE:
1620 ctk_header_bar_set_has_subtitle (bar, g_value_get_boolean (value));
1621 break;
1622
1623 case PROP_DECORATION_LAYOUT:
1624 ctk_header_bar_set_decoration_layout (bar, g_value_get_string (value));
1625 break;
1626
1627 case PROP_DECORATION_LAYOUT_SET:
1628 priv->decoration_layout_set = g_value_get_boolean (value);
1629 break;
1630
1631 default:
1632 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkheaderbar.c", 1632, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1633 break;
1634 }
1635}
1636
1637static void
1638notify_child_cb (GObject *child G_GNUC_UNUSED__attribute__ ((__unused__)),
1639 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
1640 CtkHeaderBar *bar)
1641{
1642 _ctk_header_bar_update_separator_visibility (bar);
1643}
1644
1645static void
1646ctk_header_bar_pack (CtkHeaderBar *bar,
1647 CtkWidget *widget,
1648 CtkPackType pack_type)
1649{
1650 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1651 Child *child;
1652
1653 g_return_if_fail (ctk_widget_get_parent (widget) == NULL)do { if ((ctk_widget_get_parent (widget) == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "ctk_widget_get_parent (widget) == NULL"); return; } } while
(0)
;
1654
1655 child = g_new (Child, 1)((Child *) g_malloc_n ((1), sizeof (Child)));
1656 child->widget = widget;
1657 child->pack_type = pack_type;
1658
1659 priv->children = g_list_append (priv->children, child);
1660
1661 ctk_widget_freeze_child_notify (widget);
1662 ctk_header_bar_reorder_css_node (bar, CTK_PACK_START, widget);
1663 ctk_widget_set_parent (widget, CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
1664 g_signal_connect (widget, "notify::visible", G_CALLBACK (notify_child_cb), bar)g_signal_connect_data ((widget), ("notify::visible"), (((GCallback
) (notify_child_cb))), (bar), ((void*)0), (GConnectFlags) 0)
;
1665 ctk_widget_child_notify (widget, "pack-type");
1666 ctk_widget_child_notify (widget, "position");
1667 ctk_widget_thaw_child_notify (widget);
1668
1669 _ctk_header_bar_update_separator_visibility (bar);
1670}
1671
1672static void
1673ctk_header_bar_add (CtkContainer *container,
1674 CtkWidget *child)
1675{
1676 ctk_header_bar_pack (CTK_HEADER_BAR (container)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_header_bar_get_type ()))))))
, child, CTK_PACK_START);
1677}
1678
1679static GList *
1680find_child_link (CtkHeaderBar *bar,
1681 CtkWidget *widget,
1682 gint *position)
1683{
1684 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1685 GList *l;
1686 Child *child;
1687 gint i;
1688
1689 for (l = priv->children, i = 0; l; l = l->next, i++)
1690 {
1691 child = l->data;
1692 if (child->widget == widget)
1693 {
1694 if (position)
1695 *position = i;
1696 return l;
1697 }
1698 }
1699
1700 return NULL((void*)0);
1701}
1702
1703static void
1704ctk_header_bar_remove (CtkContainer *container,
1705 CtkWidget *widget)
1706{
1707 CtkHeaderBar *bar = CTK_HEADER_BAR (container)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_header_bar_get_type ()))))))
;
1708 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1709 GList *l;
1710 Child *child;
1711
1712 l = find_child_link (bar, widget, NULL((void*)0));
1713 if (l)
1714 {
1715 child = l->data;
1716 g_signal_handlers_disconnect_by_func (widget, notify_child_cb, bar)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (notify_child_cb), (bar))
;
1717 ctk_widget_unparent (child->widget);
1718 priv->children = g_list_delete_link (priv->children, l);
1719 g_free (child);
1720 ctk_widget_queue_resize (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
1721 _ctk_header_bar_update_separator_visibility (bar);
1722 }
1723}
1724
1725static void
1726ctk_header_bar_forall (CtkContainer *container,
1727 gboolean include_internals,
1728 CtkCallback callback,
1729 gpointer callback_data)
1730{
1731 CtkHeaderBar *bar = CTK_HEADER_BAR (container)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_header_bar_get_type ()))))))
;
1732 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1733 Child *child;
1734 GList *children;
1735
1736 if (include_internals && priv->titlebar_start_box != NULL((void*)0))
1737 (* callback) (priv->titlebar_start_box, callback_data);
1738
1739 children = priv->children;
1740 while (children)
1741 {
1742 child = children->data;
1743 children = children->next;
1744 if (child->pack_type == CTK_PACK_START)
1745 (* callback) (child->widget, callback_data);
1746 }
1747
1748 if (priv->custom_title != NULL((void*)0))
1749 (* callback) (priv->custom_title, callback_data);
1750
1751 if (include_internals && priv->label_box != NULL((void*)0))
1752 (* callback) (priv->label_box, callback_data);
1753
1754 children = priv->children;
1755 while (children)
1756 {
1757 child = children->data;
1758 children = children->next;
1759 if (child->pack_type == CTK_PACK_END)
1760 (* callback) (child->widget, callback_data);
1761 }
1762
1763 if (include_internals && priv->titlebar_end_box != NULL((void*)0))
1764 (* callback) (priv->titlebar_end_box, callback_data);
1765}
1766
1767static void
1768ctk_header_bar_reorder_child (CtkHeaderBar *bar,
1769 CtkWidget *widget,
1770 gint position)
1771{
1772 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1773 GList *l;
1774 gint old_position;
1775 Child *child;
1776
1777 l = find_child_link (bar, widget, &old_position);
1778
1779 if (l == NULL((void*)0))
1780 return;
1781
1782 if (old_position == position)
1783 return;
1784
1785 child = l->data;
1786 priv->children = g_list_delete_link (priv->children, l);
1787
1788 if (position < 0)
1789 l = NULL((void*)0);
1790 else
1791 l = g_list_nth (priv->children, position);
1792
1793 priv->children = g_list_insert_before (priv->children, l, child);
1794 ctk_header_bar_reorder_css_node (bar, child->pack_type, widget);
1795 ctk_widget_child_notify (widget, "position");
1796 ctk_widget_queue_resize (widget);
1797}
1798
1799static GType
1800ctk_header_bar_child_type (CtkContainer *container G_GNUC_UNUSED__attribute__ ((__unused__)))
1801{
1802 return CTK_TYPE_WIDGET(ctk_widget_get_type ());
1803}
1804
1805static void
1806ctk_header_bar_get_child_property (CtkContainer *container,
1807 CtkWidget *widget,
1808 guint property_id,
1809 GValue *value,
1810 GParamSpec *pspec)
1811{
1812 CtkHeaderBar *bar = CTK_HEADER_BAR (container)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_header_bar_get_type ()))))))
;
1813 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (bar);
1814 GList *l;
1815 Child *child;
1816
1817 l = find_child_link (bar, widget, NULL((void*)0));
1818 if (l == NULL((void*)0))
1819 {
1820 g_param_value_set_default (pspec, value);
1821 return;
1822 }
1823
1824 child = l->data;
1825
1826 switch (property_id)
1827 {
1828 case CHILD_PROP_PACK_TYPE:
1829 g_value_set_enum (value, child->pack_type);
1830 break;
1831
1832 case CHILD_PROP_POSITION:
1833 g_value_set_int (value, g_list_position (priv->children, l));
1834 break;
1835
1836 default:
1837 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkheaderbar.c", 1837, ("child property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1838 break;
1839 }
1840}
1841
1842static void
1843ctk_header_bar_set_child_property (CtkContainer *container,
1844 CtkWidget *widget,
1845 guint property_id,
1846 const GValue *value,
1847 GParamSpec *pspec)
1848{
1849 CtkHeaderBar *bar = CTK_HEADER_BAR (container)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_header_bar_get_type ()))))))
;
1850 GList *l;
1851 Child *child;
1852
1853 l = find_child_link (bar, widget, NULL((void*)0));
1854 if (l == NULL((void*)0))
1855 return;
1856
1857 child = l->data;
1858
1859 switch (property_id)
1860 {
1861 case CHILD_PROP_PACK_TYPE:
1862 child->pack_type = g_value_get_enum (value);
1863 _ctk_header_bar_update_separator_visibility (bar);
1864 ctk_widget_queue_resize (widget);
1865 break;
1866
1867 case CHILD_PROP_POSITION:
1868 ctk_header_bar_reorder_child (bar, widget, g_value_get_int (value));
1869 break;
1870
1871 default:
1872 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkheaderbar.c", 1872, ("child property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1873 break;
1874 }
1875}
1876
1877static gint
1878ctk_header_bar_draw (CtkWidget *widget,
1879 cairo_t *cr)
1880{
1881 CtkHeaderBarPrivate *priv = ctk_header_bar_get_instance_private (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
1882
1883 ctk_css_gadget_draw (priv->gadget, cr);
1884
1885 return FALSE(0);
1886}
1887
1888static gboolean
1889ctk_header_bar_render_contents (CtkCssGadget *gadget,
1890 cairo_t *cr,
1891 int x G_GNUC_UNUSED__attribute__ ((__unused__)),
1892 int y G_GNUC_UNUSED__attribute__ ((__unused__)),
1893 int width G_GNUC_UNUSED__attribute__ ((__unused__)),
1894 int height G_GNUC_UNUSED__attribute__ ((__unused__)),
1895 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
1896{
1897 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
1898
1899 CTK_WIDGET_CLASS (ctk_header_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), ((ctk_widget_get_type ())
)))))
->draw (widget, cr);
1900
1901 return FALSE(0);
1902}
1903
1904static void
1905ctk_header_bar_realize (CtkWidget *widget)
1906{
1907 CtkSettings *settings;
1908
1909 CTK_WIDGET_CLASS (ctk_header_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), ((ctk_widget_get_type ())
)))))
->realize (widget);
1910
1911 settings = ctk_widget_get_settings (widget);
1912 g_signal_connect_swapped (settings, "notify::ctk-shell-shows-app-menu",g_signal_connect_data ((settings), ("notify::ctk-shell-shows-app-menu"
), (((GCallback) (_ctk_header_bar_update_window_buttons))), (
widget), ((void*)0), G_CONNECT_SWAPPED)
1913 G_CALLBACK (_ctk_header_bar_update_window_buttons), widget)g_signal_connect_data ((settings), ("notify::ctk-shell-shows-app-menu"
), (((GCallback) (_ctk_header_bar_update_window_buttons))), (
widget), ((void*)0), G_CONNECT_SWAPPED)
;
1914 g_signal_connect_swapped (settings, "notify::ctk-decoration-layout",g_signal_connect_data ((settings), ("notify::ctk-decoration-layout"
), (((GCallback) (_ctk_header_bar_update_window_buttons))), (
widget), ((void*)0), G_CONNECT_SWAPPED)
1915 G_CALLBACK (_ctk_header_bar_update_window_buttons), widget)g_signal_connect_data ((settings), ("notify::ctk-decoration-layout"
), (((GCallback) (_ctk_header_bar_update_window_buttons))), (
widget), ((void*)0), G_CONNECT_SWAPPED)
;
1916 _ctk_header_bar_update_window_buttons (CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
);
1917}
1918
1919static void
1920ctk_header_bar_unrealize (CtkWidget *widget)
1921{
1922 CtkSettings *settings;
1923
1924 settings = ctk_widget_get_settings (widget);
1925
1926 g_signal_handlers_disconnect_by_func (settings, _ctk_header_bar_update_window_buttons, widget)g_signal_handlers_disconnect_matched ((settings), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (_ctk_header_bar_update_window_buttons), (widget))
;
1927
1928 CTK_WIDGET_CLASS (ctk_header_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), ((ctk_widget_get_type ())
)))))
->unrealize (widget);
1929}
1930
1931static gboolean
1932window_state_changed (CtkWidget *window G_GNUC_UNUSED__attribute__ ((__unused__)),
1933 CdkEventWindowState *event,
1934 gpointer data)
1935{
1936 CtkHeaderBar *bar = CTK_HEADER_BAR (data)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_header_bar_get_type ()))))))
;
1937
1938 if (event->changed_mask & (CDK_WINDOW_STATE_FULLSCREEN |
1939 CDK_WINDOW_STATE_MAXIMIZED |
1940 CDK_WINDOW_STATE_TILED |
1941 CDK_WINDOW_STATE_TOP_TILED |
1942 CDK_WINDOW_STATE_RIGHT_TILED |
1943 CDK_WINDOW_STATE_BOTTOM_TILED |
1944 CDK_WINDOW_STATE_LEFT_TILED))
1945 _ctk_header_bar_update_window_buttons (bar);
1946
1947 return FALSE(0);
1948}
1949
1950static void
1951ctk_header_bar_hierarchy_changed (CtkWidget *widget,
1952 CtkWidget *previous_toplevel)
1953{
1954 CtkWidget *toplevel;
1955 CtkHeaderBar *bar = CTK_HEADER_BAR (widget)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_header_bar_get_type ()))))))
;
1956
1957 toplevel = ctk_widget_get_toplevel (widget);
1958
1959 if (previous_toplevel)
1960 g_signal_handlers_disconnect_by_func (previous_toplevel,g_signal_handlers_disconnect_matched ((previous_toplevel), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (window_state_changed), (widget))
1961 window_state_changed, widget)g_signal_handlers_disconnect_matched ((previous_toplevel), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (window_state_changed), (widget))
;
1962
1963 if (toplevel)
1964 g_signal_connect_after (toplevel, "window-state-event",g_signal_connect_data ((toplevel), ("window-state-event"), ((
(GCallback) (window_state_changed))), (widget), ((void*)0), G_CONNECT_AFTER
)
1965 G_CALLBACK (window_state_changed), widget)g_signal_connect_data ((toplevel), ("window-state-event"), ((
(GCallback) (window_state_changed))), (widget), ((void*)0), G_CONNECT_AFTER
)
;
1966
1967 _ctk_header_bar_update_window_buttons (bar);
1968}
1969
1970static void
1971ctk_header_bar_direction_changed (CtkWidget *widget,
1972 CtkTextDirection previous_direction)
1973{
1974 CTK_WIDGET_CLASS (ctk_header_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_header_bar_parent_class)), ((ctk_widget_get_type ())
)))))
->direction_changed (widget, previous_direction);
1975
1976 ctk_css_node_reverse_children (ctk_widget_get_css_node (widget));
1977}
1978
1979static void
1980ctk_header_bar_class_init (CtkHeaderBarClass *class)
1981{
1982 GObjectClass *object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
1983 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
;
1984 CtkContainerClass *container_class = CTK_CONTAINER_CLASS (class)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_container_get_type ()))))))
;
1985
1986 object_class->finalize = ctk_header_bar_finalize;
1987 object_class->get_property = ctk_header_bar_get_property;
1988 object_class->set_property = ctk_header_bar_set_property;
1989
1990 widget_class->destroy = ctk_header_bar_destroy;
1991 widget_class->size_allocate = ctk_header_bar_size_allocate;
1992 widget_class->get_preferred_width = ctk_header_bar_get_preferred_width;
1993 widget_class->get_preferred_height = ctk_header_bar_get_preferred_height;
1994 widget_class->get_preferred_height_for_width = ctk_header_bar_get_preferred_height_for_width;
1995 widget_class->get_preferred_width_for_height = ctk_header_bar_get_preferred_width_for_height;
1996 widget_class->draw = ctk_header_bar_draw;
1997 widget_class->realize = ctk_header_bar_realize;
1998 widget_class->unrealize = ctk_header_bar_unrealize;
1999 widget_class->hierarchy_changed = ctk_header_bar_hierarchy_changed;
2000 widget_class->direction_changed = ctk_header_bar_direction_changed;
2001
2002 container_class->add = ctk_header_bar_add;
2003 container_class->remove = ctk_header_bar_remove;
2004 container_class->forall = ctk_header_bar_forall;
2005 container_class->child_type = ctk_header_bar_child_type;
2006 container_class->set_child_property = ctk_header_bar_set_child_property;
2007 container_class->get_child_property = ctk_header_bar_get_child_property;
2008 ctk_container_class_handle_border_width (container_class);
2009
2010 ctk_container_class_install_child_property (container_class,
2011 CHILD_PROP_PACK_TYPE,
2012 g_param_spec_enum ("pack-type",
2013 P_("Pack type")g_dgettext("ctk30" "-properties","Pack type"),
2014 P_("A CtkPackType indicating whether the child is packed with reference to the start or end of the parent")g_dgettext("ctk30" "-properties","A CtkPackType indicating whether the child is packed with reference to the start or end of the parent"
)
,
2015 CTK_TYPE_PACK_TYPE(ctk_pack_type_get_type ()), CTK_PACK_START,
2016 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
2017 ctk_container_class_install_child_property (container_class,
2018 CHILD_PROP_POSITION,
2019 g_param_spec_int ("position",
2020 P_("Position")g_dgettext("ctk30" "-properties","Position"),
2021 P_("The index of the child in the parent")g_dgettext("ctk30" "-properties","The index of the child in the parent"
)
,
2022 -1, G_MAXINT2147483647, 0,
2023 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
2024
2025 header_bar_props[PROP_TITLE] =
2026 g_param_spec_string ("title",
2027 P_("Title")g_dgettext("ctk30" "-properties","Title"),
2028 P_("The title to display")g_dgettext("ctk30" "-properties","The title to display"),
2029 NULL((void*)0),
2030 G_PARAM_READWRITE);
2031
2032 header_bar_props[PROP_SUBTITLE] =
2033 g_param_spec_string ("subtitle",
2034 P_("Subtitle")g_dgettext("ctk30" "-properties","Subtitle"),
2035 P_("The subtitle to display")g_dgettext("ctk30" "-properties","The subtitle to display"),
2036 NULL((void*)0),
2037 G_PARAM_READWRITE);
2038
2039 header_bar_props[PROP_CUSTOM_TITLE] =
2040 g_param_spec_object ("custom-title",
2041 P_("Custom Title")g_dgettext("ctk30" "-properties","Custom Title"),
2042 P_("Custom title widget to display")g_dgettext("ctk30" "-properties","Custom title widget to display"
)
,
2043 CTK_TYPE_WIDGET(ctk_widget_get_type ()),
2044 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
)
);
2045
2046 header_bar_props[PROP_SPACING] =
2047 g_param_spec_int ("spacing",
2048 P_("Spacing")g_dgettext("ctk30" "-properties","Spacing"),
2049 P_("The amount of space between children")g_dgettext("ctk30" "-properties","The amount of space between children"
)
,
2050 0, G_MAXINT2147483647,
2051 DEFAULT_SPACING6,
2052 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
2053
2054 /**
2055 * CtkHeaderBar:show-close-button:
2056 *
2057 * Whether to show window decorations.
2058 *
2059 * Which buttons are actually shown and where is determined
2060 * by the #CtkHeaderBar:decoration-layout property, and by
2061 * the state of the window (e.g. a close button will not be
2062 * shown if the window can't be closed).
2063 */
2064 header_bar_props[PROP_SHOW_CLOSE_BUTTON] =
2065 g_param_spec_boolean ("show-close-button",
2066 P_("Show decorations")g_dgettext("ctk30" "-properties","Show decorations"),
2067 P_("Whether to show window decorations")g_dgettext("ctk30" "-properties","Whether to show window decorations"
)
,
2068 FALSE(0),
2069 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
2070
2071 /**
2072 * CtkHeaderBar:decoration-layout:
2073 *
2074 * The decoration layout for buttons. If this property is
2075 * not set, the #CtkSettings:ctk-decoration-layout setting
2076 * is used.
2077 *
2078 * See ctk_header_bar_set_decoration_layout() for information
2079 * about the format of this string.
2080 *
2081 * Since: 3.12
2082 */
2083 header_bar_props[PROP_DECORATION_LAYOUT] =
2084 g_param_spec_string ("decoration-layout",
2085 P_("Decoration Layout")g_dgettext("ctk30" "-properties","Decoration Layout"),
2086 P_("The layout for window decorations")g_dgettext("ctk30" "-properties","The layout for window decorations"
)
,
2087 NULL((void*)0),
2088 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
2089
2090 /**
2091 * CtkHeaderBar:decoration-layout-set:
2092 *
2093 * Set to %TRUE if #CtkHeaderBar:decoration-layout is set.
2094 *
2095 * Since: 3.12
2096 */
2097 header_bar_props[PROP_DECORATION_LAYOUT_SET] =
2098 g_param_spec_boolean ("decoration-layout-set",
2099 P_("Decoration Layout Set")g_dgettext("ctk30" "-properties","Decoration Layout Set"),
2100 P_("Whether the decoration-layout property has been set")g_dgettext("ctk30" "-properties","Whether the decoration-layout property has been set"
)
,
2101 FALSE(0),
2102 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
2103
2104 /**
2105 * CtkHeaderBar:has-subtitle:
2106 *
2107 * If %TRUE, reserve space for a subtitle, even if none
2108 * is currently set.
2109 *
2110 * Since: 3.12
2111 */
2112 header_bar_props[PROP_HAS_SUBTITLE] =
2113 g_param_spec_boolean ("has-subtitle",
2114 P_("Has Subtitle")g_dgettext("ctk30" "-properties","Has Subtitle"),
2115 P_("Whether to reserve space for a subtitle")g_dgettext("ctk30" "-properties","Whether to reserve space for a subtitle"
)
,
2116 TRUE(!(0)),
2117 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
2118
2119 g_object_class_install_properties (object_class, LAST_PROP, header_bar_props);
2120
2121 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_HEADER_BAR_ACCESSIBLE(ctk_header_bar_accessible_get_type ()));
2122 ctk_widget_class_set_accessible_role (widget_class, ATK_ROLE_PANEL);
2123 ctk_widget_class_set_css_name (widget_class, "headerbar");
2124}
2125
2126static void
2127ctk_header_bar_init (CtkHeaderBar *bar)
2128{
2129 CtkHeaderBarPrivate *priv;
2130 CtkCssNode *widget_node;
2131
2132 priv = ctk_header_bar_get_instance_private (bar);
2133
2134 ctk_widget_set_has_window (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
, FALSE(0));
2135
2136 priv->title = NULL((void*)0);
2137 priv->subtitle = NULL((void*)0);
2138 priv->custom_title = NULL((void*)0);
2139 priv->children = NULL((void*)0);
2140 priv->spacing = DEFAULT_SPACING6;
2141 priv->has_subtitle = TRUE(!(0));
2142 priv->decoration_layout = NULL((void*)0);
2143 priv->decoration_layout_set = FALSE(0);
2144
2145 init_sizing_box (bar);
2146 construct_label_box (bar);
2147
2148 widget_node = ctk_widget_get_css_node (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
2149 priv->gadget = ctk_css_custom_gadget_new_for_node (widget_node,
2150 CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
,
2151 ctk_header_bar_get_content_size,
2152 ctk_header_bar_allocate_contents,
2153 ctk_header_bar_render_contents,
2154 NULL((void*)0),
2155 NULL((void*)0));
2156
2157}
2158
2159static void
2160ctk_header_bar_buildable_add_child (CtkBuildable *buildable,
2161 CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)),
2162 GObject *child,
2163 const gchar *type)
2164{
2165 if (type && strcmp (type, "title") == 0)
2166 ctk_header_bar_set_custom_title (CTK_HEADER_BAR (buildable)((((CtkHeaderBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_header_bar_get_type ()))))))
, CTK_WIDGET (child)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_widget_get_type ()))))))
);
2167 else if (!type)
2168 ctk_container_add (CTK_CONTAINER (buildable)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_container_get_type ()))))))
, CTK_WIDGET (child)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_widget_get_type ()))))))
);
2169 else
2170 CTK_BUILDER_WARN_INVALID_CHILD_TYPE (CTK_HEADER_BAR (buildable), type)g_warning ("'%s' is not a valid child type of '%s'", type, g_type_name
((((((GTypeClass*) (((GTypeInstance*) (((((CtkHeaderBar*) (void
*) g_type_check_instance_cast ((GTypeInstance*) ((buildable)
), ((ctk_header_bar_get_type ()))))))))->g_class))->g_type
)))))
;
2171}
2172
2173static void
2174ctk_header_bar_buildable_init (CtkBuildableIface *iface)
2175{
2176 iface->add_child = ctk_header_bar_buildable_add_child;
2177}
2178
2179/**
2180 * ctk_header_bar_pack_start:
2181 * @bar: A #CtkHeaderBar
2182 * @child: the #CtkWidget to be added to @bar
2183 *
2184 * Adds @child to @bar, packed with reference to the
2185 * start of the @bar.
2186 *
2187 * Since: 3.10
2188 */
2189void
2190ctk_header_bar_pack_start (CtkHeaderBar *bar,
2191 CtkWidget *child)
2192{
2193 ctk_header_bar_pack (bar, child, CTK_PACK_START);
2194}
2195
2196/**
2197 * ctk_header_bar_pack_end:
2198 * @bar: A #CtkHeaderBar
2199 * @child: the #CtkWidget to be added to @bar
2200 *
2201 * Adds @child to @bar, packed with reference to the
2202 * end of the @bar.
2203 *
2204 * Since: 3.10
2205 */
2206void
2207ctk_header_bar_pack_end (CtkHeaderBar *bar,
2208 CtkWidget *child)
2209{
2210 ctk_header_bar_pack (bar, child, CTK_PACK_END);
2211}
2212
2213/**
2214 * ctk_header_bar_new:
2215 *
2216 * Creates a new #CtkHeaderBar widget.
2217 *
2218 * Returns: a new #CtkHeaderBar
2219 *
2220 * Since: 3.10
2221 */
2222CtkWidget *
2223ctk_header_bar_new (void)
2224{
2225 return CTK_WIDGET (g_object_new (CTK_TYPE_HEADER_BAR, NULL))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new ((ctk_header_bar_get_type ()), ((void*)0)))
), ((ctk_widget_get_type ()))))))
;
2226}
2227
2228/**
2229 * ctk_header_bar_get_show_close_button:
2230 * @bar: a #CtkHeaderBar
2231 *
2232 * Returns whether this header bar shows the standard window
2233 * decorations.
2234 *
2235 * Returns: %TRUE if the decorations are shown
2236 *
2237 * Since: 3.10
2238 */
2239gboolean
2240ctk_header_bar_get_show_close_button (CtkHeaderBar *bar)
2241{
2242 CtkHeaderBarPrivate *priv;
2243
2244 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return ((0)); } } while (0)
;
2245
2246 priv = ctk_header_bar_get_instance_private (bar);
2247
2248 return priv->shows_wm_decorations;
2249}
2250
2251/**
2252 * ctk_header_bar_set_show_close_button:
2253 * @bar: a #CtkHeaderBar
2254 * @setting: %TRUE to show standard window decorations
2255 *
2256 * Sets whether this header bar shows the standard window decorations,
2257 * including close, maximize, and minimize.
2258 *
2259 * Since: 3.10
2260 */
2261void
2262ctk_header_bar_set_show_close_button (CtkHeaderBar *bar,
2263 gboolean setting)
2264{
2265 CtkHeaderBarPrivate *priv;
2266
2267 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
2268
2269 priv = ctk_header_bar_get_instance_private (bar);
2270
2271 setting = setting != FALSE(0);
2272
2273 if (priv->shows_wm_decorations == setting)
2274 return;
2275
2276 priv->shows_wm_decorations = setting;
2277 _ctk_header_bar_update_window_buttons (bar);
2278 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_SHOW_CLOSE_BUTTON]);
2279}
2280
2281/**
2282 * ctk_header_bar_set_has_subtitle:
2283 * @bar: a #CtkHeaderBar
2284 * @setting: %TRUE to reserve space for a subtitle
2285 *
2286 * Sets whether the header bar should reserve space
2287 * for a subtitle, even if none is currently set.
2288 *
2289 * Since: 3.12
2290 */
2291void
2292ctk_header_bar_set_has_subtitle (CtkHeaderBar *bar,
2293 gboolean setting)
2294{
2295 CtkHeaderBarPrivate *priv;
2296
2297 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
2298
2299 priv = ctk_header_bar_get_instance_private (bar);
2300
2301 setting = setting != FALSE(0);
2302
2303 if (priv->has_subtitle == setting)
2304 return;
2305
2306 priv->has_subtitle = setting;
2307 ctk_widget_set_visible (priv->subtitle_sizing_label, setting || (priv->subtitle && priv->subtitle[0]));
2308
2309 ctk_widget_queue_resize (CTK_WIDGET (bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), ((ctk_widget_get_type ()))))))
);
2310
2311 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_HAS_SUBTITLE]);
2312}
2313
2314/**
2315 * ctk_header_bar_get_has_subtitle:
2316 * @bar: a #CtkHeaderBar
2317 *
2318 * Retrieves whether the header bar reserves space for
2319 * a subtitle, regardless if one is currently set or not.
2320 *
2321 * Returns: %TRUE if the header bar reserves space
2322 * for a subtitle
2323 *
2324 * Since: 3.12
2325 */
2326gboolean
2327ctk_header_bar_get_has_subtitle (CtkHeaderBar *bar)
2328{
2329 CtkHeaderBarPrivate *priv;
2330
2331 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return ((0)); } } while (0)
;
2332
2333 priv = ctk_header_bar_get_instance_private (bar);
2334
2335 return priv->has_subtitle;
2336}
2337
2338/**
2339 * ctk_header_bar_set_decoration_layout:
2340 * @bar: a #CtkHeaderBar
2341 * @layout: (allow-none): a decoration layout, or %NULL to
2342 * unset the layout
2343 *
2344 * Sets the decoration layout for this header bar, overriding
2345 * the #CtkSettings:ctk-decoration-layout setting.
2346 *
2347 * There can be valid reasons for overriding the setting, such
2348 * as a header bar design that does not allow for buttons to take
2349 * room on the right, or only offers room for a single close button.
2350 * Split header bars are another example for overriding the
2351 * setting.
2352 *
2353 * The format of the string is button names, separated by commas.
2354 * A colon separates the buttons that should appear on the left
2355 * from those on the right. Recognized button names are minimize,
2356 * maximize, close, icon (the window icon) and menu (a menu button
2357 * for the fallback app menu).
2358 *
2359 * For example, “menu:minimize,maximize,close” specifies a menu
2360 * on the left, and minimize, maximize and close buttons on the right.
2361 *
2362 * Since: 3.12
2363 */
2364void
2365ctk_header_bar_set_decoration_layout (CtkHeaderBar *bar,
2366 const gchar *layout)
2367{
2368 CtkHeaderBarPrivate *priv;
2369
2370 g_return_if_fail (CTK_IS_HEADER_BAR (bar))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return; } } while (0)
;
2371
2372 priv = ctk_header_bar_get_instance_private (bar);
2373
2374 g_free (priv->decoration_layout);
2375 priv->decoration_layout = g_strdup (layout)g_strdup_inline (layout);
2376 priv->decoration_layout_set = (layout != NULL((void*)0));
2377
2378 _ctk_header_bar_update_window_buttons (bar);
2379
2380 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_DECORATION_LAYOUT]);
2381 g_object_notify_by_pspec (G_OBJECT (bar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((bar)), (((GType) ((20) << (2))))))))
, header_bar_props[PROP_DECORATION_LAYOUT_SET]);
2382}
2383
2384/**
2385 * ctk_header_bar_get_decoration_layout:
2386 * @bar: a #CtkHeaderBar
2387 *
2388 * Gets the decoration layout set with
2389 * ctk_header_bar_set_decoration_layout().
2390 *
2391 * Returns: the decoration layout
2392 *
2393 * Since: 3.12
2394 */
2395const gchar *
2396ctk_header_bar_get_decoration_layout (CtkHeaderBar *bar)
2397{
2398 CtkHeaderBarPrivate *priv;
2399
2400 g_return_val_if_fail (CTK_IS_HEADER_BAR (bar), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((bar)); GType __t = ((ctk_header_bar_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_HEADER_BAR (bar)"); return (((void*)0)); } } while
(0)
;
2401
2402 priv = ctk_header_bar_get_instance_private (bar);
2403
2404 return priv->decoration_layout;
2405}