One aspect that I always found very appealing about gnome-shell is that you could just go in /usr/share/gnome-shell/js, make a few changes, hit Alt-F2 r and try them out. This was a very low barrier to entry – no development environment needed, no days of jhbuilding dependencies. This is at least part of the explanation why shell extensions exist in large numbers. Sure, you still have to make yourself familiar with the internal and external APIs that are used in gnome-shell, and if you are unlucky, then Alt-F2 r will show you not your cool hack, but the fail whale.
I was a bit sad to see that we’ve lost a bit of this newcomer friendliness in 3.12, when all the JavaScript and css files were wrapped up in resources and included in the gnome-shell binary (to be exact, they are located in /usr/lib64/gnome-shell/libgnome-shell.so, not in /usr/bin/gnome-shell itself). Why was this done ? I guess having everything in one file and not spread across the file system makes gnome-shell start up a tiny bit faster (although I’m not sure if anybody has measured this).
But how do I now try gnome-shell changes quickly ? Let see…
For some background, gnome-shell is using the GResource mechanism for embedding the js files in the binary. Under the covers, this puts the files in a separate ELF section and makes their content available in a filesystem-like structure. The application itself can get at the resources e.g. by constructing GFiles from resource:// URIs, like this:
file = g_file_new_for_uri ("resource:///org/gnome/software/gtk-style.css");
To access the embedded resources from the outside, you can use the gresource utility that is shipped with GLib. It can list the resources and also extract their content. Sadly, there is currently no easy way to replace existing resources with newer versions, since that requires recreating the ELF section and relinking the application.
gnome-shell has quite a few resources; the list looks like this:
gresource list /usr/lib64/gnome-shell/libgnome-shell.so /org/gnome/shell/extensionPrefs/main.js /org/gnome/shell/gdm/authPrompt.js /org/gnome/shell/gdm/batch.js /org/gnome/shell/gdm/fingerprint.js /org/gnome/shell/gdm/loginDialog.js /org/gnome/shell/gdm/oVirt.js /org/gnome/shell/gdm/realmd.js /org/gnome/shell/gdm/util.js ...
Here is how I used the gresource tool to get back to gnome-shell tweakability. Since the gresource commandline is not very versatile, I wrote this little script:
#! /bin/sh gs=/usr/lib64/gnome-shell/libgnome-shell.so cd $HOME/gnome-shell-js mkdir -p ui/components ui/status misc perf extensionPrefs gdm for r in `gresource list $gs`; do gresource extract $gs $r > ${r/#\/org\/gnome\/shell/.} done
After running this script, all the js files that make up the gnome-shell UI can be found in $HOME/gnome-shell. Now I can point gnome-shell at these files with the (undocumented) GNOME_SHELL_JS variable:
GNOME_SHELL_JS=$HOME/gnome-shell-js gnome-shell
And – voila! – gnome-shell is as hackable as it always was.