Bug Summary

File:ctk/ctkpopover.c
Warning:line 1041, column 3
3rd function call argument is an uninitialized value

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 ctkpopover.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-170505-43637-1 -x c ctkpopover.c
1/* CTK - The GIMP Toolkit
2 * Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/**
19 * SECTION:ctkpopover
20 * @Short_description: Context dependent bubbles
21 * @Title: CtkPopover
22 *
23 * CtkPopover is a bubble-like context window, primarily meant to
24 * provide context-dependent information or options. Popovers are
25 * attached to a widget, passed at construction time on ctk_popover_new(),
26 * or updated afterwards through ctk_popover_set_relative_to(), by
27 * default they will point to the whole widget area, although this
28 * behavior can be changed through ctk_popover_set_pointing_to().
29 *
30 * The position of a popover relative to the widget it is attached to
31 * can also be changed through ctk_popover_set_position().
32 *
33 * By default, #CtkPopover performs a CTK+ grab, in order to ensure
34 * input events get redirected to it while it is shown, and also so
35 * the popover is dismissed in the expected situations (clicks outside
36 * the popover, or the Esc key being pressed). If no such modal behavior
37 * is desired on a popover, ctk_popover_set_modal() may be called on it
38 * to tweak its behavior.
39 *
40 * ## CtkPopover as menu replacement
41 *
42 * CtkPopover is often used to replace menus. To facilitate this, it
43 * supports being populated from a #GMenuModel, using
44 * ctk_popover_new_from_model(). In addition to all the regular menu
45 * model features, this function supports rendering sections in the
46 * model in a more compact form, as a row of icon buttons instead of
47 * menu items.
48 *
49 * To use this rendering, set the ”display-hint” attribute of the
50 * section to ”horizontal-buttons” and set the icons of your items
51 * with the ”verb-icon” attribute.
52 *
53 * |[
54 * <section>
55 * <attribute name="display-hint">horizontal-buttons</attribute>
56 * <item>
57 * <attribute name="label">Cut</attribute>
58 * <attribute name="action">app.cut</attribute>
59 * <attribute name="verb-icon">edit-cut-symbolic</attribute>
60 * </item>
61 * <item>
62 * <attribute name="label">Copy</attribute>
63 * <attribute name="action">app.copy</attribute>
64 * <attribute name="verb-icon">edit-copy-symbolic</attribute>
65 * </item>
66 * <item>
67 * <attribute name="label">Paste</attribute>
68 * <attribute name="action">app.paste</attribute>
69 * <attribute name="verb-icon">edit-paste-symbolic</attribute>
70 * </item>
71 * </section>
72 * ]|
73 *
74 * # CSS nodes
75 *
76 * CtkPopover has a single css node called popover. It always gets the
77 * .background style class and it gets the .menu style class if it is
78 * menu-like (e.g. #CtkPopoverMenu or created using ctk_popover_new_from_model().
79 *
80 * Particular uses of CtkPopover, such as touch selection popups
81 * or magnifiers in #CtkEntry or #CtkTextView get style classes
82 * like .touch-selection or .magnifier to differentiate from
83 * plain popovers.
84 *
85 * Since: 3.12
86 */
87
88#include "config.h"
89#include <cdk/cdk.h>
90#include "ctkpopover.h"
91#include "ctkpopoverprivate.h"
92#include "ctktypebuiltins.h"
93#include "ctkmain.h"
94#include "ctkwindowprivate.h"
95#include "ctkscrollable.h"
96#include "ctkadjustment.h"
97#include "ctkprivate.h"
98#include "ctkintl.h"
99#include "ctklabel.h"
100#include "ctkbox.h"
101#include "ctkbutton.h"
102#include "ctkseparator.h"
103#include "ctkmodelbutton.h"
104#include "ctkwidgetprivate.h"
105#include "ctkactionmuxer.h"
106#include "ctkmenutracker.h"
107#include "ctkstack.h"
108#include "ctksizegroup.h"
109#include "a11y/ctkpopoveraccessible.h"
110#include "ctkmenusectionbox.h"
111#include "ctkroundedboxprivate.h"
112#include "ctkstylecontextprivate.h"
113#include "ctkprogresstrackerprivate.h"
114#include "ctksettingsprivate.h"
115
116#ifdef CDK_WINDOWING_WAYLAND
117#include "wayland/cdkwayland.h"
118#endif
119
120#define TAIL_GAP_WIDTH24 24
121#define TAIL_HEIGHT12 12
122#define TRANSITION_DIFF20 20
123#define TRANSITION_DURATION150 * 1000 150 * 1000
124
125#define POS_IS_VERTICAL(p)((p) == CTK_POS_TOP || (p) == CTK_POS_BOTTOM) ((p) == CTK_POS_TOP || (p) == CTK_POS_BOTTOM)
126
127enum {
128 PROP_RELATIVE_TO = 1,
129 PROP_POINTING_TO,
130 PROP_POSITION,
131 PROP_MODAL,
132 PROP_TRANSITIONS_ENABLED,
133 PROP_CONSTRAIN_TO,
134 NUM_PROPERTIES
135};
136
137enum {
138 CLOSED,
139 N_SIGNALS
140};
141
142enum {
143 STATE_SHOWING,
144 STATE_SHOWN,
145 STATE_HIDING,
146 STATE_HIDDEN
147};
148
149struct _CtkPopoverPrivate
150{
151 CtkWidget *widget;
152 CtkWindow *window;
153 CtkWidget *prev_focus_widget;
154 CtkWidget *default_widget;
155 CtkWidget *prev_default;
156 CtkScrollable *parent_scrollable;
157 CtkAdjustment *vadj;
158 CtkAdjustment *hadj;
159 CdkRectangle pointing_to;
160 CtkPopoverConstraint constraint;
161 CtkProgressTracker tracker;
162 CtkGesture *multipress_gesture;
163 guint prev_focus_unmap_id;
164 guint hierarchy_changed_id;
165 guint size_allocate_id;
166 guint unmap_id;
167 guint scrollable_notify_id;
168 guint grab_notify_id;
169 guint state_changed_id;
170 guint has_pointing_to : 1;
171 guint preferred_position : 2;
172 guint final_position : 2;
173 guint current_position : 2;
174 guint modal : 1;
175 guint button_pressed : 1;
176 guint grab_notify_blocked : 1;
177 guint transitions_enabled : 1;
178 guint state : 2;
179 guint visible : 1;
180 guint first_frame_skipped : 1;
181 gint transition_diff;
182 guint tick_id;
183
184 gint tip_x;
185 gint tip_y;
186};
187
188static GParamSpec *properties[NUM_PROPERTIES];
189static GQuark quark_widget_popovers = 0;
190static guint signals[N_SIGNALS] = { 0 };
191
192static void ctk_popover_update_relative_to (CtkPopover *popover,
193 CtkWidget *relative_to);
194static void ctk_popover_set_state (CtkPopover *popover,
195 guint state);
196static void ctk_popover_invalidate_borders (CtkPopover *popover);
197static void ctk_popover_apply_modality (CtkPopover *popover,
198 gboolean modal);
199
200static void ctk_popover_set_scrollable_full (CtkPopover *popover,
201 CtkScrollable *scrollable);
202
203static void ctk_popover_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
204 gint n_press,
205 gdouble widget_x,
206 gdouble widget_y,
207 CtkPopover *popover);
208
209G_DEFINE_TYPE_WITH_PRIVATE (CtkPopover, ctk_popover, CTK_TYPE_BIN)static void ctk_popover_init (CtkPopover *self); static void ctk_popover_class_init
(CtkPopoverClass *klass); static GType ctk_popover_get_type_once
(void); static gpointer ctk_popover_parent_class = ((void*)0
); static gint CtkPopover_private_offset; static void ctk_popover_class_intern_init
(gpointer klass) { ctk_popover_parent_class = g_type_class_peek_parent
(klass); if (CtkPopover_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkPopover_private_offset); ctk_popover_class_init
((CtkPopoverClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_popover_get_instance_private (CtkPopover
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkPopover_private_offset
)))); } GType ctk_popover_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_popover_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_popover_get_type_once (void)
{ GType g_define_type_id = g_type_register_static_simple ((ctk_bin_get_type
()), g_intern_static_string ("CtkPopover"), sizeof (CtkPopoverClass
), (GClassInitFunc)(void (*)(void)) ctk_popover_class_intern_init
, sizeof (CtkPopover), (GInstanceInitFunc)(void (*)(void)) ctk_popover_init
, (GTypeFlags) 0); { {{ CtkPopover_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkPopoverPrivate)); };} } return
g_define_type_id; }
210
211static void
212ctk_popover_init (CtkPopover *popover)
213{
214 CtkWidget *widget;
215 CtkStyleContext *context;
216 CtkPopoverPrivate *priv;
217
218 widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
219 ctk_widget_set_has_window (widget, TRUE(!(0)));
220 priv = popover->priv = ctk_popover_get_instance_private (popover);
221 priv->modal = TRUE(!(0));
222 priv->tick_id = 0;
223 priv->state = STATE_HIDDEN;
224 priv->visible = FALSE(0);
225 priv->transitions_enabled = TRUE(!(0));
226 priv->preferred_position = CTK_POS_TOP;
227 priv->constraint = CTK_POPOVER_CONSTRAINT_WINDOW;
228
229 priv->multipress_gesture = ctk_gesture_multi_press_new (widget);
230 g_signal_connect (priv->multipress_gesture, "pressed",g_signal_connect_data ((priv->multipress_gesture), ("pressed"
), (((GCallback) (ctk_popover_multipress_gesture_pressed))), (
popover), ((void*)0), (GConnectFlags) 0)
231 G_CALLBACK (ctk_popover_multipress_gesture_pressed), popover)g_signal_connect_data ((priv->multipress_gesture), ("pressed"
), (((GCallback) (ctk_popover_multipress_gesture_pressed))), (
popover), ((void*)0), (GConnectFlags) 0)
;
232 ctk_gesture_single_set_button (CTK_GESTURE_SINGLE (priv->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->multipress_gesture)), ((ctk_gesture_single_get_type
()))))))
, 0);
233 ctk_gesture_single_set_exclusive (CTK_GESTURE_SINGLE (priv->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->multipress_gesture)), ((ctk_gesture_single_get_type
()))))))
, TRUE(!(0)));
234 ctk_event_controller_set_propagation_phase (CTK_EVENT_CONTROLLER (priv->multipress_gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->multipress_gesture)), ((ctk_event_controller_get_type
()))))))
,
235 CTK_PHASE_CAPTURE);
236
237 context = ctk_widget_get_style_context (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
238 ctk_style_context_add_class (context, CTK_STYLE_CLASS_BACKGROUND"background");
239}
240
241static void
242ctk_popover_set_property (GObject *object,
243 guint prop_id,
244 const GValue *value,
245 GParamSpec *pspec)
246{
247 switch (prop_id)
248 {
249 case PROP_RELATIVE_TO:
250 ctk_popover_set_relative_to (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
251 g_value_get_object (value));
252 break;
253 case PROP_POINTING_TO:
254 ctk_popover_set_pointing_to (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
255 g_value_get_boxed (value));
256 break;
257 case PROP_POSITION:
258 ctk_popover_set_position (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
259 g_value_get_enum (value));
260 break;
261 case PROP_MODAL:
262 ctk_popover_set_modal (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
263 g_value_get_boolean (value));
264 break;
265 case PROP_TRANSITIONS_ENABLED:
266 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
267 ctk_popover_set_transitions_enabled (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
268 g_value_get_boolean (value));
269 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
270 break;
271 case PROP_CONSTRAIN_TO:
272 ctk_popover_set_constrain_to (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
,
273 g_value_get_enum (value));
274 break;
275 default:
276 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkpopover.c", 276, ("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)
;
277 }
278}
279
280static void
281ctk_popover_get_property (GObject *object,
282 guint prop_id,
283 GValue *value,
284 GParamSpec *pspec)
285{
286 CtkPopoverPrivate *priv = CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
->priv;
287
288 switch (prop_id)
289 {
290 case PROP_RELATIVE_TO:
291 g_value_set_object (value, priv->widget);
292 break;
293 case PROP_POINTING_TO:
294 g_value_set_boxed (value, &priv->pointing_to);
295 break;
296 case PROP_POSITION:
297 g_value_set_enum (value, priv->preferred_position);
298 break;
299 case PROP_MODAL:
300 g_value_set_boolean (value, priv->modal);
301 break;
302 case PROP_TRANSITIONS_ENABLED:
303 g_value_set_boolean (value, priv->transitions_enabled);
304 break;
305 case PROP_CONSTRAIN_TO:
306 g_value_set_enum (value, priv->constraint);
307 break;
308 default:
309 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkpopover.c", 309, ("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)
;
310 }
311}
312
313static gboolean
314transitions_enabled (CtkPopover *popover)
315{
316 CtkPopoverPrivate *priv = popover->priv;
317
318 return ctk_settings_get_enable_animations (ctk_widget_get_settings (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
)) &&
319 priv->transitions_enabled;
320}
321
322static void
323ctk_popover_hide_internal (CtkPopover *popover)
324{
325 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
326 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
327
328 if (!priv->visible)
329 return;
330
331 priv->visible = FALSE(0);
332 g_signal_emit (widget, signals[CLOSED], 0);
333
334 if (priv->modal)
335 ctk_popover_apply_modality (popover, FALSE(0));
336
337 if (ctk_widget_get_realized (widget))
338 {
339 cairo_region_t *region = cairo_region_create ();
340 cdk_window_input_shape_combine_region (ctk_widget_get_parent_window (widget),
341 region, 0, 0);
342 cairo_region_destroy (region);
343 }
344}
345
346static void
347ctk_popover_finalize (GObject *object)
348{
349 CtkPopover *popover = CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
;
350 CtkPopoverPrivate *priv = popover->priv;
351
352 if (priv->widget)
353 ctk_popover_update_relative_to (popover, NULL((void*)0));
354
355 g_clear_object (&priv->multipress_gesture)do { _Static_assert (sizeof *((&priv->multipress_gesture
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->multipress_gesture))) _pp = ((&priv->
multipress_gesture)); __typeof__ (*((&priv->multipress_gesture
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
356
357 G_OBJECT_CLASS (ctk_popover_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), (((GType) ((20) << (2)
)))))))
->finalize (object);
358}
359
360static void
361popover_unset_prev_focus (CtkPopover *popover)
362{
363 CtkPopoverPrivate *priv = popover->priv;
364
365 if (!priv->prev_focus_widget)
366 return;
367
368 if (priv->prev_focus_unmap_id)
369 {
370 g_signal_handler_disconnect (priv->prev_focus_widget,
371 priv->prev_focus_unmap_id);
372 priv->prev_focus_unmap_id = 0;
373 }
374
375 g_clear_object (&priv->prev_focus_widget)do { _Static_assert (sizeof *((&priv->prev_focus_widget
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->prev_focus_widget))) _pp = ((&priv->
prev_focus_widget)); __typeof__ (*((&priv->prev_focus_widget
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
376}
377
378static void
379ctk_popover_dispose (GObject *object)
380{
381 CtkPopover *popover = CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
;
382 CtkPopoverPrivate *priv = popover->priv;
383
384 if (priv->modal)
385 ctk_popover_apply_modality (popover, FALSE(0));
386
387 if (priv->window)
388 {
389 g_signal_handlers_disconnect_by_data (priv->window, popover)g_signal_handlers_disconnect_matched ((priv->window), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (popover))
;
390 _ctk_window_remove_popover (priv->window, CTK_WIDGET (object)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_widget_get_type ()))))))
);
391 }
392
393 priv->window = NULL((void*)0);
394
395 if (priv->widget)
396 ctk_popover_update_relative_to (popover, NULL((void*)0));
397
398 popover_unset_prev_focus (popover);
399
400 g_clear_object (&priv->default_widget)do { _Static_assert (sizeof *((&priv->default_widget))
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->default_widget))) _pp = ((&priv->default_widget
)); __typeof__ (*((&priv->default_widget))) _ptr = *_pp
; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while
(0)
;
401
402 G_OBJECT_CLASS (ctk_popover_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), (((GType) ((20) << (2)
)))))))
->dispose (object);
403}
404
405static void
406ctk_popover_realize (CtkWidget *widget)
407{
408 CtkAllocation allocation;
409 CdkWindowAttr attributes;
410 gint attributes_mask;
411 CdkWindow *window;
412
413 ctk_widget_get_allocation (widget, &allocation);
414
415 attributes.x = 0;
416 attributes.y = 0;
417 attributes.width = allocation.width;
418 attributes.height = allocation.height;
419 attributes.window_type = CDK_WINDOW_CHILD;
420 attributes.visual = ctk_widget_get_visual (widget);
421 attributes.wclass = CDK_INPUT_OUTPUT;
422 attributes.event_mask =
423 ctk_widget_get_events (widget) |
424 CDK_POINTER_MOTION_MASK |
425 CDK_BUTTON_MOTION_MASK |
426 CDK_BUTTON_PRESS_MASK |
427 CDK_BUTTON_RELEASE_MASK |
428 CDK_ENTER_NOTIFY_MASK |
429 CDK_LEAVE_NOTIFY_MASK;
430
431 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
432 window = cdk_window_new (ctk_widget_get_parent_window (widget),
433 &attributes, attributes_mask);
434 ctk_widget_set_window (widget, window);
435 ctk_widget_register_window (widget, window);
436 ctk_widget_set_realized (widget, TRUE(!(0)));
437}
438
439static gboolean
440window_focus_in (CtkWidget *widget,
441 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
442 CtkPopover *popover)
443{
444 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
445
446 /* Regain the grab when the window is focused */
447 if (priv->modal &&
448 ctk_widget_is_drawable (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
449 {
450 CtkWidget *focus;
451
452 ctk_grab_add (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
453
454 focus = ctk_window_get_focus (CTK_WINDOW (widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_window_get_type ()))))))
);
455
456 if (focus == NULL((void*)0) || !ctk_widget_is_ancestor (focus, CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
457 ctk_widget_grab_focus (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
458
459 if (priv->grab_notify_blocked)
460 g_signal_handler_unblock (priv->widget, priv->grab_notify_id);
461
462 priv->grab_notify_blocked = FALSE(0);
463 }
464 return FALSE(0);
465}
466
467static gboolean
468window_focus_out (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
469 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
470 CtkPopover *popover)
471{
472 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
473
474 /* Temporarily remove the grab when unfocused */
475 if (priv->modal &&
476 ctk_widget_is_drawable (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
477 {
478 g_signal_handler_block (priv->widget, priv->grab_notify_id);
479 ctk_grab_remove (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
480 priv->grab_notify_blocked = TRUE(!(0));
481 }
482 return FALSE(0);
483}
484
485static void
486window_set_focus (CtkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)),
487 CtkWidget *widget,
488 CtkPopover *popover)
489{
490 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
491
492 if (!priv->modal || !widget || !ctk_widget_is_drawable (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
493 return;
494
495 widget = ctk_widget_get_ancestor (widget, CTK_TYPE_POPOVER(ctk_popover_get_type ()));
496 while (widget != NULL((void*)0))
497 {
498 if (widget == CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
)
499 return;
500
501 widget = ctk_popover_get_relative_to (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
);
502 if (widget == NULL((void*)0))
503 break;
504 widget = ctk_widget_get_ancestor (widget, CTK_TYPE_POPOVER(ctk_popover_get_type ()));
505 }
506
507 popover_unset_prev_focus (popover);
508 ctk_widget_hide (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
509}
510
511static void
512prev_focus_unmap_cb (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
513 CtkPopover *popover)
514{
515 popover_unset_prev_focus (popover);
516}
517
518static void
519ctk_popover_apply_modality (CtkPopover *popover,
520 gboolean modal)
521{
522 CtkPopoverPrivate *priv = popover->priv;
523
524 if (!priv->window)
525 return;
526
527 if (modal)
528 {
529 CtkWidget *prev_focus;
530
531 prev_focus = ctk_window_get_focus (priv->window);
532 priv->prev_focus_widget = prev_focus;
533 if (priv->prev_focus_widget)
534 {
535 priv->prev_focus_unmap_id =
536 g_signal_connect (prev_focus, "unmap",g_signal_connect_data ((prev_focus), ("unmap"), (((GCallback)
(prev_focus_unmap_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
537 G_CALLBACK (prev_focus_unmap_cb), popover)g_signal_connect_data ((prev_focus), ("unmap"), (((GCallback)
(prev_focus_unmap_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
;
538 g_object_ref (prev_focus)((__typeof__ (prev_focus)) (g_object_ref) (prev_focus));
539 }
540 ctk_grab_add (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
541 ctk_window_set_focus (priv->window, NULL((void*)0));
542 ctk_widget_grab_focus (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
543
544 g_signal_connect (priv->window, "focus-in-event",g_signal_connect_data ((priv->window), ("focus-in-event"),
(((GCallback) (window_focus_in))), (popover), ((void*)0), (GConnectFlags
) 0)
545 G_CALLBACK (window_focus_in), popover)g_signal_connect_data ((priv->window), ("focus-in-event"),
(((GCallback) (window_focus_in))), (popover), ((void*)0), (GConnectFlags
) 0)
;
546 g_signal_connect (priv->window, "focus-out-event",g_signal_connect_data ((priv->window), ("focus-out-event")
, (((GCallback) (window_focus_out))), (popover), ((void*)0), (
GConnectFlags) 0)
547 G_CALLBACK (window_focus_out), popover)g_signal_connect_data ((priv->window), ("focus-out-event")
, (((GCallback) (window_focus_out))), (popover), ((void*)0), (
GConnectFlags) 0)
;
548 g_signal_connect (priv->window, "set-focus",g_signal_connect_data ((priv->window), ("set-focus"), (((GCallback
) (window_set_focus))), (popover), ((void*)0), (GConnectFlags
) 0)
549 G_CALLBACK (window_set_focus), popover)g_signal_connect_data ((priv->window), ("set-focus"), (((GCallback
) (window_set_focus))), (popover), ((void*)0), (GConnectFlags
) 0)
;
550 }
551 else
552 {
553 g_signal_handlers_disconnect_by_data (priv->window, popover)g_signal_handlers_disconnect_matched ((priv->window), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (popover))
;
554 ctk_grab_remove (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
555
556 /* Let prev_focus_widget regain focus */
557 if (priv->prev_focus_widget &&
558 ctk_widget_is_drawable (priv->prev_focus_widget))
559 {
560 if (CTK_IS_ENTRY (priv->prev_focus_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(priv->prev_focus_widget)); GType __t = ((ctk_entry_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; }))))
)
561 ctk_entry_grab_focus_without_selecting (CTK_ENTRY (priv->prev_focus_widget)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->prev_focus_widget)), ((ctk_entry_get_type ())))
)))
);
562 else
563 ctk_widget_grab_focus (priv->prev_focus_widget);
564 }
565 else if (priv->window)
566 ctk_widget_grab_focus (CTK_WIDGET (priv->window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->window)), ((ctk_widget_get_type ()))))))
);
567
568 popover_unset_prev_focus (popover);
569 }
570}
571
572static gboolean
573show_animate_cb (CtkWidget *widget,
574 CdkFrameClock *frame_clock,
575 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
576{
577 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
578 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
579 gdouble t;
580
581 if (priv->first_frame_skipped)
582 ctk_progress_tracker_advance_frame (&priv->tracker,
583 cdk_frame_clock_get_frame_time (frame_clock));
584 else
585 priv->first_frame_skipped = TRUE(!(0));
586
587 t = ctk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE(0));
588
589 if (priv->state == STATE_SHOWING)
590 {
591 priv->transition_diff = TRANSITION_DIFF20 - (TRANSITION_DIFF20 * t);
592 ctk_widget_set_opacity (widget, t);
593 }
594 else if (priv->state == STATE_HIDING)
595 {
596 priv->transition_diff = -TRANSITION_DIFF20 * t;
597 ctk_widget_set_opacity (widget, 1.0 - t);
598 }
599
600 ctk_popover_update_position (popover);
601
602 if (ctk_progress_tracker_get_state (&priv->tracker) == CTK_PROGRESS_STATE_AFTER)
603 {
604 if (priv->state == STATE_SHOWING)
605 {
606 ctk_popover_set_state (popover, STATE_SHOWN);
607
608 if (!priv->visible)
609 ctk_popover_set_state (popover, STATE_HIDING);
610 }
611 else
612 {
613 ctk_widget_hide (widget);
614 }
615
616 priv->tick_id = 0;
617 return G_SOURCE_REMOVE(0);
618 }
619 else
620 return G_SOURCE_CONTINUE(!(0));
621}
622
623static void
624ctk_popover_stop_transition (CtkPopover *popover)
625{
626 CtkPopoverPrivate *priv = popover->priv;
627
628 if (priv->tick_id != 0)
629 {
630 ctk_widget_remove_tick_callback (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, priv->tick_id);
631 priv->tick_id = 0;
632 }
633}
634
635static void
636ctk_popover_start_transition (CtkPopover *popover)
637{
638 CtkPopoverPrivate *priv = popover->priv;
639
640 if (priv->tick_id != 0)
641 return;
642
643 priv->first_frame_skipped = FALSE(0);
644 ctk_progress_tracker_start (&priv->tracker, TRANSITION_DURATION150 * 1000, 0, 1.0);
645 priv->tick_id = ctk_widget_add_tick_callback (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
,
646 show_animate_cb,
647 popover, NULL((void*)0));
648}
649
650static void
651ctk_popover_set_state (CtkPopover *popover,
652 guint state)
653{
654 CtkPopoverPrivate *priv = popover->priv;
655
656 if (!transitions_enabled (popover) ||
657 !ctk_widget_get_realized (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
658 {
659 if (state == STATE_SHOWING)
660 state = STATE_SHOWN;
661 else if (state == STATE_HIDING)
662 state = STATE_HIDDEN;
663 }
664
665 priv->state = state;
666
667 if (state == STATE_SHOWING || state == STATE_HIDING)
668 ctk_popover_start_transition (popover);
669 else
670 {
671 ctk_popover_stop_transition (popover);
672
673 ctk_widget_set_visible (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, state == STATE_SHOWN);
674 }
675}
676
677CtkWidget *
678ctk_popover_get_prev_default (CtkPopover *popover)
679{
680 g_return_val_if_fail (CTK_IS_POPOVER (popover), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return (((void*)0)); } } while
(0)
;
681
682 return popover->priv->prev_default;
683}
684
685
686static void
687ctk_popover_map (CtkWidget *widget)
688{
689 CtkPopoverPrivate *priv = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv;
690
691 priv->prev_default = ctk_window_get_default_widget (priv->window);
692 if (priv->prev_default)
693 g_object_ref (priv->prev_default)((__typeof__ (priv->prev_default)) (g_object_ref) (priv->
prev_default))
;
694
695 CTK_WIDGET_CLASS (ctk_popover_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), ((ctk_widget_get_type ()))))
))
->map (widget);
696
697 cdk_window_show (ctk_widget_get_window (widget));
698 ctk_popover_update_position (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
);
699
700 ctk_window_set_default (priv->window, priv->default_widget);
701}
702
703static void
704ctk_popover_unmap (CtkWidget *widget)
705{
706 CtkPopoverPrivate *priv = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv;
707
708 priv->button_pressed = FALSE(0);
709
710 cdk_window_hide (ctk_widget_get_window (widget));
711 CTK_WIDGET_CLASS (ctk_popover_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), ((ctk_widget_get_type ()))))
))
->unmap (widget);
712
713 if (ctk_window_get_default_widget (priv->window) == priv->default_widget)
714 ctk_window_set_default (priv->window, priv->prev_default);
715 g_clear_object (&priv->prev_default)do { _Static_assert (sizeof *((&priv->prev_default)) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&priv->prev_default))) _pp = ((&priv->prev_default
)); __typeof__ (*((&priv->prev_default))) _ptr = *_pp;
*_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while
(0)
;
716}
717
718static CtkPositionType
719get_effective_position (CtkPopover *popover,
720 CtkPositionType pos)
721{
722 if (ctk_widget_get_direction (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL)
723 {
724 if (pos == CTK_POS_LEFT)
725 pos = CTK_POS_RIGHT;
726 else if (pos == CTK_POS_RIGHT)
727 pos = CTK_POS_LEFT;
728 }
729
730 return pos;
731}
732
733static void
734get_margin (CtkWidget *widget,
735 CtkBorder *border)
736{
737 CtkStyleContext *context;
738
739 context = ctk_widget_get_style_context (widget);
740 ctk_style_context_get_margin (context,
741 ctk_style_context_get_state (context),
742 border);
743}
744
745static void
746ctk_popover_get_gap_coords (CtkPopover *popover,
747 gint *initial_x_out,
748 gint *initial_y_out,
749 gint *tip_x_out,
750 gint *tip_y_out,
751 gint *final_x_out,
752 gint *final_y_out,
753 CtkPositionType *gap_side_out)
754{
755 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
756 CtkPopoverPrivate *priv = popover->priv;
757 CdkRectangle rect;
758 gint base, tip, tip_pos;
759 gint initial_x, initial_y;
760 gint tip_x, tip_y;
761 gint final_x, final_y;
762 CtkPositionType gap_side, pos;
763 CtkAllocation allocation;
764 gint border_radius;
765 CtkStyleContext *context;
766 CtkBorder margin, border, widget_margin;
767 CtkStateFlags state;
768
769 ctk_popover_get_pointing_to (popover, &rect);
770 ctk_widget_get_allocation (widget, &allocation);
771
772#ifdef CDK_WINDOWING_WAYLAND
773 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
)
774 {
775 gint win_x, win_y;
776
777 ctk_widget_translate_coordinates (priv->widget, CTK_WIDGET (priv->window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->window)), ((ctk_widget_get_type ()))))))
,
778 rect.x, rect.y, &rect.x, &rect.y);
779 cdk_window_get_origin (ctk_widget_get_window (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
),
780 &win_x, &win_y);
781 rect.x -= win_x;
782 rect.y -= win_y;
783 }
784 else
785#endif
786 ctk_widget_translate_coordinates (priv->widget, widget,
787 rect.x, rect.y, &rect.x, &rect.y);
788
789 get_margin (widget, &margin);
790
791 if (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_LTR)
792 {
793 widget_margin.left = ctk_widget_get_margin_start (widget);
794 widget_margin.right = ctk_widget_get_margin_end (widget);
795 }
796 else
797 {
798 widget_margin.left = ctk_widget_get_margin_end (widget);
799 widget_margin.right = ctk_widget_get_margin_start (widget);
800 }
801
802 widget_margin.top = ctk_widget_get_margin_top (widget);
803 widget_margin.bottom = ctk_widget_get_margin_bottom (widget);
804
805 context = ctk_widget_get_style_context (widget);
806 state = ctk_style_context_get_state (context);
807
808 ctk_style_context_get_border (context, state, &border);
809 ctk_style_context_get (context,
810 state,
811 CTK_STYLE_PROPERTY_BORDER_RADIUS"border-radius", &border_radius,
812 NULL((void*)0));
813 pos = get_effective_position (popover, priv->final_position);
814
815 if (pos == CTK_POS_BOTTOM || pos == CTK_POS_RIGHT)
816 {
817 tip = ((pos == CTK_POS_BOTTOM) ? border.top + widget_margin.top : border.left + widget_margin.left);
818 base = tip + TAIL_HEIGHT12;
819 gap_side = (priv->final_position == CTK_POS_BOTTOM) ? CTK_POS_TOP : CTK_POS_LEFT;
820 }
821 else if (pos == CTK_POS_TOP)
822 {
823 base = allocation.height - TAIL_HEIGHT12 - border.bottom - widget_margin.bottom;
824 tip = base + TAIL_HEIGHT12;
825 gap_side = CTK_POS_BOTTOM;
826 }
827 else if (pos == CTK_POS_LEFT)
828 {
829 base = allocation.width - TAIL_HEIGHT12 - border.right - widget_margin.right;
830 tip = base + TAIL_HEIGHT12;
831 gap_side = CTK_POS_RIGHT;
832 }
833 else
834 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkpopover.c", 834, ((
const char*) (__func__)), ((void*)0)); } while (0)
;
835
836 if (POS_IS_VERTICAL (pos)((pos) == CTK_POS_TOP || (pos) == CTK_POS_BOTTOM))
837 {
838 tip_pos = rect.x + (rect.width / 2) + widget_margin.left;
839 initial_x = CLAMP (tip_pos - TAIL_GAP_WIDTH / 2,(((tip_pos - 24 / 2) > (allocation.width - 24 - margin.right
- border_radius - 12)) ? (allocation.width - 24 - margin.right
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.left + 12)) ? (border_radius + margin.left + 12) : (
tip_pos - 24 / 2)))
840 border_radius + margin.left + TAIL_HEIGHT,(((tip_pos - 24 / 2) > (allocation.width - 24 - margin.right
- border_radius - 12)) ? (allocation.width - 24 - margin.right
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.left + 12)) ? (border_radius + margin.left + 12) : (
tip_pos - 24 / 2)))
841 allocation.width - TAIL_GAP_WIDTH - margin.right - border_radius - TAIL_HEIGHT)(((tip_pos - 24 / 2) > (allocation.width - 24 - margin.right
- border_radius - 12)) ? (allocation.width - 24 - margin.right
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.left + 12)) ? (border_radius + margin.left + 12) : (
tip_pos - 24 / 2)))
;
842 initial_y = base;
843
844 tip_x = CLAMP (tip_pos, 0, allocation.width)(((tip_pos) > (allocation.width)) ? (allocation.width) : (
((tip_pos) < (0)) ? (0) : (tip_pos)))
;
845 tip_y = tip;
846
847 final_x = CLAMP (tip_pos + TAIL_GAP_WIDTH / 2,(((tip_pos + 24 / 2) > (allocation.width - margin.right - border_radius
- 12)) ? (allocation.width - margin.right - border_radius - 12
) : (((tip_pos + 24 / 2) < (border_radius + margin.left + 24
+ 12)) ? (border_radius + margin.left + 24 + 12) : (tip_pos +
24 / 2)))
848 border_radius + margin.left + TAIL_GAP_WIDTH + TAIL_HEIGHT,(((tip_pos + 24 / 2) > (allocation.width - margin.right - border_radius
- 12)) ? (allocation.width - margin.right - border_radius - 12
) : (((tip_pos + 24 / 2) < (border_radius + margin.left + 24
+ 12)) ? (border_radius + margin.left + 24 + 12) : (tip_pos +
24 / 2)))
849 allocation.width - margin.right - border_radius - TAIL_HEIGHT)(((tip_pos + 24 / 2) > (allocation.width - margin.right - border_radius
- 12)) ? (allocation.width - margin.right - border_radius - 12
) : (((tip_pos + 24 / 2) < (border_radius + margin.left + 24
+ 12)) ? (border_radius + margin.left + 24 + 12) : (tip_pos +
24 / 2)))
;
850 final_y = base;
851 }
852 else
853 {
854 tip_pos = rect.y + (rect.height / 2) + widget_margin.top;
855
856 initial_x = base;
857 initial_y = CLAMP (tip_pos - TAIL_GAP_WIDTH / 2,(((tip_pos - 24 / 2) > (allocation.height - 24 - margin.bottom
- border_radius - 12)) ? (allocation.height - 24 - margin.bottom
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.top + 12)) ? (border_radius + margin.top + 12) : (tip_pos
- 24 / 2)))
858 border_radius + margin.top + TAIL_HEIGHT,(((tip_pos - 24 / 2) > (allocation.height - 24 - margin.bottom
- border_radius - 12)) ? (allocation.height - 24 - margin.bottom
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.top + 12)) ? (border_radius + margin.top + 12) : (tip_pos
- 24 / 2)))
859 allocation.height - TAIL_GAP_WIDTH - margin.bottom - border_radius - TAIL_HEIGHT)(((tip_pos - 24 / 2) > (allocation.height - 24 - margin.bottom
- border_radius - 12)) ? (allocation.height - 24 - margin.bottom
- border_radius - 12) : (((tip_pos - 24 / 2) < (border_radius
+ margin.top + 12)) ? (border_radius + margin.top + 12) : (tip_pos
- 24 / 2)))
;
860
861 tip_x = tip;
862 tip_y = CLAMP (tip_pos, 0, allocation.height)(((tip_pos) > (allocation.height)) ? (allocation.height) :
(((tip_pos) < (0)) ? (0) : (tip_pos)))
;
863
864 final_x = base;
865 final_y = CLAMP (tip_pos + TAIL_GAP_WIDTH / 2,(((tip_pos + 24 / 2) > (allocation.height - margin.right -
border_radius - 12)) ? (allocation.height - margin.right - border_radius
- 12) : (((tip_pos + 24 / 2) < (border_radius + margin.top
+ 24 + 12)) ? (border_radius + margin.top + 24 + 12) : (tip_pos
+ 24 / 2)))
866 border_radius + margin.top + TAIL_GAP_WIDTH + TAIL_HEIGHT,(((tip_pos + 24 / 2) > (allocation.height - margin.right -
border_radius - 12)) ? (allocation.height - margin.right - border_radius
- 12) : (((tip_pos + 24 / 2) < (border_radius + margin.top
+ 24 + 12)) ? (border_radius + margin.top + 24 + 12) : (tip_pos
+ 24 / 2)))
867 allocation.height - margin.right - border_radius - TAIL_HEIGHT)(((tip_pos + 24 / 2) > (allocation.height - margin.right -
border_radius - 12)) ? (allocation.height - margin.right - border_radius
- 12) : (((tip_pos + 24 / 2) < (border_radius + margin.top
+ 24 + 12)) ? (border_radius + margin.top + 24 + 12) : (tip_pos
+ 24 / 2)))
;
868 }
869
870 if (initial_x_out)
871 *initial_x_out = initial_x;
872 if (initial_y_out)
873 *initial_y_out = initial_y;
874
875 if (tip_x_out)
876 *tip_x_out = tip_x;
877 if (tip_y_out)
878 *tip_y_out = tip_y;
879
880 if (final_x_out)
881 *final_x_out = final_x;
882 if (final_y_out)
883 *final_y_out = final_y;
884
885 if (gap_side_out)
886 *gap_side_out = gap_side;
887}
888
889static void
890ctk_popover_get_rect_for_size (CtkPopover *popover,
891 int popover_width,
892 int popover_height,
893 CdkRectangle *rect)
894{
895 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
896 int x, y, w, h;
897 CtkBorder margin;
898
899 get_margin (widget, &margin);
900
901 x = 0;
902 y = 0;
903 w = popover_width;
904 h = popover_height;
905
906 x += MAX (TAIL_HEIGHT, margin.left)(((12) > (margin.left)) ? (12) : (margin.left));
907 y += MAX (TAIL_HEIGHT, margin.top)(((12) > (margin.top)) ? (12) : (margin.top));
908 w -= x + MAX (TAIL_HEIGHT, margin.right)(((12) > (margin.right)) ? (12) : (margin.right));
909 h -= y + MAX (TAIL_HEIGHT, margin.bottom)(((12) > (margin.bottom)) ? (12) : (margin.bottom));
910
911 rect->x = x;
912 rect->y = y;
913 rect->width = w;
914 rect->height = h;
915}
916
917static void
918ctk_popover_get_rect_coords (CtkPopover *popover,
919 int *x_out,
920 int *y_out,
921 int *w_out,
922 int *h_out)
923{
924 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
925 CdkRectangle rect;
926 CtkAllocation allocation;
927
928 ctk_widget_get_allocation (widget, &allocation);
929 ctk_popover_get_rect_for_size (popover, allocation.width, allocation.height, &rect);
930
931 *x_out = rect.x;
932 *y_out = rect.y;
933 *w_out = rect.width;
934 *h_out = rect.height;
935}
936
937static void
938ctk_popover_apply_tail_path (CtkPopover *popover,
939 cairo_t *cr)
940{
941 gint initial_x, initial_y;
942 gint tip_x, tip_y;
943 gint final_x, final_y;
944
945 if (!popover->priv->widget)
946 return;
947
948 cairo_set_line_width (cr, 1);
949 ctk_popover_get_gap_coords (popover,
950 &initial_x, &initial_y,
951 &tip_x, &tip_y,
952 &final_x, &final_y,
953 NULL((void*)0));
954
955 cairo_move_to (cr, initial_x, initial_y);
956 cairo_line_to (cr, tip_x, tip_y);
957 cairo_line_to (cr, final_x, final_y);
958}
959
960static void
961ctk_popover_fill_border_path (CtkPopover *popover,
962 cairo_t *cr)
963{
964 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
965 CtkAllocation allocation;
966 CtkStyleContext *context;
967 int x, y, w, h;
968 CtkRoundedBox box;
969
970 context = ctk_widget_get_style_context (widget);
971 ctk_widget_get_allocation (widget, &allocation);
972
973 cairo_set_source_rgba (cr, 0, 0, 0, 1);
974
975 ctk_popover_apply_tail_path (popover, cr);
976 cairo_close_path (cr);
977 cairo_fill (cr);
978
979 ctk_popover_get_rect_coords (popover, &x, &y, &w, &h);
980
981 _ctk_rounded_box_init_rect (&box, x, y, w, h);
982 _ctk_rounded_box_apply_border_radius_for_style (&box,
983 ctk_style_context_lookup_style (context),
984 0);
985 _ctk_rounded_box_path (&box, cr);
986 cairo_fill (cr);
987}
988
989static void
990ctk_popover_update_shape (CtkPopover *popover)
991{
992 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
993 cairo_surface_t *surface;
994 cairo_region_t *region;
995 CdkWindow *win;
996 cairo_t *cr;
997
998#ifdef CDK_WINDOWING_WAYLAND
999 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
)
1000 return;
1001#endif
1002
1003 win = ctk_widget_get_window (widget);
1004 surface =
1005 cdk_window_create_similar_surface (win,
1006 CAIRO_CONTENT_COLOR_ALPHA,
1007 cdk_window_get_width (win),
1008 cdk_window_get_height (win));
1009
1010 cr = cairo_create (surface);
1011 ctk_popover_fill_border_path (popover, cr);
1012 cairo_destroy (cr);
1013
1014 region = cdk_cairo_region_create_from_surface (surface);
1015 cairo_surface_destroy (surface);
1016
1017 ctk_widget_shape_combine_region (widget, region);
1018 cairo_region_destroy (region);
1019
1020 cdk_window_set_child_shapes (ctk_widget_get_parent_window (widget));
1021}
1022
1023static void
1024_ctk_popover_update_child_visible (CtkPopover *popover)
1025{
1026 CtkPopoverPrivate *priv = popover->priv;
1027 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
1028 CdkRectangle rect;
1029 CtkAllocation allocation;
1030 CtkWidget *parent;
1031
1032 if (!priv->parent_scrollable)
13
Assuming field 'parent_scrollable' is non-null
14
Taking false branch
1033 {
1034 ctk_widget_set_child_visible (widget, TRUE(!(0)));
1035 return;
1036 }
1037
1038 parent = ctk_widget_get_parent (CTK_WIDGET (priv->parent_scrollable)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->parent_scrollable)), ((ctk_widget_get_type ()))
))))
);
1039 ctk_popover_get_pointing_to (popover, &rect);
15
Calling 'ctk_popover_get_pointing_to'
27
Returning from 'ctk_popover_get_pointing_to'
1040
1041 ctk_widget_translate_coordinates (priv->widget, parent,
28
3rd function call argument is an uninitialized value
1042 rect.x, rect.y, &rect.x, &rect.y);
1043
1044 ctk_widget_get_allocation (CTK_WIDGET (parent)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((parent)), ((ctk_widget_get_type ()))))))
, &allocation);
1045
1046 if (rect.x + rect.width < 0 || rect.x > allocation.width ||
1047 rect.y + rect.height < 0 || rect.y > allocation.height)
1048 ctk_widget_set_child_visible (widget, FALSE(0));
1049 else
1050 ctk_widget_set_child_visible (widget, TRUE(!(0)));
1051}
1052
1053static CtkPositionType
1054opposite_position (CtkPositionType pos)
1055{
1056 switch (pos)
1057 {
1058 default:
1059 case CTK_POS_LEFT: return CTK_POS_RIGHT;
1060 case CTK_POS_RIGHT: return CTK_POS_LEFT;
1061 case CTK_POS_TOP: return CTK_POS_BOTTOM;
1062 case CTK_POS_BOTTOM: return CTK_POS_TOP;
1063 }
1064}
1065
1066void
1067ctk_popover_update_position (CtkPopover *popover)
1068{
1069 CtkPopoverPrivate *priv = popover->priv;
1070 CtkWidget *widget = CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
;
1071 CtkAllocation window_alloc;
1072 CtkBorder window_shadow;
1073 CdkRectangle rect;
1074 CtkRequisition req;
1075 CtkPositionType pos;
1076 gint overshoot[4];
1077 gint i, j;
1078 gint best;
1079
1080 if (!priv->window)
2
Assuming field 'window' is non-null
3
Taking false branch
1081 return;
1082
1083 ctk_widget_get_preferred_size (widget, NULL((void*)0), &req);
1084 ctk_widget_get_allocation (CTK_WIDGET (priv->window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->window)), ((ctk_widget_get_type ()))))))
, &window_alloc);
1085 _ctk_window_get_shadow_width (priv->window, &window_shadow);
1086 priv->final_position = priv->preferred_position;
1087
1088 ctk_popover_get_pointing_to (popover, &rect);
1089 ctk_widget_translate_coordinates (priv->widget, CTK_WIDGET (priv->window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->window)), ((ctk_widget_get_type ()))))))
,
1090 rect.x, rect.y, &rect.x, &rect.y);
1091
1092 pos = get_effective_position (popover, priv->preferred_position);
1093
1094 overshoot[CTK_POS_TOP] = req.height - rect.y + window_shadow.top;
1095 overshoot[CTK_POS_BOTTOM] = rect.y + rect.height + req.height - window_alloc.height
1096 + window_shadow.bottom;
1097 overshoot[CTK_POS_LEFT] = req.width - rect.x + window_shadow.left;
1098 overshoot[CTK_POS_RIGHT] = rect.x + rect.width + req.width - window_alloc.width
1099 + window_shadow.right;
1100
1101#ifdef CDK_WINDOWING_WAYLAND
1102 if (CDK_IS_WAYLAND_DISPLAY (ctk_widget_get_display (widget))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_display (widget))); GType __t = ((cdk_wayland_display_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; }))))
&&
4
Assuming '__inst' is non-null
5
Taking false branch
6
Assuming field 'g_class' is null
7
Assuming the condition is true
9
Taking true branch
1103 priv->constraint == CTK_POPOVER_CONSTRAINT_NONE)
8
Assuming field 'constraint' is equal to CTK_POPOVER_CONSTRAINT_NONE
1104 {
1105 priv->final_position = priv->preferred_position;
1106 }
1107 else
1108#endif
1109 if (overshoot[pos] <= 0)
1110 {
1111 priv->final_position = priv->preferred_position;
1112 }
1113 else if (overshoot[opposite_position (pos)] <= 0)
1114 {
1115 priv->final_position = opposite_position (priv->preferred_position);
1116 }
1117 else
1118 {
1119 best = G_MAXINT2147483647;
1120 pos = 0;
1121 for (i = 0; i < 4; i++)
1122 {
1123 j = get_effective_position (popover, i);
1124 if (overshoot[j] < best)
1125 {
1126 pos = i;
1127 best = overshoot[j];
1128 }
1129 }
1130 priv->final_position = pos;
1131 }
1132
1133 switch (priv->final_position)
1134 {
1135 case CTK_POS_TOP:
1136 rect.y += priv->transition_diff;
1137 break;
1138 case CTK_POS_BOTTOM:
1139 rect.y -= priv->transition_diff;
1140 break;
1141 case CTK_POS_LEFT:
1142 rect.x += priv->transition_diff;
1143 break;
1144 case CTK_POS_RIGHT:
1145 rect.x -= priv->transition_diff;
1146 break;
1147 }
1148
1149 _ctk_window_set_popover_position (priv->window, widget,
1150 priv->final_position, &rect);
1151
1152 if (priv->final_position != priv->current_position)
10
Assuming field 'final_position' is equal to field 'current_position'
11
Taking false branch
1153 {
1154 if (ctk_widget_is_drawable (widget))
1155 ctk_popover_update_shape (popover);
1156
1157 priv->current_position = priv->final_position;
1158 ctk_popover_invalidate_borders (popover);
1159 }
1160
1161 _ctk_popover_update_child_visible (popover);
12
Calling '_ctk_popover_update_child_visible'
1162}
1163
1164static gboolean
1165ctk_popover_draw (CtkWidget *widget,
1166 cairo_t *cr)
1167{
1168 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1169 CtkStyleContext *context;
1170 CtkAllocation allocation;
1171 CtkWidget *child;
1172 CtkBorder border;
1173 CdkRGBA border_color;
1174 int rect_x, rect_y, rect_w, rect_h;
1175 gint initial_x, initial_y, final_x, final_y;
1176 gint gap_start, gap_end;
1177 CtkPositionType gap_side;
1178 CtkStateFlags state;
1179
1180 context = ctk_widget_get_style_context (widget);
1181
1182 state = ctk_style_context_get_state (context);
1183 ctk_widget_get_allocation (widget, &allocation);
1184
1185 ctk_style_context_get_border (context, state, &border);
1186 ctk_popover_get_rect_coords (popover,
1187 &rect_x, &rect_y,
1188 &rect_w, &rect_h);
1189
1190 /* Render the rect background */
1191 ctk_render_background (context, cr,
1192 rect_x, rect_y,
1193 rect_w, rect_h);
1194
1195 if (popover->priv->widget)
1196 {
1197 ctk_popover_get_gap_coords (popover,
1198 &initial_x, &initial_y,
1199 NULL((void*)0), NULL((void*)0),
1200 &final_x, &final_y,
1201 &gap_side);
1202
1203 if (POS_IS_VERTICAL (gap_side)((gap_side) == CTK_POS_TOP || (gap_side) == CTK_POS_BOTTOM))
1204 {
1205 gap_start = initial_x - rect_x;
1206 gap_end = final_x - rect_x;
1207 }
1208 else
1209 {
1210 gap_start = initial_y - rect_y;
1211 gap_end = final_y - rect_y;
1212 }
1213
1214G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
1215 /* Now render the frame, without the gap for the arrow tip */
1216 ctk_render_frame_gap (context, cr,
1217 rect_x, rect_y,
1218 rect_w, rect_h,
1219 gap_side,
1220 gap_start, gap_end);
1221G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
1222 }
1223 else
1224 {
1225 ctk_render_frame (context, cr,
1226 rect_x, rect_y,
1227 rect_w, rect_h);
1228 }
1229
1230 /* Clip to the arrow shape */
1231 cairo_save (cr);
1232
1233 ctk_popover_apply_tail_path (popover, cr);
1234 cairo_clip (cr);
1235
1236 /* Render the arrow background */
1237 ctk_render_background (context, cr,
1238 0, 0,
1239 allocation.width, allocation.height);
1240
1241 /* Render the border of the arrow tip */
1242 if (border.bottom > 0)
1243 {
1244G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
1245 ctk_style_context_get_border_color (context, state, &border_color);
1246G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
1247
1248 ctk_popover_apply_tail_path (popover, cr);
1249 cdk_cairo_set_source_rgba (cr, &border_color);
1250
1251 cairo_set_line_width (cr, border.bottom + 1);
1252 cairo_stroke (cr);
1253 }
1254
1255 /* We're done */
1256 cairo_restore (cr);
1257
1258 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1259
1260 if (child)
1261 ctk_container_propagate_draw (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
, child, cr);
1262
1263 return CDK_EVENT_PROPAGATE((0));
1264}
1265
1266static void
1267get_padding_and_border (CtkWidget *widget,
1268 CtkBorder *border)
1269{
1270 CtkStyleContext *context;
1271 CtkStateFlags state;
1272 gint border_width;
1273 CtkBorder tmp;
1274
1275 context = ctk_widget_get_style_context (widget);
1276 state = ctk_style_context_get_state (context);
1277
1278 border_width = ctk_container_get_border_width (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
);
1279
1280 ctk_style_context_get_padding (context, state, border);
1281 ctk_style_context_get_border (context, state, &tmp);
1282 border->top += tmp.top + border_width;
1283 border->right += tmp.right + border_width;
1284 border->bottom += tmp.bottom + border_width;
1285 border->left += tmp.left + border_width;
1286}
1287
1288static gint
1289get_border_radius (CtkWidget *widget)
1290{
1291 CtkStyleContext *context;
1292 CtkStateFlags state;
1293 gint border_radius;
1294
1295 context = ctk_widget_get_style_context (widget);
1296 state = ctk_style_context_get_state (context);
1297 ctk_style_context_get (context, state,
1298 CTK_STYLE_PROPERTY_BORDER_RADIUS"border-radius", &border_radius,
1299 NULL((void*)0));
1300 return border_radius;
1301}
1302
1303static gint
1304get_minimal_size (CtkPopover *popover,
1305 CtkOrientation orientation)
1306{
1307 CtkPopoverPrivate *priv = popover->priv;
1308 CtkPositionType pos;
1309 gint minimal_size;
1310
1311 minimal_size = 2 * get_border_radius (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
1312 pos = get_effective_position (popover, priv->preferred_position);
1313
1314 if ((orientation == CTK_ORIENTATION_HORIZONTAL && POS_IS_VERTICAL (pos)((pos) == CTK_POS_TOP || (pos) == CTK_POS_BOTTOM)) ||
1315 (orientation == CTK_ORIENTATION_VERTICAL && !POS_IS_VERTICAL (pos)((pos) == CTK_POS_TOP || (pos) == CTK_POS_BOTTOM)))
1316 minimal_size += TAIL_GAP_WIDTH24;
1317
1318 return minimal_size;
1319}
1320
1321static void
1322ctk_popover_get_preferred_width (CtkWidget *widget,
1323 gint *minimum_width,
1324 gint *natural_width)
1325{
1326 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1327 CtkWidget *child;
1328 gint min, nat, extra, minimal_size;
1329 CtkBorder border, margin;
1330
1331 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1332 min = nat = 0;
1333
1334 if (child)
1335 ctk_widget_get_preferred_width (child, &min, &nat);
1336
1337 get_padding_and_border (widget, &border);
1338 get_margin (widget, &margin);
1339 minimal_size = get_minimal_size (popover, CTK_ORIENTATION_HORIZONTAL);
1340
1341 min = MAX (min, minimal_size)(((min) > (minimal_size)) ? (min) : (minimal_size)) + border.left + border.right;
1342 nat = MAX (nat, minimal_size)(((nat) > (minimal_size)) ? (nat) : (minimal_size)) + border.left + border.right;
1343 extra = MAX (TAIL_HEIGHT, margin.left)(((12) > (margin.left)) ? (12) : (margin.left)) + MAX (TAIL_HEIGHT, margin.right)(((12) > (margin.right)) ? (12) : (margin.right));
1344
1345 min += extra;
1346 nat += extra;
1347
1348 *minimum_width = min;
1349 *natural_width = nat;
1350}
1351
1352static void
1353ctk_popover_get_preferred_width_for_height (CtkWidget *widget,
1354 gint height,
1355 gint *minimum_width,
1356 gint *natural_width)
1357{
1358 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1359 CtkWidget *child;
1360 CdkRectangle child_rect;
1361 gint min, nat, extra, minimal_size;
1362 gint child_height;
1363 CtkBorder border, margin;
1364
1365 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1366 min = nat = 0;
1367
1368 ctk_popover_get_rect_for_size (popover, 0, height, &child_rect);
1369 child_height = child_rect.height;
1370
1371
1372 get_padding_and_border (widget, &border);
1373 get_margin (widget, &margin);
1374 child_height -= border.top + border.bottom;
1375 minimal_size = get_minimal_size (popover, CTK_ORIENTATION_HORIZONTAL);
1376
1377 if (child)
1378 ctk_widget_get_preferred_width_for_height (child, child_height, &min, &nat);
1379
1380 min = MAX (min, minimal_size)(((min) > (minimal_size)) ? (min) : (minimal_size)) + border.left + border.right;
1381 nat = MAX (nat, minimal_size)(((nat) > (minimal_size)) ? (nat) : (minimal_size)) + border.left + border.right;
1382 extra = MAX (TAIL_HEIGHT, margin.left)(((12) > (margin.left)) ? (12) : (margin.left)) + MAX (TAIL_HEIGHT, margin.right)(((12) > (margin.right)) ? (12) : (margin.right));
1383
1384 min += extra;
1385 nat += extra;
1386
1387 *minimum_width = min;
1388 *natural_width = nat;
1389}
1390
1391static void
1392ctk_popover_get_preferred_height (CtkWidget *widget,
1393 gint *minimum_height,
1394 gint *natural_height)
1395{
1396 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1397 CtkWidget *child;
1398 gint min, nat, extra, minimal_size;
1399 CtkBorder border, margin;
1400
1401 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1402 min = nat = 0;
1403
1404 if (child)
1405 ctk_widget_get_preferred_height (child, &min, &nat);
1406
1407 get_padding_and_border (widget, &border);
1408 get_margin (widget, &margin);
1409 minimal_size = get_minimal_size (popover, CTK_ORIENTATION_VERTICAL);
1410
1411 min = MAX (min, minimal_size)(((min) > (minimal_size)) ? (min) : (minimal_size)) + border.top + border.bottom;
1412 nat = MAX (nat, minimal_size)(((nat) > (minimal_size)) ? (nat) : (minimal_size)) + border.top + border.bottom;
1413 extra = MAX (TAIL_HEIGHT, margin.top)(((12) > (margin.top)) ? (12) : (margin.top)) + MAX (TAIL_HEIGHT, margin.bottom)(((12) > (margin.bottom)) ? (12) : (margin.bottom));
1414
1415 min += extra;
1416 nat += extra;
1417
1418 *minimum_height = min;
1419 *natural_height = nat;
1420}
1421
1422static void
1423ctk_popover_get_preferred_height_for_width (CtkWidget *widget,
1424 gint width,
1425 gint *minimum_height,
1426 gint *natural_height)
1427{
1428 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1429 CtkWidget *child;
1430 CdkRectangle child_rect;
1431 gint min, nat, extra, minimal_size;
1432 gint child_width;
1433 CtkBorder border, margin;
1434
1435 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1436 min = nat = 0;
1437
1438 get_padding_and_border (widget, &border);
1439 get_margin (widget, &margin);
1440
1441 ctk_popover_get_rect_for_size (popover, width, 0, &child_rect);
1442 child_width = child_rect.width;
1443
1444 child_width -= border.left + border.right;
1445 minimal_size = get_minimal_size (popover, CTK_ORIENTATION_VERTICAL);
1446 if (child)
1447 ctk_widget_get_preferred_height_for_width (child, child_width, &min, &nat);
1448
1449 min = MAX (min, minimal_size)(((min) > (minimal_size)) ? (min) : (minimal_size)) + border.top + border.bottom;
1450 nat = MAX (nat, minimal_size)(((nat) > (minimal_size)) ? (nat) : (minimal_size)) + border.top + border.bottom;
1451 extra = MAX (TAIL_HEIGHT, margin.top)(((12) > (margin.top)) ? (12) : (margin.top)) + MAX (TAIL_HEIGHT, margin.bottom)(((12) > (margin.bottom)) ? (12) : (margin.bottom));
1452
1453 min += extra;
1454 nat += extra;
1455
1456 if (minimum_height)
1457 *minimum_height = min;
1458
1459 if (natural_height)
1460 *natural_height = nat;
1461}
1462
1463static void
1464ctk_popover_invalidate_borders (CtkPopover *popover)
1465{
1466 CtkAllocation allocation;
1467 CtkBorder border;
1468
1469 ctk_widget_get_allocation (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, &allocation);
1470 get_padding_and_border (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, &border);
1471
1472 ctk_widget_queue_draw_area (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, 0, 0, border.left + TAIL_HEIGHT12, allocation.height);
1473 ctk_widget_queue_draw_area (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, 0, 0, allocation.width, border.top + TAIL_HEIGHT12);
1474 ctk_widget_queue_draw_area (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, 0, allocation.height - border.bottom - TAIL_HEIGHT12,
1475 allocation.width, border.bottom + TAIL_HEIGHT12);
1476 ctk_widget_queue_draw_area (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, allocation.width - border.right - TAIL_HEIGHT12,
1477 0, border.right + TAIL_HEIGHT12, allocation.height);
1478}
1479
1480static void
1481ctk_popover_check_invalidate_borders (CtkPopover *popover)
1482{
1483 CtkPopoverPrivate *priv = popover->priv;
1484 CtkPositionType gap_side;
1485 gint tip_x, tip_y;
1486
1487 if (!priv->widget)
1488 return;
1489
1490 ctk_popover_get_gap_coords (popover, NULL((void*)0), NULL((void*)0),
1491 &tip_x, &tip_y, NULL((void*)0), NULL((void*)0),
1492 &gap_side);
1493
1494 if (tip_x != priv->tip_x || tip_y != priv->tip_y)
1495 {
1496 priv->tip_x = tip_x;
1497 priv->tip_y = tip_y;
1498 ctk_popover_invalidate_borders (popover);
1499 }
1500}
1501
1502static void
1503ctk_popover_size_allocate (CtkWidget *widget,
1504 CtkAllocation *allocation)
1505{
1506 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1507 CtkWidget *child;
1508
1509 ctk_widget_set_allocation (widget, allocation);
1510 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1511 if (child)
1512 {
1513 CtkAllocation child_alloc;
1514 int x, y, w, h;
1515 CtkBorder border;
1516
1517 ctk_popover_get_rect_coords (popover, &x, &y, &w, &h);
1518 get_padding_and_border (widget, &border);
1519
1520 child_alloc.x = x + border.left;
1521 child_alloc.y = y + border.top;
1522 child_alloc.width = w - border.left - border.right;
1523 child_alloc.height = h - border.top - border.bottom;
1524 ctk_widget_size_allocate (child, &child_alloc);
1525 }
1526
1527 if (ctk_widget_get_realized (widget))
1528 {
1529 cdk_window_move_resize (ctk_widget_get_window (widget),
1530 0, 0, allocation->width, allocation->height);
1531 ctk_popover_update_shape (popover);
1532 }
1533
1534 if (ctk_widget_is_drawable (widget))
1535 ctk_popover_check_invalidate_borders (popover);
1536}
1537
1538static gboolean
1539ctk_popover_button_press (CtkWidget *widget,
1540 CdkEventButton *event)
1541{
1542 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1543
1544 if (event->type != CDK_BUTTON_PRESS)
1545 return CDK_EVENT_PROPAGATE((0));
1546
1547 popover->priv->button_pressed = TRUE(!(0));
1548
1549 return CDK_EVENT_PROPAGATE((0));
1550}
1551
1552static gboolean
1553ctk_popover_button_release (CtkWidget *widget,
1554 CdkEventButton *event)
1555{
1556 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1557 CtkWidget *child, *event_widget;
1558
1559 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1560
1561 if (!popover->priv->button_pressed)
1562 return CDK_EVENT_PROPAGATE((0));
1563
1564 event_widget = ctk_get_event_widget ((CdkEvent *) event);
1565
1566 if (child && event->window == ctk_widget_get_window (widget))
1567 {
1568 CtkAllocation child_alloc;
1569
1570 ctk_widget_get_allocation (child, &child_alloc);
1571
1572 if (event->x < child_alloc.x ||
1573 event->x > child_alloc.x + child_alloc.width ||
1574 event->y < child_alloc.y ||
1575 event->y > child_alloc.y + child_alloc.height)
1576 ctk_popover_popdown (popover);
1577 }
1578 else if (!event_widget || !ctk_widget_is_ancestor (event_widget, widget))
1579 {
1580 ctk_popover_popdown (popover);
1581 }
1582
1583 return CDK_EVENT_PROPAGATE((0));
1584}
1585
1586static gboolean
1587ctk_popover_key_press (CtkWidget *widget,
1588 CdkEventKey *event)
1589{
1590 CtkWidget *toplevel, *focus;
1591
1592 if (event->keyval == CDK_KEY_Escape0xff1b)
1593 {
1594 ctk_popover_popdown (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
);
1595 return CDK_EVENT_STOP((!(0)));
1596 }
1597
1598 if (!CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv->modal)
1599 return CDK_EVENT_PROPAGATE((0));
1600
1601 toplevel = ctk_widget_get_toplevel (widget);
1602
1603 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; }))))
)
1604 {
1605 focus = ctk_window_get_focus (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
1606
1607 if (focus && ctk_widget_is_ancestor (focus, widget))
1608 return ctk_widget_event (focus, (CdkEvent*) event);
1609 }
1610
1611 return CDK_EVENT_PROPAGATE((0));
1612}
1613
1614static void
1615ctk_popover_grab_focus (CtkWidget *widget)
1616{
1617 CtkPopoverPrivate *priv = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv;
1618 CtkWidget *child;
1619
1620 if (!priv->visible)
1621 return;
1622
1623 /* Focus the first natural child */
1624 child = ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
);
1625
1626 if (child)
1627 ctk_widget_child_focus (child, CTK_DIR_TAB_FORWARD);
1628}
1629
1630static gboolean
1631ctk_popover_focus (CtkWidget *widget,
1632 CtkDirectionType direction)
1633{
1634 CtkPopover *popover = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
;
1635 CtkPopoverPrivate *priv = popover->priv;
1636
1637 if (!priv->visible)
1638 return FALSE(0);
1639
1640 if (!CTK_WIDGET_CLASS (ctk_popover_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), ((ctk_widget_get_type ()))))
))
->focus (widget, direction))
1641 {
1642 CtkWidget *focus;
1643
1644 focus = ctk_window_get_focus (popover->priv->window);
1645 focus = ctk_widget_get_parent (focus);
1646
1647 /* Unset focus child through children, so it is next stepped from
1648 * scratch.
1649 */
1650 while (focus && focus != widget)
1651 {
1652 ctk_container_set_focus_child (CTK_CONTAINER (focus)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((focus)), ((ctk_container_get_type ()))))))
, NULL((void*)0));
1653 focus = ctk_widget_get_parent (focus);
1654 }
1655
1656 return ctk_widget_child_focus (ctk_bin_get_child (CTK_BIN (widget)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_bin_get_type ()))))))
),
1657 direction);
1658 }
1659
1660 return TRUE(!(0));
1661}
1662
1663static void
1664ctk_popover_show (CtkWidget *widget)
1665{
1666 CtkPopoverPrivate *priv = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv;
1667
1668 if (priv->window)
1669 _ctk_window_raise_popover (priv->window, widget);
1670
1671 priv->visible = TRUE(!(0));
1672
1673 CTK_WIDGET_CLASS (ctk_popover_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), ((ctk_widget_get_type ()))))
))
->show (widget);
1674
1675 if (priv->modal)
1676 ctk_popover_apply_modality (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
, TRUE(!(0)));
1677
1678 priv->state = STATE_SHOWN;
1679
1680 if (ctk_widget_get_realized (widget))
1681 cdk_window_input_shape_combine_region (ctk_widget_get_parent_window (widget),
1682 NULL((void*)0), 0, 0);
1683}
1684
1685static void
1686ctk_popover_hide (CtkWidget *widget)
1687{
1688 CtkPopoverPrivate *priv = CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
->priv;
1689
1690 ctk_popover_hide_internal (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
);
1691
1692 ctk_popover_stop_transition (CTK_POPOVER (widget)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_popover_get_type ()))))))
);
1693 priv->state = STATE_HIDDEN;
1694 priv->transition_diff = 0;
1695 ctk_progress_tracker_finish (&priv->tracker);
1696 ctk_widget_set_opacity (widget, 1.0);
1697
1698
1699 CTK_WIDGET_CLASS (ctk_popover_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_popover_parent_class)), ((ctk_widget_get_type ()))))
))
->hide (widget);
1700}
1701
1702static void
1703ctk_popover_class_init (CtkPopoverClass *klass)
1704{
1705 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_widget_get_type ()))))))
;
1706 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
1707
1708 object_class->set_property = ctk_popover_set_property;
1709 object_class->get_property = ctk_popover_get_property;
1710 object_class->finalize = ctk_popover_finalize;
1711 object_class->dispose = ctk_popover_dispose;
1712
1713 widget_class->realize = ctk_popover_realize;
1714 widget_class->map = ctk_popover_map;
1715 widget_class->unmap = ctk_popover_unmap;
1716 widget_class->get_preferred_width = ctk_popover_get_preferred_width;
1717 widget_class->get_preferred_height = ctk_popover_get_preferred_height;
1718 widget_class->get_preferred_width_for_height = ctk_popover_get_preferred_width_for_height;
1719 widget_class->get_preferred_height_for_width = ctk_popover_get_preferred_height_for_width;
1720 widget_class->size_allocate = ctk_popover_size_allocate;
1721 widget_class->draw = ctk_popover_draw;
1722 widget_class->button_press_event = ctk_popover_button_press;
1723 widget_class->button_release_event = ctk_popover_button_release;
1724 widget_class->key_press_event = ctk_popover_key_press;
1725 widget_class->grab_focus = ctk_popover_grab_focus;
1726 widget_class->focus = ctk_popover_focus;
1727 widget_class->show = ctk_popover_show;
1728 widget_class->hide = ctk_popover_hide;
1729
1730 /**
1731 * CtkPopover:relative-to:
1732 *
1733 * Sets the attached widget.
1734 *
1735 * Since: 3.12
1736 */
1737 properties[PROP_RELATIVE_TO] =
1738 g_param_spec_object ("relative-to",
1739 P_("Relative to")g_dgettext("ctk30" "-properties","Relative to"),
1740 P_("Widget the bubble window points to")g_dgettext("ctk30" "-properties","Widget the bubble window points to"
)
,
1741 CTK_TYPE_WIDGET(ctk_widget_get_type ()),
1742 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1743
1744 /**
1745 * CtkPopover:pointing-to:
1746 *
1747 * Marks a specific rectangle to be pointed.
1748 *
1749 * Since: 3.12
1750 */
1751 properties[PROP_POINTING_TO] =
1752 g_param_spec_boxed ("pointing-to",
1753 P_("Pointing to")g_dgettext("ctk30" "-properties","Pointing to"),
1754 P_("Rectangle the bubble window points to")g_dgettext("ctk30" "-properties","Rectangle the bubble window points to"
)
,
1755 CDK_TYPE_RECTANGLE(cdk_rectangle_get_type ()),
1756 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1757
1758 /**
1759 * CtkPopover:position
1760 *
1761 * Sets the preferred position of the popover.
1762 *
1763 * Since: 3.12
1764 */
1765 properties[PROP_POSITION] =
1766 g_param_spec_enum ("position",
1767 P_("Position")g_dgettext("ctk30" "-properties","Position"),
1768 P_("Position to place the bubble window")g_dgettext("ctk30" "-properties","Position to place the bubble window"
)
,
1769 CTK_TYPE_POSITION_TYPE(ctk_position_type_get_type ()), CTK_POS_TOP,
1770 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1771
1772 /**
1773 * CtkPopover:modal
1774 *
1775 * Sets whether the popover is modal (so other elements in the window do not
1776 * receive input while the popover is visible).
1777 *
1778 * Since: 3.12
1779 */
1780 properties[PROP_MODAL] =
1781 g_param_spec_boolean ("modal",
1782 P_("Modal")g_dgettext("ctk30" "-properties","Modal"),
1783 P_("Whether the popover is modal")g_dgettext("ctk30" "-properties","Whether the popover is modal"
)
,
1784 TRUE(!(0)),
1785 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1786
1787 /**
1788 * CtkPopover:transitions-enabled
1789 *
1790 * Whether show/hide transitions are enabled for this popover.
1791 *
1792 * Since: 3.16
1793 *
1794 * Deprecated: 3.22: You can show or hide the popover without transitions
1795 * using ctk_widget_show() and ctk_widget_hide() while ctk_popover_popup()
1796 * and ctk_popover_popdown() will use transitions.
1797 */
1798 properties[PROP_TRANSITIONS_ENABLED] =
1799 g_param_spec_boolean ("transitions-enabled",
1800 P_("Transitions enabled")g_dgettext("ctk30" "-properties","Transitions enabled"),
1801 P_("Whether show/hide transitions are enabled or not")g_dgettext("ctk30" "-properties","Whether show/hide transitions are enabled or not"
)
,
1802 TRUE(!(0)),
1803 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1804
1805 /**
1806 * CtkPopover:constrain-to:
1807 *
1808 * Sets a constraint for the popover position.
1809 *
1810 * Since: 3.20
1811 */
1812 properties[PROP_CONSTRAIN_TO] =
1813 g_param_spec_enum ("constrain-to",
1814 P_("Constraint")g_dgettext("ctk30" "-properties","Constraint"),
1815 P_("Constraint for the popover position")g_dgettext("ctk30" "-properties","Constraint for the popover position"
)
,
1816 CTK_TYPE_POPOVER_CONSTRAINT(ctk_popover_constraint_get_type ()), CTK_POPOVER_CONSTRAINT_WINDOW,
1817 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1818
1819 g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
1820
1821 /**
1822 * CtkPopover::closed:
1823 *
1824 * This signal is emitted when the popover is dismissed either through
1825 * API or user interaction.
1826 *
1827 * Since: 3.12
1828 */
1829 signals[CLOSED] =
1830 g_signal_new (I_("closed")g_intern_static_string ("closed"),
1831 G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type),
1832 G_SIGNAL_RUN_LAST,
1833 G_STRUCT_OFFSET (CtkPopoverClass, closed)((glong) __builtin_offsetof(CtkPopoverClass, closed)),
1834 NULL((void*)0), NULL((void*)0), NULL((void*)0),
1835 G_TYPE_NONE((GType) ((1) << (2))), 0);
1836
1837 quark_widget_popovers = g_quark_from_static_string ("ctk-quark-widget-popovers");
1838 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_POPOVER_ACCESSIBLE(ctk_popover_accessible_get_type ()));
1839 ctk_widget_class_set_css_name (widget_class, "popover");
1840}
1841
1842static void
1843ctk_popover_update_scrollable (CtkPopover *popover)
1844{
1845 CtkPopoverPrivate *priv = popover->priv;
1846 CtkScrollable *scrollable;
1847
1848 scrollable = CTK_SCROLLABLE (ctk_widget_get_ancestor (priv->widget,((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_ancestor (priv->widget, (ctk_scrollable_get_type
())))), ((ctk_scrollable_get_type ()))))))
1849 CTK_TYPE_SCROLLABLE))((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_ancestor (priv->widget, (ctk_scrollable_get_type
())))), ((ctk_scrollable_get_type ()))))))
;
1850 ctk_popover_set_scrollable_full (popover, scrollable);
1851}
1852
1853static void
1854_ctk_popover_parent_hierarchy_changed (CtkWidget *widget,
1855 CtkWidget *previous_toplevel G_GNUC_UNUSED__attribute__ ((__unused__)),
1856 CtkPopover *popover)
1857{
1858 CtkPopoverPrivate *priv = popover->priv;
1859 CtkWindow *new_window;
1860
1861 new_window = CTK_WINDOW (ctk_widget_get_ancestor (widget, CTK_TYPE_WINDOW))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_ancestor (widget, (ctk_window_get_type ()
)))), ((ctk_window_get_type ()))))))
;
1862
1863 if (priv->window == new_window)
1864 return;
1865
1866 g_object_ref (popover)((__typeof__ (popover)) (g_object_ref) (popover));
1867
1868 if (ctk_widget_has_grab (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
1869 ctk_popover_apply_modality (popover, FALSE(0));
1870
1871 if (priv->window)
1872 _ctk_window_remove_popover (priv->window, CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
1873
1874 if (priv->parent_scrollable)
1875 ctk_popover_set_scrollable_full (popover, NULL((void*)0));
1876
1877 priv->window = new_window;
1878
1879 if (new_window)
1880 {
1881 _ctk_window_add_popover (new_window, CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, priv->widget, TRUE(!(0)));
1882 ctk_popover_update_scrollable (popover);
1883 ctk_popover_update_position (popover);
1884 }
1885
1886 if (ctk_widget_is_visible (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
1887 ctk_widget_queue_resize (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
1888
1889 g_object_unref (popover);
1890}
1891
1892static void
1893_popover_propagate_state (CtkPopover *popover,
1894 CtkStateFlags state,
1895 CtkStateFlags old_state,
1896 CtkStateFlags flag)
1897{
1898 if ((state & flag) != (old_state & flag))
1899 {
1900 if ((state & flag) == flag)
1901 ctk_widget_set_state_flags (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, flag, FALSE(0));
1902 else
1903 ctk_widget_unset_state_flags (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, flag);
1904 }
1905}
1906
1907static void
1908_ctk_popover_parent_state_changed (CtkWidget *widget,
1909 CtkStateFlags old_state,
1910 CtkPopover *popover)
1911{
1912 guint state;
1913
1914 state = ctk_widget_get_state_flags (widget);
1915 _popover_propagate_state (popover, state, old_state,
1916 CTK_STATE_FLAG_INSENSITIVE);
1917 _popover_propagate_state (popover, state, old_state,
1918 CTK_STATE_FLAG_BACKDROP);
1919}
1920
1921static void
1922_ctk_popover_parent_grab_notify (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1923 gboolean was_shadowed G_GNUC_UNUSED__attribute__ ((__unused__)),
1924 CtkPopover *popover)
1925{
1926 CtkPopoverPrivate *priv = popover->priv;
1927
1928 if (priv->modal &&
1929 ctk_widget_is_visible (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
) &&
1930 !ctk_widget_has_grab (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
1931 {
1932 CtkWidget *grab_widget;
1933
1934 grab_widget = ctk_grab_get_current ();
1935
1936 if (!grab_widget || !CTK_IS_POPOVER (grab_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(grab_widget)); GType __t = ((ctk_popover_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; }))))
)
1937 ctk_popover_popdown (popover);
1938 }
1939}
1940
1941static void
1942_ctk_popover_parent_unmap (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1943 CtkPopover *popover)
1944{
1945 CtkPopoverPrivate *priv = popover->priv;
1946
1947 if (priv->state == STATE_SHOWING)
1948 priv->visible = FALSE(0);
1949 else if (priv->state == STATE_SHOWN)
1950 ctk_popover_set_state (popover, STATE_HIDING);
1951}
1952
1953static void
1954_ctk_popover_parent_size_allocate (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1955 CtkAllocation *allocation G_GNUC_UNUSED__attribute__ ((__unused__)),
1956 CtkPopover *popover)
1957{
1958 ctk_popover_update_position (popover);
1959}
1960
1961static void
1962_unmanage_popover (GObject *object)
1963{
1964 ctk_popover_update_relative_to (CTK_POPOVER (object)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_popover_get_type ()))))))
, NULL((void*)0));
1965 g_object_unref (object);
1966}
1967
1968static void
1969widget_manage_popover (CtkWidget *widget,
1970 CtkPopover *popover)
1971{
1972 GHashTable *popovers;
1973
1974 popovers = g_object_get_qdata (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, quark_widget_popovers);
1975
1976 if (G_UNLIKELY (!popovers)(!popovers))
1977 {
1978 popovers = g_hash_table_new_full (NULL((void*)0), NULL((void*)0),
1979 (GDestroyNotify) _unmanage_popover, NULL((void*)0));
1980 g_object_set_qdata_full (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
,
1981 quark_widget_popovers, popovers,
1982 (GDestroyNotify) g_hash_table_unref);
1983 }
1984
1985 g_hash_table_add (popovers, g_object_ref_sink (popover)((__typeof__ (popover)) (g_object_ref_sink) (popover)));
1986}
1987
1988static void
1989widget_unmanage_popover (CtkWidget *widget,
1990 CtkPopover *popover)
1991{
1992 GHashTable *popovers;
1993
1994 popovers = g_object_get_qdata (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, quark_widget_popovers);
1995
1996 if (G_UNLIKELY (!popovers)(!popovers))
1997 return;
1998
1999 g_hash_table_remove (popovers, popover);
2000}
2001
2002static void
2003adjustment_changed_cb (CtkAdjustment *adjustment G_GNUC_UNUSED__attribute__ ((__unused__)),
2004 CtkPopover *popover)
2005{
2006 ctk_popover_update_position (popover);
1
Calling 'ctk_popover_update_position'
2007}
2008
2009static void
2010_ctk_popover_set_scrollable (CtkPopover *popover,
2011 CtkScrollable *scrollable)
2012{
2013 CtkPopoverPrivate *priv = popover->priv;
2014
2015 if (priv->parent_scrollable)
2016 {
2017 if (priv->vadj)
2018 {
2019 g_signal_handlers_disconnect_by_data (priv->vadj, popover)g_signal_handlers_disconnect_matched ((priv->vadj), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (popover))
;
2020 g_object_unref (priv->vadj);
2021 priv->vadj = NULL((void*)0);
2022 }
2023
2024 if (priv->hadj)
2025 {
2026 g_signal_handlers_disconnect_by_data (priv->hadj, popover)g_signal_handlers_disconnect_matched ((priv->hadj), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (popover))
;
2027 g_object_unref (priv->hadj);
2028 priv->hadj = NULL((void*)0);
2029 }
2030
2031 g_object_unref (priv->parent_scrollable);
2032 }
2033
2034 priv->parent_scrollable = scrollable;
2035
2036 if (scrollable)
2037 {
2038 g_object_ref (scrollable)((__typeof__ (scrollable)) (g_object_ref) (scrollable));
2039 priv->vadj = ctk_scrollable_get_vadjustment (scrollable);
2040 priv->hadj = ctk_scrollable_get_hadjustment (scrollable);
2041
2042 if (priv->vadj)
2043 {
2044 g_object_ref (priv->vadj)((__typeof__ (priv->vadj)) (g_object_ref) (priv->vadj));
2045 g_signal_connect (priv->vadj, "changed",g_signal_connect_data ((priv->vadj), ("changed"), (((GCallback
) (adjustment_changed_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
2046 G_CALLBACK (adjustment_changed_cb), popover)g_signal_connect_data ((priv->vadj), ("changed"), (((GCallback
) (adjustment_changed_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
;
2047 g_signal_connect (priv->vadj, "value-changed",g_signal_connect_data ((priv->vadj), ("value-changed"), ((
(GCallback) (adjustment_changed_cb))), (popover), ((void*)0),
(GConnectFlags) 0)
2048 G_CALLBACK (adjustment_changed_cb), popover)g_signal_connect_data ((priv->vadj), ("value-changed"), ((
(GCallback) (adjustment_changed_cb))), (popover), ((void*)0),
(GConnectFlags) 0)
;
2049 }
2050
2051 if (priv->hadj)
2052 {
2053 g_object_ref (priv->hadj)((__typeof__ (priv->hadj)) (g_object_ref) (priv->hadj));
2054 g_signal_connect (priv->hadj, "changed",g_signal_connect_data ((priv->hadj), ("changed"), (((GCallback
) (adjustment_changed_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
2055 G_CALLBACK (adjustment_changed_cb), popover)g_signal_connect_data ((priv->hadj), ("changed"), (((GCallback
) (adjustment_changed_cb))), (popover), ((void*)0), (GConnectFlags
) 0)
;
2056 g_signal_connect (priv->hadj, "value-changed",g_signal_connect_data ((priv->hadj), ("value-changed"), ((
(GCallback) (adjustment_changed_cb))), (popover), ((void*)0),
(GConnectFlags) 0)
2057 G_CALLBACK (adjustment_changed_cb), popover)g_signal_connect_data ((priv->hadj), ("value-changed"), ((
(GCallback) (adjustment_changed_cb))), (popover), ((void*)0),
(GConnectFlags) 0)
;
2058 }
2059 }
2060}
2061
2062static void
2063scrollable_notify_cb (GObject *object,
2064 GParamSpec *pspec,
2065 CtkPopover *popover)
2066{
2067 if (pspec->value_type == CTK_TYPE_ADJUSTMENT(ctk_adjustment_get_type ()))
2068 _ctk_popover_set_scrollable (popover, CTK_SCROLLABLE (object)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_scrollable_get_type ()))))))
);
2069}
2070
2071static void
2072ctk_popover_set_scrollable_full (CtkPopover *popover,
2073 CtkScrollable *scrollable)
2074{
2075 CtkPopoverPrivate *priv = popover->priv;
2076
2077 if (priv->scrollable_notify_id != 0 &&
2078 g_signal_handler_is_connected (priv->parent_scrollable, priv->scrollable_notify_id))
2079 {
2080 g_signal_handler_disconnect (priv->parent_scrollable, priv->scrollable_notify_id);
2081 priv->scrollable_notify_id = 0;
2082 }
2083
2084 _ctk_popover_set_scrollable (popover, scrollable);
2085
2086 if (scrollable)
2087 {
2088 priv->scrollable_notify_id =
2089 g_signal_connect (priv->parent_scrollable, "notify",g_signal_connect_data ((priv->parent_scrollable), ("notify"
), (((GCallback) (scrollable_notify_cb))), (popover), ((void*
)0), (GConnectFlags) 0)
2090 G_CALLBACK (scrollable_notify_cb), popover)g_signal_connect_data ((priv->parent_scrollable), ("notify"
), (((GCallback) (scrollable_notify_cb))), (popover), ((void*
)0), (GConnectFlags) 0)
;
2091 }
2092}
2093
2094static void
2095ctk_popover_update_relative_to (CtkPopover *popover,
2096 CtkWidget *relative_to)
2097{
2098 CtkPopoverPrivate *priv = popover->priv;
2099 CtkStateFlags old_state = 0;
2100
2101 if (priv->widget == relative_to)
2102 return;
2103
2104 g_object_ref (popover)((__typeof__ (popover)) (g_object_ref) (popover));
2105
2106 if (priv->window)
2107 {
2108 _ctk_window_remove_popover (priv->window, CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
2109 priv->window = NULL((void*)0);
2110 }
2111
2112 popover_unset_prev_focus (popover);
2113
2114 if (priv->widget)
2115 {
2116 old_state = ctk_widget_get_state_flags (priv->widget);
2117 if (g_signal_handler_is_connected (priv->widget, priv->hierarchy_changed_id))
2118 g_signal_handler_disconnect (priv->widget, priv->hierarchy_changed_id);
2119 if (g_signal_handler_is_connected (priv->widget, priv->size_allocate_id))
2120 g_signal_handler_disconnect (priv->widget, priv->size_allocate_id);
2121 if (g_signal_handler_is_connected (priv->widget, priv->unmap_id))
2122 g_signal_handler_disconnect (priv->widget, priv->unmap_id);
2123 if (g_signal_handler_is_connected (priv->widget, priv->state_changed_id))
2124 g_signal_handler_disconnect (priv->widget, priv->state_changed_id);
2125 if (g_signal_handler_is_connected (priv->widget, priv->grab_notify_id))
2126 g_signal_handler_disconnect (priv->widget, priv->grab_notify_id);
2127
2128 widget_unmanage_popover (priv->widget, popover);
2129 }
2130
2131 if (priv->parent_scrollable)
2132 ctk_popover_set_scrollable_full (popover, NULL((void*)0));
2133
2134 priv->widget = relative_to;
2135 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_RELATIVE_TO]);
2136
2137 if (priv->widget)
2138 {
2139 priv->window =
2140 CTK_WINDOW (ctk_widget_get_ancestor (priv->widget, CTK_TYPE_WINDOW))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_ancestor (priv->widget, (ctk_window_get_type
())))), ((ctk_window_get_type ()))))))
;
2141
2142 priv->hierarchy_changed_id =
2143 g_signal_connect (priv->widget, "hierarchy-changed",g_signal_connect_data ((priv->widget), ("hierarchy-changed"
), (((GCallback) (_ctk_popover_parent_hierarchy_changed))), (
popover), ((void*)0), (GConnectFlags) 0)
2144 G_CALLBACK (_ctk_popover_parent_hierarchy_changed),g_signal_connect_data ((priv->widget), ("hierarchy-changed"
), (((GCallback) (_ctk_popover_parent_hierarchy_changed))), (
popover), ((void*)0), (GConnectFlags) 0)
2145 popover)g_signal_connect_data ((priv->widget), ("hierarchy-changed"
), (((GCallback) (_ctk_popover_parent_hierarchy_changed))), (
popover), ((void*)0), (GConnectFlags) 0)
;
2146 priv->size_allocate_id =
2147 g_signal_connect (priv->widget, "size-allocate",g_signal_connect_data ((priv->widget), ("size-allocate"), (
((GCallback) (_ctk_popover_parent_size_allocate))), (popover)
, ((void*)0), (GConnectFlags) 0)
2148 G_CALLBACK (_ctk_popover_parent_size_allocate),g_signal_connect_data ((priv->widget), ("size-allocate"), (
((GCallback) (_ctk_popover_parent_size_allocate))), (popover)
, ((void*)0), (GConnectFlags) 0)
2149 popover)g_signal_connect_data ((priv->widget), ("size-allocate"), (
((GCallback) (_ctk_popover_parent_size_allocate))), (popover)
, ((void*)0), (GConnectFlags) 0)
;
2150 priv->unmap_id =
2151 g_signal_connect (priv->widget, "unmap",g_signal_connect_data ((priv->widget), ("unmap"), (((GCallback
) (_ctk_popover_parent_unmap))), (popover), ((void*)0), (GConnectFlags
) 0)
2152 G_CALLBACK (_ctk_popover_parent_unmap),g_signal_connect_data ((priv->widget), ("unmap"), (((GCallback
) (_ctk_popover_parent_unmap))), (popover), ((void*)0), (GConnectFlags
) 0)
2153 popover)g_signal_connect_data ((priv->widget), ("unmap"), (((GCallback
) (_ctk_popover_parent_unmap))), (popover), ((void*)0), (GConnectFlags
) 0)
;
2154 priv->state_changed_id =
2155 g_signal_connect (priv->widget, "state-flags-changed",g_signal_connect_data ((priv->widget), ("state-flags-changed"
), (((GCallback) (_ctk_popover_parent_state_changed))), (popover
), ((void*)0), (GConnectFlags) 0)
2156 G_CALLBACK (_ctk_popover_parent_state_changed),g_signal_connect_data ((priv->widget), ("state-flags-changed"
), (((GCallback) (_ctk_popover_parent_state_changed))), (popover
), ((void*)0), (GConnectFlags) 0)
2157 popover)g_signal_connect_data ((priv->widget), ("state-flags-changed"
), (((GCallback) (_ctk_popover_parent_state_changed))), (popover
), ((void*)0), (GConnectFlags) 0)
;
2158 priv->grab_notify_id =
2159 g_signal_connect (priv->widget, "grab-notify",g_signal_connect_data ((priv->widget), ("grab-notify"), ((
(GCallback) (_ctk_popover_parent_grab_notify))), (popover), (
(void*)0), (GConnectFlags) 0)
2160 G_CALLBACK (_ctk_popover_parent_grab_notify),g_signal_connect_data ((priv->widget), ("grab-notify"), ((
(GCallback) (_ctk_popover_parent_grab_notify))), (popover), (
(void*)0), (GConnectFlags) 0)
2161 popover)g_signal_connect_data ((priv->widget), ("grab-notify"), ((
(GCallback) (_ctk_popover_parent_grab_notify))), (popover), (
(void*)0), (GConnectFlags) 0)
;
2162
2163 /* Give ownership of the popover to widget */
2164 widget_manage_popover (priv->widget, popover);
2165 }
2166
2167 if (priv->window)
2168 _ctk_window_add_popover (priv->window, CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
, priv->widget, TRUE(!(0)));
2169
2170 if (priv->widget)
2171 ctk_popover_update_scrollable (popover);
2172
2173 if (priv->widget)
2174 _ctk_popover_parent_state_changed (priv->widget, old_state, popover);
2175
2176 _ctk_widget_update_parent_muxer (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
2177 g_object_unref (popover);
2178}
2179
2180static void
2181ctk_popover_update_pointing_to (CtkPopover *popover,
2182 const CdkRectangle *pointing_to)
2183{
2184 CtkPopoverPrivate *priv = popover->priv;
2185
2186 if (pointing_to)
2187 {
2188 priv->pointing_to = *pointing_to;
2189 priv->has_pointing_to = TRUE(!(0));
2190 }
2191 else
2192 priv->has_pointing_to = FALSE(0);
2193
2194 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_POINTING_TO]);
2195}
2196
2197static void
2198ctk_popover_update_preferred_position (CtkPopover *popover,
2199 CtkPositionType position)
2200{
2201 if (popover->priv->preferred_position == position)
2202 return;
2203
2204 popover->priv->preferred_position = position;
2205 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_POSITION]);
2206}
2207
2208static void
2209ctk_popover_multipress_gesture_pressed (CtkGestureMultiPress *gesture G_GNUC_UNUSED__attribute__ ((__unused__)),
2210 gint n_press G_GNUC_UNUSED__attribute__ ((__unused__)),
2211 gdouble widget_x G_GNUC_UNUSED__attribute__ ((__unused__)),
2212 gdouble widget_y G_GNUC_UNUSED__attribute__ ((__unused__)),
2213 CtkPopover *popover)
2214{
2215 CtkPopoverPrivate *priv = popover->priv;
2216
2217 if (!ctk_window_is_active (priv->window) && ctk_widget_is_drawable (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
2218 ctk_window_present_with_time (priv->window, ctk_get_current_event_time ());
2219}
2220
2221/**
2222 * ctk_popover_new:
2223 * @relative_to: (allow-none): #CtkWidget the popover is related to
2224 *
2225 * Creates a new popover to point to @relative_to
2226 *
2227 * Returns: a new #CtkPopover
2228 *
2229 * Since: 3.12
2230 **/
2231CtkWidget *
2232ctk_popover_new (CtkWidget *relative_to)
2233{
2234 g_return_val_if_fail (relative_to == NULL || CTK_IS_WIDGET (relative_to), NULL)do { if ((relative_to == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((relative_to)); 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__)), "relative_to == NULL || CTK_IS_WIDGET (relative_to)"
); return (((void*)0)); } } while (0)
;
2235
2236 return g_object_new (CTK_TYPE_POPOVER(ctk_popover_get_type ()),
2237 "relative-to", relative_to,
2238 NULL((void*)0));
2239}
2240
2241/**
2242 * ctk_popover_set_relative_to:
2243 * @popover: a #CtkPopover
2244 * @relative_to: (allow-none): a #CtkWidget
2245 *
2246 * Sets a new widget to be attached to @popover. If @popover is
2247 * visible, the position will be updated.
2248 *
2249 * Note: the ownership of popovers is always given to their @relative_to
2250 * widget, so if @relative_to is set to %NULL on an attached @popover, it
2251 * will be detached from its previous widget, and consequently destroyed
2252 * unless extra references are kept.
2253 *
2254 * Since: 3.12
2255 **/
2256void
2257ctk_popover_set_relative_to (CtkPopover *popover,
2258 CtkWidget *relative_to)
2259{
2260 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2261 g_return_if_fail (relative_to == NULL || CTK_IS_WIDGET (relative_to))do { if ((relative_to == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((relative_to)); 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__)), "relative_to == NULL || CTK_IS_WIDGET (relative_to)"
); return; } } while (0)
;
2262
2263 ctk_popover_update_relative_to (popover, relative_to);
2264
2265 if (relative_to)
2266 ctk_popover_update_position (popover);
2267}
2268
2269/**
2270 * ctk_popover_get_relative_to:
2271 * @popover: a #CtkPopover
2272 *
2273 * Returns the widget @popover is currently attached to
2274 *
2275 * Returns: (transfer none): a #CtkWidget
2276 *
2277 * Since: 3.12
2278 **/
2279CtkWidget *
2280ctk_popover_get_relative_to (CtkPopover *popover)
2281{
2282 g_return_val_if_fail (CTK_IS_POPOVER (popover), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return (((void*)0)); } } while
(0)
;
2283
2284 return popover->priv->widget;
2285}
2286
2287/**
2288 * ctk_popover_set_pointing_to:
2289 * @popover: a #CtkPopover
2290 * @rect: rectangle to point to
2291 *
2292 * Sets the rectangle that @popover will point to, in the
2293 * coordinate space of the widget @popover is attached to,
2294 * see ctk_popover_set_relative_to().
2295 *
2296 * Since: 3.12
2297 **/
2298void
2299ctk_popover_set_pointing_to (CtkPopover *popover,
2300 const CdkRectangle *rect)
2301{
2302 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2303 g_return_if_fail (rect != NULL)do { if ((rect != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "rect != NULL"); return;
} } while (0)
;
2304
2305 ctk_popover_update_pointing_to (popover, rect);
2306 ctk_popover_update_position (popover);
2307}
2308
2309/**
2310 * ctk_popover_get_pointing_to:
2311 * @popover: a #CtkPopover
2312 * @rect: (out): location to store the rectangle
2313 *
2314 * If a rectangle to point to has been set, this function will
2315 * return %TRUE and fill in @rect with such rectangle, otherwise
2316 * it will return %FALSE and fill in @rect with the attached
2317 * widget coordinates.
2318 *
2319 * Returns: %TRUE if a rectangle to point to was set.
2320 **/
2321gboolean
2322ctk_popover_get_pointing_to (CtkPopover *popover,
2323 CdkRectangle *rect)
2324{
2325 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2326
2327 g_return_val_if_fail (CTK_IS_POPOVER (popover), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return ((0)); } } while (0)
;
16
Taking false branch
17
Assuming field 'g_class' is null
18
Assuming the condition is true
19
Taking true branch
20
Loop condition is false. Exiting loop
2328
2329 if (rect
20.1
'rect' is non-null
)
21
Taking true branch
2330 {
2331 if (priv->has_pointing_to)
22
Assuming field 'has_pointing_to' is 0
23
Taking false branch
2332 *rect = priv->pointing_to;
2333 else if (priv->widget)
24
Assuming field 'widget' is null
25
Taking false branch
2334 {
2335 ctk_widget_get_allocation (priv->widget, rect);
2336 rect->x = rect->y = 0;
2337 }
2338 }
2339
2340 return priv->has_pointing_to;
26
Returning without writing to 'rect->x'
2341}
2342
2343/**
2344 * ctk_popover_set_position:
2345 * @popover: a #CtkPopover
2346 * @position: preferred popover position
2347 *
2348 * Sets the preferred position for @popover to appear. If the @popover
2349 * is currently visible, it will be immediately updated.
2350 *
2351 * This preference will be respected where possible, although
2352 * on lack of space (eg. if close to the window edges), the
2353 * #CtkPopover may choose to appear on the opposite side
2354 *
2355 * Since: 3.12
2356 **/
2357void
2358ctk_popover_set_position (CtkPopover *popover,
2359 CtkPositionType position)
2360{
2361 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2362 g_return_if_fail (position >= CTK_POS_LEFT && position <= CTK_POS_BOTTOM)do { if ((position >= CTK_POS_LEFT && position <=
CTK_POS_BOTTOM)) { } else { g_return_if_fail_warning ("Ctk",
((const char*) (__func__)), "position >= CTK_POS_LEFT && position <= CTK_POS_BOTTOM"
); return; } } while (0)
;
2363
2364 ctk_popover_update_preferred_position (popover, position);
2365 ctk_popover_update_position (popover);
2366}
2367
2368/**
2369 * ctk_popover_get_position:
2370 * @popover: a #CtkPopover
2371 *
2372 * Returns the preferred position of @popover.
2373 *
2374 * Returns: The preferred position.
2375 **/
2376CtkPositionType
2377ctk_popover_get_position (CtkPopover *popover)
2378{
2379 g_return_val_if_fail (CTK_IS_POPOVER (popover), CTK_POS_TOP)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return (CTK_POS_TOP); } } while
(0)
;
2380
2381 return popover->priv->preferred_position;
2382}
2383
2384/**
2385 * ctk_popover_set_modal:
2386 * @popover: a #CtkPopover
2387 * @modal: #TRUE to make popover claim all input within the toplevel
2388 *
2389 * Sets whether @popover is modal, a modal popover will grab all input
2390 * within the toplevel and grab the keyboard focus on it when being
2391 * displayed. Clicking outside the popover area or pressing Esc will
2392 * dismiss the popover and ungrab input.
2393 *
2394 * Since: 3.12
2395 **/
2396void
2397ctk_popover_set_modal (CtkPopover *popover,
2398 gboolean modal)
2399{
2400 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2401
2402 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2403
2404 modal = modal != FALSE(0);
2405
2406 if (priv->modal == modal)
2407 return;
2408
2409 priv->modal = modal;
2410
2411 if (ctk_widget_is_visible (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
2412 ctk_popover_apply_modality (popover, priv->modal);
2413
2414 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_MODAL]);
2415}
2416
2417/**
2418 * ctk_popover_get_modal:
2419 * @popover: a #CtkPopover
2420 *
2421 * Returns whether the popover is modal, see ctk_popover_set_modal to
2422 * see the implications of this.
2423 *
2424 * Returns: #TRUE if @popover is modal
2425 *
2426 * Since: 3.12
2427 **/
2428gboolean
2429ctk_popover_get_modal (CtkPopover *popover)
2430{
2431 g_return_val_if_fail (CTK_IS_POPOVER (popover), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return ((0)); } } while (0)
;
2432
2433 return popover->priv->modal;
2434}
2435
2436/**
2437 * ctk_popover_set_transitions_enabled:
2438 * @popover: a #CtkPopover
2439 * @transitions_enabled: Whether transitions are enabled
2440 *
2441 * Sets whether show/hide transitions are enabled on this popover
2442 *
2443 * Since: 3.16
2444 *
2445 * Deprecated: 3.22: You can show or hide the popover without transitions
2446 * using ctk_widget_show() and ctk_widget_hide() while ctk_popover_popup()
2447 * and ctk_popover_popdown() will use transitions.
2448 */
2449void
2450ctk_popover_set_transitions_enabled (CtkPopover *popover,
2451 gboolean transitions_enabled)
2452{
2453 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2454
2455 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2456
2457 transitions_enabled = !!transitions_enabled;
2458
2459 if (priv->transitions_enabled == transitions_enabled)
2460 return;
2461
2462 priv->transitions_enabled = transitions_enabled;
2463 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_TRANSITIONS_ENABLED]);
2464}
2465
2466/**
2467 * ctk_popover_get_transitions_enabled:
2468 * @popover: a #CtkPopover
2469 *
2470 * Returns whether show/hide transitions are enabled on this popover.
2471 *
2472 * Returns: #TRUE if the show and hide transitions of the given
2473 * popover are enabled, #FALSE otherwise.
2474 *
2475 * Since: 3.16
2476 *
2477 * Deprecated: 3.22: You can show or hide the popover without transitions
2478 * using ctk_widget_show() and ctk_widget_hide() while ctk_popover_popup()
2479 * and ctk_popover_popdown() will use transitions.
2480 */
2481gboolean
2482ctk_popover_get_transitions_enabled (CtkPopover *popover)
2483{
2484 g_return_val_if_fail (CTK_IS_POPOVER (popover), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return ((0)); } } while (0)
;
2485
2486 return popover->priv->transitions_enabled;
2487}
2488
2489
2490static void
2491back_to_main (CtkWidget *popover)
2492{
2493 CtkWidget *stack;
2494
2495 stack = ctk_bin_get_child (CTK_BIN (popover)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_bin_get_type ()))))))
);
2496 ctk_stack_set_visible_child_name (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, "main");
2497}
2498
2499/**
2500 * ctk_popover_bind_model:
2501 * @popover: a #CtkPopover
2502 * @model: (allow-none): the #GMenuModel to bind to or %NULL to remove
2503 * binding
2504 * @action_namespace: (allow-none): the namespace for actions in @model
2505 *
2506 * Establishes a binding between a #CtkPopover and a #GMenuModel.
2507 *
2508 * The contents of @popover are removed and then refilled with menu items
2509 * according to @model. When @model changes, @popover is updated.
2510 * Calling this function twice on @popover with different @model will
2511 * cause the first binding to be replaced with a binding to the new
2512 * model. If @model is %NULL then any previous binding is undone and
2513 * all children are removed.
2514 *
2515 * If @action_namespace is non-%NULL then the effect is as if all
2516 * actions mentioned in the @model have their names prefixed with the
2517 * namespace, plus a dot. For example, if the action “quit” is
2518 * mentioned and @action_namespace is “app” then the effective action
2519 * name is “app.quit”.
2520 *
2521 * This function uses #CtkActionable to define the action name and
2522 * target values on the created menu items. If you want to use an
2523 * action group other than “app” and “win”, or if you want to use a
2524 * #CtkMenuShell outside of a #CtkApplicationWindow, then you will need
2525 * to attach your own action group to the widget hierarchy using
2526 * ctk_widget_insert_action_group(). As an example, if you created a
2527 * group with a “quit” action and inserted it with the name “mygroup”
2528 * then you would use the action name “mygroup.quit” in your
2529 * #GMenuModel.
2530 *
2531 * Since: 3.12
2532 */
2533void
2534ctk_popover_bind_model (CtkPopover *popover,
2535 GMenuModel *model,
2536 const gchar *action_namespace)
2537{
2538 CtkWidget *child;
2539 CtkWidget *stack;
2540 CtkStyleContext *style_context;
2541
2542 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2543 g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model))do { if ((model == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((model)); GType __t = ((g_menu_model_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__)), "model == NULL || G_IS_MENU_MODEL (model)"
); return; } } while (0)
;
2544
2545 child = ctk_bin_get_child (CTK_BIN (popover)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_bin_get_type ()))))))
);
2546 if (child)
2547 ctk_widget_destroy (child);
2548
2549 style_context = ctk_widget_get_style_context (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
2550
2551 if (model)
2552 {
2553 stack = ctk_stack_new ();
2554 ctk_stack_set_vhomogeneous (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, FALSE(0));
2555 ctk_stack_set_transition_type (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, CTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
2556 ctk_stack_set_interpolate_size (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, TRUE(!(0)));
2557 ctk_widget_show (stack);
2558 ctk_container_add (CTK_CONTAINER (popover)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_container_get_type ()))))))
, stack);
2559
2560 ctk_menu_section_box_new_toplevel (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
,
2561 model,
2562 action_namespace,
2563 popover);
2564 ctk_stack_set_visible_child_name (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stack)), ((ctk_stack_get_type ()))))))
, "main");
2565
2566 g_signal_connect (popover, "unmap", G_CALLBACK (back_to_main), NULL)g_signal_connect_data ((popover), ("unmap"), (((GCallback) (back_to_main
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
2567 g_signal_connect (popover, "map", G_CALLBACK (back_to_main), NULL)g_signal_connect_data ((popover), ("map"), (((GCallback) (back_to_main
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
2568
2569 ctk_style_context_add_class (style_context, CTK_STYLE_CLASS_MENU"menu");
2570 }
2571 else
2572 {
2573 ctk_style_context_remove_class (style_context, CTK_STYLE_CLASS_MENU"menu");
2574 }
2575}
2576
2577/**
2578 * ctk_popover_new_from_model:
2579 * @relative_to: (allow-none): #CtkWidget the popover is related to
2580 * @model: a #GMenuModel
2581 *
2582 * Creates a #CtkPopover and populates it according to
2583 * @model. The popover is pointed to the @relative_to widget.
2584 *
2585 * The created buttons are connected to actions found in the
2586 * #CtkApplicationWindow to which the popover belongs - typically
2587 * by means of being attached to a widget that is contained within
2588 * the #CtkApplicationWindows widget hierarchy.
2589 *
2590 * Actions can also be added using ctk_widget_insert_action_group()
2591 * on the menus attach widget or on any of its parent widgets.
2592 *
2593 * Returns: the new #CtkPopover
2594 *
2595 * Since: 3.12
2596 */
2597CtkWidget *
2598ctk_popover_new_from_model (CtkWidget *relative_to,
2599 GMenuModel *model)
2600{
2601 CtkWidget *popover;
2602
2603 g_return_val_if_fail (relative_to == NULL || CTK_IS_WIDGET (relative_to), NULL)do { if ((relative_to == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((relative_to)); 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__)), "relative_to == NULL || CTK_IS_WIDGET (relative_to)"
); return (((void*)0)); } } while (0)
;
2604 g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((g_menu_model_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__
)), "G_IS_MENU_MODEL (model)"); return (((void*)0)); } } while
(0)
;
2605
2606 popover = ctk_popover_new (relative_to);
2607 ctk_popover_bind_model (CTK_POPOVER (popover)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_popover_get_type ()))))))
, model, NULL((void*)0));
2608
2609 return popover;
2610}
2611
2612/**
2613 * ctk_popover_set_default_widget:
2614 * @popover: a #CtkPopover
2615 * @widget: (allow-none): the new default widget, or %NULL
2616 *
2617 * Sets the widget that should be set as default widget while
2618 * the popover is shown (see ctk_window_set_default()). #CtkPopover
2619 * remembers the previous default widget and reestablishes it
2620 * when the popover is dismissed.
2621 *
2622 * Since: 3.18
2623 */
2624void
2625ctk_popover_set_default_widget (CtkPopover *popover,
2626 CtkWidget *widget)
2627{
2628 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2629
2630 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2631 g_return_if_fail (widget == NULL || ctk_widget_get_can_default (widget))do { if ((widget == ((void*)0) || ctk_widget_get_can_default (
widget))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "widget == NULL || ctk_widget_get_can_default (widget)"
); return; } } while (0)
;
2632
2633 if (priv->default_widget == widget)
2634 return;
2635
2636 if (priv->default_widget)
2637 g_object_unref (priv->default_widget);
2638
2639 priv->default_widget = widget;
2640
2641 if (priv->default_widget)
2642 g_object_ref (priv->default_widget)((__typeof__ (priv->default_widget)) (g_object_ref) (priv->
default_widget))
;
2643
2644 if (ctk_widget_get_mapped (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
))
2645 ctk_window_set_default (priv->window, priv->default_widget);
2646}
2647
2648/**
2649 * ctk_popover_get_default_widget:
2650 * @popover: a #CtkPopover
2651 *
2652 * Gets the widget that should be set as the default while
2653 * the popover is shown.
2654 *
2655 * Returns: (nullable) (transfer none): the default widget,
2656 * or %NULL if there is none
2657 *
2658 * Since: 3.18
2659 */
2660CtkWidget *
2661ctk_popover_get_default_widget (CtkPopover *popover)
2662{
2663 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2664
2665 g_return_val_if_fail (CTK_IS_POPOVER (popover), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return (((void*)0)); } } while
(0)
;
2666
2667 return priv->default_widget;
2668}
2669
2670/**
2671 * ctk_popover_set_constrain_to:
2672 * @popover: a #CtkPopover
2673 * @constraint: the new constraint
2674 *
2675 * Sets a constraint for positioning this popover.
2676 *
2677 * Note that not all platforms support placing popovers freely,
2678 * and may already impose constraints.
2679 *
2680 * Since: 3.20
2681 */
2682void
2683ctk_popover_set_constrain_to (CtkPopover *popover,
2684 CtkPopoverConstraint constraint)
2685{
2686 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2687
2688 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2689
2690 if (priv->constraint == constraint)
2691 return;
2692
2693 priv->constraint = constraint;
2694 ctk_popover_update_position (popover);
2695
2696 g_object_notify_by_pspec (G_OBJECT (popover)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), (((GType) ((20) << (2))))))))
, properties[PROP_CONSTRAIN_TO]);
2697}
2698
2699/**
2700 * ctk_popover_get_constrain_to:
2701 * @popover: a #CtkPopover
2702 *
2703 * Returns the constraint for placing this popover.
2704 * See ctk_popover_set_constrain_to().
2705 *
2706 * Returns: the constraint for placing this popover.
2707 *
2708 * Since: 3.20
2709 */
2710CtkPopoverConstraint
2711ctk_popover_get_constrain_to (CtkPopover *popover)
2712{
2713 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2714
2715 g_return_val_if_fail (CTK_IS_POPOVER (popover), CTK_POPOVER_CONSTRAINT_WINDOW)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return (CTK_POPOVER_CONSTRAINT_WINDOW
); } } while (0)
;
2716
2717 return priv->constraint;
2718}
2719
2720/**
2721 * ctk_popover_popup:
2722 * @popover: a #CtkPopover
2723 *
2724 * Pops @popover up. This is different than a ctk_widget_show() call
2725 * in that it shows the popover with a transition. If you want to show
2726 * the popover without a transition, use ctk_widget_show().
2727 *
2728 * Since: 3.22
2729 */
2730void
2731ctk_popover_popup (CtkPopover *popover)
2732{
2733 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2734
2735 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2736
2737 if (priv->state == STATE_SHOWING ||
2738 priv->state == STATE_SHOWN)
2739 return;
2740
2741 ctk_widget_show (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
2742
2743 if (transitions_enabled (popover))
2744 ctk_popover_set_state (popover, STATE_SHOWING);
2745}
2746
2747/**
2748 * ctk_popover_popdown:
2749 * @popover: a #CtkPopover
2750 *
2751 * Pops @popover down.This is different than a ctk_widget_hide() call
2752 * in that it shows the popover with a transition. If you want to hide
2753 * the popover without a transition, use ctk_widget_hide().
2754 *
2755 * Since: 3.22
2756 */
2757void
2758ctk_popover_popdown (CtkPopover *popover)
2759{
2760 CtkPopoverPrivate *priv = ctk_popover_get_instance_private (popover);
2761
2762 g_return_if_fail (CTK_IS_POPOVER (popover))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((popover)); GType __t = ((ctk_popover_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_POPOVER (popover)"); return; } } while (0)
;
2763
2764 if (priv->state == STATE_HIDING ||
2765 priv->state == STATE_HIDDEN)
2766 return;
2767
2768
2769 if (!transitions_enabled (popover))
2770 ctk_widget_hide (CTK_WIDGET (popover)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((popover)), ((ctk_widget_get_type ()))))))
);
2771 else
2772 ctk_popover_set_state (popover, STATE_HIDING);
2773
2774 ctk_popover_hide_internal (popover);
2775}