Merge lp:~apinheiro/unity/a11y-improve-window-event-emission into lp:unity
- a11y-improve-window-event-emission
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Alex Launi | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 1810 | ||||
Proposed branch: | lp:~apinheiro/unity/a11y-improve-window-event-emission | ||||
Merge into: | lp:unity | ||||
Prerequisite: | lp:~apinheiro/unity/a11y-quicklist | ||||
Diff against target: |
458 lines (+111/-163) 8 files modified
plugins/unityshell/src/nux-base-window-accessible.cpp (+34/-125) plugins/unityshell/src/nux-base-window-accessible.h (+2/-5) plugins/unityshell/src/nux-view-accessible.cpp (+0/-13) plugins/unityshell/src/unity-launcher-icon-accessible.cpp (+0/-1) plugins/unityshell/src/unity-quicklist-accessible.cpp (+0/-3) plugins/unityshell/src/unity-quicklist-menu-accessible.cpp (+1/-1) plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp (+3/-0) plugins/unityshell/src/unity-root-accessible.cpp (+71/-15) |
||||
To merge this branch: | bzr merge lp:~apinheiro/unity/a11y-improve-window-event-emission | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Launi (community) | Approve | ||
Neil J. Patel | Pending | ||
Review via email: mp+79290@code.launchpad.net |
Commit message
Description of the change
Alejandro Piñeiro (apinheiro) wrote : | # |
Alex Launi (alexlauni) wrote : | # |
API, could you please also include some tests for these merges? We're focusing on increaing our test code coverage and the a11y layer is an important part to be tested
Alejandro Piñeiro (apinheiro) wrote : | # |
> API, could you please also include some tests for these merges? We're focusing
> on increaing our test code coverage and the a11y layer is an important part to
> be tested
Yes it is true that a lot of new features were included without no new tests. Anyway, as most of those branches are already really big, and in order to keep things clean, could it possible to add tests on a different merge proposal?. In that way I could start to work on adding tests for a more global a11y support.
For example this branch is basically a improvement of previous branch, so I feel that include also tests there would be like mixing different things.
And after all, it would be good to check if it would be possible to move the a11y tests to the normal a11y directory. When I created those tests, I couldn't add them to the tests directory because there I couldn't included some Unity headers (I don't remember the details, I think that are detailed on a mail or on other merge proposal).
Alex Launi (alexlauni) wrote : | # |
Ok, sounds fair. Could you please propose some test branches as soon as possible?
Unity Merger (unity-merger) wrote : | # |
No proposals found for merge of lp:~apinheiro/unity/a11y-quicklist into lp:unity.
Preview Diff
1 | === modified file 'plugins/unityshell/src/nux-base-window-accessible.cpp' |
2 | --- plugins/unityshell/src/nux-base-window-accessible.cpp 2011-11-07 22:02:27 +0000 |
3 | +++ plugins/unityshell/src/nux-base-window-accessible.cpp 2011-11-07 22:02:27 +0000 |
4 | @@ -46,15 +46,6 @@ |
5 | #include <Nux/Area.h> |
6 | #include <Nux/Layout.h> |
7 | |
8 | -enum |
9 | -{ |
10 | - ACTIVATE, |
11 | - DEACTIVATE, |
12 | - LAST_SIGNAL |
13 | -}; |
14 | - |
15 | -static guint signals [LAST_SIGNAL] = { 0, }; |
16 | - |
17 | /* GObject */ |
18 | static void nux_base_window_accessible_class_init(NuxBaseWindowAccessibleClass* klass); |
19 | static void nux_base_window_accessible_init(NuxBaseWindowAccessible* base_window_accessible); |
20 | @@ -65,20 +56,19 @@ |
21 | static AtkObject* nux_base_window_accessible_get_parent(AtkObject* obj); |
22 | static AtkStateSet* nux_base_window_accessible_ref_state_set(AtkObject* obj); |
23 | |
24 | -/* private */ |
25 | -static void on_change_keyboard_receiver_cb(AtkObject* accessible, |
26 | - gboolean focus_in); |
27 | - |
28 | -G_DEFINE_TYPE(NuxBaseWindowAccessible, nux_base_window_accessible, NUX_TYPE_VIEW_ACCESSIBLE) |
29 | +/* AtkWindow.h */ |
30 | +static void atk_window_interface_init(AtkWindowIface* iface); |
31 | + |
32 | + |
33 | +G_DEFINE_TYPE_WITH_CODE(NuxBaseWindowAccessible, nux_base_window_accessible, |
34 | + NUX_TYPE_VIEW_ACCESSIBLE, |
35 | + G_IMPLEMENT_INTERFACE(ATK_TYPE_WINDOW, |
36 | + atk_window_interface_init)) |
37 | |
38 | struct _NuxBaseWindowAccessiblePrivate |
39 | { |
40 | /* Cached values (used to avoid extra notifications) */ |
41 | gboolean active; |
42 | - |
43 | - gboolean key_focused; |
44 | - gboolean child_key_focused; |
45 | - /* so active = key_focused || child_key_focused */ |
46 | }; |
47 | |
48 | #define NUX_BASE_WINDOW_ACCESSIBLE_GET_PRIVATE(obj) \ |
49 | @@ -97,45 +87,6 @@ |
50 | atk_class->ref_state_set = nux_base_window_accessible_ref_state_set; |
51 | |
52 | g_type_class_add_private(gobject_class, sizeof(NuxBaseWindowAccessiblePrivate)); |
53 | - |
54 | - /** |
55 | - * BaseWindow::activate: |
56 | - * @nux_object: the object which received the signal |
57 | - * |
58 | - * The ::activate signal is emitted when the window receives the key |
59 | - * focus from the underlying window system. |
60 | - * |
61 | - * Toolkit implementation note: it is used when anyone adds a global |
62 | - * event listener to "window:activate" |
63 | - */ |
64 | - signals [ACTIVATE] = |
65 | - g_signal_new("activate", |
66 | - G_TYPE_FROM_CLASS(klass), |
67 | - G_SIGNAL_RUN_LAST, |
68 | - 0, /* default signal handler */ |
69 | - NULL, NULL, |
70 | - g_cclosure_marshal_VOID__VOID, |
71 | - G_TYPE_NONE, 0); |
72 | - |
73 | - /** |
74 | - * BaseWindow::deactivate: |
75 | - * @nux_object: the object which received the signal |
76 | - * |
77 | - * The ::deactivate signal is emitted when the window loses key |
78 | - * focus from the underlying window system. |
79 | - * |
80 | - * Toolkit implementation note: it is used when anyone adds a global |
81 | - * event listener to "window:deactivate" |
82 | - */ |
83 | - signals [DEACTIVATE] = |
84 | - g_signal_new("deactivate", |
85 | - G_TYPE_FROM_CLASS(klass), |
86 | - G_SIGNAL_RUN_LAST, |
87 | - 0, /* default signal handler */ |
88 | - NULL, NULL, |
89 | - g_cclosure_marshal_VOID__VOID, |
90 | - G_TYPE_NONE, 0); |
91 | - |
92 | } |
93 | |
94 | static void |
95 | @@ -166,21 +117,9 @@ |
96 | nux_base_window_accessible_initialize(AtkObject* accessible, |
97 | gpointer data) |
98 | { |
99 | - nux::Object* nux_object = NULL; |
100 | - nux::BaseWindow* bwindow = NULL; |
101 | - |
102 | ATK_OBJECT_CLASS(nux_base_window_accessible_parent_class)->initialize(accessible, data); |
103 | |
104 | - accessible->role = ATK_ROLE_WINDOW; |
105 | - |
106 | - nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible)); |
107 | - bwindow = dynamic_cast<nux::BaseWindow*>(nux_object); |
108 | - |
109 | - /* This gives us if the window has the underlying key input */ |
110 | - bwindow->begin_key_focus.connect(sigc::bind(sigc::ptr_fun(on_change_keyboard_receiver_cb), |
111 | - accessible, TRUE)); |
112 | - bwindow->end_key_focus.connect(sigc::bind(sigc::ptr_fun(on_change_keyboard_receiver_cb), |
113 | - accessible, FALSE)); |
114 | + atk_object_set_role(accessible, ATK_ROLE_WINDOW); |
115 | } |
116 | |
117 | static AtkObject* |
118 | @@ -219,76 +158,46 @@ |
119 | return state_set; |
120 | } |
121 | |
122 | -/* private */ |
123 | +/* AtkWindow */ |
124 | static void |
125 | -check_active(NuxBaseWindowAccessible* self) |
126 | -{ |
127 | - gint signal_id; |
128 | +atk_window_interface_init(AtkWindowIface* iface) |
129 | +{ |
130 | + /* AtkWindow just define signals at this moment */ |
131 | +} |
132 | + |
133 | +/* public */ |
134 | +/* |
135 | + * Checks if we are the active window. |
136 | + */ |
137 | +void |
138 | +nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self, |
139 | + nux::BaseWindow* active_window) |
140 | +{ |
141 | + const gchar* signal_name; |
142 | gboolean is_active; |
143 | nux::Object* nux_object = NULL; |
144 | + nux::BaseWindow* bwindow = NULL; |
145 | + |
146 | + g_return_if_fail(NUX_IS_BASE_WINDOW_ACCESSIBLE(self)); |
147 | |
148 | nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self)); |
149 | - if (nux_object == NULL) /* defunct */ |
150 | + bwindow = dynamic_cast<nux::BaseWindow*>(nux_object); |
151 | + if (bwindow == NULL) /* defunct */ |
152 | return; |
153 | |
154 | - /* FIXME: this method is not infalible, as we lose some |
155 | - window->deactivate, specifically on the Dash, so this could be |
156 | - improved. As we check the active window using UBus messages we |
157 | - could use that information, but would make complex the |
158 | - quicklist. |
159 | - |
160 | - Anyway, the relevant message is the activate window, it is ok if |
161 | - we lose some deactivate methods for the moment */ |
162 | - is_active = (self->priv->key_focused || self->priv->child_key_focused); |
163 | + is_active = (bwindow == active_window); |
164 | |
165 | if (self->priv->active != is_active) |
166 | { |
167 | self->priv->active = is_active; |
168 | |
169 | if (is_active) |
170 | - signal_id = ACTIVATE; |
171 | + signal_name = "activate"; |
172 | else |
173 | - signal_id = DEACTIVATE; |
174 | + signal_name = "deactivate"; |
175 | |
176 | atk_object_notify_state_change(ATK_OBJECT(self), |
177 | ATK_STATE_ACTIVE, is_active); |
178 | - g_signal_emit(self, signals [signal_id], 0); |
179 | - } |
180 | -} |
181 | - |
182 | -static void |
183 | -on_change_keyboard_receiver_cb(AtkObject* object, |
184 | - gboolean focus_in) |
185 | -{ |
186 | - NuxBaseWindowAccessible* self = NULL; |
187 | - |
188 | - /* On the base window, we suppose that the window is active if it |
189 | - has the key focus (see nux::InputArea) */ |
190 | - self = NUX_BASE_WINDOW_ACCESSIBLE(object); |
191 | - |
192 | - if (self->priv->key_focused != focus_in) |
193 | - { |
194 | - self->priv->key_focused = focus_in; |
195 | - } |
196 | -} |
197 | - |
198 | -/* public */ |
199 | -void |
200 | -nux_base_window_set_child_key_focused(NuxBaseWindowAccessible* self, |
201 | - gboolean value) |
202 | -{ |
203 | - g_return_if_fail(NUX_IS_BASE_WINDOW_ACCESSIBLE(self)); |
204 | - |
205 | - if (self->priv->child_key_focused != value) |
206 | - { |
207 | - self->priv->child_key_focused = value; |
208 | - } |
209 | -} |
210 | - |
211 | -void |
212 | -nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self) |
213 | -{ |
214 | - g_return_if_fail(NUX_IS_BASE_WINDOW_ACCESSIBLE(self)); |
215 | - |
216 | - check_active(self); |
217 | + g_signal_emit_by_name(self, signal_name, 0); |
218 | + } |
219 | } |
220 | |
221 | === modified file 'plugins/unityshell/src/nux-base-window-accessible.h' |
222 | --- plugins/unityshell/src/nux-base-window-accessible.h 2011-11-07 22:02:27 +0000 |
223 | +++ plugins/unityshell/src/nux-base-window-accessible.h 2011-11-07 22:02:27 +0000 |
224 | @@ -54,11 +54,8 @@ |
225 | |
226 | GType nux_base_window_accessible_get_type(void); |
227 | AtkObject* nux_base_window_accessible_new(nux::Object* object); |
228 | - |
229 | -void nux_base_window_set_child_key_focused(NuxBaseWindowAccessible* self, |
230 | - gboolean value); |
231 | - |
232 | -void nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self); |
233 | +void nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self, |
234 | + nux::BaseWindow* active_window); |
235 | |
236 | |
237 | G_END_DECLS |
238 | |
239 | === modified file 'plugins/unityshell/src/nux-view-accessible.cpp' |
240 | --- plugins/unityshell/src/nux-view-accessible.cpp 2011-11-07 22:02:27 +0000 |
241 | +++ plugins/unityshell/src/nux-view-accessible.cpp 2011-11-07 22:02:27 +0000 |
242 | @@ -260,21 +260,8 @@ |
243 | |
244 | if (self->priv->key_focused != focus_in) |
245 | { |
246 | - AtkObject* parent_window = NULL; |
247 | - |
248 | self->priv->key_focused = focus_in; |
249 | |
250 | - /* this child has the key focus, so we report the top level |
251 | - * window about it. FIXME: that only works if only one object of |
252 | - * the children hierarchy can have the key focus, that is the |
253 | - * case here */ |
254 | - |
255 | - parent_window = |
256 | - nux_area_accessible_get_parent_window(NUX_AREA_ACCESSIBLE(self)); |
257 | - |
258 | - nux_base_window_set_child_key_focused(NUX_BASE_WINDOW_ACCESSIBLE(parent_window), |
259 | - focus_in); |
260 | - |
261 | /* we always led the focus notification to |
262 | _check_pending_notification, in order to allow the proper |
263 | window_activate -> focus_change order */ |
264 | |
265 | === modified file 'plugins/unityshell/src/unity-launcher-icon-accessible.cpp' |
266 | --- plugins/unityshell/src/unity-launcher-icon-accessible.cpp 2011-10-06 04:18:36 +0000 |
267 | +++ plugins/unityshell/src/unity-launcher-icon-accessible.cpp 2011-11-07 22:02:27 +0000 |
268 | @@ -326,7 +326,6 @@ |
269 | atk_object_notify_state_change(ATK_OBJECT(self), |
270 | ATK_STATE_ACTIVE, |
271 | found); |
272 | - |
273 | g_signal_emit_by_name(self, "focus-event", self->priv->selected, &return_val); |
274 | atk_focus_tracker_notify(ATK_OBJECT(self)); |
275 | } |
276 | |
277 | === modified file 'plugins/unityshell/src/unity-quicklist-accessible.cpp' |
278 | --- plugins/unityshell/src/unity-quicklist-accessible.cpp 2011-11-07 22:02:27 +0000 |
279 | +++ plugins/unityshell/src/unity-quicklist-accessible.cpp 2011-11-07 22:02:27 +0000 |
280 | @@ -132,9 +132,6 @@ |
281 | |
282 | if (quicklist == NULL) /* status defunct */ |
283 | return; |
284 | - |
285 | - atk_object_set_name(accessible, "Quicklist"); |
286 | - |
287 | } |
288 | |
289 | static gint |
290 | |
291 | === modified file 'plugins/unityshell/src/unity-quicklist-menu-accessible.cpp' |
292 | --- plugins/unityshell/src/unity-quicklist-menu-accessible.cpp 2011-11-07 22:02:27 +0000 |
293 | +++ plugins/unityshell/src/unity-quicklist-menu-accessible.cpp 2011-11-07 22:02:27 +0000 |
294 | @@ -174,7 +174,7 @@ |
295 | return; |
296 | |
297 | atk_object_set_role(accessible, ATK_ROLE_MENU); |
298 | - atk_object_set_name(accessible, "QuicklistMenu"); |
299 | + atk_object_set_name(accessible, _("Quicklist")); |
300 | |
301 | self->priv->on_selection_change_connection = |
302 | quicklist->selection_change.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self)); |
303 | |
304 | === modified file 'plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp' |
305 | --- plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp 2011-11-07 22:02:27 +0000 |
306 | +++ plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp 2011-11-07 22:02:27 +0000 |
307 | @@ -279,6 +279,9 @@ |
308 | |
309 | self->priv->selected = found; |
310 | atk_object_notify_state_change(ATK_OBJECT(self), |
311 | + ATK_STATE_FOCUSED, |
312 | + found); |
313 | + atk_object_notify_state_change(ATK_OBJECT(self), |
314 | ATK_STATE_SELECTED, |
315 | found); |
316 | atk_object_notify_state_change(ATK_OBJECT(self), |
317 | |
318 | === modified file 'plugins/unityshell/src/unity-root-accessible.cpp' |
319 | --- plugins/unityshell/src/unity-root-accessible.cpp 2011-11-07 22:02:27 +0000 |
320 | +++ plugins/unityshell/src/unity-root-accessible.cpp 2011-11-07 22:02:27 +0000 |
321 | @@ -21,7 +21,8 @@ |
322 | * @short_description: Root object for the UNITY accessible support |
323 | * |
324 | * #UnityRootAccessible is the root object of the accessibility |
325 | - * tree-like hierarchy, exposing the application level. |
326 | + * tree-like hierarchy, exposing the application level. You can see it |
327 | + * as the one exposing UnityScreen information to the a11y framework |
328 | * |
329 | */ |
330 | |
331 | @@ -63,6 +64,8 @@ |
332 | /* we save on window_list the accessible object for the windows |
333 | registered */ |
334 | GSList* window_list; |
335 | + nux::BaseWindow* active_window; |
336 | + nux::BaseWindow* launcher_window; |
337 | }; |
338 | |
339 | static void |
340 | @@ -88,6 +91,8 @@ |
341 | root->priv = UNITY_ROOT_ACCESSIBLE_GET_PRIVATE(root); |
342 | |
343 | root->priv->window_list = NULL; |
344 | + root->priv->active_window = NULL; |
345 | + root->priv->launcher_window = NULL; |
346 | } |
347 | |
348 | AtkObject* |
349 | @@ -231,8 +236,7 @@ |
350 | for (iter = self->priv->window_list; iter != NULL; iter = g_slist_next(iter)) |
351 | { |
352 | window = NUX_BASE_WINDOW_ACCESSIBLE(iter->data); |
353 | - |
354 | - nux_base_window_accessible_check_active(window); |
355 | + nux_base_window_accessible_check_active(window, self->priv->active_window); |
356 | } |
357 | } |
358 | |
359 | @@ -303,19 +307,78 @@ |
360 | } |
361 | |
362 | static void |
363 | -ubus_change_visibility_cb(GVariant* variant, |
364 | - UnityRootAccessible* self) |
365 | +set_active_window(UnityRootAccessible* self, |
366 | + nux::BaseWindow* window) |
367 | { |
368 | + g_return_if_fail(UNITY_IS_ROOT_ACCESSIBLE(self)); |
369 | + g_return_if_fail(window != NULL); |
370 | + |
371 | + self->priv->active_window = window; |
372 | check_active_window(self); |
373 | } |
374 | |
375 | -static void |
376 | -wc_change_visibility_window_cb(nux::BaseWindow* window, UnityRootAccessible* self, gboolean visible) |
377 | +nux::BaseWindow* |
378 | +search_for_launcher_window(UnityRootAccessible* self) |
379 | +{ |
380 | + GSList*iter = NULL; |
381 | + nux::Object* nux_object = NULL; |
382 | + nux::BaseWindow* bwindow = NULL; |
383 | + NuxObjectAccessible* accessible = NULL; |
384 | + gboolean found = FALSE; |
385 | + |
386 | + for (iter = self->priv->window_list; iter != NULL; iter = g_slist_next(iter)) |
387 | + { |
388 | + accessible = NUX_OBJECT_ACCESSIBLE(iter->data); |
389 | + |
390 | + nux_object = nux_object_accessible_get_object(accessible); |
391 | + bwindow = dynamic_cast<nux::BaseWindow*>(nux_object); |
392 | + |
393 | + if ((bwindow!= NULL) && (g_strcmp0(bwindow->GetWindowName().GetTCharPtr(), "Launcher") == 0)) |
394 | + { |
395 | + found = TRUE; |
396 | + break; |
397 | + } |
398 | + } |
399 | + |
400 | + if (found) |
401 | + return bwindow; |
402 | + else |
403 | + return NULL; |
404 | +} |
405 | + |
406 | +static void |
407 | +ubus_launcher_start_key_nav_cb(GVariant* variant, |
408 | + UnityRootAccessible* self) |
409 | +{ |
410 | + //launcher window is the same during all the life of Unity |
411 | + if (self->priv->launcher_window == NULL) |
412 | + self->priv->launcher_window = search_for_launcher_window(self); |
413 | + |
414 | + //launcher window became the active window |
415 | + set_active_window(self, self->priv->launcher_window); |
416 | +} |
417 | + |
418 | + |
419 | +static void |
420 | +wc_change_visibility_window_cb(nux::BaseWindow* window, |
421 | + UnityRootAccessible* self, |
422 | + gboolean visible) |
423 | { |
424 | if (visible) |
425 | + { |
426 | add_window(self, window); |
427 | + //for the dash and quicklist |
428 | + set_active_window(self, window); |
429 | + } |
430 | else |
431 | + { |
432 | + AtkObject* accessible = NULL; |
433 | + |
434 | + accessible = unity_a11y_get_accessible(window); |
435 | + nux_base_window_accessible_check_active(NUX_BASE_WINDOW_ACCESSIBLE(accessible), |
436 | + NULL); |
437 | remove_window(self, window); |
438 | + } |
439 | } |
440 | |
441 | static void |
442 | @@ -323,15 +386,8 @@ |
443 | { |
444 | static unity::UBusManager ubus_manager; |
445 | |
446 | - ubus_manager.RegisterInterest(UBUS_PLACE_VIEW_SHOWN, |
447 | - sigc::bind(sigc::ptr_fun(ubus_change_visibility_cb), self)); |
448 | - ubus_manager.RegisterInterest(UBUS_PLACE_VIEW_HIDDEN, |
449 | - sigc::bind(sigc::ptr_fun(ubus_change_visibility_cb), self)); |
450 | - |
451 | ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV, |
452 | - sigc::bind(sigc::ptr_fun(ubus_change_visibility_cb), self)); |
453 | - ubus_manager.RegisterInterest(UBUS_LAUNCHER_END_KEY_NAV, |
454 | - sigc::bind(sigc::ptr_fun(ubus_change_visibility_cb), self)); |
455 | + sigc::bind(sigc::ptr_fun(ubus_launcher_start_key_nav_cb), self)); |
456 | |
457 | nux::GetWindowCompositor().sigVisibleViewWindow. |
458 | connect(sigc::bind(sigc::ptr_fun(wc_change_visibility_window_cb), self, TRUE)); |
BTW, this branch is already being tested by the users, as it is included on this branch:
https:/ /launchpad. net/~apinheiro/ +archive/ unity-extra- a11y
I already received some positive feedback from ubuntu- accessibility mailing list