X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgactiongroupexporter.c;h=17a05fa9c8ab5dd408999879645c2045d48e0840;hb=e55a953642a9e402f4363f9fa347b6061dd78990;hp=136928cb7c10bb99baa650c2ca027a168bfb83ff;hpb=7af08e1fc06fbf0180d3e6c3b8314cda5258c0f6;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c index 136928c..17a05fa 100644 --- a/gio/gactiongroupexporter.c +++ b/gio/gactiongroupexporter.c @@ -13,9 +13,7 @@ * 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. + * Public License along with this library; if not, see . * * Authors: Ryan Lortie */ @@ -25,15 +23,16 @@ #include "gactiongroupexporter.h" #include "gdbusmethodinvocation.h" +#include "gremoteactiongroup.h" #include "gdbusintrospection.h" #include "gdbusconnection.h" #include "gactiongroup.h" -#include "gapplication.h" #include "gdbuserror.h" /** * SECTION:gactiongroupexporter * @title: GActionGroup exporter + * @include: gio/gio.h * @short_description: Export GActionGroups on D-Bus * @see_also: #GActionGroup, #GDBusActionGroup * @@ -42,10 +41,10 @@ * detail. * * To access an exported #GActionGroup remotely, use - * g_dbus_action_group_new() to obtain a #GDBusActionGroup. + * g_dbus_action_group_get() to obtain a #GDBusActionGroup. */ -G_GNUC_INTERNAL GVariant * +static GVariant * g_action_group_describe_action (GActionGroup *action_group, const gchar *name) { @@ -79,104 +78,14 @@ g_action_group_describe_action (GActionGroup *action_group, return g_variant_builder_end (&builder); } -/* The org.gtk.Actions interface - * ============================= - * - * This interface describes a group of actions. - * - * Each action: - * - has a unique string name - * - can be activated - * - optionally has a parameter type that must be given to the activation - * - has an enabled state that may be true or false - * - optionally has a state which can change value, but not type - * - * Methods - * ------- - * - * List :: () → (as) - * - * Lists the names of the actions exported at this object path. - * - * Describe :: (s) → (bgav) - * - * Describes a single action, or a given name. - * - * The return value has the following components: - * b: specifies if the action is currently enabled. This is - * a hint that attempting to interact with the action will - * produce no effect. - * g: specifies the optional parameter type. If not "", - * the string specifies the type of argument that must - * be passed to the activation. - * av: specifies the optional state. If not empty, the array - * contains the current value of the state as a variant - * - * DescribeAll :: () → (a{s(bgav)}) - * - * Describes all actions in a single round-trip. - * - * The dictionary maps action name strings to their descriptions - * (in the format discussed above). - * - * Activate :: (sava{sv}) → () - * - * Requests activation of the named action. - * - * The action is named by the first parameter (s). - * - * If the action activation requires a parameter then this parameter - * must be given in the second parameter (av). If there is no parameter - * to be specified, the array must be empty. - * - * The final parameter (a{sv}) is a list of "platform data". - * - * This method is not guaranteed to have any particular effect. The - * implementation may take some action (including changing the state - * of the action, if it is stateful) or it may take none at all. In - * particular, callers should expect their request to be completely - * ignored when the enabled flag is false (but even this is not - * guaranteed). - * - * SetState :: (sva{sv}) → () - * - * Requests the state of an action to be changed to the given value. - * - * The action is named by the first parameter (s). - * - * The requested new state is given in the second parameter (v). - * It must be equal in type to the existing state. - * - * The final parameter (a{sv}) is a list of "platform data". - * - * This method is not guaranteed to have any particular effect. - * The implementation of an action can choose to ignore the requested - * state change, or choose to change its state to something else or - * to trigger other side effects. In particular, callers should expect - * their request to be completely ignored when the enabled flag is - * false (but even this is not guaranteed). - * - * Signals - * ------- - * - * Changed :: (asa{sb}a{sv}a{s(bgav)}) - * - * Signals that some change has occured to the action group. - * - * Four separate types of changes are possible, and the 4 parameters - * of the change signal reflect these possibilities: - * as: a list of removed actions - * a{sb}: a list of actions that had their enabled flag changed - * a{sv}: a list of actions that had their state changed - * a{s(bgav)}: a list of new actions added in the same format as - * the return value of the DescribeAll method - */ - /* Using XML saves us dozens of relocations vs. using the introspection * structure types. We only need to burn cycles and memory if we * actually use the exporter -- not in every single app using GIO. * * It's also a lot easier to read. :) + * + * For documentation of this interface, see + * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI */ const char org_gtk_Actions_xml[] = "" @@ -216,10 +125,10 @@ typedef struct { GActionGroup *action_group; GDBusConnection *connection; + GMainContext *context; gchar *object_path; GHashTable *pending_changes; GSource *pending_source; - gulong signal_ids[4]; } GActionGroupExporter; #define ACTION_ADDED_EVENT (1u<<0) @@ -329,7 +238,8 @@ g_action_group_exporter_set_events (GActionGroupExporter *exporter, source = g_idle_source_new (); exporter->pending_source = source; g_source_set_callback (source, g_action_group_exporter_dispatch_events, exporter, NULL); - g_source_attach (source, NULL); + g_source_set_name (source, "[gio] g_action_group_exporter_dispatch_events"); + g_source_attach (source, exporter->context); g_source_unref (source); } @@ -443,24 +353,6 @@ g_action_group_exporter_action_enabled_changed (GActionGroup *action_group, } static void -g_action_group_exporter_pre_emit (GActionGroupExporter *exporter, - GVariant *platform_data) -{ - if (G_IS_APPLICATION (exporter->action_group)) - G_APPLICATION_GET_CLASS (exporter->action_group) - ->before_emit (G_APPLICATION (exporter->action_group), platform_data); -} - -static void -g_action_group_exporter_post_emit (GActionGroupExporter *exporter, - GVariant *platform_data) -{ - if (G_IS_APPLICATION (exporter->action_group)) - G_APPLICATION_GET_CLASS (exporter->action_group) - ->after_emit (G_APPLICATION (exporter->action_group), platform_data); -} - -static void org_gtk_Actions_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, @@ -488,6 +380,14 @@ org_gtk_Actions_method_call (GDBusConnection *connection, GVariant *desc; g_variant_get (parameters, "(&s)", &name); + + if (!g_action_group_has_action (exporter->action_group, name)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "The named action ('%s') does not exist.", name); + return; + } + desc = g_action_group_describe_action (exporter->action_group, name); result = g_variant_new ("(@(bgav))", desc); } @@ -523,9 +423,11 @@ org_gtk_Actions_method_call (GDBusConnection *connection, g_variant_iter_next (iter, "v", ¶meter); g_variant_iter_free (iter); - g_action_group_exporter_pre_emit (exporter, platform_data); - g_action_group_activate_action (exporter->action_group, name, parameter); - g_action_group_exporter_post_emit (exporter, platform_data); + if (G_IS_REMOTE_ACTION_GROUP (exporter->action_group)) + g_remote_action_group_activate_action_full (G_REMOTE_ACTION_GROUP (exporter->action_group), + name, parameter, platform_data); + else + g_action_group_activate_action (exporter->action_group, name, parameter); if (parameter) g_variant_unref (parameter); @@ -540,9 +442,13 @@ org_gtk_Actions_method_call (GDBusConnection *connection, GVariant *state; g_variant_get (parameters, "(&sv@a{sv})", &name, &state, &platform_data); - g_action_group_exporter_pre_emit (exporter, platform_data); - g_action_group_change_action_state (exporter->action_group, name, state); - g_action_group_exporter_post_emit (exporter, platform_data); + + if (G_IS_REMOTE_ACTION_GROUP (exporter->action_group)) + g_remote_action_group_change_action_state_full (G_REMOTE_ACTION_GROUP (exporter->action_group), + name, state, platform_data); + else + g_action_group_change_action_state (exporter->action_group, name, state); + g_variant_unref (platform_data); g_variant_unref (state); } @@ -557,15 +463,21 @@ static void g_action_group_exporter_free (gpointer user_data) { GActionGroupExporter *exporter = user_data; - gint i; - for (i = 0; i < G_N_ELEMENTS (exporter->signal_ids); i++) - g_signal_handler_disconnect (exporter->action_group, exporter->signal_ids[i]); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_added, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_enabled_changed, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_state_changed, exporter); + g_signal_handlers_disconnect_by_func (exporter->action_group, + g_action_group_exporter_action_removed, exporter); g_hash_table_unref (exporter->pending_changes); if (exporter->pending_source) g_source_destroy (exporter->pending_source); + g_main_context_unref (exporter->context); g_object_unref (exporter->connection); g_object_unref (exporter->action_group); g_free (exporter->object_path); @@ -585,7 +497,7 @@ g_action_group_exporter_free (gpointer user_data) * The implemented D-Bus API should be considered private. It is * subject to change in the future. * - * A given * object path can only have one action group exported on it. + * A given object path can only have one action group exported on it. * If this constraint is violated, the export will fail and 0 will be * returned (with @error set accordingly). * @@ -593,6 +505,15 @@ g_action_group_exporter_free (gpointer user_data) * g_dbus_connection_unexport_action_group() with the return value of * this function. * + * The thread default main context is taken at the time of this call. + * All incoming action activations and state change requests are + * reported from this context. Any changes on the action group that + * cause it to emit signals must also come from this same context. + * Since incoming action activations and state change requests are + * rather likely to cause changes on the action group, this effectively + * limits a given action group to being exported from only one main + * context. + * * Returns: the ID of the export (never zero), or 0 in case of failure * * Since: 2.32 @@ -633,24 +554,21 @@ g_dbus_connection_export_action_group (GDBusConnection *connection, return 0; } + exporter->context = g_main_context_ref_thread_default (); exporter->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); exporter->pending_source = NULL; exporter->action_group = g_object_ref (action_group); exporter->connection = g_object_ref (connection); exporter->object_path = g_strdup (object_path); - exporter->signal_ids[0] = - g_signal_connect (action_group, "action-added", - G_CALLBACK (g_action_group_exporter_action_added), exporter); - exporter->signal_ids[1] = - g_signal_connect (action_group, "action-removed", - G_CALLBACK (g_action_group_exporter_action_removed), exporter); - exporter->signal_ids[2] = - g_signal_connect (action_group, "action-state-changed", - G_CALLBACK (g_action_group_exporter_action_state_changed), exporter); - exporter->signal_ids[3] = - g_signal_connect (action_group, "action-enabled-changed", - G_CALLBACK (g_action_group_exporter_action_enabled_changed), exporter); + g_signal_connect (action_group, "action-added", + G_CALLBACK (g_action_group_exporter_action_added), exporter); + g_signal_connect (action_group, "action-removed", + G_CALLBACK (g_action_group_exporter_action_removed), exporter); + g_signal_connect (action_group, "action-state-changed", + G_CALLBACK (g_action_group_exporter_action_state_changed), exporter); + g_signal_connect (action_group, "action-enabled-changed", + G_CALLBACK (g_action_group_exporter_action_enabled_changed), exporter); return id; }