Bug Summary

File:ctk/ctkstack.c
Warning:line 1196, column 37
Access to field 'widget' results in a dereference of a null pointer (loaded from field 'last_visible_child')

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 ctkstack.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-171502-43637-1 -x c ctkstack.c
1/*
2 * Copyright (c) 2013 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Author: Alexander Larsson <alexl@redhat.com>
19 *
20 */
21
22#include "config.h"
23
24#include <ctk/ctk.h>
25#include "ctkstack.h"
26#include "ctkprivate.h"
27#include "ctkintl.h"
28#include "ctkcsscustomgadgetprivate.h"
29#include "ctkcontainerprivate.h"
30#include "ctkprogresstrackerprivate.h"
31#include "ctksettingsprivate.h"
32#include "ctkwidgetprivate.h"
33#include "a11y/ctkstackaccessible.h"
34#include "a11y/ctkstackaccessibleprivate.h"
35#include <math.h>
36#include <string.h>
37
38/**
39 * SECTION:ctkstack
40 * @Short_description: A stacking container
41 * @Title: CtkStack
42 * @See_also: #CtkNotebook, #CtkStackSwitcher
43 *
44 * The CtkStack widget is a container which only shows
45 * one of its children at a time. In contrast to CtkNotebook,
46 * CtkStack does not provide a means for users to change the
47 * visible child. Instead, the #CtkStackSwitcher widget can be
48 * used with CtkStack to provide this functionality.
49 *
50 * Transitions between pages can be animated as slides or
51 * fades. This can be controlled with ctk_stack_set_transition_type().
52 * These animations respect the #CtkSettings:ctk-enable-animations
53 * setting.
54 *
55 * The CtkStack widget was added in CTK+ 3.10.
56 *
57 * # CSS nodes
58 *
59 * CtkStack has a single CSS node named stack.
60 */
61
62/**
63 * CtkStackTransitionType:
64 * @CTK_STACK_TRANSITION_TYPE_NONE: No transition
65 * @CTK_STACK_TRANSITION_TYPE_CROSSFADE: A cross-fade
66 * @CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT: Slide from left to right
67 * @CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT: Slide from right to left
68 * @CTK_STACK_TRANSITION_TYPE_SLIDE_UP: Slide from bottom up
69 * @CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN: Slide from top down
70 * @CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT: Slide from left or right according to the children order
71 * @CTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN: Slide from top down or bottom up according to the order
72 * @CTK_STACK_TRANSITION_TYPE_OVER_UP: Cover the old page by sliding up. Since 3.12
73 * @CTK_STACK_TRANSITION_TYPE_OVER_DOWN: Cover the old page by sliding down. Since: 3.12
74 * @CTK_STACK_TRANSITION_TYPE_OVER_LEFT: Cover the old page by sliding to the left. Since: 3.12
75 * @CTK_STACK_TRANSITION_TYPE_OVER_RIGHT: Cover the old page by sliding to the right. Since: 3.12
76 * @CTK_STACK_TRANSITION_TYPE_UNDER_UP: Uncover the new page by sliding up. Since 3.12
77 * @CTK_STACK_TRANSITION_TYPE_UNDER_DOWN: Uncover the new page by sliding down. Since: 3.12
78 * @CTK_STACK_TRANSITION_TYPE_UNDER_LEFT: Uncover the new page by sliding to the left. Since: 3.12
79 * @CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT: Uncover the new page by sliding to the right. Since: 3.12
80 * @CTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN: Cover the old page sliding up or uncover the new page sliding down, according to order. Since: 3.12
81 * @CTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP: Cover the old page sliding down or uncover the new page sliding up, according to order. Since: 3.14
82 * @CTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT: Cover the old page sliding left or uncover the new page sliding right, according to order. Since: 3.14
83 * @CTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT: Cover the old page sliding right or uncover the new page sliding left, according to order. Since: 3.14
84 *
85 * These enumeration values describe the possible transitions
86 * between pages in a #CtkStack widget.
87 *
88 * New values may be added to this enumeration over time.
89 */
90
91/* TODO:
92 * filter events out events to the last_child widget during transitions
93 */
94
95enum {
96 PROP_0,
97 PROP_HOMOGENEOUS,
98 PROP_HHOMOGENEOUS,
99 PROP_VHOMOGENEOUS,
100 PROP_VISIBLE_CHILD,
101 PROP_VISIBLE_CHILD_NAME,
102 PROP_TRANSITION_DURATION,
103 PROP_TRANSITION_TYPE,
104 PROP_TRANSITION_RUNNING,
105 PROP_INTERPOLATE_SIZE,
106 LAST_PROP
107};
108
109enum
110{
111 CHILD_PROP_0,
112 CHILD_PROP_NAME,
113 CHILD_PROP_TITLE,
114 CHILD_PROP_ICON_NAME,
115 CHILD_PROP_POSITION,
116 CHILD_PROP_NEEDS_ATTENTION,
117 LAST_CHILD_PROP
118};
119
120typedef struct _CtkStackChildInfo CtkStackChildInfo;
121
122struct _CtkStackChildInfo {
123 CtkWidget *widget;
124 gchar *name;
125 gchar *title;
126 gchar *icon_name;
127 gboolean needs_attention;
128 CtkWidget *last_focus;
129};
130
131typedef struct {
132 GList *children;
133
134 CdkWindow* bin_window;
135 CdkWindow* view_window;
136
137 CtkStackChildInfo *visible_child;
138
139 CtkCssGadget *gadget;
140
141 gboolean hhomogeneous;
142 gboolean vhomogeneous;
143
144 CtkStackTransitionType transition_type;
145 guint transition_duration;
146
147 CtkStackChildInfo *last_visible_child;
148 cairo_surface_t *last_visible_surface;
149 CtkAllocation last_visible_surface_allocation;
150 guint tick_id;
151 CtkProgressTracker tracker;
152 gboolean first_frame_skipped;
153
154 gint last_visible_widget_width;
155 gint last_visible_widget_height;
156
157 gboolean interpolate_size;
158
159 CtkStackTransitionType active_transition_type;
160
161} CtkStackPrivate;
162
163static GParamSpec *stack_props[LAST_PROP] = { NULL((void*)0), };
164static GParamSpec *stack_child_props[LAST_CHILD_PROP] = { NULL((void*)0), };
165
166static void ctk_stack_add (CtkContainer *widget,
167 CtkWidget *child);
168static void ctk_stack_remove (CtkContainer *widget,
169 CtkWidget *child);
170static void ctk_stack_forall (CtkContainer *container,
171 gboolean include_internals,
172 CtkCallback callback,
173 gpointer callback_data);
174static void ctk_stack_compute_expand (CtkWidget *widget,
175 gboolean *hexpand,
176 gboolean *vexpand);
177static void ctk_stack_size_allocate (CtkWidget *widget,
178 CtkAllocation *allocation);
179static gboolean ctk_stack_draw (CtkWidget *widget,
180 cairo_t *cr);
181static void ctk_stack_get_preferred_height (CtkWidget *widget,
182 gint *minimum_height,
183 gint *natural_height);
184static void ctk_stack_get_preferred_height_for_width (CtkWidget *widget,
185 gint width,
186 gint *minimum_height,
187 gint *natural_height);
188static void ctk_stack_get_preferred_width (CtkWidget *widget,
189 gint *minimum_width,
190 gint *natural_width);
191static void ctk_stack_get_preferred_width_for_height (CtkWidget *widget,
192 gint height,
193 gint *minimum_width,
194 gint *natural_width);
195static void ctk_stack_finalize (GObject *obj);
196static void ctk_stack_get_property (GObject *object,
197 guint property_id,
198 GValue *value,
199 GParamSpec *pspec);
200static void ctk_stack_set_property (GObject *object,
201 guint property_id,
202 const GValue *value,
203 GParamSpec *pspec);
204static void ctk_stack_get_child_property (CtkContainer *container,
205 CtkWidget *child,
206 guint property_id,
207 GValue *value,
208 GParamSpec *pspec);
209static void ctk_stack_set_child_property (CtkContainer *container,
210 CtkWidget *child,
211 guint property_id,
212 const GValue *value,
213 GParamSpec *pspec);
214static void ctk_stack_unschedule_ticks (CtkStack *stack);
215static gint get_bin_window_x (CtkStack *stack,
216 const CtkAllocation *allocation);
217static gint get_bin_window_y (CtkStack *stack,
218 const CtkAllocation *allocation);
219
220G_DEFINE_TYPE_WITH_PRIVATE (CtkStack, ctk_stack, CTK_TYPE_CONTAINER)static void ctk_stack_init (CtkStack *self); static void ctk_stack_class_init
(CtkStackClass *klass); static GType ctk_stack_get_type_once
(void); static gpointer ctk_stack_parent_class = ((void*)0);
static gint CtkStack_private_offset; static void ctk_stack_class_intern_init
(gpointer klass) { ctk_stack_parent_class = g_type_class_peek_parent
(klass); if (CtkStack_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkStack_private_offset); ctk_stack_class_init (
(CtkStackClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_stack_get_instance_private (CtkStack *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CtkStack_private_offset
)))); } GType ctk_stack_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_stack_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_stack_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple ((ctk_container_get_type
()), g_intern_static_string ("CtkStack"), sizeof (CtkStackClass
), (GClassInitFunc)(void (*)(void)) ctk_stack_class_intern_init
, sizeof (CtkStack), (GInstanceInitFunc)(void (*)(void)) ctk_stack_init
, (GTypeFlags) 0); { {{ CtkStack_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkStackPrivate)); };} } return g_define_type_id
; }
221
222static void
223ctk_stack_dispose (GObject *obj)
224{
225 CtkStack *stack = CTK_STACK (obj)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((obj)), ((ctk_stack_get_type ()))))))
;
226 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
227
228 priv->visible_child = NULL((void*)0);
229
230 G_OBJECT_CLASS (ctk_stack_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_stack_parent_class)), (((GType) ((20) << (2)))
)))))
->dispose (obj);
231}
232
233static void
234ctk_stack_finalize (GObject *obj)
235{
236 CtkStack *stack = CTK_STACK (obj)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((obj)), ((ctk_stack_get_type ()))))))
;
237 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
238
239 ctk_stack_unschedule_ticks (stack);
240
241 if (priv->last_visible_surface != NULL((void*)0))
242 cairo_surface_destroy (priv->last_visible_surface);
243
244 g_clear_object (&priv->gadget)do { _Static_assert (sizeof *((&priv->gadget)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->gadget))) _pp = ((&priv->gadget)); __typeof__
(*((&priv->gadget))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
245
246 G_OBJECT_CLASS (ctk_stack_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_stack_parent_class)), (((GType) ((20) << (2)))
)))))
->finalize (obj);
247}
248
249static void
250ctk_stack_get_property (GObject *object,
251 guint property_id,
252 GValue *value,
253 GParamSpec *pspec)
254{
255 CtkStack *stack = CTK_STACK (object)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_stack_get_type ()))))))
;
256
257 switch (property_id)
258 {
259 case PROP_HOMOGENEOUS:
260 g_value_set_boolean (value, ctk_stack_get_homogeneous (stack));
261 break;
262 case PROP_HHOMOGENEOUS:
263 g_value_set_boolean (value, ctk_stack_get_hhomogeneous (stack));
264 break;
265 case PROP_VHOMOGENEOUS:
266 g_value_set_boolean (value, ctk_stack_get_vhomogeneous (stack));
267 break;
268 case PROP_VISIBLE_CHILD:
269 g_value_set_object (value, ctk_stack_get_visible_child (stack));
270 break;
271 case PROP_VISIBLE_CHILD_NAME:
272 g_value_set_string (value, ctk_stack_get_visible_child_name (stack));
273 break;
274 case PROP_TRANSITION_DURATION:
275 g_value_set_uint (value, ctk_stack_get_transition_duration (stack));
276 break;
277 case PROP_TRANSITION_TYPE:
278 g_value_set_enum (value, ctk_stack_get_transition_type (stack));
279 break;
280 case PROP_TRANSITION_RUNNING:
281 g_value_set_boolean (value, ctk_stack_get_transition_running (stack));
282 break;
283 case PROP_INTERPOLATE_SIZE:
284 g_value_set_boolean (value, ctk_stack_get_interpolate_size (stack));
285 break;
286 default:
287 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 287, ("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)
;
288 break;
289 }
290}
291
292static void
293ctk_stack_set_property (GObject *object,
294 guint property_id,
295 const GValue *value,
296 GParamSpec *pspec)
297{
298 CtkStack *stack = CTK_STACK (object)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_stack_get_type ()))))))
;
299
300 switch (property_id)
301 {
302 case PROP_HOMOGENEOUS:
303 ctk_stack_set_homogeneous (stack, g_value_get_boolean (value));
304 break;
305 case PROP_HHOMOGENEOUS:
306 ctk_stack_set_hhomogeneous (stack, g_value_get_boolean (value));
307 break;
308 case PROP_VHOMOGENEOUS:
309 ctk_stack_set_vhomogeneous (stack, g_value_get_boolean (value));
310 break;
311 case PROP_VISIBLE_CHILD:
312 ctk_stack_set_visible_child (stack, g_value_get_object (value));
313 break;
314 case PROP_VISIBLE_CHILD_NAME:
315 ctk_stack_set_visible_child_name (stack, g_value_get_string (value));
316 break;
317 case PROP_TRANSITION_DURATION:
318 ctk_stack_set_transition_duration (stack, g_value_get_uint (value));
319 break;
320 case PROP_TRANSITION_TYPE:
321 ctk_stack_set_transition_type (stack, g_value_get_enum (value));
322 break;
323 case PROP_INTERPOLATE_SIZE:
324 ctk_stack_set_interpolate_size (stack, g_value_get_boolean (value));
325 break;
326 default:
327 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 327, ("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)
;
328 break;
329 }
330}
331
332static void
333ctk_stack_realize (CtkWidget *widget)
334{
335 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
336 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
337 CtkAllocation allocation;
338 CdkWindowAttr attributes = { 0 };
339 CdkWindowAttributesType attributes_mask;
340 CtkStackChildInfo *info;
341 GList *l;
342
343 ctk_widget_set_realized (widget, TRUE(!(0)));
344 ctk_widget_set_window (widget, g_object_ref (ctk_widget_get_parent_window (widget))((__typeof__ (ctk_widget_get_parent_window (widget))) (g_object_ref
) (ctk_widget_get_parent_window (widget)))
);
345
346 ctk_css_gadget_get_content_allocation (priv->gadget, &allocation, NULL((void*)0));
347
348 attributes.x = allocation.x;
349 attributes.y = allocation.y;
350 attributes.width = allocation.width;
351 attributes.height = allocation.height;
352 attributes.window_type = CDK_WINDOW_CHILD;
353 attributes.wclass = CDK_INPUT_OUTPUT;
354 attributes.visual = ctk_widget_get_visual (widget);
355 attributes.event_mask =
356 ctk_widget_get_events (widget);
357 attributes_mask = (CDK_WA_X | CDK_WA_Y) | CDK_WA_VISUAL;
358
359 priv->view_window =
360 cdk_window_new (ctk_widget_get_window (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
),
361 &attributes, attributes_mask);
362 ctk_widget_register_window (widget, priv->view_window);
363
364 attributes.x = get_bin_window_x (stack, &allocation);
365 attributes.y = get_bin_window_y (stack, &allocation);
366 attributes.width = allocation.width;
367 attributes.height = allocation.height;
368
369 for (l = priv->children; l != NULL((void*)0); l = l->next)
370 {
371 info = l->data;
372 attributes.event_mask |= ctk_widget_get_events (info->widget);
373 }
374
375 priv->bin_window =
376 cdk_window_new (priv->view_window, &attributes, attributes_mask);
377 ctk_widget_register_window (widget, priv->bin_window);
378
379 for (l = priv->children; l != NULL((void*)0); l = l->next)
380 {
381 info = l->data;
382
383 ctk_widget_set_parent_window (info->widget, priv->bin_window);
384 }
385
386 cdk_window_show (priv->bin_window);
387}
388
389static void
390ctk_stack_unrealize (CtkWidget *widget)
391{
392 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
393 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
394
395 ctk_widget_unregister_window (widget, priv->bin_window);
396 cdk_window_destroy (priv->bin_window);
397 priv->bin_window = NULL((void*)0);
398 ctk_widget_unregister_window (widget, priv->view_window);
399 cdk_window_destroy (priv->view_window);
400 priv->view_window = NULL((void*)0);
401
402 CTK_WIDGET_CLASS (ctk_stack_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_stack_parent_class)), ((ctk_widget_get_type ()))))))
->unrealize (widget);
403}
404
405static void
406ctk_stack_map (CtkWidget *widget)
407{
408 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
409 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
410
411 CTK_WIDGET_CLASS (ctk_stack_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_stack_parent_class)), ((ctk_widget_get_type ()))))))
->map (widget);
412
413 cdk_window_show (priv->view_window);
414}
415
416static void
417ctk_stack_unmap (CtkWidget *widget)
418{
419 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
420 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
421
422 cdk_window_hide (priv->view_window);
423
424 CTK_WIDGET_CLASS (ctk_stack_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_stack_parent_class)), ((ctk_widget_get_type ()))))))
->unmap (widget);
425}
426
427static void
428ctk_stack_class_init (CtkStackClass *klass)
429{
430 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
431 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_widget_get_type ()))))))
;
432 CtkContainerClass *container_class = CTK_CONTAINER_CLASS (klass)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_container_get_type ()))))))
;
433
434 object_class->get_property = ctk_stack_get_property;
435 object_class->set_property = ctk_stack_set_property;
436 object_class->dispose = ctk_stack_dispose;
437 object_class->finalize = ctk_stack_finalize;
438
439 widget_class->size_allocate = ctk_stack_size_allocate;
440 widget_class->draw = ctk_stack_draw;
441 widget_class->realize = ctk_stack_realize;
442 widget_class->unrealize = ctk_stack_unrealize;
443 widget_class->map = ctk_stack_map;
444 widget_class->unmap = ctk_stack_unmap;
445 widget_class->get_preferred_height = ctk_stack_get_preferred_height;
446 widget_class->get_preferred_height_for_width = ctk_stack_get_preferred_height_for_width;
447 widget_class->get_preferred_width = ctk_stack_get_preferred_width;
448 widget_class->get_preferred_width_for_height = ctk_stack_get_preferred_width_for_height;
449 widget_class->compute_expand = ctk_stack_compute_expand;
450
451 container_class->add = ctk_stack_add;
452 container_class->remove = ctk_stack_remove;
453 container_class->forall = ctk_stack_forall;
454 container_class->set_child_property = ctk_stack_set_child_property;
455 container_class->get_child_property = ctk_stack_get_child_property;
456 ctk_container_class_handle_border_width (container_class);
457
458 stack_props[PROP_HOMOGENEOUS] =
459 g_param_spec_boolean ("homogeneous", P_("Homogeneous")g_dgettext("ctk30" "-properties","Homogeneous"), P_("Homogeneous sizing")g_dgettext("ctk30" "-properties","Homogeneous sizing"),
460 TRUE(!(0)),
461 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
462
463 /**
464 * CtkStack:hhomogeneous:
465 *
466 * %TRUE if the stack allocates the same width for all children.
467 *
468 * Since: 3.16
469 */
470 stack_props[PROP_HHOMOGENEOUS] =
471 g_param_spec_boolean ("hhomogeneous", P_("Horizontally homogeneous")g_dgettext("ctk30" "-properties","Horizontally homogeneous"), P_("Horizontally homogeneous sizing")g_dgettext("ctk30" "-properties","Horizontally homogeneous sizing"
)
,
472 TRUE(!(0)),
473 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
474
475 /**
476 * CtkStack:vhomogeneous:
477 *
478 * %TRUE if the stack allocates the same height for all children.
479 *
480 * Since: 3.16
481 */
482 stack_props[PROP_VHOMOGENEOUS] =
483 g_param_spec_boolean ("vhomogeneous", P_("Vertically homogeneous")g_dgettext("ctk30" "-properties","Vertically homogeneous"), P_("Vertically homogeneous sizing")g_dgettext("ctk30" "-properties","Vertically homogeneous sizing"
)
,
484 TRUE(!(0)),
485 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
486 stack_props[PROP_VISIBLE_CHILD] =
487 g_param_spec_object ("visible-child", P_("Visible child")g_dgettext("ctk30" "-properties","Visible child"), P_("The widget currently visible in the stack")g_dgettext("ctk30" "-properties","The widget currently visible in the stack"
)
,
488 CTK_TYPE_WIDGET(ctk_widget_get_type ()),
489 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
490 stack_props[PROP_VISIBLE_CHILD_NAME] =
491 g_param_spec_string ("visible-child-name", P_("Name of visible child")g_dgettext("ctk30" "-properties","Name of visible child"), P_("The name of the widget currently visible in the stack")g_dgettext("ctk30" "-properties","The name of the widget currently visible in the stack"
)
,
492 NULL((void*)0),
493 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
494 stack_props[PROP_TRANSITION_DURATION] =
495 g_param_spec_uint ("transition-duration", P_("Transition duration")g_dgettext("ctk30" "-properties","Transition duration"), P_("The animation duration, in milliseconds")g_dgettext("ctk30" "-properties","The animation duration, in milliseconds"
)
,
496 0, G_MAXUINT(2147483647 *2U +1U), 200,
497 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
498 stack_props[PROP_TRANSITION_TYPE] =
499 g_param_spec_enum ("transition-type", P_("Transition type")g_dgettext("ctk30" "-properties","Transition type"), P_("The type of animation used to transition")g_dgettext("ctk30" "-properties","The type of animation used to transition"
)
,
500 CTK_TYPE_STACK_TRANSITION_TYPE(ctk_stack_transition_type_get_type ()), CTK_STACK_TRANSITION_TYPE_NONE,
501 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
502 stack_props[PROP_TRANSITION_RUNNING] =
503 g_param_spec_boolean ("transition-running", P_("Transition running")g_dgettext("ctk30" "-properties","Transition running"), P_("Whether or not the transition is currently running")g_dgettext("ctk30" "-properties","Whether or not the transition is currently running"
)
,
504 FALSE(0),
505 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
506 stack_props[PROP_INTERPOLATE_SIZE] =
507 g_param_spec_boolean ("interpolate-size", P_("Interpolate size")g_dgettext("ctk30" "-properties","Interpolate size"), P_("Whether or not the size should smoothly change when changing between differently sized children")g_dgettext("ctk30" "-properties","Whether or not the size should smoothly change when changing between differently sized children"
)
,
508 FALSE(0),
509 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_EXPLICIT_NOTIFY);
510
511
512 g_object_class_install_properties (object_class, LAST_PROP, stack_props);
513
514 stack_child_props[CHILD_PROP_NAME] =
515 g_param_spec_string ("name",
516 P_("Name")g_dgettext("ctk30" "-properties","Name"),
517 P_("The name of the child page")g_dgettext("ctk30" "-properties","The name of the child page"
)
,
518 NULL((void*)0),
519 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
520
521 stack_child_props[CHILD_PROP_TITLE] =
522 g_param_spec_string ("title",
523 P_("Title")g_dgettext("ctk30" "-properties","Title"),
524 P_("The title of the child page")g_dgettext("ctk30" "-properties","The title of the child page"
)
,
525 NULL((void*)0),
526 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
527
528 stack_child_props[CHILD_PROP_ICON_NAME] =
529 g_param_spec_string ("icon-name",
530 P_("Icon name")g_dgettext("ctk30" "-properties","Icon name"),
531 P_("The icon name of the child page")g_dgettext("ctk30" "-properties","The icon name of the child page"
)
,
532 NULL((void*)0),
533 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
534
535 stack_child_props[CHILD_PROP_POSITION] =
536 g_param_spec_int ("position",
537 P_("Position")g_dgettext("ctk30" "-properties","Position"),
538 P_("The index of the child in the parent")g_dgettext("ctk30" "-properties","The index of the child in the parent"
)
,
539 -1, G_MAXINT2147483647,
540 0,
541 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
542
543 /**
544 * CtkStack:needs-attention:
545 *
546 * Sets a flag specifying whether the child requires the user attention.
547 * This is used by the #CtkStackSwitcher to change the appearance of the
548 * corresponding button when a page needs attention and it is not the
549 * current one.
550 *
551 * Since: 3.12
552 */
553 stack_child_props[CHILD_PROP_NEEDS_ATTENTION] =
554 g_param_spec_boolean ("needs-attention",
555 P_("Needs Attention")g_dgettext("ctk30" "-properties","Needs Attention"),
556 P_("Whether this page needs attention")g_dgettext("ctk30" "-properties","Whether this page needs attention"
)
,
557 FALSE(0),
558 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
559
560 ctk_container_class_install_child_properties (container_class, LAST_CHILD_PROP, stack_child_props);
561
562 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_STACK_ACCESSIBLE(ctk_stack_accessible_get_type ()));
563 ctk_widget_class_set_css_name (widget_class, "stack");
564}
565
566/**
567 * ctk_stack_new:
568 *
569 * Creates a new #CtkStack container.
570 *
571 * Returns: a new #CtkStack
572 *
573 * Since: 3.10
574 */
575CtkWidget *
576ctk_stack_new (void)
577{
578 return g_object_new (CTK_TYPE_STACK(ctk_stack_get_type ()), NULL((void*)0));
579}
580
581static CtkStackChildInfo *
582find_child_info_for_widget (CtkStack *stack,
583 CtkWidget *child)
584{
585 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
586 CtkStackChildInfo *info;
587 GList *l;
588
589 for (l = priv->children; l != NULL((void*)0); l = l->next)
590 {
591 info = l->data;
592 if (info->widget == child)
593 return info;
594 }
595
596 return NULL((void*)0);
597}
598
599static void
600reorder_child (CtkStack *stack,
601 CtkWidget *child,
602 gint position)
603{
604 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
605 GList *l;
606 GList *old_link = NULL((void*)0);
607 GList *new_link = NULL((void*)0);
608 CtkStackChildInfo *child_info = NULL((void*)0);
609 gint num = 0;
610
611 l = priv->children;
612
613 /* Loop to find the old position and link of child, new link of child and
614 * total number of children. new_link will be NULL if the child should be
615 * moved to the end (in case of position being < 0 || >= num)
616 */
617 while (l && (new_link == NULL((void*)0) || old_link == NULL((void*)0)))
618 {
619 /* Record the new position if found */
620 if (position == num)
621 new_link = l;
622
623 if (old_link == NULL((void*)0))
624 {
625 CtkStackChildInfo *info;
626 info = l->data;
627
628 /* Keep trying to find the current position and link location of the child */
629 if (info->widget == child)
630 {
631 old_link = l;
632 child_info = info;
633 }
634 }
635
636 l = l->next;
637 num++;
638 }
639
640 g_return_if_fail (old_link != NULL)do { if ((old_link != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "old_link != NULL"); return
; } } while (0)
;
641
642 if (old_link == new_link || (old_link->next == NULL((void*)0) && new_link == NULL((void*)0)))
643 return;
644
645 priv->children = g_list_delete_link (priv->children, old_link);
646 priv->children = g_list_insert_before (priv->children, new_link, child_info);
647
648 ctk_container_child_notify_by_pspec (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
, child, stack_child_props[CHILD_PROP_POSITION]);
649}
650
651static void
652ctk_stack_get_child_property (CtkContainer *container,
653 CtkWidget *child,
654 guint property_id,
655 GValue *value,
656 GParamSpec *pspec)
657{
658 CtkStack *stack = CTK_STACK (container)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_stack_get_type ()))))))
;
659 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
660 CtkStackChildInfo *info;
661
662 info = find_child_info_for_widget (stack, child);
663 if (info == NULL((void*)0))
664 {
665 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 665, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
666 return;
667 }
668
669 switch (property_id)
670 {
671 case CHILD_PROP_NAME:
672 g_value_set_string (value, info->name);
673 break;
674
675 case CHILD_PROP_TITLE:
676 g_value_set_string (value, info->title);
677 break;
678
679 case CHILD_PROP_ICON_NAME:
680 g_value_set_string (value, info->icon_name);
681 break;
682
683 case CHILD_PROP_POSITION:
684 g_value_set_int (value, g_list_index (priv->children, info));
685 break;
686
687 case CHILD_PROP_NEEDS_ATTENTION:
688 g_value_set_boolean (value, info->needs_attention);
689 break;
690
691 default:
692 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 692, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
693 break;
694 }
695}
696
697static void
698ctk_stack_set_child_property (CtkContainer *container,
699 CtkWidget *child,
700 guint property_id,
701 const GValue *value,
702 GParamSpec *pspec)
703{
704 CtkStack *stack = CTK_STACK (container)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_stack_get_type ()))))))
;
705 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
706 CtkStackChildInfo *info;
707 CtkStackChildInfo *info2;
708 gchar *name;
709 GList *l;
710
711 info = find_child_info_for_widget (stack, child);
712 if (info == NULL((void*)0))
713 {
714 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 714, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
715 return;
716 }
717
718 switch (property_id)
719 {
720 case CHILD_PROP_NAME:
721 name = g_value_dup_string (value);
722 for (l = priv->children; l != NULL((void*)0); l = l->next)
723 {
724 info2 = l->data;
725 if (info == info2)
726 continue;
727 if (g_strcmp0 (info2->name, name) == 0)
728 {
729 g_warning ("Duplicate child name in CtkStack: %s", name);
730 break;
731 }
732 }
733
734 g_free (info->name);
735 info->name = name;
736
737 ctk_container_child_notify_by_pspec (container, child, pspec);
738
739 if (priv->visible_child == info)
740 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
,
741 stack_props[PROP_VISIBLE_CHILD_NAME]);
742
743 break;
744
745 case CHILD_PROP_TITLE:
746 g_free (info->title);
747 info->title = g_value_dup_string (value);
748 ctk_container_child_notify_by_pspec (container, child, pspec);
749 break;
750
751 case CHILD_PROP_ICON_NAME:
752 g_free (info->icon_name);
753 info->icon_name = g_value_dup_string (value);
754 ctk_container_child_notify_by_pspec (container, child, pspec);
755 break;
756
757 case CHILD_PROP_POSITION:
758 reorder_child (stack, child, g_value_get_int (value));
759 break;
760
761 case CHILD_PROP_NEEDS_ATTENTION:
762 info->needs_attention = g_value_get_boolean (value);
763 ctk_container_child_notify_by_pspec (container, child, pspec);
764 break;
765
766 default:
767 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkstack.c", 767, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
768 break;
769 }
770}
771
772static inline gboolean
773is_left_transition (CtkStackTransitionType transition_type)
774{
775 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT ||
776 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_LEFT);
777}
778
779static inline gboolean
780is_right_transition (CtkStackTransitionType transition_type)
781{
782 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT ||
783 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_RIGHT);
784}
785
786static inline gboolean
787is_up_transition (CtkStackTransitionType transition_type)
788{
789 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_UP ||
790 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_UP);
791}
792
793static inline gboolean
794is_down_transition (CtkStackTransitionType transition_type)
795{
796 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN ||
797 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_DOWN);
798}
799
800/* Transitions that cause the bin window to move */
801static inline gboolean
802is_window_moving_transition (CtkStackTransitionType transition_type)
803{
804 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT ||
805 transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT ||
806 transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_UP ||
807 transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN ||
808 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_UP ||
809 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_DOWN ||
810 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_LEFT ||
811 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_RIGHT);
812}
813
814/* Transitions that change direction depending on the relative order of the
815old and new child */
816static inline gboolean
817is_direction_dependent_transition (CtkStackTransitionType transition_type)
818{
819 return (transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT ||
820 transition_type == CTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN ||
821 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN ||
822 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP ||
823 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT ||
824 transition_type == CTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT);
825}
826
827/* Returns simple transition type for a direction dependent transition, given
828whether the new child (the one being switched to) is first in the stacking order
829(added earlier). */
830static inline CtkStackTransitionType
831get_simple_transition_type (gboolean new_child_first,
832 CtkStackTransitionType transition_type)
833{
834 switch (transition_type)
835 {
836 case CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT:
837 return new_child_first ? CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT : CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT;
838 case CTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN:
839 return new_child_first ? CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN : CTK_STACK_TRANSITION_TYPE_SLIDE_UP;
840 case CTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN:
841 return new_child_first ? CTK_STACK_TRANSITION_TYPE_UNDER_DOWN : CTK_STACK_TRANSITION_TYPE_OVER_UP;
842 case CTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP:
843 return new_child_first ? CTK_STACK_TRANSITION_TYPE_UNDER_UP : CTK_STACK_TRANSITION_TYPE_OVER_DOWN;
844 case CTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT:
845 return new_child_first ? CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT : CTK_STACK_TRANSITION_TYPE_OVER_LEFT;
846 case CTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT:
847 return new_child_first ? CTK_STACK_TRANSITION_TYPE_UNDER_LEFT : CTK_STACK_TRANSITION_TYPE_OVER_RIGHT;
848 default: ;
849 }
850 return transition_type;
851}
852
853static gint
854get_bin_window_x (CtkStack *stack,
855 const CtkAllocation *allocation)
856{
857 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
858 int x = 0;
859
860 if (ctk_progress_tracker_get_state (&priv->tracker) != CTK_PROGRESS_STATE_AFTER)
861 {
862 if (is_left_transition (priv->active_transition_type))
863 x = allocation->width * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
864 if (is_right_transition (priv->active_transition_type))
865 x = -allocation->width * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
866 }
867
868 return x;
869}
870
871static gint
872get_bin_window_y (CtkStack *stack,
873 const CtkAllocation *allocation)
874{
875 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
876 int y = 0;
877
878 if (ctk_progress_tracker_get_state (&priv->tracker) != CTK_PROGRESS_STATE_AFTER)
879 {
880 if (is_up_transition (priv->active_transition_type))
881 y = allocation->height * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
882 if (is_down_transition(priv->active_transition_type))
883 y = -allocation->height * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
884 }
885
886 return y;
887}
888
889static void
890ctk_stack_progress_updated (CtkStack *stack)
891{
892 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
893
894 ctk_widget_queue_draw (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
895
896 if (!priv->vhomogeneous || !priv->hhomogeneous)
897 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
898
899 if (priv->bin_window != NULL((void*)0) &&
900 is_window_moving_transition (priv->active_transition_type))
901 {
902 CtkAllocation allocation;
903 ctk_widget_get_allocation (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
, &allocation);
904 cdk_window_move (priv->bin_window,
905 get_bin_window_x (stack, &allocation), get_bin_window_y (stack, &allocation));
906 }
907
908 if (ctk_progress_tracker_get_state (&priv->tracker) == CTK_PROGRESS_STATE_AFTER)
909 {
910 if (priv->last_visible_surface != NULL((void*)0))
911 {
912 cairo_surface_destroy (priv->last_visible_surface);
913 priv->last_visible_surface = NULL((void*)0);
914 }
915
916 if (priv->last_visible_child != NULL((void*)0))
917 {
918 ctk_widget_set_child_visible (priv->last_visible_child->widget, FALSE(0));
919 priv->last_visible_child = NULL((void*)0);
920 }
921 }
922}
923
924static gboolean
925ctk_stack_transition_cb (CtkWidget *widget,
926 CdkFrameClock *frame_clock,
927 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
928{
929 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
930 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
931
932 if (priv->first_frame_skipped)
933 ctk_progress_tracker_advance_frame (&priv->tracker,
934 cdk_frame_clock_get_frame_time (frame_clock));
935 else
936 priv->first_frame_skipped = TRUE(!(0));
937
938 /* Finish animation early if not mapped anymore */
939 if (!ctk_widget_get_mapped (widget))
940 ctk_progress_tracker_finish (&priv->tracker);
941
942 ctk_stack_progress_updated (CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
);
943
944 if (ctk_progress_tracker_get_state (&priv->tracker) == CTK_PROGRESS_STATE_AFTER)
945 {
946 priv->tick_id = 0;
947 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_TRANSITION_RUNNING]);
948
949 return FALSE(0);
950 }
951
952 return TRUE(!(0));
953}
954
955static void
956ctk_stack_schedule_ticks (CtkStack *stack)
957{
958 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
959
960 if (priv->tick_id == 0)
961 {
962 priv->tick_id =
963 ctk_widget_add_tick_callback (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
, ctk_stack_transition_cb, stack, NULL((void*)0));
964 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_TRANSITION_RUNNING]);
965 }
966}
967
968static void
969ctk_stack_unschedule_ticks (CtkStack *stack)
970{
971 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
972
973 if (priv->tick_id != 0)
974 {
975 ctk_widget_remove_tick_callback (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
, priv->tick_id);
976 priv->tick_id = 0;
977 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_TRANSITION_RUNNING]);
978 }
979}
980
981static CtkStackTransitionType
982effective_transition_type (CtkStack *stack,
983 CtkStackTransitionType transition_type)
984{
985 if (ctk_widget_get_direction (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL)
986 {
987 switch (transition_type)
988 {
989 case CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
990 return CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT;
991 case CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
992 return CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT;
993 case CTK_STACK_TRANSITION_TYPE_OVER_LEFT:
994 return CTK_STACK_TRANSITION_TYPE_OVER_RIGHT;
995 case CTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
996 return CTK_STACK_TRANSITION_TYPE_OVER_LEFT;
997 case CTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
998 return CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT;
999 case CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
1000 return CTK_STACK_TRANSITION_TYPE_UNDER_LEFT;
1001 default: ;
1002 }
1003 }
1004
1005 return transition_type;
1006}
1007
1008static void
1009ctk_stack_start_transition (CtkStack *stack,
1010 CtkStackTransitionType transition_type,
1011 guint transition_duration)
1012{
1013 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1014 CtkWidget *widget = CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
;
1015
1016 if (ctk_widget_get_mapped (widget) &&
1017 ctk_settings_get_enable_animations (ctk_widget_get_settings (widget)) &&
1018 transition_type != CTK_STACK_TRANSITION_TYPE_NONE &&
1019 transition_duration != 0 &&
1020 priv->last_visible_child != NULL((void*)0))
1021 {
1022 priv->active_transition_type = effective_transition_type (stack, transition_type);
1023 priv->first_frame_skipped = FALSE(0);
1024 ctk_stack_schedule_ticks (stack);
1025 ctk_progress_tracker_start (&priv->tracker,
1026 priv->transition_duration * 1000,
1027 0,
1028 1.0);
1029 }
1030 else
1031 {
1032 ctk_stack_unschedule_ticks (stack);
1033 priv->active_transition_type = CTK_STACK_TRANSITION_TYPE_NONE;
1034 ctk_progress_tracker_finish (&priv->tracker);
1035 }
1036
1037 ctk_stack_progress_updated (CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
);
1038}
1039
1040static void
1041set_visible_child (CtkStack *stack,
1042 CtkStackChildInfo *child_info,
1043 CtkStackTransitionType transition_type,
1044 guint transition_duration)
1045{
1046 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1047 CtkStackChildInfo *info;
1048 CtkWidget *widget = CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
;
1049 GList *l;
1050 CtkWidget *toplevel;
1051 CtkWidget *focus;
1052 gboolean contains_focus = FALSE(0);
1053
1054 /* if we are being destroyed, do not bother with transitions
1055 * and notifications
1056 */
1057 if (ctk_widget_in_destruction (widget))
1058 return;
1059
1060 /* If none, pick first visible */
1061 if (child_info == NULL((void*)0))
1062 {
1063 for (l = priv->children; l != NULL((void*)0); l = l->next)
1064 {
1065 info = l->data;
1066 if (ctk_widget_get_visible (info->widget))
1067 {
1068 child_info = info;
1069 break;
1070 }
1071 }
1072 }
1073
1074 if (child_info == priv->visible_child)
1075 return;
1076
1077 toplevel = ctk_widget_get_toplevel (widget);
1078 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; }))))
)
1079 {
1080 focus = ctk_window_get_focus (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
1081 if (focus &&
1082 priv->visible_child &&
1083 priv->visible_child->widget &&
1084 ctk_widget_is_ancestor (focus, priv->visible_child->widget))
1085 {
1086 contains_focus = TRUE(!(0));
1087
1088 if (priv->visible_child->last_focus)
1089 g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->visible_child->last_focus)), (((GType) ((20)
<< (2))))))))
,
1090 (gpointer *)&priv->visible_child->last_focus);
1091 priv->visible_child->last_focus = focus;
1092 g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->visible_child->last_focus)), (((GType) ((20)
<< (2))))))))
,
1093 (gpointer *)&priv->visible_child->last_focus);
1094 }
1095 }
1096
1097 if (priv->last_visible_child)
1098 ctk_widget_set_child_visible (priv->last_visible_child->widget, FALSE(0));
1099 priv->last_visible_child = NULL((void*)0);
1100
1101 if (priv->last_visible_surface != NULL((void*)0))
1102 cairo_surface_destroy (priv->last_visible_surface);
1103 priv->last_visible_surface = NULL((void*)0);
1104
1105 if (priv->visible_child && priv->visible_child->widget)
1106 {
1107 if (ctk_widget_is_visible (widget))
1108 {
1109 CtkAllocation allocation;
1110
1111 priv->last_visible_child = priv->visible_child;
1112 ctk_widget_get_allocated_size (priv->last_visible_child->widget, &allocation, NULL((void*)0));
1113 priv->last_visible_widget_width = allocation.width;
1114 priv->last_visible_widget_height = allocation.height;
1115 }
1116 else
1117 {
1118 ctk_widget_set_child_visible (priv->visible_child->widget, FALSE(0));
1119 }
1120 }
1121
1122 ctk_stack_accessible_update_visible_child (stack,
1123 priv->visible_child ? priv->visible_child->widget : NULL((void*)0),
1124 child_info ? child_info->widget : NULL((void*)0));
1125
1126 priv->visible_child = child_info;
1127
1128 if (child_info)
1129 {
1130 ctk_widget_set_child_visible (child_info->widget, TRUE(!(0)));
1131
1132 if (contains_focus)
1133 {
1134 if (child_info->last_focus)
1135 ctk_widget_grab_focus (child_info->last_focus);
1136 else
1137 ctk_widget_child_focus (child_info->widget, CTK_DIR_TAB_FORWARD);
1138 }
1139 }
1140
1141 if ((child_info == NULL((void*)0) || priv->last_visible_child == NULL((void*)0)) &&
1142 is_direction_dependent_transition (transition_type))
1143 {
1144 transition_type = CTK_STACK_TRANSITION_TYPE_NONE;
1145 }
1146 else if (is_direction_dependent_transition (transition_type))
1147 {
1148 gboolean i_first = FALSE(0);
1149 for (l = priv->children; l != NULL((void*)0); l = l->next)
1150 {
1151 if (child_info == l->data)
1152 {
1153 i_first = TRUE(!(0));
1154 break;
1155 }
1156 if (priv->last_visible_child == l->data)
1157 break;
1158 }
1159
1160 transition_type = get_simple_transition_type (i_first, transition_type);
1161 }
1162
1163 if (priv->hhomogeneous && priv->vhomogeneous)
1164 ctk_widget_queue_allocate (widget);
1165 else
1166 ctk_widget_queue_resize (widget);
1167
1168 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_VISIBLE_CHILD]);
1169 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
,
1170 stack_props[PROP_VISIBLE_CHILD_NAME]);
1171
1172 ctk_stack_start_transition (stack, transition_type, transition_duration);
1173}
1174
1175static void
1176stack_child_visibility_notify_cb (GObject *obj,
1177 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
1178 gpointer user_data)
1179{
1180 CtkStack *stack = CTK_STACK (user_data)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((ctk_stack_get_type ()))))))
;
1181 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1182 CtkWidget *child = CTK_WIDGET (obj)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((obj)), ((ctk_widget_get_type ()))))))
;
1183 CtkStackChildInfo *child_info;
1184
1185 child_info = find_child_info_for_widget (stack, child);
1186
1187 if (priv->visible_child == NULL((void*)0) &&
1
Assuming field 'visible_child' is equal to NULL
1188 ctk_widget_get_visible (child))
2
Assuming the condition is false
1189 set_visible_child (stack, child_info, priv->transition_type, priv->transition_duration);
1190 else if (priv->visible_child == child_info &&
3
Assuming 'child_info' is equal to field 'visible_child'
5
Taking false branch
1191 !ctk_widget_get_visible (child))
4
Assuming the condition is false
1192 set_visible_child (stack, NULL((void*)0), priv->transition_type, priv->transition_duration);
1193
1194 if (child_info == priv->last_visible_child)
6
Assuming 'child_info' is equal to field 'last_visible_child'
7
Taking true branch
1195 {
1196 ctk_widget_set_child_visible (priv->last_visible_child->widget, FALSE(0));
8
Access to field 'widget' results in a dereference of a null pointer (loaded from field 'last_visible_child')
1197 priv->last_visible_child = NULL((void*)0);
1198 }
1199}
1200
1201/**
1202 * ctk_stack_add_titled:
1203 * @stack: a #CtkStack
1204 * @child: the widget to add
1205 * @name: the name for @child
1206 * @title: a human-readable title for @child
1207 *
1208 * Adds a child to @stack.
1209 * The child is identified by the @name. The @title
1210 * will be used by #CtkStackSwitcher to represent
1211 * @child in a tab bar, so it should be short.
1212 *
1213 * Since: 3.10
1214 */
1215void
1216ctk_stack_add_titled (CtkStack *stack,
1217 CtkWidget *child,
1218 const gchar *name,
1219 const gchar *title)
1220{
1221 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1222 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)
;
1223
1224 ctk_container_add_with_properties (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
1225 child,
1226 "name", name,
1227 "title", title,
1228 NULL((void*)0));
1229}
1230
1231/**
1232 * ctk_stack_add_named:
1233 * @stack: a #CtkStack
1234 * @child: the widget to add
1235 * @name: the name for @child
1236 *
1237 * Adds a child to @stack.
1238 * The child is identified by the @name.
1239 *
1240 * Since: 3.10
1241 */
1242void
1243ctk_stack_add_named (CtkStack *stack,
1244 CtkWidget *child,
1245 const gchar *name)
1246{
1247 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1248 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)
;
1249
1250 ctk_container_add_with_properties (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
1251 child,
1252 "name", name,
1253 NULL((void*)0));
1254}
1255
1256static void
1257ctk_stack_add (CtkContainer *container,
1258 CtkWidget *child)
1259{
1260 CtkStack *stack = CTK_STACK (container)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_stack_get_type ()))))))
;
1261 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1262 CtkStackChildInfo *child_info;
1263
1264 g_return_if_fail (child != NULL)do { if ((child != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child != NULL"); return
; } } while (0)
;
1265
1266 child_info = g_slice_new (CtkStackChildInfo)((CtkStackChildInfo*) g_slice_alloc (sizeof (CtkStackChildInfo
)))
;
1267 child_info->widget = child;
1268 child_info->name = NULL((void*)0);
1269 child_info->title = NULL((void*)0);
1270 child_info->icon_name = NULL((void*)0);
1271 child_info->needs_attention = FALSE(0);
1272 child_info->last_focus = NULL((void*)0);
1273
1274 priv->children = g_list_append (priv->children, child_info);
1275
1276 ctk_widget_set_child_visible (child, FALSE(0));
1277 ctk_widget_set_parent_window (child, priv->bin_window);
1278 ctk_widget_set_parent (child, CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1279
1280 if (priv->bin_window)
1281 cdk_window_set_events (priv->bin_window,
1282 cdk_window_get_events (priv->bin_window) |
1283 ctk_widget_get_events (child));
1284
1285 g_signal_connect (child, "notify::visible",g_signal_connect_data ((child), ("notify::visible"), (((GCallback
) (stack_child_visibility_notify_cb))), (stack), ((void*)0), (
GConnectFlags) 0)
1286 G_CALLBACK (stack_child_visibility_notify_cb), stack)g_signal_connect_data ((child), ("notify::visible"), (((GCallback
) (stack_child_visibility_notify_cb))), (stack), ((void*)0), (
GConnectFlags) 0)
;
1287
1288 ctk_container_child_notify_by_pspec (container, child, stack_child_props[CHILD_PROP_POSITION]);
1289
1290 if (priv->visible_child == NULL((void*)0) &&
1291 ctk_widget_get_visible (child))
1292 set_visible_child (stack, child_info, priv->transition_type, priv->transition_duration);
1293
1294 if (priv->hhomogeneous || priv->vhomogeneous || priv->visible_child == child_info)
1295 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1296}
1297
1298static void
1299ctk_stack_remove (CtkContainer *container,
1300 CtkWidget *child)
1301{
1302 CtkStack *stack = CTK_STACK (container)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_stack_get_type ()))))))
;
1303 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1304 CtkStackChildInfo *child_info;
1305 gboolean was_visible;
1306
1307 child_info = find_child_info_for_widget (stack, child);
1308 if (child_info == NULL((void*)0))
1309 return;
1310
1311 priv->children = g_list_remove (priv->children, child_info);
1312
1313 g_signal_handlers_disconnect_by_func (child,g_signal_handlers_disconnect_matched ((child), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (stack_child_visibility_notify_cb), (stack))
1314 stack_child_visibility_notify_cb,g_signal_handlers_disconnect_matched ((child), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (stack_child_visibility_notify_cb), (stack))
1315 stack)g_signal_handlers_disconnect_matched ((child), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (stack_child_visibility_notify_cb), (stack))
;
1316
1317 was_visible = ctk_widget_get_visible (child);
1318
1319 child_info->widget = NULL((void*)0);
1320
1321 if (priv->visible_child == child_info)
1322 set_visible_child (stack, NULL((void*)0), priv->transition_type, priv->transition_duration);
1323
1324 if (priv->last_visible_child == child_info)
1325 priv->last_visible_child = NULL((void*)0);
1326
1327 ctk_widget_unparent (child);
1328
1329 g_free (child_info->name);
1330 g_free (child_info->title);
1331 g_free (child_info->icon_name);
1332
1333 if (child_info->last_focus)
1334 g_object_remove_weak_pointer (G_OBJECT (child_info->last_focus)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child_info->last_focus)), (((GType) ((20) << (2
))))))))
,
1335 (gpointer *)&child_info->last_focus);
1336
1337 g_slice_free (CtkStackChildInfo, child_info)do { if (1) g_slice_free1 (sizeof (CtkStackChildInfo), (child_info
)); else (void) ((CtkStackChildInfo*) 0 == (child_info)); } while
(0)
;
1338
1339 if ((priv->hhomogeneous || priv->vhomogeneous) && was_visible)
1340 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1341}
1342
1343/**
1344 * ctk_stack_get_child_by_name:
1345 * @stack: a #CtkStack
1346 * @name: the name of the child to find
1347 *
1348 * Finds the child of the #CtkStack with the name given as
1349 * the argument. Returns %NULL if there is no child with this
1350 * name.
1351 *
1352 * Returns: (transfer none) (nullable): the requested child of the #CtkStack
1353 *
1354 * Since: 3.12
1355 */
1356CtkWidget *
1357ctk_stack_get_child_by_name (CtkStack *stack,
1358 const gchar *name)
1359{
1360 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1361 CtkStackChildInfo *info;
1362 GList *l;
1363
1364 g_return_val_if_fail (CTK_IS_STACK (stack), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return (((void*)0)); } } while (
0)
;
1365 g_return_val_if_fail (name != NULL, NULL)do { if ((name != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "name != NULL"); return (
((void*)0)); } } while (0)
;
1366
1367 for (l = priv->children; l != NULL((void*)0); l = l->next)
1368 {
1369 info = l->data;
1370 if (info->name && strcmp (info->name, name) == 0)
1371 return info->widget;
1372 }
1373
1374 return NULL((void*)0);
1375}
1376
1377/**
1378 * ctk_stack_set_homogeneous:
1379 * @stack: a #CtkStack
1380 * @homogeneous: %TRUE to make @stack homogeneous
1381 *
1382 * Sets the #CtkStack to be homogeneous or not. If it
1383 * is homogeneous, the #CtkStack will request the same
1384 * size for all its children. If it isn't, the stack
1385 * may change size when a different child becomes visible.
1386 *
1387 * Since 3.16, homogeneity can be controlled separately
1388 * for horizontal and vertical size, with the
1389 * #CtkStack:hhomogeneous and #CtkStack:vhomogeneous.
1390 *
1391 * Since: 3.10
1392 */
1393void
1394ctk_stack_set_homogeneous (CtkStack *stack,
1395 gboolean homogeneous)
1396{
1397 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1398
1399 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1400
1401 homogeneous = !!homogeneous;
1402
1403 if ((priv->hhomogeneous && priv->vhomogeneous) == homogeneous)
1404 return;
1405
1406 g_object_freeze_notify (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
);
1407
1408 if (priv->hhomogeneous != homogeneous)
1409 {
1410 priv->hhomogeneous = homogeneous;
1411 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_HHOMOGENEOUS]);
1412 }
1413
1414 if (priv->vhomogeneous != homogeneous)
1415 {
1416 priv->vhomogeneous = homogeneous;
1417 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_VHOMOGENEOUS]);
1418 }
1419
1420 if (ctk_widget_get_visible (CTK_WIDGET(stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
))
1421 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1422
1423 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_HOMOGENEOUS]);
1424 g_object_thaw_notify (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
);
1425}
1426
1427/**
1428 * ctk_stack_get_homogeneous:
1429 * @stack: a #CtkStack
1430 *
1431 * Gets whether @stack is homogeneous.
1432 * See ctk_stack_set_homogeneous().
1433 *
1434 * Returns: whether @stack is homogeneous.
1435 *
1436 * Since: 3.10
1437 */
1438gboolean
1439ctk_stack_get_homogeneous (CtkStack *stack)
1440{
1441 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1442
1443 g_return_val_if_fail (CTK_IS_STACK (stack), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return ((0)); } } while (0)
;
1444
1445 return priv->hhomogeneous && priv->vhomogeneous;
1446}
1447
1448/**
1449 * ctk_stack_set_hhomogeneous:
1450 * @stack: a #CtkStack
1451 * @hhomogeneous: %TRUE to make @stack horizontally homogeneous
1452 *
1453 * Sets the #CtkStack to be horizontally homogeneous or not.
1454 * If it is homogeneous, the #CtkStack will request the same
1455 * width for all its children. If it isn't, the stack
1456 * may change width when a different child becomes visible.
1457 *
1458 * Since: 3.16
1459 */
1460void
1461ctk_stack_set_hhomogeneous (CtkStack *stack,
1462 gboolean hhomogeneous)
1463{
1464 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1465
1466 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1467
1468 hhomogeneous = !!hhomogeneous;
1469
1470 if (priv->hhomogeneous == hhomogeneous)
1471 return;
1472
1473 priv->hhomogeneous = hhomogeneous;
1474
1475 if (ctk_widget_get_visible (CTK_WIDGET(stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
))
1476 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1477
1478 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_HHOMOGENEOUS]);
1479}
1480
1481/**
1482 * ctk_stack_get_hhomogeneous:
1483 * @stack: a #CtkStack
1484 *
1485 * Gets whether @stack is horizontally homogeneous.
1486 * See ctk_stack_set_hhomogeneous().
1487 *
1488 * Returns: whether @stack is horizontally homogeneous.
1489 *
1490 * Since: 3.16
1491 */
1492gboolean
1493ctk_stack_get_hhomogeneous (CtkStack *stack)
1494{
1495 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1496
1497 g_return_val_if_fail (CTK_IS_STACK (stack), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return ((0)); } } while (0)
;
1498
1499 return priv->hhomogeneous;
1500}
1501
1502/**
1503 * ctk_stack_set_vhomogeneous:
1504 * @stack: a #CtkStack
1505 * @vhomogeneous: %TRUE to make @stack vertically homogeneous
1506 *
1507 * Sets the #CtkStack to be vertically homogeneous or not.
1508 * If it is homogeneous, the #CtkStack will request the same
1509 * height for all its children. If it isn't, the stack
1510 * may change height when a different child becomes visible.
1511 *
1512 * Since: 3.16
1513 */
1514void
1515ctk_stack_set_vhomogeneous (CtkStack *stack,
1516 gboolean vhomogeneous)
1517{
1518 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1519
1520 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1521
1522 vhomogeneous = !!vhomogeneous;
1523
1524 if (priv->vhomogeneous == vhomogeneous)
1525 return;
1526
1527 priv->vhomogeneous = vhomogeneous;
1528
1529 if (ctk_widget_get_visible (CTK_WIDGET(stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
))
1530 ctk_widget_queue_resize (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
);
1531
1532 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
, stack_props[PROP_VHOMOGENEOUS]);
1533}
1534
1535/**
1536 * ctk_stack_get_vhomogeneous:
1537 * @stack: a #CtkStack
1538 *
1539 * Gets whether @stack is vertically homogeneous.
1540 * See ctk_stack_set_vhomogeneous().
1541 *
1542 * Returns: whether @stack is vertically homogeneous.
1543 *
1544 * Since: 3.16
1545 */
1546gboolean
1547ctk_stack_get_vhomogeneous (CtkStack *stack)
1548{
1549 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1550
1551 g_return_val_if_fail (CTK_IS_STACK (stack), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return ((0)); } } while (0)
;
1552
1553 return priv->vhomogeneous;
1554}
1555
1556/**
1557 * ctk_stack_get_transition_duration:
1558 * @stack: a #CtkStack
1559 *
1560 * Returns the amount of time (in milliseconds) that
1561 * transitions between pages in @stack will take.
1562 *
1563 * Returns: the transition duration
1564 *
1565 * Since: 3.10
1566 */
1567guint
1568ctk_stack_get_transition_duration (CtkStack *stack)
1569{
1570 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1571
1572 g_return_val_if_fail (CTK_IS_STACK (stack), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return (0); } } while (0)
;
1573
1574 return priv->transition_duration;
1575}
1576
1577/**
1578 * ctk_stack_set_transition_duration:
1579 * @stack: a #CtkStack
1580 * @duration: the new duration, in milliseconds
1581 *
1582 * Sets the duration that transitions between pages in @stack
1583 * will take.
1584 *
1585 * Since: 3.10
1586 */
1587void
1588ctk_stack_set_transition_duration (CtkStack *stack,
1589 guint duration)
1590{
1591 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1592
1593 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1594
1595 if (priv->transition_duration == duration)
1596 return;
1597
1598 priv->transition_duration = duration;
1599 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
,
1600 stack_props[PROP_TRANSITION_DURATION]);
1601}
1602
1603/**
1604 * ctk_stack_get_transition_type:
1605 * @stack: a #CtkStack
1606 *
1607 * Gets the type of animation that will be used
1608 * for transitions between pages in @stack.
1609 *
1610 * Returns: the current transition type of @stack
1611 *
1612 * Since: 3.10
1613 */
1614CtkStackTransitionType
1615ctk_stack_get_transition_type (CtkStack *stack)
1616{
1617 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1618
1619 g_return_val_if_fail (CTK_IS_STACK (stack), CTK_STACK_TRANSITION_TYPE_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return (CTK_STACK_TRANSITION_TYPE_NONE
); } } while (0)
;
1620
1621 return priv->transition_type;
1622}
1623
1624/**
1625 * ctk_stack_set_transition_type:
1626 * @stack: a #CtkStack
1627 * @transition: the new transition type
1628 *
1629 * Sets the type of animation that will be used for
1630 * transitions between pages in @stack. Available
1631 * types include various kinds of fades and slides.
1632 *
1633 * The transition type can be changed without problems
1634 * at runtime, so it is possible to change the animation
1635 * based on the page that is about to become current.
1636 *
1637 * Since: 3.10
1638 */
1639void
1640ctk_stack_set_transition_type (CtkStack *stack,
1641 CtkStackTransitionType transition)
1642{
1643 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1644
1645 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1646
1647 if (priv->transition_type == transition)
1648 return;
1649
1650 priv->transition_type = transition;
1651 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
,
1652 stack_props[PROP_TRANSITION_TYPE]);
1653}
1654
1655/**
1656 * ctk_stack_get_transition_running:
1657 * @stack: a #CtkStack
1658 *
1659 * Returns whether the @stack is currently in a transition from one page to
1660 * another.
1661 *
1662 * Returns: %TRUE if the transition is currently running, %FALSE otherwise.
1663 *
1664 * Since: 3.12
1665 */
1666gboolean
1667ctk_stack_get_transition_running (CtkStack *stack)
1668{
1669 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1670
1671 g_return_val_if_fail (CTK_IS_STACK (stack), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return ((0)); } } while (0)
;
1672
1673 return (priv->tick_id != 0);
1674}
1675
1676/**
1677 * ctk_stack_set_interpolate_size:
1678 * @stack: A #CtkStack
1679 * @interpolate_size: the new value
1680 *
1681 * Sets whether or not @stack will interpolate its size when
1682 * changing the visible child. If the #CtkStack:interpolate-size
1683 * property is set to %TRUE, @stack will interpolate its size between
1684 * the current one and the one it'll take after changing the
1685 * visible child, according to the set transition duration.
1686 *
1687 * Since: 3.18
1688 */
1689void
1690ctk_stack_set_interpolate_size (CtkStack *stack,
1691 gboolean interpolate_size)
1692{
1693 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1694 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1695
1696 interpolate_size = !!interpolate_size;
1697
1698 if (priv->interpolate_size == interpolate_size)
1699 return;
1700
1701 priv->interpolate_size = interpolate_size;
1702 g_object_notify_by_pspec (G_OBJECT (stack)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), (((GType) ((20) << (2))))))))
,
1703 stack_props[PROP_INTERPOLATE_SIZE]);
1704}
1705
1706/**
1707 * ctk_stack_get_interpolate_size:
1708 * @stack: A #CtkStack
1709 *
1710 * Returns wether the #CtkStack is set up to interpolate between
1711 * the sizes of children on page switch.
1712 *
1713 * Returns: %TRUE if child sizes are interpolated
1714 *
1715 * Since: 3.18
1716 */
1717gboolean
1718ctk_stack_get_interpolate_size (CtkStack *stack)
1719{
1720 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1721 g_return_val_if_fail (CTK_IS_STACK (stack), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return ((0)); } } while (0)
;
1722
1723 return priv->interpolate_size;
1724}
1725
1726
1727
1728/**
1729 * ctk_stack_get_visible_child:
1730 * @stack: a #CtkStack
1731 *
1732 * Gets the currently visible child of @stack, or %NULL if
1733 * there are no visible children.
1734 *
1735 * Returns: (transfer none) (nullable): the visible child of the #CtkStack
1736 *
1737 * Since: 3.10
1738 */
1739CtkWidget *
1740ctk_stack_get_visible_child (CtkStack *stack)
1741{
1742 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1743
1744 g_return_val_if_fail (CTK_IS_STACK (stack), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return (((void*)0)); } } while (
0)
;
1745
1746 return priv->visible_child ? priv->visible_child->widget : NULL((void*)0);
1747}
1748
1749/**
1750 * ctk_stack_get_visible_child_name:
1751 * @stack: a #CtkStack
1752 *
1753 * Returns the name of the currently visible child of @stack, or
1754 * %NULL if there is no visible child.
1755 *
1756 * Returns: (transfer none) (nullable): the name of the visible child of the #CtkStack
1757 *
1758 * Since: 3.10
1759 */
1760const gchar *
1761ctk_stack_get_visible_child_name (CtkStack *stack)
1762{
1763 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1764
1765 g_return_val_if_fail (CTK_IS_STACK (stack), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return (((void*)0)); } } while (
0)
;
1766
1767 if (priv->visible_child)
1768 return priv->visible_child->name;
1769
1770 return NULL((void*)0);
1771}
1772
1773/**
1774 * ctk_stack_set_visible_child:
1775 * @stack: a #CtkStack
1776 * @child: a child of @stack
1777 *
1778 * Makes @child the visible child of @stack.
1779 *
1780 * If @child is different from the currently
1781 * visible child, the transition between the
1782 * two will be animated with the current
1783 * transition type of @stack.
1784 *
1785 * Note that the @child widget has to be visible itself
1786 * (see ctk_widget_show()) in order to become the visible
1787 * child of @stack.
1788 *
1789 * Since: 3.10
1790 */
1791void
1792ctk_stack_set_visible_child (CtkStack *stack,
1793 CtkWidget *child)
1794{
1795 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1796 CtkStackChildInfo *child_info;
1797
1798 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1799 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)
;
1800
1801 child_info = find_child_info_for_widget (stack, child);
1802 if (child_info == NULL((void*)0))
1803 {
1804 g_warning ("Given child of type '%s' not found in CtkStack",
1805 G_OBJECT_TYPE_NAME (child)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (child))->
g_class))->g_type)))))
);
1806 return;
1807 }
1808
1809 if (ctk_widget_get_visible (child_info->widget))
1810 set_visible_child (stack, child_info,
1811 priv->transition_type,
1812 priv->transition_duration);
1813}
1814
1815/**
1816 * ctk_stack_set_visible_child_name:
1817 * @stack: a #CtkStack
1818 * @name: the name of the child to make visible
1819 *
1820 * Makes the child with the given name visible.
1821 *
1822 * If @child is different from the currently
1823 * visible child, the transition between the
1824 * two will be animated with the current
1825 * transition type of @stack.
1826 *
1827 * Note that the child widget has to be visible itself
1828 * (see ctk_widget_show()) in order to become the visible
1829 * child of @stack.
1830 *
1831 * Since: 3.10
1832 */
1833void
1834ctk_stack_set_visible_child_name (CtkStack *stack,
1835 const gchar *name)
1836{
1837 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1838
1839 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1840
1841 ctk_stack_set_visible_child_full (stack, name, priv->transition_type);
1842}
1843
1844/**
1845 * ctk_stack_set_visible_child_full:
1846 * @stack: a #CtkStack
1847 * @name: the name of the child to make visible
1848 * @transition: the transition type to use
1849 *
1850 * Makes the child with the given name visible.
1851 *
1852 * Note that the child widget has to be visible itself
1853 * (see ctk_widget_show()) in order to become the visible
1854 * child of @stack.
1855 *
1856 * Since: 3.10
1857 */
1858void
1859ctk_stack_set_visible_child_full (CtkStack *stack,
1860 const gchar *name,
1861 CtkStackTransitionType transition)
1862{
1863 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1864 CtkStackChildInfo *child_info, *info;
1865 GList *l;
1866
1867 g_return_if_fail (CTK_IS_STACK (stack))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stack)); GType __t = ((ctk_stack_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_STACK (stack)"); return; } } while (0)
;
1868
1869 if (name == NULL((void*)0))
1870 return;
1871
1872 child_info = NULL((void*)0);
1873 for (l = priv->children; l != NULL((void*)0); l = l->next)
1874 {
1875 info = l->data;
1876 if (info->name != NULL((void*)0) &&
1877 strcmp (info->name, name) == 0)
1878 {
1879 child_info = info;
1880 break;
1881 }
1882 }
1883
1884 if (child_info == NULL((void*)0))
1885 {
1886 g_warning ("Child name '%s' not found in CtkStack", name);
1887 return;
1888 }
1889
1890 if (ctk_widget_get_visible (child_info->widget))
1891 set_visible_child (stack, child_info, transition, priv->transition_duration);
1892}
1893
1894static void
1895ctk_stack_forall (CtkContainer *container,
1896 gboolean include_internals G_GNUC_UNUSED__attribute__ ((__unused__)),
1897 CtkCallback callback,
1898 gpointer callback_data)
1899{
1900 CtkStack *stack = CTK_STACK (container)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_stack_get_type ()))))))
;
1901 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1902 CtkStackChildInfo *child_info;
1903 GList *l;
1904
1905 l = priv->children;
1906 while (l)
1907 {
1908 child_info = l->data;
1909 l = l->next;
1910
1911 (* callback) (child_info->widget, callback_data);
1912 }
1913}
1914
1915static void
1916ctk_stack_compute_expand (CtkWidget *widget,
1917 gboolean *hexpand_p,
1918 gboolean *vexpand_p)
1919{
1920 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
1921 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1922 gboolean hexpand, vexpand;
1923 CtkStackChildInfo *child_info;
1924 CtkWidget *child;
1925 GList *l;
1926
1927 hexpand = FALSE(0);
1928 vexpand = FALSE(0);
1929 for (l = priv->children; l != NULL((void*)0); l = l->next)
1930 {
1931 child_info = l->data;
1932 child = child_info->widget;
1933
1934 if (!hexpand &&
1935 ctk_widget_compute_expand (child, CTK_ORIENTATION_HORIZONTAL))
1936 hexpand = TRUE(!(0));
1937
1938 if (!vexpand &&
1939 ctk_widget_compute_expand (child, CTK_ORIENTATION_VERTICAL))
1940 vexpand = TRUE(!(0));
1941
1942 if (hexpand && vexpand)
1943 break;
1944 }
1945
1946 *hexpand_p = hexpand;
1947 *vexpand_p = vexpand;
1948}
1949
1950static void
1951ctk_stack_draw_crossfade (CtkWidget *widget,
1952 cairo_t *cr)
1953{
1954 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
1955 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1956 gdouble progress = ctk_progress_tracker_get_progress (&priv->tracker, FALSE(0));
1957
1958 cairo_push_group (cr);
1959 ctk_container_propagate_draw (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
1960 priv->visible_child->widget,
1961 cr);
1962 cairo_save (cr);
1963
1964 /* Multiply alpha by progress */
1965 cairo_set_source_rgba (cr, 1, 1, 1, progress);
1966 cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN);
1967 cairo_paint (cr);
1968
1969 if (priv->last_visible_surface)
1970 {
1971 cairo_set_source_surface (cr, priv->last_visible_surface,
1972 priv->last_visible_surface_allocation.x,
1973 priv->last_visible_surface_allocation.y);
1974 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
1975 cairo_paint_with_alpha (cr, MAX (1.0 - progress, 0)(((1.0 - progress) > (0)) ? (1.0 - progress) : (0)));
1976 }
1977
1978 cairo_restore (cr);
1979
1980 cairo_pop_group_to_source (cr);
1981 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
1982 cairo_paint (cr);
1983}
1984
1985static void
1986ctk_stack_draw_under (CtkWidget *widget,
1987 cairo_t *cr)
1988{
1989 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
1990 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
1991 CtkAllocation allocation;
1992 gint x, y, width, height, pos_x, pos_y;
1993
1994 ctk_widget_get_allocation (widget, &allocation);
1995 x = y = 0;
1996 width = allocation.width;
1997 height = allocation.height;
1998 pos_x = pos_y = 0;
1999
2000 switch (priv->active_transition_type)
2001 {
2002 case CTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
2003 y = 0;
2004 height = allocation.height * (ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
2005 pos_y = height;
2006 break;
2007 case CTK_STACK_TRANSITION_TYPE_UNDER_UP:
2008 y = allocation.height * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
2009 height = allocation.height - y;
2010 pos_y = y - allocation.height;
2011 break;
2012 case CTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
2013 x = allocation.width * (1 - ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
2014 width = allocation.width - x;
2015 pos_x = x - allocation.width;
2016 break;
2017 case CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
2018 x = 0;
2019 width = allocation.width * (ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)));
2020 pos_x = width;
2021 break;
2022 default:
2023 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkstack.c", 2023, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
2024 }
2025
2026 cairo_save (cr);
2027 cairo_rectangle (cr, x, y, width, height);
2028 cairo_clip (cr);
2029
2030 ctk_container_propagate_draw (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
2031 priv->visible_child->widget,
2032 cr);
2033
2034 cairo_restore (cr);
2035
2036 if (priv->last_visible_surface)
2037 {
2038 cairo_set_source_surface (cr, priv->last_visible_surface, pos_x, pos_y);
2039 cairo_paint (cr);
2040 }
2041}
2042
2043static void
2044ctk_stack_draw_slide (CtkWidget *widget,
2045 cairo_t *cr)
2046{
2047 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2048 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2049
2050 if (priv->last_visible_surface &&
2051 ctk_cairo_should_draw_window (cr, priv->view_window))
2052 {
2053 CtkAllocation allocation;
2054 int x, y;
2055
2056 ctk_widget_get_allocation (widget, &allocation);
2057
2058 x = get_bin_window_x (stack, &allocation);
2059 y = get_bin_window_y (stack, &allocation);
2060
2061 switch (priv->active_transition_type)
2062 {
2063 case CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
2064 x -= allocation.width;
2065 break;
2066 case CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
2067 x += allocation.width;
2068 break;
2069 case CTK_STACK_TRANSITION_TYPE_SLIDE_UP:
2070 y -= allocation.height;
2071 break;
2072 case CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN:
2073 y += allocation.height;
2074 break;
2075 case CTK_STACK_TRANSITION_TYPE_OVER_UP:
2076 case CTK_STACK_TRANSITION_TYPE_OVER_DOWN:
2077 y = 0;
2078 break;
2079 case CTK_STACK_TRANSITION_TYPE_OVER_LEFT:
2080 case CTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
2081 x = 0;
2082 break;
2083 default:
2084 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkstack.c", 2084, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
2085 break;
2086 }
2087
2088 x += priv->last_visible_surface_allocation.x;
2089 y += priv->last_visible_surface_allocation.y;
2090
2091 if (priv->last_visible_child != NULL((void*)0))
2092 {
2093 if (ctk_widget_get_valign (priv->last_visible_child->widget) == CTK_ALIGN_END &&
2094 priv->last_visible_widget_height > allocation.height)
2095 y -= priv->last_visible_widget_height - allocation.height;
2096 else if (ctk_widget_get_valign (priv->last_visible_child->widget) == CTK_ALIGN_CENTER)
2097 y -= (priv->last_visible_widget_height - allocation.height) / 2;
2098 }
2099
2100 cairo_save (cr);
2101 cairo_set_source_surface (cr, priv->last_visible_surface, x, y);
2102 cairo_paint (cr);
2103 cairo_restore (cr);
2104 }
2105
2106 if (ctk_cairo_should_draw_window (cr, priv->bin_window))
2107 ctk_container_propagate_draw (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
2108 priv->visible_child->widget,
2109 cr);
2110}
2111
2112static gboolean
2113ctk_stack_draw (CtkWidget *widget,
2114 cairo_t *cr)
2115{
2116 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2117 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2118
2119 ctk_css_gadget_draw (priv->gadget, cr);
2120
2121 return FALSE(0);
2122}
2123
2124static gboolean
2125ctk_stack_render (CtkCssGadget *gadget,
2126 cairo_t *cr,
2127 int x G_GNUC_UNUSED__attribute__ ((__unused__)),
2128 int y G_GNUC_UNUSED__attribute__ ((__unused__)),
2129 int width G_GNUC_UNUSED__attribute__ ((__unused__)),
2130 int height G_GNUC_UNUSED__attribute__ ((__unused__)),
2131 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
2132{
2133 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
2134 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2135 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2136 cairo_t *pattern_cr;
2137
2138 if (ctk_cairo_should_draw_window (cr, priv->view_window))
2139 {
2140 CtkStyleContext *context;
2141
2142 context = ctk_widget_get_style_context (widget);
2143 ctk_render_background (context,
2144 cr,
2145 0, 0,
2146 ctk_widget_get_allocated_width (widget),
2147 ctk_widget_get_allocated_height (widget));
2148 }
2149
2150 if (priv->visible_child)
2151 {
2152 if (ctk_progress_tracker_get_state (&priv->tracker) != CTK_PROGRESS_STATE_AFTER)
2153 {
2154 if (priv->last_visible_surface == NULL((void*)0) &&
2155 priv->last_visible_child != NULL((void*)0))
2156 {
2157 ctk_widget_get_allocation (priv->last_visible_child->widget,
2158 &priv->last_visible_surface_allocation);
2159 priv->last_visible_surface =
2160 cdk_window_create_similar_surface (ctk_widget_get_window (widget),
2161 CAIRO_CONTENT_COLOR_ALPHA,
2162 priv->last_visible_surface_allocation.width,
2163 priv->last_visible_surface_allocation.height);
2164 pattern_cr = cairo_create (priv->last_visible_surface);
2165 /* We don't use propagate_draw here, because we don't want to apply
2166 * the bin_window offset
2167 */
2168 ctk_widget_draw (priv->last_visible_child->widget, pattern_cr);
2169 cairo_destroy (pattern_cr);
2170 }
2171
2172 cairo_rectangle (cr,
2173 0, 0,
2174 ctk_widget_get_allocated_width (widget),
2175 ctk_widget_get_allocated_height (widget));
2176 cairo_clip (cr);
2177
2178 switch (priv->active_transition_type)
2179 {
2180 case CTK_STACK_TRANSITION_TYPE_CROSSFADE:
2181 if (ctk_cairo_should_draw_window (cr, priv->bin_window))
2182 ctk_stack_draw_crossfade (widget, cr);
2183 break;
2184 case CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
2185 case CTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
2186 case CTK_STACK_TRANSITION_TYPE_SLIDE_UP:
2187 case CTK_STACK_TRANSITION_TYPE_SLIDE_DOWN:
2188 case CTK_STACK_TRANSITION_TYPE_OVER_UP:
2189 case CTK_STACK_TRANSITION_TYPE_OVER_DOWN:
2190 case CTK_STACK_TRANSITION_TYPE_OVER_LEFT:
2191 case CTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
2192 ctk_stack_draw_slide (widget, cr);
2193 break;
2194 case CTK_STACK_TRANSITION_TYPE_UNDER_UP:
2195 case CTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
2196 case CTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
2197 case CTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
2198 if (ctk_cairo_should_draw_window (cr, priv->bin_window))
2199 ctk_stack_draw_under (widget, cr);
2200 break;
2201 default:
2202 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkstack.c", 2202, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
2203 }
2204
2205 }
2206 else if (ctk_cairo_should_draw_window (cr, priv->bin_window))
2207 ctk_container_propagate_draw (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_container_get_type ()))))))
,
2208 priv->visible_child->widget,
2209 cr);
2210 }
2211
2212 return FALSE(0);
2213}
2214
2215static void
2216ctk_stack_size_allocate (CtkWidget *widget,
2217 CtkAllocation *allocation)
2218{
2219 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2220 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2221 CtkAllocation clip;
2222
2223 ctk_widget_set_allocation (widget, allocation);
2224
2225 ctk_css_gadget_allocate (priv->gadget,
2226 allocation,
2227 ctk_widget_get_allocated_baseline (widget),
2228 &clip);
2229
2230 ctk_widget_set_clip (widget, &clip);
2231}
2232
2233static void
2234ctk_stack_allocate (CtkCssGadget *gadget,
2235 const CtkAllocation *allocation,
2236 int baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
2237 CtkAllocation *out_clip,
2238 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
2239{
2240 CtkWidget *widget;
2241 CtkStack *stack;
2242 CtkStackPrivate *priv;
2243 CtkAllocation child_allocation;
2244
2245 widget = ctk_css_gadget_get_owner (gadget);
2246 stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2247 priv = ctk_stack_get_instance_private (stack);
2248
2249 child_allocation.x = 0;
2250 child_allocation.y = 0;
2251
2252 if (ctk_widget_get_realized (widget))
2253 {
2254 cdk_window_move_resize (priv->view_window,
2255 allocation->x, allocation->y,
2256 allocation->width, allocation->height);
2257 cdk_window_move_resize (priv->bin_window,
2258 get_bin_window_x (stack, allocation), get_bin_window_y (stack, allocation),
2259 allocation->width, allocation->height);
2260 }
2261
2262 if (priv->last_visible_child)
2263 {
2264 int min, nat;
2265 ctk_widget_get_preferred_width (priv->last_visible_child->widget, &min, &nat);
2266 child_allocation.width = MAX (min, allocation->width)(((min) > (allocation->width)) ? (min) : (allocation->
width))
;
2267 ctk_widget_get_preferred_height_for_width (priv->last_visible_child->widget,
2268 child_allocation.width,
2269 &min, &nat);
2270 child_allocation.height = MAX (min, allocation->height)(((min) > (allocation->height)) ? (min) : (allocation->
height))
;
2271
2272 ctk_widget_size_allocate (priv->last_visible_child->widget, &child_allocation);
2273 }
2274
2275 child_allocation.width = allocation->width;
2276 child_allocation.height = allocation->height;
2277
2278 if (priv->visible_child)
2279 {
2280 int min, nat;
2281 CtkAlign valign;
2282
2283 ctk_widget_get_preferred_height_for_width (priv->visible_child->widget,
2284 allocation->width,
2285 &min, &nat);
2286 if (priv->interpolate_size)
2287 {
2288 valign = ctk_widget_get_valign (priv->visible_child->widget);
2289 child_allocation.height = MAX (nat, allocation->height)(((nat) > (allocation->height)) ? (nat) : (allocation->
height))
;
2290 if (valign == CTK_ALIGN_END &&
2291 child_allocation.height > allocation->height)
2292 child_allocation.y -= nat - allocation->height;
2293 else if (valign == CTK_ALIGN_CENTER &&
2294 child_allocation.height > allocation->height)
2295 child_allocation.y -= (nat - allocation->height) / 2;
2296 }
2297
2298 ctk_widget_size_allocate (priv->visible_child->widget, &child_allocation);
2299 }
2300 ctk_container_get_children_clip (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
, out_clip);
2301}
2302
2303static void
2304ctk_stack_get_preferred_width (CtkWidget *widget,
2305 gint *minimum,
2306 gint *natural)
2307{
2308 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2309 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2310
2311 ctk_css_gadget_get_preferred_size (priv->gadget,
2312 CTK_ORIENTATION_HORIZONTAL,
2313 -1,
2314 minimum, natural,
2315 NULL((void*)0), NULL((void*)0));
2316}
2317
2318static void
2319ctk_stack_get_preferred_width_for_height (CtkWidget *widget,
2320 gint height,
2321 gint *minimum,
2322 gint *natural)
2323{
2324 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2325 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2326
2327 ctk_css_gadget_get_preferred_size (priv->gadget,
2328 CTK_ORIENTATION_HORIZONTAL,
2329 height,
2330 minimum, natural,
2331 NULL((void*)0), NULL((void*)0));
2332}
2333
2334static void
2335ctk_stack_get_preferred_height (CtkWidget *widget,
2336 gint *minimum,
2337 gint *natural)
2338{
2339 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2340 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2341
2342 ctk_css_gadget_get_preferred_size (priv->gadget,
2343 CTK_ORIENTATION_VERTICAL,
2344 -1,
2345 minimum, natural,
2346 NULL((void*)0), NULL((void*)0));
2347}
2348
2349static void
2350ctk_stack_get_preferred_height_for_width (CtkWidget *widget,
2351 gint width,
2352 gint *minimum,
2353 gint *natural)
2354{
2355 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2356 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2357
2358 ctk_css_gadget_get_preferred_size (priv->gadget,
2359 CTK_ORIENTATION_VERTICAL,
2360 width,
2361 minimum, natural,
2362 NULL((void*)0), NULL((void*)0));
2363}
2364
2365#define LERP(a, b, t)((a) + (((b) - (a)) * (1.0 - (t)))) ((a) + (((b) - (a)) * (1.0 - (t))))
2366
2367static void
2368ctk_stack_measure (CtkCssGadget *gadget,
2369 CtkOrientation orientation,
2370 int for_size,
2371 int *minimum,
2372 int *natural,
2373 int *minimum_baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
2374 int *natural_baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
2375 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
2376{
2377 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
2378 CtkStack *stack = CTK_STACK (widget)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_stack_get_type ()))))))
;
2379 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2380 CtkStackChildInfo *child_info;
2381 CtkWidget *child;
2382 gint child_min, child_nat;
2383 GList *l;
2384
2385 *minimum = 0;
2386 *natural = 0;
2387
2388 for (l = priv->children; l != NULL((void*)0); l = l->next)
2389 {
2390 child_info = l->data;
2391 child = child_info->widget;
2392
2393 if (((orientation == CTK_ORIENTATION_VERTICAL && !priv->vhomogeneous) ||
2394 (orientation == CTK_ORIENTATION_HORIZONTAL && !priv->hhomogeneous)) &&
2395 priv->visible_child != child_info)
2396 continue;
2397
2398 if (ctk_widget_get_visible (child))
2399 {
2400 if (orientation == CTK_ORIENTATION_VERTICAL)
2401 {
2402 if (for_size < 0)
2403 ctk_widget_get_preferred_height (child, &child_min, &child_nat);
2404 else
2405 ctk_widget_get_preferred_height_for_width (child, for_size, &child_min, &child_nat);
2406 }
2407 else
2408 {
2409 if (for_size < 0)
2410 ctk_widget_get_preferred_width (child, &child_min, &child_nat);
2411 else
2412 ctk_widget_get_preferred_width_for_height (child, for_size, &child_min, &child_nat);
2413 }
2414
2415 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
2416 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
2417 }
2418 }
2419
2420 if (priv->last_visible_child != NULL((void*)0))
2421 {
2422 if (orientation == CTK_ORIENTATION_VERTICAL && !priv->vhomogeneous)
2423 {
2424 gdouble t = priv->interpolate_size ? ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)) : 1.0;
2425 *minimum = LERP (*minimum, priv->last_visible_widget_height, t)((*minimum) + (((priv->last_visible_widget_height) - (*minimum
)) * (1.0 - (t))))
;
2426 *natural = LERP (*natural, priv->last_visible_widget_height, t)((*natural) + (((priv->last_visible_widget_height) - (*natural
)) * (1.0 - (t))))
;
2427 }
2428 if (orientation == CTK_ORIENTATION_HORIZONTAL && !priv->hhomogeneous)
2429 {
2430 gdouble t = priv->interpolate_size ? ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0)) : 1.0;
2431 *minimum = LERP (*minimum, priv->last_visible_widget_width, t)((*minimum) + (((priv->last_visible_widget_width) - (*minimum
)) * (1.0 - (t))))
;
2432 *natural = LERP (*natural, priv->last_visible_widget_width, t)((*natural) + (((priv->last_visible_widget_width) - (*natural
)) * (1.0 - (t))))
;
2433 }
2434 }
2435}
2436
2437static void
2438ctk_stack_init (CtkStack *stack)
2439{
2440 CtkStackPrivate *priv = ctk_stack_get_instance_private (stack);
2441
2442 ctk_widget_set_has_window (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
, FALSE(0));
2443
2444 priv->vhomogeneous = TRUE(!(0));
2445 priv->hhomogeneous = TRUE(!(0));
2446 priv->transition_duration = 200;
2447 priv->transition_type = CTK_STACK_TRANSITION_TYPE_NONE;
2448
2449 priv->gadget = ctk_css_custom_gadget_new_for_node (ctk_widget_get_css_node (CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
),
2450 CTK_WIDGET (stack)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_widget_get_type ()))))))
,
2451 ctk_stack_measure,
2452 ctk_stack_allocate,
2453 ctk_stack_render,
2454 NULL((void*)0),
2455 NULL((void*)0));
2456
2457}