~bilalakhtar/unity/software-center-integration-for-o

« back to all changes in this revision

Viewing changes to plugins/unityshell/src/unity-switcher-accessible.cpp

  • Committer: Bilal Akhtar
  • Date: 2012-01-15 14:03:49 UTC
  • mfrom: (1346.2.488 unity)
  • Revision ID: bilalakhtar@ubuntu.com-20120115140349-mht4dke0occbsyra
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
 
17
 */
 
18
 
 
19
/**
 
20
 * SECTION:unity-switcher-accessible
 
21
 * @Title: UnitySwitcherAccessible
 
22
 * @short_description: Implementation of the ATK interfaces for #SwitcherView
 
23
 * @see_also: SwitcherView
 
24
 *
 
25
 * #UnitySwitcherAccessible implements the required ATK interfaces for
 
26
 * #SwitcherView, ie: exposing the different AbstractLauncherIcon on the
 
27
 * #model as child of the object.
 
28
 *
 
29
 */
 
30
 
 
31
#include <glib/gi18n.h>
 
32
 
 
33
#include "unity-switcher-accessible.h"
 
34
#include "unity-launcher-icon-accessible.h"
 
35
 
 
36
#include "unitya11y.h"
 
37
#include "SwitcherView.h"
 
38
#include "SwitcherModel.h"
 
39
 
 
40
using namespace unity::switcher;
 
41
using namespace unity::launcher;
 
42
 
 
43
/* GObject */
 
44
static void unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass);
 
45
static void unity_switcher_accessible_init(UnitySwitcherAccessible* self);
 
46
static void unity_switcher_accessible_finalize(GObject* object);
 
47
 
 
48
/* AtkObject.h */
 
49
static void       unity_switcher_accessible_initialize(AtkObject* accessible,
 
50
                                                       gpointer   data);
 
51
static gint       unity_switcher_accessible_get_n_children(AtkObject* obj);
 
52
static AtkObject* unity_switcher_accessible_ref_child(AtkObject* obj,
 
53
                                                      gint i);
 
54
static AtkStateSet* unity_switcher_accessible_ref_state_set(AtkObject* obj);
 
55
 
 
56
/* AtkSelection */
 
57
static void       atk_selection_interface_init(AtkSelectionIface* iface);
 
58
static AtkObject* unity_switcher_accessible_ref_selection(AtkSelection* selection,
 
59
                                                          gint i);
 
60
static gint       unity_switcher_accessible_get_selection_count(AtkSelection* selection);
 
61
static gboolean   unity_switcher_accessible_is_child_selected(AtkSelection* selection,
 
62
                                                              gint i);
 
63
/* NuxAreaAccessible */
 
64
static gboolean   unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self);
 
65
 
 
66
/* private */
 
67
static void       on_selection_changed_cb(AbstractLauncherIcon* icon,
 
68
                                          UnitySwitcherAccessible* switcher_accessible);
 
69
static void       create_children(UnitySwitcherAccessible* self);
 
70
 
 
71
 
 
72
G_DEFINE_TYPE_WITH_CODE(UnitySwitcherAccessible, unity_switcher_accessible,  NUX_TYPE_VIEW_ACCESSIBLE,
 
73
                        G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
 
74
 
 
75
#define UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(obj)                      \
 
76
  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE,  \
 
77
                                UnitySwitcherAccessiblePrivate))
 
78
 
 
79
struct _UnitySwitcherAccessiblePrivate
 
80
{
 
81
  /* We maintain the children. Although the LauncherIcon are shared
 
82
   * between the Switcher and Launcher, in order to keep a hierarchy
 
83
   * coherence, we create a different accessible object  */
 
84
  GSList* children;
 
85
 
 
86
  sigc::connection on_selection_changed_connection;
 
87
};
 
88
 
 
89
 
 
90
static void
 
91
unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass)
 
92
{
 
93
  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
 
94
  AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
 
95
  NuxAreaAccessibleClass* area_class = NUX_AREA_ACCESSIBLE_CLASS(klass);
 
96
 
 
97
  gobject_class->finalize = unity_switcher_accessible_finalize;
 
98
 
 
99
  /* AtkObject */
 
100
  atk_class->get_n_children = unity_switcher_accessible_get_n_children;
 
101
  atk_class->ref_child = unity_switcher_accessible_ref_child;
 
102
  atk_class->initialize = unity_switcher_accessible_initialize;
 
103
  atk_class->ref_state_set = unity_switcher_accessible_ref_state_set;
 
104
 
 
105
  /* NuxAreaAccessible */
 
106
  area_class->check_pending_notification = unity_switcher_accessible_check_pending_notification;
 
107
 
 
108
  g_type_class_add_private(gobject_class, sizeof(UnitySwitcherAccessiblePrivate));
 
109
}
 
110
 
 
111
static void
 
112
unity_switcher_accessible_init(UnitySwitcherAccessible* self)
 
113
{
 
114
  UnitySwitcherAccessiblePrivate* priv =
 
115
    UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(self);
 
116
 
 
117
  self->priv = priv;
 
118
  self->priv->children = NULL;
 
119
}
 
120
 
 
121
static void
 
122
unity_switcher_accessible_finalize(GObject* object)
 
123
{
 
124
  UnitySwitcherAccessible* self = UNITY_SWITCHER_ACCESSIBLE(object);
 
125
 
 
126
  self->priv->on_selection_changed_connection.disconnect();
 
127
 
 
128
  if (self->priv->children)
 
129
  {
 
130
    g_slist_free_full(self->priv->children, g_object_unref);
 
131
    self->priv->children = NULL;
 
132
  }
 
133
 
 
134
  G_OBJECT_CLASS(unity_switcher_accessible_parent_class)->finalize(object);
 
135
}
 
136
 
 
137
AtkObject*
 
138
unity_switcher_accessible_new(nux::Object* object)
 
139
{
 
140
  AtkObject* accessible = NULL;
 
141
 
 
142
  g_return_val_if_fail(dynamic_cast<SwitcherView*>(object), NULL);
 
143
 
 
144
  accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SWITCHER_ACCESSIBLE, NULL));
 
145
 
 
146
  atk_object_initialize(accessible, object);
 
147
  atk_object_set_name(accessible, _("Switcher"));
 
148
 
 
149
  return accessible;
 
150
}
 
151
 
 
152
/* AtkObject.h */
 
153
static void
 
154
unity_switcher_accessible_initialize(AtkObject* accessible,
 
155
                                     gpointer data)
 
156
{
 
157
  SwitcherView* switcher = NULL;
 
158
  nux::Object* nux_object = NULL;
 
159
  UnitySwitcherAccessible* self = NULL;
 
160
  SwitcherModel::Ptr model;
 
161
 
 
162
  ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->initialize(accessible, data);
 
163
 
 
164
  atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
 
165
 
 
166
  self = UNITY_SWITCHER_ACCESSIBLE(accessible);
 
167
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
 
168
  switcher = dynamic_cast<SwitcherView*>(nux_object);
 
169
  if (switcher == NULL)
 
170
    return;
 
171
 
 
172
  model = switcher->GetModel();
 
173
 
 
174
  if (model)
 
175
  {
 
176
    self->priv->on_selection_changed_connection  =
 
177
      model->selection_changed.connect(sigc::bind(sigc::ptr_fun(on_selection_changed_cb),
 
178
                                                  self));
 
179
 
 
180
    create_children(self);
 
181
  }
 
182
 
 
183
  /* To force being connected to the window::activate signal */
 
184
  nux_area_accessible_parent_window_active(NUX_AREA_ACCESSIBLE(self));
 
185
}
 
186
 
 
187
static gint
 
188
unity_switcher_accessible_get_n_children(AtkObject* obj)
 
189
{
 
190
  nux::Object* object = NULL;
 
191
  UnitySwitcherAccessible* self = NULL;
 
192
 
 
193
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), 0);
 
194
  self = UNITY_SWITCHER_ACCESSIBLE(obj);
 
195
 
 
196
  object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
 
197
  if (!object) /* state is defunct */
 
198
    return 0;
 
199
 
 
200
  return g_slist_length(self->priv->children);
 
201
}
 
202
 
 
203
static AtkObject*
 
204
unity_switcher_accessible_ref_child(AtkObject* obj,
 
205
                                    gint i)
 
206
{
 
207
  gint num = 0;
 
208
  nux::Object* nux_object = NULL;
 
209
  AtkObject* child_accessible = NULL;
 
210
  UnitySwitcherAccessible* self = NULL;
 
211
 
 
212
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
 
213
  num = atk_object_get_n_accessible_children(obj);
 
214
  g_return_val_if_fail((i < num) && (i >= 0), NULL);
 
215
  self = UNITY_SWITCHER_ACCESSIBLE(obj);
 
216
 
 
217
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
 
218
  if (!nux_object) /* state is defunct */
 
219
    return 0;
 
220
 
 
221
  child_accessible = ATK_OBJECT(g_slist_nth_data(self->priv->children, i));
 
222
 
 
223
  g_object_ref(child_accessible);
 
224
 
 
225
  return child_accessible;
 
226
}
 
227
 
 
228
static AtkStateSet*
 
229
unity_switcher_accessible_ref_state_set(AtkObject* obj)
 
230
{
 
231
  AtkStateSet* state_set = NULL;
 
232
  nux::Object* nux_object = NULL;
 
233
 
 
234
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
 
235
 
 
236
  state_set =
 
237
    ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->ref_state_set(obj);
 
238
 
 
239
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
 
240
 
 
241
  if (nux_object == NULL) /* defunct */
 
242
    return state_set;
 
243
 
 
244
  /* The Switcher is always focusable */
 
245
  atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
 
246
 
 
247
  /* The Switcher is always focused. Looking SwitcherController code,
 
248
   * SwitcherView is only created to be presented to the user */
 
249
  atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
 
250
 
 
251
  return state_set;
 
252
}
 
253
 
 
254
/* AtkSelection */
 
255
static void
 
256
atk_selection_interface_init(AtkSelectionIface* iface)
 
257
{
 
258
  iface->ref_selection = unity_switcher_accessible_ref_selection;
 
259
  iface->get_selection_count = unity_switcher_accessible_get_selection_count;
 
260
  iface->is_child_selected = unity_switcher_accessible_is_child_selected;
 
261
 
 
262
  /* NOTE: for the moment we don't provide the implementation for the
 
263
     "interactable" methods, it is, the methods that allow to change
 
264
     the selected icon. The Switcher doesn't provide that API, and
 
265
     right now  we are focusing on a normal user input.*/
 
266
  /* iface->add_selection = unity_switcher_accessible_add_selection; */
 
267
  /* iface->clear_selection = unity_switcher_accessible_clear_selection; */
 
268
  /* iface->remove_selection = unity_switcher_accessible_remove_selection; */
 
269
 
 
270
  /* This method will never be implemented, as select all the switcher
 
271
     icons makes no sense */
 
272
  /* iface->select_all = unity_switcher_accessible_select_all_selection; */
 
273
}
 
274
 
 
275
static AtkObject*
 
276
unity_switcher_accessible_ref_selection(AtkSelection* selection,
 
277
                                        gint i)
 
278
{
 
279
  SwitcherView* switcher = NULL;
 
280
  SwitcherModel::Ptr switcher_model;
 
281
  nux::Object* nux_object = NULL;
 
282
  gint selected_index = 0;
 
283
  AtkObject* accessible_selected = NULL;
 
284
  UnitySwitcherAccessible* self = NULL;
 
285
 
 
286
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
 
287
  /* there can be only just item selected */
 
288
  g_return_val_if_fail(i == 0, NULL);
 
289
  self = UNITY_SWITCHER_ACCESSIBLE(selection);
 
290
 
 
291
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
 
292
  if (!nux_object) /* state is defunct */
 
293
    return 0;
 
294
 
 
295
  switcher = dynamic_cast<SwitcherView*>(nux_object);
 
296
 
 
297
  switcher_model = switcher->GetModel();
 
298
  selected_index = switcher_model->SelectionIndex();
 
299
 
 
300
  accessible_selected = ATK_OBJECT(g_slist_nth_data(self->priv->children,
 
301
                                                    selected_index));
 
302
 
 
303
  if (accessible_selected != NULL)
 
304
    g_object_ref(accessible_selected);
 
305
 
 
306
  return accessible_selected;
 
307
}
 
308
 
 
309
static gint
 
310
unity_switcher_accessible_get_selection_count(AtkSelection* selection)
 
311
{
 
312
  SwitcherView* switcher = NULL;
 
313
  SwitcherModel::Ptr switcher_model;
 
314
  AbstractLauncherIcon* selected_icon = NULL;
 
315
  nux::Object* nux_object = NULL;
 
316
 
 
317
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
 
318
 
 
319
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
 
320
  if (!nux_object) /* state is defunct */
 
321
    return 0;
 
322
 
 
323
  switcher = dynamic_cast<SwitcherView*>(nux_object);
 
324
  switcher_model = switcher->GetModel();
 
325
 
 
326
  selected_icon = switcher_model->Selection();
 
327
 
 
328
  if (selected_icon == 0)
 
329
    return 0;
 
330
  else
 
331
    return 1;
 
332
}
 
333
 
 
334
static gboolean
 
335
unity_switcher_accessible_is_child_selected(AtkSelection* selection,
 
336
                                            gint i)
 
337
{
 
338
  SwitcherView* switcher = NULL;
 
339
  SwitcherModel::Ptr switcher_model;
 
340
  SwitcherModel::iterator it;
 
341
  nux::Object* nux_object = NULL;
 
342
  gint selected_index = 0;
 
343
 
 
344
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), FALSE);
 
345
 
 
346
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
 
347
  if (!nux_object) /* state is defunct */
 
348
    return 0;
 
349
 
 
350
  switcher = dynamic_cast<SwitcherView*>(nux_object);
 
351
  switcher_model = switcher->GetModel();
 
352
  selected_index = switcher_model->SelectionIndex();
 
353
 
 
354
  if (selected_index == i)
 
355
    return TRUE;
 
356
  else
 
357
    return FALSE;
 
358
}
 
359
 
 
360
/* NuxAreaAccessible */
 
361
static gboolean
 
362
unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self)
 
363
{
 
364
  g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(self), FALSE);
 
365
 
 
366
  /* Overriding the method: the switcher doesn't get the key focus of
 
367
   * focus (Focusable) */
 
368
  /* From SwitcherController: it shows that the switcher only exists
 
369
   * to be shown to the user, so if the parent window gets actived, we
 
370
   * assume that the switcher will be automatically focused
 
371
   */
 
372
  atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, TRUE);
 
373
  g_signal_emit_by_name(self, "focus-event", TRUE, NULL);
 
374
 
 
375
  return TRUE;
 
376
}
 
377
 
 
378
/* private */
 
379
static void
 
380
on_selection_changed_cb(AbstractLauncherIcon* icon,
 
381
                        UnitySwitcherAccessible* switcher_accessible)
 
382
{
 
383
  g_signal_emit_by_name(ATK_OBJECT(switcher_accessible), "selection-changed");
 
384
}
 
385
 
 
386
static void
 
387
create_children(UnitySwitcherAccessible* self)
 
388
{
 
389
  gint index = 0;
 
390
  nux::Object* nux_object = NULL;
 
391
  SwitcherView* switcher = NULL;
 
392
  SwitcherModel::Ptr switcher_model;
 
393
  SwitcherModel::iterator it;
 
394
  LauncherIcon* child = NULL;
 
395
  AtkObject* child_accessible = NULL;
 
396
 
 
397
  nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
 
398
  if (!nux_object) /* state is defunct */
 
399
    return;
 
400
 
 
401
  switcher = dynamic_cast<SwitcherView*>(nux_object);
 
402
  switcher_model = switcher->GetModel();
 
403
 
 
404
  if (switcher_model == NULL)
 
405
    return;
 
406
 
 
407
  for (it = switcher_model->begin(); it != switcher_model->end(); it++)
 
408
  {
 
409
    child =  dynamic_cast<LauncherIcon*>(*it);
 
410
    child_accessible = unity_launcher_icon_accessible_new(child);
 
411
    atk_object_set_parent(child_accessible, ATK_OBJECT(self));
 
412
    self->priv->children = g_slist_append(self->priv->children,
 
413
                                          child_accessible);
 
414
    unity_launcher_icon_accessible_set_index(UNITY_LAUNCHER_ICON_ACCESSIBLE(child_accessible),
 
415
                                             index++);
 
416
  }
 
417
}