Official website for Linux User & Developer
FOLLOW US ON:
Dec
29

Build extensions for the GNOME desktop environment

by Kunal Deo

Among many new features in GNOME 3, the most exciting one is the ability to build extensions. Here’s how it’s done…

The GNOME 3 desktop environment represents a dramatic shift from the traditional desktop metaphor. The key element in this redesign is GNOME Shell. It provides core user interface functions that are essential to the GNOME 3 user experience, such as switching windows and launching applications. It also provides core user interface components such as the panel, activities window and message tray.

GNOME Shell extensions are small plug-ins (pieces of code) that can add, remove or modify GNOME Shell features. These extensions exist outside the GNOME design and development process and therefore provide a great deal of independence for what you can do. You also don’t need to learn full GNOME source code in order build extensions. Heck, you do not even need to know C or C++ to build GNOME Shell extensions (unlike the core GNOME components), as GNOME Shell extensions are written in JavaScript.

In this tutorial we will be building a GNOME Shell extension called LUD Volume Control Extender. The tutorial will demonstrate how easy it is modify the core the GNOME feature while keeping the entire experience coherent with the rest of the GNOME system.

Resources

Modern Linux distribution
GNOME 3.2 or above
GNOME Shell Integration plug-in

Step by Step

Step 01

Preparing the development environment

First and foremost, make sure you have installed the latest version of GNOME 3 – at the time of writing, this is version 3.6, so we’ve used that. While this tutorial should also work with future versions of GNOME 3, sometimes compatibility may break. The same goes for earlier versions as well.

To get started, you will also need to install the following packages:

gnome-shell-extensions: Installing this official package will make sure that your system is ready for GNOME Shell extensions.

gnome-tweak-tool: The GNOME Tweak Tool allows the adjustment of several advanced GNOME options that can’t be configured in GNOME-control-center. While it is not mandatory for development, it comes in very handy for managing GNOME extensions.

On Ubuntu (12.10) systems, you can install these packages as follows…

Add the GNOME 3 repository :

$ sudo add-apt-repository ppa:gnome3-team/gnome3

Run the following command to install GNOME 3 and all the required packages:

$ sudo apt-get install gnome-tweak- tool gnome-shell-extensions

For other distributions, please consult your distro’s documentation.

Step 02

Creating extension LUD Volume Control Extender

GNOME Shell comes with a tool called gnome-shell-extension-tool. This tool can be used to create extensions. Let’s start off by using this command:

$ gnome-shell-extension-tool --create-extension

You will be asked for some basic information about the extension:

Name: LUD Volume Control Extender

Description: LUD example to demonstrate GNOME Shell extensions.

UUID: LUDVolCtrlExt@kunaldeo.gmail.com

As of now, a working extension has been created for you in the following directory:

$HOME/.local/share/gnome-shell/ extensions/ LUDVolCtrlExt@kunaldeo. gmail.com

Note that the system-wide extensions are kept in /usr/share/gnome-shell/extensions.

Step 03

Running the newly created extension

The extension we have just created is not just a stub, but actually a working Hello World example. Let’s run it. To do this you will need to restart the GNOME Shell. Press Alt+F2, then type ‘r’ in the console and hit Enter. You will notice a small gears icon appearing on the panel. Clicking on it will flash ‘Hello World’ on the centre of the screen.

You can also enable a Shell extension using the GNOME Tweak Tool:

$ gnome-tweak-tool

Go to Shell Extensions. You will see that our newly created extension ‘LUD Volume Control Extender’ is listed there. Turn it ON to load it.

Step 04

Inside a GNOME Shell extension

Let’s look what is inside the extension. metadata.json : This file holds the metadata for the extension. It contains information such as the compatible shell-version the extension will work with, UUID, name and the description of the extension.

metada.json
{
   “shell-version”: [“3.6.1”],
   “uuid”: “ HYPERLINK
“mailto:LUDVolCtrlExt@kunaldeo.gmail.com” LUDVolCtrlExt@kunaldeo.gmail.com”,
   “name”: “LUD Volume Control Extender”,
           “description”: “LUD Example to demonstrate GNOME Shell Extensions”
}

stylesheet.css : This file contains the CSS for the extension, which in turn controls the extension’s look and feel.

extension.js : This is the main JavaScript file which holds the main code for the extension. This file must have a function called init(), which acts as the entry point (analogous to many other development environments) of the extension.

Step 05

Examining Hello World

Our Hello World extension demonstrates some very important functions of Shell extensions, such as putting an icon on the panel, responding to a click event and displaying a message.

Before we go about building our own extension, let’s look in more detail at how this basic extension works.

extension.js starts with the following import statements:

extension.js
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;

The top-level import ‘gi’ stands for GObject- introspection. It is a middleware layer between C libraries (using GObject) and language bindings; in this case it is JavaScript. Its main purpose is to collect and extend the API metadata for GObject-based libraries.

The other top-level import, ‘ui’, refers to user interface components. In this case we are using main and tweener. Tweener is a class used to create tweenings and other transitions using ActionScript.

Let’s take a look at the init function now (explanations are added in the form of comments):

extension.js
function init() {

We are creating a simple container with one actor.

button = new St.Bin({ style_class:
‘panel-button’,
   reactive: true,
   can_focus: true,
   x_fill: true,
   y_fill: false,
   track_hover: true });

Setting up the icon for the container:

let icon = new St.Icon({ icon_name:
‘system-run-symbolic’,
   style_class: ‘system-status-icon’
});
button.set_child(icon);

Setting up the event handler for button- press event:

button.connect(‘button-press-event’, _showHello);
}

Now, let’s look at the event handler:

extension.js
function _showHello() {
    if (!text) {
//St.Label is a widget for displaying text. Note that the style assigned to it ‘helloworld-label’
//is defined in the stylesheet.css file.
        text = new St.Label({ style_
class: ‘helloworld-label’, text:
“Hello, world!” });
//Here we are adding the actor text to the stage. Items on the stage are called actors.
        Main.uiGroup.add_
actor(text);
   }
   text.opacity = 255;
// Here we are calculating the position to display the text.
   let monitor = Main.
layoutManager.primaryMonitor;
   text.set_position(Math.
floor(monitor.width / 2 - text.width / 2),
        Math.floor(monitor.height /m2 - text.height / 2));
//Here we are defining the animation which will be used while displaying the text
//Note that we are calling function _hideHello at the end of the animation.
   Tweener.addTween(text,
        { opacity: 0,
        time: 2,
        transition: ‘easeOutQuad’,
        onComplete: _hideHello });
}
@code excerpt: extension.js
// in this function we are removing the actor text from the stage
function _hideHello() {
    Main.uiGroup.remove_actor(text);
    text = null; }
// The following functions are called when you enable or disable
the extension.
function enable() {
    Main.panel._rightBox.insert_
child_at_index(button, 0);
}
function disable() {
    Main.panel._rightBox.remove_
child(button);
}

As mentioned before, the style helloworld-label is defined in the
separate CSS file called stylesheet.css . This is your typical CSS style
sheet and reuse your existing web skills in this CSS.

@code:stylesheet.css
.helloworld-label {
    font-size: 36px;
    font-weight: bold;
    color: #ffffff;
    background-color:
rgba(10,10,10,0.7);
    border-radius: 5px;
    padding: .5em;
}

Pages: 1 2
  • Tell a Friend
  • Follow our Twitter to find out about all the latest Linux news, reviews, previews, interviews, features and a whole more.