summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2010-08-11 01:23:23 -0400
committerRyan Lortie <desrt@desrt.ca>2010-10-19 01:31:09 +0200
commitab5fb5dee5089d21c0e9d0b059d4d56362dcf327 (patch)
tree7dfb9a01e4779d3e3ac27bf7d828aac960f5a335
parentff142ac2efe0a396fa3a4da0f6be1a68b3eace6b (diff)
downloadgtk+-ab5fb5dee5089d21c0e9d0b059d4d56362dcf327.tar.gz
GtkApplication rewrite
-rw-r--r--gdk/gdk.symbols1
-rw-r--r--gtk/gtk.symbols9
-rw-r--r--gtk/gtkapplication.c694
-rw-r--r--gtk/gtkapplication.h64
-rw-r--r--gtk/gtkwindow.c94
-rw-r--r--gtk/gtkwindow.h5
-rw-r--r--gtk/tests/gtk-example-application.c100
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/testapplication.c108
9 files changed, 227 insertions, 852 deletions
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index e65bcc6263..ea06efb6a4 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -957,6 +957,7 @@ gdk_x11_display_ungrab
gdk_x11_lookup_xdisplay
gdk_x11_display_broadcast_startup_message
gdk_x11_display_get_startup_notification_id
+gdk_x11_display_set_startup_notification_id
gdk_x11_register_standard_event_type
gdk_x11_display_error_trap_push
gdk_x11_display_error_trap_pop
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 92243db540..bada8c25f0 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -252,13 +252,6 @@ gtk_alignment_set_padding
#if IN_FILE(__GTK_APPLICATION_C__)
gtk_application_get_type G_GNUC_CONST
gtk_application_new
-gtk_application_set_action_group
-gtk_application_create_window
-gtk_application_get_window
-gtk_application_get_windows
-gtk_application_add_window
-gtk_application_run
-gtk_application_quit
#endif
#endif
@@ -4400,6 +4393,7 @@ gtk_window_begin_resize_drag
gtk_window_deiconify
gtk_window_fullscreen
gtk_window_get_accept_focus
+gtk_window_get_application
gtk_window_get_decorated
gtk_window_get_deletable
gtk_window_get_default_widget
@@ -4462,6 +4456,7 @@ gtk_window_resize
gtk_window_resize_grip_is_visible
gtk_window_resize_to_geometry
gtk_window_set_accept_focus
+gtk_window_set_application
gtk_window_set_auto_startup_notification
gtk_window_set_decorated
gtk_window_set_deletable
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index a59e236d5d..6e6cd1636c 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -1,11 +1,10 @@
-/* GTK - The GIMP Toolkit
- *
- * Copyright (C) 2010 Red Hat, Inc.
+/*
+ * Copyright © 2010 Codethink Limited
*
* 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.
+ * version 2 of the licence, 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
@@ -17,26 +16,19 @@
* 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/.
+ * Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
#include "gtkapplication.h"
-#include "gtkmain.h"
#include "gtkmarshalers.h"
-#include "gtkintl.h"
-#include "gtkprivate.h"
+#include "gtkwindow.h"
+#include "gtkmain.h"
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
@@ -66,671 +58,99 @@
* </programlisting>
* </example>
*/
-enum
-{
- PROP_0,
-
- PROP_WINDOW
-};
-
-enum
-{
- ACTIVATED,
- QUIT,
- ACTION,
-
- LAST_SIGNAL
-};
-
-static guint gtk_application_signals[LAST_SIGNAL] = { 0 };
-
-struct _GtkApplicationPrivate
-{
- GtkActionGroup *main_actions;
-
- GtkWindow *default_window;
- GSList *windows;
-};
G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
-static void
-process_timestamp_from_platform_data (GVariant *platform_data)
-{
- /* TODO - extract timestamp from here, update GDK time */
-}
-
-static gboolean
-gtk_application_default_quit (GtkApplication *application)
-{
- gtk_main_quit ();
- return TRUE;
-}
-
-static gboolean
-gtk_application_default_quit_with_data (GApplication *application,
- GVariant *platform_data)
-{
- gboolean result;
-
- process_timestamp_from_platform_data (platform_data);
-
- g_signal_emit (application, gtk_application_signals[QUIT], 0, &result);
-
- return result;
-}
-
-static void
-gtk_application_default_run (GApplication *application)
+GtkApplication *
+gtk_application_new (const gchar *application_id,
+ GApplicationFlags flags)
{
- gtk_main ();
-}
+ g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
-static void
-gtk_application_default_prepare_activation (GApplication *application,
- GVariant *arguments,
- GVariant *platform_data)
-{
- GVariantIter iter;
- const gchar *key;
- GVariant *value;
+ g_type_init ();
- g_variant_iter_init (&iter, platform_data);
- while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
- {
- if (strcmp (key, "startup-notification-id") == 0 &&
- g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
- gdk_notify_startup_complete_with_id (g_variant_get_string (value, NULL));
- g_variant_unref (value);
- }
-
- g_signal_emit (G_OBJECT (application), gtk_application_signals[ACTIVATED], 0, arguments);
-}
-
-static void
-gtk_application_default_activated (GtkApplication *application,
- GVariant *arguments)
-{
- GtkApplicationPrivate *priv = application->priv;
-
- /* TODO: should we raise the last focused window instead ? */
- if (priv->default_window != NULL)
- gtk_window_present (priv->default_window);
+ return g_object_new (GTK_TYPE_APPLICATION,
+ "application-id", application_id,
+ "flags", flags,
+ NULL);
}
static void
-gtk_application_default_action (GtkApplication *application,
- const gchar *action_name)
-{
- GtkApplicationPrivate *priv = application->priv;
- GtkAction *action;
-
- if (!priv->main_actions)
- return;
-
- action = gtk_action_group_get_action (priv->main_actions, action_name);
- if (action)
- gtk_action_activate (action);
-}
-
-static GtkWindow *
-gtk_application_default_create_window (GtkApplication *application)
+gtk_application_startup (GApplication *application)
{
- return GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
+ gtk_init (0, 0);
}
static void
-gtk_application_default_action_with_data (GApplication *application,
- const gchar *action_name,
- GVariant *platform_data)
+gtk_application_quit_mainloop (GApplication *application)
{
- process_timestamp_from_platform_data (platform_data);
-
- g_signal_emit (application, gtk_application_signals[ACTION], g_quark_from_string (action_name));
-}
-
-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:
- * @appid: System-dependent application identifier
- * @argc: (allow-none) (inout): System argument count
- * @argv: (allow-none) (inout): System argument vector
- *
- * 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 (const gchar *appid,
- gint *argc,
- gchar ***argv)
-{
- GtkApplication *app;
- gint argc_for_app;
- const gchar **argv_for_app;
- GVariant *argv_variant;
- GError *error = NULL;
-
- gtk_init (argc, argv);
-
- if (argc)
- argc_for_app = *argc;
- else
- argc_for_app = 0;
-
- if (argv)
- argv_for_app = (const gchar **) *argv;
- else
- argv_for_app = NULL;
-
- argv_variant = g_variant_new_bytestring_array (argv_for_app, argc_for_app);
-
- app = g_initable_new (GTK_TYPE_APPLICATION,
- NULL,
- &error,
- "application-id", appid,
- "argv", argv_variant,
- NULL);
- if (app == NULL)
- {
- g_error ("%s", error->message);
- g_clear_error (&error);
- return NULL;
- }
-
- return app;
+ gtk_main_quit ();
}
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 (GTK_IS_ACTION_GROUP (group));
- 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 all the windows managed by #GtkApplication are closed, the
- * #GtkApplication will call gtk_application_quit(), and quit
- * the application.
- *
- * If your application uses only a single toplevel window, you can
- * use gtk_application_get_window(). If you are using a sub-class
- * of #GtkApplication you should call gtk_application_create_window()
- * to let the #GtkApplication instance create a #GtkWindow and add
- * it to the list of toplevels of the application. You should call
- * this function only to add #GtkWindow<!-- -->s that you created
- * directly using gtk_window_new().
- *
- * Since: 3.0
- */
-void
-gtk_application_add_window (GtkApplication *app,
- GtkWindow *window)
-{
- GtkApplicationPrivate *priv;
-
- g_return_if_fail (GTK_IS_APPLICATION (app));
- g_return_if_fail (GTK_IS_WINDOW (window));
-
- priv = app->priv;
-
- if (g_slist_find (priv->windows, window) != NULL)
- return;
-
- priv->windows = g_slist_prepend (priv->windows, window);
-
- if (priv->default_window == NULL)
- priv->default_window = 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_create_window() or
- * gtk_application_add_window() instead.
- *
- * Returns: (transfer none): The default #GtkWindow for this application
- *
- * Since: 3.0
- */
-GtkWindow *
-gtk_application_get_window (GtkApplication *app)
-{
- GtkApplicationPrivate *priv;
-
- g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
-
- priv = app->priv;
-
- if (priv->default_window != NULL)
- return priv->default_window;
-
- return gtk_application_create_window (app);
-}
-
-/**
- * gtk_application_get_windows:
- * @app: a #GtkApplication
- *
- * Retrieves the list of windows previously registered with
- * gtk_application_create_window() or gtk_application_add_window().
- *
- * Return value: (element-type GtkWindow) (transfer none): A pointer
- * to the list of #GtkWindow<!-- -->s registered by this application,
- * or %NULL. The returned #GSList is owned by the #GtkApplication
- * and it should not be modified or freed directly.
- *
- * Since: 3.0
- */
-G_CONST_RETURN GSList *
-gtk_application_get_windows (GtkApplication *app)
-{
- g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
-
- return app->priv->windows;
-}
-
-/**
- * gtk_application_create_window:
- * @app: a #GtkApplication
- *
- * Creates a new #GtkWindow for the application.
- *
- * This function calls the #GtkApplication::create_window() virtual function,
- * which can be overridden by sub-classes, for instance to use #GtkBuilder to
- * create the user interface. After creating a new #GtkWindow instance, it will
- * be added to the list of toplevels associated to the application.
- *
- * Return value: (transfer none): the newly created application #GtkWindow
- *
- * Since: 3.0
- */
-GtkWindow *
-gtk_application_create_window (GtkApplication *app)
-{
- GtkWindow *window;
-
- g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
-
- window = GTK_APPLICATION_GET_CLASS (app)->create_window (app);
- gtk_application_add_window (app, window);
-
- return 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)
+gtk_application_run_mainloop (GApplication *application)
{
- g_application_run (G_APPLICATION (app));
-}
-
-/**
- * gtk_application_quit:
- * @app: a #GtkApplication
- *
- * Request the application exit. This function invokes
- * g_application_quit_with_data(), which normally will
- * in turn cause @app to emit #GtkApplication::quit.
- *
- * To control an application's quit behavior (for example, to ask for
- * files to be saved), connect to the #GtkApplication::quit signal
- * handler.
- *
- * Since: 3.0
- */
-void
-gtk_application_quit (GtkApplication *app)
-{
- GVariantBuilder builder;
- GVariant *platform_data;
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}",
- "timestamp",
- g_variant_new ("u", gtk_get_current_event_time ()));
- platform_data = g_variant_builder_end (&builder);
-
- g_application_quit_with_data (G_APPLICATION (app), platform_data);
-
- g_variant_unref (platform_data);
+ gtk_main ();
}
static void
-gtk_application_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+gtk_application_add_platform_data (GApplication *application,
+ GVariantBuilder *builder)
{
- GtkApplication *app = GTK_APPLICATION (object);
+ const gchar *startup_id;
- 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);
- }
+ startup_id = getenv ("DESKTOP_STARTUP_ID");
+
+ if (startup_id && g_utf8_validate (startup_id, -1, NULL))
+ g_variant_builder_add (builder, "{sv}", "desktop-startup-id",
+ g_variant_new_string (startup_id));
}
static void
-gtk_application_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_application_before_emit (GApplication *application,
+ GVariant *platform_data)
{
- GtkApplication *app = GTK_APPLICATION (object);
-
- g_assert (app != NULL);
+ GVariantIter iter;
+ const gchar *key;
+ GVariant *value;
- switch (prop_id)
+ g_variant_iter_init (&iter, platform_data);
+ while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
{
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ if (strcmp (key, "desktop-startup-id") == 0)
+ {
+ GdkDisplay *display;
+ const gchar *id;
+
+ display = gdk_display_get_default ();
+ id = g_variant_get_string (value, NULL);
+ gdk_x11_display_set_startup_notification_id (display, id);
+ }
}
}
static void
-setup_default_window_decorations (void)
+gtk_application_after_emit (GApplication *application,
+ GVariant *platform_data)
{
- 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);
-
- 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);
+ gdk_notify_startup_complete ();
}
static void
gtk_application_init (GtkApplication *application)
{
- application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application, GTK_TYPE_APPLICATION, GtkApplicationPrivate);
-
- g_object_set (application, "platform-data", gtk_application_format_activation_data (), NULL);
-
- 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)
+gtk_application_class_init (GtkApplicationClass *class)
{
- 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_with_data = gtk_application_default_quit_with_data;
- application_class->action_with_data = gtk_application_default_action_with_data;
- application_class->prepare_activation = gtk_application_default_prepare_activation;
-
- klass->quit = gtk_application_default_quit;
- klass->action = gtk_application_default_action;
- klass->create_window = gtk_application_default_create_window;
-
- 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.
- *
- * Since: 3.0
- */
- 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__VARIANT,
- G_TYPE_NONE, 1,
- G_TYPE_VARIANT);
+ GApplicationClass *application_class = G_APPLICATION_CLASS (class);
- /**
- * GtkApplication::quit:
- * @application: the object on which the signal is emitted
- *
- * This signal is emitted when a quit is initiated. See also
- * the #GApplication::quit-with-data signal which may in
- * turn trigger this signal.
- *
- * The default handler for this signal exits the mainloop of the
- * application. It is possible to override the default handler
- * by simply returning %TRUE from a callback, e.g.:
- *
- * |[
- * static gboolean
- * my_application_quit (GtkApplication *application)
- * {
- * /&ast; if some_condition is TRUE, do not quit &ast;/
- * if (some_condition)
- * return TRUE;
- *
- * /&ast; this will cause the application to quit &ast;
- * return FALSE;
- * }
- *
- * g_signal_connect (application, "quit",
- * G_CALLBACK (my_application_quit),
- * NULL);
- * ]|
- *
- * Returns: %TRUE if the signal has been handled, %FALSE to continue
- * signal emission
- *
- * Since: 3.0
- */
- gtk_application_signals[QUIT] =
- g_signal_new (g_intern_static_string ("quit"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkApplicationClass, quit),
- g_signal_accumulator_true_handled, NULL,
- _gtk_marshal_BOOLEAN__VOID,
- G_TYPE_BOOLEAN, 0);
+ application_class->add_platform_data = gtk_application_add_platform_data;
+ application_class->before_emit = gtk_application_before_emit;
+ application_class->after_emit = gtk_application_after_emit;
+ application_class->startup = gtk_application_startup;
- /**
- * GtkApplication::action:
- * @application: the object on which the signal is emitted
- * @name: The name of the activated action
- *
- * This signal is emitted when an action is activated. The action name
- * is passed as the first argument, but also as signal detail, so it
- * is possible to connect to this signal for individual actions.
- *
- * See also the #GApplication::action-with-data signal which may in
- * turn trigger this signal.
- *
- * The signal is never emitted for disabled actions.
- *
- * Since: 3.0
- */
- gtk_application_signals[ACTION] =
- g_signal_new (g_intern_static_string ("action"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED,
- G_STRUCT_OFFSET (GtkApplicationClass, action),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- g_type_class_add_private (gobject_class, sizeof (GtkApplicationPrivate));
+ application_class->quit_mainloop = gtk_application_quit_mainloop;
+ application_class->run_mainloop = gtk_application_run_mainloop;
}
diff --git a/gtk/gtkapplication.h b/gtk/gtkapplication.h
index a6b2e8bfc6..a4ff6c5d0a 100644
--- a/gtk/gtkapplication.h
+++ b/gtk/gtkapplication.h
@@ -1,15 +1,14 @@
-/* GTK - The GIMP Toolkit
- *
- * Copyright (C) 2010 Red Hat, Inc.
+/*
+ * Copyright © 2010 Codethink Limited
*
* 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.
+ * version 2 of the licence, 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
+ * 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
@@ -17,14 +16,7 @@
* 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/.
+ * Author: Ryan Lortie <desrt@desrt.ca>
*/
#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
@@ -34,10 +26,9 @@
#ifndef __GTK_APPLICATION_H__
#define __GTK_APPLICATION_H__
-#include <gio/gio.h>
-#include <gtk/gtkaction.h>
#include <gtk/gtkactiongroup.h>
-#include <gtk/gtkwindow.h>
+#include <gtk/gtkwidget.h>
+#include <gio/gio.h>
G_BEGIN_DECLS
@@ -57,7 +48,6 @@ struct _GtkApplication
GApplication parent;
/*< private >*/
-
GtkApplicationPrivate *priv;
};
@@ -66,40 +56,16 @@ struct _GtkApplicationClass
GApplicationClass parent_class;
/*< vfuncs >*/
- GtkWindow *(* create_window) (GtkApplication *app);
- void (* activated) (GtkApplication *app,
- GVariant *args);
- void (* action) (GtkApplication *app,
- const gchar *action_name);
- gboolean (* quit) (GtkApplication *app);
-
-
- /* 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);
+ GtkWindow *(* create_window) (GtkApplication *application);
+
+ /*< private >*/
+ gpointer padding[12];
};
-GType gtk_application_get_type (void) G_GNUC_CONST;
-GtkApplication* gtk_application_new (const gchar *appid,
- gint *argc,
- gchar ***argv);
-void gtk_application_set_action_group (GtkApplication *app,
- GtkActionGroup *group);
-GtkWindow * gtk_application_create_window (GtkApplication *app);
-GtkWindow * gtk_application_get_window (GtkApplication *app);
-G_CONST_RETURN GSList * gtk_application_get_windows (GtkApplication *app);
-void gtk_application_add_window (GtkApplication *app,
- GtkWindow *window);
-void gtk_application_run (GtkApplication *app);
-void gtk_application_quit (GtkApplication *app);
+GType gtk_application_get_type (void) G_GNUC_CONST;
+
+GtkApplication* gtk_application_new (const gchar *application_id,
+ GApplicationFlags flags);
G_END_DECLS
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index f56b3ccbd0..6b8f66719b 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -113,6 +113,8 @@ struct _GtkWindowPrivate
GdkWindow *frame;
GdkWindowTypeHint gdk_type_hint;
+ GtkApplication *application;
+
gdouble opacity;
GdkWindow *grip_window;
@@ -223,7 +225,7 @@ enum {
PROP_OPACITY,
PROP_HAS_RESIZE_GRIP,
PROP_RESIZE_GRIP_VISIBLE,
-
+ PROP_APPLICATION,
/* Readonly properties */
PROP_IS_ACTIVE,
PROP_HAS_TOPLEVEL_FOCUS,
@@ -937,7 +939,6 @@ gtk_window_class_init (GtkWindowClass *klass)
1.0,
GTK_PARAM_READWRITE));
-
/* Style properties.
*/
gtk_widget_class_install_style_property (widget_class,
@@ -955,6 +956,24 @@ gtk_window_class_init (GtkWindowClass *klass)
/* Signals
*/
+ /**
+ * GtkWindow:application:
+ *
+ * The #GtkApplication associated with the window.
+ *
+ * The application will be kept alive for at least as long as the
+ * window is open.
+ *
+ * Since: 3.0
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_APPLICATION,
+ g_param_spec_object ("application",
+ P_("GtkApplication"),
+ P_("The GtkApplication for the window"),
+ GTK_TYPE_APPLICATION,
+ GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
window_signals[SET_FOCUS] =
g_signal_new (I_("set-focus"),
G_TYPE_FROM_CLASS (gobject_class),
@@ -1219,6 +1238,9 @@ gtk_window_set_property (GObject *object,
case PROP_HAS_RESIZE_GRIP:
gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
break;
+ case PROP_APPLICATION:
+ gtk_window_set_application (window, g_value_get_object (value));
+ break;
case PROP_MNEMONICS_VISIBLE:
gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
break;
@@ -1334,6 +1356,9 @@ gtk_window_get_property (GObject *object,
case PROP_RESIZE_GRIP_VISIBLE:
g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
break;
+ case PROP_APPLICATION:
+ g_value_set_object (value, gtk_window_get_application (window));
+ break;
case PROP_MNEMONICS_VISIBLE:
g_value_set_boolean (value, priv->mnemonics_visible);
break;
@@ -2599,6 +2624,70 @@ gtk_window_get_opacity (GtkWindow *window)
}
/**
+ * gtk_window_get_application:
+ * @window: a #GtkWindow
+ *
+ * Gets the #GtkApplication associated with the window (if any).
+ *
+ * Return value: a #GtkApplication, or %NULL
+ *
+ * Since: 3.0
+ **/
+GtkApplication *
+gtk_window_get_application (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ return window->priv->application;
+}
+
+static void
+gtk_window_release_application (GtkWindow *window)
+{
+ if (window->priv->application)
+ {
+ g_application_release (G_APPLICATION (window->priv->application));
+ g_object_unref (window->priv->application);
+
+ window->priv->application = NULL;
+ }
+}
+
+/**
+ * gtk_window_set_application:
+ * @window: a #GtkWindow
+ * @application: a #GtkApplication, or %NULL
+ *
+ * Sets or unsets the #GtkApplication associated with the window.
+ *
+ * The application will be kept alive for at least as long as the window
+ * is open.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_window_set_application (GtkWindow *window,
+ GtkApplication *application)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->priv->application != application)
+ {
+ gtk_window_release_application (window);
+
+ window->priv->application = application;
+
+ if (window->priv->application != NULL)
+ {
+ g_application_hold (G_APPLICATION (window->priv->application));
+ g_object_ref (window->priv->application);
+ }
+
+ g_object_notify (G_OBJECT (window), "application");
+ }
+}
+
+/**
* gtk_window_set_type_hint:
* @window: a #GtkWindow
* @hint: the window type
@@ -4488,6 +4577,7 @@ gtk_window_finalize (GObject *object)
g_free (priv->wmclass_name);
g_free (priv->wmclass_class);
g_free (priv->wm_role);
+ gtk_window_release_application (window);
mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
if (mnemonic_hash)
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 96008b8e1f..29e729e90f 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -32,6 +32,7 @@
#define __GTK_WINDOW_H__
+#include <gtk/gtkapplication.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkbin.h>
@@ -345,6 +346,10 @@ GList * gtk_window_group_list_windows (GtkWindowGroup *window_grou
GtkWidget * gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
GdkDevice *device);
+GtkApplication *gtk_window_get_application (GtkWindow *window);
+void gtk_window_set_application (GtkWindow *window,
+ GtkApplication *application);
+
/* Window grips
*/
diff --git a/gtk/tests/gtk-example-application.c b/gtk/tests/gtk-example-application.c
index 2bd5f78d06..8e02804106 100644
--- a/gtk/tests/gtk-example-application.c
+++ b/gtk/tests/gtk-example-application.c
@@ -1,60 +1,68 @@
#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
+new_window (GtkApplication *app,
+ GFile *file)
+{
+ GtkWidget *window, *scrolled, *view;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_application (GTK_WINDOW (window), app);
+ gtk_window_set_title (GTK_WINDOW (window), "Bloatpad");
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ view = gtk_text_view_new ();
+ gtk_container_add (GTK_CONTAINER (scrolled), view);
+ gtk_container_add (GTK_CONTAINER (window), scrolled);
+
+ if (file != NULL)
+ {
+ gchar *contents;
+ gsize length;
+
+ if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
+ {
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ gtk_text_buffer_set_text (buffer, contents, length);
+ g_free (contents);
+ }
+ }
+
+ gtk_widget_show_all (GTK_WIDGET (window));
+}
+
+static void
+activate (GtkApplication *application)
+{
+ new_window (application, NULL);
+}
static void
-about_activate (GtkAction *action,
- gpointer user_data)
+open (GtkApplication *application,
+ GFile **files,
+ gint n_files,
+ const gchar *hint,
+ gpointer user_data)
{
- gtk_dialog_run (GTK_DIALOG (about_dialog));
- gtk_widget_hide (GTK_WIDGET (about_dialog));
+ gint i;
+
+ for (i = 0; i < n_files; i++)
+ new_window (application, files[i]);
}
int
main (int argc, char **argv)
{
GtkApplication *app;
- GtkWindow *window;
- GtkBuilder *builder;
- GtkAction *action;
- GtkActionGroup *actions;
-
- app = gtk_application_new ("org.gtk.Example", &argc, &argv);
- 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));
+ int status;
- gtk_application_run (app);
+ app = gtk_application_new ("org.gtk.Test.bloatpad",
+ G_APPLICATION_HANDLES_OPEN);
+ g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+ g_signal_connect (app, "open", G_CALLBACK (open), NULL);
+ status = g_application_run (G_APPLICATION (app), argc, argv);
+ g_object_unref (app);
- return 0;
+ return status;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 175b7cf83a..455bf4bf54 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -95,7 +95,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testvolumebutton
if USE_X11
-noinst_PROGRAMS += testapplication testerrors
+noinst_PROGRAMS += testerrors
endif
if HAVE_CXX
@@ -118,7 +118,6 @@ testheightforwidth_DEPENDENCIES = $(TEST_DEPS)
testicontheme_DEPENDENCIES = $(TEST_DEPS)
testiconview_DEPENDENCIES = $(TEST_DEPS)
testaccel_DEPENDENCIES = $(TEST_DEPS)
-testapplication_DEPENDENCIES = $(TEST_DEPS)
testadjustsize_DEPENDENCIES = $(TEST_DEPS)
testassistant_DEPENDENCIES = $(TEST_DEPS)
testbbox_DEPENDENCIES = $(TEST_DEPS)
@@ -185,7 +184,6 @@ simple_LDADD = $(LDADDS)
print_editor_LDADD = $(LDADDS)
testaccel_LDADD = $(LDADDS)
testadjustsize_LDADD = $(LDADDS)
-testapplication_LDADD = $(LDADDS)
testassistant_LDADD = $(LDADDS)
testbbox_LDADD = $(LDADDS)
testbuttons_LDADD = $(LDADDS)
diff --git a/tests/testapplication.c b/tests/testapplication.c
deleted file mode 100644
index 992301dc63..0000000000
--- a/tests/testapplication.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* 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 <stdlib.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;
- GtkWidget *window2;
- GtkBuilder *builder;
- GtkAction *action;
- GtkActionGroup *actions;
-
- if (argc > 1 && g_strcmp0 (argv[1], "--launch-yourself") == 0)
- {
- launch_myself ();
- exit (0);
- }
-
- app = gtk_application_new ("org.gtk.TestApp", &argc, &argv);
- 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 (window2);
- gtk_application_add_window (app, GTK_WINDOW (window2));
-
- gtk_application_run (app);
-
- return 0;
-}