]> Pileus Git - ~andy/gtk/blob - gtk/gsimpleactionobserver.c
Require XInput2.h in X11 backend
[~andy/gtk] / gtk / gsimpleactionobserver.c
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 "config.h"
21
22 #include "gsimpleactionobserver.h"
23 #include "gactionobservable.h"
24
25 typedef GObjectClass GSimpleActionObserverClass;
26 struct _GSimpleActionObserver
27 {
28   GObject parent_instance;
29
30   GActionGroup *action_group;
31   gchar *action_name;
32   GVariant *target;
33
34   gboolean can_activate;
35   gboolean active;
36   gboolean enabled;
37
38   gint reporting;
39 };
40
41 static void g_simple_action_observer_init_iface (GActionObserverInterface *iface);
42 G_DEFINE_TYPE_WITH_CODE (GSimpleActionObserver, g_simple_action_observer, G_TYPE_OBJECT,
43                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVER, g_simple_action_observer_init_iface));
44
45 enum
46 {
47   PROP_0,
48   PROP_ACTIVE,
49   PROP_ENABLED,
50   N_PROPS
51 };
52
53 static GParamSpec *g_simple_action_observer_pspecs[N_PROPS];
54
55 static void
56 g_simple_action_observer_action_added (GActionObserver    *g_observer,
57                                        GActionObservable  *observable,
58                                        const gchar        *action_name,
59                                        const GVariantType *parameter_type,
60                                        gboolean            enabled,
61                                        GVariant           *state)
62 {
63   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
64   gboolean active;
65
66   /* we can only activate if we have the correct type of parameter */
67   observer->can_activate = (observer->target == NULL && parameter_type == NULL) ||
68                             (observer->target != NULL && parameter_type != NULL &&
69                              g_variant_is_of_type (observer->target, parameter_type));
70
71   if (observer->can_activate)
72     {
73       if (observer->target != NULL && state != NULL)
74         active = g_variant_equal (state, observer->target);
75
76       else if (state != NULL && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
77         active = g_variant_get_boolean (state);
78
79       else
80         active = FALSE;
81
82       if (active != observer->active)
83         {
84           observer->active = active;
85           observer->reporting++;
86           g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
87           observer->reporting--;
88         }
89
90       if (enabled != observer->enabled)
91         {
92           observer->enabled = enabled;
93           g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
94         }
95     }
96 }
97
98 static void
99 g_simple_action_observer_action_enabled_changed (GActionObserver   *g_observer,
100                                                  GActionObservable *observable,
101                                                  const gchar       *action_name,
102                                                  gboolean           enabled)
103 {
104   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
105
106   if (!observer->can_activate)
107     return;
108
109   if (enabled != observer->enabled)
110     {
111       observer->enabled = enabled;
112       g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
113     }
114 }
115
116 static void
117 g_simple_action_observer_action_state_changed (GActionObserver   *g_observer,
118                                                GActionObservable *observable,
119                                                const gchar       *action_name,
120                                                GVariant          *state)
121 {
122   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
123   gboolean active = FALSE;
124
125   if (!observer->can_activate)
126     return;
127
128   if (observer->target)
129     active = g_variant_equal (state, observer->target);
130
131   else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
132     active = g_variant_get_boolean (state);
133
134   if (active != observer->active)
135     {
136       observer->active = active;
137       observer->reporting++;
138       g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
139       observer->reporting--;
140     }
141 }
142
143 static void
144 g_simple_action_observer_action_removed (GActionObserver   *g_observer,
145                                          GActionObservable *observable,
146                                          const gchar       *action_name)
147 {
148   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
149
150   if (!observer->can_activate)
151     return;
152
153   observer->can_activate = FALSE;
154
155   if (observer->active)
156     {
157       observer->active = FALSE;
158       observer->reporting++;
159       g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
160       observer->reporting--;
161     }
162
163   if (observer->enabled)
164     {
165       observer->enabled = FALSE;
166       g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
167     }
168 }
169
170 static void
171 g_simple_action_observer_get_property (GObject *object, guint prop_id,
172                                        GValue *value, GParamSpec *pspec)
173 {
174   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (object);
175
176   switch (prop_id)
177     {
178     case PROP_ACTIVE:
179       g_value_set_boolean (value, observer->active);
180       break;
181
182     case PROP_ENABLED:
183       g_value_set_boolean (value, observer->enabled);
184       break;
185
186     default:
187       g_assert_not_reached ();
188     }
189 }
190
191 static void
192 g_simple_action_observer_finalize (GObject *object)
193 {
194   GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (object);
195
196   g_object_unref (observer->action_group);
197   g_free (observer->action_name);
198
199   if (observer->target)
200     g_variant_unref (observer->target);
201
202   G_OBJECT_CLASS (g_simple_action_observer_parent_class)
203     ->finalize (object);
204 }
205
206 static void
207 g_simple_action_observer_init (GSimpleActionObserver *observer)
208 {
209 }
210
211 static void
212 g_simple_action_observer_init_iface (GActionObserverInterface *iface)
213 {
214   iface->action_added = g_simple_action_observer_action_added;
215   iface->action_enabled_changed = g_simple_action_observer_action_enabled_changed;
216   iface->action_state_changed = g_simple_action_observer_action_state_changed;
217   iface->action_removed = g_simple_action_observer_action_removed;
218 }
219
220 static void
221 g_simple_action_observer_class_init (GObjectClass *class)
222 {
223   class->get_property = g_simple_action_observer_get_property;
224   class->finalize = g_simple_action_observer_finalize;
225
226   g_simple_action_observer_pspecs[PROP_ACTIVE] = g_param_spec_boolean ("active", "active", "active", FALSE,
227                                                                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
228   g_simple_action_observer_pspecs[PROP_ENABLED] = g_param_spec_boolean ("enabled", "enabled", "enabled", FALSE,
229                                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
230   g_object_class_install_properties (class, N_PROPS, g_simple_action_observer_pspecs);
231 }
232
233 GSimpleActionObserver *
234 g_simple_action_observer_new (GActionObservable *observable,
235                               const gchar       *action_name,
236                               GVariant          *target)
237 {
238   GSimpleActionObserver *observer;
239   const GVariantType *type;
240   gboolean enabled;
241   GVariant *state;
242
243   observer = g_object_new (G_TYPE_SIMPLE_ACTION_OBSERVER, NULL);
244   observer->action_group = g_object_ref (observable);
245   observer->action_name = g_strdup (action_name);
246   if (target)
247     observer->target = g_variant_ref_sink (target);
248
249   g_action_observable_register_observer (observable, action_name, G_ACTION_OBSERVER (observer));
250
251   if (g_action_group_query_action (observer->action_group, action_name, &enabled, &type, NULL, NULL, &state))
252     {
253       g_simple_action_observer_action_added (G_ACTION_OBSERVER (observer), observable,
254                                              action_name, type, enabled, state);
255       if (state)
256         g_variant_unref (state);
257     }
258
259   return observer;
260 }
261
262 void
263 g_simple_action_observer_activate (GSimpleActionObserver *observer)
264 {
265   g_return_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer));
266
267   if (observer->can_activate && !observer->reporting)
268     g_action_group_activate_action (G_ACTION_GROUP (observer->action_group),
269                                     observer->action_name, observer->target);
270 }
271
272 gboolean
273 g_simple_action_observer_get_active (GSimpleActionObserver *observer)
274 {
275   g_return_val_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer), FALSE);
276
277   return observer->active;
278 }
279
280 gboolean
281 g_simple_action_observer_get_enabled (GSimpleActionObserver *observer)
282 {
283   g_return_val_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer), FALSE);
284
285   return observer->enabled;
286 }