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.
Suppose you want to use a standard Fedora icon instead of the Activities text string as shown below:
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.
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.
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:
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.
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.
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!
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?
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.
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!
Christopher, thanks for the great tip!
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.
@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.
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
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!
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.
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!
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.
@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
In javascript of course.
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
@Emesto. Probably best if you downloaded a working version from: http://www.fpmurphy.com/gnome-shell-extensions/activitiesbutton.tar.gz
All sorts of things could be going wrong for you. To activate LG, use Alt-F2 lg. Selects the Errors panel to see the current errors. Do this just after you reload the GNOME Shell using Alt-F2 r
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
@ Guilherme. The META Key (typically the Windows key) activates the overview. No need to use the hot corner.
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, thanks for letting me know about that error! Fixed it to read “metadata.json”.
No, problem, I’m pleased I figured it out!
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
@Jim, See the new section at bottom of this blog. This explains what you need to do.
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)
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.
this does not work i have tried all examples and it doesnt work
Nathan, exactly what does not work?
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,
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
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.
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?
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.