[gtk+] Add GtkApplication
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Add GtkApplication
- Date: Mon, 7 Jun 2010 20:49:26 +0000 (UTC)
commit 1ae257d00a2921f903048777664f1f171ff24c9b
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Jun 7 16:44:58 2010 -0400
Add GtkApplication
This is a work in progress to stub out an application class. The
primary goal is to provide a mechanism for applications to export
GtkActions, and there is a standard "Quit" action.
This is based on GApplication.
Future work:
* Add a way to say "This is my application menubar", which gets
put into all toplevel windows on non-OS-X, and into the top
on OS X.
* Support session management.
* Support application settings.
https://bugzilla.gnome.org/show_bug.cgi?id=127958
docs/reference/gtk/gtk-docs.sgml | 9 +-
docs/reference/gtk/gtk3-sections.txt | 25 ++
docs/reference/gtk/gtk3.types | 1 +
gtk/Makefile.am | 2 +
gtk/gtk.h | 1 +
gtk/gtk.symbols | 11 +
gtk/gtkapplication.c | 540 ++++++++++++++++++++++++++++++++++
gtk/gtkapplication.h | 100 +++++++
gtk/tests/Makefile.am | 6 +-
gtk/tests/gtk-example-application.c | 60 ++++
tests/Makefile.am | 7 +-
tests/testapplication.c | 105 +++++++
tests/testapplication.desktop | 6 +
13 files changed, 868 insertions(+), 5 deletions(-)
---
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index 7f5b99c..3ffb6c2 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -407,6 +407,11 @@ that is, GUI components such as #GtkButton or #GtkTextView.
<xi:include href="xml/gtkbuildable.xml" />
<xi:include href="xml/gtkbuilder.xml" />
</chapter>
+
+ <chapter id="Application">
+ <title>Application support</title>
+ <xi:include href="xml/gtkapplication.xml" />
+ </chapter>
</part>
<part id="migrating">
@@ -414,8 +419,8 @@ that is, GUI components such as #GtkButton or #GtkTextView.
<partintro>
<para>
- This part describes what you need to change in programs use
- older versions of GTK+ so that they can use the new features.
+ This part describes what you need to change in programs use
+ older versions of GTK+ so that they can use the new features.
It also mentions how to convert applications using widgets
found in the libgnomeui library to use their counterparts
in GTK+.
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 5d12c3d..c7ef3c2 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -6340,3 +6340,28 @@ GTK_TYPE_EXTENDED_LAYOUT
<SUBSECTION Private>
gtk_extended_layout_get_type
</SECTION>
+
+<SECTION>
+<FILE>gtkapplication</FILE>
+<TITLE>GtkApplication</TITLE>
+GtkApplication
+
+gtk_application_new
+gtk_application_run
+gtk_application_quit
+gtk_application_set_action_group
+gtk_application_get_window
+gtk_application_add_window
+
+<SUBSECTION Standard>
+GtkApplicationClass
+GTK_TYPE_APPLICATION
+GTK_APPLICATION
+GTK_APPLICATION_CLASS
+GTK_IS_APPLICATION
+GTK_IS_APPLICATION_CLASS
+GTK_APPLICATION_GET_CLASS
+<SUBSECTION Private>
+gtk_application_get_type
+GtkApplicationPrivate
+</SECTION>
diff --git a/docs/reference/gtk/gtk3.types b/docs/reference/gtk/gtk3.types
index 873c63b..b03bb0c 100644
--- a/docs/reference/gtk/gtk3.types
+++ b/docs/reference/gtk/gtk3.types
@@ -11,6 +11,7 @@ gtk_action_group_get_type
gtk_activatable_get_type
gtk_adjustment_get_type
gtk_alignment_get_type
+gtk_application_get_type
gtk_arrow_get_type
gtk_aspect_frame_get_type
gtk_assistant_get_type
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ce1e2af..e10be5f 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -170,6 +170,7 @@ gtk_public_h_sources = \
gtkactivatable.h \
gtkadjustment.h \
gtkalignment.h \
+ gtkapplication.h \
gtkarrow.h \
gtkaspectframe.h \
gtkassistant.h \
@@ -428,6 +429,7 @@ gtk_base_c_sources = \
gtkactivatable.c \
gtkadjustment.c \
gtkalignment.c \
+ gtkapplication.c \
gtkarrow.c \
gtkaspectframe.c \
gtkassistant.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index cbac475..120555b 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -40,6 +40,7 @@
#include <gtk/gtkactivatable.h>
#include <gtk/gtkadjustment.h>
#include <gtk/gtkalignment.h>
+#include <gtk/gtkapplication.h>
#include <gtk/gtkarrow.h>
#include <gtk/gtkaspectframe.h>
#include <gtk/gtkassistant.h>
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 03b815a..6439b90 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -257,6 +257,17 @@ gtk_alignment_set_padding
#endif
#endif
+#if IN_HEADER(__GTK_APPLICATION_H__)
+#if IN_FILE(__GTK_APPLICATION_C__)
+gtk_application_get_type G_GNUC_CONST
+gtk_application_new
+gtk_application_set_action_group
+gtk_application_get_window
+gtk_application_add_window
+gtk_application_run
+gtk_application_quit
+#endif
+#endif
#if IN_HEADER(__GTK_ASSISTANT_H__)
#if IN_FILE(__GTK_ASSISTANT_C__)
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
new file mode 100644
index 0000000..c8dbde9
--- /dev/null
+++ b/gtk/gtkapplication.c
@@ -0,0 +1,540 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "gtkapplication.h"
+#include "gtkmain.h"
+#include "gtkintl.h"
+#include "gtkprivate.h"
+
+#include "gtkalias.h"
+
+#include <gdk/gdk.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#endif
+
+/**
+ * SECTION:gtkapplication
+ * @title: GtkApplication
+ * @short_description: Application class
+ *
+ * #GtkApplication is a class that handles many important aspects
+ * of a GTK+ application in a convenient fashion, without enforcing
+ * a one-size-fits-all application model.
+ *
+ * Currently, GtkApplication handles application uniqueness, provides
+ * some basic scriptability by exporting 'actions', implements some
+ * standard actions itself (such as 'Quit') and provides a main window
+ * whose life-cycle is automatically tied to the life-cycle of your
+ * application.
+ *
+ * <example id="gtkapplication"><title>A simple application</title>
+ * <programlisting>
+ * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/tests/gtk-example-application.c">
+ * <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
+ * </xi:include>
+ * </programlisting>
+ * </example>
+ */
+enum
+{
+ PROP_0,
+ PROP_WINDOW
+};
+
+enum
+{
+ ACTIVATED,
+
+ LAST_SIGNAL
+};
+
+static guint gtk_application_signals[LAST_SIGNAL] = { 0 };
+
+struct _GtkApplicationPrivate
+{
+ char *appid;
+ GtkActionGroup *main_actions;
+
+ GtkWindow *default_window;
+ GSList *windows;
+};
+
+G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
+
+static gboolean
+gtk_application_default_quit (GApplication *application,
+ guint timestamp)
+{
+ gtk_main_quit ();
+ return TRUE;
+}
+
+static void
+gtk_application_default_run (GApplication *application)
+{
+ gtk_main ();
+}
+
+static void
+gtk_application_default_prepare_activation (GApplication *application,
+ GVariant *arguments,
+ GVariant *platform_data)
+{
+ GVariantIter iter;
+ gchar *key;
+ GVariant *value;
+
+ g_variant_iter_init (&iter, platform_data);
+ while (g_variant_iter_next (&iter, "{sv}", &key, &value))
+ {
+ if (strcmp (key, "startup-notification-id") == 0 &&
+ strcmp (g_variant_get_type_string (value), "s") == 0)
+ gdk_notify_startup_complete_with_id (g_variant_get_string (value, NULL));
+ g_free (key);
+ g_variant_unref (value);
+ }
+
+ g_signal_emit (G_OBJECT (application), gtk_application_signals[ACTIVATED], 0, arguments);
+}
+
+static void
+gtk_application_default_activated (GApplication *application,
+ GVariant *arguments)
+{
+ GtkApplication *app = GTK_APPLICATION (application);
+
+ /* TODO: should we raise the last focused window instead ? */
+ if (app->priv->default_window != NULL)
+ gtk_window_present (app->priv->default_window);
+}
+
+static void
+gtk_application_default_action (GApplication *application,
+ const gchar *action,
+ guint timestamp)
+{
+ GtkApplication *app = GTK_APPLICATION (application);
+ GList *actions, *iter;
+
+ actions = gtk_action_group_list_actions (app->priv->main_actions);
+ for (iter = actions; iter; iter = iter->next)
+ {
+ GtkAction *gtkaction = iter->data;
+ if (strcmp (action, gtk_action_get_name (gtkaction)) == 0)
+ {
+ /* TODO set timestamp */
+ gtk_action_activate (gtkaction);
+ break;
+ }
+ }
+ g_list_free (actions);
+}
+
+static GVariant *
+gtk_application_format_activation_data (void)
+{
+ const gchar *startup_id = NULL;
+ GdkDisplay *display = gdk_display_get_default ();
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ /* try and get the startup notification id from GDK, the environment
+ * or, if everything else failed, fake one.
+ */
+#ifdef GDK_WINDOWING_X11
+ startup_id = gdk_x11_display_get_startup_notification_id (display);
+#endif /* GDK_WINDOWING_X11 */
+
+ if (startup_id)
+ g_variant_builder_add (&builder, "{sv}", "startup-notification-id",
+ g_variant_new ("s", startup_id));
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * gtk_application_new:
+ * @argc: (allow-none) (inout): System argument count
+ * @argv: (allow-none) (inout): System argument vector
+ * @appid: System-dependent application identifier
+ *
+ * Create a new #GtkApplication, or if one has already been initialized
+ * in this process, return the existing instance. This function will as
+ * a side effect initialize the display system; see gtk_init().
+ *
+ * For the behavior if this application is running in another process,
+ * see g_application_new().
+ *
+ * Returns: (transfer full): A newly-referenced #GtkApplication
+ *
+ * Since: 3.0
+ */
+GtkApplication*
+gtk_application_new (gint *argc,
+ gchar ***argv,
+ const gchar *appid)
+{
+ GtkApplication *app;
+ gint argc_for_app;
+ gchar **argv_for_app;
+ GVariant *platform_data;
+
+ gtk_init (argc, argv);
+
+ if (argc)
+ argc_for_app = *argc;
+ else
+ argc_for_app = 0;
+ if (argv)
+ argv_for_app = *argv;
+ else
+ argv_for_app = NULL;
+
+ app = g_object_new (GTK_TYPE_APPLICATION, "appid", appid, NULL);
+
+ platform_data = gtk_application_format_activation_data ();
+ g_application_register_with_data (G_APPLICATION (app), argc_for_app, argv_for_app,
+ platform_data);
+ g_variant_unref (platform_data);
+
+ return app;
+}
+
+static void
+on_action_sensitive (GtkAction *action,
+ GParamSpec *pspec,
+ GtkApplication *app)
+{
+ g_application_set_action_enabled (G_APPLICATION (app),
+ gtk_action_get_name (action),
+ gtk_action_get_sensitive (action));
+}
+
+/**
+ * gtk_application_set_action_group:
+ * @app: A #GtkApplication
+ * @group: A #GtkActionGroup
+ *
+ * Set @group as this application's global action group.
+ * This will ensure the operating system interface uses
+ * these actions as follows:
+ *
+ * <itemizedlist>
+ * <listitem>In GNOME 2 this exposes the actions for scripting.</listitem>
+ * <listitem>In GNOME 3, this function populates the application menu.</listitem>
+ * <listitem>In Windows prior to version 7, this function does nothing.</listitem>
+ * <listitem>In Windows 7, this function adds "Tasks" to the Jump List.</listitem>
+ * <listitem>In Mac OS X, this function extends the Dock menu.</listitem>
+ * </itemizedlist>
+ *
+ * It is an error to call this function more than once.
+ *
+ * Since: 3.0
+ */
+void
+gtk_application_set_action_group (GtkApplication *app,
+ GtkActionGroup *group)
+{
+ GList *actions, *iter;
+
+ g_return_if_fail (GTK_IS_APPLICATION (app));
+ g_return_if_fail (app->priv->main_actions == NULL);
+
+ app->priv->main_actions = g_object_ref (group);
+ actions = gtk_action_group_list_actions (group);
+ for (iter = actions; iter; iter = iter->next)
+ {
+ GtkAction *action = iter->data;
+ g_application_add_action (G_APPLICATION (app),
+ gtk_action_get_name (action),
+ gtk_action_get_tooltip (action));
+ g_signal_connect (action, "notify::sensitive",
+ G_CALLBACK (on_action_sensitive), app);
+ }
+ g_list_free (actions);
+}
+
+static gboolean
+gtk_application_on_window_destroy (GtkWidget *window,
+ gpointer user_data)
+{
+ GtkApplication *app = GTK_APPLICATION (user_data);
+
+ app->priv->windows = g_slist_remove (app->priv->windows, window);
+
+ if (app->priv->windows == NULL)
+ gtk_application_quit (app);
+
+ return FALSE;
+}
+
+static gchar *default_title;
+
+/**
+ * gtk_application_add_window:
+ * @app: a #GtkApplication
+ * @window: a toplevel window to add to @app
+ *
+ * Adds a window to the #GtkApplication.
+ *
+ * If the user closes all of the windows added to @app, the default
+ * behaviour is to call gtk_application_quit().
+ *
+ * If your application uses only a single toplevel window, you can
+ * use gtk_application_get_window().
+ *
+ * Since: 3.0
+ */
+void
+gtk_application_add_window (GtkApplication *app,
+ GtkWindow *window)
+{
+ app->priv->windows = g_slist_prepend (app->priv->windows, window);
+
+ if (gtk_window_get_title (window) == NULL && default_title != NULL)
+ gtk_window_set_title (window, default_title);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_application_on_window_destroy), app);
+}
+
+/**
+ * gtk_application_get_window:
+ * @app: a #GtkApplication
+ *
+ * A simple #GtkApplication has a "default window". This window should
+ * act as the primary user interaction point with your application.
+ * The window returned by this function is of type #GTK_WINDOW_TYPE_TOPLEVEL
+ * and its properties such as "title" and "icon-name" will be initialized
+ * as appropriate for the platform.
+ *
+ * If the user closes this window, and your application hasn't created
+ * any other windows, the default action will be to call gtk_application_quit().
+ *
+ * If your application has more than one toplevel window (e.g. an
+ * single-document-interface application with multiple open documents),
+ * or if you are constructing your toplevel windows yourself (e.g. using
+ * #GtkBuilder), use gtk_application_add_window() instead.
+ *
+ * Returns: (transfer none): The default #GtkWindow for this application
+ *
+ * Since: 3.0
+ */
+GtkWindow *
+gtk_application_get_window (GtkApplication *app)
+{
+ if (app->priv->default_window != NULL)
+ return app->priv->default_window;
+
+ app->priv->default_window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
+ g_object_ref_sink (app->priv->default_window);
+
+ gtk_application_add_window (app, app->priv->default_window);
+
+ return app->priv->default_window;
+}
+
+/**
+ * gtk_application_run:
+ * @app: a #GtkApplication
+ *
+ * Runs the main loop; see g_application_run().
+ * The default implementation for #GtkApplication uses gtk_main().
+ *
+ * Since: 3.0
+ */
+void
+gtk_application_run (GtkApplication *app)
+{
+ g_application_run (G_APPLICATION (app));
+}
+
+/**
+ * gtk_application_quit:
+ * @app: a #GtkApplication
+ *
+ * Request the application exit.
+ * By default, this method will exit the main loop; see gtk_main_quit().
+ *
+ * Since: 3.0
+ */
+void
+gtk_application_quit (GtkApplication *app)
+{
+ g_application_quit (G_APPLICATION (app), gtk_get_current_event_time ());
+}
+
+static void
+gtk_application_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkApplication *app = GTK_APPLICATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ g_value_set_object (value, gtk_application_get_window (app));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_application_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkApplication *app = GTK_APPLICATION (object);
+
+ g_assert (app != NULL);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+setup_default_window_decorations (void)
+{
+ const gchar *pid;
+ const gchar *filename;
+ GKeyFile *keyfile;
+ gchar *title;
+ gchar *icon_name;
+
+ pid = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID");
+ filename = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE");
+
+ keyfile = g_key_file_new ();
+
+ if (pid != NULL && filename != NULL && atoi (pid) == getpid () &&
+ g_key_file_load_from_file (keyfile, filename, 0, NULL))
+ {
+ title = g_key_file_get_locale_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, NULL);
+ icon_name = g_key_file_get_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL);
+
+ g_print ("default title: %s\n", title);
+ g_print ("default icon: %s\n", icon_name);
+
+ if (default_title == NULL)
+ default_title = title;
+
+ if (gtk_window_get_default_icon_name () == NULL)
+ gtk_window_set_default_icon_name (icon_name);
+
+ g_free (icon_name);
+ }
+
+ g_key_file_free (keyfile);
+}
+
+static void
+gtk_application_init (GtkApplication *application)
+{
+ application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application, GTK_TYPE_APPLICATION, GtkApplicationPrivate);
+
+ setup_default_window_decorations ();
+}
+
+
+static GObject*
+gtk_application_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+
+ /* Last ditch effort here */
+ gtk_init (0, NULL);
+
+ object = (* G_OBJECT_CLASS (gtk_application_parent_class)->constructor) (type,
+ n_construct_properties,
+ construct_params);
+
+ return object;
+}
+
+static void
+gtk_application_class_init (GtkApplicationClass *klass)
+{
+ GObjectClass *gobject_class;
+ GApplicationClass *application_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ application_class = G_APPLICATION_CLASS (klass);
+
+ gobject_class->constructor = gtk_application_constructor;
+ gobject_class->get_property = gtk_application_get_property;
+ gobject_class->set_property = gtk_application_set_property;
+
+ application_class->run = gtk_application_default_run;
+ application_class->quit = gtk_application_default_quit;
+ application_class->action = gtk_application_default_action;
+ application_class->prepare_activation = gtk_application_default_prepare_activation;
+
+ klass->activated = gtk_application_default_activated;
+
+ /**
+ * GtkApplication::activated:
+ * @arguments: A #GVariant with the signature "aay"
+ *
+ * This signal is emitted when a non-primary process for a given
+ * application is invoked while your application is running; for
+ * example, when a file browser launches your program to open a
+ * file. The raw operating system arguments are passed in the
+ * variant @arguments.
+ */
+
+ gtk_application_signals[ACTIVATED] =
+ g_signal_new (g_intern_static_string ("activated"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkApplicationClass, activated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ G_TYPE_VARIANT);
+
+ g_type_class_add_private (gobject_class, sizeof (GtkApplicationPrivate));
+}
+
+#define __GTK_APPLICATION_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkapplication.h b/gtk/gtkapplication.h
new file mode 100644
index 0000000..6581bcd
--- /dev/null
+++ b/gtk/gtkapplication.h
@@ -0,0 +1,100 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_APPLICATION_H__
+#define __GTK_APPLICATION_H__
+
+#include <gio/gio.h>
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+#include <gtk/gtkwindow.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_APPLICATION (gtk_application_get_type ())
+#define GTK_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_APPLICATION, GtkApplication))
+#define GTK_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_APPLICATION, GtkApplicationClass))
+#define GTK_IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_APPLICATION))
+#define GTK_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_APPLICATION))
+#define GTK_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_APPLICATION, GtkApplicationClass))
+
+typedef struct _GtkApplication GtkApplication;
+typedef struct _GtkApplicationClass GtkApplicationClass;
+typedef struct _GtkApplicationPrivate GtkApplicationPrivate;
+
+struct _GtkApplication
+{
+ GApplication parent;
+
+ /*< private >*/
+
+ GtkApplicationPrivate *priv;
+};
+
+struct _GtkApplicationClass
+{
+ GApplicationClass parent_class;
+
+ /*< vfuncs >*/
+ void (* activated) (GApplication *application,
+ GVariant *args);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+ void (*_gtk_reserved5) (void);
+ void (*_gtk_reserved6) (void);
+ void (*_gtk_reserved7) (void);
+ void (*_gtk_reserved8) (void);
+ void (*_gtk_reserved9) (void);
+ void (*_gtk_reserved10) (void);
+};
+
+GType gtk_application_get_type (void) G_GNUC_CONST;
+GtkApplication* gtk_application_new (gint *argc,
+ gchar ***argv,
+ const gchar *appid);
+void gtk_application_set_action_group (GtkApplication *app,
+ GtkActionGroup *group);
+GtkWindow * gtk_application_get_window (GtkApplication *app);
+void gtk_application_add_window (GtkApplication *app,
+ GtkWindow *window);
+void gtk_application_run (GtkApplication *app);
+void gtk_application_quit (GtkApplication *app);
+
+G_END_DECLS
+
+#endif /* __GTK_APPLICATION_H__ */
+
diff --git a/gtk/tests/Makefile.am b/gtk/tests/Makefile.am
index cf209a1..803314f 100644
--- a/gtk/tests/Makefile.am
+++ b/gtk/tests/Makefile.am
@@ -20,7 +20,7 @@ progs_ldadd = \
$(top_builddir)/gtk/$(gtktargetlib) \
$(GTK_DEP_LIBS)
-noinst_PROGRAMS = $(TEST_PROGS)
+noinst_PROGRAMS = $(TEST_PROGS) $(SAMPLE_PROGS)
TEST_PROGS += testing
@@ -94,6 +94,10 @@ TEST_PROGS += action
action_SOURCES = action.c
action_LDADD = $(progs_ldadd)
+SAMPLE_PROGS = gtk-example-application
+gtk_example_application_SOURCES = gtk-example-application.c
+gtk_example_application_LDADD = $(progs_ldadd)
+
EXTRA_DIST += \
file-chooser-test-dir/empty \
diff --git a/gtk/tests/gtk-example-application.c b/gtk/tests/gtk-example-application.c
new file mode 100644
index 0000000..4248e0e
--- /dev/null
+++ b/gtk/tests/gtk-example-application.c
@@ -0,0 +1,60 @@
+#include <gtk/gtk.h>
+
+static const char *builder_data =
+"<interface>"
+"<object class=\"GtkAboutDialog\" id=\"about_dialog\">"
+" <property name=\"program-name\">Example Application</property>"
+" <property name=\"website\">http://www.gtk.org</property>"
+"</object>"
+"<object class=\"GtkActionGroup\" id=\"actions\">"
+" <child>"
+" <object class=\"GtkAction\" id=\"About\">"
+" <property name=\"name\">About</property>"
+" <property name=\"stock_id\">gtk-about</property>"
+" </object>"
+" </child>"
+"</object>"
+"</interface>";
+
+static GtkWidget *about_dialog;
+
+static void
+about_activate (GtkAction *action,
+ gpointer user_data)
+{
+ gtk_dialog_run (GTK_DIALOG (about_dialog));
+ gtk_widget_hide (GTK_WIDGET (about_dialog));
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkApplication *app;
+ GtkWindow *window;
+ GtkBuilder *builder;
+ GtkAction *action;
+ GtkActionGroup *actions;
+
+ app = gtk_application_new (&argc, &argv, "org.gtk.Example");
+ builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_string (builder, builder_data, -1, NULL))
+ g_error ("failed to parse UI");
+ actions = GTK_ACTION_GROUP (gtk_builder_get_object (builder, "actions"));
+ gtk_application_set_action_group (app, actions);
+
+ action = gtk_action_group_get_action (actions, "About");
+ g_signal_connect (action, "activate", G_CALLBACK (about_activate), app);
+
+ about_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "about_dialog"));
+
+ gtk_builder_connect_signals (builder, app);
+ g_object_unref (builder);
+
+ window = gtk_application_get_window (app);
+ gtk_container_add (GTK_CONTAINER (window), gtk_label_new ("Hello world"));
+ gtk_widget_show_all (GTK_WIDGET (window));
+
+ gtk_application_run (app);
+
+ return 0;
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a4a9f5f..a7c9705 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,8 @@ INCLUDES = \
-DGDK_DISABLE_DEPRECATED \
-DGTK_DISABLE_DEPRECATED \
$(GTK_DEBUG_FLAGS) \
- $(GTK_DEP_CFLAGS)
+ $(GTK_DEP_CFLAGS) \
+ $(GDK_DEP_CFLAGS)
DEPS = \
$(top_builddir)/gdk-pixbuf/libgdk_pixbuf-$(GTK_API_VERSION).la \
@@ -31,6 +32,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
print-editor \
extendedlayoutexample \
testaccel \
+ testapplication \
testassistant \
testbbox \
testbuttons \
@@ -116,6 +118,7 @@ extendedlayoutexample_DEPENDENCIES = $(TEST_DEPS)
testicontheme_DEPENDENCIES = $(TEST_DEPS)
testiconview_DEPENDENCIES = $(TEST_DEPS)
testaccel_DEPENDENCIES = $(TEST_DEPS)
+testapplication_DEPENDENCIES = $(TEST_DEPS)
testassistant_DEPENDENCIES = $(TEST_DEPS)
testbbox_DEPENDENCIES = $(TEST_DEPS)
testbuttons_DEPENDENCIES = $(TEST_DEPS)
@@ -178,6 +181,7 @@ simple_LDADD = $(LDADDS)
print_editor_LDADD = $(LDADDS)
extendedlayoutexample_LDADD = $(LDADDS)
testaccel_LDADD = $(LDADDS)
+testapplication_LDADD = $(LDADDS)
testassistant_LDADD = $(LDADDS)
testbbox_LDADD = $(LDADDS)
testbuttons_LDADD = $(LDADDS)
@@ -245,7 +249,6 @@ testtooltips_LDADD = $(LDADDS)
testvolumebutton_LDADD = $(LDADDS)
testwindows_LDADD = $(LDADDS)
-
testentrycompletion_SOURCES = \
prop-editor.c \
testentrycompletion.c
diff --git a/tests/testapplication.c b/tests/testapplication.c
new file mode 100644
index 0000000..a2883fa
--- /dev/null
+++ b/tests/testapplication.c
@@ -0,0 +1,105 @@
+/* GTK - The GIMP Toolkit
+ * testapplication.c: Using GtkApplication
+ * Copyright (C) 2010, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <gio/gdesktopappinfo.h>
+
+static const char *builder_data =
+"<interface>"
+"<object class=\"GtkAboutDialog\" id=\"about_dialog\">"
+" <property name=\"program-name\">Test Application</property>"
+" <property name=\"website\">http://gtk.org</property>"
+"</object>"
+"<object class=\"GtkActionGroup\" id=\"actions\">"
+" <child>"
+" <object class=\"GtkAction\" id=\"About\">"
+" <property name=\"name\">About</property>"
+" <property name=\"stock_id\">gtk-about</property>"
+" </object>"
+" </child>"
+"</object>"
+"</interface>";
+
+static GtkWidget *about_dialog;
+
+static void
+about_activate (GtkAction *action,
+ gpointer user_data)
+{
+ gtk_dialog_run (GTK_DIALOG (about_dialog));
+ gtk_widget_hide (GTK_WIDGET (about_dialog));
+}
+
+static void
+launch_myself (void)
+{
+ GAppInfo *ai;
+
+ g_type_init ();
+
+ ai = (GAppInfo*)g_desktop_app_info_new_from_filename ("./testapplication.desktop");
+ g_app_info_launch (ai, NULL, NULL, NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkApplication *app;
+ GtkWindow *window;
+ GtkWindow *window2;
+ GtkBuilder *builder;
+ GtkAction *action;
+ GtkActionGroup *actions;
+
+ if (argc > 1 && strcmp (argv[1], "--launch-yourself") == 0)
+ {
+ launch_myself ();
+ exit (0);
+ }
+
+ app = gtk_application_new (&argc, &argv, "org.gtk.TestApp");
+ builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_string (builder, builder_data, -1, NULL))
+ g_error ("failed to parse UI");
+ actions = GTK_ACTION_GROUP (gtk_builder_get_object (builder, "actions"));
+ gtk_application_set_action_group (app, actions);
+
+ action = gtk_action_group_get_action (actions, "About");
+ g_signal_connect (action, "activate", G_CALLBACK (about_activate), app);
+
+ about_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "about_dialog"));
+
+ gtk_builder_connect_signals (builder, app);
+ g_object_unref (builder);
+
+ window = gtk_application_get_window (app);
+ gtk_container_add (GTK_CONTAINER (window), gtk_label_new ("Hello world"));
+ gtk_widget_show_all (GTK_WIDGET (window));
+
+ window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_container_add (GTK_CONTAINER (window2), gtk_label_new ("Hello again"));
+ gtk_widget_show_all (GTK_WIDGET (window2));
+ gtk_application_add_window (app, window2);
+
+ gtk_application_run (app);
+
+ return 0;
+}
diff --git a/tests/testapplication.desktop b/tests/testapplication.desktop
new file mode 100644
index 0000000..430bb37
--- /dev/null
+++ b/tests/testapplication.desktop
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=Application
+Name=testapplication
+Name[de]=Test-Applikation
+Exec=./testapplication
+Icon=accessories-calculator
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]