Foreword

Since epiphany is moving away from Gecko, this page will likely be unmaintained for quite some time. Hopefully, that extension will then get ported to WebKit.

Goal

Make epiphany able to emphasize some shortcuts to ease the navigation through the links of a given page, so that it becomes possible to access them with a single key, instead of a bunch of TAB hits. The goal is to clone konqueror's Control key behaviour.

Definition

The term hotkey will be preferred to accesskey, which is defined by the W3 Consortium, but looks like mostly unsupported. This term might be changed as soon as a better one is found.

Documentation

Many links are available.

Plans

As an epiphany extension as much as possible, but it looks like needed to add some code in epiphany too. It seems that there's no way to catch key presses in the embed mozilla widget, so that would have to be added (probably in embed/).

According to the GtkMozEmbed signal reference there are no mouse click callbacks, but there are in EphyEmbed signal reference: ge-dom-mouse-click and ge-dom-mouse-down. So it should be possible to add something like ge-dom-key-down, so as to determine the pressed key.

Once it is done, the proposed way is the following: On Ctrl press, the accessibility mode is toggled. Off by default, when it turns to on, the DOM is modified so as to emphasize some given characters in the links, possibly using the first letter of each, but also avoiding hotkey collision. To ease customization, using a span tag could be use at least at the beginning, so that changing a bit of CSS is sufficient to have a nice display. When it is switch back to off, a simple way to remove the added information would be to reload the page, which would flush this.

At the moment, a javascript DOM modification is quite easy, based on the one published by Christian Schmidt, but it would be better to do it on epiphany side, so that the hotkey—URL mapping is kept where it is computed. This javascript basic implementation could still be used until the key handling is implemented, so as to get an overview.

Progress

Key presses

In embed/mozilla/mozilla-embed.cpp, the following mapping happens:

So it looks that no modification to the mozilla code in epiphany is needed. There's still a need of exposing an additional signal in epiphany.

Key presses (bis)

Just grep in epiphany-extensions for key-press | key_press, and here it is:

/* Prototype taken from ephy-gesture.c */
static gboolean
dom_key_press_cb (GtkWidget *widget,
                  GdkEventKey *event,
                  EphySample2Extension *extension)

Unfortunately, it looks like it is not possible to receive the events when the focus is in an input text field, but that sounds like a good start.

Now let's work on epiphany-extensions only, using sample-mozilla as a basis: git repository.

Proposed behaviour

h enables the hotkeys, Esc then disables them. Once enabled, if a key is pressed, an eventual mapping is checked. If it's mapped, load the link in the embed, if not, ignore it.

To store the mapping, the proposed structure is proposed: a linked list of structures, containing: an guint (the key value), the old nsIDOMHTMLLinkElement (backuped so that it can be restored once the hotkeys are disabled), and the new nsIDOMHTMLLinkElement (which could be replaced by a const char*, being the URL to load.

At the beginning, restoring the old nsIDOMHTMLLinkElement could be ignored.

At the beginning, when a hotkey matches several times, the first occurrence is considered. Then, one could consider having a cycling through all occurrences until Enter is pressed, and a direct loading when there's only one occurrence. Another way is to use additional keys, as konqueror does, but that means additional code to pick the right one.

Browse the DOM to find the Anchors

It is done by getting the DOM toplevel, then querying each node, checking the Anchor (and not Link) ones, and modifying them, while keeping a copy of them, so that they can be restored once the hotkeys are disabled.

Here is an example of hotkeys enabled on http://www.google.fr/ with an hardcoded (quick & dirty) CSS style:

Google — Example 1

0.1 release

As of this release (git tag), it is possible to enable/disable the hotkeys using h/Esc, and to browse the links on a first matching occurrence basis.

Next step: make it possible to browse the links when there are multiple key value occurrences, use only uppercase characters.

Proposed implementations:

  1. When there's only a match, load the link directly. When there are several matches, cycle through them, and only link when Enter is pressed.

  2. When there are multiple matches, try and use another character of the link for the next occurrences. The implementation using GSList * could be a bit inefficient, beware. Also, what kind of character to use when all characters are already taken? A bit harder, left for later.

Later goals:

Unicode handling, uppercase

The following functions are used to determine the key value to store/look for.

Later...

Maybe update the statusbar when there are several links, explaining one has to use Enter to validate the current link.

Note to self

Don't forget to copy the objects passed to g_hash_table_insert, especially if they are integers.

As of 0.2

[Fixed] Troubles with some pages, e.g. on http://news.google.fr/, but might be unrelated to the number of links, though.

[Fixed] When going back and forth, the extension toggling appears to be buggy. Hooking another even might be sufficient to fix this.

An additional feature could be back-cycling, which could be achieved when Shift, which can be detected thanks to:

 guint state; a bit-mask representing the state of the modifier
 keys (e.g. Control, Shift and Alt) and the pointer buttons. See
 GdkModifierType.

Another alternative/configuration option

To have a visible emphasis, it is possible to call Focus() on the selected item, but the way it is focussed might be unpleasant. That's why it has been implemented the following way: Focus() is called so that the page scrolls to the appropriate location if needed, then Blur() is called so that there's no visible trace of the previsou Focus() call.

0.3 release

Just two things:

Next targets:

Known bug

Installation on debian sid (and maybe lenny)

Just do the following the first time:

git-clone git://git.debian.org/git/users/kibi-guest/epiphany-extensions.git
cd epiphany-extensions
DEB_BUILD_OPTIONS=nostrip debuild -us -uc -b -nc # Some Build-Depends may
                                                 # need to be installed.
sudo debi                  # Installs the generated binary package
pkill epiphany && epiphany # Then Tools>Extensions, and activate Hotkeys

To update:

cd extensions/hotkeys      # Or in the inverse order, not important
git-pull                   # Merge remote changes into local working copy
make                       # Optional, make install will call it if needed
sudo make install          # Update the .so in /usr/lib/epiphany/2.18
pkill epiphany && epiphany

0.4 release

Next features/TODOs

How to implement these features

  1. [Done] 1st target: first character isn't alphanum()

    a. Move to the next element. If it is '<', call continue (at least until the 2nd target is implemented).

    b. Otherwise, see whether that other character is alphanum(), then move to a if needed.

  2. 2nd target: nested element: If there are nested elements, dig further if there's only a hierarchy of modifier elements (b, i, strong, font), until... what?

    a. Maybe until InnerHTML doesn't contain any '<' anymore?

    b. Maybe until there's no more HTMLElement child(ren)?

Problems/remarks

[Done] What if a link contains entity-encoded characters? No problem since the InnerHTML string is encoded using HTML entities, so an opening ‘&’ should always match a closing ‘;’.

0.5 release

Idea to handle nested tags

To be able to handle the nested tags, it is of course possible to analyze the tree, but an alternative way could be used: when an < character is encountered, search for a matching >. The problem is that it might break on things like that:

<a href="/location"><img   src="someimage>.png"  >Foo</a>

which would result in having the p of png being defined as the hotkey, and the additional <span> being embedded in the src attribute. Hopefully such things get escaped (and extra spaces get munged):

<img src="someimage%3E.png">Foo</a>

Further tasks

0.6 release

Fetching the sources

It looks like it is not possible to mix git-svn and git-fetch… Well, see the first post tagged epiphany.

0.7 release

Further ideas