Compare commits

...

1 Commits

Author SHA1 Message Date
Ryan Lortie
5ae008606d GtkApplication rewrite 2010-08-11 01:23:23 -04:00
4 changed files with 275 additions and 613 deletions

View File

@@ -33,10 +33,8 @@
#include <unistd.h>
#include "gtkapplication.h"
#include "gtkwindow.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
@@ -66,668 +64,250 @@
* </programlisting>
* </example>
*/
enum
{
PROP_0,
PROP_WINDOW
};
enum
{
ACTIVATED,
QUIT,
ACTION,
LAST_SIGNAL
PROP_NONE,
PROP_ACTION_GROUP,
PROP_DEFAULT_WINDOW
};
static guint gtk_application_signals[LAST_SIGNAL] = { 0 };
struct _GtkApplicationPrivate
{
GtkActionGroup *main_actions;
GtkActionGroup *action_group;
GtkWindow *default_window;
GSList *windows;
};
G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
static void
process_timestamp_from_platform_data (GVariant *platform_data)
gtk_application_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
/* TODO - extract timestamp from here, update GDK time */
}
GtkApplication *application = GTK_APPLICATION (object);
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)
{
gtk_main ();
}
static void
gtk_application_default_prepare_activation (GApplication *application,
GVariant *arguments,
GVariant *platform_data)
{
GVariantIter iter;
const gchar *key;
GVariant *value;
g_variant_iter_init (&iter, platform_data);
while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
switch (prop_id)
{
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);
case PROP_ACTION_GROUP:
gtk_application_set_action_group (application,
g_value_get_object (value));
break;
case PROP_DEFAULT_WINDOW:
gtk_application_set_default_window (application,
g_value_get_object (value));
break;
default:
g_assert_not_reached ();
}
g_signal_emit (G_OBJECT (application), gtk_application_signals[ACTIVATED], 0, arguments);
}
static void
gtk_application_default_activated (GtkApplication *application,
GVariant *arguments)
gtk_application_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GtkApplicationPrivate *priv = application->priv;
GtkApplication *application = GTK_APPLICATION (object);
/* TODO: should we raise the last focused window instead ? */
if (priv->default_window != NULL)
gtk_window_present (priv->default_window);
}
switch (prop_id)
{
case PROP_ACTION_GROUP:
g_value_set_object (value,
gtk_application_get_action_group (application));
break;
static void
gtk_application_default_action (GtkApplication *application,
const gchar *action_name)
{
GtkApplicationPrivate *priv = application->priv;
GtkAction *action;
case PROP_DEFAULT_WINDOW:
g_value_set_object (value,
gtk_application_get_default_window (application));
break;
action = gtk_action_group_get_action (priv->main_actions, action_name);
if (action)
gtk_action_activate (action);
default:
g_assert_not_reached ();
}
}
static GtkWindow *
gtk_application_default_create_window (GtkApplication *application)
gtk_application_real_create_window (GtkApplication *application)
{
return GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
}
static void
gtk_application_default_action_with_data (GApplication *application,
const gchar *action_name,
GVariant *platform_data)
gtk_application_activate (GApplication *gapplication)
{
process_timestamp_from_platform_data (platform_data);
GtkApplication *application = GTK_APPLICATION (gapplication);
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)
if (application->priv->default_window == NULL)
{
g_error ("%s", error->message);
g_clear_error (&error);
return NULL;
GtkWindow *window;
window = GTK_APPLICATION_GET_CLASS (application)
->create_window (application);
if (window != NULL)
gtk_application_set_default_window (application, window);
}
return app;
if (application->priv->default_window != NULL)
gtk_window_present (application->priv->default_window);
}
static void
on_action_sensitive (GtkAction *action,
GParamSpec *pspec,
GtkApplication *app)
gtk_application_action (GApplication *gapplication,
const gchar *action_name,
GVariant *parameters)
{
g_application_set_action_enabled (G_APPLICATION (app),
gtk_action_get_name (action),
gtk_action_get_sensitive (action));
}
GtkApplication *application = GTK_APPLICATION (gapplication);
/**
* 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)
if (parameters == NULL && application->priv->action_group != NULL)
{
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);
GtkAction *action;
action = gtk_action_group_get_action (application->priv->action_group,
action_name);
if (action != NULL)
{
gtk_action_activate (action);
return;
}
}
g_list_free (actions);
}
static gboolean
gtk_application_on_window_destroy (GtkWidget *window,
gpointer user_data)
GtkApplication *
gtk_application_new (const gchar *application_id,
GApplicationFlags flags,
GtkActionGroup *action_group)
{
GtkApplication *app = GTK_APPLICATION (user_data);
g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
app->priv->windows = g_slist_remove (app->priv->windows, window);
gtk_init (NULL, NULL);
if (app->priv->windows == NULL)
gtk_application_quit (app);
return FALSE;
return g_object_new (GTK_TYPE_APPLICATION,
"application-id", application_id,
"flags", flags,
"action-group", action_group,
NULL);
}
static gchar *default_title;
GtkActionGroup *
gtk_application_get_action_group (GtkApplication *application)
{
g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
return application->priv->action_group;
}
/**
* 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)
gtk_application_set_action_group (GtkApplication *application,
GtkActionGroup *action_group)
{
GtkApplicationPrivate *priv;
g_return_if_fail (GTK_IS_APPLICATION (application));
g_return_if_fail (action_group == NULL || GTK_IS_ACTION_GROUP (action_group));
g_return_if_fail (GTK_IS_APPLICATION (app));
g_return_if_fail (GTK_IS_WINDOW (window));
if (application->priv->action_group != action_group)
{
if (application->priv->action_group)
g_object_unref (application->priv->action_group);
priv = app->priv;
application->priv->action_group = action_group;
if (g_slist_find (priv->windows, window) != NULL)
return;
if (application->priv->action_group)
g_object_ref (application->priv->action_group);
priv->windows = g_slist_prepend (priv->windows, window);
/* XXX synch the list... */
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);
g_object_notify (G_OBJECT (application), "action-group");
}
}
/**
* 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)
gtk_application_get_default_window (GtkApplication *application)
{
GtkApplicationPrivate *priv;
g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
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);
return application->priv->default_window;
}
/**
* 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_set_default_window (GtkApplication *application,
GtkWindow *window)
{
g_application_run (G_APPLICATION (app));
}
g_return_if_fail (GTK_IS_APPLICATION (application));
g_return_if_fail (window == NULL || GTK_IS_WINDOW (window));
/**
* 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);
}
static void
gtk_application_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkApplication *app = GTK_APPLICATION (object);
switch (prop_id)
if (application->priv->default_window != window)
{
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);
if (window)
gtk_window_set_application (window, application);
application->priv->default_window = window;
g_object_notify (G_OBJECT (application), "default-window");
}
}
static void
gtk_application_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
gtk_application_quit_mainloop (GApplication *application)
{
GtkApplication *app = GTK_APPLICATION (object);
g_assert (app != NULL);
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
gtk_main_quit ();
}
static void
setup_default_window_decorations (void)
gtk_application_run_mainloop (GApplication *application)
{
const gchar *pid;
const gchar *filename;
GKeyFile *keyfile;
gchar *title;
gchar *icon_name;
gtk_main ();
}
pid = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID");
filename = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE");
static void
gtk_application_finalize (GObject *object)
{
GtkApplication *application = GTK_APPLICATION (object);
keyfile = g_key_file_new ();
if (application->priv->action_group)
g_object_unref (application->priv->action_group);
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);
G_OBJECT_CLASS (gtk_application_parent_class)
->finalize (object);
}
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;
application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application,
GTK_TYPE_APPLICATION,
GtkApplicationPrivate);
}
static void
gtk_application_class_init (GtkApplicationClass *klass)
gtk_application_class_init (GtkApplicationClass *class)
{
GObjectClass *gobject_class;
GApplicationClass *application_class;
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
gobject_class = G_OBJECT_CLASS (klass);
application_class = G_APPLICATION_CLASS (klass);
object_class->set_property = gtk_application_set_property;
object_class->get_property = gtk_application_get_property;
gobject_class->constructor = gtk_application_constructor;
gobject_class->get_property = gtk_application_get_property;
gobject_class->set_property = gtk_application_set_property;
class->create_window = gtk_application_real_create_window;
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;
application_class->quit_mainloop = gtk_application_quit_mainloop;
application_class->run_mainloop = gtk_application_run_mainloop;
application_class->activate = gtk_application_activate;
application_class->action = gtk_application_action;
klass->quit = gtk_application_default_quit;
klass->action = gtk_application_default_action;
klass->create_window = gtk_application_default_create_window;
object_class->finalize = gtk_application_finalize;
klass->activated = gtk_application_default_activated;
g_object_class_install_property (object_class, PROP_ACTION_GROUP,
g_param_spec_object ("action-group", "action group",
"the GtkActionGroup for the application",
GTK_TYPE_ACTION_GROUP, G_PARAM_READWRITE |
G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
/**
* 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);
g_object_class_install_property (object_class, PROP_DEFAULT_WINDOW,
g_param_spec_object ("default-window", "default window",
"the default window for the application",
GTK_TYPE_WINDOW,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* 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);
/**
* 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));
g_type_class_add_private (object_class, sizeof (GtkApplicationPrivate));
}

View File

@@ -1,5 +1,5 @@
/* GTK - The GIMP Toolkit
*
/*
* Copyright © 2010 Codethink Limited
* Copyright (C) 2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -17,14 +17,8 @@
* 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>
* Colin Walters <walters@verbum.org>
*/
#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
@@ -34,10 +28,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 +50,6 @@ struct _GtkApplication
GApplication parent;
/*< private >*/
GtkApplicationPrivate *priv;
};
@@ -67,39 +59,24 @@ struct _GtkApplicationClass
/*< vfuncs >*/
GtkWindow *(* create_window) (GtkApplication *application);
void (* activated) (GtkApplication *application,
GVariant *args);
void (* action) (GtkApplication *application,
const gchar *action_name);
gboolean (* quit) (GtkApplication *application);
/* 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);
/*< 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 *appid,
GApplicationFlags flags,
GtkActionGroup *action_group);
GtkActionGroup * gtk_application_get_action_group (GtkApplication *application);
void gtk_application_set_action_group (GtkApplication *application,
GtkActionGroup *action_group);
GtkWindow * gtk_application_get_default_window (GtkApplication *application);
void gtk_application_set_default_window (GtkApplication *application,
GtkWindow *window);
G_END_DECLS

View File

@@ -124,6 +124,7 @@ enum {
PROP_GRAVITY,
PROP_TRANSIENT_FOR,
PROP_OPACITY,
PROP_APPLICATION,
/* Readonly properties */
PROP_IS_ACTIVE,
@@ -223,6 +224,7 @@ struct _GtkWindowPrivate
guint mnemonics_visible_set : 1;
GdkWindowTypeHint type_hint;
GtkApplication *application;
gdouble opacity;
@@ -826,6 +828,24 @@ gtk_window_class_init (GtkWindowClass *klass)
1.0,
GTK_PARAM_READWRITE));
/**
* 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),
@@ -1091,6 +1111,9 @@ gtk_window_set_property (GObject *object,
case PROP_OPACITY:
gtk_window_set_opacity (window, g_value_get_double (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;
@@ -1203,6 +1226,9 @@ gtk_window_get_property (GObject *object,
case PROP_OPACITY:
g_value_set_double (value, gtk_window_get_opacity (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;
@@ -2411,6 +2437,78 @@ gtk_window_get_opacity (GtkWindow *window)
return priv->opacity;
}
/**
* 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 GTK_WINDOW_GET_PRIVATE (window)->application;
}
static void
gtk_window_release_application (GtkWindow *window,
GtkWindowPrivate *priv)
{
if (priv->application)
{
if (gtk_application_get_default_window (priv->application) == window)
gtk_application_set_default_window (priv->application, NULL);
g_application_release (G_APPLICATION (priv->application));
g_object_unref (priv->application);
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)
{
GtkWindowPrivate *priv;
g_return_if_fail (GTK_IS_WINDOW (window));
priv = GTK_WINDOW_GET_PRIVATE (window);
if (priv->application != application)
{
gtk_window_release_application (window, priv);
priv->application = application;
if (priv->application != NULL)
{
g_application_hold (G_APPLICATION (priv->application));
g_object_ref (priv->application);
}
g_object_notify (G_OBJECT (window), "application");
}
}
/**
* gtk_window_set_type_hint:
* @window: a #GtkWindow
@@ -4422,6 +4520,8 @@ gtk_window_finalize (GObject *object)
GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
GtkMnemonicHash *mnemonic_hash;
gtk_window_release_application (window, priv);
g_free (window->title);
g_free (window->wmclass_name);
g_free (window->wmclass_class);

View File

@@ -32,6 +32,7 @@
#define __GTK_WINDOW_H__
#include <gtk/gtkapplication.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkbin.h>
@@ -399,6 +400,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);
/* --- internal functions --- */
void _gtk_window_internal_set_focus (GtkWindow *window,