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
Control key behaviour.
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.
Many links are available.
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
According to the
GtkMozEmbed signal reference
there are no mouse click callbacks, but there are in
EphyEmbed signal reference:
ge-dom-mouse-down. So it should be possible
to add something like
ge-dom-key-down, so as to determine the
Once it is done, the proposed way is the following: On
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.
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
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
as a basis:
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
nsIDOMHTMLLinkElement (backuped so that it can be restored once
the hotkeys are disabled), and the new
could be replaced by a
const char*, being the URL to load.
At the beginning, restoring the old
nsIDOMHTMLLinkElement could be
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
konqueror does, but that means additional code to pick the
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:
As of this release
it is possible to enable/disable the hotkeys using
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.
When there's only a match, load the link directly. When there are several matches, cycle through them, and only link when
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.
- Make the CSS style customizable.
Unicode handling, uppercase
The following functions are used to determine the key value to store/look for.
gchar g_ascii_toupper (gchar c);
gboolean g_unichar_isalnum (gunichar c);
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
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
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
Just two things:
- [Major fix] Fixes crash when an empty link is encountered, by initializing
0. Hopefully epiphany shouldn't crash anymore.
- Handle nested tags (e.g. contained
<strong>, etc. tags).
- Handle links beginning with spaces (either
and so on).
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
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
- Moved from
extensions/hotkeys, with proper copyright entries. Restored the ancient tree.
- Added an icon indicating the current hotkeys status.
- Fixed bad tab handling. Now the extension should just behave fine with several tabs (that was just an horror, really). There are still problems when several windows are involved, but at least it sounds less critical than non-functional tabs.
- [Done] Add a textbox displaying the number of links.
- [Done] Factor some parts of the code (hotkeys enabling/disabling), remove
embedfrom the structure if one is certain (or can make certain) that the tab sync is called when finalizing. Putting a call in the
ephy_hotkeys_extension_finalize()function should be sufficient, so that the structures are freed before closing.
- Implement the above-mentioned next targets.
- Add configuration items (accessible through an UI?)
- Try using additional CSS style to let the user customize the hotkeys display.
How to implement these features
[Done] 1st target: first character isn't alphanum()
Move to the next element. If it is '<', call
continue(at least until the 2nd target is implemented).
Otherwise, see whether that other character is alphanum(), then move to a if needed.
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?
Maybe until InnerHTML doesn't contain any '<' anymore?
Maybe until there's no more HTMLElement child(ren)?
[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 ‘;’.
- [New] Statusbar gets an icon and a label displaying the number of links when the hotkeys are enabled.
- [New] CSS can be customised through the user stylesheet in Epiphany's preferences. No hardcoded default properties are used anymore. See the README file in the sources for an example (and full instructions).
- [New] Handle the cases where the first character of a link isn't alphanumerical. Previously, the link was dropped, now the next characters are considered. Nested tags aren't supported yet, though.
- Code cleanup (with no user-visible change).
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
png being defined as the
hotkey, and the additional
<span> being embedded in the
attribute. Hopefully such things get escaped (and extra spaces get
- [Done] Add help accessible through the
- Use the clickable item to popup the instructions to set the CSS and an example?
- Investigate the disparition of the RSS icon when the hotkeys get activated.
- [New] Handle nested tags
<a href="..."><b>Bold links</b></a>).
- [Fix] Re-ordered instructions for the status of hotkeys display, so that it is not possible to either disable the hotkeys while they are still being computed, or disable the hotkeys twice in a row. That prevents two kinds of (SEGV) crashes.
Fetching the sources
It looks like it is not possible to mix
Well, see the first post tagged epiphany.
- [New] A manual entry has been added with introduction, usage, configuration (with an example), and limitations.
[Done] Add backcycling when
Open in a new tab when
Ctrlis pressed. (It might be possible to open a new window, but which key would it be?
Altmaybe?) Interesting thinks are in
ephy_link_open(), with some nice flags. A problem, though: it might be difficult (if not impossible) to substract the
Controlkey from the
mozilla_is_a_hotkey(), so this function might have to handle several
Entercases, with or without
Shiftpressed, for example. Hmm. After some tests, it looks like
Control+Enterdoesn't reach the
mozilla_is_a_hotkey()function. Not seen as a
GdkEventby the DOM, maybe?
When either the hotkeys get activated or the browser/extension gets started (whatever is OK with both performance and usability), see whether the user (custom) stylesheet contains a given identifier. If it does, just use the
<span>tags as they are used now. If the CSS doesn't contain such identifier, use an hardcoded default style in the
style=attribute, so that the extension is usable without any configuration, and remains fully customizable to ones needs. Hopefully
USER_STYLESHEET_FILENAMEdefine. Unfortunately, it would be needed to have access to the (private)
ephy_dot_dir()for it to be useful, so that we can concat'em (it is located in
libs/ephy-file-helpers.c). Given the code of
ephy_file_helpers_init()(same file), it is unlikely to be duplicated. Deadend until one assumes a particular location? :/ (e.g.
The question is: how would one benefit from the
USER_STYLESHEET_FILENAMEdefine when one doesn't know in which directory it can be found? By the way,
ephy-embed-prefs.his only about GConf keys, besides this define.
Add an option to always have the same behaviour: pressing
Enteris needed even if there's only one link.