[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gtk-devel
Subject:    single instance (was Re: Minutes of the GTK+ meeting at GUADEC)
From:       Havoc Pennington <hp () redhat ! com>
Date:       2007-08-10 20:58:04
Message-ID: 46BCD15C.1070601 () redhat ! com
[Download RAW message or body]

Hi,

Kristian Rietveld wrote:
> GUnique was brought up as a possible feature for 2.14, a small discussion
> about its usefulness as "stand-alone" feature emerged.  It doesn't make all
> that much sense without an application window class, subsequently an
> application window class doesn't make much sense without session
> management.  Basically, you start questioning whether you want to introduce
> a document based window/application model (like Cocoa has) -- getting this
> done requires a good amount of work and discussion because it possibly
> takes over a lot.  In the end we concluded that all of this would be more
> useful as a higher level library including all these pieces.

I don't buy this really, though obviously I missed the conversation ;-)

I would expect a basic API like the following, though a high-level app 
window thing could be useful too.

void
handle_application_launch(GdkScreen *screen,
                           GtkLaunch *launch,
                           void      *data)
{
   GSList *urls;
   GtkWindow *document_window;

   urls = gtk_launch_get_property(launch, "urls");

   foreach (url in urls) {
     /* get a GtkWindow with startup notification stuff
      * from the launch properly configured; in real life
      * you'd probably have an application window subclass,
      * or a GtkAppWindow, or whatever, but those things
      * would build on this.
      */
     if (already have window for url) {
        document_window = window we already have;
        gtk_window_present_from_launch(document_window, launch);
     } else {
        document_window = gtk_window_new_for_launch(screen, launch);
        gtk_window_show (document_window);
     }
   }
}

void
handle_lost_single_instance(void *data)
{
   exit(0);
}

int
main(int argc, char **argv)
{
   gtk_init_single_instance(argc, argv, "org.gnome.MyAppBusName",
                            0, /* flags or something */
                            handle_application_launch, NULL,
                            handle_lost_single_instance, NULL);

   gtk_main();

   return 0;
}

Where init_single_instance will try to send the launch details to the 
bus name, which will be activated if necessary; if that fails, then it 
would try to get the bus name itself, and if it gets it, calls 
handle_application_launch within the current process. If the bus name is 
never obtained or is later lost, handle_lost_single_instance is called.

This can implement a --replace option automatically.

Details forwarded to the existing bus name would include env variables 
and command line options, as needed, there are some tricky bits to sort 
that out.

init_single_instance need not open the X display until it knows it needs 
to call handle_application_launch().

The whole connect-to-bus-and-wait-for-bus-name thing can be done 
asynchronously, so if the app wanted to do something else after 
init_single_instance then it could. gtk_init_single_instance() would 
"fire off" the bus name request, then return, so in gtk_main() either 
handle_application_launch or handle_lost_single_instance ends up getting 
called. This means that initial app startup and later opening of a new 
window uses *the same codepath*

Standard API could be offered to "simulate" a launch within the process, 
for e.g. a New... or Open menu item, which ideally ends up just calling 
handle_application_launch():
   gtk_launch_open_document(GdkScreen *screen, const char * bus_name,
                            const char *url);
or whatever. Heck this could also work fine with other apps, it could 
just happen to send the dbus message to itself if the current app owned 
the bus name.

Obviously there is some API fine-tuning, e.g. maybe a struct of handlers 
is better than a bunch of function args for gtk_init_single_instance, as 
one drop in the fine-tuning bucket. Or another example is that having to 
do the full gtk_init is a pain, ideally there's a 
gtk_launch_set_handlers() that is separate and the gtk_init thing is 
just a convenience API.

Anyway this is a ton of good functionality for an app, and something 
everyone is getting wrong hand-coding, so I would not wait for an 
AppWindow widget and stuff.

Havoc
_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-devel-list
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic