diff options
author | Matthias Clasen <mclasen@redhat.com> | 2010-06-07 16:44:58 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2010-06-07 16:46:30 -0400 |
commit | 1ae257d00a2921f903048777664f1f171ff24c9b (patch) | |
tree | b564b248f30571f29fa93873b4ba4e8ad8c9f737 /gtk | |
parent | 2c5871479e55a4a5d8e67aef5491c33e14a93f57 (diff) | |
download | gtk+-1ae257d00a2921f903048777664f1f171ff24c9b.tar.gz |
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
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtk.symbols | 11 | ||||
-rw-r--r-- | gtk/gtkapplication.c | 540 | ||||
-rw-r--r-- | gtk/gtkapplication.h | 100 | ||||
-rw-r--r-- | gtk/tests/Makefile.am | 6 | ||||
-rw-r--r-- | gtk/tests/gtk-example-application.c | 60 |
7 files changed, 719 insertions, 1 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index ce1e2af8d8..e10be5f251 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 \ @@ -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 03b815a83b..6439b90e34 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 0000000000..c8dbde904c --- /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 0000000000..6581bcd923 --- /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 cf209a1c06..803314f026 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 0000000000..4248e0ef2b --- /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; +} |