< adj35

So you want to edit GNOME Shell?

Andy's Adventures in GNOMELand

I am not an experienced software developer. When Ubuntu switched from Unity to GNOME in 17.04, I was immensely irritated to find that pressing PrtSc would now dump screenshots into ~/Pictures. Sure, it was possible to add a keyboard shortcut to invoke gnome-screenshot, but that was lowkey inelegant and I've always resented aftermarket fixes like that. So like a true Brit I did absolutely nothing about it besides getting irritated for the next four years.

Yesterday I decided to try to fix this irritation. I did it in the wrong place and my merge request was (rightfully) filed in /dev/null, but what I learnt along the way about gnome-shell might save some poor soul several hours of staring at various build processes eating all of their CPU and RAM.

GNOME shell is more or less a layer of JavaScript on a foundation of C. If you want to build it from source you will have a world of pain as you need a pretty bleeding-edge setup and it's easy to get it wrong. Unless you know what you're doing (in which case this page can only serve to kill off your precious brain cells), you are likely to accidentally compile WebKit, which weighs about 20GB and takes an age to build. This is not fun, and if you have a 'mere' 8GB of RAM you'll need to reduce the number of jobs it will spawn simultaneously.

However, if the bit you want to change is in the JavaScript, then there's an easier way originally described here. In case that link should break, or indeed to save your finger the effort of clicking it, it's a two-step process:

  1. Extract the builtin JavaScript from the gnome-shell binary:
    #! /bin/sh
    
    # Yours may be in a subtly different location like /usr/lib64
    gs=/usr/lib/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
    
  2. Tell gnome-shell to run the JavaScript from your files rather than from the builtin gresource
    GNOME_SHELL_JS="$HOME/gnome-shell-js" gnome-shell --replace

There's just one small problem: if you try this it will just crash your GNOME session. This is because of some change somewhere that I don't understand; this Stack Overflow question explains how to restart the shell in the brave new world of 2021: killall -SIGQUIT gnome-shell or Alt+F2 then r. These will happily restart the shell, but prepending GNOME_SHELL_JS=... as before does not make GNOME obey. A way around this is to add the line

GNOME_SHELL_JS="$HOME/gnome-shell-js"
to your ~/.profile so that the shell loads it on login. After making changes to the JavaScript you can then restart gnome-shell with with either of the two approaches above, but the disadvantage is that you need to remember to comment the line out of the profile once you're done tweaking the code.

Settings

Suppose you want to add a GSetting for something, while editing JS as above. This is totally doable: you need to write a schema for it (as per this introduction and this documentation), stick it in /usr/share/glib-2.0/schemas, and then glib-compile-schemas /usr/share/glib-2.0/schemas and then sure enough if you check dconf-editor or your preferred gsettings viewer (what do you mean you don't have one?) your beautiful new setting should be sitting there ready for you to access from the shell JS.