Bug Summary

File:ctk/ctkmenusectionbox.c
Warning:line 394, column 28
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

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 ctkmenusectionbox.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 -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -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-16/lib/clang/16/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 -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -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.core.SizeofPtr -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-09-19-171836-43636-1 -x c ctkmenusectionbox.c
1/*
2 * Copyright © 2014 Canonical Limited
3 * Copyright © 2013 Carlos Garnacho
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the licence, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Ryan Lortie <desrt@desrt.ca>
19 */
20
21#include "config.h"
22
23#include "ctkmenusectionbox.h"
24
25#include "ctkwidgetprivate.h"
26#include "ctklabel.h"
27#include "ctkmenutracker.h"
28#include "ctkmodelbutton.h"
29#include "ctkseparator.h"
30#include "ctksizegroup.h"
31#include "ctkstack.h"
32#include "ctkstylecontext.h"
33#include "ctkpopover.h"
34#include "ctkorientable.h"
35
36typedef CtkBoxClass CtkMenuSectionBoxClass;
37
38struct _CtkMenuSectionBox
39{
40 CtkBox parent_instance;
41
42 CtkMenuSectionBox *toplevel;
43 CtkMenuTracker *tracker;
44 CtkBox *item_box;
45 CtkWidget *separator;
46 guint separator_sync_idle;
47 gboolean iconic;
48 gint depth;
49};
50
51typedef struct
52{
53 gint n_items;
54 gboolean previous_is_iconic;
55} MenuData;
56
57G_DEFINE_TYPE (CtkMenuSectionBox, ctk_menu_section_box, CTK_TYPE_BOX)static void ctk_menu_section_box_init (CtkMenuSectionBox *self
); static void ctk_menu_section_box_class_init (CtkMenuSectionBoxClass
*klass); static GType ctk_menu_section_box_get_type_once (void
); static gpointer ctk_menu_section_box_parent_class = ((void
*)0); static gint CtkMenuSectionBox_private_offset; static void
ctk_menu_section_box_class_intern_init (gpointer klass) { ctk_menu_section_box_parent_class
= g_type_class_peek_parent (klass); if (CtkMenuSectionBox_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkMenuSectionBox_private_offset
); ctk_menu_section_box_class_init ((CtkMenuSectionBoxClass*)
klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_menu_section_box_get_instance_private (CtkMenuSectionBox
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkMenuSectionBox_private_offset
)))); } GType ctk_menu_section_box_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_menu_section_box_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_menu_section_box_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_box_get_type ()), g_intern_static_string ("CtkMenuSectionBox"
), sizeof (CtkMenuSectionBoxClass), (GClassInitFunc)(void (*)
(void)) ctk_menu_section_box_class_intern_init, sizeof (CtkMenuSectionBox
), (GInstanceInitFunc)(void (*)(void)) ctk_menu_section_box_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
58
59static void ctk_menu_section_box_sync_separators (CtkMenuSectionBox *box,
60 MenuData *data);
61static void ctk_menu_section_box_new_submenu (CtkMenuTrackerItem *item,
62 CtkMenuSectionBox *toplevel,
63 CtkWidget *focus,
64 const gchar *name);
65static CtkWidget * ctk_menu_section_box_new_section (CtkMenuTrackerItem *item,
66 CtkMenuSectionBox *parent);
67
68static void
69ctk_menu_section_box_sync_item (CtkWidget *widget,
70 gpointer user_data)
71{
72 MenuData *data = (MenuData *)user_data;
73
74 if (CTK_IS_MENU_SECTION_BOX (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_menu_section_box_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; }))))
)
75 ctk_menu_section_box_sync_separators (CTK_MENU_SECTION_BOX (widget)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), ((ctk_menu_section_box_get_type (
)))))))
, data);
76 else
77 data->n_items++;
78}
79
80/* We are trying to implement the following rules here:
81 *
82 * rule 1: never ever show separators for empty sections
83 * rule 2: always show a separator if there is a label
84 * rule 3: don't show a separator for the first section
85 * rule 4: don't show a separator for the following sections if there are
86 * no items before it
87 * rule 5: never show separators directly above or below an iconic box
88 * (rule 6: these rules don't apply exactly the same way for subsections)
89 */
90static void
91ctk_menu_section_box_sync_separators (CtkMenuSectionBox *box,
92 MenuData *data)
93{
94 gboolean previous_section_is_iconic;
95 gboolean should_have_separator;
96 gboolean should_have_top_margin = FALSE(0);
97 gboolean is_not_empty_item;
98 gboolean has_separator;
99 gboolean has_label;
100 gboolean separator_condition;
101 gint n_items_before;
102
103 n_items_before = data->n_items;
104 previous_section_is_iconic = data->previous_is_iconic;
105
106 ctk_container_foreach (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_container_get_type ()))))))
, ctk_menu_section_box_sync_item, data);
107
108 is_not_empty_item = (data->n_items > n_items_before);
109
110 if (is_not_empty_item)
111 data->previous_is_iconic = box->iconic;
112
113 if (box->separator == NULL((void*)0))
114 return;
115
116 has_separator = ctk_widget_get_parent (box->separator) != NULL((void*)0);
117 has_label = !CTK_IS_SEPARATOR (box->separator)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(box->separator)); GType __t = ((ctk_separator_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; }))))
;
118
119 separator_condition = has_label ? TRUE(!(0)) : n_items_before > 0 &&
120 box->depth <= 1 &&
121 !previous_section_is_iconic &&
122 !box->iconic;
123
124 should_have_separator = separator_condition && is_not_empty_item;
125
126 should_have_top_margin = !should_have_separator &&
127 (box->depth <= 1 || box->iconic) &&
128 n_items_before > 0 &&
129 is_not_empty_item;
130
131 ctk_widget_set_margin_top (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_widget_get_type ()))))))
, should_have_top_margin ? 10 : 0);
132
133 if (should_have_separator == has_separator)
134 return;
135
136 if (should_have_separator)
137 ctk_box_pack_start (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_box_get_type ()))))))
, box->separator, FALSE(0), FALSE(0), 0);
138 else
139 ctk_container_remove (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_container_get_type ()))))))
, box->separator);
140}
141
142static gboolean
143ctk_menu_section_box_handle_sync_separators (gpointer user_data)
144{
145 CtkMenuSectionBox *box = user_data;
146 MenuData data;
147
148 data.n_items = 0;
149 data.previous_is_iconic = FALSE(0);
150 ctk_menu_section_box_sync_separators (box, &data);
151
152 box->separator_sync_idle = 0;
153
154 return G_SOURCE_REMOVE(0);
155}
156
157static void
158ctk_menu_section_box_schedule_separator_sync (CtkMenuSectionBox *box)
159{
160 box = box->toplevel;
161
162 if (!box->separator_sync_idle)
163 box->separator_sync_idle = cdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE100, /* before resize... */
164 ctk_menu_section_box_handle_sync_separators,
165 box, NULL((void*)0));
166}
167
168static void
169ctk_popover_item_activate (CtkWidget *button,
170 gpointer user_data)
171{
172 CtkMenuTrackerItem *item = user_data;
173 CtkWidget *popover = NULL((void*)0);
174
175 if (ctk_menu_tracker_item_get_role (item) == CTK_MENU_TRACKER_ITEM_ROLE_NORMAL)
176 {
177 /* Activating the item could cause the popover
178 * to be free'd, for example if it is a Quit item
179 */
180 popover = g_object_ref (ctk_widget_get_ancestor (button,((__typeof__ (ctk_widget_get_ancestor (button, (ctk_popover_get_type
())))) (g_object_ref) (ctk_widget_get_ancestor (button, (ctk_popover_get_type
()))))
181 CTK_TYPE_POPOVER))((__typeof__ (ctk_widget_get_ancestor (button, (ctk_popover_get_type
())))) (g_object_ref) (ctk_widget_get_ancestor (button, (ctk_popover_get_type
()))))
;
182 }
183
184 ctk_menu_tracker_item_activated (item);
185
186 if (popover != NULL((void*)0))
187 {
188 ctk_widget_hide (popover);
189 g_object_unref (popover);
190 }
191}
192
193static void
194ctk_menu_section_box_remove_func (gint position,
195 gpointer user_data)
196{
197 CtkMenuSectionBox *box = user_data;
198 CtkMenuTrackerItem *item;
199 CtkWidget *widget;
200 GList *children;
201
202 children = ctk_container_get_children (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_container_get_type ()))))))
);
203
204 widget = g_list_nth_data (children, position);
205
206 item = g_object_get_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "CtkMenuTrackerItem");
207 if (ctk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU"submenu"))
208 {
209 CtkWidget *stack, *subbox;
210
211 stack = ctk_widget_get_ancestor (CTK_WIDGET (box->toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->toplevel)), ((ctk_widget_get_type ()))))))
, CTK_TYPE_STACK(ctk_stack_get_type ()));
212 subbox = ctk_stack_get_child_by_name (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, ctk_menu_tracker_item_get_label (item));
213 if (subbox != NULL((void*)0))
214 ctk_container_remove (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
, subbox);
215 }
216
217 ctk_widget_destroy (g_list_nth_data (children, position));
218 g_list_free (children);
219
220 ctk_menu_section_box_schedule_separator_sync (box);
221}
222
223static gboolean
224get_ancestors (CtkWidget *widget,
225 GType widget_type,
226 CtkWidget **ancestor,
227 CtkWidget **below)
228{
229 CtkWidget *a, *b;
230
231 a = NULL((void*)0);
232 b = widget;
233 while (b != NULL((void*)0))
234 {
235 a = ctk_widget_get_parent (b);
236 if (!a)
237 return FALSE(0);
238 if (g_type_is_a (G_OBJECT_TYPE (a), widget_type)(((((((GTypeClass*) (((GTypeInstance*) (a))->g_class))->
g_type)))) == (widget_type) || (g_type_is_a) (((((((GTypeClass
*) (((GTypeInstance*) (a))->g_class))->g_type)))), (widget_type
)))
)
239 break;
240 b = a;
241 }
242
243 *below = b;
244 *ancestor = a;
245
246 return TRUE(!(0));
247}
248
249static void
250close_submenu (CtkWidget *button,
251 gpointer data)
252{
253 CtkMenuTrackerItem *item = data;
254 CtkWidget *focus;
255
256 if (ctk_menu_tracker_item_get_should_request_show (item))
257 ctk_menu_tracker_item_request_submenu_shown (item, FALSE(0));
258
259 focus = CTK_WIDGET (g_object_get_data (G_OBJECT (button), "focus"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "focus"))), ((ctk_widget_get_type ()))))))
;
260 ctk_widget_grab_focus (focus);
261}
262
263static void
264open_submenu (CtkWidget *button,
265 gpointer data)
266{
267 CtkMenuTrackerItem *item = data;
268 CtkWidget *focus;
269
270 if (ctk_menu_tracker_item_get_should_request_show (item))
271 ctk_menu_tracker_item_request_submenu_shown (item, TRUE(!(0)));
272
273 focus = CTK_WIDGET (g_object_get_data (G_OBJECT (button), "focus"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "focus"))), ((ctk_widget_get_type ()))))))
;
274 ctk_widget_grab_focus (focus);
275}
276
277static void
278ctk_menu_section_box_insert_func (CtkMenuTrackerItem *item,
279 gint position,
280 gpointer user_data)
281{
282 CtkMenuSectionBox *box = user_data;
283 CtkWidget *widget;
284
285 if (ctk_menu_tracker_item_get_is_separator (item))
286 {
287 widget = ctk_menu_section_box_new_section (item, box);
288 }
289 else if (ctk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU"submenu"))
290 {
291 CtkWidget *stack = NULL((void*)0);
292 CtkWidget *parent = NULL((void*)0);
293 gchar *name;
294
295 widget = g_object_new (CTK_TYPE_MODEL_BUTTON(ctk_model_button_get_type ()),
296 "menu-name", ctk_menu_tracker_item_get_label (item),
297 NULL((void*)0));
298 g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
299 g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
300 g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE);
301
302 get_ancestors (CTK_WIDGET (box->toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->toplevel)), ((ctk_widget_get_type ()))))))
, CTK_TYPE_STACK(ctk_stack_get_type ()), &stack, &parent);
303 ctk_container_child_get (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
, parent, "name", &name, NULL((void*)0));
304 ctk_menu_section_box_new_submenu (item, box->toplevel, widget, name);
305 g_free (name);
306 }
307 else
308 {
309 widget = ctk_model_button_new ();
310 g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
311
312 if (box->iconic)
313 {
314 g_object_bind_property (item, "verb-icon", widget, "icon", G_BINDING_SYNC_CREATE);
315 g_object_set (widget, "iconic", TRUE(!(0)), "centered", TRUE(!(0)), NULL((void*)0));
316 }
317 else
318 g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
319
320 g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE);
321 g_object_bind_property (item, "role", widget, "role", G_BINDING_SYNC_CREATE);
322 g_object_bind_property (item, "toggled", widget, "active", G_BINDING_SYNC_CREATE);
323 g_signal_connect (widget, "clicked", G_CALLBACK (ctk_popover_item_activate), item)g_signal_connect_data ((widget), ("clicked"), (((GCallback) (
ctk_popover_item_activate))), (item), ((void*)0), (GConnectFlags
) 0)
;
324 }
325
326 ctk_widget_show (widget);
327
328 g_object_set_data_full (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "CtkMenuTrackerItem", g_object_ref (item)((__typeof__ (item)) (g_object_ref) (item)), g_object_unref);
329
330 ctk_widget_set_halign (widget, CTK_ALIGN_FILL);
331 if (box->iconic)
332 ctk_box_pack_start (CTK_BOX (box->item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_box_get_type ()))))))
, widget, TRUE(!(0)), TRUE(!(0)), 0);
333 else
334 ctk_container_add (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_container_get_type ()))))))
, widget);
335 ctk_box_reorder_child (CTK_BOX (box->item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_box_get_type ()))))))
, widget, position);
336
337 ctk_menu_section_box_schedule_separator_sync (box);
338}
339
340static void
341ctk_menu_section_box_init (CtkMenuSectionBox *box)
342{
343 CtkWidget *item_box;
344
345 ctk_orientable_set_orientation (CTK_ORIENTABLE (box)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_orientable_get_type ()))))))
, CTK_ORIENTATION_VERTICAL);
346
347 box->toplevel = box;
348
349 item_box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
350 box->item_box = CTK_BOX (item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((item_box)), ((ctk_box_get_type ()))))))
;
351 ctk_box_pack_end (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_box_get_type ()))))))
, item_box, FALSE(0), FALSE(0), 0);
352 ctk_widget_set_halign (CTK_WIDGET (item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((item_box)), ((ctk_widget_get_type ()))))))
, CTK_ALIGN_FILL);
353 ctk_widget_show (item_box);
354
355 ctk_widget_set_halign (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
, CTK_ALIGN_FILL);
356 g_object_set (box, "margin", 0, NULL((void*)0));
357
358}
359
360static void
361ctk_menu_section_box_dispose (GObject *object)
362{
363 CtkMenuSectionBox *box = CTK_MENU_SECTION_BOX (object)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((ctk_menu_section_box_get_type (
)))))))
;
364
365 if (box->separator_sync_idle)
366 {
367 g_source_remove (box->separator_sync_idle);
368 box->separator_sync_idle = 0;
369 }
370
371 g_clear_object (&box->separator)do { _Static_assert (sizeof *((&box->separator)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&box->separator))) _pp = ((&box->separator)); __typeof__
(*((&box->separator))) _ptr = *_pp; *_pp = ((void*)0)
; if (_ptr) (g_object_unref) (_ptr); } while (0)
;
372
373 if (box->tracker)
374 {
375 ctk_menu_tracker_free (box->tracker);
376 box->tracker = NULL((void*)0);
377 }
378
379 G_OBJECT_CLASS (ctk_menu_section_box_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_menu_section_box_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
380}
381
382static void
383ctk_menu_section_box_class_init (CtkMenuSectionBoxClass *class)
384{
385 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->dispose = ctk_menu_section_box_dispose;
386}
387
388static void
389update_popover_position_cb (GObject *source,
390 GParamSpec *spec G_GNUC_UNUSED__attribute__ ((__unused__)),
391 gpointer *user_data)
392{
393 CtkPopover *popover = CTK_POPOVER (source)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source)), ((ctk_popover_get_type ()))))))
;
394 CtkMenuSectionBox *box = CTK_MENU_SECTION_BOX (user_data)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((user_data)), ((ctk_menu_section_box_get_type
()))))))
;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
395
396 CtkPositionType new_pos = ctk_popover_get_position (popover);
397
398 GList *children = ctk_container_get_children (CTK_CONTAINER (ctk_widget_get_parent (CTK_WIDGET (box)))((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_parent (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((box)), ((ctk_widget_get_type ())))))))))
, ((ctk_container_get_type ()))))))
);
399 GList *l;
400
401 for (l = children;
402 l != NULL((void*)0);
403 l = l->next)
404 {
405 CtkWidget *w = l->data;
406
407 if (new_pos == CTK_POS_BOTTOM)
408 ctk_widget_set_valign (w, CTK_ALIGN_START);
409 else if (new_pos == CTK_POS_TOP)
410 ctk_widget_set_valign (w, CTK_ALIGN_END);
411 else
412 ctk_widget_set_valign (w, CTK_ALIGN_CENTER);
413 }
414
415 g_list_free (children);
416}
417
418void
419ctk_menu_section_box_new_toplevel (CtkStack *stack,
420 GMenuModel *model,
421 const gchar *action_namespace,
422 CtkPopover *popover)
423{
424 CtkMenuSectionBox *box;
425
426 box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), "margin", 10, NULL((void*)0));
427 ctk_stack_add_named (stack, CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
, "main");
428
429 box->tracker = ctk_menu_tracker_new (CTK_ACTION_OBSERVABLE (_ctk_widget_get_action_muxer (CTK_WIDGET (box), TRUE))((((CtkActionObservable*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((_ctk_widget_get_action_muxer (((((CtkWidget
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((box
)), ((ctk_widget_get_type ())))))), (!(0))))), ((ctk_action_observable_get_type
()))))))
,
430 model, TRUE(!(0)), FALSE(0), FALSE(0), action_namespace,
431 ctk_menu_section_box_insert_func,
432 ctk_menu_section_box_remove_func, box);
433
434 g_signal_connect (G_OBJECT (popover), "notify::position", G_CALLBACK (update_popover_position_cb), box)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((popover)), (((GType) ((20) << (2))
))))))), ("notify::position"), (((GCallback) (update_popover_position_cb
))), (box), ((void*)0), (GConnectFlags) 0)
;
435
436
437 ctk_widget_show (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
);
438}
439
440static void
441ctk_menu_section_box_new_submenu (CtkMenuTrackerItem *item,
442 CtkMenuSectionBox *toplevel,
443 CtkWidget *focus,
444 const gchar *name)
445{
446 CtkMenuSectionBox *box;
447 CtkWidget *button;
448
449 box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), "margin", 10, NULL((void*)0));
450
451 button = g_object_new (CTK_TYPE_MODEL_BUTTON(ctk_model_button_get_type ()),
452 "menu-name", name,
453 "inverted", TRUE(!(0)),
454 "centered", TRUE(!(0)),
455 NULL((void*)0));
456
457 g_object_bind_property (item, "label", button, "text", G_BINDING_SYNC_CREATE);
458 g_object_bind_property (item, "icon", button, "icon", G_BINDING_SYNC_CREATE);
459
460 g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "focus", focus);
461 g_object_set_data (G_OBJECT (focus)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((focus)), (((GType) ((20) << (2))))))))
, "focus", 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 ctk_widget_show (button);
465
466 g_signal_connect (focus, "clicked", G_CALLBACK (open_submenu), item)g_signal_connect_data ((focus), ("clicked"), (((GCallback) (open_submenu
))), (item), ((void*)0), (GConnectFlags) 0)
;
467 g_signal_connect (button, "clicked", G_CALLBACK (close_submenu), item)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
close_submenu))), (item), ((void*)0), (GConnectFlags) 0)
;
468
469 ctk_stack_add_named (CTK_STACK (ctk_widget_get_ancestor (CTK_WIDGET (toplevel), CTK_TYPE_STACK))((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_ancestor (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((toplevel)), ((ctk_widget_get_type ()))))
)), (ctk_stack_get_type ())))), ((ctk_stack_get_type ()))))))
,
470 CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
, ctk_menu_tracker_item_get_label (item));
471 ctk_widget_show (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
);
472
473 box->tracker = ctk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SUBMENU"submenu", FALSE(0), FALSE(0),
474 ctk_menu_section_box_insert_func,
475 ctk_menu_section_box_remove_func,
476 box);
477}
478
479static CtkWidget *
480ctk_menu_section_box_new_section (CtkMenuTrackerItem *item,
481 CtkMenuSectionBox *parent)
482{
483 CtkMenuSectionBox *box;
484 const gchar *label;
485 const gchar *hint;
486 const gchar *text_direction;
487
488 box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), NULL((void*)0));
489 box->toplevel = parent->toplevel;
490 box->depth = parent->depth + 1;
491
492 label = ctk_menu_tracker_item_get_label (item);
493 hint = ctk_menu_tracker_item_get_display_hint (item);
494 text_direction = ctk_menu_tracker_item_get_text_direction (item);
495
496 if (hint && g_str_equal (hint, "horizontal-buttons")(strcmp ((const char *) (hint), (const char *) ("horizontal-buttons"
)) == 0)
)
497 {
498 ctk_orientable_set_orientation (CTK_ORIENTABLE (box->item_box)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_orientable_get_type ()))))))
, CTK_ORIENTATION_HORIZONTAL);
499 ctk_style_context_add_class (ctk_widget_get_style_context (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_widget_get_type ()))))))
), CTK_STYLE_CLASS_LINKED"linked");
500 box->iconic = TRUE(!(0));
501
502 if (text_direction)
503 {
504 CtkTextDirection dir = CTK_TEXT_DIR_NONE;
505
506 if (g_str_equal (text_direction, "rtl")(strcmp ((const char *) (text_direction), (const char *) ("rtl"
)) == 0)
)
507 dir = CTK_TEXT_DIR_RTL;
508 else if (g_str_equal (text_direction, "ltr")(strcmp ((const char *) (text_direction), (const char *) ("ltr"
)) == 0)
)
509 dir = CTK_TEXT_DIR_LTR;
510
511 ctk_widget_set_direction (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->item_box)), ((ctk_widget_get_type ()))))))
, dir);
512 }
513 }
514
515 if (label != NULL((void*)0))
516 {
517 CtkWidget *separator;
518 CtkWidget *title;
519
520 box->separator = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 4);
521 g_object_ref_sink (box->separator)((__typeof__ (box->separator)) (g_object_ref_sink) (box->
separator))
;
522
523 separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL);
524 ctk_widget_set_valign (separator, CTK_ALIGN_CENTER);
525 ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->separator)), ((ctk_box_get_type ()))))))
, separator, TRUE(!(0)), TRUE(!(0)), 0);
526
527 title = ctk_label_new (label);
528 g_object_bind_property (item, "label", title, "label", G_BINDING_SYNC_CREATE);
529 ctk_style_context_add_class (ctk_widget_get_style_context (title), CTK_STYLE_CLASS_SEPARATOR"separator");
530 ctk_widget_set_halign (title, CTK_ALIGN_START);
531 ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->separator)), ((ctk_box_get_type ()))))))
, title, FALSE(0), FALSE(0), 0);
532
533 separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL);
534 ctk_widget_set_valign (separator, CTK_ALIGN_CENTER);
535 ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box->separator)), ((ctk_box_get_type ()))))))
, separator, TRUE(!(0)), TRUE(!(0)), 0);
536
537 ctk_widget_show_all (box->separator);
538 }
539 else
540 {
541 box->separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL);
542 g_object_ref_sink (box->separator)((__typeof__ (box->separator)) (g_object_ref_sink) (box->
separator))
;
543
544 ctk_widget_show (box->separator);
545 }
546
547 box->tracker = ctk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SECTION"section", FALSE(0), FALSE(0),
548 ctk_menu_section_box_insert_func,
549 ctk_menu_section_box_remove_func,
550 box);
551
552 return CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_widget_get_type ()))))))
;
553}