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"
37 #include "gtkmarshalers.h"
39 #include "gtkprivate.h"
42 #ifdef GDK_WINDOWING_X11
43 #include <gdk/x11/gdkx.h>
47 * SECTION:gtkapplication
48 * @title: GtkApplication
49 * @short_description: Application class
51 * #GtkApplication is a class that handles many important aspects
52 * of a GTK+ application in a convenient fashion, without enforcing
53 * a one-size-fits-all application model.
55 * Currently, GtkApplication handles application uniqueness, provides
56 * some basic scriptability by exporting 'actions', implements some
57 * standard actions itself (such as 'Quit') and provides a main window
58 * whose life-cycle is automatically tied to the life-cycle of your
61 * <example id="gtkapplication"><title>A simple application</title>
63 * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/tests/gtk-example-application.c">
64 * <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
85 static guint gtk_application_signals[LAST_SIGNAL] = { 0 };
87 struct _GtkApplicationPrivate
89 GtkActionGroup *main_actions;
91 GtkWindow *default_window;
95 G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
98 process_timestamp_from_platform_data (GVariant *platform_data)
100 /* TODO - extract timestamp from here, update GDK time */
104 gtk_application_default_quit (GtkApplication *application)
111 gtk_application_default_quit_with_data (GApplication *application,
112 GVariant *platform_data)
116 process_timestamp_from_platform_data (platform_data);
118 g_signal_emit (application, gtk_application_signals[QUIT], 0, &result);
124 gtk_application_default_run (GApplication *application)
130 gtk_application_default_prepare_activation (GApplication *application,
132 GVariant *platform_data)
138 g_variant_iter_init (&iter, platform_data);
139 while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
141 if (strcmp (key, "startup-notification-id") == 0 &&
142 g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
143 gdk_notify_startup_complete_with_id (g_variant_get_string (value, NULL));
144 g_variant_unref (value);
147 g_signal_emit (G_OBJECT (application), gtk_application_signals[ACTIVATED], 0, arguments);
151 gtk_application_default_activated (GtkApplication *application,
154 GtkApplicationPrivate *priv = application->priv;
156 /* TODO: should we raise the last focused window instead ? */
157 if (priv->default_window != NULL)
158 gtk_window_present (priv->default_window);
162 gtk_application_default_action (GtkApplication *application,
163 const gchar *action_name)
165 GtkApplicationPrivate *priv = application->priv;
168 action = gtk_action_group_get_action (priv->main_actions, action_name);
170 gtk_action_activate (action);
174 gtk_application_default_create_window (GtkApplication *application)
176 return GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
180 gtk_application_default_action_with_data (GApplication *application,
181 const gchar *action_name,
182 GVariant *platform_data)
184 process_timestamp_from_platform_data (platform_data);
186 g_signal_emit (application, gtk_application_signals[ACTION], g_quark_from_string (action_name));
190 gtk_application_format_activation_data (void)
192 const gchar *startup_id = NULL;
193 GdkDisplay *display = gdk_display_get_default ();
194 GVariantBuilder builder;
196 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
198 /* try and get the startup notification id from GDK, the environment
199 * or, if everything else failed, fake one.
201 #ifdef GDK_WINDOWING_X11
202 startup_id = gdk_x11_display_get_startup_notification_id (display);
203 #endif /* GDK_WINDOWING_X11 */
206 g_variant_builder_add (&builder, "{sv}", "startup-notification-id",
207 g_variant_new ("s", startup_id));
208 return g_variant_builder_end (&builder);
212 * gtk_application_new:
213 * @appid: System-dependent application identifier
214 * @argc: (allow-none) (inout): System argument count
215 * @argv: (allow-none) (inout): System argument vector
217 * Create a new #GtkApplication, or if one has already been initialized
218 * in this process, return the existing instance. This function will as
219 * a side effect initialize the display system; see gtk_init().
221 * For the behavior if this application is running in another process,
222 * see g_application_new().
224 * Returns: (transfer full): A newly-referenced #GtkApplication
229 gtk_application_new (const gchar *appid,
235 const gchar **argv_for_app;
236 GVariant *argv_variant;
237 GError *error = NULL;
239 gtk_init (argc, argv);
242 argc_for_app = *argc;
247 argv_for_app = (const gchar **) *argv;
251 argv_variant = g_variant_new_bytestring_array (argv_for_app, argc_for_app);
253 app = g_initable_new (GTK_TYPE_APPLICATION,
256 "application-id", appid,
257 "argv", argv_variant,
261 g_error ("%s", error->message);
262 g_clear_error (&error);
270 on_action_sensitive (GtkAction *action,
274 g_application_set_action_enabled (G_APPLICATION (app),
275 gtk_action_get_name (action),
276 gtk_action_get_sensitive (action));
280 * gtk_application_set_action_group:
281 * @app: A #GtkApplication
282 * @group: A #GtkActionGroup
284 * Set @group as this application's global action group.
285 * This will ensure the operating system interface uses
286 * these actions as follows:
289 * <listitem>In GNOME 2 this exposes the actions for scripting.</listitem>
290 * <listitem>In GNOME 3, this function populates the application menu.</listitem>
291 * <listitem>In Windows prior to version 7, this function does nothing.</listitem>
292 * <listitem>In Windows 7, this function adds "Tasks" to the Jump List.</listitem>
293 * <listitem>In Mac OS X, this function extends the Dock menu.</listitem>
296 * It is an error to call this function more than once.
301 gtk_application_set_action_group (GtkApplication *app,
302 GtkActionGroup *group)
304 GList *actions, *iter;
306 g_return_if_fail (GTK_IS_APPLICATION (app));
307 g_return_if_fail (GTK_IS_ACTION_GROUP (group));
308 g_return_if_fail (app->priv->main_actions == NULL);
310 app->priv->main_actions = g_object_ref (group);
311 actions = gtk_action_group_list_actions (group);
312 for (iter = actions; iter; iter = iter->next)
314 GtkAction *action = iter->data;
315 g_application_add_action (G_APPLICATION (app),
316 gtk_action_get_name (action),
317 gtk_action_get_tooltip (action));
318 g_signal_connect (action, "notify::sensitive",
319 G_CALLBACK (on_action_sensitive), app);
321 g_list_free (actions);
325 gtk_application_on_window_destroy (GtkWidget *window,
328 GtkApplication *app = GTK_APPLICATION (user_data);
330 app->priv->windows = g_slist_remove (app->priv->windows, window);
332 if (app->priv->windows == NULL)
333 gtk_application_quit (app);
338 static gchar *default_title;
341 * gtk_application_add_window:
342 * @app: a #GtkApplication
343 * @window: a toplevel window to add to @app
345 * Adds a window to the #GtkApplication.
347 * If all the windows managed by #GtkApplication are closed, the
348 * #GtkApplication will call gtk_application_quit(), and quit
351 * If your application uses only a single toplevel window, you can
352 * use gtk_application_get_window(). If you are using a sub-class
353 * of #GtkApplication you should call gtk_application_create_window()
354 * to let the #GtkApplication instance create a #GtkWindow and add
355 * it to the list of toplevels of the application. You should call
356 * this function only to add #GtkWindow<!-- -->s that you created
357 * directly using gtk_window_new().
362 gtk_application_add_window (GtkApplication *app,
365 GtkApplicationPrivate *priv;
367 g_return_if_fail (GTK_IS_APPLICATION (app));
368 g_return_if_fail (GTK_IS_WINDOW (window));
372 if (g_slist_find (priv->windows, window) != NULL)
375 priv->windows = g_slist_prepend (priv->windows, window);
377 if (priv->default_window == NULL)
378 priv->default_window = window;
380 if (gtk_window_get_title (window) == NULL && default_title != NULL)
381 gtk_window_set_title (window, default_title);
383 g_signal_connect (window, "destroy",
384 G_CALLBACK (gtk_application_on_window_destroy),
389 * gtk_application_get_window:
390 * @app: a #GtkApplication
392 * A simple #GtkApplication has a "default window". This window should
393 * act as the primary user interaction point with your application.
394 * The window returned by this function is of type #GTK_WINDOW_TYPE_TOPLEVEL
395 * and its properties such as "title" and "icon-name" will be initialized
396 * as appropriate for the platform.
398 * If the user closes this window, and your application hasn't created
399 * any other windows, the default action will be to call gtk_application_quit().
401 * If your application has more than one toplevel window (e.g. an
402 * single-document-interface application with multiple open documents),
403 * or if you are constructing your toplevel windows yourself (e.g. using
404 * #GtkBuilder), use gtk_application_create_window() or
405 * gtk_application_add_window() instead.
407 * Returns: (transfer none): The default #GtkWindow for this application
412 gtk_application_get_window (GtkApplication *app)
414 GtkApplicationPrivate *priv;
416 g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
420 if (priv->default_window != NULL)
421 return priv->default_window;
423 return gtk_application_create_window (app);
427 * gtk_application_get_windows:
428 * @app: a #GtkApplication
430 * Retrieves the list of windows previously registered with
431 * gtk_application_create_window() or gtk_application_add_window().
433 * Return value: (element-type GtkWindow) (transfer none): A pointer
434 * to the list of #GtkWindow<!-- -->s registered by this application,
435 * or %NULL. The returned #GSList is owned by the #GtkApplication
436 * and it should not be modified or freed directly.
440 G_CONST_RETURN GSList *
441 gtk_application_get_windows (GtkApplication *app)
443 g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
445 return app->priv->windows;
449 * gtk_application_create_window:
450 * @app: a #GtkApplication
452 * Creates a new #GtkWindow for the application.
454 * This function calls the #GtkApplication::create_window() virtual function,
455 * which can be overridden by sub-classes, for instance to use #GtkBuilder to
456 * create the user interface. After creating a new #GtkWindow instance, it will
457 * be added to the list of toplevels associated to the application.
459 * Return value: (transfer none): the newly created application #GtkWindow
464 gtk_application_create_window (GtkApplication *app)
468 g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
470 window = GTK_APPLICATION_GET_CLASS (app)->create_window (app);
471 gtk_application_add_window (app, window);
477 * gtk_application_run:
478 * @app: a #GtkApplication
480 * Runs the main loop; see g_application_run().
481 * The default implementation for #GtkApplication uses gtk_main().
486 gtk_application_run (GtkApplication *app)
488 g_application_run (G_APPLICATION (app));
492 * gtk_application_quit:
493 * @app: a #GtkApplication
495 * Request the application exit. This function invokes
496 * g_application_quit_with_data(), which normally will
497 * in turn cause @app to emit #GtkApplication::quit.
499 * To control an application's quit behavior (for example, to ask for
500 * files to be saved), connect to the #GtkApplication::quit signal
506 gtk_application_quit (GtkApplication *app)
508 GVariantBuilder builder;
509 GVariant *platform_data;
511 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
512 g_variant_builder_add (&builder, "{sv}",
514 g_variant_new ("u", gtk_get_current_event_time ()));
515 platform_data = g_variant_builder_end (&builder);
517 g_application_quit_with_data (G_APPLICATION (app), platform_data);
519 g_variant_unref (platform_data);
523 gtk_application_get_property (GObject *object,
528 GtkApplication *app = GTK_APPLICATION (object);
533 g_value_set_object (value, gtk_application_get_window (app));
536 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541 gtk_application_set_property (GObject *object,
546 GtkApplication *app = GTK_APPLICATION (object);
548 g_assert (app != NULL);
553 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
558 setup_default_window_decorations (void)
561 const gchar *filename;
566 pid = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID");
567 filename = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE");
569 keyfile = g_key_file_new ();
571 if (pid != NULL && filename != NULL && atoi (pid) == getpid () &&
572 g_key_file_load_from_file (keyfile, filename, 0, NULL))
574 title = g_key_file_get_locale_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, NULL);
575 icon_name = g_key_file_get_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL);
577 if (default_title == NULL)
578 default_title = title;
580 if (gtk_window_get_default_icon_name () == NULL)
581 gtk_window_set_default_icon_name (icon_name);
586 g_key_file_free (keyfile);
590 gtk_application_init (GtkApplication *application)
592 application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application, GTK_TYPE_APPLICATION, GtkApplicationPrivate);
594 g_object_set (application, "platform-data", gtk_application_format_activation_data (), NULL);
596 setup_default_window_decorations ();
601 gtk_application_constructor (GType type,
602 guint n_construct_properties,
603 GObjectConstructParam *construct_params)
607 /* Last ditch effort here */
610 object = (* G_OBJECT_CLASS (gtk_application_parent_class)->constructor) (type,
611 n_construct_properties,
618 gtk_application_class_init (GtkApplicationClass *klass)
620 GObjectClass *gobject_class;
621 GApplicationClass *application_class;
623 gobject_class = G_OBJECT_CLASS (klass);
624 application_class = G_APPLICATION_CLASS (klass);
626 gobject_class->constructor = gtk_application_constructor;
627 gobject_class->get_property = gtk_application_get_property;
628 gobject_class->set_property = gtk_application_set_property;
630 application_class->run = gtk_application_default_run;
631 application_class->quit_with_data = gtk_application_default_quit_with_data;
632 application_class->action_with_data = gtk_application_default_action_with_data;
633 application_class->prepare_activation = gtk_application_default_prepare_activation;
635 klass->quit = gtk_application_default_quit;
636 klass->action = gtk_application_default_action;
637 klass->create_window = gtk_application_default_create_window;
639 klass->activated = gtk_application_default_activated;
642 * GtkApplication::activated:
643 * @arguments: A #GVariant with the signature "aay"
645 * This signal is emitted when a non-primary process for a given
646 * application is invoked while your application is running; for
647 * example, when a file browser launches your program to open a
648 * file. The raw operating system arguments are passed in the
649 * variant @arguments.
653 gtk_application_signals[ACTIVATED] =
654 g_signal_new (g_intern_static_string ("activated"),
655 G_OBJECT_CLASS_TYPE (klass),
657 G_STRUCT_OFFSET (GtkApplicationClass, activated),
659 g_cclosure_marshal_VOID__VARIANT,
664 * GtkApplication::quit:
665 * @application: the object on which the signal is emitted
667 * This signal is emitted when a quit is initiated. See also
668 * the #GApplication::quit-with-data signal which may in
669 * turn trigger this signal.
671 * The default handler for this signal exits the mainloop of the
672 * application. It is possible to override the default handler
673 * by simply returning %TRUE from a callback, e.g.:
677 * my_application_quit (GtkApplication *application)
679 * /* if some_condition is TRUE, do not quit */
680 * if (some_condition)
683 * /* this will cause the application to quit *
687 * g_signal_connect (application, "quit",
688 * G_CALLBACK (my_application_quit),
692 * Returns: %TRUE if the signal has been handled, %FALSE to continue
697 gtk_application_signals[QUIT] =
698 g_signal_new (g_intern_static_string ("quit"),
699 G_OBJECT_CLASS_TYPE (klass),
701 G_STRUCT_OFFSET (GtkApplicationClass, quit),
702 g_signal_accumulator_true_handled, NULL,
703 _gtk_marshal_BOOLEAN__VOID,
707 * GtkApplication::action:
708 * @application: the object on which the signal is emitted
709 * @name: The name of the activated action
711 * This signal is emitted when an action is activated. The action name
712 * is passed as the first argument, but also as signal detail, so it
713 * is possible to connect to this signal for individual actions.
715 * See also the #GApplication::action-with-data signal which may in
716 * turn trigger this signal.
718 * The signal is never emitted for disabled actions.
722 gtk_application_signals[ACTION] =
723 g_signal_new (g_intern_static_string ("action"),
724 G_OBJECT_CLASS_TYPE (klass),
725 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED,
726 G_STRUCT_OFFSET (GtkApplicationClass, action),
728 g_cclosure_marshal_VOID__STRING,
732 g_type_class_add_private (gobject_class, sizeof (GtkApplicationPrivate));