24 March, 2011

GApplication in Cheese.

I have been working for the last few weeks on porting Cheese to GTK+3. I found some challenges along the way, and migrating from LibUnique to GApplication was definitely one of them, so I thought that this might deserve some special attention. New and more detailed documentation is now available, but I created a small flow chart just to have an overview of how GApplication works within a real application which is familiar to us.

Created using Graphviz (awesome tool!). 
First of all, I want to make it clear that this does not meant to be a guide or tutorial, it is just what I did and understood. It worked and I am happy to share it with you and I will be happier if it helps you to deal with GApplication in the future or even if I get some feedback on things which might be wrong :)). 

What problems did I face first? 
GApplication is new, the documentation was not as detailed as it is nowadays and it was the first time that I had ever used it. I never worked with LibUnique before either, and the terms primary instance, remote instance and local instance were new to me. So, what was that?
With some reading and bothering David King for a while, I discovered how everything worked together and what those terms meant. If you are as confused as I was, this might help you:
  • Primary instance: The very first instance of the program, that means, the first instance you run. Example: Run firefox for the first time and there you have a primary instance.
  • Local instance: The very last instance you run from a program, this is the last one you started working with. Example: In our example, the firefox instance you started, would be at the same time primary and local. If you start a new firefox instance, then the first one would still be the primary, and the second one would be the local.
  • Remote instance: Every instance of the same application that is not the primary one. Example: In our example, the second instance of firefox that you run would be the remote one.
Cheese works as a single instance, and with a single window for that instance. Every time Cheese is called from a terminal with command line arguments, those are handled  locally by the newly created instance, and here, GApplication::local_command_line() plays the main role. Every time g_application_run() is called, GApplication::local_command_line() is invoked. This function always runs in the local instance, which is the last instance you run.

By default, GApplication::local_command_line() tries to handle the command line in the primary instance, but since I wanted to be faithful to the original implementation, the purpose was to handle command line arguments locally, and for that, I needed to override the GApplication::local_command_line() function to make it return TRUE, and this is in essence what the diagram tries to explain.

This is how the main function looks like. (Cheese.Main inherits from GtkApplication which inherits from GApplication): 

public int main (string[] args)
   Cheese.Main app;
   app = new Cheese.Main ("org.gnome.Cheese",ApplicationFlags.FLAGS_NONE);
   app.activate.connect (app.on_app_activate);
   int status = app.run (args);
   return status; 

I hope this is helpful, in some way, to somebody. As you can see, the diagram starts on the app.run(args) call. You can check out the source code on git.gnome.org, and for a more colourful version, in my GitHub repository.

I wanted to take the opportunity to thank David King for his infinite patience and help during my work migrating Cheese to GTK+3, Jürg Billeter for being so responsive and helpful in every single issue I had with Vala, and Carlos Garnacho for helping me out with some GtkStyleContext problems.

Thanks to all of them for the help and to you for reading!


  1. Very useful info, thank you. Documentation for GApplication and GtkApplication seems very poor, so hopefully lots of people will find their way here :-)

  2. hey patti!

    Could you try to clean this up and add the graphs to the GApplication/GtkApplication documentation? I think that would be very helpful.

  3. Yeah, I agree with both Tristan and Johannes.
    Great work!

  4. Another +1 to improve the upstream documentation. I would not mind to also have that picture part of it (maybe we could agree on a color scheme for dot diagrams and have more of them in the docs in the long run - talk to me on irc #gtk-doc if you like the idea).

  5. Thanks to all of you :).

    ensonic, I will talk to you on irc.

  6. It's not clear what this graph is of. A documentation of internal implementation doesn't belong in API documentation. But if it's meant to help you use the API to achieve a certain program flow then it needs to be rephrased somehow.