1 /* GTK - The GIMP Toolkit
3 * Copyright (C) 2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Colin Walters <walters@verbum.org>
24 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
25 * file for a list of people on the GTK+ Team. See the ChangeLog
26 * files for a list of changes. These files are distributed with
27 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
35 #include "gtkapplication.h"
38 #include "gtkprivate.h"
43 #ifdef GDK_WINDOWING_X11
44 #include <gdk/x11/gdkx.h>
48 * SECTION:gtkapplication
49 * @title: GtkApplication
50 * @short_description: Application class
52 * #GtkApplication is a class that handles many important aspects
53 * of a GTK+ application in a convenient fashion, without enforcing
54 * a one-size-fits-all application model.
56 * Currently, GtkApplication handles application uniqueness, provides
57 * some basic scriptability by exporting 'actions', implements some
58 * standard actions itself (such as 'Quit') and provides a main window
59 * whose life-cycle is automatically tied to the life-cycle of your
62 * <example id="gtkapplication"><title>A simple application</title>
64 * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/tests/gtk-example-application.c">
65 * <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
83 static guint gtk_application_signals[LAST_SIGNAL] = { 0 };
85 struct _GtkApplicationPrivate
87 GtkActionGroup *main_actions;
89 GtkWindow *default_window;
93 G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
96 gtk_application_default_quit (GApplication *application,
104 gtk_application_default_run (GApplication *application)
110 gtk_application_default_prepare_activation (GApplication *application,
112 GVariant *platform_data)
118 g_variant_iter_init (&iter, platform_data);
119 while (g_variant_iter_next (&iter, "{sv}", &key, &value))
121 if (strcmp (key, "startup-notification-id") == 0 &&
122 strcmp (g_variant_get_type_string (value), "s") == 0)
123 gdk_notify_startup_complete_with_id (g_variant_get_string (value, NULL));
125 g_variant_unref (value);
128 g_signal_emit (G_OBJECT (application), gtk_application_signals[ACTIVATED], 0, arguments);
132 gtk_application_default_activated (GApplication *application,
135 GtkApplication *app = GTK_APPLICATION (application);
137 /* TODO: should we raise the last focused window instead ? */
138 if (app->priv->default_window != NULL)
139 gtk_window_present (app->priv->default_window);
143 gtk_application_default_action (GApplication *application,
147 GtkApplication *app = GTK_APPLICATION (application);
148 GList *actions, *iter;
150 actions = gtk_action_group_list_actions (app->priv->main_actions);
151 for (iter = actions; iter; iter = iter->next)
153 GtkAction *gtkaction = iter->data;
154 if (strcmp (action, gtk_action_get_name (gtkaction)) == 0)
156 /* TODO set timestamp */
157 gtk_action_activate (gtkaction);
161 g_list_free (actions);
165 gtk_application_format_activation_data (void)
167 const gchar *startup_id = NULL;
168 GdkDisplay *display = gdk_display_get_default ();
169 GVariantBuilder builder;
171 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
173 /* try and get the startup notification id from GDK, the environment
174 * or, if everything else failed, fake one.
176 #ifdef GDK_WINDOWING_X11
177 startup_id = gdk_x11_display_get_startup_notification_id (display);
178 #endif /* GDK_WINDOWING_X11 */
181 g_variant_builder_add (&builder, "{sv}", "startup-notification-id",
182 g_variant_new ("s", startup_id));
183 return g_variant_builder_end (&builder);
187 * gtk_application_new:
188 * @argc: (allow-none) (inout): System argument count
189 * @argv: (allow-none) (inout): System argument vector
190 * @appid: System-dependent application identifier
192 * Create a new #GtkApplication, or if one has already been initialized
193 * in this process, return the existing instance. This function will as
194 * a side effect initialize the display system; see gtk_init().
196 * For the behavior if this application is running in another process,
197 * see g_application_new().
199 * Returns: (transfer full): A newly-referenced #GtkApplication
204 gtk_application_new (gint *argc,
210 gchar **argv_for_app;
211 GVariant *platform_data;
213 gtk_init (argc, argv);
216 argc_for_app = *argc;
220 argv_for_app = *argv;
224 app = g_object_new (GTK_TYPE_APPLICATION, "application-id", appid, NULL);
226 platform_data = gtk_application_format_activation_data ();
227 g_application_register_with_data (G_APPLICATION (app), argc_for_app, argv_for_app,
229 g_variant_unref (platform_data);
235 on_action_sensitive (GtkAction *action,
239 g_application_set_action_enabled (G_APPLICATION (app),
240 gtk_action_get_name (action),
241 gtk_action_get_sensitive (action));
245 * gtk_application_set_action_group:
246 * @app: A #GtkApplication
247 * @group: A #GtkActionGroup
249 * Set @group as this application's global action group.
250 * This will ensure the operating system interface uses
251 * these actions as follows:
254 * <listitem>In GNOME 2 this exposes the actions for scripting.</listitem>
255 * <listitem>In GNOME 3, this function populates the application menu.</listitem>
256 * <listitem>In Windows prior to version 7, this function does nothing.</listitem>
257 * <listitem>In Windows 7, this function adds "Tasks" to the Jump List.</listitem>
258 * <listitem>In Mac OS X, this function extends the Dock menu.</listitem>
261 * It is an error to call this function more than once.
266 gtk_application_set_action_group (GtkApplication *app,
267 GtkActionGroup *group)
269 GList *actions, *iter;
271 g_return_if_fail (GTK_IS_APPLICATION (app));
272 g_return_if_fail (app->priv->main_actions == NULL);
274 app->priv->main_actions = g_object_ref (group);
275 actions = gtk_action_group_list_actions (group);
276 for (iter = actions; iter; iter = iter->next)
278 GtkAction *action = iter->data;
279 g_application_add_action (G_APPLICATION (app),
280 gtk_action_get_name (action),
281 gtk_action_get_tooltip (action));
282 g_signal_connect (action, "notify::sensitive",
283 G_CALLBACK (on_action_sensitive), app);
285 g_list_free (actions);
289 gtk_application_on_window_destroy (GtkWidget *window,
292 GtkApplication *app = GTK_APPLICATION (user_data);
294 app->priv->windows = g_slist_remove (app->priv->windows, window);
296 if (app->priv->windows == NULL)
297 gtk_application_quit (app);
302 static gchar *default_title;
305 * gtk_application_add_window:
306 * @app: a #GtkApplication
307 * @window: a toplevel window to add to @app
309 * Adds a window to the #GtkApplication.
311 * If the user closes all of the windows added to @app, the default
312 * behaviour is to call gtk_application_quit().
314 * If your application uses only a single toplevel window, you can
315 * use gtk_application_get_window().
320 gtk_application_add_window (GtkApplication *app,
323 app->priv->windows = g_slist_prepend (app->priv->windows, window);
325 if (gtk_window_get_title (window) == NULL && default_title != NULL)
326 gtk_window_set_title (window, default_title);
328 g_signal_connect (window, "destroy",
329 G_CALLBACK (gtk_application_on_window_destroy), app);
333 * gtk_application_get_window:
334 * @app: a #GtkApplication
336 * A simple #GtkApplication has a "default window". This window should
337 * act as the primary user interaction point with your application.
338 * The window returned by this function is of type #GTK_WINDOW_TYPE_TOPLEVEL
339 * and its properties such as "title" and "icon-name" will be initialized
340 * as appropriate for the platform.
342 * If the user closes this window, and your application hasn't created
343 * any other windows, the default action will be to call gtk_application_quit().
345 * If your application has more than one toplevel window (e.g. an
346 * single-document-interface application with multiple open documents),
347 * or if you are constructing your toplevel windows yourself (e.g. using
348 * #GtkBuilder), use gtk_application_add_window() instead.
350 * Returns: (transfer none): The default #GtkWindow for this application
355 gtk_application_get_window (GtkApplication *app)
357 if (app->priv->default_window != NULL)
358 return app->priv->default_window;
360 app->priv->default_window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
361 g_object_ref_sink (app->priv->default_window);
363 gtk_application_add_window (app, app->priv->default_window);
365 return app->priv->default_window;
369 * gtk_application_run:
370 * @app: a #GtkApplication
372 * Runs the main loop; see g_application_run().
373 * The default implementation for #GtkApplication uses gtk_main().
378 gtk_application_run (GtkApplication *app)
380 g_application_run (G_APPLICATION (app));
384 * gtk_application_quit:
385 * @app: a #GtkApplication
387 * Request the application exit.
388 * By default, this method will exit the main loop; see gtk_main_quit().
393 gtk_application_quit (GtkApplication *app)
395 g_application_quit (G_APPLICATION (app), gtk_get_current_event_time ());
399 gtk_application_get_property (GObject *object,
404 GtkApplication *app = GTK_APPLICATION (object);
409 g_value_set_object (value, gtk_application_get_window (app));
412 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417 gtk_application_set_property (GObject *object,
422 GtkApplication *app = GTK_APPLICATION (object);
424 g_assert (app != NULL);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
434 setup_default_window_decorations (void)
437 const gchar *filename;
442 pid = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID");
443 filename = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE");
445 keyfile = g_key_file_new ();
447 if (pid != NULL && filename != NULL && atoi (pid) == getpid () &&
448 g_key_file_load_from_file (keyfile, filename, 0, NULL))
450 title = g_key_file_get_locale_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, NULL);
451 icon_name = g_key_file_get_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL);
453 g_print ("default title: %s\n", title);
454 g_print ("default icon: %s\n", icon_name);
456 if (default_title == NULL)
457 default_title = title;
459 if (gtk_window_get_default_icon_name () == NULL)
460 gtk_window_set_default_icon_name (icon_name);
465 g_key_file_free (keyfile);
469 gtk_application_init (GtkApplication *application)
471 application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application, GTK_TYPE_APPLICATION, GtkApplicationPrivate);
473 setup_default_window_decorations ();
478 gtk_application_constructor (GType type,
479 guint n_construct_properties,
480 GObjectConstructParam *construct_params)
484 /* Last ditch effort here */
487 object = (* G_OBJECT_CLASS (gtk_application_parent_class)->constructor) (type,
488 n_construct_properties,
495 gtk_application_class_init (GtkApplicationClass *klass)
497 GObjectClass *gobject_class;
498 GApplicationClass *application_class;
500 gobject_class = G_OBJECT_CLASS (klass);
501 application_class = G_APPLICATION_CLASS (klass);
503 gobject_class->constructor = gtk_application_constructor;
504 gobject_class->get_property = gtk_application_get_property;
505 gobject_class->set_property = gtk_application_set_property;
507 application_class->run = gtk_application_default_run;
508 application_class->quit = gtk_application_default_quit;
509 application_class->action = gtk_application_default_action;
510 application_class->prepare_activation = gtk_application_default_prepare_activation;
512 klass->activated = gtk_application_default_activated;
515 * GtkApplication::activated:
516 * @arguments: A #GVariant with the signature "aay"
518 * This signal is emitted when a non-primary process for a given
519 * application is invoked while your application is running; for
520 * example, when a file browser launches your program to open a
521 * file. The raw operating system arguments are passed in the
522 * variant @arguments.
525 gtk_application_signals[ACTIVATED] =
526 g_signal_new (g_intern_static_string ("activated"),
527 G_OBJECT_CLASS_TYPE (klass),
529 G_STRUCT_OFFSET (GtkApplicationClass, activated),
531 g_cclosure_marshal_VOID__BOXED,
535 g_type_class_add_private (gobject_class, sizeof (GtkApplicationPrivate));
538 #define __GTK_APPLICATION_C__
539 #include "gtkaliasdef.c"