After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 637334 - Port Epiphany to GtkApplication
Port Epiphany to GtkApplication
Status: RESOLVED FIXED
Product: epiphany
Classification: Core
Component: General
unspecified
Other Linux
: Normal normal
: ---
Assigned To: Epiphany Maintainers
Epiphany Maintainers
Depends on:
Blocks:
 
 
Reported: 2010-12-15 18:22 UTC by Diego Escalante Urrelo (not reading bugmail)
Modified: 2011-06-23 21:36 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Half-working port of Epiphany to GtkApplication (37.62 KB, patch)
2011-02-04 11:06 UTC, Alexandre Mazari
none Details | Review
Working patch of port of Epiphany to GtkApplication (48.29 KB, patch)
2011-02-09 18:56 UTC, Alexandre Mazari
none Details | Review
Use GtkApplication subclass to ensure unicity instead of custom DBus service registration. (49.16 KB, patch)
2011-03-02 17:56 UTC, Alexandre Mazari
needs-work Details | Review
Remove all direct accesses to the ephy_shell global variable (24.76 KB, patch)
2011-03-02 19:08 UTC, Alexandre Mazari
none Details | Review
Do not instanciate a global EphyShell instance. Instead set a field of GtkApplication. (3.76 KB, patch)
2011-03-02 19:08 UTC, Alexandre Mazari
none Details | Review
Replace ephy_shell_get_default calls by ephy_application_get_shell (45.85 KB, patch)
2011-03-02 19:09 UTC, Alexandre Mazari
none Details | Review
Use GtkApplication to ensure unicity (55.26 KB, patch)
2011-03-03 22:03 UTC, Alexandre Mazari
none Details | Review
Move desktop session manager handling from EphySession into a GtkApplication subclass, inherited by EphyApplication. (33.18 KB, patch)
2011-03-07 19:24 UTC, Alexandre Mazari
none Details | Review
Use a interface trait for session management instead of subclassing GtkApplication. Fix Typo (26.65 KB, patch)
2011-03-07 19:24 UTC, Alexandre Mazari
none Details | Review
Make the tests compliant with the new GtkApplication (4.49 KB, patch)
2011-03-07 19:24 UTC, Alexandre Mazari
none Details | Review
Implement GtkApplication based activation and uniqueness (14.96 KB, patch)
2011-06-20 22:31 UTC, Claudio Saavedra
rejected Details | Review
Implement GtkApplication based activation and uniqueness (30.22 KB, patch)
2011-06-20 22:34 UTC, Claudio Saavedra
none Details | Review
This is a new version, removing some cruft I left yesterday. (29.93 KB, patch)
2011-06-21 09:22 UTC, Claudio Saavedra
needs-work Details | Review
Implement GtkApplication based activation and uniqueness (30.45 KB, patch)
2011-06-22 15:37 UTC, Claudio Saavedra
committed Details | Review

Description Diego Escalante Urrelo (not reading bugmail) 2010-12-15 18:22:03 UTC
All the cool kids are doing it anyway.
Comment 1 Alexandre Mazari 2011-02-04 11:06:02 UTC
Created attachment 180069 [details] [review]
Half-working port of Epiphany to GtkApplication

Use GtkApplication to ensure unicity instead of custom DBus service registration.
The primary instance takes care of command-line arguments parsing passed to the
secondary instances.
To ensure the application life-cycle, new windows are attached to the application
(TODO: attach bookmarks, settings... windows too).
Also the application is held when there is commands in the queue, so that it wont
quit even if no window has been previously created.

TODO: find out why the mainloop stall after a "open uri" command is enqueued fram a remote instance
TODO: attach bookmark, settings and history windows to the application
TODO: expose Actions
Comment 2 Alexandre Mazari 2011-02-04 11:15:26 UTC
I need some of your light to help me debug a mainloop issue stalling after a remote instance ask for an uri opening.

Here is the workflow :

- a new instance is launched, become the primary instance, is initialized in the startup_epiphany handler, then takes care of its local command line args in the command_line_cb, fired in response to the "command-line_signal". That works fine.

- another epiphany invocation is issued by the user (ex. epiphany http://google.fr)
- GApllication notices there is already a running instance, so send it the cmd line arguments then quit
- the primary instance receive the args, and is notified by the "command-line" signal, handled by command_line_cb again.
- those arguments are parsed into commands (EPHY_SESSION_CMD_OPEN_URIS mostly), that are then queued.

And then... the mainloop hangs before the command is poped up from the session queue to be executed.

If any of you has a theory/solution, I'll be very glad !
Comment 3 Alexandre Mazari 2011-02-09 09:27:50 UTC
Here is the stack trace when the loop is hanging :


  • #0 read
    from /lib64/libpthread.so.0
  • #1 ??
    from /usr/lib64/libICE.so.6
  • #2 _IceRead
    from /usr/lib64/libICE.so.6
  • #3 IceProcessMessages
    from /usr/lib64/libICE.so.6
  • #4 process_ice_messages
    at eggsmclient-xsmp.c line 1323
  • #5 g_main_dispatch
    at gmain.c line 2440
  • #6 g_main_context_dispatch
    at gmain.c line 3013
  • #7 g_main_context_iterate
    at gmain.c line 3091
  • #8 g_main_loop_run
    at gmain.c line 3299
  • #9 gtk_main
    at gtkmain.c line 1338
  • #10 g_application_run
    at gapplication.c line 1242
  • #11 main
    at ephy-main.c line 597

Seems like something stange happens in eggsmclient. Any hints guys ?
Comment 4 Dan Winship 2011-02-09 13:58:47 UTC
You don't want to use GOptionContext to parse command line args passed via GApplication. Lots of code assumes that things triggered from a GOptionContext will only happen once, and only right at the start of the program. Eg, the option group returned by egg_sm_client_get_option_group() connects to the SM server after the command line has been parsed, and (apparently) messes things up if that code gets run a second time.

(It's also possible, depending on the details of GApplication, that if you start one epiphany, and then do "epiphany --help" from another terminal, that it will cause the first instance to print command-line help and then exit.)

I don't know exactly what the right way to do command-line handling in GApplication is, but this isn't it.
Comment 5 Alexandre Mazari 2011-02-09 17:38:17 UTC
Thanks for your input Dan.

GOption is indeed not really fit for multiple invocations. Even more, a lot of libs use it parse-hooks facility to do initialization, thus modify the global state.

EggSmClient is indeed one of those, so I modified our local copy in order to only invoke its init once.
Also, I decided to create a GOptionContext for each invocation, so to avoid the (broken?) behaviour on remaining arguments (the pointer to the string array is handled badly there).
That seems to work fine !

A more future-proof solution might be to do the parsing locally, even on the secondary instances, and communication with the primary by the mean of actions exported with the GApplication facilities.
Comment 6 Alexandre Mazari 2011-02-09 18:56:41 UTC
Created attachment 180499 [details] [review]
Working patch of port of Epiphany to GtkApplication

This patches fixes (hopefully) the mainloop hanging found in the previous patch.

Please review, comment or bash !
Comment 7 Alexandre Mazari 2011-02-09 19:08:18 UTC
At a later stage, I'd like to implement an EphyApplication class deriving from GtkApplication, which would also take care of 
- the session manager handling (extracted from EphySession)
- the EphyShell access, avoiding the current singleton

Also, the action currently defined in ephy-activation need to be converted in GActions, exposed on the bus via GApplication.
Comment 8 Alexandre Mazari 2011-03-02 17:56:41 UTC
Created attachment 182282 [details] [review]
Use GtkApplication subclass to ensure unicity instead of custom DBus service registration.

The primary instance takes care of command-line arguments parsing passed to the
secondary instances.
To ensure the application life-cycle, new windows are attached to the application
Also the application is held when there is commands in the queue, so that it wont quit even if no window has been previously created.

Move some utilities procedures from main into ephy-string and ephy-file-helper
Comment 9 Alexandre Mazari 2011-03-02 19:08:49 UTC
Created attachment 182297 [details] [review]
Remove all direct accesses to the ephy_shell global variable

https://bugzilla.gnome.org/show_bug.cgi?id=628364
Comment 10 Alexandre Mazari 2011-03-02 19:08:55 UTC
Created attachment 182298 [details] [review]
Do not instanciate a global EphyShell instance. Instead set a field of GtkApplication.

https://bugzilla.gnome.org/show_bug.cgi?id=628364
Comment 11 Alexandre Mazari 2011-03-02 19:09:00 UTC
Created attachment 182299 [details] [review]
Replace ephy_shell_get_default calls by ephy_application_get_shell

https://bugzilla.gnome.org/show_bug.cgi?id=628364
Comment 12 Alexandre Mazari 2011-03-03 22:03:11 UTC
Created attachment 182406 [details] [review]
Use GtkApplication to ensure unicity

Use GtkApplication subclass to ensure unicity instead of custom DBus service registration.
This version of the patch delegates command-line arguments parsing to the secondary instances. These then communicate with the primary instance by the mean of exposed GActions (currently "Open", "Open Bookmark editor" and "Load session")
To ensure the application life-cycle, new windows are attached to the application
Also the application is held when there is commands in the queue, so that it wont quit even if no window has been previously created.

Move some utilities procedures from main into ephy-string and ephy-file-helper
Comment 13 Alexandre Mazari 2011-03-03 22:10:00 UTC
The latest attached patch let the secondary instances doing the command-line parsing. These then communicate with the primary instance using the exposed GApplication's actions (via DBus).

This has many advantages:
- avoid GOption non-reentrancy issues
- let the primary instance mainloop free from "heavy" parsing
- force the extraction of the actions, which could be used in other contexts
- DBus API for free
- future dev of GApplication might bring "activation" and nice gnome-shell "jump lists" using those actions
Comment 14 Alexandre Mazari 2011-03-07 19:24:26 UTC
Created attachment 182749 [details] [review]
Move desktop session manager handling from EphySession into a GtkApplication subclass, inherited by EphyApplication.
Comment 15 Alexandre Mazari 2011-03-07 19:24:31 UTC
Created attachment 182750 [details] [review]
Use a interface trait for session management instead of subclassing GtkApplication. Fix Typo
Comment 16 Alexandre Mazari 2011-03-07 19:24:34 UTC
Created attachment 182751 [details] [review]
Make the tests compliant with the new GtkApplication
Comment 17 Claudio Saavedra 2011-06-01 15:24:24 UTC
Review of attachment 182282 [details] [review]:

I had a look to this patch. Bear in mind that I am not very familiar with the epiphany codebase, yet I see some stuff worth commenting. I didn't test it either yet.

Basically:

- there are a lot of whitespace noise changes, please review before submitting. Same for coding style.
- Style fixes or changes that you find necessary should be submitted separately.
- Code refactoring should be done only if needed, and in such case, please use separate patches.

::: lib/ephy-file-helpers.h
@@ +90,1 @@
 

Moving stuff like this around, when necessary, is better done in a single standalone patch.

::: lib/ephy-string.c
@@ +504,3 @@
+*/
+static char*
+ephy_string_to_uri(char *input, GError **error)

Freeing a parameter is not a standard practice. Better receive a const char * and return a newly allocated one. Leave the memory management to the method user (even if this is a static method).

@@ +551,3 @@
+ */
+gboolean
+        return NULL;

Modifying an array contents in place is not a very common practice, as far as I know. Just return a linked list or some other structure.

On the other hand, there is no reason to do this refactoring. When working on a well established codebase, it is a better idea to do this type of refactorings only if you need to use the same or similar code somewhere else. In such case, writing a single refactoring patch is advisable. However, we don't need this here, and it makes understanding the core idea of the patch a bit harder.

::: src/Makefile.am
@@ +16,3 @@
 NOINST_H_FILES = \
+	ephy-goption.h				    \
+	ephy-application.h				\

Too much spacing I guess.

@@ +60,1 @@
 	ephy-activation.c			\

Ditto.

::: src/ephy-application.c
@@ +226,3 @@
+ephy_application_init (EphyApplication *application)
+{
+	application->priv = EPHY_APPLICATION_GET_PRIVATE(application);

Missing space before the opening parenthesis.

::: src/ephy-session.c
@@ +41,3 @@
 #include "ephy-stock-icons.h"
 #include "ephy-window.h"
+#include "ephy-application.h"

This appears to be unnecessary..

@@ -512,3 @@
-}
-
-	{

I don't understand why you needed to shuffle this code around.

@@ +520,3 @@
 				    EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW_RESTORE,
 				    NULL, NULL, user_time, FALSE);
+

Not needed.

@@ +535,3 @@
 
+
+

Not needed.

@@ +551,3 @@
 	priv = session->priv;
 
 	shell = ephy_shell_get_default ();

Not needed.

@@ +710,3 @@
 	g_assert (cmd != NULL);
 
+	LOG ("dispatching queue cmd:%d\n", cmd->command);

This change is unnecessary.

@@ +1752,3 @@
 	GList *element;
 	SessionCommand *cmd;
+	

This should not be in the patch.

::: src/ephy-shell.c
@@ +58,3 @@
 #include "ephy-stock-icons.h"
 #include "ephy-web-view.h"
+#include "ephy-application.h"

I don't understand whether this include is really needed here?
Comment 18 Claudio Saavedra 2011-06-03 13:45:10 UTC
(In reply to comment #9)
> Created an attachment (id=182297) [details] [review]
> Remove all direct accesses to the ephy_shell global variable
> 
> https://bugzilla.gnome.org/show_bug.cgi?id=628364

(In reply to comment #10)
> Created an attachment (id=182298) [details] [review]
> Do not instanciate a global EphyShell instance. Instead set a field of
> GtkApplication.
> 
> https://bugzilla.gnome.org/show_bug.cgi?id=628364

(In reply to comment #11)
> Created an attachment (id=182299) [details] [review]
> Replace ephy_shell_get_default calls by ephy_application_get_shell
> 
> https://bugzilla.gnome.org/show_bug.cgi?id=628364

This seems like a good idea, but I think you could perfectly fine squash these three commits together and avoid doing intermediate changes, since there is no reason to go from global_shell -> shell_get_default() -> app_get_default_shell() in one series of patches.
Comment 19 Alexandre Mazari 2011-06-08 08:47:20 UTC
Hi Claudio,

Thanks for your review. I'll provide a fix for most of your concerns regarding style ASAP.
Here are some comments on the remaining points:

> 
> ::: lib/ephy-file-helpers.h
> @@ +90,1 @@
> 
> 
> Moving stuff like this around, when necessary, is better done in a single
> standalone patch.

Alright.

> 
> ::: lib/ephy-string.c
> @@ +504,3 @@
> +*/
> +static char*
> +ephy_string_to_uri(char *input, GError **error)
> 
> Freeing a parameter is not a standard practice. Better receive a const char *
> and return a newly allocated one. Leave the memory management to the method
> user (even if this is a static method).
> 

Agreed, this implementation was already present. Just move it around and planned to modify it.

> @@ +551,3 @@
> + */
> +gboolean
> +        return NULL;
> 
> Modifying an array contents in place is not a very common practice, as far as I
> know. Just return a linked list or some other structure.
> 

Same here.

> On the other hand, there is no reason to do this refactoring. When working on a
> well established codebase, it is a better idea to do this type of refactorings
> only if you need to use the same or similar code somewhere else. In such case,
> writing a single refactoring patch is advisable. However, we don't need this
> here, and it makes understanding the core idea of the patch a bit harder.
> 

Understood.
Comment 20 Claudio Saavedra 2011-06-20 22:31:04 UTC
Created attachment 190319 [details] [review]
Implement GtkApplication based activation and uniqueness

This replaces the existing dbus-glib activation and uniqueness code.
The changes are kept to the minimum necessary to make all the features
work, but there are still some optimizations possible (like doing most
of the initialization in ephy_application_startup() when we know we
are not remoting). These changes are left for later to avoid making
this patch huge.

Command-line parameter parsing is done in the main method and
parameters are passed to the application through a
EphyApplicationStartupContext structure, which is later passed as a
GVariant to the primare instance. This way we avoid moving the
GOption code out of the place where it's intended to run: in the
main() method.

Based in work by Alexandre Mazari.
Comment 21 Claudio Saavedra 2011-06-20 22:34:22 UTC
Created attachment 190322 [details] [review]
Implement GtkApplication based activation and uniqueness

This replaces the existing dbus-glib activation and uniqueness code.
The changes are kept to the minimum necessary to make all the features
work, but there are still some optimizations possible (like doing most
of the initialization in ephy_application_startup() when we know we
are not remoting). These changes are left for later to avoid making
this patch huge.

Command-line parameter parsing is done in the main method and
parameters are passed to the application through a
EphyApplicationStartupContext structure, which is later passed as a
GVariant to the primare instance. This way we avoid moving the
GOption code out of the place where it's intended to run: in the
main() method.

Based in work by Alexandre Mazari.
Comment 22 Claudio Saavedra 2011-06-20 22:34:51 UTC
Comment on attachment 190319 [details] [review]
Implement GtkApplication based activation and uniqueness

missing files
Comment 23 Claudio Saavedra 2011-06-21 09:22:11 UTC
Created attachment 190351 [details] [review]
This is a new version, removing some cruft I left yesterday.

Implement GtkApplication based activation and uniqueness

This replaces the existing dbus-glib activation and uniqueness code.
The changes are kept to the minimum necessary to make all the features
work, but there are still some optimizations possible (like doing most
of the initialization in ephy_application_startup() when we know we
are not remoting). These changes are left for later to avoid making
this patch huge.

Command-line parameter parsing is done in the main method and
parameters are passed to the application through a
EphyApplicationStartupContext structure, which is later passed as a
GVariant to the primare instance. This way we avoid moving the
GOption code out of the place where it's intended to run: in the
main() method.

Based in work by Alexandre Mazari.
Comment 24 Xan Lopez 2011-06-21 15:52:49 UTC
Review of attachment 190351 [details] [review]:

::: src/ephy-application.c
@@ +32,3 @@
+#define EPHY_APPLICATION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_APPLICATION, EphyApplicationPrivate))
+struct _EphyApplicationPrivate
+{

Brace.

@@ +50,3 @@
+ * @bookmark_url: A URL to be added to the bookmarks.
+ * @arguments: A %NULL-terminated array of URLs and file URIs to be opened.
+ * @user_time: THe user time when the EphyApplication startup was invoked.

The.

@@ +60,3 @@
+ephy_application_startup_context_new (gboolean new_tab,
+                                      gboolean new_window,
+                                      gboolean bookmarks_editor,

These three could be flags probably, more extensible.

@@ +67,3 @@
+                                      guint32 user_time)
+{
+  EphyApplicationStartupContext *ctx = g_new0 (EphyApplicationStartupContext, 1);

I believe generally we use g_slice to alocate structures, but meh...

@@ +110,3 @@
+
+  shell = ephy_shell_get_default ();
+  g_assert (shell != NULL);

Don't really want to get into philosophical debates, but this seems like it's basically impossible, so the assert does not seem very useful.

@@ +112,3 @@
+  g_assert (shell != NULL);
+  session = EPHY_SESSION (ephy_shell_get_session (shell));
+  g_assert (session != NULL);

Same?

@@ +120,3 @@
+                                EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR,
+                                NULL, NULL, ctx->user_time, FALSE);
+  else if (ctx->session_filename != NULL)

The { style is all wrong in the rest of the function. Also is repeated throughout the file, so just go over it again I guess.

@@ +134,3 @@
+      GString *options;
+
+      options = g_string_sized_new (64);

Drop the microoptimization :P

@@ +221,3 @@
+                                          ctx->new_window,
+                                          ctx->bookmarks_editor,
+                                          UNNULLIFY(ctx->bookmarks_filename),

To be honest I don't mind just having s ? s : "", here, but if there's any way of not doing this kind of thing, better.

::: src/ephy-application.h
@@ +45,3 @@
+
+struct _EphyApplication
+{

I guess the brace should go in the previous line.

@@ +52,3 @@
+
+struct _EphyApplicationClass
+{

Same here.

@@ +57,3 @@
+
+typedef struct {
+  gchar **arguments;

char instead of gchar (see HACKING).

::: src/ephy-main.c
@@ +421,3 @@
+	application = ephy_application_new ();
+	ephy_shell_set_application (ephy_shell_get_default (),
+				    application);

If the Shell only can have one app, which can only be set once, perhaps it's better for now to just make the Shell create it and use the getter here.

::: src/ephy-shell.c
@@ +206,2 @@
 	shell->priv = EPHY_SHELL_GET_PRIVATE (shell);
+	shell->priv->application = NULL;

This is not really needed and we don't do it for the other members, so let's drop it.
Comment 25 Xan Lopez 2011-06-21 16:00:55 UTC
Another follow-up to this can be to get rid of the EphyEmbedShell _trak_object API, I suppose. I understand GtkApplication has something equivalent already built-in.
Comment 26 Claudio Saavedra 2011-06-21 16:45:15 UTC
Review of attachment 190351 [details] [review]:

::: src/ephy-application.c
@@ +60,3 @@
+ephy_application_startup_context_new (gboolean new_tab,
+                                      gboolean new_window,
+                                      gboolean bookmarks_editor,

Sure.

@@ +67,3 @@
+                                      guint32 user_time)
+{
+  EphyApplicationStartupContext *ctx = g_new0 (EphyApplicationStartupContext, 1);

Hm, I thought all these functions were using g_slice() internally..

@@ +110,3 @@
+
+  shell = ephy_shell_get_default ();
+  g_assert (shell != NULL);

This code is verbatim from the existing queue_commands() in main(), so I preferred to leave is as is. It can be fixed now or later, as you prefer.

@@ +112,3 @@
+  g_assert (shell != NULL);
+  session = EPHY_SESSION (ephy_shell_get_session (shell));
+  g_assert (session != NULL);

Same as above.

@@ +134,3 @@
+      GString *options;
+
+      options = g_string_sized_new (64);

Same as above comments.

@@ +221,3 @@
+                                          ctx->new_window,
+                                          ctx->bookmarks_editor,
+                                          UNNULLIFY(ctx->bookmarks_filename),

It's possible to instead use a dictionary variant and only append these that are not NULL. That could avoid these hacks.

::: src/ephy-main.c
@@ +421,3 @@
+	application = ephy_application_new ();
+	ephy_shell_set_application (ephy_shell_get_default (),
+				    application);

Sure.

::: src/ephy-shell.c
@@ +206,2 @@
 	shell->priv = EPHY_SHELL_GET_PRIVATE (shell);
+	shell->priv->application = NULL;

OK.
Comment 27 Xan Lopez 2011-06-21 19:59:41 UTC
In the cases where you are just copying code around I guess it's better to leave it as it is and then change it later if we feel like it.
Comment 28 Claudio Saavedra 2011-06-22 15:37:05 UTC
Created attachment 190448 [details] [review]
Implement GtkApplication based activation and uniqueness

- Hopefully fixed all style issues and typos. I also fixed those in
  the methods copied to avoid having commits later that only fix indentation.
- Use gslice functions where appropriate.
- Use flags instead of multiple boolean parameters in the context structure.
- Let the shell instantiate the EphyApplication and get it from there. Remove
  the setter as well.
- (the big change) use a GVariant dictionary array that is filed only
  with the command-line parameters that are actually passed on instantiation.
  This avoids filing up the variant with empty strings. However (as it can be
  seen) the packing/unpacking of the variant is a bit more complex; nevertheless
  way more readable.
- The recover session command is called always (apparently it's needed
  even for remote instantiations; it's the way it was in the original queue_commands()
  method.)

This replaces the existing dbus-glib activation and uniqueness code.
The changes are kept to the minimum necessary to make all the features
work, but there are still some optimizations possible (like doing most
of the initialization in ephy_application_startup() when we know we
are not remoting). These changes are left for later to avoid making
this patch huge.

Command-line parameter parsing is done in the main method and
parameters are passed to the application through a
EphyApplicationStartupContext structure, which is later passed as a
GVariant to the primare instance. This way we avoid moving the
GOption code out of the place where it's intended to run: in the
main() method.

Based in work by Alexandre Mazari.
Comment 29 Xan Lopez 2011-06-23 20:41:46 UTC
Review of attachment 190448 [details] [review]:

Looks good!

::: src/ephy-shell.c
@@ -800,0 +808,17 @@
+/**
+ * ephy_shell_get_application:
+ * @shell: A #EphyApplication
... 14 more ...

I think it makes more sense to do this in _init and just return it here. You can fix before landing.
Comment 30 Claudio Saavedra 2011-06-23 21:36:15 UTC
Attachment 190448 [details] pushed as 8415cf6 - Implement GtkApplication based activation and uniqueness