Merge lp:~alanbell/compiz/texttracking into lp:compiz/0.9.8

Proposed by Alan Bell on 2012-06-23
Status: Work in progress
Proposed branch: lp:~alanbell/compiz/texttracking
Merge into: lp:compiz/0.9.8
Diff against target: 1249 lines (+1101/-2)
13 files modified
plugins/accessibility/AUTHORS (+1/-0)
plugins/accessibility/CMakeLists.txt (+5/-0)
plugins/accessibility/VERSION (+1/-0)
plugins/accessibility/accessibility.xml.in (+17/-0)
plugins/accessibility/compiz-accessibility.pc.in (+12/-0)
plugins/accessibility/include/accessibility/accessibility.h (+217/-0)
plugins/accessibility/src/accessibility.cpp (+651/-0)
plugins/accessibility/src/private.h (+113/-0)
plugins/ezoom/CMakeLists.txt (+1/-1)
plugins/ezoom/ezoom.xml.in (+2/-0)
plugins/ezoom/src/ezoom.cpp (+71/-0)
plugins/ezoom/src/ezoom.h (+9/-0)
plugins/mousepoll/mousepoll.xml.in (+1/-1)
To merge this branch: bzr merge lp:~alanbell/compiz/texttracking
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing on 2012-07-03
Sam Spilsbury 2012-06-23 Needs Fixing on 2012-06-23
Review via email: mp+111710@code.launchpad.net

Description of the change

merges in code from
https://github.com/gloob/gloob-Ezoom-fork
https://github.com/gloob/compiz-accessibility-plugin
fixing lp:#727290
it compiles, might have an additional dependency on at-spi stuff, I don't know how to merge it with the debian packaging to make an installable package.

To post a comment you must log in.
Sam Spilsbury (smspillaz) wrote :
Download full text (9.2 KiB)

Looks good, and definitely on the right track, needs some work before we can merge it in, but definitely something we can have for 12.10

The README can probably be cut down or go entirely, it seems to be mostly about how to enable AT-SPI and how to build and install the plugin, which is mostly redundant anyways as the buildsystem will build it for us.

There are a few indentation problems that need to be fixed. Indentation in compiz is a little weird (X11 style). It goes:

4 spaces
8-wide tab
8-wide tab + 4 spaces
8-wide tab + 8 wide tab
8-wide tab + 8-wide tab + 4 spaces

etc

So some areas where this needs to be fixed are:

215 + virtual AccessibilityEntity *
216 + clone () const;
217 +
218 + AtspiAccessible *
219 + getObject ();

215 + virtual AccessibilityEntity *
216 + clone () const;
217 +
218 + AtspiAccessible *
219 + getObject ();

412 + for (int i = 0; i < len; i++) {
413 +

The brace goes on the next line, eg
for (int i = 0; i < len; i++)
{

 + switch (iface) {

ditto

518 + compLogMessage ("Accessibility", CompLogLevelInfo,
519 + "AccessibilityEntity::AccessibilityEntity (%s)\n", object->name);
520 +

I don't think these messages are necessary. Program function can be verified through unit tests (which I'll get on to in a minute)

1269 + if (a11yHandle->active ())
1270 + a11yHandle->unregisterAll ();

That needs to be a tab and not four spaces.

The second big thing I have about this code is that the design feels a little weird.

The inheritance hierarchy looks a bit like this:

AccessibilityEntity
 - AccessibilityComponent
 - AccessibilityText

AccessibleObject (which appears to be a wrapper around AtspiAccessible *)
Accessibility (which appears to be a manager class)

The real gripe I have here are things like this:

434 + case Component:
435 + entity = AccessibilityEntity::Ptr (new AccessibilityComponent (object));
436 + break;
437 +
438 + case Text:
439 + entity = AccessibilityEntity::Ptr (new AccessibilityText (object));
440 + break;
441 +
442 + case Accessible:
443 + case Action:
444 + case Collection:
445 + case Document:
446 + case EditableText:
447 + case Hypertext:
448 + case Hyperlink:
449 + case Image:
450 + case Selection:
451 + case Table:
452 + case Value:
453 + break;
454 +
455 + default:
456 + entity = AccessibilityEntity::Ptr (new AccessibilityEntity (object));

This code feels fragile, because our fallback case is "silently do nothing", and we just waste memory by tracking objects we don't really care about. Moreover, that behaviour is different from cases that we know we don't care about where we return a shared_ptr to NULL and then the client code just assumes that the pointer is valid.

There are other examples like this:

941 + if (object->is (Component))
942 + {
943 +
944 + AccessibilityComponent::Ptr ac =
945 + boost::static_pointer_cast<AccessibilityComponent>
946 + (object->getEntity (Component));

Generally speaking, code where you need to go from some "placeholder" down to something that you think the object is feels to me like reintepret_casting through void * with a note that everything will be okay.

I understand that Atspi is based on GObject and as such, you have to handle the type system at run...

Read more...

review: Needs Fixing
Sam Spilsbury (smspillaz) wrote :

Oh yeah, totally forgot! Tests...

Generally speaking, I prefer all code going into compiz to come with unit tests. I don't think getting this particular code under test will be that difficult. The majority of the a11y code looks like its just wrappers for managing objects coming to us from AT-SPI.

Stuff that I think needs to be tested (or needs to be deleted, since it looks unused):

206 + virtual bool
207 + load (AtspiAccessible *);
208 +
209 + virtual bool
210 + contains (AccessibilityEntity *, int, int);
211 +

Actually they can be deleted completely as they are unused. But...

236 + CompRect
237 + getExtents () const;
238 +
239 + CompPoint
240 + getPosition () const;
241 +
242 + CompPoint
243 + getSize () const;

I am like 99% sure the second two are unused.

The relationship between getExtents and this:

1214 + if (optionGetZoomMode () == EzoomOptions::ZoomModePanArea)
1215 + {
1216 + ensureVisibilityArea (rect.x1(),
1217 + rect.y1(),
1218 + rect.x2(),
1219 + rect.y2(),
1220 + optionGetRestrainMargin (),
1221 + NORTHWEST);
1222 + }

Or, a potential getZoomCenterArea () needs to come under test

As well as:

267 + CompRect
268 + getCharacterExtents (int) const;
269 +
270 + CompRect
271 + getRangeExtents (int) const;
272 +
273 + int
274 + getCaretOffset ();

(getRangeExtents can be deleted)

But the relationship between the first and the third needs to be tested. That means breaking the dependency on

654 + AtspiRect *character_rect = atspi_text_get_character_extents
655 + (text, offset, ATSPI_COORD_TYPE_SCREEN, &error);

through an interface by which AtspiRect can be manipulated and atspi_text_get_character_extents be queried.

Then you can use Mock Objects to verify the behaviour of getCharacterExtents and the resulting zoom rect.

Feel free to poke with questions on IRC. I'm on planes for the next two days, but I can be found on freenode (nick: smspillaz)

lp:~alanbell/compiz/texttracking updated on 2012-06-23
3254. By Alan Bell on 2012-06-23

remove README and fix indentation

3255. By Alan Bell on 2012-06-23

remove message

3256. By Alan Bell on 2012-06-23

indentation issue

Daniel van Vugt (vanvugt) wrote :

Please review and fix the indentation and style again. For example:

135 + virtual IfaceType
136 + is ();
137 +
138 + virtual AccessibilityEntity *
139 + clone () const;
140 +
141 + AtspiAccessible *
142 + getObject ();

should be more like:

   virtual IfaceType is ();
   virtual AccessibilityEntity *clone () const;
   AtspiAccessible *getObject ();

And the same applies elsewhere.

review: Needs Fixing
Daniel van Vugt (vanvugt) wrote :

When done, please click Resubmit so we get notified.

Daniel van Vugt (vanvugt) wrote :

Please also click "Set commit message" when done so the automerger doesn't reject it once approved by us.

Sam Spilsbury (smspillaz) wrote :

(This will be looked at and I will propose a merge to fix some of the overarching design issues once the gles2 and gsettings work is done)

Alan Bell (alanbell) wrote :

I will have a go at the indentation issues, but I am a bit out of my depth on the refactoring, this isn't my code, I am just trying to integrate it into the upstream tree, I will try and contact gloob https://github.com/gloob for some help I think.

Sam Spilsbury (smspillaz) wrote :

Sure, no problem :)

Alejandro Leiva (gloob) wrote :

Hi guys, thanks for working on this.

As Sam pointed out before there's some methods, classes and structures that I'm not using in the plugin. In fact I'm not happy with the global architecture. A refactor is needed. I'll do.

Alan if you can grant me write access to your branch I won't need to create a new branch and merge and so on.

Cheers.

Alan Bell (alanbell) wrote :

thanks Alejandro,

I don't think I can give you write access to my branch, but you can probably do
bzr branch lp:~alanbell/compiz/texttracking
bzr push lp:~gloob/compiz/texttracking

and then do a merge request from there

Unmerged revisions

3256. By Alan Bell on 2012-06-23

indentation issue

3255. By Alan Bell on 2012-06-23

remove message

3254. By Alan Bell on 2012-06-23

remove README and fix indentation

3253. By Alan Bell on 2012-06-22

renamed the accessibility plugin folder and fixed an unused variable in ezoom

3252. By Alan Bell on 2012-06-22

merging in text tracking zoom work by Alejandro Leiva
https://github.com/gloob/compiz-accessibility-plugin
https://github.com/gloob/gloob-Ezoom-fork

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'plugins/accessibility'
2=== added file 'plugins/accessibility/AUTHORS'
3--- plugins/accessibility/AUTHORS 1970-01-01 00:00:00 +0000
4+++ plugins/accessibility/AUTHORS 2012-06-23 15:04:23 +0000
5@@ -0,0 +1,1 @@
6+Alejandro Leiva <aleiva@emergya.com>
7
8=== added file 'plugins/accessibility/CMakeLists.txt'
9--- plugins/accessibility/CMakeLists.txt 1970-01-01 00:00:00 +0000
10+++ plugins/accessibility/CMakeLists.txt 2012-06-23 15:04:23 +0000
11@@ -0,0 +1,5 @@
12+find_package (Compiz REQUIRED)
13+
14+include (CompizPlugin)
15+
16+compiz_plugin (accessibility PKGDEPS atspi-2)
17
18=== added file 'plugins/accessibility/ChangeLog'
19=== added file 'plugins/accessibility/NEWS'
20=== added file 'plugins/accessibility/VERSION'
21--- plugins/accessibility/VERSION 1970-01-01 00:00:00 +0000
22+++ plugins/accessibility/VERSION 2012-06-23 15:04:23 +0000
23@@ -0,0 +1,1 @@
24+0.9.5.0
25
26=== added file 'plugins/accessibility/accessibility.xml.in'
27--- plugins/accessibility/accessibility.xml.in 1970-01-01 00:00:00 +0000
28+++ plugins/accessibility/accessibility.xml.in 2012-06-23 15:04:23 +0000
29@@ -0,0 +1,17 @@
30+<?xml version="1.0"?>
31+<compiz>
32+ <plugin name="accessibility" useBcop="true">
33+ <_short>Accessibility</_short>
34+ <_long>Activate compatibility with accessibility layer.</_long>
35+ <category>Accessibility</category>
36+ <deps>
37+ <relation type="after">
38+ <plugin>opengl</plugin>
39+ <plugin>composite</plugin>
40+ <plugin>decor</plugin>
41+ </relation>
42+ </deps>
43+ <options>
44+ </options>
45+ </plugin>
46+</compiz>
47
48=== added file 'plugins/accessibility/compiz-accessibility.pc.in'
49--- plugins/accessibility/compiz-accessibility.pc.in 1970-01-01 00:00:00 +0000
50+++ plugins/accessibility/compiz-accessibility.pc.in 2012-06-23 15:04:23 +0000
51@@ -0,0 +1,12 @@
52+prefix=@prefix@
53+exec_prefix=@prefix@
54+libdir=@libdir@
55+includedir=@includedir@
56+
57+Name: compiz-accessibility
58+Description: Accessibility (based in AT-SPI2) plugin for compiz
59+Version: @VERSION@
60+
61+Requires: compiz
62+Libs: -L${libdir}/compiz -laccessibility
63+Cflags: @COMPIZ_CFLAGS@ -I${includedir}/compiz
64
65=== added directory 'plugins/accessibility/include'
66=== added directory 'plugins/accessibility/include/accessibility'
67=== added file 'plugins/accessibility/include/accessibility/accessibility.h'
68--- plugins/accessibility/include/accessibility/accessibility.h 1970-01-01 00:00:00 +0000
69+++ plugins/accessibility/include/accessibility/accessibility.h 2012-06-23 15:04:23 +0000
70@@ -0,0 +1,217 @@
71+/*
72+ * Compiz Accessibility PLugin
73+ *
74+ * Copyright (c) 2011 F123 Consulting & Mais Diferenças
75+ *
76+ * This program is free software; you can redistribute it and/or
77+ * modify it under the terms of the GNU General Public License
78+ * as published by the Free Software Foundation; either version 2
79+ * of the License, or (at your option) any later version.
80+ *
81+ * This program is distributed in the hope that it will be useful,
82+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
83+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84+ * GNU General Public License for more details.
85+ *
86+ * Author: Alejandro Leiva <aleiva@emergya.com>
87+ *
88+ */
89+
90+#ifndef _ACCESSIBILITY_H
91+#define _ACCESSIBILITY_H
92+
93+#ifdef __cplusplus
94+extern "C" {
95+#endif
96+#include <atspi/atspi.h>
97+#ifdef __cplusplus
98+}
99+#endif
100+
101+/*
102+ * Class hierarchy that hold and manage differents accessible objects.
103+ */
104+enum IfaceType
105+{
106+ Accessible = 0,
107+ Action,
108+ Collection,
109+ Component,
110+ Document,
111+ EditableText,
112+ Hypertext,
113+ Hyperlink,
114+ Image,
115+ Selection,
116+ Table,
117+ Text,
118+ Value,
119+};
120+
121+class AccessibilityEntity
122+{
123+ public:
124+ typedef boost::shared_ptr<AccessibilityEntity> Ptr;
125+
126+ AccessibilityEntity (AtspiAccessible *);
127+ virtual ~AccessibilityEntity ();
128+
129+ virtual bool
130+ load (AtspiAccessible *);
131+
132+ virtual bool
133+ contains (AccessibilityEntity *, int, int);
134+
135+ virtual IfaceType
136+ is ();
137+
138+ virtual AccessibilityEntity *
139+ clone () const;
140+
141+ AtspiAccessible *
142+ getObject ();
143+
144+ protected:
145+ AtspiAccessible * obj;
146+};
147+
148+class AccessibilityComponent :
149+ public AccessibilityEntity
150+{
151+ public:
152+ typedef boost::shared_ptr<AccessibilityComponent> Ptr;
153+
154+ AccessibilityComponent (AtspiAccessible *);
155+
156+ virtual AccessibilityComponent *
157+ clone () const;
158+
159+ CompRect
160+ getExtents () const;
161+
162+ CompPoint
163+ getPosition () const;
164+
165+ CompPoint
166+ getSize () const;
167+
168+ virtual IfaceType
169+ is ();
170+
171+ /* TODO: Implement based in a compiz layer type.
172+ CompLayer
173+ getLayer ();
174+ */
175+ protected:
176+ AtspiComponent *component;
177+};
178+
179+class AccessibilityText :
180+ public AccessibilityEntity
181+{
182+ public:
183+ typedef boost::shared_ptr<AccessibilityText> Ptr;
184+
185+ AccessibilityText (AtspiAccessible *);
186+
187+ virtual AccessibilityText *
188+ clone () const;
189+
190+ CompRect
191+ getCharacterExtents (int) const;
192+
193+ CompRect
194+ getRangeExtents (int) const;
195+
196+ int
197+ getCaretOffset ();
198+
199+ virtual IfaceType
200+ is ();
201+
202+ protected:
203+ AtspiText *text;
204+};
205+
206+class AccessibleObject
207+{
208+ public:
209+ typedef std::vector <AccessibilityEntity::Ptr> Entities;
210+ typedef std::vector <IfaceType> Interfaces;
211+
212+ AccessibleObject (AtspiAccessible *);
213+
214+ AccessibleObject::Entities
215+ create (AtspiAccessible *);
216+
217+ AccessibilityEntity::Ptr
218+ get (IfaceType);
219+
220+ bool
221+ is (IfaceType);
222+
223+ AccessibilityEntity::Ptr
224+ getEntity (IfaceType);
225+
226+ private:
227+ AccessibilityEntity::Ptr
228+ instantiate (AtspiAccessible *, IfaceType);
229+
230+ static IfaceType
231+ enumFromStr (const char *);
232+
233+ int
234+ getIfaceIndex (IfaceType);
235+
236+ private:
237+ Entities ents;
238+ Interfaces interfaces;
239+ AtspiAccessible * obj;
240+};
241+
242+class AccessibilityEvent
243+{
244+ public:
245+ AccessibilityEvent (const AtspiEvent *);
246+ ~AccessibilityEvent ();
247+
248+ const char *
249+ getType ();
250+
251+ AccessibleObject *
252+ getAccessibleObject ();
253+
254+ private:
255+ const AtspiEvent *event;
256+ AccessibleObject *object;
257+
258+};
259+
260+typedef boost::function<void (AccessibilityEvent *)> AccessibilityEventCallback;
261+
262+class Accessibility
263+{
264+ public:
265+
266+ Accessibility ();
267+ ~Accessibility ();
268+
269+ bool
270+ start ();
271+
272+ bool
273+ stop ();
274+
275+ bool
276+ active ();
277+
278+ bool
279+ registerEventHandler (const char *, AccessibilityEventCallback);
280+
281+ void
282+ unregisterAll ();
283+
284+ friend class AccessibilityScreen;
285+};
286+
287+#endif // _ACCESSIBILITY_H
288
289=== added directory 'plugins/accessibility/src'
290=== added file 'plugins/accessibility/src/accessibility.cpp'
291--- plugins/accessibility/src/accessibility.cpp 1970-01-01 00:00:00 +0000
292+++ plugins/accessibility/src/accessibility.cpp 2012-06-23 15:04:23 +0000
293@@ -0,0 +1,651 @@
294+/*
295+ * Compiz Accessibility PLugin
296+ *
297+ * Copyright (c) 2011 F123 Consulting & Mais Diferenças
298+ *
299+ * This program is free software; you can redistribute it and/or
300+ * modify it under the terms of the GNU General Public License
301+ * as published by the Free Software Foundation; either version 2
302+ * of the License, or (at your option) any later version.
303+ *
304+ * This program is distributed in the hope that it will be useful,
305+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
306+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
307+ * GNU General Public License for more details.
308+ *
309+ * Author: Alejandro Leiva <aleiva@emergya.com>
310+ *
311+ */
312+
313+#include "private.h"
314+
315+COMPIZ_PLUGIN_20090315 (accessibility, AccessibilityPluginVTable);
316+
317+AccessibleObject::AccessibleObject (AtspiAccessible *object)
318+{
319+ compLogMessage ("Accessibility", CompLogLevelInfo,
320+ "AccessibleObject::AccessibleObject (%s)\n", object->name);
321+
322+ obj = object;
323+
324+ create (object);
325+}
326+
327+AccessibleObject::Entities
328+AccessibleObject::create (AtspiAccessible *object)
329+{
330+ GArray * ifaces = atspi_accessible_get_interfaces (object);
331+
332+ int len = (int) ifaces->len;
333+
334+ for (int i = 0; i < len; i++)
335+ {
336+
337+ char *iface = (char *) g_array_index (ifaces, gchar *, i);
338+
339+ interfaces.push_back (enumFromStr (iface));
340+ // Defer the creation of the AccessibilityEntity structure.
341+ // TODO: Create a new method to create it from AccessibleObject.
342+ //ents.push_back (instantiate (object, iface));
343+ }
344+
345+ g_array_free (ifaces, TRUE);
346+
347+ return ents;
348+}
349+
350+AccessibilityEntity::Ptr
351+AccessibleObject::instantiate (AtspiAccessible *object, IfaceType iface)
352+{
353+ AccessibilityEntity::Ptr entity;
354+
355+ switch (iface)
356+ {
357+
358+ case Component:
359+ entity = AccessibilityEntity::Ptr (new AccessibilityComponent (object));
360+ break;
361+
362+ case Text:
363+ entity = AccessibilityEntity::Ptr (new AccessibilityText (object));
364+ break;
365+
366+ case Accessible:
367+ case Action:
368+ case Collection:
369+ case Document:
370+ case EditableText:
371+ case Hypertext:
372+ case Hyperlink:
373+ case Image:
374+ case Selection:
375+ case Table:
376+ case Value:
377+ break;
378+
379+ default:
380+ entity = AccessibilityEntity::Ptr (new AccessibilityEntity (object));
381+ }
382+
383+ return entity;
384+}
385+
386+IfaceType
387+AccessibleObject::enumFromStr (const char *str)
388+{
389+
390+ for (int i = 0; i < NUM_IFACES_SUPPORTED; i++)
391+ if (!strcmp (IfaceTypeStr[i], str))
392+ return (IfaceType) i;
393+
394+ return Accessible;
395+}
396+
397+AccessibilityEntity::Ptr
398+AccessibleObject::get (IfaceType type)
399+{
400+ int index = getIfaceIndex (type);
401+ compLogMessage ("Accessibility", CompLogLevelInfo, "AccessibleObject::get(%s) = %d\n",
402+ type, index);
403+
404+ if (index < 0)
405+ return AccessibilityEntity::Ptr ();
406+
407+ return ents[index];
408+}
409+
410+bool
411+AccessibleObject::is (IfaceType type)
412+{
413+ int index = getIfaceIndex (type);
414+
415+ if (index < 0)
416+ return false;
417+
418+ return true;
419+}
420+
421+int
422+AccessibleObject::getIfaceIndex (IfaceType type)
423+{
424+ for (int i = 0; i < (int) interfaces.size(); i++)
425+ {
426+ if (type == interfaces[i])
427+ return i;
428+ }
429+
430+ return -1;
431+}
432+
433+AccessibilityEntity::Ptr
434+AccessibleObject::getEntity (IfaceType type)
435+{
436+ return instantiate (obj, type);
437+}
438+
439+
440+AccessibilityEntity::AccessibilityEntity (AtspiAccessible *object)
441+{
442+ obj = object;
443+}
444+
445+AccessibilityEntity::~AccessibilityEntity () {
446+
447+}
448+
449+bool
450+AccessibilityEntity::load (AtspiAccessible *object)
451+{
452+ return true;
453+}
454+
455+bool
456+AccessibilityEntity::contains (AccessibilityEntity *entity, int x, int y)
457+{
458+ return true;
459+}
460+
461+IfaceType
462+AccessibilityEntity::is ()
463+{
464+ return Accessible;
465+}
466+
467+AccessibilityEntity *
468+AccessibilityEntity::clone () const
469+{
470+ return new AccessibilityEntity (obj);
471+}
472+
473+AtspiAccessible *
474+AccessibilityEntity::getObject () {
475+ return obj;
476+}
477+
478+
479+AccessibilityComponent::AccessibilityComponent (AtspiAccessible *obj) :
480+ AccessibilityEntity (obj)
481+{
482+ compLogMessage ("Accessibility", CompLogLevelInfo,
483+ "AccessibilityComponent::AccessibilityComponent (%s)\n", obj->name);
484+
485+ component = atspi_accessible_get_component (obj);
486+}
487+
488+AccessibilityComponent *
489+AccessibilityComponent::clone () const
490+{
491+ return new AccessibilityComponent (obj);
492+}
493+
494+CompRect
495+AccessibilityComponent::getExtents () const
496+{
497+ CompRect rect;
498+ GError *error = NULL;
499+
500+ AtspiRect *component_rect =
501+ atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, &error);
502+
503+ if (!component_rect)
504+ g_error_free (error);
505+ else
506+ rect = CompRect (component_rect->x,
507+ component_rect->y,
508+ component_rect->width,
509+ component_rect->height);
510+
511+ return rect;
512+}
513+
514+CompPoint
515+AccessibilityComponent::getPosition () const
516+{
517+ CompPoint position;
518+ GError *error = NULL;
519+
520+ AtspiPoint *component_position =
521+ atspi_component_get_position (component, ATSPI_COORD_TYPE_SCREEN, &error);
522+
523+ if (!component_position)
524+ g_error_free (error);
525+ else
526+ position = CompPoint (component_position->x, component_position->y);
527+
528+ return position;
529+}
530+
531+CompPoint
532+AccessibilityComponent::getSize () const
533+{
534+ CompPoint size;
535+ GError *error = NULL;
536+
537+ AtspiPoint *component_size = atspi_component_get_size (component, &error);
538+
539+ if (!component_size)
540+ g_error_free (error);
541+ else
542+ size = CompPoint (component_size->x, component_size->y);
543+
544+ return size;
545+}
546+
547+IfaceType
548+AccessibilityComponent::is ()
549+{
550+ return Component;
551+}
552+
553+
554+AccessibilityText::AccessibilityText (AtspiAccessible *obj) :
555+ AccessibilityEntity (obj)
556+{
557+ compLogMessage ("Accessibility", CompLogLevelInfo,
558+ "AccessibilityText::AccessibilityText (%s)\n", obj->name);
559+
560+ text = atspi_accessible_get_text (obj);
561+}
562+
563+AccessibilityText *
564+AccessibilityText::clone () const
565+{
566+ return new AccessibilityText (obj);
567+}
568+
569+CompRect
570+AccessibilityText::getCharacterExtents (int offset) const
571+{
572+ CompRect rect;
573+ GError *error = NULL;
574+
575+ AtspiRect *character_rect = atspi_text_get_character_extents
576+ (text, offset, ATSPI_COORD_TYPE_SCREEN, &error);
577+
578+ if (!character_rect)
579+ g_error_free (error);
580+ else
581+ rect = CompRect (character_rect->x,
582+ character_rect->y,
583+ character_rect->width,
584+ character_rect->height);
585+
586+ return rect;
587+}
588+
589+CompRect
590+AccessibilityText::getRangeExtents (int offset) const
591+{
592+ CompRect rect;
593+ GError *error = NULL;
594+
595+ AtspiRect *range_rect = atspi_text_get_range_extents
596+ (text, 0, 0, ATSPI_COORD_TYPE_SCREEN, &error);
597+
598+ if (!range_rect)
599+ g_error_free (error);
600+ else
601+ rect = CompRect (range_rect->x,
602+ range_rect->y,
603+ range_rect->width,
604+ range_rect->height);
605+
606+ return rect;
607+}
608+
609+int
610+AccessibilityText::getCaretOffset ()
611+{
612+ GError *error = NULL;
613+
614+ int caret_offset = atspi_text_get_caret_offset (text, &error);
615+
616+ if (!caret_offset)
617+ g_error_free (error);
618+
619+ return caret_offset;
620+}
621+
622+IfaceType
623+AccessibilityText::is ()
624+{
625+ return Text;
626+}
627+
628+
629+Accessibility::Accessibility ()
630+{
631+ compLogMessage ("Accessibility", CompLogLevelInfo,
632+ "Accessibility constructor called.\n");
633+
634+}
635+
636+Accessibility::~Accessibility ()
637+{
638+ compLogMessage ("Accessibility", CompLogLevelInfo,
639+ "Accessibility destructor called.\n");
640+
641+}
642+
643+bool
644+Accessibility::start ()
645+{
646+ return true;
647+}
648+
649+bool
650+Accessibility::stop ()
651+{
652+ return true;
653+}
654+
655+bool
656+Accessibility::active ()
657+{
658+ return true;
659+}
660+
661+bool
662+Accessibility::registerEventHandler (const char *event_type, AccessibilityEventCallback cb)
663+{
664+ ACCESSIBILITY_SCREEN (screen);
665+
666+ as->registerEventHandler (event_type, cb);
667+
668+ return true;
669+}
670+
671+void
672+Accessibility::unregisterAll ()
673+{
674+ ACCESSIBILITY_SCREEN (screen);
675+
676+ as->unregisterAll ();
677+}
678+
679+void
680+staticAccessibilityEventCallback (const AtspiEvent *event)
681+{
682+ if (!event)
683+ return;
684+
685+ ACCESSIBILITY_SCREEN (screen);
686+
687+ AccessibilityHandlerList list = as->list;
688+
689+ std::list<AccessibilityHandler *>::iterator it;
690+
691+ AccessibilityEvent *e = new AccessibilityEvent (event);
692+
693+ for (it = list.begin (); it != list.end (); it++)
694+ {
695+ const char * target_type = (*it)->event_type;
696+
697+ if (strncmp (target_type, event->type, strlen(target_type)) == 0)
698+ {
699+ compLogMessage ("Accessibility", CompLogLevelInfo,
700+ "Delegating (%s) to -> functor [%d][%s]\n",
701+ event->type,
702+ (*it)->id, (*it)->event_type);
703+
704+ (*it)->cb (e);
705+ }
706+ }
707+
708+ delete (e);
709+}
710+
711+void
712+staticAccessibilityEventDestroyCallback (void *data)
713+{
714+ ACCESSIBILITY_SCREEN (screen);
715+
716+ AccessibilityHandlerList list = as->list;
717+
718+ std::list<AccessibilityHandler *>::iterator it;
719+
720+ for (it = list.begin (); it != list.end (); it++)
721+ {
722+ compLogMessage ("Accessibility", CompLogLevelInfo,
723+ "Delegating destroy to -> functor [%d][%s]\n",
724+ (*it)->id);
725+ // TODO: Implement callback mechanism for handles destroy.
726+ }
727+}
728+
729+AccessibilityEvent::AccessibilityEvent (const AtspiEvent *event)
730+{
731+ this->event = event;
732+ this->object = new AccessibleObject (event->source);
733+}
734+
735+AccessibilityEvent::~AccessibilityEvent ()
736+{
737+ delete (event);
738+ delete (object);
739+}
740+
741+const char *
742+AccessibilityEvent::getType ()
743+{
744+ return event->type;
745+}
746+
747+AccessibleObject *
748+AccessibilityEvent::getAccessibleObject ()
749+{
750+ return object;
751+}
752+
753+AccessibilityEventHandler
754+AccessibilityScreen::registerEventHandler (const char *event_type,
755+ AccessibilityEventCallback cb)
756+{
757+
758+ AccessibilityHandler *hnd = new AccessibilityHandler ();
759+
760+ if (!hnd)
761+ return 0;
762+
763+ if (!event_type || !cb)
764+ return 0;
765+
766+ // Create event listeners
767+ GError *error = NULL;
768+
769+ AtspiEventListener *event_listener =
770+ atspi_event_listener_new_simple (staticAccessibilityEventCallback,
771+ staticAccessibilityEventDestroyCallback);
772+
773+ if (!atspi_event_listener_register (event_listener, event_type, &error))
774+ {
775+ compLogMessage ("Accessibility", CompLogLevelInfo,
776+ "Cannot create event listener (%s). [%s]\n",
777+ event_type,
778+ error->message);
779+
780+ g_error_free (error);
781+ error = NULL;
782+ }
783+
784+ hnd->event_type = event_type;
785+ hnd->event_listener = event_listener;
786+ hnd->cb = cb;
787+ hnd->id = lastEventHandler++;
788+
789+ list.push_front (hnd);
790+
791+ compLogMessage ("Accessibility", CompLogLevelInfo, "Registered new listener (%d): (%s))\n", hnd->id, hnd->event_type);
792+
793+ return hnd->id;
794+}
795+
796+void
797+AccessibilityScreen::unregisterEventHandler (AccessibilityEventHandler handler)
798+{
799+
800+ std::list<AccessibilityHandler *>::iterator it;
801+ AccessibilityHandler *h;
802+
803+ if (list.size() < 0)
804+ return;
805+
806+ for (it = list.begin (); it != list.end (); it++)
807+ if ((*it)->id == handler)
808+ break;
809+
810+ if (it == list.end ())
811+ return;
812+
813+ // Unregister event.
814+ GError *error = NULL;
815+
816+ if (!atspi_event_listener_deregister ((*it)->event_listener, (*it)->event_type, &error))
817+ {
818+ compLogMessage ("Accessibility", CompLogLevelInfo,
819+ "Cannot unregister event listener (%s). [%s]\n",
820+ (*it)->event_type,
821+ error->message);
822+
823+ g_error_free (error);
824+ error = NULL;
825+ }
826+
827+ // Free and erase from the list.
828+ h = (*it);
829+ delete (h);
830+
831+ list.erase (it);
832+}
833+
834+
835+bool
836+AccessibilityScreen::unregisterByType (const char * event_type)
837+{
838+ //TODO
839+ return true;
840+}
841+
842+void
843+AccessibilityScreen::unregisterAll ()
844+{
845+ std::list<AccessibilityHandler *>::iterator it;
846+
847+ if (list.size () < 0)
848+ return;
849+
850+ for (it = list.begin (); it != list.end (); it++)
851+ {
852+ unregisterEventHandler ((*it)->id);
853+ }
854+}
855+
856+void
857+AccessibilityScreen::handleAccessibilityEvent (AccessibilityEvent *event)
858+{
859+
860+ AccessibleObject *object = event->getAccessibleObject ();
861+
862+ if (object->is (Component))
863+ {
864+
865+ AccessibilityComponent::Ptr ac =
866+ boost::static_pointer_cast<AccessibilityComponent>
867+ (object->getEntity (Component));
868+
869+ CompRect rect = ac->getExtents ();
870+
871+ compLogMessage ("Accessibility", CompLogLevelInfo, "Object is Component\n");
872+
873+ compLogMessage ("Accessibility", CompLogLevelInfo,
874+ "Component Area [%d, %d] [%d, %d]\n",
875+ rect.x1(), rect.y1(), rect.x2(), rect.y2());
876+ }
877+ else
878+ {
879+
880+ compLogMessage ("Accessibility", CompLogLevelInfo, "Object is NOT Component\n");
881+ }
882+}
883+
884+AccessibilityScreen::AccessibilityScreen (CompScreen *screen) :
885+ PluginClassHandler <AccessibilityScreen, CompScreen> (screen),
886+ screen (screen),
887+ lastEventHandler (0)
888+{
889+ compLogMessage ("Accessibility", CompLogLevelInfo,
890+ "AccessibilityScreen called.\n");
891+
892+ /* TODO: Check atspi_init() code. There's a memory leak when registryd
893+ * isn't running.
894+ */
895+ int atspi_status = atspi_init ();
896+
897+ compLogMessage ("Accessibility", CompLogLevelInfo,
898+ "AccessibilityScreen: AT-SPI init() %d.\n", atspi_status);
899+
900+ /*
901+ registerEventHandler ("object:state-changed:", boost::bind (
902+ &AccessibilityScreen::handleAccessibilityEvent, this, _1));
903+ */
904+
905+ compLogMessage ("Accessibility", CompLogLevelInfo, "Running!\n");
906+
907+ /*
908+ // Launch main event atspi loop
909+ // This is not needed because compiz private screen launches its own
910+ // Glib MainLoop
911+ */
912+ /*
913+
914+ atspi_event_main();
915+ */
916+}
917+
918+AccessibilityScreen::~AccessibilityScreen ()
919+{
920+
921+ unregisterAll ();
922+
923+ //atspi_event_quit();
924+ int atspi_status = atspi_exit ();
925+
926+ compLogMessage ("Accessibility", CompLogLevelInfo,
927+ "~AccessibilityScreen called. Exit value: %d\n", atspi_status);
928+}
929+
930+bool
931+AccessibilityPluginVTable::init ()
932+{
933+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
934+ {
935+ compLogMessage ("Accessibility", CompLogLevelInfo,
936+ "compiz core not in sync.\n");
937+ return false;
938+ }
939+
940+ compLogMessage ("Accessibility", CompLogLevelInfo,
941+ "Running Accessibility plugin.\n");
942+
943+ return true;
944+}
945
946=== added file 'plugins/accessibility/src/private.h'
947--- plugins/accessibility/src/private.h 1970-01-01 00:00:00 +0000
948+++ plugins/accessibility/src/private.h 2012-06-23 15:04:23 +0000
949@@ -0,0 +1,113 @@
950+/*
951+ * Compiz Accessibility PLugin
952+ *
953+ * Copyright (c) 2011 F123 Consulting & Mais Diferenças
954+ *
955+ * This program is free software; you can redistribute it and/or
956+ * modify it under the terms of the GNU General Public License
957+ * as published by the Free Software Foundation; either version 2
958+ * of the License, or (at your option) any later version.
959+ *
960+ * This program is distributed in the hope that it will be useful,
961+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
962+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
963+ * GNU General Public License for more details.
964+ *
965+ * Author: Alejandro Leiva <aleiva@emergya.com>
966+ *
967+ */
968+
969+#include <vector>
970+#include <cstring>
971+
972+#include <boost/shared_ptr.hpp>
973+
974+#include <core/core.h>
975+#include <core/pluginclasshandler.h>
976+
977+#include <glibmm/main.h>
978+
979+#include <accessibility/accessibility.h>
980+#include "accessibility_options.h"
981+
982+static const char *IfaceTypeStr[] =
983+{
984+ "Accessible",
985+ "Action",
986+ "Collection",
987+ "Component",
988+ "Document",
989+ "EditableText",
990+ "Hypertext",
991+ "Hyperlink",
992+ "Image",
993+ "Selection",
994+ "Table",
995+ "Text",
996+ "Value",
997+};
998+
999+#define NUM_IFACES_SUPPORTED 13
1000+
1001+typedef int AccessibilityEventHandler;
1002+
1003+/* Struct of a handler and list of handlers */
1004+struct AccessibilityHandler {
1005+ const char * event_type;
1006+ AtspiEventListener * event_listener;
1007+ AccessibilityEventCallback cb;
1008+ AccessibilityEventHandler id;
1009+};
1010+
1011+typedef std::list<AccessibilityHandler *> AccessibilityHandlerList;
1012+
1013+class AccessibilityScreen :
1014+ public PluginClassHandler <AccessibilityScreen, CompScreen>,
1015+ public ScreenInterface,
1016+ public AccessibilityOptions
1017+{
1018+ public:
1019+
1020+ AccessibilityScreen (CompScreen *);
1021+ ~AccessibilityScreen ();
1022+
1023+ CompScreen *screen;
1024+
1025+ AccessibilityEventHandler
1026+ registerEventHandler (const char * event_type,
1027+ AccessibilityEventCallback cb);
1028+
1029+ void
1030+ unregisterEventHandler (AccessibilityEventHandler handler);
1031+
1032+ bool
1033+ unregisterByType (const char * event_type);
1034+
1035+ void
1036+ unregisterAll ();
1037+
1038+ void
1039+ handleAccessibilityEvent (AccessibilityEvent *);
1040+
1041+ public:
1042+
1043+ AccessibilityHandlerList list;
1044+ int lastEventHandler;
1045+
1046+ protected:
1047+
1048+ AtspiEventListener *listener;
1049+
1050+};
1051+
1052+#define ACCESSIBILITY_SCREEN(s) \
1053+ AccessibilityScreen *as = AccessibilityScreen::get (s)
1054+
1055+class AccessibilityPluginVTable :
1056+ public CompPlugin::VTableForScreen <AccessibilityScreen>
1057+{
1058+ public:
1059+
1060+ bool init();
1061+
1062+};
1063
1064=== modified file 'plugins/ezoom/CMakeLists.txt'
1065--- plugins/ezoom/CMakeLists.txt 2012-05-16 17:40:27 +0000
1066+++ plugins/ezoom/CMakeLists.txt 2012-06-23 15:04:23 +0000
1067@@ -2,4 +2,4 @@
1068
1069 include (CompizPlugin)
1070
1071-compiz_plugin (ezoom PLUGINDEPS composite opengl mousepoll)
1072+compiz_plugin (ezoom PLUGINDEPS composite opengl mousepoll accessibility PKGDEPS atspi-2)
1073
1074=== modified file 'plugins/ezoom/ezoom.xml.in'
1075--- plugins/ezoom/ezoom.xml.in 2012-05-16 17:40:27 +0000
1076+++ plugins/ezoom/ezoom.xml.in 2012-06-23 15:04:23 +0000
1077@@ -6,6 +6,7 @@
1078 <plugin>opengl</plugin>
1079 <plugin>expo</plugin>
1080 <plugin>decor</plugin>
1081+ <plugin>accessibility</plugin>
1082 </relation>
1083 <relation type="before">
1084 <plugin>staticswitcher</plugin>
1085@@ -14,6 +15,7 @@
1086 <requirement>
1087 <plugin>opengl</plugin>
1088 <plugin>mousepoll</plugin>
1089+ <plugin>accessibility</plugin>
1090 </requirement>
1091 </deps>
1092 <_short>Enhanced Zoom Desktop</_short>
1093
1094=== modified file 'plugins/ezoom/src/ezoom.cpp'
1095--- plugins/ezoom/src/ezoom.cpp 2012-05-18 06:52:20 +0000
1096+++ plugins/ezoom/src/ezoom.cpp 2012-06-23 15:04:23 +0000
1097@@ -604,6 +604,12 @@
1098 mouse = MousePoller::getCurrentPosition ();
1099 }
1100
1101+void
1102+EZoomScreen::enableAccessibility ()
1103+{
1104+ ;
1105+}
1106+
1107 /* Sets the zoom (or scale) level.
1108 * Cleans up if we are suddenly zoomed out.
1109 */
1110@@ -1790,6 +1796,62 @@
1111 screen->handleEvent (event);
1112 }
1113
1114+void
1115+EZoomScreen::handleAccessibilityEvent (AccessibilityEvent *event)
1116+{
1117+ AccessibleObject *object = event->getAccessibleObject ();
1118+
1119+ compLogMessage ("EZoom", CompLogLevelInfo,
1120+ "event->type: %s\n", event->getType());
1121+
1122+ if (object->is (Component))
1123+ {
1124+
1125+ AccessibilityComponent::Ptr ac =
1126+ boost::static_pointer_cast<AccessibilityComponent>
1127+ (object->getEntity (Component));
1128+
1129+ CompRect rect = ac->getExtents ();
1130+
1131+ compLogMessage ("Ezoom", CompLogLevelInfo,
1132+ "ensureVisibilityArea [%d, %d] [%d, %d]\n",
1133+ rect.x1(), rect.y1(), rect.x2(), rect.y2());
1134+
1135+ if (optionGetZoomMode () == EzoomOptions::ZoomModePanArea)
1136+ {
1137+ ensureVisibilityArea (rect.x1(),
1138+ rect.y1(),
1139+ rect.x2(),
1140+ rect.y2(),
1141+ optionGetRestrainMargin (),
1142+ NORTHWEST);
1143+ }
1144+ }
1145+
1146+ if (object->is (Text))
1147+ {
1148+ AccessibilityText::Ptr at =
1149+ boost::static_pointer_cast<AccessibilityText>
1150+ (object->getEntity (Text));
1151+
1152+ CompRect rect = at->getCharacterExtents (at->getCaretOffset ());
1153+
1154+ compLogMessage ("Ezoom", CompLogLevelInfo,
1155+ "TEXT - [%d, %d] [%d, %d]\n",
1156+ rect.x1(), rect.y1(), rect.x2(), rect.y2());
1157+
1158+ if (optionGetZoomMode () == EzoomOptions::ZoomModePanArea)
1159+ {
1160+ ensureVisibilityArea (rect.x1(),
1161+ rect.y1(),
1162+ rect.x2(),
1163+ rect.y2(),
1164+ optionGetRestrainMargin (),
1165+ NORTHWEST);
1166+ }
1167+ }
1168+}
1169+
1170 /* TODO: Use this ctor carefully */
1171
1172 EZoomScreen::CursorTexture::CursorTexture () :
1173@@ -1866,6 +1928,12 @@
1174 pollHandle.setCallback (boost::bind (
1175 &EZoomScreen::updateMouseInterval, this, _1));
1176
1177+ a11yHandle = new Accessibility();
1178+ a11yHandle->registerEventHandler ("object:state-changed", boost::bind (
1179+ &EZoomScreen::handleAccessibilityEvent, this, _1));
1180+ a11yHandle->registerEventHandler ("object:text-changed", boost::bind (
1181+ &EZoomScreen::handleAccessibilityEvent, this, _1));
1182+
1183 optionSetZoomInButtonInitiate (boost::bind (&EZoomScreen::zoomIn, this, _1,
1184 _2, _3));
1185 optionSetZoomOutButtonInitiate (boost::bind (&EZoomScreen::zoomOut, this, _1,
1186@@ -1926,6 +1994,9 @@
1187 if (pollHandle.active ())
1188 pollHandle.stop ();
1189
1190+ if (a11yHandle->active ())
1191+ a11yHandle->unregisterAll ();
1192+
1193 if (zooms.size ())
1194 zooms.clear ();
1195
1196
1197=== modified file 'plugins/ezoom/src/ezoom.h'
1198--- plugins/ezoom/src/ezoom.h 2010-10-25 02:23:36 +0000
1199+++ plugins/ezoom/src/ezoom.h 2012-06-23 15:04:23 +0000
1200@@ -44,6 +44,7 @@
1201 #include <composite/composite.h>
1202 #include <opengl/opengl.h>
1203 #include <mousepoll/mousepoll.h>
1204+#include <accessibility/accessibility.h>
1205
1206
1207 #include "ezoom_options.h"
1208@@ -184,6 +185,8 @@
1209
1210 MousePoller pollHandle; // mouse poller object
1211
1212+ Accessibility *a11yHandle; // Accessibility object
1213+
1214 private:
1215
1216 bool fixesSupported;
1217@@ -212,6 +215,9 @@
1218 void
1219 handleEvent (XEvent *);
1220
1221+ void
1222+ handleAccessibilityEvent (AccessibilityEvent *event);
1223+
1224 public:
1225
1226 int
1227@@ -250,6 +256,9 @@
1228 void
1229 enableMousePolling ();
1230
1231+ void
1232+ enableAccessibility ();
1233+
1234 void
1235 setScale (int out, float value);
1236
1237
1238=== modified file 'plugins/mousepoll/mousepoll.xml.in'
1239--- plugins/mousepoll/mousepoll.xml.in 2012-05-16 17:43:36 +0000
1240+++ plugins/mousepoll/mousepoll.xml.in 2012-06-23 15:04:23 +0000
1241@@ -16,7 +16,7 @@
1242 <option type="int" name="mouse_poll_interval">
1243 <_short>Mouse Poll Interval</_short>
1244 <_long>How often to poll the mouse position, in miliseconds. Reduce this to reduce choppy behavior.</_long>
1245- <default>40</default>
1246+ <default>10</default>
1247 <min>1</min>
1248 <max>500</max>
1249 </option>

Subscribers

People subscribed via source and target branches