diff options
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtk.symbols | 9 | ||||
-rw-r--r-- | gtk/gtkapplication.c | 694 | ||||
-rw-r--r-- | gtk/gtkapplication.h | 64 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 94 | ||||
-rw-r--r-- | gtk/gtkwindow.h | 5 | ||||
-rw-r--r-- | gtk/tests/gtk-example-application.c | 100 |
6 files changed, 225 insertions, 741 deletions
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) - * { - * /* if some_condition is TRUE, do not quit */ - * if (some_condition) - * return TRUE; - * - * /* this will cause the application to quit * - * 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; } |