File: | ctk/ctkactionhelper.c |
Warning: | line 253, column 45 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright © 2012 Canonical Limited |
3 | * |
4 | * This library is free software: you can redistribute it and/or modify |
5 | * it under the terms of the GNU Lesser General Public License as |
6 | * published by the Free Software Foundation; either version 2 of the |
7 | * licence or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, but |
10 | * 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 | * Authors: Ryan Lortie <desrt@desrt.ca> |
18 | */ |
19 | |
20 | #include "ctkactionhelper.h" |
21 | #include "ctkactionobservable.h" |
22 | |
23 | #include "ctkwidget.h" |
24 | #include "ctkwidgetprivate.h" |
25 | #include "ctkdebug.h" |
26 | #include "ctkmodelbutton.h" |
27 | #include "ctktypebuiltins.h" |
28 | |
29 | #include <string.h> |
30 | |
31 | typedef struct |
32 | { |
33 | GActionGroup *group; |
34 | |
35 | GHashTable *watchers; |
36 | } CtkActionHelperGroup; |
37 | |
38 | static void ctk_action_helper_action_added (CtkActionHelper *helper, |
39 | gboolean enabled, |
40 | const GVariantType *parameter_type, |
41 | GVariant *state, |
42 | gboolean should_emit_signals); |
43 | |
44 | static void ctk_action_helper_action_removed (CtkActionHelper *helper, |
45 | gboolean should_emit_signals); |
46 | |
47 | static void ctk_action_helper_action_enabled_changed (CtkActionHelper *helper, |
48 | gboolean enabled); |
49 | |
50 | static void ctk_action_helper_action_state_changed (CtkActionHelper *helper, |
51 | GVariant *new_state); |
52 | |
53 | typedef GObjectClass CtkActionHelperClass; |
54 | |
55 | struct _CtkActionHelper |
56 | { |
57 | GObject parent_instance; |
58 | |
59 | CtkWidget *widget; |
60 | |
61 | CtkActionHelperGroup *group; |
62 | |
63 | CtkActionMuxer *action_context; |
64 | gchar *action_name; |
65 | |
66 | GVariant *target; |
67 | |
68 | gboolean can_activate; |
69 | gboolean enabled; |
70 | gboolean active; |
71 | |
72 | CtkButtonRole role; |
73 | |
74 | gint reporting; |
75 | }; |
76 | |
77 | enum |
78 | { |
79 | PROP_0, |
80 | PROP_ENABLED, |
81 | PROP_ACTIVE, |
82 | PROP_ROLE, |
83 | N_PROPS |
84 | }; |
85 | |
86 | static GParamSpec *ctk_action_helper_pspecs[N_PROPS]; |
87 | |
88 | static void ctk_action_helper_observer_iface_init (CtkActionObserverInterface *iface); |
89 | |
90 | G_DEFINE_TYPE_WITH_CODE (CtkActionHelper, ctk_action_helper, G_TYPE_OBJECT,static void ctk_action_helper_init (CtkActionHelper *self); static void ctk_action_helper_class_init (CtkActionHelperClass *klass ); static GType ctk_action_helper_get_type_once (void); static gpointer ctk_action_helper_parent_class = ((void*)0); static gint CtkActionHelper_private_offset; static void ctk_action_helper_class_intern_init (gpointer klass) { ctk_action_helper_parent_class = g_type_class_peek_parent (klass); if (CtkActionHelper_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkActionHelper_private_offset); ctk_action_helper_class_init ((CtkActionHelperClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer ctk_action_helper_get_instance_private (CtkActionHelper *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CtkActionHelper_private_offset)))); } GType ctk_action_helper_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_action_helper_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_action_helper_get_type_once ( void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CtkActionHelper" ), sizeof (CtkActionHelperClass), (GClassInitFunc)(void (*)(void )) ctk_action_helper_class_intern_init, sizeof (CtkActionHelper ), (GInstanceInitFunc)(void (*)(void)) ctk_action_helper_init , (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc)(void (*)(void)) ctk_action_helper_observer_iface_init , ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id , (ctk_action_observer_get_type ()), &g_implement_interface_info ); };} } return g_define_type_id; } |
91 | G_IMPLEMENT_INTERFACE (CTK_TYPE_ACTION_OBSERVER, ctk_action_helper_observer_iface_init))static void ctk_action_helper_init (CtkActionHelper *self); static void ctk_action_helper_class_init (CtkActionHelperClass *klass ); static GType ctk_action_helper_get_type_once (void); static gpointer ctk_action_helper_parent_class = ((void*)0); static gint CtkActionHelper_private_offset; static void ctk_action_helper_class_intern_init (gpointer klass) { ctk_action_helper_parent_class = g_type_class_peek_parent (klass); if (CtkActionHelper_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkActionHelper_private_offset); ctk_action_helper_class_init ((CtkActionHelperClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer ctk_action_helper_get_instance_private (CtkActionHelper *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CtkActionHelper_private_offset)))); } GType ctk_action_helper_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_action_helper_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_action_helper_get_type_once ( void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CtkActionHelper" ), sizeof (CtkActionHelperClass), (GClassInitFunc)(void (*)(void )) ctk_action_helper_class_intern_init, sizeof (CtkActionHelper ), (GInstanceInitFunc)(void (*)(void)) ctk_action_helper_init , (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc)(void (*)(void)) ctk_action_helper_observer_iface_init , ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id , (ctk_action_observer_get_type ()), &g_implement_interface_info ); };} } return g_define_type_id; } |
92 | |
93 | static void |
94 | ctk_action_helper_report_change (CtkActionHelper *helper, |
95 | guint prop_id) |
96 | { |
97 | helper->reporting++; |
98 | |
99 | switch (prop_id) |
100 | { |
101 | case PROP_ENABLED: |
102 | ctk_widget_set_sensitive (CTK_WIDGET (helper->widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), ((ctk_widget_get_type ())))))), helper->enabled); |
103 | break; |
104 | |
105 | case PROP_ACTIVE: |
106 | { |
107 | GParamSpec *pspec; |
108 | |
109 | pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (helper->widget)((((GObjectClass*) (((GTypeInstance*) ((helper->widget)))-> g_class)))), "active"); |
110 | |
111 | if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((pspec)), (((GType) ((19) << (2))))))))->value_type ) == G_TYPE_BOOLEAN((GType) ((5) << (2)))) |
112 | g_object_set (G_OBJECT (helper->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), (((GType) ((20) << (2)))))))), "active", helper->active, NULL((void*)0)); |
113 | } |
114 | break; |
115 | |
116 | case PROP_ROLE: |
117 | { |
118 | GParamSpec *pspec; |
119 | |
120 | pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (helper->widget)((((GObjectClass*) (((GTypeInstance*) ((helper->widget)))-> g_class)))), "role"); |
121 | |
122 | if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((pspec)), (((GType) ((19) << (2))))))))->value_type ) == CTK_TYPE_BUTTON_ROLE(ctk_button_role_get_type ())) |
123 | g_object_set (G_OBJECT (helper->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), (((GType) ((20) << (2)))))))), "role", helper->role, NULL((void*)0)); |
124 | } |
125 | break; |
126 | |
127 | default: |
128 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkactionhelper.c", 128 , ((const char*) (__func__)), ((void*)0)); } while (0); |
129 | } |
130 | |
131 | g_object_notify_by_pspec (G_OBJECT (helper)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper)), (((GType) ((20) << (2)))))))), ctk_action_helper_pspecs[prop_id]); |
132 | helper->reporting--; |
133 | } |
134 | |
135 | static void |
136 | ctk_action_helper_action_added (CtkActionHelper *helper, |
137 | gboolean enabled, |
138 | const GVariantType *parameter_type, |
139 | GVariant *state, |
140 | gboolean should_emit_signals) |
141 | { |
142 | CTK_NOTE(ACTIONS, g_message("%s: action %s added", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s added", "actionhelper", helper->action_name ); }; } while (0); |
143 | |
144 | /* we can only activate if we have the correct type of parameter */ |
145 | helper->can_activate = (helper->target == NULL((void*)0) && parameter_type == NULL((void*)0)) || |
146 | (helper->target != NULL((void*)0) && parameter_type != NULL((void*)0) && |
147 | g_variant_is_of_type (helper->target, parameter_type)); |
148 | |
149 | if (!helper->can_activate) |
150 | { |
151 | g_warning ("%s: action %s can't be activated due to parameter type mismatch " |
152 | "(parameter type %s, target type %s)", |
153 | "actionhelper", |
154 | helper->action_name, |
155 | parameter_type ? g_variant_type_peek_string (parameter_type) : "NULL", |
156 | helper->target ? g_variant_get_type_string (helper->target) : "NULL"); |
157 | return; |
158 | } |
159 | |
160 | CTK_NOTE(ACTIONS, g_message ("%s: %s can be activated", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: %s can be activated", "actionhelper", helper->action_name ); }; } while (0); |
161 | |
162 | helper->enabled = enabled; |
163 | |
164 | CTK_NOTE(ACTIONS, g_message ("%s: action %s is %s", "actionhelper", helper->action_name, enabled ? "enabled" : "disabled"))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s is %s", "actionhelper", helper->action_name , enabled ? "enabled" : "disabled"); }; } while (0); |
165 | |
166 | if (helper->target != NULL((void*)0) && state != NULL((void*)0)) |
167 | { |
168 | helper->active = g_variant_equal (state, helper->target); |
169 | helper->role = CTK_BUTTON_ROLE_RADIO; |
170 | } |
171 | else if (state != NULL((void*)0) && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN((const GVariantType *) "b"))) |
172 | { |
173 | helper->active = g_variant_get_boolean (state); |
174 | helper->role = CTK_BUTTON_ROLE_CHECK; |
175 | } |
176 | else |
177 | { |
178 | helper->role = CTK_BUTTON_ROLE_NORMAL; |
179 | } |
180 | |
181 | if (should_emit_signals) |
182 | { |
183 | if (helper->enabled) |
184 | ctk_action_helper_report_change (helper, PROP_ENABLED); |
185 | |
186 | if (helper->active) |
187 | ctk_action_helper_report_change (helper, PROP_ACTIVE); |
188 | |
189 | ctk_action_helper_report_change (helper, PROP_ROLE); |
190 | } |
191 | } |
192 | |
193 | static void |
194 | ctk_action_helper_action_removed (CtkActionHelper *helper, |
195 | gboolean should_emit_signals) |
196 | { |
197 | CTK_NOTE(ACTIONS, g_message ("%s: action %s was removed", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s was removed", "actionhelper", helper->action_name ); }; } while (0); |
198 | |
199 | if (!helper->can_activate) |
200 | return; |
201 | |
202 | helper->can_activate = FALSE(0); |
203 | |
204 | if (helper->enabled) |
205 | { |
206 | helper->enabled = FALSE(0); |
207 | |
208 | if (should_emit_signals) |
209 | ctk_action_helper_report_change (helper, PROP_ENABLED); |
210 | } |
211 | |
212 | if (helper->active) |
213 | { |
214 | helper->active = FALSE(0); |
215 | |
216 | if (should_emit_signals) |
217 | ctk_action_helper_report_change (helper, PROP_ACTIVE); |
218 | } |
219 | } |
220 | |
221 | static void |
222 | ctk_action_helper_action_enabled_changed (CtkActionHelper *helper, |
223 | gboolean enabled) |
224 | { |
225 | CTK_NOTE(ACTIONS, g_message ("%s: action %s: enabled changed to %d", "actionhelper", helper->action_name, enabled))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s: enabled changed to %d", "actionhelper", helper ->action_name, enabled); }; } while (0); |
226 | |
227 | if (!helper->can_activate) |
228 | return; |
229 | |
230 | if (helper->enabled == enabled) |
231 | return; |
232 | |
233 | helper->enabled = enabled; |
234 | ctk_action_helper_report_change (helper, PROP_ENABLED); |
235 | } |
236 | |
237 | static void |
238 | ctk_action_helper_action_state_changed (CtkActionHelper *helper, |
239 | GVariant *new_state) |
240 | { |
241 | gboolean was_active; |
242 | |
243 | CTK_NOTE(ACTIONS, g_message ("%s: %s state changed", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: %s state changed", "actionhelper", helper->action_name ); }; } while (0); |
244 | |
245 | if (!helper->can_activate) |
246 | return; |
247 | |
248 | was_active = helper->active; |
249 | |
250 | if (helper->target) |
251 | helper->active = g_variant_equal (new_state, helper->target); |
252 | |
253 | else if (g_variant_is_of_type (new_state, G_VARIANT_TYPE_BOOLEAN((const GVariantType *) "b"))) |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
254 | helper->active = g_variant_get_boolean (new_state); |
255 | |
256 | else |
257 | helper->active = FALSE(0); |
258 | |
259 | if (helper->active != was_active) |
260 | ctk_action_helper_report_change (helper, PROP_ACTIVE); |
261 | } |
262 | |
263 | static void |
264 | ctk_action_helper_get_property (GObject *object, |
265 | guint prop_id, |
266 | GValue *value, |
267 | GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__))) |
268 | { |
269 | CtkActionHelper *helper = CTK_ACTION_HELPER (object)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_action_helper_get_type ())))))); |
270 | |
271 | switch (prop_id) |
272 | { |
273 | case PROP_ENABLED: |
274 | g_value_set_boolean (value, helper->enabled); |
275 | break; |
276 | |
277 | case PROP_ACTIVE: |
278 | g_value_set_boolean (value, helper->active); |
279 | break; |
280 | |
281 | case PROP_ROLE: |
282 | g_value_set_enum (value, helper->role); |
283 | break; |
284 | |
285 | default: |
286 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkactionhelper.c", 286 , ((const char*) (__func__)), ((void*)0)); } while (0); |
287 | } |
288 | } |
289 | |
290 | static void |
291 | ctk_action_helper_finalize (GObject *object) |
292 | { |
293 | CtkActionHelper *helper = CTK_ACTION_HELPER (object)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_action_helper_get_type ())))))); |
294 | |
295 | g_free (helper->action_name); |
296 | |
297 | if (helper->target) |
298 | g_variant_unref (helper->target); |
299 | |
300 | G_OBJECT_CLASS (ctk_action_helper_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_action_helper_parent_class)), (((GType) ((20) << (2)))))))) |
301 | ->finalize (object); |
302 | } |
303 | |
304 | static void |
305 | ctk_action_helper_observer_action_added (CtkActionObserver *observer, |
306 | CtkActionObservable *observable G_GNUC_UNUSED__attribute__ ((__unused__)), |
307 | const gchar *action_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
308 | const GVariantType *parameter_type, |
309 | gboolean enabled, |
310 | GVariant *state) |
311 | { |
312 | ctk_action_helper_action_added (CTK_ACTION_HELPER (observer)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((observer)), ((ctk_action_helper_get_type ())))))), enabled, parameter_type, state, TRUE(!(0))); |
313 | } |
314 | |
315 | static void |
316 | ctk_action_helper_observer_action_enabled_changed (CtkActionObserver *observer, |
317 | CtkActionObservable *observable G_GNUC_UNUSED__attribute__ ((__unused__)), |
318 | const gchar *action_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
319 | gboolean enabled) |
320 | { |
321 | ctk_action_helper_action_enabled_changed (CTK_ACTION_HELPER (observer)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((observer)), ((ctk_action_helper_get_type ())))))), enabled); |
322 | } |
323 | |
324 | static void |
325 | ctk_action_helper_observer_action_state_changed (CtkActionObserver *observer, |
326 | CtkActionObservable *observable G_GNUC_UNUSED__attribute__ ((__unused__)), |
327 | const gchar *action_name G_GNUC_UNUSED__attribute__ ((__unused__)), |
328 | GVariant *state) |
329 | { |
330 | ctk_action_helper_action_state_changed (CTK_ACTION_HELPER (observer)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((observer)), ((ctk_action_helper_get_type ())))))), state); |
331 | } |
332 | |
333 | static void |
334 | ctk_action_helper_observer_action_removed (CtkActionObserver *observer, |
335 | CtkActionObservable *observable G_GNUC_UNUSED__attribute__ ((__unused__)), |
336 | const gchar *action_name G_GNUC_UNUSED__attribute__ ((__unused__))) |
337 | { |
338 | ctk_action_helper_action_removed (CTK_ACTION_HELPER (observer)((((CtkActionHelper*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((observer)), ((ctk_action_helper_get_type ())))))), TRUE(!(0))); |
339 | } |
340 | |
341 | static void |
342 | ctk_action_helper_init (CtkActionHelper *helper G_GNUC_UNUSED__attribute__ ((__unused__))) |
343 | { |
344 | } |
345 | |
346 | static void |
347 | ctk_action_helper_class_init (CtkActionHelperClass *class) |
348 | { |
349 | class->get_property = ctk_action_helper_get_property; |
350 | class->finalize = ctk_action_helper_finalize; |
351 | |
352 | ctk_action_helper_pspecs[PROP_ENABLED] = g_param_spec_boolean ("enabled", "enabled", "enabled", FALSE(0), |
353 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); |
354 | ctk_action_helper_pspecs[PROP_ACTIVE] = g_param_spec_boolean ("active", "active", "active", FALSE(0), |
355 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); |
356 | ctk_action_helper_pspecs[PROP_ROLE] = g_param_spec_enum ("role", "role", "role", |
357 | CTK_TYPE_BUTTON_ROLE(ctk_button_role_get_type ()), |
358 | CTK_BUTTON_ROLE_NORMAL, |
359 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); |
360 | g_object_class_install_properties (class, N_PROPS, ctk_action_helper_pspecs); |
361 | } |
362 | |
363 | static void |
364 | ctk_action_helper_observer_iface_init (CtkActionObserverInterface *iface) |
365 | { |
366 | iface->action_added = ctk_action_helper_observer_action_added; |
367 | iface->action_enabled_changed = ctk_action_helper_observer_action_enabled_changed; |
368 | iface->action_state_changed = ctk_action_helper_observer_action_state_changed; |
369 | iface->action_removed = ctk_action_helper_observer_action_removed; |
370 | } |
371 | |
372 | /*< private > |
373 | * ctk_action_helper_new: |
374 | * @widget: a #CtkWidget implementing #CtkActionable |
375 | * |
376 | * Creates a helper to track the state of a named action. This will |
377 | * usually be used by widgets implementing #CtkActionable. |
378 | * |
379 | * This helper class is usually used by @widget itself. In order to |
380 | * avoid reference cycles, the helper does not hold a reference on |
381 | * @widget, but will assume that it continues to exist for the duration |
382 | * of the life of the helper. If you are using the helper from outside |
383 | * of the widget, you should take a ref on @widget for each ref you hold |
384 | * on the helper. |
385 | * |
386 | * Returns: a new #CtkActionHelper |
387 | */ |
388 | CtkActionHelper * |
389 | ctk_action_helper_new (CtkActionable *widget) |
390 | { |
391 | CtkActionHelper *helper; |
392 | GParamSpec *pspec; |
393 | |
394 | g_return_val_if_fail (CTK_IS_ACTIONABLE (widget), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((widget)); GType __t = ((ctk_actionable_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_ACTIONABLE (widget)"); return (((void*)0)); } } while (0); |
395 | helper = g_object_new (CTK_TYPE_ACTION_HELPER(ctk_action_helper_get_type ()), NULL((void*)0)); |
396 | |
397 | helper->widget = CTK_WIDGET (widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_widget_get_type ())))))); |
398 | helper->enabled = ctk_widget_get_sensitive (CTK_WIDGET (helper->widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), ((ctk_widget_get_type ()))))))); |
399 | |
400 | pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (helper->widget)((((GObjectClass*) (((GTypeInstance*) ((helper->widget)))-> g_class)))), "active"); |
401 | if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((pspec)), (((GType) ((19) << (2))))))))->value_type ) == G_TYPE_BOOLEAN((GType) ((5) << (2)))) |
402 | g_object_get (G_OBJECT (helper->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), (((GType) ((20) << (2)))))))), "active", &helper->active, NULL((void*)0)); |
403 | |
404 | helper->action_context = _ctk_widget_get_action_muxer (CTK_WIDGET (widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_widget_get_type ())))))), TRUE(!(0))); |
405 | |
406 | return helper; |
407 | } |
408 | |
409 | void |
410 | ctk_action_helper_set_action_name (CtkActionHelper *helper, |
411 | const gchar *action_name) |
412 | { |
413 | gboolean was_enabled, was_active; |
414 | const GVariantType *parameter_type; |
415 | gboolean enabled; |
416 | GVariant *state; |
417 | |
418 | if (g_strcmp0 (action_name, helper->action_name) == 0) |
419 | return; |
420 | |
421 | CTK_NOTE(ACTIONS,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { if (action_name == ((void*)0) || !strchr (action_name, '.')) g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; " "it is unlikely to work" , "actionhelper", action_name); }; } while (0) |
422 | if (action_name == NULL || !strchr (action_name, '.'))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { if (action_name == ((void*)0) || !strchr (action_name, '.')) g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; " "it is unlikely to work" , "actionhelper", action_name); }; } while (0) |
423 | g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; "do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { if (action_name == ((void*)0) || !strchr (action_name, '.')) g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; " "it is unlikely to work" , "actionhelper", action_name); }; } while (0) |
424 | "it is unlikely to work",do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { if (action_name == ((void*)0) || !strchr (action_name, '.')) g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; " "it is unlikely to work" , "actionhelper", action_name); }; } while (0) |
425 | "actionhelper", action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { if (action_name == ((void*)0) || !strchr (action_name, '.')) g_message ("%s: action name %s doesn't look like 'app.' or 'win.'; " "it is unlikely to work" , "actionhelper", action_name); }; } while (0); |
426 | |
427 | /* Start by recording the current state of our properties so we know |
428 | * what notify signals we will need to send. |
429 | */ |
430 | was_enabled = helper->enabled; |
431 | was_active = helper->active; |
432 | |
433 | if (helper->action_name) |
434 | { |
435 | ctk_action_helper_action_removed (helper, FALSE(0)); |
436 | ctk_action_observable_unregister_observer (CTK_ACTION_OBSERVABLE (helper->action_context)((((CtkActionObservable*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((helper->action_context)), ((ctk_action_observable_get_type ())))))), |
437 | helper->action_name, |
438 | CTK_ACTION_OBSERVER (helper)((((CtkActionObserver*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((helper)), ((ctk_action_observer_get_type ( )))))))); |
439 | g_clear_pointer (&helper->action_name, g_free)do { _Static_assert (sizeof *(&helper->action_name) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((&helper->action_name)) _pp = (&helper->action_name ); __typeof__ (*(&helper->action_name)) _ptr = *_pp; * _pp = ((void*)0); if (_ptr) (g_free) (_ptr); } while (0); |
440 | } |
441 | |
442 | if (action_name) |
443 | { |
444 | helper->action_name = g_strdup (action_name)g_strdup_inline (action_name); |
445 | |
446 | ctk_action_observable_register_observer (CTK_ACTION_OBSERVABLE (helper->action_context)((((CtkActionObservable*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((helper->action_context)), ((ctk_action_observable_get_type ())))))), |
447 | helper->action_name, |
448 | CTK_ACTION_OBSERVER (helper)((((CtkActionObserver*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((helper)), ((ctk_action_observer_get_type ( )))))))); |
449 | |
450 | if (g_action_group_query_action (G_ACTION_GROUP (helper->action_context)((((GActionGroup*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->action_context)), ((g_action_group_get_type ( ))))))), helper->action_name, |
451 | &enabled, ¶meter_type, NULL((void*)0), NULL((void*)0), &state)) |
452 | { |
453 | CTK_NOTE(ACTIONS, g_message ("%s: action %s existed from the start", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s existed from the start", "actionhelper", helper ->action_name); }; } while (0); |
454 | |
455 | ctk_action_helper_action_added (helper, enabled, parameter_type, state, FALSE(0)); |
456 | |
457 | if (state) |
458 | g_variant_unref (state); |
459 | } |
460 | else |
461 | { |
462 | CTK_NOTE(ACTIONS, g_message ("%s: action %s missing from the start", "actionhelper", helper->action_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ACTIONS)) { g_message ("%s: action %s missing from the start", "actionhelper", helper ->action_name); }; } while (0); |
463 | helper->enabled = FALSE(0); |
464 | } |
465 | } |
466 | |
467 | /* Send the notifies for the properties that changed. |
468 | * |
469 | * When called during construction, widget is NULL. We don't need to |
470 | * report in that case. |
471 | */ |
472 | if (helper->enabled != was_enabled) |
473 | ctk_action_helper_report_change (helper, PROP_ENABLED); |
474 | |
475 | if (helper->active != was_active) |
476 | ctk_action_helper_report_change (helper, PROP_ACTIVE); |
477 | |
478 | g_object_notify (G_OBJECT (helper->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), (((GType) ((20) << (2)))))))), "action-name"); |
479 | } |
480 | |
481 | /*< private > |
482 | * ctk_action_helper_set_action_target_value: |
483 | * @helper: a #CtkActionHelper |
484 | * @target_value: an action target, as per #CtkActionable |
485 | * |
486 | * This function consumes @action_target if it is floating. |
487 | */ |
488 | void |
489 | ctk_action_helper_set_action_target_value (CtkActionHelper *helper, |
490 | GVariant *target_value) |
491 | { |
492 | gboolean was_enabled; |
493 | gboolean was_active; |
494 | |
495 | if (target_value == helper->target) |
496 | return; |
497 | |
498 | if (target_value && helper->target && g_variant_equal (target_value, helper->target)) |
499 | { |
500 | g_variant_unref (g_variant_ref_sink (target_value)); |
501 | return; |
502 | } |
503 | |
504 | if (helper->target) |
505 | { |
506 | g_variant_unref (helper->target); |
507 | helper->target = NULL((void*)0); |
508 | } |
509 | |
510 | if (target_value) |
511 | helper->target = g_variant_ref_sink (target_value); |
512 | |
513 | /* The action_name has not yet been set. Don't do anything yet. */ |
514 | if (helper->action_name == NULL((void*)0)) |
515 | return; |
516 | |
517 | was_enabled = helper->enabled; |
518 | was_active = helper->active; |
519 | |
520 | /* If we are attached to an action group then it is possible that this |
521 | * change of the target value could impact our properties (including |
522 | * changes to 'can_activate' and therefore 'enabled', due to resolving |
523 | * a parameter type mismatch). |
524 | * |
525 | * Start over again by pretending the action gets re-added. |
526 | */ |
527 | helper->can_activate = FALSE(0); |
528 | helper->enabled = FALSE(0); |
529 | helper->active = FALSE(0); |
530 | |
531 | if (helper->action_context) |
532 | { |
533 | const GVariantType *parameter_type; |
534 | gboolean enabled; |
535 | GVariant *state; |
536 | |
537 | if (g_action_group_query_action (G_ACTION_GROUP (helper->action_context)((((GActionGroup*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->action_context)), ((g_action_group_get_type ( ))))))), |
538 | helper->action_name, &enabled, ¶meter_type, |
539 | NULL((void*)0), NULL((void*)0), &state)) |
540 | { |
541 | ctk_action_helper_action_added (helper, enabled, parameter_type, state, FALSE(0)); |
542 | |
543 | if (state) |
544 | g_variant_unref (state); |
545 | } |
546 | } |
547 | |
548 | if (helper->enabled != was_enabled) |
549 | ctk_action_helper_report_change (helper, PROP_ENABLED); |
550 | |
551 | if (helper->active != was_active) |
552 | ctk_action_helper_report_change (helper, PROP_ACTIVE); |
553 | |
554 | g_object_notify (G_OBJECT (helper->widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->widget)), (((GType) ((20) << (2)))))))), "action-target"); |
555 | } |
556 | |
557 | const gchar * |
558 | ctk_action_helper_get_action_name (CtkActionHelper *helper) |
559 | { |
560 | if (helper == NULL((void*)0)) |
561 | return NULL((void*)0); |
562 | |
563 | return helper->action_name; |
564 | } |
565 | |
566 | GVariant * |
567 | ctk_action_helper_get_action_target_value (CtkActionHelper *helper) |
568 | { |
569 | if (helper == NULL((void*)0)) |
570 | return NULL((void*)0); |
571 | |
572 | return helper->target; |
573 | } |
574 | |
575 | gboolean |
576 | ctk_action_helper_get_enabled (CtkActionHelper *helper) |
577 | { |
578 | g_return_val_if_fail (CTK_IS_ACTION_HELPER (helper), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((helper)); GType __t = ((ctk_action_helper_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_ACTION_HELPER (helper)"); return ((0) ); } } while (0); |
579 | |
580 | return helper->enabled; |
581 | } |
582 | |
583 | gboolean |
584 | ctk_action_helper_get_active (CtkActionHelper *helper) |
585 | { |
586 | g_return_val_if_fail (CTK_IS_ACTION_HELPER (helper), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((helper)); GType __t = ((ctk_action_helper_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_ACTION_HELPER (helper)"); return ((0) ); } } while (0); |
587 | |
588 | return helper->active; |
589 | } |
590 | |
591 | void |
592 | ctk_action_helper_activate (CtkActionHelper *helper) |
593 | { |
594 | g_return_if_fail (CTK_IS_ACTION_HELPER (helper))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((helper)); GType __t = ((ctk_action_helper_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_ACTION_HELPER (helper)"); return; } } while (0); |
595 | |
596 | if (!helper->can_activate || helper->reporting) |
597 | return; |
598 | |
599 | g_action_group_activate_action (G_ACTION_GROUP (helper->action_context)((((GActionGroup*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((helper->action_context)), ((g_action_group_get_type ( ))))))), |
600 | helper->action_name, helper->target); |
601 | } |