Translate

Archives

Replace GNOME Shell Activities Text String with Icon

In a recent post I provided an example of a GNOME Shell extension that changed the Hot Spot Activities text string to a Fedora Icon. A number of people contacted me about this because they wanted to use a different icon but were unable to get their icon to appear. As a result, I decided to write this post to explain things in more detail.

First, for base reference purposes, here is the default GNOME Shell (v3.0) desktop on Fedora 15 beta without any customization. I added the red arrows pointing at the Activities area to each of the images in this post.

GNOME3 Shell screenshot

Suppose you want to use a standard Fedora icon instead of the Activities text string as shown below:

GNOME3 Shell screenshot

How do you make the changes? Well, one way is to go to /usr/share/gnome-shell/js/ui/panel.js and edit the relevant lines in the JavaScript code.

        /* Button on the left side of the panel. */
        /* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */
        let label = new St.Label({ text: _("Activities") });
        this.button = new St.Button({ name: 'panelActivities',
                                      style_class: 'panel-button',
                                      reactive: true,
                                      can_focus: true });
        this.button.set_child(label);


However your modified source code file would probably be overwritten every time the GNOME Shell was updated. A better approach is to use a GNOME Shell extension.

Here is a simple extension which replace Activities with the standard default Fedora icon. This works on Fedora 15. Place the following two files in ~/.local/share/gnome-shell/extensions/activities@fpmurphy.com.

$ cat metadata.json
{
   "shell-version": ["3.0"],
   "uuid": "activities@fpmurphy.com",
   "name": "activities",
   "description": "Replace Activities text string",
   "original-authors": "Finnbarr P. Murphy",
   "url": "http://fpmurphy.com/gnome-shell-extensions"
}

$ cat extension.js
const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;

function main() {

   hotSpotButton = Main.panel.button;

   let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR, 
                            icon_size: hotSpotButton.height, 
                            icon_name: 'fedora-logo-icon' });
   let box = new St.BoxLayout();
   box.add_actor(logo);

   hotSpotButton.set_child(box);
}


Reload your GNOME Shell using Alt-F2 r and you should see the Fedora icon instead of Activities as shown above.

This extension works on Fedora 15 because the icon image file(s) for fedora-logo-icon are already present on the system.

$ cd /usr/share/icons
$ ls
Adwaita    default  gnome    HighContrast         LowContrast
Bluecurve  Fedora   hicolor  HighContrastInverse  oxygen
$ find ./ -name "fedora-logo-icon.*"
./hicolor/32x32/apps/fedora-logo-icon.png
./hicolor/22x22/apps/fedora-logo-icon.png
./hicolor/256x256/apps/fedora-logo-icon.png
./hicolor/16x16/apps/fedora-logo-icon.png
./hicolor/24x24/apps/fedora-logo-icon.png
./hicolor/96x96/apps/fedora-logo-icon.png
./hicolor/36x36/apps/fedora-logo-icon.png
./hicolor/48x48/apps/fedora-logo-icon.png
./Adwaita/fedora-logo-icon.png
$ 


As you can see, fedora-logo-icon icon image files exist in a number of locations. The image file used by the extension is the file under /usr/share/icons/Adwaita, which, by the way, is the default (and only) theme for the GNOME Shell at present. What about all the icon image files under the /usr/share/icons/hicolor subdirectory? What are these files and what is the hicolor theme? According to the Icon Theme specification

In order to have a place for third party applications to install their icons there should always exist a theme called “hicolor”. The data for the hicolor theme is available for download at: http://www.freedesktop.org/software/icon-theme/. Implementations are required to look in the “hicolor” theme if an icon was not found in the current theme.

What if you want to use an icon which is not present by default on your system? For example, suppose you want to (horror of horrors!) use a red Fedora icon as shown in the screenshot below.

GNOME3 Shell screenshot

First you must create an appropriate icon image. I am not going to go into details about how to do this. I assume you know how to do this if you are reading this post. Suffice to say that the icon image file must be one of the following types: PNG, XPM, or SVG, and the corresponding filename extension must be .png, .xpm, or .svg.

Assuming you have correctly created the icon image file, the question then is – what do you name the file and where do you place it so that the Shell extension uses it. In the following example, we will name the icon image file fedora-logo-icon-red.png. According to the Icon Theme Specification, applications should look for icons in $HOME/.icons (for backwards compatibility), in $XDG_DATA_DIRS/icons and in /usr/share/pixmaps (in that order) and according to the XDG Base Directory Specification

$XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.

I tried both ~/.icons and /usr/share/pixmap but the extension failed to retrieve the icon image file. However when the icon image file is placed in $HOME/.local/share/icons, the extension was able to load and use the icon image file. One caveat, it appears that the icon image filename must be unique, i.e. the filename cannot already exist under /usr/share/icons. I do not yet know why this is the case. I would have thought that the Shell extension would first check $HOME/.local/icons before checking /usr/share/icons but this does not seem to be the case. By the way the same behaviour occurs with custom themes.

Here is the modified extension.js which installs the red Fedora icon.

const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;


function main() {

   hotSpotButton = Main.panel.button;

   let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR, 
                                      icon_size: hotSpotButton.height, icon_name: 'fedora-logo-icon-red' });
   let box = new St.BoxLayout();
   box.add_actor(logo);

   hotSpotButton.set_child(box);
}


Finally, what if for you do not want either the Activities text string or an icon denoting the Hot Spot.

GNOME3 Shell screenshot

There are a number of ways to achieve this. Specifying a non-existent icon is one way. Setting a zero length text string is another way and this is what is used in our modified extension.js.

const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;


function main() {

   hotSpotButton = Main.panel.button;

   let label = new St.Label({ text: "" });

   hotSpotButton.set_child(label);
}

Suppose you want a permanent Fedora logo to be displayed in the upper left hand corner sized say 100px x 100px. The problem with the approach I have used in the previous examples is that panel will expand to 100px in height also. Why? Because everything on the top bar is contained within panel which is type of Clutter container. That is just the way Clutter works.

If you want to put a larger icon in the top left corner without disturbing the top bar, you need to so something like the following:

$ cat extension.js
const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;

function main() {

   let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
                            icon_size: 25,
                            icon_name: 'fedora-logo-icon' });
   let box = new St.BoxLayout({ style_class: 'big-icon-box' });
   box.add_actor(logo);

   global.stage.add_actor(box);
}

$ cat stylesheet.css
.big-icon-box {
    margin: 0px;
    padding: 0px;
    width: 100px;
    height: 100px;
}


Here is what you get when you restart your GNOME Shell:

GNOME3 Shell screenshot

This is not quite what we what, so we change the icon size property as shown below.

$ cat extension.js
const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;

function main() {

   hotSpotButton = Main.panel.button;
   let label = new St.Label({ text: "" });
   hotSpotButton.set_child(label);

   let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
                            icon_size: 100,
                            icon_name: 'fedora-logo-icon' });
   let box = new St.BoxLayout({ style_class: 'big-icon-box' });
   box.add_actor(logo);

   global.stage.add_actor(box);
}


Here is what what you should see when you restart the GNOME Shell.

GNOME3 Shell screenshot

Note that I have not added any functionality to this icon and this icon is on top of everything else. It is even displaced when the screen is locked! I will leave it up to you to figure out how to make it a working Activities button.

That is all you should need to know to handle this particular modification to the GNOME Shell. For further information, you should read the GNOME Icon specification and the XDG Base Directory Specification.

These examples work in GNOME Shell v3.0. There is no guarantee, however, that they will work in future versions of the GNOME Shell as no public APIs have been published to date nor do I think that such APIs will ever be published. You can download a working version of this extension in the GNOME Shell Extensions download area of my website.

P.S. If you have found this post via an Internet search, you might be interested to know that I have written a number of other posts in this blog about configuring and extending the GNOME 3 Shell.

45 comments to Replace GNOME Shell Activities Text String with Icon

  • Kitheme

    Finn,

    I appreciate the additional information! This method did work for me, despite having to make slight adjustments as I am on the Ubuntu Gnome 3 PPA.

    However, I ended up going in the opposite direction and making the extension global. I didn’t like the fact that I was linking a file (the logo) from a user account to a system folder, and eventually I’ll have more than one individual logging into this machine. Your method works great for a user-specific Shell adjustment, and I’m sure to use this in another fashion in the near future!

  • Gustav Tiger

    It should also be possible to use an image in your extension directory:

    var image = new Clutter.Texture({
    keep_aspect_ratio: true,
    filename: extensionMeta.path + “/myimage.png”});
    Main.panel.button.set_child(image);

    This is highly untested though. Perhaps something you can look into?

  • Daniel4m

    Man, your blog is one of the only so far to describe the Gnome 3. Things that you are show are beautiful. After all this, Gnome 3 (with shell) is more and more comfortable for me.

  • Christopher Robin Elmersson

    Just a suggestion: a cleaner way of removing the Activities label would be:
    hotSpotButton.visible = false;
    That way you don’t get a highlighted border or the glow either!

  • Is there a way to show both text and a logo? For example:
    (Fedora Logo) Activites

    • @Ian. Yes you can do that. Here is what you need in an extension.js to display both an icon and a label.

      const St = imports.gi.St;
      const Main = imports.ui.main;
      const Panel = imports.ui.panel;
      const Gettext = imports.gettext.domain(‘gnome-shell’);
      const _ = Gettext.gettext;

      function main() {

      let hotCornerButton = Main.panel.button;

      let label = new St.Label({ text: _(“Activities”) });
      let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR, icon_size: hotCornerButton.height, icon_name: ‘fedora-logo-icon’ });
      let box = new St.BoxLayout();
      box.add_actor(logo);
      box.add_actor(label);

      Main.panel.button.set_child(box);
      }

  • Thanks, but it didn’t work. I used the following code:
    const St = imports.gi.St;
    const Main = imports.ui.main;
    const Panel = imports.ui.panel;
    const Gettext = imports.gettext.domain(‘gnome-shell’);
    const _ = Gettext.gettext;

    function main() {

    let hotCornerButton = Main.panel.button;

    let label = new St.Label({ text: _(“Activities”) });
    let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR, icon_size: hotCornerButton.height, icon_name: ‘ubuntu-logo’ });
    let box = new St.BoxLayout();
    box.add_actor(logo);
    box.add_actor(label);

    Main.panel.button.set_child(box);
    }

    And it only displayed the Activities text.

    I am running Ubuntu Natty Narwhal with Gnome 3.0.0.

  • fpmurphy

    @Ian

    Does the ubuntu-logo.svg file exist and is it in the correct path?

  • The original code worked with the Ubuntu logo.

    • Sorry but I have no idea what is going on. The extension code I provided should work on any version of GNOME 3 Shell that is out there at present. However I have not got GNOME 3 Shell set up on Ubuntu so cannot advise you other than to suggest that you use the LookingGlass Shell debugger (Alt F2 lg) to see what is going on.

  • Raul

    I tried and worked for me in Ubuntu. By the way, I get the coloured icon, any way to use black_and_white one?

    Thanks,

    Raul

  • Kitheme

    My previously working logo replacement extension broke after updating from the official GNOME 3 PPA for Ubuntu… I finally realized that the shell version had changed (by checking Looking Glass), and GNOME Shell was blocking my extension. Changed the shell version within my extension, and ta-da! Fixed!

  • Mike

    Raul,
    I got the black and white one working. It took some time but I finally figured out how the directories differed for my Ubuntu install.

    /usr/share/icons/gnome/scalable/places
    The icons you need to replace are located there. I simply downloaded this: http://kernel.ubuntu.com/~kernel-ppa/reports/img/logo.svg
    and renamed the file to ubuntu-logo.svg
    Then I renamed the file /usr/share/icons/gnome/scalable/places/ubuntu-logo.svg to /usr/share/icons/gnome/scalable/places/ubuntu-logo.svg.old and moved the downloaded ubuntu-logo.svg to the directory. My modified extension.js file looks like this:

    icon_size: hotSpotButton.height, icon_name: ‘ubuntu-logo-icon’ });

    Now I have a black and white icon that goes quite well with the default gnome-shell theme.

  • I got the icon and activities text working in Ubuntu.
    The code:
    let label = new St.Label({ text: _(“Activities”) });
    Didn’t work, but the code:
    let label = new St.Label({ text: “Activities” });
    Did.

    • @Ian

      That would indicate that string localization is different on Ubuntu. You did include the following lines?


      const Gettext = imports.gettext;
      const _ = Gettext.gettext;

  • I’m using a scalable SVG icon and I think it looks a bit small. Is there any way to change the icon size depending on the panel height? I remember that gnome-panel used to do this. It used the png icon specified in places/24/start-here.png for example when the panel was set to a small size. It then moved on to 32, 48, 64 etc if the panel was extremely huge. :P (Using the scalable icon in between if I remember right.)

  • I did include those two lines. It seems my Gnome Shell was in version 3.0 instead of 3.0.1. This may be the problem, but I have not tested the original code.

  • anon

    Excellent post as usual! Just commenting to say you’re blog is excellent, and especially appreciate the time you take to actually explain everything. One of the highest-quality blogs i’ve seen. Keep up the excellent work!

  • nuk

    Great post.

    lg ftw

    Had some issues (miss spelling) looked all over the place but all I had to do was check lg for errors… and there they were.

    Btw I moved the activities@example.com folder to /usr/share/gnome-shell/extensions/ think pacman installed some other extensions there and to keep it tidy, Im on Arch just fyi.

    • @nuk. Sure, you can move any extension to /usr/share/gnome/extensions. Extensions in this location are visible to everybody. Extensions under $HOME/.local/share/gnome-shell/extensions are specific to the user.

  • ycDref

    @Gustav Tiver

    Yes it work well (with some modifications).

    I had do a media player control with clutter for print the cover : http://img828.imageshack.us/img828/7183/capture2bew.png

  • ycDref

    In javascript of course.

  • ernesto

    I followed your instructions on my fedora 15 box but it did not work :(

    Can you give me some pointers as to how to debug using lg?
    I tried running that debugger console but no idea how it works :S

  • Please,
    I want to disable altogether the hotspot. I tend to hover by accident the mouse over the corner and that annoys me!

    Would not be nicer to have the activities menu open just with the key?

    Thanks

  • Jim (SUSE 11.4)

    Hi, great post as usual, keep it up!

    Followed your instructions for placing customised icon in place of activities, eventually got it to work after trying many alternatives, (i’m new to this so thought I was doing something wrong). Anyway I tried Looking Glass (which I’d never used before) and there was an error showing ‘missing metadata.json’. So I changed the name of the file ‘activities.json’, (this was the name of the file given to create at the beginning), to ‘metadata.json’, and it worked.

    Does this make sense.

    Cheers

  • Jim (SUSE 11.4)

    One other thing, how to I make the icon appear larger, I already tried increasing pixel size to 500×500 (file size is 124Kb)

    Thanks

  • Abhay

    Your Tutorials seems perfect, Just one Question.
    I did put Extension in .local/share/gnome-shell/extension Directory It didn’t work.
    However by putting it into /usr/share/gnome-shell/extension/ It works just fine.

    • Which extension are you talking about.? Generally there should be no difference in behaviour between a GLOBAL install (/usr/share/gnome-shell/extension) and a LOCAL install (~/.local/share/gnome-shell/extensions)

  • Stefan

    Hey, nice extension.
    Do you know how to make it work in Gnome-Shell 3.1.3 or later.
    Main.panel.button is not available anymore. Replaced it with Main.panel._activites, but this destroys the HotCorner. Just click or win-key enable the overview.

  • nathan

    this does not work i have tried all examples and it doesnt work

  • Evilandi666

    Will you ever update this to Gnome 3.2?

    Changing to the new init(),enable(),disable() style is no a big problem, but there is another problem: Main.panel.button seems deprecated, …

    • As I have said several times in the last week … I will be updating my GNOME Shell extensions in a few weeks time. Just waiting for the initial set of GS 3.2 bugs to be fixed first,

  • snoxu

    For some reason when I enable this extension my shell theme gets disabled and goes back to default shell theme. I have to disable the Activities button extension and disable and re-enable user-theme extension to get the Ambiance shell theme back.

    Bit of a bummer

  • snoxu

    When ever I enable this extension gnome shell goes back to the default shell theme. I have to disable the activities button extension and disable and re-enable the user-themes extension the get the Ambiance shell theme back

    Bit of a bummer

    • This particular extension uses CSS to change the Activities button. You probably have other extensions enabled that also use CSS. The GNOME Shell can get confused if this is the case.

  • marti

    I have been unable to make this extension working on Linux Mint with gnome shell 3.2 because the text I need to change (as mentioned above) doesn’t exist in the activitiesbuttonicon@fpmurphy.com extension. Have I chosen the wrong extension?, I would be really grateful if you could tell what I need to change in this extension to get this working.

    Thanks.

    • In general. GNOME Shell extensions do not work on Cinnamon with being modified.

      I do not know why you would want to replace Cinnamon with GNOME Shell on Linux Mint. This is not something that I would do. How did you manage to do it?

  • marti

    I am using Linux MInt with Gnome Shell, I’ve tweaked GS and I like the way it looks now (I tried Cinnamon, but I preferred to keep using Gnome Shell).

    I’ve managed to replace the activities text, with the text LinuxMint by editting panel.js, but I have not been able to replace the text with Linux MInt’s icon, but I have not been able to do it with this extension, and I would be really grateful if you could help me. Thanks.