Bug Summary

File:ctk/ctkcontainer.c
Warning:line 972, column 27
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 ctkcontainer.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-172619-43637-1 -x c ctkcontainer.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the CTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * CTK+ at ftp://ftp.ctk.org/pub/ctk/.
23 */
24
25#include "config.h"
26
27#define CDK_DISABLE_DEPRECATION_WARNINGS
28#include "ctkcontainer.h"
29#include "ctkcontainerprivate.h"
30
31#include <stdarg.h>
32#include <string.h>
33#include <stdlib.h>
34
35#include <gobject/gobjectnotifyqueue.c>
36#include <gobject/gvaluecollector.h>
37
38#include "ctkadjustment.h"
39#include "ctkbuildable.h"
40#include "ctkbuilderprivate.h"
41#include "ctktypebuiltins.h"
42#include "ctkprivate.h"
43#include "ctkmain.h"
44#include "ctkmarshalers.h"
45#include "ctksizerequest.h"
46#include "ctksizerequestcacheprivate.h"
47#include "ctkwidgetprivate.h"
48#include "ctkwindow.h"
49#include "ctkassistant.h"
50#include "ctkintl.h"
51#include "ctkstylecontextprivate.h"
52#include "ctkwidgetpath.h"
53#include "a11y/ctkcontaineraccessible.h"
54#include "a11y/ctkcontaineraccessibleprivate.h"
55#include "ctkpopovermenu.h"
56#include "ctkshortcutswindow.h"
57
58/* A handful of containers inside CTK+ are cheating and widgets
59 * inside internal structure as direct children for the purpose
60 * of forall().
61 */
62#define SPECIAL_CONTAINER(x)((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*)
((x)); GType __t = ((ctk_assistant_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
x)); GType __t = ((ctk_action_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
x)); GType __t = ((ctk_popover_menu_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
x)); GType __t = ((ctk_shortcuts_section_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
x)); GType __t = ((ctk_shortcuts_window_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; })))))
(CTK_IS_ASSISTANT (x)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(x)); GType __t = ((ctk_assistant_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; }))))
|| \
63 CTK_IS_ACTION_BAR (x)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(x)); GType __t = ((ctk_action_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; }))))
|| \
64 CTK_IS_POPOVER_MENU (x)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(x)); GType __t = ((ctk_popover_menu_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; }))))
|| \
65 CTK_IS_SHORTCUTS_SECTION (x)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(x)); GType __t = ((ctk_shortcuts_section_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; }))))
|| \
66 CTK_IS_SHORTCUTS_WINDOW (x)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(x)); GType __t = ((ctk_shortcuts_window_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; }))))
)
67
68/**
69 * SECTION:ctkcontainer
70 * @Short_description: Base class for widgets which contain other widgets
71 * @Title: CtkContainer
72 *
73 * A CTK+ user interface is constructed by nesting widgets inside widgets.
74 * Container widgets are the inner nodes in the resulting tree of widgets:
75 * they contain other widgets. So, for example, you might have a #CtkWindow
76 * containing a #CtkFrame containing a #CtkLabel. If you wanted an image instead
77 * of a textual label inside the frame, you might replace the #CtkLabel widget
78 * with a #CtkImage widget.
79 *
80 * There are two major kinds of container widgets in CTK+. Both are subclasses
81 * of the abstract CtkContainer base class.
82 *
83 * The first type of container widget has a single child widget and derives
84 * from #CtkBin. These containers are decorators, which
85 * add some kind of functionality to the child. For example, a #CtkButton makes
86 * its child into a clickable button; a #CtkFrame draws a frame around its child
87 * and a #CtkWindow places its child widget inside a top-level window.
88 *
89 * The second type of container can have more than one child; its purpose is to
90 * manage layout. This means that these containers assign
91 * sizes and positions to their children. For example, a #CtkHBox arranges its
92 * children in a horizontal row, and a #CtkGrid arranges the widgets it contains
93 * in a two-dimensional grid.
94 *
95 * For implementations of #CtkContainer the virtual method #CtkContainerClass.forall()
96 * is always required, since it's used for drawing and other internal operations
97 * on the children.
98 * If the #CtkContainer implementation expect to have non internal children
99 * it's needed to implement both #CtkContainerClass.add() and #CtkContainerClass.remove().
100 * If the CtkContainer implementation has internal children, they should be added
101 * with ctk_widget_set_parent() on init() and removed with ctk_widget_unparent()
102 * in the #CtkWidgetClass.destroy() implementation.
103 * See more about implementing custom widgets at https://wiki.gnome.org/HowDoI/CustomWidgets
104 *
105 * # Height for width geometry management
106 *
107 * CTK+ uses a height-for-width (and width-for-height) geometry management system.
108 * Height-for-width means that a widget can change how much vertical space it needs,
109 * depending on the amount of horizontal space that it is given (and similar for
110 * width-for-height).
111 *
112 * There are some things to keep in mind when implementing container widgets
113 * that make use of CTK+’s height for width geometry management system. First,
114 * it’s important to note that a container must prioritize one of its
115 * dimensions, that is to say that a widget or container can only have a
116 * #CtkSizeRequestMode that is %CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or
117 * %CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT. However, every widget and container
118 * must be able to respond to the APIs for both dimensions, i.e. even if a
119 * widget has a request mode that is height-for-width, it is possible that
120 * its parent will request its sizes using the width-for-height APIs.
121 *
122 * To ensure that everything works properly, here are some guidelines to follow
123 * when implementing height-for-width (or width-for-height) containers.
124 *
125 * Each request mode involves 2 virtual methods. Height-for-width apis run
126 * through ctk_widget_get_preferred_width() and then through ctk_widget_get_preferred_height_for_width().
127 * When handling requests in the opposite #CtkSizeRequestMode it is important that
128 * every widget request at least enough space to display all of its content at all times.
129 *
130 * When ctk_widget_get_preferred_height() is called on a container that is height-for-width,
131 * the container must return the height for its minimum width. This is easily achieved by
132 * simply calling the reverse apis implemented for itself as follows:
133 *
134 * |[<!-- language="C" -->
135 * static void
136 * foo_container_get_preferred_height (CtkWidget *widget,
137 * gint *min_height,
138 * gint *nat_height)
139 * {
140 * if (i_am_in_height_for_width_mode)
141 * {
142 * gint min_width;
143 *
144 * CTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
145 * &min_width,
146 * NULL);
147 * CTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width
148 * (widget,
149 * min_width,
150 * min_height,
151 * nat_height);
152 * }
153 * else
154 * {
155 * ... many containers support both request modes, execute the
156 * real width-for-height request here by returning the
157 * collective heights of all widgets that are stacked
158 * vertically (or whatever is appropriate for this container)
159 * ...
160 * }
161 * }
162 * ]|
163 *
164 * Similarly, when ctk_widget_get_preferred_width_for_height() is called for a container or widget
165 * that is height-for-width, it then only needs to return the base minimum width like so:
166 *
167 * |[<!-- language="C" -->
168 * static void
169 * foo_container_get_preferred_width_for_height (CtkWidget *widget,
170 * gint for_height,
171 * gint *min_width,
172 * gint *nat_width)
173 * {
174 * if (i_am_in_height_for_width_mode)
175 * {
176 * CTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
177 * min_width,
178 * nat_width);
179 * }
180 * else
181 * {
182 * ... execute the real width-for-height request here based on
183 * the required width of the children collectively if the
184 * container were to be allocated the said height ...
185 * }
186 * }
187 * ]|
188 *
189 * Height for width requests are generally implemented in terms of a virtual allocation
190 * of widgets in the input orientation. Assuming an height-for-width request mode, a container
191 * would implement the get_preferred_height_for_width() virtual function by first calling
192 * ctk_widget_get_preferred_width() for each of its children.
193 *
194 * For each potential group of children that are lined up horizontally, the values returned by
195 * ctk_widget_get_preferred_width() should be collected in an array of #CtkRequestedSize structures.
196 * Any child spacing should be removed from the input @for_width and then the collective size should be
197 * allocated using the ctk_distribute_natural_allocation() convenience function.
198 *
199 * The container will then move on to request the preferred height for each child by using
200 * ctk_widget_get_preferred_height_for_width() and using the sizes stored in the #CtkRequestedSize array.
201 *
202 * To allocate a height-for-width container, it’s again important
203 * to consider that a container must prioritize one dimension over the other. So if
204 * a container is a height-for-width container it must first allocate all widgets horizontally
205 * using a #CtkRequestedSize array and ctk_distribute_natural_allocation() and then add any
206 * extra space (if and where appropriate) for the widget to expand.
207 *
208 * After adding all the expand space, the container assumes it was allocated sufficient
209 * height to fit all of its content. At this time, the container must use the total horizontal sizes
210 * of each widget to request the height-for-width of each of its children and store the requests in a
211 * #CtkRequestedSize array for any widgets that stack vertically (for tabular containers this can
212 * be generalized into the heights and widths of rows and columns).
213 * The vertical space must then again be distributed using ctk_distribute_natural_allocation()
214 * while this time considering the allocated height of the widget minus any vertical spacing
215 * that the container adds. Then vertical expand space should be added where appropriate and available
216 * and the container should go on to actually allocating the child widgets.
217 *
218 * See [CtkWidget’s geometry management section][geometry-management]
219 * to learn more about implementing height-for-width geometry management for widgets.
220 *
221 * # Child properties
222 *
223 * CtkContainer introduces child properties.
224 * These are object properties that are not specific
225 * to either the container or the contained widget, but rather to their relation.
226 * Typical examples of child properties are the position or pack-type of a widget
227 * which is contained in a #CtkBox.
228 *
229 * Use ctk_container_class_install_child_property() to install child properties
230 * for a container class and ctk_container_class_find_child_property() or
231 * ctk_container_class_list_child_properties() to get information about existing
232 * child properties.
233 *
234 * To set the value of a child property, use ctk_container_child_set_property(),
235 * ctk_container_child_set() or ctk_container_child_set_valist().
236 * To obtain the value of a child property, use
237 * ctk_container_child_get_property(), ctk_container_child_get() or
238 * ctk_container_child_get_valist(). To emit notification about child property
239 * changes, use ctk_widget_child_notify().
240 *
241 * # CtkContainer as CtkBuildable
242 *
243 * The CtkContainer implementation of the CtkBuildable interface supports
244 * a <packing> element for children, which can contain multiple <property>
245 * elements that specify child properties for the child.
246 *
247 * Since 2.16, child properties can also be marked as translatable using
248 * the same “translatable”, “comments” and “context” attributes that are used
249 * for regular properties.
250 *
251 * Since 3.16, containers can have a <focus-chain> element containing multiple
252 * <widget> elements, one for each child that should be added to the focus
253 * chain. The ”name” attribute gives the id of the widget.
254 *
255 * An example of these properties in UI definitions:
256 * |[
257 * <object class="CtkBox">
258 * <child>
259 * <object class="CtkEntry" id="entry1"/>
260 * <packing>
261 * <property name="pack-type">start</property>
262 * </packing>
263 * </child>
264 * <child>
265 * <object class="CtkEntry" id="entry2"/>
266 * </child>
267 * <focus-chain>
268 * <widget name="entry1"/>
269 * <widget name="entry2"/>
270 * </focus-chain>
271 * </object>
272 * ]|
273 *
274 */
275
276
277struct _CtkContainerPrivate
278{
279 CtkWidget *focus_child;
280
281 CdkFrameClock *resize_clock;
282 guint resize_handler;
283
284 guint border_width : 16;
285 guint border_width_set : 1;
286
287 guint has_focus_chain : 1;
288 guint reallocate_redraws : 1;
289 guint restyle_pending : 1;
290 guint resize_mode : 2;
291 guint resize_mode_set : 1;
292 guint request_mode : 2;
293};
294
295enum {
296 ADD,
297 REMOVE,
298 CHECK_RESIZE,
299 SET_FOCUS_CHILD,
300 LAST_SIGNAL
301};
302
303enum {
304 PROP_0,
305 PROP_BORDER_WIDTH,
306 PROP_RESIZE_MODE,
307 PROP_CHILD,
308 LAST_PROP
309};
310
311static GParamSpec *container_props[LAST_PROP];
312
313#define PARAM_SPEC_PARAM_ID(pspec)((pspec)->param_id) ((pspec)->param_id)
314#define PARAM_SPEC_SET_PARAM_ID(pspec, id)((pspec)->param_id = (id)) ((pspec)->param_id = (id))
315
316
317/* --- prototypes --- */
318static void ctk_container_base_class_init (CtkContainerClass *klass);
319static void ctk_container_base_class_finalize (CtkContainerClass *klass);
320static void ctk_container_class_init (CtkContainerClass *klass);
321static void ctk_container_init (CtkContainer *container);
322static void ctk_container_destroy (CtkWidget *widget);
323static void ctk_container_set_property (GObject *object,
324 guint prop_id,
325 const GValue *value,
326 GParamSpec *pspec);
327static void ctk_container_get_property (GObject *object,
328 guint prop_id,
329 GValue *value,
330 GParamSpec *pspec);
331static void ctk_container_add_unimplemented (CtkContainer *container,
332 CtkWidget *widget);
333static void ctk_container_remove_unimplemented (CtkContainer *container,
334 CtkWidget *widget);
335static void ctk_container_real_check_resize (CtkContainer *container);
336static void ctk_container_compute_expand (CtkWidget *widget,
337 gboolean *hexpand_p,
338 gboolean *vexpand_p);
339static gboolean ctk_container_focus (CtkWidget *widget,
340 CtkDirectionType direction);
341static void ctk_container_real_set_focus_child (CtkContainer *container,
342 CtkWidget *widget);
343
344static gboolean ctk_container_focus_move (CtkContainer *container,
345 GList *children,
346 CtkDirectionType direction);
347static void ctk_container_children_callback (CtkWidget *widget,
348 gpointer client_data);
349static void ctk_container_show_all (CtkWidget *widget);
350static gint ctk_container_draw (CtkWidget *widget,
351 cairo_t *cr);
352static void ctk_container_map (CtkWidget *widget);
353static void ctk_container_unmap (CtkWidget *widget);
354static void ctk_container_adjust_size_request (CtkWidget *widget,
355 CtkOrientation orientation,
356 gint *minimum_size,
357 gint *natural_size);
358static void ctk_container_adjust_baseline_request (CtkWidget *widget,
359 gint *minimum_baseline,
360 gint *natural_baseline);
361static void ctk_container_adjust_size_allocation (CtkWidget *widget,
362 CtkOrientation orientation,
363 gint *minimum_size,
364 gint *natural_size,
365 gint *allocated_pos,
366 gint *allocated_size);
367static void ctk_container_adjust_baseline_allocation (CtkWidget *widget,
368 gint *baseline);
369static CtkSizeRequestMode ctk_container_get_request_mode (CtkWidget *widget);
370
371static gchar* ctk_container_child_default_composite_name (CtkContainer *container,
372 CtkWidget *child);
373
374static CtkWidgetPath * ctk_container_real_get_path_for_child (CtkContainer *container,
375 CtkWidget *child);
376
377/* CtkBuildable */
378static void ctk_container_buildable_init (CtkBuildableIface *iface);
379static void ctk_container_buildable_add_child (CtkBuildable *buildable,
380 CtkBuilder *builder,
381 GObject *child,
382 const gchar *type);
383static gboolean ctk_container_buildable_custom_tag_start (CtkBuildable *buildable,
384 CtkBuilder *builder,
385 GObject *child,
386 const gchar *tagname,
387 GMarkupParser *parser,
388 gpointer *data);
389static void ctk_container_buildable_custom_tag_end (CtkBuildable *buildable,
390 CtkBuilder *builder,
391 GObject *child,
392 const gchar *tagname,
393 gpointer *data);
394static void ctk_container_buildable_custom_finished (CtkBuildable *buildable,
395 CtkBuilder *builder,
396 GObject *child,
397 const gchar *tagname,
398 gpointer data);
399
400static gboolean ctk_container_should_propagate_draw (CtkContainer *container,
401 CtkWidget *child,
402 cairo_t *cr);
403
404/* --- variables --- */
405static GQuark vadjustment_key_id;
406static GQuark hadjustment_key_id;
407static GQuark quark_focus_chain;
408static guint container_signals[LAST_SIGNAL] = { 0 };
409static gint CtkContainer_private_offset;
410static CtkWidgetClass *parent_class = NULL((void*)0);
411extern GParamSpecPool *_ctk_widget_child_property_pool;
412extern GObjectNotifyContext *_ctk_widget_child_property_notify_context;
413static CtkBuildableIface *parent_buildable_iface;
414
415
416/* --- functions --- */
417static inline gpointer
418ctk_container_get_instance_private (CtkContainer *self)
419{
420 return G_STRUCT_MEMBER_P (self, CtkContainer_private_offset)((gpointer) ((guint8*) (self) + (glong) (CtkContainer_private_offset
)))
;
421}
422
423GType
424ctk_container_get_type (void)
425{
426 static GType container_type = 0;
427
428 if (!container_type)
429 {
430 const GTypeInfo container_info =
431 {
432 sizeof (CtkContainerClass),
433 (GBaseInitFunc) ctk_container_base_class_init,
434 (GBaseFinalizeFunc) ctk_container_base_class_finalize,
435 (GClassInitFunc) ctk_container_class_init,
436 NULL((void*)0) /* class_finalize */,
437 NULL((void*)0) /* class_data */,
438 sizeof (CtkContainer),
439 0 /* n_preallocs */,
440 (GInstanceInitFunc) ctk_container_init,
441 NULL((void*)0), /* value_table */
442 };
443
444 const GInterfaceInfo buildable_info =
445 {
446 (GInterfaceInitFunc) ctk_container_buildable_init,
447 NULL((void*)0),
448 NULL((void*)0)
449 };
450
451 container_type =
452 g_type_register_static (CTK_TYPE_WIDGET(ctk_widget_get_type ()), I_("CtkContainer")g_intern_static_string ("CtkContainer"),
453 &container_info, G_TYPE_FLAG_ABSTRACT);
454
455 CtkContainer_private_offset =
456 g_type_add_instance_private (container_type, sizeof (CtkContainerPrivate));
457
458 g_type_add_interface_static (container_type,
459 CTK_TYPE_BUILDABLE(ctk_buildable_get_type ()),
460 &buildable_info);
461
462 }
463
464 return container_type;
465}
466
467static void
468ctk_container_base_class_init (CtkContainerClass *class)
469{
470 /* reset instance specifc class fields that don't get inherited */
471 class->set_child_property = NULL((void*)0);
472 class->get_child_property = NULL((void*)0);
473}
474
475static void
476ctk_container_base_class_finalize (CtkContainerClass *class)
477{
478 GList *list, *node;
479
480 list = g_param_spec_pool_list_owned (_ctk_widget_child_property_pool, G_OBJECT_CLASS_TYPE (class)((((GTypeClass*) (class))->g_type)));
481 for (node = list; node; node = node->next)
482 {
483 GParamSpec *pspec = node->data;
484
485 g_param_spec_pool_remove (_ctk_widget_child_property_pool, pspec);
486 PARAM_SPEC_SET_PARAM_ID (pspec, 0)((pspec)->param_id = (0));
487 g_param_spec_unref (pspec);
488 }
489 g_list_free (list);
490}
491
492static void
493ctk_container_class_init (CtkContainerClass *class)
494{
495 GObjectClass *gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
496 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
;
497
498 parent_class = g_type_class_peek_parent (class);
499
500 vadjustment_key_id = g_quark_from_static_string ("ctk-vadjustment");
501 hadjustment_key_id = g_quark_from_static_string ("ctk-hadjustment");
502 quark_focus_chain = g_quark_from_static_string ("ctk-container-focus-chain");
503
504 gobject_class->set_property = ctk_container_set_property;
505 gobject_class->get_property = ctk_container_get_property;
506
507 widget_class->destroy = ctk_container_destroy;
508 widget_class->compute_expand = ctk_container_compute_expand;
509 widget_class->show_all = ctk_container_show_all;
510 widget_class->draw = ctk_container_draw;
511 widget_class->map = ctk_container_map;
512 widget_class->unmap = ctk_container_unmap;
513 widget_class->focus = ctk_container_focus;
514
515 widget_class->adjust_size_request = ctk_container_adjust_size_request;
516 widget_class->adjust_baseline_request = ctk_container_adjust_baseline_request;
517 widget_class->adjust_size_allocation = ctk_container_adjust_size_allocation;
518 widget_class->adjust_baseline_allocation = ctk_container_adjust_baseline_allocation;
519 widget_class->get_request_mode = ctk_container_get_request_mode;
520
521 class->add = ctk_container_add_unimplemented;
522 class->remove = ctk_container_remove_unimplemented;
523 class->check_resize = ctk_container_real_check_resize;
524 class->forall = NULL((void*)0);
525 class->set_focus_child = ctk_container_real_set_focus_child;
526 class->child_type = NULL((void*)0);
527 class->composite_name = ctk_container_child_default_composite_name;
528 class->get_path_for_child = ctk_container_real_get_path_for_child;
529
530 container_props[PROP_RESIZE_MODE] =
531 g_param_spec_enum ("resize-mode",
532 P_("Resize mode")g_dgettext("ctk30" "-properties","Resize mode"),
533 P_("Specify how resize events are handled")g_dgettext("ctk30" "-properties","Specify how resize events are handled"
)
,
534 CTK_TYPE_RESIZE_MODE(ctk_resize_mode_get_type ()),
535 CTK_RESIZE_PARENT,
536 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
537
538 container_props[PROP_BORDER_WIDTH] =
539 g_param_spec_uint ("border-width",
540 P_("Border width")g_dgettext("ctk30" "-properties","Border width"),
541 P_("The width of the empty border outside the containers children")g_dgettext("ctk30" "-properties","The width of the empty border outside the containers children"
)
,
542 0, 65535,
543 0,
544 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
545
546 container_props[PROP_CHILD] =
547 g_param_spec_object ("child",
548 P_("Child")g_dgettext("ctk30" "-properties","Child"),
549 P_("Can be used to add a new child to the container")g_dgettext("ctk30" "-properties","Can be used to add a new child to the container"
)
,
550 CTK_TYPE_WIDGET(ctk_widget_get_type ()),
551 CTK_PARAM_WRITABLEG_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_DEPRECATED);
552
553 g_object_class_install_properties (gobject_class, LAST_PROP, container_props);
554
555 container_signals[ADD] =
556 g_signal_new (I_("add")g_intern_static_string ("add"),
557 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
558 G_SIGNAL_RUN_FIRST,
559 G_STRUCT_OFFSET (CtkContainerClass, add)((glong) __builtin_offsetof(CtkContainerClass, add)),
560 NULL((void*)0), NULL((void*)0),
561 NULL((void*)0),
562 G_TYPE_NONE((GType) ((1) << (2))), 1,
563 CTK_TYPE_WIDGET(ctk_widget_get_type ()));
564 container_signals[REMOVE] =
565 g_signal_new (I_("remove")g_intern_static_string ("remove"),
566 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
567 G_SIGNAL_RUN_FIRST,
568 G_STRUCT_OFFSET (CtkContainerClass, remove)((glong) __builtin_offsetof(CtkContainerClass, remove)),
569 NULL((void*)0), NULL((void*)0),
570 NULL((void*)0),
571 G_TYPE_NONE((GType) ((1) << (2))), 1,
572 CTK_TYPE_WIDGET(ctk_widget_get_type ()));
573 container_signals[CHECK_RESIZE] =
574 g_signal_new (I_("check-resize")g_intern_static_string ("check-resize"),
575 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
576 G_SIGNAL_RUN_LAST,
577 G_STRUCT_OFFSET (CtkContainerClass, check_resize)((glong) __builtin_offsetof(CtkContainerClass, check_resize)),
578 NULL((void*)0), NULL((void*)0),
579 NULL((void*)0),
580 G_TYPE_NONE((GType) ((1) << (2))), 0);
581 container_signals[SET_FOCUS_CHILD] =
582 g_signal_new (I_("set-focus-child")g_intern_static_string ("set-focus-child"),
583 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
584 G_SIGNAL_RUN_FIRST,
585 G_STRUCT_OFFSET (CtkContainerClass, set_focus_child)((glong) __builtin_offsetof(CtkContainerClass, set_focus_child
))
,
586 NULL((void*)0), NULL((void*)0),
587 NULL((void*)0),
588 G_TYPE_NONE((GType) ((1) << (2))), 1,
589 CTK_TYPE_WIDGET(ctk_widget_get_type ()));
590
591 if (CtkContainer_private_offset != 0)
592 g_type_class_adjust_private_offset (class, &CtkContainer_private_offset);
593
594 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_CONTAINER_ACCESSIBLE(ctk_container_accessible_get_type ()));
595}
596
597static void
598ctk_container_buildable_init (CtkBuildableIface *iface)
599{
600 parent_buildable_iface = g_type_interface_peek_parent (iface);
601 iface->add_child = ctk_container_buildable_add_child;
602 iface->custom_tag_start = ctk_container_buildable_custom_tag_start;
603 iface->custom_tag_end = ctk_container_buildable_custom_tag_end;
604 iface->custom_finished = ctk_container_buildable_custom_finished;
605}
606
607static void
608ctk_container_buildable_add_child (CtkBuildable *buildable,
609 CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)),
610 GObject *child,
611 const gchar *type)
612{
613 if (type)
614 {
615 CTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type)g_warning ("'%s' is not a valid child type of '%s'", type, g_type_name
((((((GTypeClass*) (((GTypeInstance*) (buildable))->g_class
))->g_type)))))
;
616 }
617 else if (CTK_IS_WIDGET (child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(child)); 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; }))))
&&
618 _ctk_widget_get_parent (CTK_WIDGET (child)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_widget_get_type ()))))))
) == NULL((void*)0))
619 {
620 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 ()))))))
);
621 }
622 else
623 g_warning ("Cannot add an object of type %s to a container of type %s",
624 g_type_name (G_OBJECT_TYPE (child)(((((GTypeClass*) (((GTypeInstance*) (child))->g_class))->
g_type)))
), g_type_name (G_OBJECT_TYPE (buildable)(((((GTypeClass*) (((GTypeInstance*) (buildable))->g_class
))->g_type)))
));
625}
626
627static inline void
628container_set_child_property (CtkContainer *container,
629 CtkWidget *child,
630 GParamSpec *pspec,
631 const GValue *value,
632 GObjectNotifyQueue *nqueue)
633{
634 GValue tmp_value = G_VALUE_INIT{ 0, { { 0 } } };
635 CtkContainerClass *class = g_type_class_peek (pspec->owner_type);
636
637 /* provide a copy to work from, convert (if necessary) and validate */
638 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
);
639 if (!g_value_transform (value, &tmp_value))
640 g_warning ("unable to set child property '%s' of type '%s' from value of type '%s'",
641 pspec->name,
642 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
),
643 G_VALUE_TYPE_NAME (value)(g_type_name ((((GValue*) (value))->g_type))));
644 else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
645 {
646 gchar *contents = g_strdup_value_contents (value);
647
648 g_warning ("value \"%s\" of type '%s' is invalid for property '%s' of type '%s'",
649 contents,
650 G_VALUE_TYPE_NAME (value)(g_type_name ((((GValue*) (value))->g_type))),
651 pspec->name,
652 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
));
653 g_free (contents);
654 }
655 else
656 {
657 class->set_child_property (container, child, PARAM_SPEC_PARAM_ID (pspec)((pspec)->param_id), &tmp_value, pspec);
658 g_object_notify_queue_add (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, nqueue, pspec);
659 }
660 g_value_unset (&tmp_value);
661}
662
663static void
664ctk_container_buildable_set_child_property (CtkContainer *container,
665 CtkBuilder *builder,
666 CtkWidget *child,
667 gchar *name,
668 const gchar *value)
669{
670 GParamSpec *pspec;
671 GValue gvalue = G_VALUE_INIT{ 0, { { 0 } } };
672 GError *error = NULL((void*)0);
673 GObjectNotifyQueue *nqueue;
674
675 if (_ctk_widget_get_parent (child) != (CtkWidget *)container &&
676 !SPECIAL_CONTAINER (container)((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*)
((container)); GType __t = ((ctk_assistant_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
container)); GType __t = ((ctk_action_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
container)); GType __t = ((ctk_popover_menu_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
container)); GType __t = ((ctk_shortcuts_section_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; })))) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_shortcuts_window_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; })))))
)
677 {
678 /* This can happen with internal children of complex widgets.
679 * Silently ignore the child properties in this case. We explicitly
680 * allow it for CtkAssistant, since that is how it works.
681 */
682 return;
683 }
684
685 pspec = ctk_container_class_find_child_property (G_OBJECT_GET_CLASS (container)((((GObjectClass*) (((GTypeInstance*) ((container)))->g_class
))))
, name);
686 if (!pspec)
687 {
688 g_warning ("%s does not have a child property called %s",
689 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
, name);
690 return;
691 }
692 else if (!(pspec->flags & G_PARAM_WRITABLE))
693 {
694 g_warning ("Child property '%s' of container class '%s' is not writable",
695 name, G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
);
696 return;
697 }
698
699 if (!ctk_builder_value_from_string (builder, pspec, value, &gvalue, &error))
700 {
701 g_warning ("Could not read property %s:%s with value %s of type %s: %s",
702 g_type_name (G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
),
703 name,
704 value,
705 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
),
706 error->message);
707 g_error_free (error);
708 return;
709 }
710
711 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
712 g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
713 nqueue = g_object_notify_queue_freeze (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, _ctk_widget_child_property_notify_context);
714 container_set_child_property (container, child, pspec, &gvalue, nqueue);
715 g_object_notify_queue_thaw (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, nqueue);
716 g_object_unref (container);
717 g_object_unref (child);
718 g_value_unset (&gvalue);
719}
720
721typedef struct {
722 CtkBuilder *builder;
723 CtkContainer *container;
724 CtkWidget *child;
725 GString *string;
726 gchar *child_prop_name;
727 gchar *context;
728 gboolean translatable;
729} PackingData;
730
731static void
732packing_start_element (GMarkupParseContext *context,
733 const gchar *element_name,
734 const gchar **names,
735 const gchar **values,
736 gpointer user_data,
737 GError **error)
738{
739 PackingData *data = (PackingData*)user_data;
740
741 if (strcmp (element_name, "property") == 0)
742 {
743 const gchar *name;
744 gboolean translatable = FALSE(0);
745 const gchar *ctx = NULL((void*)0);
746
747 if (!_ctk_builder_check_parent (data->builder, context, "packing", error))
748 return;
749
750 if (!g_markup_collect_attributes (element_name, names, values, error,
751 G_MARKUP_COLLECT_STRING, "name", &name,
752 G_MARKUP_COLLECT_BOOLEAN|G_MARKUP_COLLECT_OPTIONAL, "translatable", &translatable,
753 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "comments", NULL((void*)0),
754 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "context", &ctx,
755 G_MARKUP_COLLECT_INVALID))
756 {
757 _ctk_builder_prefix_error (data->builder, context, error);
758 return;
759 }
760
761 data->child_prop_name = g_strdup (name)g_strdup_inline (name);
762 data->translatable = translatable;
763 data->context = g_strdup (ctx)g_strdup_inline (ctx);
764 }
765 else if (strcmp (element_name, "packing") == 0)
766 {
767 if (!_ctk_builder_check_parent (data->builder, context, "child", error))
768 return;
769
770 if (!g_markup_collect_attributes (element_name, names, values, error,
771 G_MARKUP_COLLECT_INVALID, NULL((void*)0), NULL((void*)0),
772 G_MARKUP_COLLECT_INVALID))
773 _ctk_builder_prefix_error (data->builder, context, error);
774 }
775 else
776 {
777 _ctk_builder_error_unhandled_tag (data->builder, context,
778 "CtkContainer", element_name,
779 error);
780 }
781}
782
783static void
784packing_text_element (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
785 const gchar *text,
786 gsize text_len,
787 gpointer user_data,
788 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
789{
790 PackingData *data = (PackingData*)user_data;
791
792 if (data->child_prop_name)
793 g_string_append_len (data->string, text, text_len)g_string_append_len_inline (data->string, text, text_len);
794}
795
796static void
797packing_end_element (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
798 const gchar *element_name G_GNUC_UNUSED__attribute__ ((__unused__)),
799 gpointer user_data,
800 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
801{
802 PackingData *data = (PackingData*)user_data;
803
804 /* translate the string */
805 if (data->string->len && data->translatable)
806 {
807 const gchar *translated;
808 const gchar *domain;
809
810 domain = ctk_builder_get_translation_domain (data->builder);
811
812 translated = _ctk_builder_parser_translate (domain,
813 data->context,
814 data->string->str);
815 g_string_assign (data->string, translated);
816 }
817
818 if (data->child_prop_name)
819 ctk_container_buildable_set_child_property (data->container,
820 data->builder,
821 data->child,
822 data->child_prop_name,
823 data->string->str);
824
825 g_string_set_size (data->string, 0);
826 g_clear_pointer (&data->child_prop_name, g_free)do { _Static_assert (sizeof *(&data->child_prop_name) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&data->child_prop_name)) _pp = (&data->child_prop_name
); __typeof__ (*(&data->child_prop_name)) _ptr = *_pp;
*_pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0)
;
827 g_clear_pointer (&data->context, g_free)do { _Static_assert (sizeof *(&data->context) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ ((&
data->context)) _pp = (&data->context); __typeof__ (
*(&data->context)) _ptr = *_pp; *_pp = ((void*)0); if (
_ptr) (g_free) (_ptr); } while (0)
;
828 data->translatable = FALSE(0);
829}
830
831static const GMarkupParser packing_parser =
832 {
833 .start_element = packing_start_element,
834 .end_element = packing_end_element,
835 .text = packing_text_element,
836 };
837
838typedef struct
839 {
840 gchar *name;
841 gint line;
842 gint col;
843 } FocusChainWidget;
844
845static void
846focus_chain_widget_free (gpointer data)
847{
848 FocusChainWidget *fcw = data;
849
850 g_free (fcw->name);
851 g_free (fcw);
852}
853
854typedef struct
855 {
856 GSList *items;
857 GObject *object;
858 CtkBuilder *builder;
859 gint line;
860 gint col;
861 } FocusChainData;
862
863static void
864focus_chain_start_element (GMarkupParseContext *context,
865 const gchar *element_name,
866 const gchar **names,
867 const gchar **values,
868 gpointer user_data,
869 GError **error)
870{
871 FocusChainData *data = (FocusChainData*)user_data;
872
873 if (strcmp (element_name, "widget") == 0)
874 {
875 const gchar *name;
876 FocusChainWidget *fcw;
877
878 if (!_ctk_builder_check_parent (data->builder, context, "focus-chain", error))
879 return;
880
881 if (!g_markup_collect_attributes (element_name, names, values, error,
882 G_MARKUP_COLLECT_STRING, "name", &name,
883 G_MARKUP_COLLECT_INVALID))
884 {
885 _ctk_builder_prefix_error (data->builder, context, error);
886 return;
887 }
888
889 fcw = g_new (FocusChainWidget, 1)((FocusChainWidget *) g_malloc_n ((1), sizeof (FocusChainWidget
)))
;
890 fcw->name = g_strdup (name)g_strdup_inline (name);
891 g_markup_parse_context_get_position (context, &fcw->line, &fcw->col);
892 data->items = g_slist_prepend (data->items, fcw);
893 }
894 else if (strcmp (element_name, "focus-chain") == 0)
895 {
896 if (!_ctk_builder_check_parent (data->builder, context, "object", error))
897 return;
898
899 if (!g_markup_collect_attributes (element_name, names, values, error,
900 G_MARKUP_COLLECT_INVALID, "", NULL((void*)0),
901 G_MARKUP_COLLECT_INVALID))
902 _ctk_builder_prefix_error (data->builder, context, error);
903 }
904 else
905 {
906 _ctk_builder_error_unhandled_tag (data->builder, context,
907 "CtkContainer", element_name,
908 error);
909 }
910}
911
912static const GMarkupParser focus_chain_parser =
913 {
914 .start_element = focus_chain_start_element
915 };
916
917static gboolean
918ctk_container_buildable_custom_tag_start (CtkBuildable *buildable,
919 CtkBuilder *builder,
920 GObject *child,
921 const gchar *tagname,
922 GMarkupParser *parser,
923 gpointer *parser_data)
924{
925 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
926 tagname, parser, parser_data))
927 return TRUE(!(0));
928
929 if (child && strcmp (tagname, "packing") == 0)
930 {
931 PackingData *data;
932
933 data = g_slice_new0 (PackingData)((PackingData*) g_slice_alloc0 (sizeof (PackingData)));
934 data->string = g_string_new ("");
935 data->builder = builder;
936 data->container = CTK_CONTAINER (buildable)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_container_get_type ()))))))
;
937 data->child = CTK_WIDGET (child)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_widget_get_type ()))))))
;
938 data->child_prop_name = NULL((void*)0);
939
940 *parser = packing_parser;
941 *parser_data = data;
942
943 return TRUE(!(0));
944 }
945 else if (!child && strcmp (tagname, "focus-chain") == 0)
946 {
947 FocusChainData *data;
948
949 data = g_slice_new0 (FocusChainData)((FocusChainData*) g_slice_alloc0 (sizeof (FocusChainData)));
950 data->items = NULL((void*)0);
951 data->object = G_OBJECT (buildable)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), (((GType) ((20) << (2))))))))
;
952 data->builder = builder;
953
954 *parser = focus_chain_parser;
955 *parser_data = data;
956
957 return TRUE(!(0));
958 }
959
960 return FALSE(0);
961}
962
963static void
964ctk_container_buildable_custom_tag_end (CtkBuildable *buildable,
965 CtkBuilder *builder,
966 GObject *child,
967 const gchar *tagname,
968 gpointer *parser_data)
969{
970 if (strcmp (tagname, "packing") == 0)
971 {
972 PackingData *data = (PackingData*)parser_data;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
973
974 g_string_free (data->string, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(data->string), ((!(0)))) : g_string_free_and_steal (data->
string)) : (g_string_free) ((data->string), ((!(0)))))
;
975 g_slice_free (PackingData, data)do { if (1) g_slice_free1 (sizeof (PackingData), (data)); else
(void) ((PackingData*) 0 == (data)); } while (0)
;
976
977 return;
978 }
979
980 if (parent_buildable_iface->custom_tag_end)
981 parent_buildable_iface->custom_tag_end (buildable, builder,
982 child, tagname, parser_data);
983}
984
985static void
986ctk_container_buildable_custom_finished (CtkBuildable *buildable,
987 CtkBuilder *builder,
988 GObject *child,
989 const gchar *tagname,
990 gpointer parser_data)
991{
992 if (strcmp (tagname, "focus-chain") == 0)
993 {
994 FocusChainData *data = (FocusChainData*)parser_data;
995 FocusChainWidget *fcw;
996 GSList *l;
997 GList *chain;
998 GObject *object;
999
1000 chain = NULL((void*)0);
1001 for (l = data->items; l; l = l->next)
1002 {
1003 fcw = l->data;
1004 object = _ctk_builder_lookup_object (builder, fcw->name, fcw->line, fcw->col);
1005 if (!object)
1006 continue;
1007 chain = g_list_prepend (chain, object);
1008 }
1009
1010 ctk_container_set_focus_chain (CTK_CONTAINER (data->object)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->object)), ((ctk_container_get_type ()))))))
, chain);
1011 g_list_free (chain);
1012
1013 g_slist_free_full (data->items, focus_chain_widget_free);
1014 g_slice_free (FocusChainData, data)do { if (1) g_slice_free1 (sizeof (FocusChainData), (data)); else
(void) ((FocusChainData*) 0 == (data)); } while (0)
;
1015
1016 return;
1017 }
1018
1019 if (parent_buildable_iface->custom_finished)
1020 parent_buildable_iface->custom_finished (buildable, builder,
1021 child, tagname, parser_data);
1022}
1023
1024/**
1025 * ctk_container_child_type:
1026 * @container: a #CtkContainer
1027 *
1028 * Returns the type of the children supported by the container.
1029 *
1030 * Note that this may return %G_TYPE_NONE to indicate that no more
1031 * children can be added, e.g. for a #CtkPaned which already has two
1032 * children.
1033 *
1034 * Returns: a #GType.
1035 **/
1036GType
1037ctk_container_child_type (CtkContainer *container)
1038{
1039 GType slot;
1040 CtkContainerClass *class;
1041
1042 g_return_val_if_fail (CTK_IS_CONTAINER (container), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (0); } } while (0
)
;
1043
1044 class = CTK_CONTAINER_GET_CLASS (container)((((CtkContainerClass*) (((GTypeInstance*) ((container)))->
g_class))))
;
1045 if (class->child_type)
1046 slot = class->child_type (container);
1047 else
1048 slot = G_TYPE_NONE((GType) ((1) << (2)));
1049
1050 return slot;
1051}
1052
1053/* --- CtkContainer child property mechanism --- */
1054
1055/**
1056 * ctk_container_child_notify:
1057 * @container: the #CtkContainer
1058 * @child: the child widget
1059 * @child_property: the name of a child property installed on
1060 * the class of @container
1061 *
1062 * Emits a #CtkWidget::child-notify signal for the
1063 * [child property][child-properties]
1064 * @child_property on the child.
1065 *
1066 * This is an analogue of g_object_notify() for child properties.
1067 *
1068 * Also see ctk_widget_child_notify().
1069 *
1070 * Since: 3.2
1071 */
1072void
1073ctk_container_child_notify (CtkContainer *container,
1074 CtkWidget *child,
1075 const gchar *child_property)
1076{
1077 GObject *obj;
1078 GParamSpec *pspec;
1079
1080 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1081 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1082 g_return_if_fail (child_property != NULL)do { if ((child_property != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child_property != NULL"
); return; } } while (0)
;
1083
1084 obj = G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
;
1085
1086 if (obj->ref_count == 0)
1087 return;
1088
1089 g_object_ref (obj)((__typeof__ (obj)) (g_object_ref) (obj));
1090
1091 pspec = g_param_spec_pool_lookup (_ctk_widget_child_property_pool,
1092 child_property,
1093 G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
,
1094 TRUE(!(0)));
1095
1096 if (pspec == NULL((void*)0))
1097 {
1098 g_warning ("%s: container class '%s' has no child property named '%s'",
1099 G_STRLOC"ctkcontainer.c" ":" "1099",
1100 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
1101 child_property);
1102 }
1103 else
1104 {
1105 GObjectNotifyQueue *nqueue;
1106
1107 nqueue = g_object_notify_queue_freeze (obj, _ctk_widget_child_property_notify_context);
1108
1109 g_object_notify_queue_add (obj, nqueue, pspec);
1110 g_object_notify_queue_thaw (obj, nqueue);
1111 }
1112
1113 g_object_unref (obj);
1114}
1115
1116/**
1117 * ctk_container_child_notify_by_pspec:
1118 * @container: the #CtkContainer
1119 * @child: the child widget
1120 * @pspec: the #GParamSpec of a child property instealled on
1121 * the class of @container
1122 *
1123 * Emits a #CtkWidget::child-notify signal for the
1124 * [child property][child-properties] specified by
1125 * @pspec on the child.
1126 *
1127 * This is an analogue of g_object_notify_by_pspec() for child properties.
1128 *
1129 * Since: 3.18
1130 */
1131void
1132ctk_container_child_notify_by_pspec (CtkContainer *container,
1133 CtkWidget *child,
1134 GParamSpec *pspec)
1135{
1136 GObject *obj = G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
;
1137 GObjectNotifyQueue *nqueue;
1138
1139 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1140 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1141 g_return_if_fail (G_IS_PARAM_SPEC (pspec))do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2)))))))))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"G_IS_PARAM_SPEC (pspec)"); return; } } while (0)
;
1142
1143 if (obj->ref_count == 0)
1144 return;
1145
1146 g_object_ref (obj)((__typeof__ (obj)) (g_object_ref) (obj));
1147
1148 nqueue = g_object_notify_queue_freeze (obj, _ctk_widget_child_property_notify_context);
1149
1150 g_object_notify_queue_add (obj, nqueue, pspec);
1151 g_object_notify_queue_thaw (obj, nqueue);
1152
1153 g_object_unref (obj);
1154}
1155
1156static inline void
1157container_get_child_property (CtkContainer *container,
1158 CtkWidget *child,
1159 GParamSpec *pspec,
1160 GValue *value)
1161{
1162 CtkContainerClass *class = g_type_class_peek (pspec->owner_type);
1163
1164 class->get_child_property (container, child, PARAM_SPEC_PARAM_ID (pspec)((pspec)->param_id), value, pspec);
1165}
1166
1167/**
1168 * ctk_container_child_get_valist:
1169 * @container: a #CtkContainer
1170 * @child: a widget which is a child of @container
1171 * @first_property_name: the name of the first property to get
1172 * @var_args: return location for the first property, followed
1173 * optionally by more name/return location pairs, followed by %NULL
1174 *
1175 * Gets the values of one or more child properties for @child and @container.
1176 **/
1177void
1178ctk_container_child_get_valist (CtkContainer *container,
1179 CtkWidget *child,
1180 const gchar *first_property_name,
1181 va_list var_args)
1182{
1183 const gchar *name;
1184
1185 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1186 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1187
1188 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1189 g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
1190
1191 name = first_property_name;
1192 while (name)
1193 {
1194 GValue value = G_VALUE_INIT{ 0, { { 0 } } };
1195 GParamSpec *pspec;
1196 gchar *error;
1197
1198 pspec = g_param_spec_pool_lookup (_ctk_widget_child_property_pool,
1199 name,
1200 G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
,
1201 TRUE(!(0)));
1202 if (!pspec)
1203 {
1204 g_warning ("%s: container class '%s' has no child property named '%s'",
1205 G_STRLOC"ctkcontainer.c" ":" "1205",
1206 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
1207 name);
1208 break;
1209 }
1210 if (!(pspec->flags & G_PARAM_READABLE))
1211 {
1212 g_warning ("%s: child property '%s' of container class '%s' is not readable",
1213 G_STRLOC"ctkcontainer.c" ":" "1213",
1214 pspec->name,
1215 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
);
1216 break;
1217 }
1218 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
);
1219 container_get_child_property (container, child, pspec, &value);
1220 G_VALUE_LCOPY (&value, var_args, 0, &error)do { const GValue *g_vl_value = (&value); guint g_vl_flags
= (0); GType g_vl_value_type = (((GValue*) (g_vl_value))->
g_type); GTypeValueTable *g_vl_vtable = g_type_value_table_peek
(g_vl_value_type); const gchar *g_vl_lcopy_format = g_vl_vtable
->lcopy_format; GTypeCValue g_vl_cvalues[(8)] = { { 0, }, }
; guint g_vl_n_values = 0; while (*g_vl_lcopy_format) { GTypeCValue
*g_vl_cvalue = g_vl_cvalues + g_vl_n_values++; switch (*g_vl_lcopy_format
++) { case G_VALUE_COLLECT_INT: g_vl_cvalue->v_int = __builtin_va_arg
((var_args), gint); break; case G_VALUE_COLLECT_LONG: g_vl_cvalue
->v_long = __builtin_va_arg((var_args), glong); break; case
G_VALUE_COLLECT_INT64: g_vl_cvalue->v_int64 = __builtin_va_arg
((var_args), gint64); break; case G_VALUE_COLLECT_DOUBLE: g_vl_cvalue
->v_double = __builtin_va_arg((var_args), gdouble); break;
case G_VALUE_COLLECT_POINTER: g_vl_cvalue->v_pointer = __builtin_va_arg
((var_args), gpointer); break; default: do { g_assertion_message_expr
("Ctk", "ctkcontainer.c", 1220, ((const char*) (__func__)), (
(void*)0)); } while (0); } } *(&error) = g_vl_vtable->
lcopy_value (g_vl_value, g_vl_n_values, g_vl_cvalues, g_vl_flags
); } while (0)
;
1221 if (error)
1222 {
1223 g_warning ("%s: %s", G_STRLOC"ctkcontainer.c" ":" "1223", error);
1224 g_free (error);
1225 g_value_unset (&value);
1226 break;
1227 }
1228 g_value_unset (&value);
1229 name = va_arg (var_args, gchar*)__builtin_va_arg(var_args, gchar*);
1230 }
1231
1232 g_object_unref (child);
1233 g_object_unref (container);
1234}
1235
1236/**
1237 * ctk_container_child_get_property:
1238 * @container: a #CtkContainer
1239 * @child: a widget which is a child of @container
1240 * @property_name: the name of the property to get
1241 * @value: a location to return the value
1242 *
1243 * Gets the value of a child property for @child and @container.
1244 **/
1245void
1246ctk_container_child_get_property (CtkContainer *container,
1247 CtkWidget *child,
1248 const gchar *property_name,
1249 GValue *value)
1250{
1251 GParamSpec *pspec;
1252
1253 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1254 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1255 g_return_if_fail (property_name != NULL)do { if ((property_name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "property_name != NULL")
; return; } } while (0)
;
1256 g_return_if_fail (G_IS_VALUE (value))do { if (((((g_type_check_value ((GValue*) (value))))))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "G_IS_VALUE (value)"); return; } } while (0)
;
1257
1258 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1259 g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
1260 pspec = g_param_spec_pool_lookup (_ctk_widget_child_property_pool, property_name,
1261 G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
, TRUE(!(0)));
1262 if (!pspec)
1263 g_warning ("%s: container class '%s' has no child property named '%s'",
1264 G_STRLOC"ctkcontainer.c" ":" "1264",
1265 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
1266 property_name);
1267 else if (!(pspec->flags & G_PARAM_READABLE))
1268 g_warning ("%s: child property '%s' of container class '%s' is not readable",
1269 G_STRLOC"ctkcontainer.c" ":" "1269",
1270 pspec->name,
1271 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
);
1272 else
1273 {
1274 GValue *prop_value, tmp_value = G_VALUE_INIT{ 0, { { 0 } } };
1275
1276 /* auto-conversion of the callers value type
1277 */
1278 if (G_VALUE_TYPE (value)(((GValue*) (value))->g_type) == G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
)
1279 {
1280 g_value_reset (value);
1281 prop_value = value;
1282 }
1283 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
, G_VALUE_TYPE (value)(((GValue*) (value))->g_type)))
1284 {
1285 g_warning ("can't retrieve child property '%s' of type '%s' as value of type '%s'",
1286 pspec->name,
1287 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
),
1288 G_VALUE_TYPE_NAME (value)(g_type_name ((((GValue*) (value))->g_type))));
1289 g_object_unref (child);
1290 g_object_unref (container);
1291 return;
1292 }
1293 else
1294 {
1295 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
)
);
1296 prop_value = &tmp_value;
1297 }
1298 container_get_child_property (container, child, pspec, prop_value);
1299 if (prop_value != value)
1300 {
1301 g_value_transform (prop_value, value);
1302 g_value_unset (&tmp_value);
1303 }
1304 }
1305 g_object_unref (child);
1306 g_object_unref (container);
1307}
1308
1309/**
1310 * ctk_container_child_set_valist:
1311 * @container: a #CtkContainer
1312 * @child: a widget which is a child of @container
1313 * @first_property_name: the name of the first property to set
1314 * @var_args: a %NULL-terminated list of property names and values, starting
1315 * with @first_prop_name
1316 *
1317 * Sets one or more child properties for @child and @container.
1318 **/
1319void
1320ctk_container_child_set_valist (CtkContainer *container,
1321 CtkWidget *child,
1322 const gchar *first_property_name,
1323 va_list var_args)
1324{
1325 GObjectNotifyQueue *nqueue;
1326 const gchar *name;
1327
1328 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1329 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1330
1331 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1332 g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
1333
1334 nqueue = g_object_notify_queue_freeze (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, _ctk_widget_child_property_notify_context);
1335 name = first_property_name;
1336 while (name)
1337 {
1338 GValue value = G_VALUE_INIT{ 0, { { 0 } } };
1339 gchar *error = NULL((void*)0);
1340 GParamSpec *pspec = g_param_spec_pool_lookup (_ctk_widget_child_property_pool,
1341 name,
1342 G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
,
1343 TRUE(!(0)));
1344 if (!pspec)
1345 {
1346 g_warning ("%s: container class '%s' has no child property named '%s'",
1347 G_STRLOC"ctkcontainer.c" ":" "1347",
1348 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
1349 name);
1350 break;
1351 }
1352 if (!(pspec->flags & G_PARAM_WRITABLE))
1353 {
1354 g_warning ("%s: child property '%s' of container class '%s' is not writable",
1355 G_STRLOC"ctkcontainer.c" ":" "1355",
1356 pspec->name,
1357 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
);
1358 break;
1359 }
1360
1361 G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec),do { GTypeValueTable *g_vci_vtab; do { GValue *g_vci_val = (&
value); guint g_vci_flags = (0); const gchar *g_vci_collect_format
; GTypeCValue g_vci_cvalues[(8)] = { { 0, }, }; guint g_vci_n_values
= 0; g_vci_vtab = g_type_value_table_peek ((((((GParamSpec*)
(void *) g_type_check_instance_cast ((GTypeInstance*) ((pspec
)), (((GType) ((19) << (2))))))))->value_type)); g_vci_collect_format
= g_vci_vtab->collect_format; g_vci_val->g_type = ((((
(GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
); while (*g_vci_collect_format) { GTypeCValue *g_vci_cvalue =
g_vci_cvalues + g_vci_n_values++; switch (*g_vci_collect_format
++) { case G_VALUE_COLLECT_INT: g_vci_cvalue->v_int = __builtin_va_arg
((var_args), gint); break; case G_VALUE_COLLECT_LONG: g_vci_cvalue
->v_long = __builtin_va_arg((var_args), glong); break; case
G_VALUE_COLLECT_INT64: g_vci_cvalue->v_int64 = __builtin_va_arg
((var_args), gint64); break; case G_VALUE_COLLECT_DOUBLE: g_vci_cvalue
->v_double = __builtin_va_arg((var_args), gdouble); break;
case G_VALUE_COLLECT_POINTER: g_vci_cvalue->v_pointer = __builtin_va_arg
((var_args), gpointer); break; default: do { g_assertion_message_expr
("Ctk", "ctkcontainer.c", 1362, ((const char*) (__func__)), (
(void*)0)); } while (0); } } *(&error) = g_vci_vtab->collect_value
(g_vci_val, g_vci_n_values, g_vci_cvalues, g_vci_flags); } while
(0); } while (0)
1362 var_args, 0, &error)do { GTypeValueTable *g_vci_vtab; do { GValue *g_vci_val = (&
value); guint g_vci_flags = (0); const gchar *g_vci_collect_format
; GTypeCValue g_vci_cvalues[(8)] = { { 0, }, }; guint g_vci_n_values
= 0; g_vci_vtab = g_type_value_table_peek ((((((GParamSpec*)
(void *) g_type_check_instance_cast ((GTypeInstance*) ((pspec
)), (((GType) ((19) << (2))))))))->value_type)); g_vci_collect_format
= g_vci_vtab->collect_format; g_vci_val->g_type = ((((
(GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2))))))))->value_type
); while (*g_vci_collect_format) { GTypeCValue *g_vci_cvalue =
g_vci_cvalues + g_vci_n_values++; switch (*g_vci_collect_format
++) { case G_VALUE_COLLECT_INT: g_vci_cvalue->v_int = __builtin_va_arg
((var_args), gint); break; case G_VALUE_COLLECT_LONG: g_vci_cvalue
->v_long = __builtin_va_arg((var_args), glong); break; case
G_VALUE_COLLECT_INT64: g_vci_cvalue->v_int64 = __builtin_va_arg
((var_args), gint64); break; case G_VALUE_COLLECT_DOUBLE: g_vci_cvalue
->v_double = __builtin_va_arg((var_args), gdouble); break;
case G_VALUE_COLLECT_POINTER: g_vci_cvalue->v_pointer = __builtin_va_arg
((var_args), gpointer); break; default: do { g_assertion_message_expr
("Ctk", "ctkcontainer.c", 1362, ((const char*) (__func__)), (
(void*)0)); } while (0); } } *(&error) = g_vci_vtab->collect_value
(g_vci_val, g_vci_n_values, g_vci_cvalues, g_vci_flags); } while
(0); } while (0)
;
1363 if (error)
1364 {
1365 g_warning ("%s: %s", G_STRLOC"ctkcontainer.c" ":" "1365", error);
1366 g_free (error);
1367
1368 /* we purposely leak the value here, it might not be
1369 * in a sane state if an error condition occoured
1370 */
1371 break;
1372 }
1373 container_set_child_property (container, child, pspec, &value, nqueue);
1374 g_value_unset (&value);
1375 name = va_arg (var_args, gchar*)__builtin_va_arg(var_args, gchar*);
1376 }
1377 g_object_notify_queue_thaw (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, nqueue);
1378
1379 g_object_unref (container);
1380 g_object_unref (child);
1381}
1382
1383/**
1384 * ctk_container_child_set_property:
1385 * @container: a #CtkContainer
1386 * @child: a widget which is a child of @container
1387 * @property_name: the name of the property to set
1388 * @value: the value to set the property to
1389 *
1390 * Sets a child property for @child and @container.
1391 **/
1392void
1393ctk_container_child_set_property (CtkContainer *container,
1394 CtkWidget *child,
1395 const gchar *property_name,
1396 const GValue *value)
1397{
1398 GObjectNotifyQueue *nqueue;
1399 GParamSpec *pspec;
1400
1401 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1402 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
1403 g_return_if_fail (property_name != NULL)do { if ((property_name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "property_name != NULL")
; return; } } while (0)
;
1404 g_return_if_fail (G_IS_VALUE (value))do { if (((((g_type_check_value ((GValue*) (value))))))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "G_IS_VALUE (value)"); return; } } while (0)
;
1405
1406 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1407 g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
1408
1409 nqueue = g_object_notify_queue_freeze (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, _ctk_widget_child_property_notify_context);
1410 pspec = g_param_spec_pool_lookup (_ctk_widget_child_property_pool, property_name,
1411 G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
, TRUE(!(0)));
1412 if (!pspec)
1413 g_warning ("%s: container class '%s' has no child property named '%s'",
1414 G_STRLOC"ctkcontainer.c" ":" "1414",
1415 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
1416 property_name);
1417 else if (!(pspec->flags & G_PARAM_WRITABLE))
1418 g_warning ("%s: child property '%s' of container class '%s' is not writable",
1419 G_STRLOC"ctkcontainer.c" ":" "1419",
1420 pspec->name,
1421 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
);
1422 else
1423 {
1424 container_set_child_property (container, child, pspec, value, nqueue);
1425 }
1426 g_object_notify_queue_thaw (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, nqueue);
1427 g_object_unref (container);
1428 g_object_unref (child);
1429}
1430
1431/**
1432 * ctk_container_add_with_properties:
1433 * @container: a #CtkContainer
1434 * @widget: a widget to be placed inside @container
1435 * @first_prop_name: the name of the first child property to set
1436 * @...: a %NULL-terminated list of property names and values, starting
1437 * with @first_prop_name
1438 *
1439 * Adds @widget to @container, setting child properties at the same time.
1440 * See ctk_container_add() and ctk_container_child_set() for more details.
1441 */
1442void
1443ctk_container_add_with_properties (CtkContainer *container,
1444 CtkWidget *widget,
1445 const gchar *first_prop_name,
1446 ...)
1447{
1448 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1449 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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 (widget)"); return; } } while (0)
;
1450 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)
;
1451
1452 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1453 g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
1454 ctk_widget_freeze_child_notify (widget);
1455
1456 g_signal_emit (container, container_signals[ADD], 0, widget);
1457 if (_ctk_widget_get_parent (widget))
1458 {
1459 va_list var_args;
1460
1461 va_start (var_args, first_prop_name)__builtin_va_start(var_args, first_prop_name);
1462 ctk_container_child_set_valist (container, widget, first_prop_name, var_args);
1463 va_end (var_args)__builtin_va_end(var_args);
1464 }
1465
1466 ctk_widget_thaw_child_notify (widget);
1467 g_object_unref (widget);
1468 g_object_unref (container);
1469}
1470
1471/**
1472 * ctk_container_child_set:
1473 * @container: a #CtkContainer
1474 * @child: a widget which is a child of @container
1475 * @first_prop_name: the name of the first property to set
1476 * @...: a %NULL-terminated list of property names and values, starting
1477 * with @first_prop_name
1478 *
1479 * Sets one or more child properties for @child and @container.
1480 */
1481void
1482ctk_container_child_set (CtkContainer *container,
1483 CtkWidget *child,
1484 const gchar *first_prop_name,
1485 ...)
1486{
1487 va_list var_args;
1488
1489 va_start (var_args, first_prop_name)__builtin_va_start(var_args, first_prop_name);
1490 ctk_container_child_set_valist (container, child, first_prop_name, var_args);
1491 va_end (var_args)__builtin_va_end(var_args);
1492}
1493
1494/**
1495 * ctk_container_child_get:
1496 * @container: a #CtkContainer
1497 * @child: a widget which is a child of @container
1498 * @first_prop_name: the name of the first property to get
1499 * @...: return location for the first property, followed
1500 * optionally by more name/return location pairs, followed by %NULL
1501 *
1502 * Gets the values of one or more child properties for @child and @container.
1503 */
1504void
1505ctk_container_child_get (CtkContainer *container,
1506 CtkWidget *child,
1507 const gchar *first_prop_name,
1508 ...)
1509{
1510 va_list var_args;
1511
1512 va_start (var_args, first_prop_name)__builtin_va_start(var_args, first_prop_name);
1513 ctk_container_child_get_valist (container, child, first_prop_name, var_args);
1514 va_end (var_args)__builtin_va_end(var_args);
1515}
1516
1517static inline void
1518install_child_property_internal (GType g_type,
1519 guint property_id,
1520 GParamSpec *pspec)
1521{
1522 if (g_param_spec_pool_lookup (_ctk_widget_child_property_pool, pspec->name, g_type, FALSE(0)))
1523 {
1524 g_warning ("Class '%s' already contains a child property named '%s'",
1525 g_type_name (g_type),
1526 pspec->name);
1527 return;
1528 }
1529 g_param_spec_ref (pspec);
1530 g_param_spec_sink (pspec);
1531 PARAM_SPEC_SET_PARAM_ID (pspec, property_id)((pspec)->param_id = (property_id));
1532 g_param_spec_pool_insert (_ctk_widget_child_property_pool, pspec, g_type);
1533}
1534
1535/**
1536 * ctk_container_class_install_child_property:
1537 * @cclass: a #CtkContainerClass
1538 * @property_id: the id for the property
1539 * @pspec: the #GParamSpec for the property
1540 *
1541 * Installs a child property on a container class.
1542 **/
1543void
1544ctk_container_class_install_child_property (CtkContainerClass *cclass,
1545 guint property_id,
1546 GParamSpec *pspec)
1547{
1548 g_return_if_fail (CTK_IS_CONTAINER_CLASS (cclass))do { if (((((__extension__ ({ GTypeClass *__class = (GTypeClass
*) ((cclass)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "CTK_IS_CONTAINER_CLASS (cclass)"
); return; } } while (0)
;
1549 g_return_if_fail (G_IS_PARAM_SPEC (pspec))do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2)))))))))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"G_IS_PARAM_SPEC (pspec)"); return; } } while (0)
;
1550 if (pspec->flags & G_PARAM_WRITABLE)
1551 g_return_if_fail (cclass->set_child_property != NULL)do { if ((cclass->set_child_property != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "cclass->set_child_property != NULL"); return; } } while
(0)
;
1552 if (pspec->flags & G_PARAM_READABLE)
1553 g_return_if_fail (cclass->get_child_property != NULL)do { if ((cclass->get_child_property != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "cclass->get_child_property != NULL"); return; } } while
(0)
;
1554 g_return_if_fail (property_id > 0)do { if ((property_id > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "property_id > 0"); return
; } } while (0)
;
1555 g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0)do { if ((((pspec)->param_id) == 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "PARAM_SPEC_PARAM_ID (pspec) == 0"
); return; } } while (0)
; /* paranoid */
1556 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
1557 g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0)do { if (((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY
)) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0"
); return; } } while (0)
;
1558
1559 install_child_property_internal (G_OBJECT_CLASS_TYPE (cclass)((((GTypeClass*) (cclass))->g_type)), property_id, pspec);
1560}
1561
1562/**
1563 * ctk_container_class_install_child_properties:
1564 * @cclass: a #CtkContainerClass
1565 * @n_pspecs: the length of the #GParamSpec array
1566 * @pspecs: (array length=n_pspecs): the #GParamSpec array defining the new
1567 * child properties
1568 *
1569 * Installs child properties on a container class.
1570 *
1571 * Since: 3.18
1572 */
1573void
1574ctk_container_class_install_child_properties (CtkContainerClass *cclass,
1575 guint n_pspecs,
1576 GParamSpec **pspecs)
1577{
1578 gint i;
1579
1580 g_return_if_fail (CTK_IS_CONTAINER_CLASS (cclass))do { if (((((__extension__ ({ GTypeClass *__class = (GTypeClass
*) ((cclass)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "CTK_IS_CONTAINER_CLASS (cclass)"
); return; } } while (0)
;
1581 g_return_if_fail (n_pspecs > 1)do { if ((n_pspecs > 1)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "n_pspecs > 1"); return
; } } while (0)
;
1582 g_return_if_fail (pspecs[0] == NULL)do { if ((pspecs[0] == ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "pspecs[0] == NULL"); return
; } } while (0)
;
1583
1584 /* we skip the first element of the array as it would have a 0 prop_id */
1585 for (i = 1; i < n_pspecs; i++)
1586 {
1587 GParamSpec *pspec = pspecs[i];
1588
1589 g_return_if_fail (G_IS_PARAM_SPEC (pspec))do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((pspec)), (((GType) ((19) << (2)))))))))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"G_IS_PARAM_SPEC (pspec)"); return; } } while (0)
;
1590 if (pspec->flags & G_PARAM_WRITABLE)
1591 g_return_if_fail (cclass->set_child_property != NULL)do { if ((cclass->set_child_property != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "cclass->set_child_property != NULL"); return; } } while
(0)
;
1592 if (pspec->flags & G_PARAM_READABLE)
1593 g_return_if_fail (cclass->get_child_property != NULL)do { if ((cclass->get_child_property != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "cclass->get_child_property != NULL"); return; } } while
(0)
;
1594 g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0)do { if ((((pspec)->param_id) == 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "PARAM_SPEC_PARAM_ID (pspec) == 0"
); return; } } while (0)
; /* paranoid */
1595 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
1596 g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0)do { if (((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY
)) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0"
); return; } } while (0)
;
1597
1598 install_child_property_internal (G_OBJECT_CLASS_TYPE (cclass)((((GTypeClass*) (cclass))->g_type)), i, pspec);
1599 }
1600}
1601
1602/**
1603 * ctk_container_class_find_child_property:
1604 * @cclass: (type CtkContainerClass): a #CtkContainerClass
1605 * @property_name: the name of the child property to find
1606 *
1607 * Finds a child property of a container class by name.
1608 *
1609 * Returns: (nullable) (transfer none): the #GParamSpec of the child
1610 * property or %NULL if @class has no child property with that
1611 * name.
1612 */
1613GParamSpec*
1614ctk_container_class_find_child_property (GObjectClass *cclass,
1615 const gchar *property_name)
1616{
1617 g_return_val_if_fail (CTK_IS_CONTAINER_CLASS (cclass), NULL)do { if (((((__extension__ ({ GTypeClass *__class = (GTypeClass
*) ((cclass)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "CTK_IS_CONTAINER_CLASS (cclass)"
); return (((void*)0)); } } while (0)
;
1618 g_return_val_if_fail (property_name != NULL, NULL)do { if ((property_name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "property_name != NULL")
; return (((void*)0)); } } while (0)
;
1619
1620 return g_param_spec_pool_lookup (_ctk_widget_child_property_pool,
1621 property_name,
1622 G_OBJECT_CLASS_TYPE (cclass)((((GTypeClass*) (cclass))->g_type)),
1623 TRUE(!(0)));
1624}
1625
1626/**
1627 * ctk_container_class_list_child_properties:
1628 * @cclass: (type CtkContainerClass): a #CtkContainerClass
1629 * @n_properties: location to return the number of child properties found
1630 *
1631 * Returns all child properties of a container class.
1632 *
1633 * Returns: (array length=n_properties) (transfer container):
1634 * a newly allocated %NULL-terminated array of #GParamSpec*.
1635 * The array must be freed with g_free().
1636 */
1637GParamSpec**
1638ctk_container_class_list_child_properties (GObjectClass *cclass,
1639 guint *n_properties)
1640{
1641 GParamSpec **pspecs;
1642 guint n;
1643
1644 g_return_val_if_fail (CTK_IS_CONTAINER_CLASS (cclass), NULL)do { if (((((__extension__ ({ GTypeClass *__class = (GTypeClass
*) ((cclass)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "CTK_IS_CONTAINER_CLASS (cclass)"
); return (((void*)0)); } } while (0)
;
1645
1646 pspecs = g_param_spec_pool_list (_ctk_widget_child_property_pool,
1647 G_OBJECT_CLASS_TYPE (cclass)((((GTypeClass*) (cclass))->g_type)),
1648 &n);
1649 if (n_properties)
1650 *n_properties = n;
1651
1652 return pspecs;
1653}
1654
1655static void
1656ctk_container_add_unimplemented (CtkContainer *container,
1657 CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)))
1658{
1659 g_warning ("CtkContainerClass::add not implemented for '%s'", g_type_name (G_TYPE_FROM_INSTANCE (container)((((GTypeClass*) (((GTypeInstance*) (container))->g_class)
)->g_type))
));
1660}
1661
1662static void
1663ctk_container_remove_unimplemented (CtkContainer *container,
1664 CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)))
1665{
1666 g_warning ("CtkContainerClass::remove not implemented for '%s'", g_type_name (G_TYPE_FROM_INSTANCE (container)((((GTypeClass*) (((GTypeInstance*) (container))->g_class)
)->g_type))
));
1667}
1668
1669static void
1670ctk_container_init (CtkContainer *container)
1671{
1672 CtkContainerPrivate *priv;
1673
1674 container->priv = ctk_container_get_instance_private (container);
1675 priv = container->priv;
1676
1677 priv->focus_child = NULL((void*)0);
1678 priv->border_width = 0;
1679 priv->resize_mode = CTK_RESIZE_PARENT;
1680 priv->reallocate_redraws = FALSE(0);
1681 priv->border_width_set = FALSE(0);
1682}
1683
1684static void
1685ctk_container_destroy (CtkWidget *widget)
1686{
1687 CtkContainer *container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
1688 CtkContainerPrivate *priv = container->priv;
1689
1690 if (priv->restyle_pending)
1691 priv->restyle_pending = FALSE(0);
1692
1693 g_clear_object (&priv->focus_child)do { _Static_assert (sizeof *((&priv->focus_child)) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->focus_child))) _pp = ((&priv->focus_child
)); __typeof__ (*((&priv->focus_child))) _ptr = *_pp; *
_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (
0)
;
1694
1695 /* do this before walking child widgets, to avoid
1696 * removing children from focus chain one by one.
1697 */
1698 if (priv->has_focus_chain)
1699 ctk_container_unset_focus_chain (container);
1700
1701 ctk_container_foreach (container, (CtkCallback) ctk_widget_destroy, NULL((void*)0));
1702
1703 CTK_WIDGET_CLASS (parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((parent_class)), ((ctk_widget_get_type ()))))))
->destroy (widget);
1704}
1705
1706static void
1707ctk_container_set_property (GObject *object,
1708 guint prop_id,
1709 const GValue *value,
1710 GParamSpec *pspec)
1711{
1712 CtkContainer *container = CTK_CONTAINER (object)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_container_get_type ()))))))
;
1713
1714 switch (prop_id)
1715 {
1716 case PROP_BORDER_WIDTH:
1717 ctk_container_set_border_width (container, g_value_get_uint (value));
1718 break;
1719 case PROP_RESIZE_MODE:
1720 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
1721 ctk_container_set_resize_mode (container, g_value_get_enum (value));
1722 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
1723 break;
1724 case PROP_CHILD:
1725 ctk_container_add (container, CTK_WIDGET (g_value_get_object (value))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_value_get_object (value))), ((ctk_widget_get_type ()))
))))
);
1726 break;
1727 default:
1728 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'"
, "ctkcontainer.c", 1728, ("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)
;
1729 break;
1730 }
1731}
1732
1733static void
1734ctk_container_get_property (GObject *object,
1735 guint prop_id,
1736 GValue *value,
1737 GParamSpec *pspec)
1738{
1739 CtkContainer *container = CTK_CONTAINER (object)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_container_get_type ()))))))
;
1740 CtkContainerPrivate *priv = container->priv;
1741
1742 switch (prop_id)
1743 {
1744 case PROP_BORDER_WIDTH:
1745 g_value_set_uint (value, priv->border_width);
1746 break;
1747 case PROP_RESIZE_MODE:
1748 g_value_set_enum (value, priv->resize_mode);
1749 break;
1750 default:
1751 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'"
, "ctkcontainer.c", 1751, ("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)
;
1752 break;
1753 }
1754}
1755
1756gboolean
1757_ctk_container_get_border_width_set (CtkContainer *container)
1758{
1759 CtkContainerPrivate *priv;
1760
1761 g_return_val_if_fail (CTK_IS_CONTAINER (container), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return ((0)); } } while (
0)
;
1762
1763 priv = container->priv;
1764
1765 return priv->border_width_set;
1766}
1767
1768void
1769_ctk_container_set_border_width_set (CtkContainer *container,
1770 gboolean border_width_set)
1771{
1772 CtkContainerPrivate *priv;
1773
1774 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1775
1776 priv = container->priv;
1777
1778 priv->border_width_set = border_width_set ? TRUE(!(0)) : FALSE(0);
1779}
1780
1781/**
1782 * ctk_container_set_border_width:
1783 * @container: a #CtkContainer
1784 * @border_width: amount of blank space to leave outside
1785 * the container. Valid values are in the range 0-65535 pixels.
1786 *
1787 * Sets the border width of the container.
1788 *
1789 * The border width of a container is the amount of space to leave
1790 * around the outside of the container. The only exception to this is
1791 * #CtkWindow; because toplevel windows can’t leave space outside,
1792 * they leave the space inside. The border is added on all sides of
1793 * the container. To add space to only one side, use a specific
1794 * #CtkWidget:margin property on the child widget, for example
1795 * #CtkWidget:margin-top.
1796 **/
1797void
1798ctk_container_set_border_width (CtkContainer *container,
1799 guint border_width)
1800{
1801 CtkContainerPrivate *priv;
1802
1803 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1804
1805 priv = container->priv;
1806
1807 if (priv->border_width != border_width)
1808 {
1809 priv->border_width = border_width;
1810 _ctk_container_set_border_width_set (container, TRUE(!(0)));
1811
1812 g_object_notify_by_pspec (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, container_props[PROP_BORDER_WIDTH]);
1813
1814 if (_ctk_widget_get_realized (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
))
1815 ctk_widget_queue_resize (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
1816 }
1817}
1818
1819/**
1820 * ctk_container_get_border_width:
1821 * @container: a #CtkContainer
1822 *
1823 * Retrieves the border width of the container. See
1824 * ctk_container_set_border_width().
1825 *
1826 * Returns: the current border width
1827 **/
1828guint
1829ctk_container_get_border_width (CtkContainer *container)
1830{
1831 g_return_val_if_fail (CTK_IS_CONTAINER (container), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (0); } } while (0
)
;
1832
1833 return container->priv->border_width;
1834}
1835
1836/**
1837 * ctk_container_add:
1838 * @container: a #CtkContainer
1839 * @widget: a widget to be placed inside @container
1840 *
1841 * Adds @widget to @container. Typically used for simple containers
1842 * such as #CtkWindow, #CtkFrame, or #CtkButton; for more complicated
1843 * layout containers such as #CtkBox or #CtkGrid, this function will
1844 * pick default packing parameters that may not be correct. So
1845 * consider functions such as ctk_box_pack_start() and
1846 * ctk_grid_attach() as an alternative to ctk_container_add() in
1847 * those cases. A widget may be added to only one container at a time;
1848 * you can’t place the same widget inside two different containers.
1849 *
1850 * Note that some containers, such as #CtkScrolledWindow or #CtkListBox,
1851 * may add intermediate children between the added widget and the
1852 * container.
1853 */
1854void
1855ctk_container_add (CtkContainer *container,
1856 CtkWidget *widget)
1857{
1858 CtkWidget *parent;
1859
1860 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1861 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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 (widget)"); return; } } while (0)
;
1862
1863 parent = _ctk_widget_get_parent (widget);
1864
1865 if (parent != NULL((void*)0))
1866 {
1867 g_warning ("Attempting to add a widget with type %s to a container of "
1868 "type %s, but the widget is already inside a container of type %s, "
1869 "please remove the widget from its existing container first." ,
1870 g_type_name (G_OBJECT_TYPE (widget)(((((GTypeClass*) (((GTypeInstance*) (widget))->g_class))->
g_type)))
),
1871 g_type_name (G_OBJECT_TYPE (container)(((((GTypeClass*) (((GTypeInstance*) (container))->g_class
))->g_type)))
),
1872 g_type_name (G_OBJECT_TYPE (parent)(((((GTypeClass*) (((GTypeInstance*) (parent))->g_class))->
g_type)))
));
1873 return;
1874 }
1875
1876 g_signal_emit (container, container_signals[ADD], 0, widget);
1877
1878 _ctk_container_accessible_add (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, widget);
1879}
1880
1881/**
1882 * ctk_container_remove:
1883 * @container: a #CtkContainer
1884 * @widget: a current child of @container
1885 *
1886 * Removes @widget from @container. @widget must be inside @container.
1887 * Note that @container will own a reference to @widget, and that this
1888 * may be the last reference held; so removing a widget from its
1889 * container can destroy that widget. If you want to use @widget
1890 * again, you need to add a reference to it before removing it from
1891 * a container, using g_object_ref(). If you don’t want to use @widget
1892 * again it’s usually more efficient to simply destroy it directly
1893 * using ctk_widget_destroy() since this will remove it from the
1894 * container and help break any circular reference count cycles.
1895 **/
1896void
1897ctk_container_remove (CtkContainer *container,
1898 CtkWidget *widget)
1899{
1900 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1901 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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 (widget)"); return; } } while (0)
;
1902
1903 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
1904 g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
1905
1906 g_signal_emit (container, container_signals[REMOVE], 0, widget);
1907
1908 _ctk_container_accessible_remove (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, widget);
1909
1910 g_object_unref (widget);
1911 g_object_unref (container);
1912}
1913
1914static void
1915ctk_container_real_set_resize_mode (CtkContainer *container,
1916 CtkResizeMode resize_mode)
1917{
1918 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
1919 CtkContainerPrivate *priv = container->priv;
1920
1921 if (_ctk_widget_is_toplevel (widget) &&
1922 resize_mode == CTK_RESIZE_PARENT)
1923 {
1924 resize_mode = CTK_RESIZE_QUEUE;
1925 }
1926
1927 if (priv->resize_mode != resize_mode)
1928 {
1929 priv->resize_mode = resize_mode;
1930
1931 ctk_widget_queue_resize (widget);
1932 g_object_notify_by_pspec (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, container_props[PROP_RESIZE_MODE]);
1933 }
1934}
1935
1936/**
1937 * ctk_container_set_resize_mode:
1938 * @container: a #CtkContainer
1939 * @resize_mode: the new resize mode
1940 *
1941 * Sets the resize mode for the container.
1942 *
1943 * The resize mode of a container determines whether a resize request
1944 * will be passed to the container’s parent, queued for later execution
1945 * or executed immediately.
1946 *
1947 * Deprecated: 3.12: Resize modes are deprecated. They aren’t necessary
1948 * anymore since frame clocks and might introduce obscure bugs if
1949 * used.
1950 **/
1951void
1952ctk_container_set_resize_mode (CtkContainer *container,
1953 CtkResizeMode resize_mode)
1954{
1955 CtkContainerPrivate *priv;
1956
1957 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
1958 g_return_if_fail (resize_mode <= CTK_RESIZE_IMMEDIATE)do { if ((resize_mode <= CTK_RESIZE_IMMEDIATE)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"resize_mode <= CTK_RESIZE_IMMEDIATE"); return; } } while
(0)
;
1959
1960 priv = container->priv;
1961 priv->resize_mode_set = TRUE(!(0));
1962
1963 ctk_container_real_set_resize_mode (container, resize_mode);
1964}
1965
1966void
1967ctk_container_set_default_resize_mode (CtkContainer *container,
1968 CtkResizeMode resize_mode)
1969{
1970 CtkContainerPrivate *priv = container->priv;
1971
1972 if (priv->resize_mode_set)
1973 return;
1974
1975 ctk_container_real_set_resize_mode (container, resize_mode);
1976}
1977
1978/**
1979 * ctk_container_get_resize_mode:
1980 * @container: a #CtkContainer
1981 *
1982 * Returns the resize mode for the container. See
1983 * ctk_container_set_resize_mode ().
1984 *
1985 * Returns: the current resize mode
1986 *
1987 * Deprecated: 3.12: Resize modes are deprecated. They aren’t necessary
1988 * anymore since frame clocks and might introduce obscure bugs if
1989 * used.
1990 **/
1991CtkResizeMode
1992ctk_container_get_resize_mode (CtkContainer *container)
1993{
1994 g_return_val_if_fail (CTK_IS_CONTAINER (container), CTK_RESIZE_PARENT)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (CTK_RESIZE_PARENT
); } } while (0)
;
1995
1996 return container->priv->resize_mode;
1997}
1998
1999/**
2000 * ctk_container_set_reallocate_redraws:
2001 * @container: a #CtkContainer
2002 * @needs_redraws: the new value for the container’s @reallocate_redraws flag
2003 *
2004 * Sets the @reallocate_redraws flag of the container to the given value.
2005 *
2006 * Containers requesting reallocation redraws get automatically
2007 * redrawn if any of their children changed allocation.
2008 *
2009 * Deprecated: 3.14: Call ctk_widget_queue_draw() in your size_allocate handler.
2010 **/
2011void
2012ctk_container_set_reallocate_redraws (CtkContainer *container,
2013 gboolean needs_redraws)
2014{
2015 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2016
2017 container->priv->reallocate_redraws = needs_redraws ? TRUE(!(0)) : FALSE(0);
2018}
2019
2020static gboolean
2021ctk_container_needs_idle_sizer (CtkContainer *container)
2022{
2023 CtkContainerPrivate *priv = container->priv;
2024
2025 if (priv->resize_mode == CTK_RESIZE_PARENT)
2026 return FALSE(0);
2027
2028 if (container->priv->restyle_pending)
2029 return TRUE(!(0));
2030
2031 if (priv->resize_mode == CTK_RESIZE_IMMEDIATE)
2032 return FALSE(0);
2033
2034 return ctk_widget_needs_allocate (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
2035}
2036
2037static void
2038ctk_container_idle_sizer (CdkFrameClock *clock,
2039 CtkContainer *container)
2040{
2041 /* We validate the style contexts in a single loop before even trying
2042 * to handle resizes instead of doing validations inline.
2043 * This is mostly necessary for compatibility reasons with old code,
2044 * because both style_updated and size_allocate functions often change
2045 * styles and so could cause infinite loops in this function.
2046 *
2047 * It's important to note that even an invalid style context returns
2048 * sane values. So the result of an invalid style context will never be
2049 * a program crash, but only a wrong layout or rendering.
2050 */
2051 if (container->priv->restyle_pending)
2052 {
2053 container->priv->restyle_pending = FALSE(0);
2054 ctk_css_node_validate (ctk_widget_get_css_node (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
));
2055 }
2056
2057 /* we may be invoked with a container_resize_queue of NULL, because
2058 * queue_resize could have been adding an extra idle function while
2059 * the queue still got processed. we better just ignore such case
2060 * than trying to explicitly work around them with some extra flags,
2061 * since it doesn't cause any actual harm.
2062 */
2063 if (ctk_widget_needs_allocate (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
))
2064 {
2065 ctk_container_check_resize (container);
2066 }
2067
2068 if (!ctk_container_needs_idle_sizer (container))
2069 {
2070 _ctk_container_stop_idle_sizer (container);
2071 }
2072 else
2073 {
2074 cdk_frame_clock_request_phase (clock,
2075 CDK_FRAME_CLOCK_PHASE_LAYOUT);
2076 }
2077}
2078
2079static void
2080ctk_container_start_idle_sizer (CtkContainer *container)
2081{
2082 CdkFrameClock *clock;
2083
2084 if (container->priv->resize_handler != 0)
2085 return;
2086
2087 clock = ctk_widget_get_frame_clock (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
2088 if (clock == NULL((void*)0))
2089 return;
2090
2091 if (!CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
->priv->frameclock_connected)
2092 return;
2093
2094 container->priv->resize_clock = clock;
2095 container->priv->resize_handler = g_signal_connect (clock, "layout",g_signal_connect_data ((clock), ("layout"), (((GCallback) (ctk_container_idle_sizer
))), (container), ((void*)0), (GConnectFlags) 0)
2096 G_CALLBACK (ctk_container_idle_sizer), container)g_signal_connect_data ((clock), ("layout"), (((GCallback) (ctk_container_idle_sizer
))), (container), ((void*)0), (GConnectFlags) 0)
;
2097 cdk_frame_clock_request_phase (clock,
2098 CDK_FRAME_CLOCK_PHASE_LAYOUT);
2099}
2100
2101void
2102_ctk_container_stop_idle_sizer (CtkContainer *container)
2103{
2104 if (container->priv->resize_handler == 0)
2105 return;
2106
2107 g_signal_handler_disconnect (container->priv->resize_clock,
2108 container->priv->resize_handler);
2109 container->priv->resize_handler = 0;
2110 container->priv->resize_clock = NULL((void*)0);
2111}
2112
2113void
2114ctk_container_queue_resize_handler (CtkContainer *container)
2115{
2116 CtkWidget *widget;
2117
2118 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
2119 g_return_if_fail (CTK_IS_RESIZE_CONTAINER (container))do { if ((((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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; })))) &&
(ctk_container_get_resize_mode (((((CtkContainer*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((ctk_container_get_type ()
))))))) != CTK_RESIZE_PARENT)))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_IS_RESIZE_CONTAINER (container)"
); return; } } while (0)
;
2120 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
2121
2122 widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
2123
2124 if (_ctk_widget_get_visible (widget) &&
2125 (_ctk_widget_is_toplevel (widget) ||
2126 _ctk_widget_get_realized (widget)))
2127 {
2128 switch (container->priv->resize_mode)
2129 {
2130 case CTK_RESIZE_QUEUE:
2131 if (ctk_widget_needs_allocate (widget))
2132 ctk_container_start_idle_sizer (container);
2133 break;
2134
2135 case CTK_RESIZE_IMMEDIATE:
2136 ctk_container_check_resize (container);
2137 break;
2138
2139 case CTK_RESIZE_PARENT:
2140 default:
2141 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcontainer.c", 2141,
((const char*) (__func__)), ((void*)0)); } while (0)
;
2142 break;
2143 }
2144 }
2145}
2146
2147void
2148_ctk_container_queue_restyle (CtkContainer *container)
2149{
2150 CtkContainerPrivate *priv;
2151
2152 g_return_if_fail (CTK_CONTAINER (container))do { if ((((((CtkContainer*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((ctk_container_get_type ()
)))))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_CONTAINER (container)"); return; } } while
(0)
;
2153
2154 priv = container->priv;
2155
2156 if (priv->restyle_pending)
2157 return;
2158
2159 ctk_container_start_idle_sizer (container);
2160 priv->restyle_pending = TRUE(!(0));
2161}
2162
2163void
2164_ctk_container_maybe_start_idle_sizer (CtkContainer *container)
2165{
2166 if (ctk_container_needs_idle_sizer (container))
2167 ctk_container_start_idle_sizer (container);
2168}
2169
2170void
2171ctk_container_check_resize (CtkContainer *container)
2172{
2173 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2174
2175 g_signal_emit (container, container_signals[CHECK_RESIZE], 0);
2176}
2177
2178static void
2179ctk_container_real_check_resize (CtkContainer *container)
2180{
2181 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
2182 CtkAllocation allocation;
2183 CtkRequisition requisition;
2184 int baseline;
2185
2186 if (_ctk_widget_get_alloc_needed (widget))
2187 {
2188 ctk_widget_get_preferred_size (widget, &requisition, NULL((void*)0));
2189 ctk_widget_get_allocated_size (widget, &allocation, &baseline);
2190
2191 if (requisition.width > allocation.width ||
2192 requisition.height > allocation.height)
2193 {
2194 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
2195 if (CTK_IS_RESIZE_CONTAINER (container)((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*)
((container)); GType __t = ((ctk_container_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; })))) &&
(ctk_container_get_resize_mode (((((CtkContainer*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((ctk_container_get_type ()
))))))) != CTK_RESIZE_PARENT))
)
2196 {
2197 ctk_widget_size_allocate (widget, &allocation);
2198 }
2199 else
2200 ctk_widget_queue_resize (widget);
2201 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
2202 }
2203 else
2204 {
2205 ctk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
2206 }
2207 }
2208 else
2209 {
2210 ctk_widget_ensure_allocate (widget);
2211 }
2212}
2213
2214/* The container hasn't changed size but one of its children
2215 * queued a resize request. Which means that the allocation
2216 * is not sufficient for the requisition of some child.
2217 * We’ve already performed a size request at this point,
2218 * so we simply need to reallocate and let the allocation
2219 * trickle down via CTK_WIDGET_ALLOC_NEEDED flags.
2220 */
2221/**
2222 * ctk_container_resize_children:
2223 * @container: a #CtkContainer
2224 *
2225 * Deprecated: 3.10
2226 **/
2227void
2228ctk_container_resize_children (CtkContainer *container)
2229{
2230 CtkAllocation allocation;
2231 CtkWidget *widget;
2232 gint baseline;
2233
2234 /* resizing invariants:
2235 * toplevels have *always* resize_mode != CTK_RESIZE_PARENT set.
2236 * containers that have an idle sizer pending must be flagged with
2237 * RESIZE_PENDING.
2238 */
2239 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2240
2241 widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
2242 ctk_widget_get_allocated_size (widget, &allocation, &baseline);
2243
2244 ctk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
2245}
2246
2247static void
2248ctk_container_adjust_size_request (CtkWidget *widget,
2249 CtkOrientation orientation,
2250 gint *minimum_size,
2251 gint *natural_size)
2252{
2253 CtkContainer *container;
2254
2255 container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2256
2257 if (CTK_CONTAINER_GET_CLASS (widget)((((CtkContainerClass*) (((GTypeInstance*) ((widget)))->g_class
))))
->_handle_border_width)
2258 {
2259 int border_width;
2260
2261 border_width = container->priv->border_width;
2262
2263 *minimum_size += border_width * 2;
2264 *natural_size += border_width * 2;
2265 }
2266
2267 /* chain up last so ctk_widget_set_size_request() values
2268 * will have a chance to overwrite our border width.
2269 */
2270 parent_class->adjust_size_request (widget, orientation,
2271 minimum_size, natural_size);
2272}
2273
2274static void
2275ctk_container_adjust_baseline_request (CtkWidget *widget,
2276 gint *minimum_baseline,
2277 gint *natural_baseline)
2278{
2279 CtkContainer *container;
2280
2281 container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2282
2283 if (CTK_CONTAINER_GET_CLASS (widget)((((CtkContainerClass*) (((GTypeInstance*) ((widget)))->g_class
))))
->_handle_border_width)
2284 {
2285 int border_width;
2286
2287 border_width = container->priv->border_width;
2288
2289 *minimum_baseline += border_width;
2290 *natural_baseline += border_width;
2291 }
2292
2293 parent_class->adjust_baseline_request (widget, minimum_baseline, natural_baseline);
2294}
2295
2296static void
2297ctk_container_adjust_size_allocation (CtkWidget *widget,
2298 CtkOrientation orientation,
2299 gint *minimum_size,
2300 gint *natural_size,
2301 gint *allocated_pos,
2302 gint *allocated_size)
2303{
2304 CtkContainer *container;
2305 int border_width;
2306
2307 container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2308
2309 if (CTK_CONTAINER_GET_CLASS (widget)((((CtkContainerClass*) (((GTypeInstance*) ((widget)))->g_class
))))
->_handle_border_width)
2310 {
2311 border_width = container->priv->border_width;
2312
2313 *allocated_size -= border_width * 2;
2314 *allocated_pos += border_width;
2315 *minimum_size -= border_width * 2;
2316 *natural_size -= border_width * 2;
2317 }
2318
2319 /* Chain up to CtkWidgetClass *after* removing our border width from
2320 * the proposed allocation size. This is because it's possible that the
2321 * widget was allocated more space than it needs in a said orientation,
2322 * if CtkWidgetClass does any alignments and thus limits the size to the
2323 * natural size... then we need that to be done *after* removing any margins
2324 * and padding values.
2325 */
2326 parent_class->adjust_size_allocation (widget, orientation,
2327 minimum_size, natural_size, allocated_pos,
2328 allocated_size);
2329}
2330
2331static void
2332ctk_container_adjust_baseline_allocation (CtkWidget *widget,
2333 gint *baseline)
2334{
2335 CtkContainer *container;
2336 int border_width;
2337
2338 container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2339
2340 if (CTK_CONTAINER_GET_CLASS (widget)((((CtkContainerClass*) (((GTypeInstance*) ((widget)))->g_class
))))
->_handle_border_width)
2341 {
2342 border_width = container->priv->border_width;
2343
2344 if (*baseline >= 0)
2345 *baseline -= border_width;
2346 }
2347
2348 parent_class->adjust_baseline_allocation (widget, baseline);
2349}
2350
2351
2352typedef struct {
2353 gint hfw;
2354 gint wfh;
2355} RequestModeCount;
2356
2357static void
2358count_request_modes (CtkWidget *widget,
2359 RequestModeCount *count)
2360{
2361 CtkSizeRequestMode mode = ctk_widget_get_request_mode (widget);
2362
2363 switch (mode)
2364 {
2365 case CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH:
2366 count->hfw++;
2367 break;
2368 case CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT:
2369 count->wfh++;
2370 break;
2371 case CTK_SIZE_REQUEST_CONSTANT_SIZE:
2372 default:
2373 break;
2374 }
2375}
2376
2377static CtkSizeRequestMode
2378ctk_container_get_request_mode (CtkWidget *widget)
2379{
2380 CtkContainer *container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2381 RequestModeCount count = { 0, 0 };
2382
2383 ctk_container_forall (container, (CtkCallback)count_request_modes, &count);
2384
2385 if (!count.hfw && !count.wfh)
2386 return CTK_SIZE_REQUEST_CONSTANT_SIZE;
2387 else
2388 return count.wfh > count.hfw ?
2389 CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
2390 CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
2391}
2392
2393/**
2394 * ctk_container_class_handle_border_width:
2395 * @klass: the class struct of a #CtkContainer subclass
2396 *
2397 * Modifies a subclass of #CtkContainerClass to automatically add and
2398 * remove the border-width setting on CtkContainer. This allows the
2399 * subclass to ignore the border width in its size request and
2400 * allocate methods. The intent is for a subclass to invoke this
2401 * in its class_init function.
2402 *
2403 * ctk_container_class_handle_border_width() is necessary because it
2404 * would break API too badly to make this behavior the default. So
2405 * subclasses must “opt in” to the parent class handling border_width
2406 * for them.
2407 */
2408void
2409ctk_container_class_handle_border_width (CtkContainerClass *klass)
2410{
2411 g_return_if_fail (CTK_IS_CONTAINER_CLASS (klass))do { if (((((__extension__ ({ GTypeClass *__class = (GTypeClass
*) ((klass)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "CTK_IS_CONTAINER_CLASS (klass)"
); return; } } while (0)
;
2412
2413 klass->_handle_border_width = TRUE(!(0));
2414}
2415
2416/**
2417 * ctk_container_forall: (virtual forall)
2418 * @container: a #CtkContainer
2419 * @callback: (scope call) (closure callback_data): a callback
2420 * @callback_data: callback user data
2421 *
2422 * Invokes @callback on each direct child of @container, including
2423 * children that are considered “internal” (implementation details
2424 * of the container). “Internal” children generally weren’t added
2425 * by the user of the container, but were added by the container
2426 * implementation itself.
2427 *
2428 * Most applications should use ctk_container_foreach(), rather
2429 * than ctk_container_forall().
2430 **/
2431void
2432ctk_container_forall (CtkContainer *container,
2433 CtkCallback callback,
2434 gpointer callback_data)
2435{
2436 CtkContainerClass *class;
2437
2438 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2439 g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "callback != NULL"); return
; } } while (0)
;
2440
2441 class = CTK_CONTAINER_GET_CLASS (container)((((CtkContainerClass*) (((GTypeInstance*) ((container)))->
g_class))))
;
2442
2443 if (class->forall)
2444 class->forall (container, TRUE(!(0)), callback, callback_data);
2445}
2446
2447/**
2448 * ctk_container_foreach:
2449 * @container: a #CtkContainer
2450 * @callback: (scope call): a callback
2451 * @callback_data: callback user data
2452 *
2453 * Invokes @callback on each non-internal child of @container.
2454 * See ctk_container_forall() for details on what constitutes
2455 * an “internal” child. For all practical purposes, this function
2456 * should iterate over precisely those child widgets that were
2457 * added to the container by the application with explicit add()
2458 * calls.
2459 *
2460 * It is permissible to remove the child from the @callback handler.
2461 *
2462 * Most applications should use ctk_container_foreach(),
2463 * rather than ctk_container_forall().
2464 **/
2465void
2466ctk_container_foreach (CtkContainer *container,
2467 CtkCallback callback,
2468 gpointer callback_data)
2469{
2470 CtkContainerClass *class;
2471
2472 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2473 g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "callback != NULL"); return
; } } while (0)
;
2474
2475 class = CTK_CONTAINER_GET_CLASS (container)((((CtkContainerClass*) (((GTypeInstance*) ((container)))->
g_class))))
;
2476
2477 if (class->forall)
2478 class->forall (container, FALSE(0), callback, callback_data);
2479}
2480
2481/**
2482 * ctk_container_set_focus_child:
2483 * @container: a #CtkContainer
2484 * @child: (allow-none): a #CtkWidget, or %NULL
2485 *
2486 * Sets, or unsets if @child is %NULL, the focused child of @container.
2487 *
2488 * This function emits the CtkContainer::set_focus_child signal of
2489 * @container. Implementations of #CtkContainer can override the
2490 * default behaviour by overriding the class closure of this signal.
2491 *
2492 * This is function is mostly meant to be used by widgets. Applications can use
2493 * ctk_widget_grab_focus() to manually set the focus to a specific widget.
2494 */
2495void
2496ctk_container_set_focus_child (CtkContainer *container,
2497 CtkWidget *child)
2498{
2499 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2500 if (child)
2501 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
2502
2503 g_signal_emit (container, container_signals[SET_FOCUS_CHILD], 0, child);
2504}
2505
2506/**
2507 * ctk_container_get_focus_child:
2508 * @container: a #CtkContainer
2509 *
2510 * Returns the current focus child widget inside @container. This is not the
2511 * currently focused widget. That can be obtained by calling
2512 * ctk_window_get_focus().
2513 *
2514 * Returns: (nullable) (transfer none): The child widget which will receive the
2515 * focus inside @container when the @container is focused,
2516 * or %NULL if none is set.
2517 *
2518 * Since: 2.14
2519 **/
2520CtkWidget *
2521ctk_container_get_focus_child (CtkContainer *container)
2522{
2523 g_return_val_if_fail (CTK_IS_CONTAINER (container), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (((void*)0)); } }
while (0)
;
2524
2525 return container->priv->focus_child;
2526}
2527
2528/**
2529 * ctk_container_get_children:
2530 * @container: a #CtkContainer
2531 *
2532 * Returns the container’s non-internal children. See
2533 * ctk_container_forall() for details on what constitutes an "internal" child.
2534 *
2535 * Returns: (element-type CtkWidget) (transfer container): a newly-allocated list of the container’s non-internal children.
2536 **/
2537GList*
2538ctk_container_get_children (CtkContainer *container)
2539{
2540 GList *children = NULL((void*)0);
2541
2542 ctk_container_foreach (container,
2543 ctk_container_children_callback,
2544 &children);
2545
2546 return g_list_reverse (children);
2547}
2548
2549static void
2550ctk_container_child_position_callback (CtkWidget *widget,
2551 gpointer client_data)
2552{
2553 struct {
2554 CtkWidget *child;
2555 guint i;
2556 guint index;
2557 } *data = client_data;
2558
2559 data->i++;
2560 if (data->child == widget)
2561 data->index = data->i;
2562}
2563
2564static gchar*
2565ctk_container_child_default_composite_name (CtkContainer *container,
2566 CtkWidget *child)
2567{
2568 struct {
2569 CtkWidget *child;
2570 guint i;
2571 guint index;
2572 } data;
2573 gchar *name;
2574
2575 /* fallback implementation */
2576 data.child = child;
2577 data.i = 0;
2578 data.index = 0;
2579 ctk_container_forall (container,
2580 ctk_container_child_position_callback,
2581 &data);
2582
2583 name = g_strdup_printf ("%s-%u",
2584 g_type_name (G_TYPE_FROM_INSTANCE (child)((((GTypeClass*) (((GTypeInstance*) (child))->g_class))->
g_type))
),
2585 data.index);
2586
2587 return name;
2588}
2589
2590gchar*
2591_ctk_container_child_composite_name (CtkContainer *container,
2592 CtkWidget *child)
2593{
2594 gboolean composite_child;
2595
2596 g_return_val_if_fail (CTK_IS_CONTAINER (container), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (((void*)0)); } }
while (0)
;
2597 g_return_val_if_fail (CTK_IS_WIDGET (child), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return (((void*)0)); } } while (
0)
;
2598 g_return_val_if_fail (_ctk_widget_get_parent (child) == CTK_WIDGET (container), NULL)do { if ((_ctk_widget_get_parent (child) == ((((CtkWidget*) (
void *) g_type_check_instance_cast ((GTypeInstance*) ((container
)), ((ctk_widget_get_type ())))))))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "_ctk_widget_get_parent (child) == CTK_WIDGET (container)"
); return (((void*)0)); } } while (0)
;
2599
2600 g_object_get (child, "composite-child", &composite_child, NULL((void*)0));
2601 if (composite_child)
2602 {
2603 static GQuark quark_composite_name = 0;
2604 gchar *name;
2605
2606 if (!quark_composite_name)
2607 quark_composite_name = g_quark_from_static_string ("ctk-composite-name");
2608
2609 name = g_object_get_qdata (G_OBJECT (child)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), (((GType) ((20) << (2))))))))
, quark_composite_name);
2610 if (!name)
2611 {
2612 CtkContainerClass *class;
2613
2614 class = CTK_CONTAINER_GET_CLASS (container)((((CtkContainerClass*) (((GTypeInstance*) ((container)))->
g_class))))
;
2615 if (class->composite_name)
2616 name = class->composite_name (container, child);
2617 }
2618 else
2619 name = g_strdup (name)g_strdup_inline (name);
2620
2621 return name;
2622 }
2623
2624 return NULL((void*)0);
2625}
2626
2627typedef struct {
2628 gboolean hexpand;
2629 gboolean vexpand;
2630} ComputeExpandData;
2631
2632static void
2633ctk_container_compute_expand_callback (CtkWidget *widget,
2634 gpointer client_data)
2635{
2636 ComputeExpandData *data = client_data;
2637
2638 /* note that we don't get_expand on the child if we already know we
2639 * have to expand, so we only recurse into children until we find
2640 * one that expands and then we basically don't do any more
2641 * work. This means that we can leave some children in a
2642 * need_compute_expand state, which is fine, as long as CtkWidget
2643 * doesn't rely on an invariant that "if a child has
2644 * need_compute_expand, its parents also do"
2645 *
2646 * ctk_widget_compute_expand() always returns FALSE if the
2647 * child is !visible so that's taken care of.
2648 */
2649 data->hexpand = data->hexpand ||
2650 ctk_widget_compute_expand (widget, CTK_ORIENTATION_HORIZONTAL);
2651
2652 data->vexpand = data->vexpand ||
2653 ctk_widget_compute_expand (widget, CTK_ORIENTATION_VERTICAL);
2654}
2655
2656static void
2657ctk_container_compute_expand (CtkWidget *widget,
2658 gboolean *hexpand_p,
2659 gboolean *vexpand_p)
2660{
2661 ComputeExpandData data;
2662
2663 data.hexpand = FALSE(0);
2664 data.vexpand = FALSE(0);
2665
2666 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
2667 ctk_container_compute_expand_callback,
2668 &data);
2669
2670 *hexpand_p = data.hexpand;
2671 *vexpand_p = data.vexpand;
2672}
2673
2674static void
2675ctk_container_real_set_focus_child (CtkContainer *container,
2676 CtkWidget *child)
2677{
2678 CtkContainerPrivate *priv;
2679
2680 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
2681 g_return_if_fail (child == NULL || CTK_IS_WIDGET (child))do { if ((child == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((child)); 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__)), "child == NULL || CTK_IS_WIDGET (child)"
); return; } } while (0)
;
2682
2683 priv = container->priv;
2684
2685 if (child != priv->focus_child)
2686 {
2687 if (priv->focus_child)
2688 g_object_unref (priv->focus_child);
2689
2690 priv->focus_child = child;
2691
2692 if (priv->focus_child)
2693 g_object_ref (priv->focus_child)((__typeof__ (priv->focus_child)) (g_object_ref) (priv->
focus_child))
;
2694 }
2695
2696 /* Check for h/v adjustments and scroll to show the focus child if possible */
2697 if (priv->focus_child)
2698 {
2699 CtkAdjustment *hadj;
2700 CtkAdjustment *vadj;
2701 CtkAllocation allocation;
2702 CtkWidget *focus_child;
2703 gint x, y;
2704
2705 hadj = g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, hadjustment_key_id);
2706 vadj = g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, vadjustment_key_id);
2707 if (hadj || vadj)
2708 {
2709 focus_child = priv->focus_child;
2710 while (CTK_IS_CONTAINER (focus_child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(focus_child)); GType __t = ((ctk_container_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; }))))
&& ctk_container_get_focus_child (CTK_CONTAINER (focus_child)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((focus_child)), ((ctk_container_get_type ()))))))
))
2711 {
2712 focus_child = ctk_container_get_focus_child (CTK_CONTAINER (focus_child)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((focus_child)), ((ctk_container_get_type ()))))))
);
2713 }
2714
2715 if (!ctk_widget_translate_coordinates (focus_child, priv->focus_child,
2716 0, 0, &x, &y))
2717 return;
2718
2719 _ctk_widget_get_allocation (priv->focus_child, &allocation);
2720 x += allocation.x;
2721 y += allocation.y;
2722
2723 _ctk_widget_get_allocation (focus_child, &allocation);
2724
2725 if (vadj)
2726 ctk_adjustment_clamp_page (vadj, y, y + allocation.height);
2727
2728 if (hadj)
2729 ctk_adjustment_clamp_page (hadj, x, x + allocation.width);
2730 }
2731 }
2732}
2733
2734static GList*
2735get_focus_chain (CtkContainer *container)
2736{
2737 return g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, quark_focus_chain);
2738}
2739
2740/* same as ctk_container_get_children, except it includes internals
2741 */
2742GList *
2743ctk_container_get_all_children (CtkContainer *container)
2744{
2745 GList *children = NULL((void*)0);
2746
2747 ctk_container_forall (container,
2748 ctk_container_children_callback,
2749 &children);
2750
2751 return children;
2752}
2753
2754static CtkWidgetPath *
2755ctk_container_real_get_path_for_child (CtkContainer *container,
2756 CtkWidget *child)
2757{
2758 CtkWidgetPath *path;
2759 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
2760
2761 path = _ctk_widget_create_path (widget);
2762
2763 ctk_widget_path_append_for_widget (path, child);
2764
2765 return path;
2766}
2767
2768static gboolean
2769ctk_container_focus (CtkWidget *widget,
2770 CtkDirectionType direction)
2771{
2772 GList *children;
2773 GList *sorted_children;
2774 gint return_val;
2775 CtkContainer *container;
2776 CtkContainerPrivate *priv;
2777
2778 g_return_val_if_fail (CTK_IS_CONTAINER (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_container_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_CONTAINER (widget)"); return ((0)); } } while (0)
;
2779
2780 container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
2781 priv = container->priv;
2782
2783 return_val = FALSE(0);
2784
2785 if (ctk_widget_get_can_focus (widget))
2786 {
2787 if (!ctk_widget_has_focus (widget))
2788 {
2789 ctk_widget_grab_focus (widget);
2790 return_val = TRUE(!(0));
2791 }
2792 }
2793 else
2794 {
2795 /* Get a list of the containers children, allowing focus
2796 * chain to override.
2797 */
2798 if (priv->has_focus_chain)
2799 children = g_list_copy (get_focus_chain (container));
2800 else
2801 children = ctk_container_get_all_children (container);
2802
2803 if (priv->has_focus_chain &&
2804 (direction == CTK_DIR_TAB_FORWARD ||
2805 direction == CTK_DIR_TAB_BACKWARD))
2806 {
2807 sorted_children = g_list_copy (children);
2808
2809 if (direction == CTK_DIR_TAB_BACKWARD)
2810 sorted_children = g_list_reverse (sorted_children);
2811 }
2812 else
2813 sorted_children = _ctk_container_focus_sort (container, children, direction, NULL((void*)0));
2814
2815 return_val = ctk_container_focus_move (container, sorted_children, direction);
2816
2817 g_list_free (sorted_children);
2818 g_list_free (children);
2819 }
2820
2821 return return_val;
2822}
2823
2824static gint
2825tab_compare (gconstpointer a,
2826 gconstpointer b,
2827 gpointer data)
2828{
2829 CtkAllocation child1_allocation, child2_allocation;
2830 const CtkWidget *child1 = a;
2831 const CtkWidget *child2 = b;
2832 CtkTextDirection text_direction = GPOINTER_TO_INT (data)((gint) (glong) (data));
2833 gint y1, y2;
2834
2835 _ctk_widget_get_allocation ((CtkWidget *) child1, &child1_allocation);
2836 _ctk_widget_get_allocation ((CtkWidget *) child2, &child2_allocation);
2837
2838 y1 = child1_allocation.y + child1_allocation.height / 2;
2839 y2 = child2_allocation.y + child2_allocation.height / 2;
2840
2841 if (y1 == y2)
2842 {
2843 gint x1 = child1_allocation.x + child1_allocation.width / 2;
2844 gint x2 = child2_allocation.x + child2_allocation.width / 2;
2845
2846 if (text_direction == CTK_TEXT_DIR_RTL)
2847 return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1);
2848 else
2849 return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1);
2850 }
2851 else
2852 return (y1 < y2) ? -1 : 1;
2853}
2854
2855static GList *
2856ctk_container_focus_sort_tab (CtkContainer *container,
2857 GList *children,
2858 CtkDirectionType direction,
2859 CtkWidget *old_focus G_GNUC_UNUSED__attribute__ ((__unused__)))
2860{
2861 CtkTextDirection text_direction = _ctk_widget_get_direction (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
2862 children = g_list_sort_with_data (children, tab_compare, GINT_TO_POINTER (text_direction)((gpointer) (glong) (text_direction)));
2863
2864 /* if we are going backwards then reverse the order
2865 * of the children.
2866 */
2867 if (direction == CTK_DIR_TAB_BACKWARD)
2868 children = g_list_reverse (children);
2869
2870 return children;
2871}
2872
2873/* Get coordinates of @widget's allocation with respect to
2874 * allocation of @container.
2875 */
2876static gboolean
2877get_allocation_coords (CtkContainer *container,
2878 CtkWidget *widget,
2879 CdkRectangle *allocation)
2880{
2881 ctk_widget_get_allocation (widget, allocation);
2882
2883 return ctk_widget_translate_coordinates (widget, CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
,
2884 0, 0, &allocation->x, &allocation->y);
2885}
2886
2887/* Look for a child in @children that is intermediate between
2888 * the focus widget and container. This widget, if it exists,
2889 * acts as the starting widget for focus navigation.
2890 */
2891static CtkWidget *
2892find_old_focus (CtkContainer *container,
2893 GList *children)
2894{
2895 GList *tmp_list = children;
2896 while (tmp_list)
2897 {
2898 CtkWidget *child = tmp_list->data;
2899 CtkWidget *widget = child;
2900
2901 while (widget && widget != (CtkWidget *)container)
2902 {
2903 CtkWidget *parent;
2904
2905 parent = _ctk_widget_get_parent (widget);
2906
2907 if (parent && (ctk_container_get_focus_child (CTK_CONTAINER (parent)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((parent)), ((ctk_container_get_type ()))))))
) != widget))
2908 goto next;
2909
2910 widget = parent;
2911 }
2912
2913 return child;
2914
2915 next:
2916 tmp_list = tmp_list->next;
2917 }
2918
2919 return NULL((void*)0);
2920}
2921
2922static gboolean
2923old_focus_coords (CtkContainer *container,
2924 CdkRectangle *old_focus_rect)
2925{
2926 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
2927 CtkWidget *toplevel = _ctk_widget_get_toplevel (widget);
2928 CtkWidget *old_focus;
2929
2930 if (CTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((ctk_window_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; }))))
)
2931 {
2932 old_focus = ctk_window_get_focus (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
2933 if (old_focus)
2934 return get_allocation_coords (container, old_focus, old_focus_rect);
2935 }
2936
2937 return FALSE(0);
2938}
2939
2940typedef struct _CompareInfo CompareInfo;
2941
2942struct _CompareInfo
2943{
2944 CtkContainer *container;
2945 gint x;
2946 gint y;
2947 gboolean reverse;
2948};
2949
2950static gint
2951up_down_compare (gconstpointer a,
2952 gconstpointer b,
2953 gpointer data)
2954{
2955 CdkRectangle allocation1;
2956 CdkRectangle allocation2;
2957 CompareInfo *compare = data;
2958 gint y1, y2;
2959
2960 get_allocation_coords (compare->container, (CtkWidget *)a, &allocation1);
2961 get_allocation_coords (compare->container, (CtkWidget *)b, &allocation2);
2962
2963 y1 = allocation1.y + allocation1.height / 2;
2964 y2 = allocation2.y + allocation2.height / 2;
2965
2966 if (y1 == y2)
2967 {
2968 gint x1 = abs (allocation1.x + allocation1.width / 2 - compare->x);
2969 gint x2 = abs (allocation2.x + allocation2.width / 2 - compare->x);
2970
2971 if (compare->reverse)
2972 return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1);
2973 else
2974 return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1);
2975 }
2976 else
2977 return (y1 < y2) ? -1 : 1;
2978}
2979
2980static GList *
2981ctk_container_focus_sort_up_down (CtkContainer *container,
2982 GList *children,
2983 CtkDirectionType direction,
2984 CtkWidget *old_focus)
2985{
2986 CompareInfo compare;
2987 GList *tmp_list;
2988 CdkRectangle old_allocation;
2989
2990 compare.container = container;
2991 compare.reverse = (direction == CTK_DIR_UP);
2992
2993 if (!old_focus)
2994 old_focus = find_old_focus (container, children);
2995
2996 if (old_focus && get_allocation_coords (container, old_focus, &old_allocation))
2997 {
2998 gint compare_x1;
2999 gint compare_x2;
3000 gint compare_y;
3001
3002 /* Delete widgets from list that don't match minimum criteria */
3003
3004 compare_x1 = old_allocation.x;
3005 compare_x2 = old_allocation.x + old_allocation.width;
3006
3007 if (direction == CTK_DIR_UP)
3008 compare_y = old_allocation.y;
3009 else
3010 compare_y = old_allocation.y + old_allocation.height;
3011
3012 tmp_list = children;
3013 while (tmp_list)
3014 {
3015 CtkWidget *child = tmp_list->data;
3016 GList *next = tmp_list->next;
3017 gint child_x1, child_x2;
3018 CdkRectangle child_allocation;
3019
3020 if (child != old_focus)
3021 {
3022 if (get_allocation_coords (container, child, &child_allocation))
3023 {
3024 child_x1 = child_allocation.x;
3025 child_x2 = child_allocation.x + child_allocation.width;
3026
3027 if ((child_x2 <= compare_x1 || child_x1 >= compare_x2) /* No horizontal overlap */ ||
3028 (direction == CTK_DIR_DOWN && child_allocation.y + child_allocation.height < compare_y) || /* Not below */
3029 (direction == CTK_DIR_UP && child_allocation.y > compare_y)) /* Not above */
3030 {
3031 children = g_list_delete_link (children, tmp_list);
3032 }
3033 }
3034 else
3035 children = g_list_delete_link (children, tmp_list);
3036 }
3037
3038 tmp_list = next;
3039 }
3040
3041 compare.x = (compare_x1 + compare_x2) / 2;
3042 compare.y = old_allocation.y + old_allocation.height / 2;
3043 }
3044 else
3045 {
3046 /* No old focus widget, need to figure out starting x,y some other way
3047 */
3048 CtkAllocation allocation;
3049 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
3050 CdkRectangle old_focus_rect;
3051
3052 _ctk_widget_get_allocation (widget, &allocation);
3053
3054 if (old_focus_coords (container, &old_focus_rect))
3055 {
3056 compare.x = old_focus_rect.x + old_focus_rect.width / 2;
3057 }
3058 else
3059 {
3060 if (!_ctk_widget_get_has_window (widget))
3061 compare.x = allocation.x + allocation.width / 2;
3062 else
3063 compare.x = allocation.width / 2;
3064 }
3065
3066 if (!_ctk_widget_get_has_window (widget))
3067 compare.y = (direction == CTK_DIR_DOWN) ? allocation.y : allocation.y + allocation.height;
3068 else
3069 compare.y = (direction == CTK_DIR_DOWN) ? 0 : + allocation.height;
3070 }
3071
3072 children = g_list_sort_with_data (children, up_down_compare, &compare);
3073
3074 if (compare.reverse)
3075 children = g_list_reverse (children);
3076
3077 return children;
3078}
3079
3080static gint
3081left_right_compare (gconstpointer a,
3082 gconstpointer b,
3083 gpointer data)
3084{
3085 CdkRectangle allocation1;
3086 CdkRectangle allocation2;
3087 CompareInfo *compare = data;
3088 gint x1, x2;
3089
3090 get_allocation_coords (compare->container, (CtkWidget *)a, &allocation1);
3091 get_allocation_coords (compare->container, (CtkWidget *)b, &allocation2);
3092
3093 x1 = allocation1.x + allocation1.width / 2;
3094 x2 = allocation2.x + allocation2.width / 2;
3095
3096 if (x1 == x2)
3097 {
3098 gint y1 = abs (allocation1.y + allocation1.height / 2 - compare->y);
3099 gint y2 = abs (allocation2.y + allocation2.height / 2 - compare->y);
3100
3101 if (compare->reverse)
3102 return (y1 < y2) ? 1 : ((y1 == y2) ? 0 : -1);
3103 else
3104 return (y1 < y2) ? -1 : ((y1 == y2) ? 0 : 1);
3105 }
3106 else
3107 return (x1 < x2) ? -1 : 1;
3108}
3109
3110static GList *
3111ctk_container_focus_sort_left_right (CtkContainer *container,
3112 GList *children,
3113 CtkDirectionType direction,
3114 CtkWidget *old_focus)
3115{
3116 CompareInfo compare;
3117 GList *tmp_list;
3118 CdkRectangle old_allocation;
3119
3120 compare.container = container;
3121 compare.reverse = (direction == CTK_DIR_LEFT);
3122
3123 if (!old_focus)
3124 old_focus = find_old_focus (container, children);
3125
3126 if (old_focus && get_allocation_coords (container, old_focus, &old_allocation))
3127 {
3128 gint compare_y1;
3129 gint compare_y2;
3130 gint compare_x;
3131
3132 /* Delete widgets from list that don't match minimum criteria */
3133
3134 compare_y1 = old_allocation.y;
3135 compare_y2 = old_allocation.y + old_allocation.height;
3136
3137 if (direction == CTK_DIR_LEFT)
3138 compare_x = old_allocation.x;
3139 else
3140 compare_x = old_allocation.x + old_allocation.width;
3141
3142 tmp_list = children;
3143 while (tmp_list)
3144 {
3145 CtkWidget *child = tmp_list->data;
3146 GList *next = tmp_list->next;
3147 gint child_y1, child_y2;
3148 CdkRectangle child_allocation;
3149
3150 if (child != old_focus)
3151 {
3152 if (get_allocation_coords (container, child, &child_allocation))
3153 {
3154 child_y1 = child_allocation.y;
3155 child_y2 = child_allocation.y + child_allocation.height;
3156
3157 if ((child_y2 <= compare_y1 || child_y1 >= compare_y2) /* No vertical overlap */ ||
3158 (direction == CTK_DIR_RIGHT && child_allocation.x + child_allocation.width < compare_x) || /* Not to left */
3159 (direction == CTK_DIR_LEFT && child_allocation.x > compare_x)) /* Not to right */
3160 {
3161 children = g_list_delete_link (children, tmp_list);
3162 }
3163 }
3164 else
3165 children = g_list_delete_link (children, tmp_list);
3166 }
3167
3168 tmp_list = next;
3169 }
3170
3171 compare.y = (compare_y1 + compare_y2) / 2;
3172 compare.x = old_allocation.x + old_allocation.width / 2;
3173 }
3174 else
3175 {
3176 /* No old focus widget, need to figure out starting x,y some other way
3177 */
3178 CtkAllocation allocation;
3179 CtkWidget *widget = CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
;
3180 CdkRectangle old_focus_rect;
3181
3182 _ctk_widget_get_allocation (widget, &allocation);
3183
3184 if (old_focus_coords (container, &old_focus_rect))
3185 {
3186 compare.y = old_focus_rect.y + old_focus_rect.height / 2;
3187 }
3188 else
3189 {
3190 if (!_ctk_widget_get_has_window (widget))
3191 compare.y = allocation.y + allocation.height / 2;
3192 else
3193 compare.y = allocation.height / 2;
3194 }
3195
3196 if (!_ctk_widget_get_has_window (widget))
3197 compare.x = (direction == CTK_DIR_RIGHT) ? allocation.x : allocation.x + allocation.width;
3198 else
3199 compare.x = (direction == CTK_DIR_RIGHT) ? 0 : allocation.width;
3200 }
3201
3202 children = g_list_sort_with_data (children, left_right_compare, &compare);
3203
3204 if (compare.reverse)
3205 children = g_list_reverse (children);
3206
3207 return children;
3208}
3209
3210/**
3211 * ctk_container_focus_sort:
3212 * @container: a #CtkContainer
3213 * @children: a list of descendents of @container (they don't
3214 * have to be direct children)
3215 * @direction: focus direction
3216 * @old_focus: (allow-none): widget to use for the starting position, or %NULL
3217 * to determine this automatically.
3218 * (Note, this argument isn’t used for CTK_DIR_TAB_*,
3219 * which is the only @direction we use currently,
3220 * so perhaps this argument should be removed)
3221 *
3222 * Sorts @children in the correct order for focusing with
3223 * direction type @direction.
3224 *
3225 * Returns: a copy of @children, sorted in correct focusing order,
3226 * with children that aren’t suitable for focusing in this direction
3227 * removed.
3228 **/
3229GList *
3230_ctk_container_focus_sort (CtkContainer *container,
3231 GList *children,
3232 CtkDirectionType direction,
3233 CtkWidget *old_focus)
3234{
3235 GList *visible_children = NULL((void*)0);
3236
3237 while (children)
3238 {
3239 if (_ctk_widget_get_realized (children->data))
3240 visible_children = g_list_prepend (visible_children, children->data);
3241 children = children->next;
3242 }
3243
3244 switch (direction)
3245 {
3246 case CTK_DIR_TAB_FORWARD:
3247 case CTK_DIR_TAB_BACKWARD:
3248 return ctk_container_focus_sort_tab (container, visible_children, direction, old_focus);
3249 case CTK_DIR_UP:
3250 case CTK_DIR_DOWN:
3251 return ctk_container_focus_sort_up_down (container, visible_children, direction, old_focus);
3252 case CTK_DIR_LEFT:
3253 case CTK_DIR_RIGHT:
3254 return ctk_container_focus_sort_left_right (container, visible_children, direction, old_focus);
3255 }
3256
3257 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcontainer.c", 3257,
((const char*) (__func__)), ((void*)0)); } while (0)
;
3258
3259 return NULL((void*)0);
3260}
3261
3262static gboolean
3263ctk_container_focus_move (CtkContainer *container,
3264 GList *children,
3265 CtkDirectionType direction)
3266{
3267 CtkContainerPrivate *priv = container->priv;
3268 CtkWidget *focus_child;
3269 CtkWidget *child;
3270
3271 focus_child = priv->focus_child;
3272
3273 while (children)
3274 {
3275 child = children->data;
3276 children = children->next;
3277
3278 if (!child)
3279 continue;
3280
3281 if (focus_child)
3282 {
3283 if (focus_child == child)
3284 {
3285 focus_child = NULL((void*)0);
3286
3287 if (ctk_widget_child_focus (child, direction))
3288 return TRUE(!(0));
3289 }
3290 }
3291 else if (_ctk_widget_is_drawable (child) &&
3292 ctk_widget_is_ancestor (child, CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
))
3293 {
3294 if (ctk_widget_child_focus (child, direction))
3295 return TRUE(!(0));
3296 }
3297 }
3298
3299 return FALSE(0);
3300}
3301
3302
3303static void
3304ctk_container_children_callback (CtkWidget *widget,
3305 gpointer client_data)
3306{
3307 GList **children;
3308
3309 children = (GList**) client_data;
3310 *children = g_list_prepend (*children, widget);
3311}
3312
3313static void
3314chain_widget_destroyed (CtkWidget *widget,
3315 gpointer user_data)
3316{
3317 CtkContainer *container;
3318 GList *chain;
3319
3320 container = CTK_CONTAINER (user_data)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((ctk_container_get_type ()))))))
;
3321
3322 chain = g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, quark_focus_chain);
3323
3324 chain = g_list_remove (chain, widget);
3325
3326 g_signal_handlers_disconnect_by_func (widget,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (user_data))
3327 chain_widget_destroyed,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (user_data))
3328 user_data)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (user_data))
;
3329
3330 g_object_set_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, quark_focus_chain, chain);
3331}
3332
3333/**
3334 * ctk_container_set_focus_chain:
3335 * @container: a #CtkContainer
3336 * @focusable_widgets: (transfer none) (element-type CtkWidget):
3337 * the new focus chain
3338 *
3339 * Sets a focus chain, overriding the one computed automatically by CTK+.
3340 *
3341 * In principle each widget in the chain should be a descendant of the
3342 * container, but this is not enforced by this method, since it’s allowed
3343 * to set the focus chain before you pack the widgets, or have a widget
3344 * in the chain that isn’t always packed. The necessary checks are done
3345 * when the focus chain is actually traversed.
3346 **/
3347void
3348ctk_container_set_focus_chain (CtkContainer *container,
3349 GList *focusable_widgets)
3350{
3351 GList *chain;
3352 GList *tmp_list;
3353 CtkContainerPrivate *priv;
3354
3355 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
3356
3357 priv = container->priv;
3358
3359 if (priv->has_focus_chain)
3360 ctk_container_unset_focus_chain (container);
3361
3362 priv->has_focus_chain = TRUE(!(0));
3363
3364 chain = NULL((void*)0);
3365 tmp_list = focusable_widgets;
3366 while (tmp_list != NULL((void*)0))
3367 {
3368 g_return_if_fail (CTK_IS_WIDGET (tmp_list->data))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tmp_list->data)); 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 (tmp_list->data)"); return
; } } while (0)
;
3369
3370 /* In principle each widget in the chain should be a descendant
3371 * of the container, but we don't want to check that here. It's
3372 * expensive and also it's allowed to set the focus chain before
3373 * you pack the widgets, or have a widget in the chain that isn't
3374 * always packed. So we check for ancestor during actual traversal.
3375 */
3376
3377 chain = g_list_prepend (chain, tmp_list->data);
3378
3379 g_signal_connect (tmp_list->data,g_signal_connect_data ((tmp_list->data), ("destroy"), (((GCallback
) (chain_widget_destroyed))), (container), ((void*)0), (GConnectFlags
) 0)
3380 "destroy",g_signal_connect_data ((tmp_list->data), ("destroy"), (((GCallback
) (chain_widget_destroyed))), (container), ((void*)0), (GConnectFlags
) 0)
3381 G_CALLBACK (chain_widget_destroyed),g_signal_connect_data ((tmp_list->data), ("destroy"), (((GCallback
) (chain_widget_destroyed))), (container), ((void*)0), (GConnectFlags
) 0)
3382 container)g_signal_connect_data ((tmp_list->data), ("destroy"), (((GCallback
) (chain_widget_destroyed))), (container), ((void*)0), (GConnectFlags
) 0)
;
3383
3384 tmp_list = tmp_list->next;
3385 }
3386
3387 chain = g_list_reverse (chain);
3388
3389 g_object_set_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, quark_focus_chain, chain);
3390}
3391
3392/**
3393 * ctk_container_get_focus_chain:
3394 * @container: a #CtkContainer
3395 * @focusable_widgets: (element-type CtkWidget) (out) (transfer container): location
3396 * to store the focus chain of the
3397 * container, or %NULL. You should free this list
3398 * using g_list_free() when you are done with it, however
3399 * no additional reference count is added to the
3400 * individual widgets in the focus chain.
3401 *
3402 * Retrieves the focus chain of the container, if one has been
3403 * set explicitly. If no focus chain has been explicitly
3404 * set, CTK+ computes the focus chain based on the positions
3405 * of the children. In that case, CTK+ stores %NULL in
3406 * @focusable_widgets and returns %FALSE.
3407 *
3408 * Returns: %TRUE if the focus chain of the container
3409 * has been set explicitly.
3410 **/
3411gboolean
3412ctk_container_get_focus_chain (CtkContainer *container,
3413 GList **focus_chain)
3414{
3415 CtkContainerPrivate *priv;
3416
3417 g_return_val_if_fail (CTK_IS_CONTAINER (container), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return ((0)); } } while (
0)
;
3418
3419 priv = container->priv;
3420
3421 if (focus_chain)
3422 {
3423 if (priv->has_focus_chain)
3424 *focus_chain = g_list_copy (get_focus_chain (container));
3425 else
3426 *focus_chain = NULL((void*)0);
3427 }
3428
3429 return priv->has_focus_chain;
3430}
3431
3432/**
3433 * ctk_container_unset_focus_chain:
3434 * @container: a #CtkContainer
3435 *
3436 * Removes a focus chain explicitly set with ctk_container_set_focus_chain().
3437 **/
3438void
3439ctk_container_unset_focus_chain (CtkContainer *container)
3440{
3441 CtkContainerPrivate *priv;
3442
3443 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
3444
3445 priv = container->priv;
3446
3447 if (priv->has_focus_chain)
3448 {
3449 GList *chain;
3450 GList *tmp_list;
3451
3452 chain = get_focus_chain (container);
3453
3454 priv->has_focus_chain = FALSE(0);
3455
3456 g_object_set_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, quark_focus_chain, NULL((void*)0));
3457
3458 tmp_list = chain;
3459 while (tmp_list != NULL((void*)0))
3460 {
3461 g_signal_handlers_disconnect_by_func (tmp_list->data,g_signal_handlers_disconnect_matched ((tmp_list->data), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (container))
3462 chain_widget_destroyed,g_signal_handlers_disconnect_matched ((tmp_list->data), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (container))
3463 container)g_signal_handlers_disconnect_matched ((tmp_list->data), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chain_widget_destroyed), (container))
;
3464
3465 tmp_list = tmp_list->next;
3466 }
3467
3468 g_list_free (chain);
3469 }
3470}
3471
3472/**
3473 * ctk_container_set_focus_vadjustment:
3474 * @container: a #CtkContainer
3475 * @adjustment: an adjustment which should be adjusted when the focus
3476 * is moved among the descendents of @container
3477 *
3478 * Hooks up an adjustment to focus handling in a container, so when a
3479 * child of the container is focused, the adjustment is scrolled to
3480 * show that widget. This function sets the vertical alignment. See
3481 * ctk_scrolled_window_get_vadjustment() for a typical way of obtaining
3482 * the adjustment and ctk_container_set_focus_hadjustment() for setting
3483 * the horizontal adjustment.
3484 *
3485 * The adjustments have to be in pixel units and in the same coordinate
3486 * system as the allocation for immediate children of the container.
3487 */
3488void
3489ctk_container_set_focus_vadjustment (CtkContainer *container,
3490 CtkAdjustment *adjustment)
3491{
3492 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
3493 if (adjustment)
3494 g_return_if_fail (CTK_IS_ADJUSTMENT (adjustment))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((adjustment)); GType __t = ((ctk_adjustment_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_ADJUSTMENT (adjustment)"); return; } }
while (0)
;
3495
3496 if (adjustment)
3497 g_object_ref (adjustment)((__typeof__ (adjustment)) (g_object_ref) (adjustment));
3498
3499 g_object_set_qdata_full (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
,
3500 vadjustment_key_id,
3501 adjustment,
3502 g_object_unref);
3503}
3504
3505/**
3506 * ctk_container_get_focus_vadjustment:
3507 * @container: a #CtkContainer
3508 *
3509 * Retrieves the vertical focus adjustment for the container. See
3510 * ctk_container_set_focus_vadjustment().
3511 *
3512 * Returns: (nullable) (transfer none): the vertical focus adjustment, or
3513 * %NULL if none has been set.
3514 **/
3515CtkAdjustment *
3516ctk_container_get_focus_vadjustment (CtkContainer *container)
3517{
3518 CtkAdjustment *vadjustment;
3519
3520 g_return_val_if_fail (CTK_IS_CONTAINER (container), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (((void*)0)); } }
while (0)
;
3521
3522 vadjustment = g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, vadjustment_key_id);
3523
3524 return vadjustment;
3525}
3526
3527/**
3528 * ctk_container_set_focus_hadjustment:
3529 * @container: a #CtkContainer
3530 * @adjustment: an adjustment which should be adjusted when the focus is
3531 * moved among the descendents of @container
3532 *
3533 * Hooks up an adjustment to focus handling in a container, so when a child
3534 * of the container is focused, the adjustment is scrolled to show that
3535 * widget. This function sets the horizontal alignment.
3536 * See ctk_scrolled_window_get_hadjustment() for a typical way of obtaining
3537 * the adjustment and ctk_container_set_focus_vadjustment() for setting
3538 * the vertical adjustment.
3539 *
3540 * The adjustments have to be in pixel units and in the same coordinate
3541 * system as the allocation for immediate children of the container.
3542 */
3543void
3544ctk_container_set_focus_hadjustment (CtkContainer *container,
3545 CtkAdjustment *adjustment)
3546{
3547 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
3548 if (adjustment)
3549 g_return_if_fail (CTK_IS_ADJUSTMENT (adjustment))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((adjustment)); GType __t = ((ctk_adjustment_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_ADJUSTMENT (adjustment)"); return; } }
while (0)
;
3550
3551 if (adjustment)
3552 g_object_ref (adjustment)((__typeof__ (adjustment)) (g_object_ref) (adjustment));
3553
3554 g_object_set_qdata_full (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
,
3555 hadjustment_key_id,
3556 adjustment,
3557 g_object_unref);
3558}
3559
3560/**
3561 * ctk_container_get_focus_hadjustment:
3562 * @container: a #CtkContainer
3563 *
3564 * Retrieves the horizontal focus adjustment for the container. See
3565 * ctk_container_set_focus_hadjustment ().
3566 *
3567 * Returns: (nullable) (transfer none): the horizontal focus adjustment, or %NULL if
3568 * none has been set.
3569 **/
3570CtkAdjustment *
3571ctk_container_get_focus_hadjustment (CtkContainer *container)
3572{
3573 CtkAdjustment *hadjustment;
3574
3575 g_return_val_if_fail (CTK_IS_CONTAINER (container), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (((void*)0)); } }
while (0)
;
3576
3577 hadjustment = g_object_get_qdata (G_OBJECT (container)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), (((GType) ((20) << (2))))))))
, hadjustment_key_id);
3578
3579 return hadjustment;
3580}
3581
3582
3583static void
3584ctk_container_show_all (CtkWidget *widget)
3585{
3586 g_return_if_fail (CTK_IS_CONTAINER (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_container_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_CONTAINER (widget)"); return; } } while (0)
;
3587
3588 ctk_container_foreach (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
3589 (CtkCallback) ctk_widget_show_all,
3590 NULL((void*)0));
3591 ctk_widget_show (widget);
3592}
3593
3594typedef struct {
3595 CtkWidget *child;
3596 int window_depth;
3597} ChildOrderInfo;
3598
3599static void
3600ctk_container_draw_forall (CtkWidget *widget,
3601 gpointer client_data)
3602{
3603 struct {
3604 CtkContainer *container;
3605 GArray *child_infos;
3606 cairo_t *cr;
3607 } *data = client_data;
3608 ChildOrderInfo info;
3609 GList *siblings;
3610 CdkWindow *window;
3611
3612 if (ctk_container_should_propagate_draw (data->container, widget, data->cr))
3613 {
3614 info.child = widget;
3615 info.window_depth = G_MAXINT2147483647;
3616 window = _ctk_widget_get_window (widget);
3617 if (window != ctk_widget_get_window (CTK_WIDGET (data->container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->container)), ((ctk_widget_get_type ()))))))
))
3618 {
3619 siblings = cdk_window_peek_children (cdk_window_get_parent (window));
3620 info.window_depth = g_list_index (siblings, window);
3621 }
3622 g_array_append_val (data->child_infos, info)g_array_append_vals (data->child_infos, &(info), 1);
3623 }
3624}
3625
3626static gint
3627compare_children_for_draw (gconstpointer _a,
3628 gconstpointer _b)
3629{
3630 const ChildOrderInfo *a = _a;
3631 const ChildOrderInfo *b = _b;
3632
3633 return b->window_depth - a->window_depth;
3634}
3635
3636static gint
3637ctk_container_draw (CtkWidget *widget,
3638 cairo_t *cr)
3639{
3640 CtkContainer *container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
3641 GArray *child_infos;
3642 int i;
3643 ChildOrderInfo *child_info;
3644 struct {
3645 CtkContainer *container;
3646 GArray *child_infos;
3647 cairo_t *cr;
3648 } data;
3649
3650 child_infos = g_array_new (FALSE(0), TRUE(!(0)), sizeof (ChildOrderInfo));
3651
3652 data.container = container;
3653 data.cr = cr;
3654 data.child_infos = child_infos;
3655 ctk_container_forall (container,
3656 ctk_container_draw_forall,
3657 &data);
3658
3659 g_array_sort (child_infos, compare_children_for_draw);
3660
3661 for (i = 0; i < child_infos->len; i++)
3662 {
3663 child_info = &g_array_index (child_infos, ChildOrderInfo, i)(((ChildOrderInfo*) (void *) (child_infos)->data) [(i)]);
3664 ctk_container_propagate_draw (container, child_info->child, cr);
3665 }
3666
3667 g_array_free (child_infos, TRUE(!(0)));
3668
3669 return FALSE(0);
3670}
3671
3672static void
3673ctk_container_map_child (CtkWidget *child,
3674 gpointer client_data G_GNUC_UNUSED__attribute__ ((__unused__)))
3675{
3676 if (_ctk_widget_get_visible (child) &&
3677 _ctk_widget_get_child_visible (child) &&
3678 !_ctk_widget_get_mapped (child))
3679 ctk_widget_map (child);
3680}
3681
3682static void
3683ctk_container_map (CtkWidget *widget)
3684{
3685 ctk_widget_set_mapped (widget, TRUE(!(0)));
3686
3687 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
3688 ctk_container_map_child,
3689 NULL((void*)0));
3690
3691 if (_ctk_widget_get_has_window (widget))
3692 cdk_window_show (_ctk_widget_get_window (widget));
3693}
3694
3695static void
3696ctk_container_unmap (CtkWidget *widget)
3697{
3698 ctk_widget_set_mapped (widget, FALSE(0));
3699
3700 /* hide our window first so user doesn't see all the child windows
3701 * vanishing one by one. (only matters these days if one of the
3702 * children has an actual native window instead of client-side
3703 * window, e.g. a CtkSocket would)
3704 */
3705 if (_ctk_widget_get_has_window (widget))
3706 cdk_window_hide (_ctk_widget_get_window (widget));
3707
3708 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
3709 (CtkCallback)ctk_widget_unmap,
3710 NULL((void*)0));
3711}
3712
3713static gboolean
3714ctk_container_should_propagate_draw (CtkContainer *container G_GNUC_UNUSED__attribute__ ((__unused__)),
3715 CtkWidget *child,
3716 cairo_t *cr)
3717{
3718 CdkWindow *child_in_window;
3719
3720 if (!_ctk_widget_is_drawable (child))
3721 return FALSE(0);
3722
3723 /* Never propagate to a child window when exposing a window
3724 * that is not the one the child widget is in.
3725 */
3726 if (_ctk_widget_get_has_window (child))
3727 child_in_window = cdk_window_get_parent (_ctk_widget_get_window (child));
3728 else
3729 child_in_window = _ctk_widget_get_window (child);
3730 if (!ctk_cairo_should_draw_window (cr, child_in_window))
3731 return FALSE(0);
3732
3733 return TRUE(!(0));
3734}
3735
3736static void
3737union_with_clip (CtkWidget *widget,
3738 gpointer data)
3739{
3740 CdkRectangle *clip = data;
3741 CtkAllocation widget_clip;
3742
3743 if (!ctk_widget_is_visible (widget) ||
3744 !_ctk_widget_get_child_visible (widget))
3745 return;
3746
3747 ctk_widget_get_clip (widget, &widget_clip);
3748
3749 if (clip->width == 0 || clip->height == 0)
3750 *clip = widget_clip;
3751 else
3752 cdk_rectangle_union (&widget_clip, clip, clip);
3753}
3754
3755void
3756ctk_container_get_children_clip (CtkContainer *container,
3757 CtkAllocation *out_clip)
3758{
3759 memset (out_clip, 0, sizeof (CtkAllocation));
3760
3761 ctk_container_forall (container, union_with_clip, out_clip);
3762}
3763
3764/**
3765 * ctk_container_propagate_draw:
3766 * @container: a #CtkContainer
3767 * @child: a child of @container
3768 * @cr: Cairo context as passed to the container. If you want to use @cr
3769 * in container’s draw function, consider using cairo_save() and
3770 * cairo_restore() before calling this function.
3771 *
3772 * When a container receives a call to the draw function, it must send
3773 * synthetic #CtkWidget::draw calls to all children that don’t have their
3774 * own #CdkWindows. This function provides a convenient way of doing this.
3775 * A container, when it receives a call to its #CtkWidget::draw function,
3776 * calls ctk_container_propagate_draw() once for each child, passing in
3777 * the @cr the container received.
3778 *
3779 * ctk_container_propagate_draw() takes care of translating the origin of @cr,
3780 * and deciding whether the draw needs to be sent to the child. It is a
3781 * convenient and optimized way of getting the same effect as calling
3782 * ctk_widget_draw() on the child directly.
3783 *
3784 * In most cases, a container can simply either inherit the
3785 * #CtkWidget::draw implementation from #CtkContainer, or do some drawing
3786 * and then chain to the ::draw implementation from #CtkContainer.
3787 **/
3788void
3789ctk_container_propagate_draw (CtkContainer *container,
3790 CtkWidget *child,
3791 cairo_t *cr)
3792{
3793 CtkAllocation allocation;
3794 CdkWindow *window, *w;
3795 int x, y;
3796
3797 g_return_if_fail (CTK_IS_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return; } } while (0)
;
3798 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return; } } while (0)
;
3799 g_return_if_fail (cr != NULL)do { if ((cr != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "cr != NULL"); return; }
} while (0)
;
3800 g_return_if_fail (_ctk_widget_get_parent (child) == CTK_WIDGET (container))do { if ((_ctk_widget_get_parent (child) == ((((CtkWidget*) (
void *) g_type_check_instance_cast ((GTypeInstance*) ((container
)), ((ctk_widget_get_type ())))))))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "_ctk_widget_get_parent (child) == CTK_WIDGET (container)"
); return; } } while (0)
;
3801
3802 if (!ctk_container_should_propagate_draw (container, child, cr))
3803 return;
3804
3805 /* translate coordinates. Ugly business, that. */
3806 if (!_ctk_widget_get_has_window (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
))
3807 {
3808 _ctk_widget_get_allocation (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, &allocation);
3809 x = -allocation.x;
3810 y = -allocation.y;
3811 }
3812 else
3813 {
3814 x = 0;
3815 y = 0;
3816 }
3817
3818 window = _ctk_widget_get_window (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
3819
3820 for (w = _ctk_widget_get_window (child); w && w != window; w = cdk_window_get_parent (w))
3821 {
3822 int wx, wy;
3823 cdk_window_get_position (w, &wx, &wy);
3824 x += wx;
3825 y += wy;
3826 }
3827
3828 if (w == NULL((void*)0))
3829 {
3830 x = 0;
3831 y = 0;
3832 }
3833
3834 if (!_ctk_widget_get_has_window (child))
3835 {
3836 _ctk_widget_get_allocation (child, &allocation);
3837 x += allocation.x;
3838 y += allocation.y;
3839 }
3840
3841 cairo_save (cr);
3842 cairo_translate (cr, x, y);
3843
3844 ctk_widget_draw_internal (child, cr, TRUE(!(0)));
3845
3846 cairo_restore (cr);
3847}
3848
3849gboolean
3850_ctk_container_get_reallocate_redraws (CtkContainer *container)
3851{
3852 return container->priv->reallocate_redraws;
3853}
3854
3855/**
3856 * ctk_container_get_path_for_child:
3857 * @container: a #CtkContainer
3858 * @child: a child of @container
3859 *
3860 * Returns a newly created widget path representing all the widget hierarchy
3861 * from the toplevel down to and including @child.
3862 *
3863 * Returns: A newly created #CtkWidgetPath
3864 **/
3865CtkWidgetPath *
3866ctk_container_get_path_for_child (CtkContainer *container,
3867 CtkWidget *child)
3868{
3869 CtkWidgetPath *path;
3870
3871 g_return_val_if_fail (CTK_IS_CONTAINER (container), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((ctk_container_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_CONTAINER (container)"); return (((void*)0)); } }
while (0)
;
3872 g_return_val_if_fail (CTK_IS_WIDGET (child), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); 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 (child)"); return (((void*)0)); } } while (
0)
;
3873 g_return_val_if_fail (container == (CtkContainer *) _ctk_widget_get_parent (child), NULL)do { if ((container == (CtkContainer *) _ctk_widget_get_parent
(child))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "container == (CtkContainer *) _ctk_widget_get_parent (child)"
); return (((void*)0)); } } while (0)
;
3874
3875 path = CTK_CONTAINER_GET_CLASS (container)((((CtkContainerClass*) (((GTypeInstance*) ((container)))->
g_class))))
->get_path_for_child (container, child);
3876 if (ctk_widget_path_get_object_type (path) != G_OBJECT_TYPE (child)(((((GTypeClass*) (((GTypeInstance*) (child))->g_class))->
g_type)))
)
3877 {
3878 g_critical ("%s %p returned a widget path for type %s, but child is %s",
3879 G_OBJECT_TYPE_NAME (container)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (container
))->g_class))->g_type)))))
,
3880 container,
3881 g_type_name (ctk_widget_path_get_object_type (path)),
3882 G_OBJECT_TYPE_NAME (child)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (child))->
g_class))->g_type)))))
);
3883 }
3884
3885 return path;
3886}