Commit d168066d authored by Nick Schermer's avatar Nick Schermer

Support remote event replies from the wrapper.

Because of the dbus signal we cannot return the reply
of the remote event, so add a method and handle ids to
reply to the panel.
When an implementation of the panel plugin provider returns
a handle, the dbus service waits for the reply before it
continues.
parent 8a1c6516
......@@ -27,34 +27,33 @@
#define PANEL_DBUS_WRAPPER_INTERFACE PANEL_DBUS_INTERFACE ".Wrapper"
/* internal signals send over dbus */
#define SIGNAL_PREFIX '_'
#define SIGNAL_PREFIX_S "_"
#define SIGNAL_SET_SIZE SIGNAL_PREFIX_S "a"
#define SIGNAL_SET_ORIENTATION SIGNAL_PREFIX_S "b"
#define SIGNAL_SET_SCREEN_POSITION SIGNAL_PREFIX_S "c"
#define SIGNAL_SET_LOCKED SIGNAL_PREFIX_S "d"
#define SIGNAL_SAVE SIGNAL_PREFIX_S "e"
#define SIGNAL_SHOW_CONFIGURE SIGNAL_PREFIX_S "f"
#define SIGNAL_SHOW_ABOUT SIGNAL_PREFIX_S "g"
#define SIGNAL_REMOVED SIGNAL_PREFIX_S "h"
#define SIGNAL_WRAPPER_SET_SENSITIVE SIGNAL_PREFIX_S "i"
#define SIGNAL_WRAPPER_BACKGROUND_ALPHA SIGNAL_PREFIX_S "j"
#define SIGNAL_WRAPPER_QUIT SIGNAL_PREFIX_S "k"
#define SIGNAL_SET_SIZE "a"
#define SIGNAL_SET_ORIENTATION "b"
#define SIGNAL_SET_SCREEN_POSITION "c"
#define SIGNAL_SET_LOCKED "d"
#define SIGNAL_SAVE "e"
#define SIGNAL_SHOW_CONFIGURE "f"
#define SIGNAL_SHOW_ABOUT "g"
#define SIGNAL_REMOVED "h"
#define SIGNAL_WRAPPER_SET_SENSITIVE "i"
#define SIGNAL_WRAPPER_BACKGROUND_ALPHA "j"
#define SIGNAL_WRAPPER_QUIT "k"
/* special types for dbus communication */
#define PANEL_TYPE_DBUS_SET_MESSAGE dbus_g_type_get_struct ("GValueArray", \
G_TYPE_STRING, \
G_TYPE_VALUE, \
G_TYPE_UINT, \
G_TYPE_INVALID)
#define PANEL_TYPE_DBUS_SET_SIGNAL dbus_g_type_get_collection ("GPtrArray", \
PANEL_TYPE_DBUS_SET_MESSAGE)
#define PANEL_TYPE_DBUS_SET_MESSAGE \
dbus_g_type_get_struct ("GValueArray", \
G_TYPE_STRING, \
G_TYPE_VALUE, \
G_TYPE_INVALID)
#define PANEL_TYPE_DBUS_SET_SIGNAL \
dbus_g_type_get_collection ("GPtrArray", \
PANEL_TYPE_DBUS_SET_MESSAGE)
enum
{
DBUS_SET_PROPERTY,
DBUS_SET_VALUE,
DBUS_SET_REPLY_ID
DBUS_SET_VALUE
};
#endif /* !__PANEL_DBUS_H__ */
......@@ -77,6 +77,7 @@ pkgconfig_DATA = libxfce4panel-$(LIBXFCE4PANEL_VERSION_API).pc
# Build sources
#
if MAINTAINER_MODE
libxfce4panel-marshal.h: libxfce4panel-marshal.list Makefile
$(AM_V_GEN) glib-genmarshal --prefix=_libxfce4panel_marshal --internal --header $< > $@
......@@ -117,6 +118,7 @@ BUILT_SOURCES = \
CLEANFILES = \
actual-abi \
expected-abi
endif
EXTRA_DIST = \
......
......@@ -211,13 +211,26 @@ xfce_panel_plugin_provider_removed (XfcePanelPluginProvider *provider)
gboolean
xfce_panel_plugin_provider_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value)
const GValue *value,
guint *handle)
{
const GValue *real_value = value;
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), TRUE);
panel_return_val_if_fail (name != NULL, TRUE);
panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), TRUE);
return (*XFCE_PANEL_PLUGIN_PROVIDER_GET_INTERFACE (provider)->remote_event) (provider, name, value);
if (XFCE_PANEL_PLUGIN_PROVIDER_GET_INTERFACE (provider)->remote_event != NULL)
{
if (real_value != NULL
&& G_VALUE_HOLDS_UCHAR (real_value)
&& g_value_get_uchar == '\0')
real_value = NULL;
return (*XFCE_PANEL_PLUGIN_PROVIDER_GET_INTERFACE (provider)->remote_event) (provider, name, real_value, handle);
}
return FALSE;
}
......
......@@ -64,7 +64,8 @@ struct _XfcePanelPluginProviderInterface
void (*removed) (XfcePanelPluginProvider *provider);
gboolean (*remote_event) (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value);
const GValue *value,
guint *handle);
void (*set_locked) (XfcePanelPluginProvider *provider,
gboolean locked);
};
......@@ -149,7 +150,8 @@ void xfce_panel_plugin_provider_removed (XfcePanelP
gboolean xfce_panel_plugin_provider_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value);
const GValue *value,
guint *handle);
void xfce_panel_plugin_provider_set_locked (XfcePanelPluginProvider *provider,
gboolean locked);
......
......@@ -95,7 +95,8 @@ static void xfce_panel_plugin_show_about (XfcePanelPluginPr
static void xfce_panel_plugin_removed (XfcePanelPluginProvider *provider);
static gboolean xfce_panel_plugin_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value);
const GValue *value,
guint *handle);
static void xfce_panel_plugin_set_locked (XfcePanelPluginProvider *provider,
gboolean locked);
static void xfce_panel_plugin_take_window_notify (gpointer data,
......@@ -1346,7 +1347,8 @@ xfce_panel_plugin_removed (XfcePanelPluginProvider *provider)
static gboolean
xfce_panel_plugin_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value)
const GValue *value,
guint *handle)
{
gboolean stop_emission;
......
......@@ -15,6 +15,8 @@ bin_PROGRAMS = \
xfce4_panel_built_sources = \
panel-dbus-service-infos.h \
panel-dbus-client-infos.h \
panel-marshal.c \
panel-marshal.h \
panel-plugin-external-infos.h \
panel-preferences-dialog-ui.h
......@@ -80,6 +82,13 @@ xfce4_panel_DEPENDENCIES = \
if MAINTAINER_MODE
panel-marshal.h: panel-marshal.list Makefile
$(AM_V_GEN) glib-genmarshal --prefix=_panel_marshal --internal --header $< > $@
panel-marshal.c: panel-marshal.list Makefile
$(AM_V_GEN) echo "#include <panel/panel-marshal.h>" > $@ \
&& glib-genmarshal --prefix=_panel_marshal --body $< >> $@
panel-dbus-service-infos.h: $(srcdir)/panel-dbus-service-infos.xml Makefile
$(AM_V_GEN) dbus-binding-tool --prefix=panel_dbus_service --mode=glib-server $< > $@
......@@ -110,6 +119,7 @@ endif
EXTRA_DIST = \
panel-dbus-service-infos.xml \
panel-plugin-external-infos.xml \
panel-preferences-dialog.glade
panel-preferences-dialog.glade \
panel-marshal.list
# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
......@@ -220,8 +220,7 @@ panel_dbus_client_plugin_event (const gchar *plugin_event,
if (!(n_tokens == 2 || n_tokens == N_TOKENS)
|| exo_str_is_empty (tokens[PLUGIN_NAME])
|| exo_str_is_empty (tokens[NAME])
|| *tokens[NAME] == SIGNAL_PREFIX)
|| exo_str_is_empty (tokens[NAME]))
{
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
_("Invalid plugin event syntax specified. "
......
......@@ -54,6 +54,7 @@ static gboolean panel_dbus_service_add_new_item (PanelDBusService
const gchar *plugin_name,
gchar **arguments,
GError **error);
static void panel_dbus_service_plugin_event_free (gpointer data);
static gboolean panel_dbus_service_plugin_event (PanelDBusService *service,
const gchar *plugin_name,
const gchar *name,
......@@ -81,8 +82,20 @@ struct _PanelDBusService
/* the dbus connection */
DBusGConnection *connection;
/* queue for remote-events */
GHashTable *remote_events;
};
typedef struct
{
guint handle;
gchar *name;
GValue value;
GSList *plugins;
}
PluginEvent;
/* shared boolean for restart or quit */
......@@ -114,6 +127,9 @@ panel_dbus_service_init (PanelDBusService *service)
GError *error = NULL;
DBusConnection *connection;
service->remote_events = g_hash_table_new_full (g_int_hash, g_int_equal, NULL,
panel_dbus_service_plugin_event_free);
service->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
if (G_LIKELY (service->connection != NULL))
{
......@@ -141,6 +157,8 @@ panel_dbus_service_finalize (GObject *object)
PanelDBusService *service = PANEL_DBUS_SERVICE (object);
DBusConnection *connection;
panel_return_if_fail (g_hash_table_size (service->remote_events) == 0);
if (G_LIKELY (service->connection != NULL))
{
/* release the org.xfce.Panel name */
......@@ -151,6 +169,8 @@ panel_dbus_service_finalize (GObject *object)
dbus_g_connection_unref (service->connection);
}
g_hash_table_destroy (service->remote_events);
(*G_OBJECT_CLASS (panel_dbus_service_parent_class)->finalize) (object);
}
......@@ -242,6 +262,82 @@ panel_dbus_service_add_new_item (PanelDBusService *service,
static void
panel_dbus_service_plugin_event_free (gpointer data)
{
PluginEvent *event = data;
g_value_unset (&event->value);
g_free (event->name);
g_slist_free (event->plugins);
g_slice_free (PluginEvent, event);
}
static void
panel_dbus_service_plugin_event_result (XfcePanelPluginProvider *prev_provider,
guint handle,
gboolean result,
PanelDBusService *service)
{
PluginEvent *event;
GSList *li, *lnext;
XfcePanelPluginProvider *provider;
guint new_handle;
gboolean new_result;
g_signal_handlers_disconnect_by_func (G_OBJECT (prev_provider),
G_CALLBACK (panel_dbus_service_plugin_event_result), service);
event = g_hash_table_lookup (service->remote_events, &handle);
if (G_LIKELY (event != NULL))
{
panel_assert (event->handle == handle);
if (!result)
{
for (li = event->plugins, new_handle = 0; li != NULL; li = lnext, new_handle = 0)
{
lnext = li->next;
provider = li->data;
event->plugins = g_slist_delete_link (event->plugins, li);
/* maybe the plugin has been destroyed */
if (!XFCE_PANEL_PLUGIN_PROVIDER (provider))
continue;
new_result = xfce_panel_plugin_provider_remote_event (provider, event->name,
&event->value, &new_handle);
if (new_handle > 0 && lnext != NULL)
{
/* steal the old value */
g_hash_table_steal (service->remote_events, &handle);
/* update handle and insert again */
event->handle = new_handle;
g_hash_table_insert (service->remote_events, &event->handle, event);
g_signal_connect (G_OBJECT (provider), "remote-event-result",
G_CALLBACK (panel_dbus_service_plugin_event_result), service);
/* leave and wait for reply */
return;
}
else if (new_result)
{
/* we're done, remove from hash table below */
break;
}
}
}
/* handle can be removed */
g_hash_table_remove (service->remote_events, &handle);
}
}
static gboolean
panel_dbus_service_plugin_event (PanelDBusService *service,
const gchar *plugin_name,
......@@ -249,9 +345,11 @@ panel_dbus_service_plugin_event (PanelDBusService *service,
const GValue *value,
GError **error)
{
GSList *plugins, *li;
GSList *plugins, *li, *lnext;
PanelModuleFactory *factory;
const GValue *real_value = value;
PluginEvent *event;
guint handle;
gboolean result;
panel_return_val_if_fail (PANEL_IS_DBUS_SERVICE (service), FALSE);
panel_return_val_if_fail (error == NULL || *error == NULL, FALSE);
......@@ -259,22 +357,41 @@ panel_dbus_service_plugin_event (PanelDBusService *service,
panel_return_val_if_fail (name != NULL, FALSE);
panel_return_val_if_fail (G_IS_VALUE (value), FALSE);
/* if no type and value is send with the signal we send a char type
* with nul value */
if (G_VALUE_HOLDS_UCHAR (value)
&& g_value_get_uchar (value) == '\0')
real_value = NULL;
/* send the event to all matching plugins, break if one of the
* plugins return TRUE in this remote-event handler */
* plugins returns TRUE in this remote-event handler */
factory = panel_module_factory_get ();
plugins = panel_module_factory_get_plugins (factory, plugin_name);
for (li = plugins; li != NULL; li = li->next)
for (li = plugins, handle = 0; li != NULL; li = lnext, handle = 0)
{
lnext = li->next;
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (li->data), FALSE);
if (xfce_panel_plugin_provider_remote_event (li->data, name, real_value))
break;
result = xfce_panel_plugin_provider_remote_event (li->data, name, value, &handle);
if (handle > 0 && lnext != NULL)
{
event = g_slice_new0 (PluginEvent);
event->handle = handle;
event->name = g_strdup (name);
event->plugins = g_slist_copy (lnext);
g_value_init (&event->value, G_VALUE_TYPE (value));
g_value_copy (value, &event->value);
g_hash_table_insert (service->remote_events, &event->handle, event);
g_signal_connect (G_OBJECT (li->data), "remote-event-result",
G_CALLBACK (panel_dbus_service_plugin_event_result), service);
/* we're going to wait until the plugin replied */
break;
}
else if (result)
{
/* plugin returned %TRUE, so abort the event notification */
break;
}
}
g_slist_free (plugins);
g_object_unref (G_OBJECT (factory));
......
VOID:UINT,BOOLEAN
VOID:STRING,BOXED,UINT
......@@ -86,7 +86,8 @@ static void panel_plugin_external_46_show_about (XfcePanelPlu
static void panel_plugin_external_46_removed (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_46_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value);
const GValue *value,
guint *handler_id);
static void panel_plugin_external_46_set_locked (XfcePanelPluginProvider *provider,
gboolean locked);
static void panel_plugin_external_46_set_sensitive (PanelPluginExternal46 *external);
......@@ -757,7 +758,8 @@ panel_plugin_external_46_removed (XfcePanelPluginProvider *provider)
static gboolean
panel_plugin_external_46_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value)
const GValue *value,
guint *handle)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), TRUE);
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), TRUE);
......
......@@ -9,31 +9,42 @@
value="wrapper_dbus" />
<!--
property : Name of the property to set on the wrapper. This is used
for both panel values (no reply required) and plugin
event (require a reply from the plugin).
value : GValue with the value for the property.
reply_id : 0 if no reply is needed, if bigger then 0, the id to
return together with the Reply method.
s : property : Name of the property to set on the wrapper. This is used
for both panel values (no reply required) and plugin
event (require a reply from the plugin).
v : value : GValue with the value for the property.
-->
<signal name="Set">
<arg name="values" type="a(svu)" />
<arg name="values" type="a(sv)" />
</signal>
<!--
replay_id : The reply id given during the request.
value : The return value for the reply.
name : name of the event.
value : GValue with the value of the name.
handle : unique id for the RemoteEventResult method.
-->
<method name="Reply">
<arg name="reply_id" type="u" />
<signal name="RemoteEvent">
<arg name="name" type="s" />
<arg name="value" type="v" />
</method>
<arg name="handle" type="u" />
</signal>
<!--
signal : A provider signal from XfcePanelPluginProviderSignal.
-->
<method name="ProviderSignal">
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true" />
<arg name="signal" type="u" />
</method>
<!--
handle : the id send to the RemoteEvent signal.
result : result of the call.
-->
<method name="RemoteEventResult">
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true" />
<arg name="handle" type="u" />
<arg name="result" type="b" />
</method>
</interface>
</node>
......@@ -43,6 +43,7 @@
#include <panel/panel-plugin-external.h>
#include <panel/panel-window.h>
#include <panel/panel-dialogs.h>
#include <panel/panel-marshal.h>
......@@ -50,63 +51,64 @@
static void panel_plugin_external_provider_init (XfcePanelPluginProviderInterface *iface);
static GObject *panel_plugin_external_constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params);
static void panel_plugin_external_finalize (GObject *object);
static void panel_plugin_external_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void panel_plugin_external_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void panel_plugin_external_realize (GtkWidget *widget);
static void panel_plugin_external_unrealize (GtkWidget *widget);
static gboolean panel_plugin_external_plug_removed (GtkSocket *socket);
static void panel_plugin_external_plug_added (GtkSocket *socket);
static gboolean panel_plugin_external_dbus_reply (PanelPluginExternal *external,
guint reply_id,
const GValue *value,
GError **error);
static gboolean panel_plugin_external_dbus_provider_signal (PanelPluginExternal *external,
XfcePanelPluginProviderSignal provider_signal,
GError **error);
static void panel_plugin_external_dbus_set (PanelPluginExternal *external,
gboolean force);
static void panel_plugin_external_queue_add (PanelPluginExternal *external,
gboolean force,
const gchar *property,
const GValue *value);
static void panel_plugin_external_queue_add_noop (PanelPluginExternal *external,
gboolean force,
const gchar *property);
static const gchar *panel_plugin_external_get_name (XfcePanelPluginProvider *provider);
static gint panel_plugin_external_get_unique_id (XfcePanelPluginProvider *provider);
static void panel_plugin_external_set_size (XfcePanelPluginProvider *provider,
gint size);
static void panel_plugin_external_set_orientation (XfcePanelPluginProvider *provider,
GtkOrientation orientation);
static void panel_plugin_external_set_screen_position (XfcePanelPluginProvider *provider,
XfceScreenPosition screen_position);
static void panel_plugin_external_save (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_get_show_configure (XfcePanelPluginProvider *provider);
static void panel_plugin_external_show_configure (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_get_show_about (XfcePanelPluginProvider *provider);
static void panel_plugin_external_show_about (XfcePanelPluginProvider *provider);
static void panel_plugin_external_removed (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value);
static void panel_plugin_external_set_locked (XfcePanelPluginProvider *provider,
gboolean locked);
static void panel_plugin_external_set_sensitive (PanelPluginExternal *external);
static void panel_plugin_external_child_watch (GPid pid,
gint status,
gpointer user_data);
static void panel_plugin_external_child_watch_destroyed (gpointer user_data);
static void panel_plugin_external_provider_init (XfcePanelPluginProviderInterface *iface);
static GObject *panel_plugin_external_constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params);
static void panel_plugin_external_finalize (GObject *object);
static void panel_plugin_external_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void panel_plugin_external_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void panel_plugin_external_realize (GtkWidget *widget);
static void panel_plugin_external_unrealize (GtkWidget *widget);
static gboolean panel_plugin_external_plug_removed (GtkSocket *socket);
static void panel_plugin_external_plug_added (GtkSocket *socket);
static gboolean panel_plugin_external_dbus_provider_signal (PanelPluginExternal *external,
XfcePanelPluginProviderSignal provider_signal,
GError **error);
static gboolean panel_plugin_external_dbus_remote_event_result (PanelPluginExternal *external,
guint handle,
gboolean result,
GError **error);
static void panel_plugin_external_dbus_set (PanelPluginExternal *external,
gboolean force);
static void panel_plugin_external_queue_add (PanelPluginExternal *external,
gboolean force,
const gchar *property,
const GValue *value);
static void panel_plugin_external_queue_add_noop (PanelPluginExternal *external,
gboolean force,
const gchar *property);
static const gchar *panel_plugin_external_get_name (XfcePanelPluginProvider *provider);
static gint panel_plugin_external_get_unique_id (XfcePanelPluginProvider *provider);
static void panel_plugin_external_set_size (XfcePanelPluginProvider *provider,
gint size);
static void panel_plugin_external_set_orientation (XfcePanelPluginProvider *provider,
GtkOrientation orientation);
static void panel_plugin_external_set_screen_position (XfcePanelPluginProvider *provider,
XfceScreenPosition screen_position);
static void panel_plugin_external_save (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_get_show_configure (XfcePanelPluginProvider *provider);
static void panel_plugin_external_show_configure (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_get_show_about (XfcePanelPluginProvider *provider);
static void panel_plugin_external_show_about (XfcePanelPluginProvider *provider);
static void panel_plugin_external_removed (XfcePanelPluginProvider *provider);
static gboolean panel_plugin_external_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value,
guint *handler_id);
static void panel_plugin_external_set_locked (XfcePanelPluginProvider *provider,
gboolean locked);
static void panel_plugin_external_set_sensitive (PanelPluginExternal *external);
static void panel_plugin_external_child_watch (GPid pid,
gint status,
gpointer user_data);
static void panel_plugin_external_child_watch_destroyed (gpointer user_data);
......@@ -159,6 +161,8 @@ enum
enum
{
SET,
REMOTE_EVENT,
REMOTE_EVENT_RESULT,
LAST_SIGNAL
};
......@@ -203,6 +207,24 @@ panel_plugin_external_class_init (PanelPluginExternalClass *klass)
G_TYPE_NONE, 1,
PANEL_TYPE_DBUS_SET_SIGNAL);
external_signals[REMOTE_EVENT] =
g_signal_new (g_intern_static_string ("remote-event"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_panel_marshal_VOID__STRING_BOXED_UINT,