2
* Copyright (C) 2011 Canonical Ltd
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.
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.
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/>.
16
* Authored by: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
20
* SECTION:unity-switcher-accessible
21
* @Title: UnitySwitcherAccessible
22
* @short_description: Implementation of the ATK interfaces for #SwitcherView
23
* @see_also: SwitcherView
25
* #UnitySwitcherAccessible implements the required ATK interfaces for
26
* #SwitcherView, ie: exposing the different AbstractLauncherIcon on the
27
* #model as child of the object.
31
#include <glib/gi18n.h>
33
#include "unity-switcher-accessible.h"
34
#include "unity-launcher-icon-accessible.h"
36
#include "unitya11y.h"
37
#include "SwitcherView.h"
38
#include "SwitcherModel.h"
40
using namespace unity::switcher;
41
using namespace unity::launcher;
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);
49
static void unity_switcher_accessible_initialize(AtkObject* accessible,
51
static gint unity_switcher_accessible_get_n_children(AtkObject* obj);
52
static AtkObject* unity_switcher_accessible_ref_child(AtkObject* obj,
54
static AtkStateSet* unity_switcher_accessible_ref_state_set(AtkObject* obj);
57
static void atk_selection_interface_init(AtkSelectionIface* iface);
58
static AtkObject* unity_switcher_accessible_ref_selection(AtkSelection* selection,
60
static gint unity_switcher_accessible_get_selection_count(AtkSelection* selection);
61
static gboolean unity_switcher_accessible_is_child_selected(AtkSelection* selection,
63
/* NuxAreaAccessible */
64
static gboolean unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self);
67
static void on_selection_changed_cb(AbstractLauncherIcon* icon,
68
UnitySwitcherAccessible* switcher_accessible);
69
static void create_children(UnitySwitcherAccessible* self);
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))
75
#define UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(obj) \
76
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, \
77
UnitySwitcherAccessiblePrivate))
79
struct _UnitySwitcherAccessiblePrivate
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 */
86
sigc::connection on_selection_changed_connection;
91
unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass)
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);
97
gobject_class->finalize = unity_switcher_accessible_finalize;
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;
105
/* NuxAreaAccessible */
106
area_class->check_pending_notification = unity_switcher_accessible_check_pending_notification;
108
g_type_class_add_private(gobject_class, sizeof(UnitySwitcherAccessiblePrivate));
112
unity_switcher_accessible_init(UnitySwitcherAccessible* self)
114
UnitySwitcherAccessiblePrivate* priv =
115
UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(self);
118
self->priv->children = NULL;
122
unity_switcher_accessible_finalize(GObject* object)
124
UnitySwitcherAccessible* self = UNITY_SWITCHER_ACCESSIBLE(object);
126
self->priv->on_selection_changed_connection.disconnect();
128
if (self->priv->children)
130
g_slist_free_full(self->priv->children, g_object_unref);
131
self->priv->children = NULL;
134
G_OBJECT_CLASS(unity_switcher_accessible_parent_class)->finalize(object);
138
unity_switcher_accessible_new(nux::Object* object)
140
AtkObject* accessible = NULL;
142
g_return_val_if_fail(dynamic_cast<SwitcherView*>(object), NULL);
144
accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SWITCHER_ACCESSIBLE, NULL));
146
atk_object_initialize(accessible, object);
147
atk_object_set_name(accessible, _("Switcher"));
154
unity_switcher_accessible_initialize(AtkObject* accessible,
157
SwitcherView* switcher = NULL;
158
nux::Object* nux_object = NULL;
159
UnitySwitcherAccessible* self = NULL;
160
SwitcherModel::Ptr model;
162
ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->initialize(accessible, data);
164
atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
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)
172
model = switcher->GetModel();
176
self->priv->on_selection_changed_connection =
177
model->selection_changed.connect(sigc::bind(sigc::ptr_fun(on_selection_changed_cb),
180
create_children(self);
183
/* To force being connected to the window::activate signal */
184
nux_area_accessible_parent_window_active(NUX_AREA_ACCESSIBLE(self));
188
unity_switcher_accessible_get_n_children(AtkObject* obj)
190
nux::Object* object = NULL;
191
UnitySwitcherAccessible* self = NULL;
193
g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), 0);
194
self = UNITY_SWITCHER_ACCESSIBLE(obj);
196
object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
197
if (!object) /* state is defunct */
200
return g_slist_length(self->priv->children);
204
unity_switcher_accessible_ref_child(AtkObject* obj,
208
nux::Object* nux_object = NULL;
209
AtkObject* child_accessible = NULL;
210
UnitySwitcherAccessible* self = NULL;
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);
217
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
218
if (!nux_object) /* state is defunct */
221
child_accessible = ATK_OBJECT(g_slist_nth_data(self->priv->children, i));
223
g_object_ref(child_accessible);
225
return child_accessible;
229
unity_switcher_accessible_ref_state_set(AtkObject* obj)
231
AtkStateSet* state_set = NULL;
232
nux::Object* nux_object = NULL;
234
g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
237
ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->ref_state_set(obj);
239
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
241
if (nux_object == NULL) /* defunct */
244
/* The Switcher is always focusable */
245
atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
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);
256
atk_selection_interface_init(AtkSelectionIface* iface)
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;
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; */
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; */
276
unity_switcher_accessible_ref_selection(AtkSelection* selection,
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;
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);
291
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
292
if (!nux_object) /* state is defunct */
295
switcher = dynamic_cast<SwitcherView*>(nux_object);
297
switcher_model = switcher->GetModel();
298
selected_index = switcher_model->SelectionIndex();
300
accessible_selected = ATK_OBJECT(g_slist_nth_data(self->priv->children,
303
if (accessible_selected != NULL)
304
g_object_ref(accessible_selected);
306
return accessible_selected;
310
unity_switcher_accessible_get_selection_count(AtkSelection* selection)
312
SwitcherView* switcher = NULL;
313
SwitcherModel::Ptr switcher_model;
314
AbstractLauncherIcon* selected_icon = NULL;
315
nux::Object* nux_object = NULL;
317
g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
319
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
320
if (!nux_object) /* state is defunct */
323
switcher = dynamic_cast<SwitcherView*>(nux_object);
324
switcher_model = switcher->GetModel();
326
selected_icon = switcher_model->Selection();
328
if (selected_icon == 0)
335
unity_switcher_accessible_is_child_selected(AtkSelection* selection,
338
SwitcherView* switcher = NULL;
339
SwitcherModel::Ptr switcher_model;
340
SwitcherModel::iterator it;
341
nux::Object* nux_object = NULL;
342
gint selected_index = 0;
344
g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), FALSE);
346
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
347
if (!nux_object) /* state is defunct */
350
switcher = dynamic_cast<SwitcherView*>(nux_object);
351
switcher_model = switcher->GetModel();
352
selected_index = switcher_model->SelectionIndex();
354
if (selected_index == i)
360
/* NuxAreaAccessible */
362
unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self)
364
g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(self), FALSE);
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
372
atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, TRUE);
373
g_signal_emit_by_name(self, "focus-event", TRUE, NULL);
380
on_selection_changed_cb(AbstractLauncherIcon* icon,
381
UnitySwitcherAccessible* switcher_accessible)
383
g_signal_emit_by_name(ATK_OBJECT(switcher_accessible), "selection-changed");
387
create_children(UnitySwitcherAccessible* self)
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;
397
nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
398
if (!nux_object) /* state is defunct */
401
switcher = dynamic_cast<SwitcherView*>(nux_object);
402
switcher_model = switcher->GetModel();
404
if (switcher_model == NULL)
407
for (it = switcher_model->begin(); it != switcher_model->end(); it++)
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,
414
unity_launcher_icon_accessible_set_index(UNITY_LAUNCHER_ICON_ACCESSIBLE(child_accessible),