Developing for Gtk/Glib

Hi everyone. It’s been a while since I blogged something. Been busy day-to-day work.

Yesterday something started to bug me, a new project like, a new toy application. After some modeling/sketching on a page I decided to start writing some demo code.

It took me a while to notice that I’m far from setting a GObject development environment fast. I’m using Eclipse IDE for C/C++ Linux Developers, and valgrind and the usual tools in my Archlinux. There’s, by the way, a package group in pacman called base-devel, I always had installed first hand.

Anyway I’ll talk about the main three issues I found in my way to set up start and star coding some mockups and early designs of my toy app.

Autotools packaging

I’m not the guy who lined up with cmake cause autotools is old, and should be improved, although I think it needs some improvements [1]. The main issue with autotools is that it is hard to learn, the existent documentation is little and somewhat cryptic, and that makes the learning curve steep. After read some things on the web, and been this not first time I stand before the issues, I did what I think everyone should, I made my own sample-autootols project which keeps a minimal configuration of what I need to develop a Gtk application. I included tips from this post about improving and modernizing the autotools configuration, and some others about using xz compression instead of gz. The project is in github, and I’m planning to improve it with several configurations for several kinds of builds. Anyway, that for point one, I will keep my template at hand, but I think for new developers, and for the good of the platform, Gnome should make something like Ubuntu Quickly. Note: I’ve tried to use anjuta, really tried, but it doesn’t feel right or stable, and this is not for the developers to take it personal, it just my experience with it had been bad.

GObject based C class

This is so simple is really a shame it had taken me so long to pass this point. I needed some GObject based class, to handle some  internals structures of my application, and then I found myself copying parts of devhelp tutorials to headers and sources files to build the class, this code is all templates, is the same over and over for every class I had and have to make. I just want some script that make me the files after I provide the name of the class I want. If I had the time to learn howto make Eclipse plugins I’ll make the Eclipse Template for those files header and source file for  a GObject based class. I tried vala before and I know it does, one possible solution is for vala to print the translation into some pretty formatted code. If I can’t find any solution soon, I’ll make some awk script that output the files with the required boilerplate needed.

Valgrind debugging

Finally, the third point is the fair beginner one, I have to say this pretty much my first time doing C development of Gtk/Glib applications. Until now I’ve used some vala, and some JavaScript, and some C++, but C, nope, so I think this is mainly why I found this obstacles in my path. After having some windows running and some buttons doings it’s work I felt it was time to profile the memory usage I was using. I used valgrind since the Eclipse bring with support for it included, and I notice I need a suppression file for Gtk/Glib possible memory lost, which isn’t real. Digged a little on the web, actually digged nothing this was the first results that pops out: Valgrind at live.gnome.org, and I went after the suppression file, just to learn that the file was missing or something else (I’m getting some internal error, which I now realize I have to tell the maintainers of the wiki). After that I decided I have to do it by myself. I think that the gnome developers should have a file like that somewhere, but I’m to shy to ask for it, so I’ll take the time to do one for me, someday.

Again I think that, in order to promote the platform, is necessary to publish things like this, The new look of developer.gnome.org and the samples in there helps to that purpose, but still feel more work in that direction is missing.

[1] Autotools needs to handle parallel configure, since parallel make is handled by the -j flag.

DBus in the Shell

As a companion of the post I made before on connecting to DBus exported objects on Gjs JavaScript runtime over the Shell, should be other post talking as how to export object over DBus inside Shell JavaScript environment. More or less this one is about that.

The code I will show here isn’t mine, even I think I contribute some part to it, the main architecture of the thing was already made by the time the code get to me. That part of thanks for the help, and the guidance should go to Vamsi Krishna Brahmajosyula.

So, let’s get our hands dirty

First you need to create the interface you will export, similar to the way you made before for getting proxy objects.

[sourcecode language=”javascript”] const LoggerIface = {

name: 'org.gnome.Logger',
methods: [{
            name: 'log',
            inSignature: 's',
            outSignature: ''
          }
       ],
signals: [{
            name: 'added',
            inSignature: 's'
        }],
properties: []

}; [/sourcecode]

As you can see, we’ll planning to create an object exporting one method ‘Logger::log’ and one signal ‘Logger::added’. The method has one parameter and no return value, and the signal has one arguments, in both cases the argument/parameters is the same, the message log sent. So, our objects will have and array of log messages sent to him, and for every time you call its method ‘log’ it emit the signal added. Very simple.

Now we’ll create the object conforming the interface we defined before.

[sourcecode language=”javascript”] function Logger() {

this._init();

}

Logger.prototype = {

_init: function() {
    this.logs = [];
    DBus.session.exportObject('/org/gnome/Logger', this);
},

log: function(message) {
    this.logs.push(message);
    global.log('Received: ' + message);
    this._emitAdded(message);
},

_emitAdded: function(message) {
    DBus.session.emit_signal('/org/gnome/Logger',
                             'org.gnome.Logger',
                             'Added', 's',
                             [message]);
}

}; [/sourcecode]

As you see we defined a method with the same name we did in the interface and the same signature. And now we’ll pass to see the Gjs DBus magic:

[sourcecode language=”javascript”] DBus.session.exportObject(‘/org/gnome/Logger’, this); [/sourcecode]

This was called inside our _init method, and that’s the method of the Gjs telling DBus, this is the object we want to export. And, later on this one is the one telling DBus to check if our class/prototype conforms the interface we said it conforms:

[sourcecode language=”javascript”] DBus.conformExport(Logger.prototype, LoggerIface); [/sourcecode]

Finally the extension entry point. Ohh wait I didn’t said that before, we’re reviewing an extension, as this is a so easy way to test Gnome 3 stuff. So the entry point, the main function.

[sourcecode language=”javascript”] function main() {

// I did this to get the object after the extension code run
Main.logger = new Logger()

//this was the missing instruction
DBus.session.acquire_name('org.gnome.Logger', 0, null, null);

} [/sourcecode]

And here is a great trick, you see that line saying “this was the missing instruction”, yeah I had all the code written and reviewed like a thousand times, and still doesn’t worked, I keep testing but nothing the object wasn’t there. I opened Looking Glass, and typed Main.logger and the object was create, but it wasn’t receiving any notice when I called the method, actually I was getting errors cause that method doesn’t existed at all. After some back and forward between DBus documentation, and Gnome Shell source code, I figured out. The missing part was, of course, I’ve should known, the part when your object grab the DBus name it want to publish. So first I went to DBus.session.own_name but that is not a function, and then I tried this one DBus.session.acquire_name, with doesn’t exist at all in the devhelp documentation but it seems is the wrapper of Gjs for the own_name GDBus method.

So, that’s all for now. I know I’m still missing some things. I want to learn how catch a signal emit over DBus, and how to handle exported object properties, make some samples and toy with it a bit.

But that will be later. Keep in touch.

BTW: I’m still figuring out how to publish the full examples, but I will do it, sometime

JSON.parse and JSON.stringify

The Gnome Shell Extensions system is one mighty and powerful beast. Just yesterday I found myself wanting to have a simple list of stuff I wanted to check later. After looking around a bit to storage components in Gnome Shell environment I decide I’ll use simple files with JSON strings inside.

I started coding and in a while I got my wish-list extension. The  beauty of this is what I learnt in the process. Two stuff I never tried, before:

  • Hacking with autotools: This is the kind of things you should know once you decide to get involved in software development for Linux.

  • How to hack a new kind of PopMenuItem for the Shell UI

Since I have access to the facilities of JavaScript and GLib system from the extension I can do almost everything with it. I used a file as a back-end for my list of wishes and  use JSON.parse for reading and parsing the content back into an array and JSON.stringify to dumps the objects into the file. You can go down through the code later. Anyway there’s those two snippets

Using GLib/Gio and JSON [sourcecode language=”javascript”] let dir = Gio.file_new_for_path(Main.ExtensionSystem.extensionMeta[UUID].path); let listFile = dir.get_child(‘lists.json’);

let raw = listFile.replace(null, false,

                Gio.FileCreateFlags.NONE,
                null);

let out = Gio.BufferedOutputStream.new_sized (raw, 4096); Shell.write_string_to_stream (out, JSON.stringify(this.list)); out.close(null) [/sourcecode]

Instantiating PopupMenuItem [sourcecode language=”javascript”] PopupEntryMenuItem.prototype = {

__proto__: PopupMenu.PopupBaseMenuItem.prototype,

_init: function (style) {
    PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { activate: false });

    this.entry = new St.Entry({ style_class: style });

    this.entry.clutter_text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
    this.addActor(this.entry, { span: -1, expand: true });

    this.actor.add_style_class_name('menu-entry');
}

} Signals.addSignalMethods(PopupEntryMenuItem.prototype) [/sourcecode] The page is linked above. See you around.

Morning Echoes

Here goes some of the morning news you can find around:

Some tech now:

And some jokes wouldn’t kill anyone:

So, monday is kinda slow day, or at least at this time in the morning.

I’ll bring you back tomorrow or the day after that.

DBus in Gjs and Gnome Shell

The Story

Last few days I’ve got a bunch of ideas about Gnome Shell extensions. Gnome 3 platform has made the development of Gnome really close to the public, more than anything by using JavaScript to made the Shell.

The use of JavaScript has lower the barrier for making contributions for Gnome Desktop, because JavaScript it’s a well known language in the web development world an it’s a easier language to learn than the typical C/C++ and even Python. There’s still some things to address about the use of JavaScript, the definition and standardization of an engine for use in the gnome development (look at this discussion about the use of Seed or Gjs [1]), the stabilization of some interfaces in the actual engines, but there’s a lot of way made already.

About standardization and stabilization of interfaces goes this post. DBus is a clever way of communication between process that has become almost a must have for every desktop application for providing services and hooks to internals API, the JavaScript engine powering Gnome Shell then, needs a DBus interface and here comes the problem.

When I realize of my need of using DBus when writing some Gnome-Shell extension I go through the process of selecting which DBus interface I will use. First I decide to use GLib GDBus interface since it goes inside GLib, so no matters which JavaScript engine you use, as long as it has GLib bindings it should work. I avoid the low-level interfaces, and I got the Devhelp documentation to work with so, It just left start coding.

After a while I realize that not everything worked as I thought, first and the biggest problem I had was the need of using GLib.Variant in JavaScript to define the signature of the methods you call over DBus and the fact the Gjs not implement GLib.Variant support or at least as long as I can find. I tried with almost every method declared in the GLib-2.0.gir file which is suppose to provide the introspection data, no one works. After asking in the JavaScript mailing list, and got no answer, I decide I should give up and use DBus interface provided by Gjs.

The Code

After looking around, I decide to go the only way, reading Gnome Shell code.

For calling a method exported over DBus using Gjs the first is import (include, load the code) the unit containing the DBus interface

<span class="kwrd">const</span> DBus = imports.dbus;

This code loads the JavaScript file dbus.js. After that you need to declare the interface you’re trying to reach and the signature of the methods you’re planning to call

<span class="kwrd">const</span> NotificationRemoteInterface = {
    name: <span class="str">'org.freedesktop.Notifications'</span>, <span class="rem">//interface name</span>
    methods: [
        {    <span class="rem">//method name and signature</span>
            name: <span class="str">'Notify'</span>,
            inSignature: <span class="str">'susssasa{sv}i'</span>,
            outSignature: <span class="str">'u'</span>
        }
    ]
};

Now it comes the Gjs-DBus implementation magic, you need to call this method from DBus object tha makes a class of the proxy object you’ll need to instantiate

let NotificationProxy = DBus.makeProxyClass(NotificationRemoteInterface);

After that you’ll be ready to get the proxy object and and call its method, or at least the ones you declared.

    let notification_proxy = <span class="kwrd">new</span> NotificationProxy(DBus.session,
                                                    <span class="str">'org.freedesktop.Notifications'</span>,
                                                    <span class="str">'/org/freedesktop/Notifications'</span>);
    notification_proxy.NotifyRemote(<span class="str">'my_app_sample'</span>,    <span class="rem">//these are the params of the method called</span>
                                    0,
                                    <span class="str">'dialog-info'</span>,
                                    <span class="str">'Summary of the notification'</span>,
                                    <span class="str">'Big Body of the sample Notification'</span>,
                                    [],
                                    {},
                                    120,
                                    <span class="kwrd">function</span>(result, err){
                                        log(<span class="str">'This is the result: '</span> + result);
                                        log(<span class="str">'This is the error: '</span> + err);
    });

Well, and that’s it. After that you called the method and you have the callback set there, so you can what you want with the returned values.

The conclusion

I know there still a bunch of stuff you can make with DBus, but this is a start. There’re still watching for a bus name, and watching for signals and properties changes. It will come soon, I hope.


[1] Gjs vs Seed