Conduit and Accessibility

August 4th, 2008 by John Carr

This blog post is a friendly note to application maintainers out there to think carefully about how accessible your software is, especially when using non-standard widgets or canvases. Accessibility is important and it can also be hard. So think about it early and think about it often. Below are some notes from in the trenches, and if you think about a11y from the beginning things won’t end up this way for you.

One issue to rise out of the current module proposal discussion is Conduit and its accessibility. In order to be a good GNOME application, Conduit needs to be accessible. The use of a canvas to render shiny goodness manually means that we sacrifice lots of ready made accessibility.

Conduit has two major issues on the accessibility front. Can I control it without using a mouse? And can I tell what is happening when i’m using a screen reader? Sadly, the current answer is no and no. Having decided to change this, I’ve spent the weekend looking at how to pass more useful information to the accessibility infrastructure.

We use GooCanvas, which is actually already accessible. Each item that is added to the canvas is available to accessibility tools, be it a raw canvas item or a gtk widget. Basic information such as its size and position is exposed without any effort on the part of the application author. Whilst experimenting, I have hit the following limitations:

1. Without implementing more ATK interfaces, the only Conduit relevant information I can expose is a name and a description for each object. Its not easy to implement new interfaces without throwing away the existing interface. This is really quite limiting, and I don’t think it will make for a good enough user experience. (I don’t consider this a GooCanvas bug, but instead something that Conduit needs to fix on its own).

2. GooCanvas doesn’t seem to implement the children-changed signal. In testing this has meant that accerciser is unaware of changes on the canvas, and i’ve needed to keep restarting accerciser.

So GooCanvas needs a patch to fix children-changed. Lets defer that to later, i’ll look at it early in the next cycle. For now I need to work on fixing Conduit. Hopefully I can derive from the existing Goocanvas ATK objects and extend, as opposed to rewriting it all. Sadly not, the GooCanvas accessibility code isn’t available from python, so I need to re-implement everything. Again, potential patch to pygoocanvas deferred to early next cycle.

From reading the Devhelp for ATK, it seems that I just need to implement an atk.Object (and assorted interfaces) and an atk.ObjectFactory for each accessible GObject I want to have. So how do I implement an interface in python? My initial thought was that I would just have to derive from them:

>>> import gobject
>>> import atk
>>> class Foo(atk.Object, atk.Component):
...    def some_method(self, param):
...        pass
...

Is it enough?

>>> gobject.type_interfaces(Foo)
[]

GObject doesn’t seem to know that I want to implement an interface. So my code is not enough. After poking this for some time it turns out there are two fundamental pieces of fail with my first attempt.

At some point, pygtk claimed to automatically register things for me. In this case, maybe more generally, this is not the case. I need to register my class with the GObject type system:

>>> gobject.type_register(Foo)
>>> gobject.type_interfaces(Foo)
[<GType AtkComponent (136469760)>]

Victory! At this point I was hoping my code would spring to life, but it didn’t. Poke, poke, poke. When overriding a GObject method from python or implementing an interface you need a do_ prefix. Presumably this is to make the introspection foo a little less scary. So I needed:

>>> class Foo(atk.Object, atk.Component):
>>>    def do_some_method(self, param):
>>>       pass

Once you have implemented your accessible object, you need an accessible object factory, and you need to register it with the default ATK registry. I’m leaving some bits out here, but basically:

>>> class FooFactory(atk.ObjectFactory):
...     def do_create_accessible(self, obj):
...         return Foo(obj)
...
>>> gobject.type_register(FooFactory)
>>> atk.get_default_registry().set_factory_type(GooFoo, FooFactory)

Now when ATK encounters a GooFoo object it should ask FooFactory for an accessible version of it. It will get a new Foo object.

Unfortunately this is not what happens. !”£$. A new FooFactory is instanced, and then a GCritical fires, because create_accessible isn’t happening and something is then trying to ref a null. Sigh. Epic Fail. After examining pygtk, it turns out that the create_accessible method of atk is blacklisted when bindings are generated. I unblacklisted it and encountered a nice compile error. If you poke around (or ask Rob), you’ll see that create_accessible is defined without a self, its essentially a @staticmethod. This is an edge case that the code generator doesn’t currently handle, and the wrapper ends up trying to pass too many arguments. So now I need to figure out a suitable patch for pyatk (or the code generator) before I can continue…

Big thanks to Rob for helping me with this so far, your big chunk of clue has been most welcome. You can has beer.

The blinding past

July 25th, 2008 by John Carr

I lolled so hard. Thanks Rob.

Syncing my phone, its actually easy

July 25th, 2008 by John Carr

A few days ago, I saw a blog post highlighting how difficult it can be to sync a phone on the free desktop. For a battle hardened command line user, the steps aren’t that troubling (although that example looks easy compared to some of the setups i’ve seen). Regardless, I certainly wouldn’t want to put my parents through this experience.

In contrast, after a recent mishap with my phone, restoring its address book from Evolution was trivial with the copy of Conduit SVN I had kicking around.
Conduit and WM6

I started Conduit and plugged in my phone. It appeared on the left hand side of the screen, so I dragged it and the Evolution endpoints to the canvas, and I did a sync. My address book is back.

There is more UI love to go of course. SynCE automagicness is getting there, but we can make it even better. Plus, we love HAL, and the next step is to respond to new devices and say “Hey, I know how to deal with that thingy you just plugged in” and offer to sync to some sensible defaults (Evolution for PIM stuff, Tomboy for Notes, F-Spot for Photos, Banshee/Rhythmbox for Music). And of course, the next time I plug it in.. Just sync it. Never make me press the sync button again.

The blinding future is to use PackageKit to download extra support packages like SynCE and libgpod as needed, when you plug in the device.

Awesome Closing Party

July 13th, 2008 by John Carr

I still have Google Beer tokens (8 or so) lying around. And to my wrist are fastened 2 Electronica festival istanbul 2008 tags. Win.

Now to pack for home…

GUADEC Boat Party

July 11th, 2008 by John Carr

I cannot remember after a certain hour. If you can help fill in my memory, please say hi.

83% of statistics are made up on the spot

July 7th, 2008 by John Carr

Got up early for some healthy debate on the differences between Bazaar and Git at the DVCS Bof. Maybe the slot was changed when I wasn’t looking, but it turned into a “introduction to Git and Gitorious” presentation, with a packed audience. For a session meant to focus on DVCS in general, and how GNOME can move from SVN to $DVCS, it was a bit of a shame. BUT THEN…

There was a second smaller talk on DVCS that was slightly more productive. Neither side has managed to provide an action plan so far. When the Bazaar and the Git advocates can come to GNOME and say “we have a plan, this is how we are migrating and this is how we are going to fix all the systems that depend on GNOME”.. then we can talk. This whole issue needs some JFDI – we can’t cry/shout until our DVCS is picked, and then expect the sysadmins to take care of it.

On a lighter note, got some swag. Quite happy with the laptop bag, and the T-shirt is quite nice. Doesn’t match the codethink t-shirts though ;)

Now back to cleaning up the Git code so Rob doesn’t harm me.

Off To GUADEC

July 5th, 2008 by John Carr

Setting off for the airport soon. I arrive with codethink somewhere around 2AM local time on Sunday.

Looking forward to seeing John Stowers and maybe getting some Conduit hacking done. It would be cool to see some of the build brigade people and see if we can get build.gnome.org running the newest buildbot code, with a single master (instead of one per project). Theres a chance i’ll have to talk about libgitcore, and the joys horrors of Git coding. Oh and the scary DVCS discussion. It will be interesting to see who wears both a “I use Bazaar lots” *and* a “I use Git lots” badge.

And I heard something about whisky…

If there are any veggies or vegans coming, be sure to poke me and say hi, we can go track down some carrots together :-) Jc2k on IRC, or comment here. Failing that, look out for codethink t-shirts – I won’t be far away.

When mixing git-rebase and alcohol

July 4th, 2008 by John Carr

Always, always, always remember to

git-rebase --continue

Or strange confusing things happen, and if you don’t have experts on hand… FAIL.

(Needless to say, the silly little typo I was trying to rebase away made it into public history after all. Poo.)

Loggerhead + Search

June 26th, 2008 by John Carr

TWIB blogged about a little something we have been working on with the Bazaar guys. The Bazaar mirror now has loggerhead and search, based on the bzr-search plugin. This lets it search over the whole history of trunk. When beuno finishes skinning it i’ll integrate it in to the main site. In the mean time, enjoy.

Oh, it also shows off something I badly explained the other day. See here. Revision 5 was committed by myself, but bzr-svn also saved the –author property, attributing that code to Jelmer correctly.

Is speed the only reason?

June 26th, 2008 by John Carr

zeenix decided to quote me in a recent blog post. My remark was meant to be a light hearted jibe at our obsession with going over and over the same points but never getting anywhere. I failed, but it looks even worse out of context. So lets try this again.

We have ALL heard how Bazaar is so slow you might actually die of old age before you finish checking out your module, and that Git is so hard and voodoo ridden that you will erase your project from history and cause the universe to collapse if you use the wrong incantation.

Both of these arguments are nothing new. They are both very tired, and of questionable correctness in recent versions of both tools. Thats why I didn’t want to hear about them *again*. That doesn’t mean that they aren’t valid concerns, just that covering them again didn’t seem constructive.

As it happens, zeenix posted about how Git is fast. Now some interesting debate is happening over in the comments of that entry, so maybe my poor sense of humour did some good. Note that I never bothered to try and say Bazaar wasn’t slower because i thought it a waste of time and a good way to get flamed, but the people are now saying “hey, Bazaar is actually doing OK”. Yay.

In closing: people, please don’t get upset, i’d never waste my vodka over something like DVCS-wars! Now if this was vim vs emacs…