You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1146 lines
39 KiB

/*
* Copyright (C) 2008-2010 Nick Schermer <nick@xfce.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <exo/exo.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <libxfce4util/libxfce4util.h>
#include <dbus/dbus-glib.h>
#include <common/panel-private.h>
#include <common/panel-dbus.h>
#include <common/panel-debug.h>
#include <libxfce4panel/libxfce4panel.h>
#include <libxfce4panel/xfce-panel-plugin-provider.h>
#include <panel/panel-module.h>
#include <panel/panel-plugin-external.h>
#include <panel/panel-plugin-external-46.h>
#include <panel/panel-window.h>
#include <panel/panel-dialogs.h>
static void panel_plugin_external_provider_init (XfcePanelPluginProviderInterface *iface);
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 void panel_plugin_external_plug_added (GtkSocket *socket);
static gboolean panel_plugin_external_plug_removed (GtkSocket *socket);
static gboolean panel_plugin_external_child_ask_restart (PanelPluginExternal *external);
static void panel_plugin_external_child_spawn (PanelPluginExternal *external);
static gboolean panel_plugin_external_child_respawn (gpointer user_data);
static void panel_plugin_external_child_respawn_destroyed (gpointer user_data);
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_queue_free (PanelPluginExternal *external);
static void panel_plugin_external_queue_send_to_child (PanelPluginExternal *external);
static void panel_plugin_external_queue_add (PanelPluginExternal *external,
XfcePanelPluginProviderPropType type,
const GValue *value);
static void panel_plugin_external_queue_add_action (PanelPluginExternal *external,
XfcePanelPluginProviderPropType type);
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_ask_remove (XfcePanelPluginProvider *provider);
static void panel_plugin_external_set_sensitive (PanelPluginExternal *external);
struct _PanelPluginExternalPrivate
{
/* startup arguments */
gchar **arguments;
guint embedded : 1;
/* dbus message queue */
GSList *queue;
/* auto restart timer */
GTimer *restart_timer;
/* child watch data */
GPid pid;
guint watch_id;
/* delayed spawning */
guint spawn_timeout_id;
};
enum
{
PROP_0,
PROP_MODULE,
PROP_UNIQUE_ID,
PROP_ARGUMENTS
};
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PanelPluginExternal, panel_plugin_external, GTK_TYPE_SOCKET,
G_IMPLEMENT_INTERFACE (XFCE_TYPE_PANEL_PLUGIN_PROVIDER, panel_plugin_external_provider_init))
static void
panel_plugin_external_class_init (PanelPluginExternalClass *klass)
{
GObjectClass *gobject_class;
GtkWidgetClass *gtkwidget_class;
GtkSocketClass *gtksocket_class;
g_type_class_add_private (klass, sizeof (PanelPluginExternalPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = panel_plugin_external_finalize;
gobject_class->set_property = panel_plugin_external_set_property;
gobject_class->get_property = panel_plugin_external_get_property;
gtkwidget_class = GTK_WIDGET_CLASS (klass);
gtkwidget_class->realize = panel_plugin_external_realize;
gtkwidget_class->unrealize = panel_plugin_external_unrealize;
gtksocket_class = GTK_SOCKET_CLASS (klass);
gtksocket_class->plug_added = panel_plugin_external_plug_added;
gtksocket_class->plug_removed = panel_plugin_external_plug_removed;
g_object_class_install_property (gobject_class,
PROP_UNIQUE_ID,
g_param_spec_int ("unique-id",
NULL, NULL,
-1, G_MAXINT, -1,
EXO_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_MODULE,
g_param_spec_object ("module",
NULL, NULL,
PANEL_TYPE_MODULE,
EXO_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_ARGUMENTS,
g_param_spec_boxed ("arguments",
NULL, NULL,
G_TYPE_STRV,
EXO_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY));
}
static void
panel_plugin_external_init (PanelPluginExternal *external)
{
external->priv = G_TYPE_INSTANCE_GET_PRIVATE (external, PANEL_TYPE_PLUGIN_EXTERNAL, PanelPluginExternalPrivate);
external->module = NULL;
external->show_configure = FALSE;
external->show_about = FALSE;
external->unique_id = -1;
external->priv->arguments = NULL;
external->priv->queue = NULL;
external->priv->restart_timer = NULL;
external->priv->embedded = FALSE;
external->priv->pid = 0;
external->priv->spawn_timeout_id = 0;
/* signal to pass gtk_widget_set_sensitive() changes to the remote window */
g_signal_connect (G_OBJECT (external), "notify::sensitive",
G_CALLBACK (panel_plugin_external_set_sensitive), NULL);
}
static void
panel_plugin_external_provider_init (XfcePanelPluginProviderInterface *iface)
{
iface->get_name = panel_plugin_external_get_name;
iface->get_unique_id = panel_plugin_external_get_unique_id;
iface->set_size = panel_plugin_external_set_size;
iface->set_orientation = panel_plugin_external_set_orientation;
iface->set_screen_position = panel_plugin_external_set_screen_position;
iface->save = panel_plugin_external_save;
iface->get_show_configure = panel_plugin_external_get_show_configure;
iface->show_configure = panel_plugin_external_show_configure;
iface->get_show_about = panel_plugin_external_get_show_about;
iface->show_about = panel_plugin_external_show_about;
iface->removed = panel_plugin_external_removed;
iface->remote_event = panel_plugin_external_remote_event;
iface->set_locked = panel_plugin_external_set_locked;
iface->ask_remove = panel_plugin_external_ask_remove;
}
static void
panel_plugin_external_finalize (GObject *object)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (object);
if (external->priv->spawn_timeout_id != 0)
g_source_remove (external->priv->spawn_timeout_id);
if (external->priv->watch_id != 0)
{
/* remove the child watch and don't leave zombies */
g_source_remove (external->priv->watch_id);
g_child_watch_add (external->priv->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
}
panel_plugin_external_queue_free (external);
g_strfreev (external->priv->arguments);
if (external->priv->restart_timer != NULL)
g_timer_destroy (external->priv->restart_timer);
g_object_unref (G_OBJECT (external->module));
(*G_OBJECT_CLASS (panel_plugin_external_parent_class)->finalize) (object);
}
static void
panel_plugin_external_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (object);
switch (prop_id)
{
case PROP_UNIQUE_ID:
g_value_set_int (value, external->unique_id);
break;
case PROP_ARGUMENTS:
g_value_set_boxed (value, external->priv->arguments);
break;
case PROP_MODULE:
g_value_set_object (value, external->module);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
panel_plugin_external_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (object);
switch (prop_id)
{
case PROP_UNIQUE_ID:
external->unique_id = g_value_get_int (value);
break;
case PROP_ARGUMENTS:
external->priv->arguments = g_value_dup_boxed (value);
break;
case PROP_MODULE:
external->module = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
panel_plugin_external_realize (GtkWidget *widget)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (widget);
/* realize the socket first */
(*GTK_WIDGET_CLASS (panel_plugin_external_parent_class)->realize) (widget);
if (external->priv->pid == 0)
{
if (external->priv->spawn_timeout_id != 0)
g_source_remove (external->priv->spawn_timeout_id);
panel_plugin_external_child_spawn (external);
}
}
static void
panel_plugin_external_unrealize (GtkWidget *widget)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (widget);
/* ask the child to quit */
if (external->priv->pid != 0)
{
if (external->priv->embedded)
panel_plugin_external_queue_add_action (external, PROVIDER_PROP_TYPE_ACTION_QUIT);
else
kill (external->priv->pid, SIGTERM);
}
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: plugin unrealized; quiting child",
panel_module_get_name (external->module),
external->unique_id);
(*GTK_WIDGET_CLASS (panel_plugin_external_parent_class)->unrealize) (widget);
}
static void
panel_plugin_external_plug_added (GtkSocket *socket)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (socket);
external->priv->embedded = TRUE;
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: child is embedded; %d properties in queue",
panel_module_get_name (external->module),
external->unique_id,
g_slist_length (external->priv->queue));
/* send queue to wrapper */
panel_plugin_external_queue_send_to_child (external);
}
static gboolean
panel_plugin_external_plug_removed (GtkSocket *socket)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (socket);
external->priv->embedded = FALSE;
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: child is unembedded",
panel_module_get_name (external->module),
external->unique_id);
return TRUE;
}
static gboolean
panel_plugin_external_child_ask_restart_dialog (GtkWindow *parent,
const gchar *plugin_name)
{
GtkWidget *dialog;
gint response;
panel_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
panel_return_val_if_fail (plugin_name != NULL, FALSE);
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
_("Plugin \"%s\" unexpectedly left the panel, do you want to restart it?"),
plugin_name);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("The plugin restarted more than once in "
"the last %d seconds. If you press Execute the panel will try to restart "
"the plugin otherwise it will be permanently removed from the panel."),
PANEL_PLUGIN_AUTO_RESTART);
gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_EXECUTE, GTK_RESPONSE_OK,
GTK_STOCK_REMOVE, GTK_RESPONSE_CLOSE, NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return (response == GTK_RESPONSE_OK);
}
static gboolean
panel_plugin_external_child_ask_restart (PanelPluginExternal *external)
{
GtkWidget *toplevel;
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (external));
panel_return_val_if_fail (PANEL_IS_WINDOW (toplevel), FALSE);
if (external->priv->restart_timer == NULL
|| g_timer_elapsed (external->priv->restart_timer, NULL) > PANEL_PLUGIN_AUTO_RESTART)
{
g_message ("Plugin %s-%d has been automatically restarted after crash.",
panel_module_get_name (external->module),
external->unique_id);
}
else if (!panel_plugin_external_child_ask_restart_dialog (GTK_WINDOW (toplevel),
panel_module_get_display_name (external->module)))
{
if (external->priv->watch_id != 0)
{
/* remove the child watch and don't leave zombies */
g_source_remove (external->priv->watch_id);
g_child_watch_add (external->priv->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
external->priv->watch_id = 0;
}
/* cleanup the plugin configuration (in PanelApplication) and
* destroy the plugin */
xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
PROVIDER_SIGNAL_REMOVE_PLUGIN);
return FALSE;
}
/* create or reset the restart timer */
if (external->priv->restart_timer == NULL)
external->priv->restart_timer = g_timer_new ();
else
g_timer_reset (external->priv->restart_timer);
return TRUE;
}
static void
panel_plugin_external_child_spawn (PanelPluginExternal *external)
{
gchar **argv, **dbg_argv, **tmp_argv;
GError *error = NULL;
gboolean succeed;
GPid pid;
gchar *program, *cmd_line;
guint i;
gint tmp_argc;
GTimeVal timestamp;
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
panel_return_if_fail (GTK_WIDGET_REALIZED (external));
/* set plugin specific arguments */
argv = (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (external)->get_argv) (external, external->priv->arguments);
panel_return_if_fail (argv != NULL);
/* check debugging state */
if (panel_debug_has_domain (PANEL_DEBUG_GDB)
|| panel_debug_has_domain (PANEL_DEBUG_VALGRIND))
{
g_get_current_time (&timestamp);
cmd_line = NULL;
program = NULL;
/* note that if the program was not found in PATH, we already warned
* for it in panel_debug_notify_proxy, so no need to do that again */
if (panel_debug_has_domain (PANEL_DEBUG_GDB))
{
program = g_find_program_in_path ("gdb");
if (G_LIKELY (program != NULL))
{
cmd_line = g_strdup_printf ("%s -batch "
"-ex 'set logging file %s" G_DIR_SEPARATOR_S "%li_gdb_%s_%s.log' "
"-ex 'set logging on' "
"-ex 'set pagination off' "
"-ex 'set logging redirect on' "
"-ex 'run' "
"-ex 'backtrace full' "
"-ex 'info registers' "
"-args",
program, g_get_tmp_dir (), timestamp.tv_sec,
panel_module_get_name (external->module),
argv[PLUGIN_ARGV_UNIQUE_ID]);
}
}
else if (panel_debug_has_domain (PANEL_DEBUG_VALGRIND))
{
program = g_find_program_in_path ("valgrind");
if (G_LIKELY (program != NULL))
{
cmd_line = g_strdup_printf ("%s "
"--log-file='%s" G_DIR_SEPARATOR_S "%li_valgrind_%s_%s.log' "
"--leak-check=full --show-reachable=yes -v ",
program, g_get_tmp_dir (), timestamp.tv_sec,
panel_module_get_name (external->module),
argv[PLUGIN_ARGV_UNIQUE_ID]);
}
}
if (cmd_line != NULL
&& g_shell_parse_argv (cmd_line, &tmp_argc, &tmp_argv, &error))
{
dbg_argv = g_new0 (gchar *, tmp_argc + g_strv_length (argv) + 1);
for (i = 0; tmp_argv[i] != NULL; i++)
dbg_argv[i] = tmp_argv[i];
g_free (tmp_argv);
for (i = 0; argv[i] != NULL; i++)
dbg_argv[i + tmp_argc] = argv[i];
g_free (argv);
argv = dbg_argv;
}
else
{
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: Failed to run the plugin in %s: %s",
panel_module_get_name (external->module),
external->unique_id, program,
cmd_line != NULL ? error->message : "debugger not found");
g_error_free (error);
return;
}
g_free (program);
g_free (cmd_line);
}
/* spawn the proccess */
succeed = gdk_spawn_on_screen (gtk_widget_get_screen (GTK_WIDGET (external)),
NULL, argv, NULL,
G_SPAWN_DO_NOT_REAP_CHILD, NULL,
NULL, &pid, &error);
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: child spawned; pid=%d, argc=%d",
panel_module_get_name (external->module),
external->unique_id, pid, g_strv_length (argv));
if (G_LIKELY (succeed))
{
/* watch the child */
external->priv->pid = pid;
external->priv->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid,
panel_plugin_external_child_watch, external,
panel_plugin_external_child_watch_destroyed);
}
else
{
g_critical ("Failed to spawn the xfce4-panel-wrapper: %s", error->message);
g_error_free (error);
}
g_strfreev (argv);
}
static gboolean
panel_plugin_external_child_respawn (gpointer user_data)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
GtkWidget *window;
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
/* abort startup if the plugin is not realized */
if (!GTK_WIDGET_REALIZED (external))
return FALSE;
/* delay startup if the old child is still embedded */
if (external->priv->embedded)
{
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: still a child embedded, respawn delayed",
panel_module_get_name (external->module), external->unique_id);
return TRUE;
}
panel_plugin_external_queue_free (external);
window = gtk_widget_get_toplevel (GTK_WIDGET (external));
panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
panel_window_set_povider_info (PANEL_WINDOW (window), GTK_WIDGET (external));
panel_plugin_external_child_spawn (external);
/* stop timeout */
return FALSE;
}
static void
panel_plugin_external_child_respawn_destroyed (gpointer user_data)
{
PANEL_PLUGIN_EXTERNAL (user_data)->priv->spawn_timeout_id = 0;
}
static void
panel_plugin_external_child_watch (GPid pid,
gint status,
gpointer user_data)
{
PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
gboolean auto_restart = FALSE;
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
panel_return_if_fail (external->priv->pid == pid);
external->priv->pid = 0;
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: child exited with status %d",
panel_module_get_name (external->module),
external->unique_id, status);
if (WIFEXITED (status))
{
/* extract our return value from the status */
switch (WEXITSTATUS (status))
{
case PLUGIN_EXIT_SUCCESS:
/* normal exit, do not try to restart */
goto close_pid;
case PLUGIN_EXIT_SUCCESS_AND_RESTART:
/* the panel asked for a restart, so do not bother the user */
auto_restart = TRUE;
break;
case PLUGIN_EXIT_FAILURE:
/* do nothing, maybe we try to restart */
break;
case PLUGIN_EXIT_ARGUMENTS_FAILED:
case PLUGIN_EXIT_PREINIT_FAILED:
case PLUGIN_EXIT_CHECK_FAILED:
case PLUGIN_EXIT_NO_PROVIDER:
g_warning ("Plugin %s-%d exited with status %d, removing from panel configuration",
panel_module_get_name (external->module),
external->unique_id, WEXITSTATUS (status));
/* cleanup the plugin configuration (in PanelApplication) */
xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
PROVIDER_SIGNAL_REMOVE_PLUGIN);
/* wait until everything is settled before we destroy */
exo_gtk_object_destroy_later (GTK_OBJECT (external));
goto close_pid;
}
}
else if (WIFSIGNALED (status))
{
switch (WTERMSIG (status))
{
case SIGUSR1:
/* the panel asked for a restart, so do not bother the user */
auto_restart = TRUE;
break;
}
}
if (GTK_WIDGET_REALIZED (external)
&& external->priv->spawn_timeout_id == 0
&& (auto_restart || panel_plugin_external_child_ask_restart (external)))
{
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: scheduled a respawn of the child",
panel_module_get_name (external->module), external->unique_id);
/* schedule a restart timeout */
external->priv->spawn_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 100, panel_plugin_external_child_respawn,
external, panel_plugin_external_child_respawn_destroyed);
}
close_pid:
g_spawn_close_pid (pid);
}
static void
panel_plugin_external_child_watch_destroyed (gpointer user_data)
{
if (PANEL_IS_PLUGIN_EXTERNAL (user_data))
PANEL_PLUGIN_EXTERNAL (user_data)->priv->watch_id = 0;
}
static void
panel_plugin_external_queue_free (PanelPluginExternal *external)
{
PluginProperty *property;
GSList *li;
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
for (li = external->priv->queue; li != NULL; li = li->next)
{
property = li->data;
g_value_unset (&property->value);
g_slice_free (PluginProperty, property);
}
g_slist_free (external->priv->queue);
external->priv->queue = NULL;
}
static void
panel_plugin_external_queue_send_to_child (PanelPluginExternal *external)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
if (external->priv->queue != NULL)
{
external->priv->queue = g_slist_reverse (external->priv->queue);
(*PANEL_PLUGIN_EXTERNAL_GET_CLASS (external)->set_properties) (external, external->priv->queue);
panel_plugin_external_queue_free (external);
}
}
static void
panel_plugin_external_queue_add (PanelPluginExternal *external,
XfcePanelPluginProviderPropType type,
const GValue *value)
{
PluginProperty *prop;
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
panel_return_if_fail (G_TYPE_CHECK_VALUE (value));
prop = g_slice_new0 (PluginProperty);
prop->type = type;
g_value_init (&prop->value, G_VALUE_TYPE (value));
g_value_copy (value, &prop->value);
external->priv->queue = g_slist_prepend (external->priv->queue, prop);
if (external->priv->embedded)
panel_plugin_external_queue_send_to_child (external);
}
static void
panel_plugin_external_queue_add_action (PanelPluginExternal *external,
XfcePanelPluginProviderPropType type)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
/* add to queue with noop boolean */
g_value_init (&value, G_TYPE_BOOLEAN);
panel_plugin_external_queue_add (external, type, &value);
g_value_unset (&value);
}
static const gchar *
panel_plugin_external_get_name (XfcePanelPluginProvider *provider)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider), NULL);
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), NULL);
return panel_module_get_name (PANEL_PLUGIN_EXTERNAL (provider)->module);
}
static gint
panel_plugin_external_get_unique_id (XfcePanelPluginProvider *provider)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider), -1);
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), -1);
return PANEL_PLUGIN_EXTERNAL (provider)->unique_id;
}
static void
panel_plugin_external_set_size (XfcePanelPluginProvider *provider,
gint size)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, size);
panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_SET_SIZE, &value);
g_value_unset (&value);
}
static void
panel_plugin_external_set_orientation (XfcePanelPluginProvider *provider,
GtkOrientation orientation)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, orientation);
panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_SET_ORIENTATION, &value);
g_value_unset (&value);
}
static void
panel_plugin_external_set_screen_position (XfcePanelPluginProvider *provider,
XfceScreenPosition screen_position)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, screen_position);
panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_SET_SCREEN_POSITION, &value);
g_value_unset (&value);
}
static void
panel_plugin_external_save (XfcePanelPluginProvider *provider)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_ACTION_SAVE);
}
static gboolean
panel_plugin_external_get_show_configure (XfcePanelPluginProvider *provider)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider), FALSE);
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), FALSE);
return PANEL_PLUGIN_EXTERNAL (provider)->show_configure;
}
static void
panel_plugin_external_show_configure (XfcePanelPluginProvider *provider)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE);
}
static gboolean
panel_plugin_external_get_show_about (XfcePanelPluginProvider *provider)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider), FALSE);
panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), FALSE);
return PANEL_PLUGIN_EXTERNAL (provider)->show_about;
}
static void
panel_plugin_external_show_about (XfcePanelPluginProvider *provider)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT);
}
static void
panel_plugin_external_removed (XfcePanelPluginProvider *provider)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_ACTION_REMOVED);
}
static gboolean
panel_plugin_external_remote_event (XfcePanelPluginProvider *provider,
const gchar *name,
const GValue *value,
guint *handle)
{
return (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (provider)->remote_event) (PANEL_PLUGIN_EXTERNAL (provider),
name, value, handle);
}
static void
panel_plugin_external_set_locked (XfcePanelPluginProvider *provider,
gboolean locked)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, locked);
panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_SET_LOCKED, &value);
g_value_unset (&value);
}
static void
panel_plugin_external_ask_remove (XfcePanelPluginProvider *provider)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
PROVIDER_PROP_TYPE_ACTION_ASK_REMOVE);
}
static void
panel_plugin_external_set_sensitive (PanelPluginExternal *external)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, GTK_WIDGET_IS_SENSITIVE (external));
panel_plugin_external_queue_add (external, PROVIDER_PROP_TYPE_SET_SENSITIVE,
&value);
g_value_unset (&value);
}
void
panel_plugin_external_restart (PanelPluginExternal *external)
{
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
if (external->priv->pid != 0)
{
panel_debug (PANEL_DEBUG_EXTERNAL,
"%s-%d: child asked to restart; pid=%d",
panel_module_get_name (external->module),
external->unique_id, external->priv->pid);
panel_plugin_external_queue_free (external);
if (external->priv->embedded)
panel_plugin_external_queue_add_action (external, PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART);
else
kill (external->priv->pid, SIGUSR1);
}
}
void
panel_plugin_external_set_background_alpha (PanelPluginExternal *external,
gdouble alpha)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
g_value_init (&value, G_TYPE_DOUBLE);
g_value_set_double (&value, alpha);
panel_plugin_external_queue_add (external, PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA,
&value);
g_value_unset (&value);
}
void
panel_plugin_external_set_background_color (PanelPluginExternal *external,
const GdkColor *color)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
if (G_LIKELY (color != NULL))
{
g_value_init (&value, G_TYPE_STRING);
g_value_take_string (&value, gdk_color_to_string (color));
panel_plugin_external_queue_add (external,
PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR,
&value);
g_value_unset (&value);
}
else
{
panel_plugin_external_queue_add_action (external,
PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET);
}
}
void
panel_plugin_external_set_background_image (PanelPluginExternal *external,
const gchar *image)
{
GValue value = { 0, };
panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
if (!external->priv->embedded
&& PANEL_IS_PLUGIN_EXTERNAL_46 (external))
{
/* hack to set the background of 4.6 plugins before the child is
* embedded, so it is directly send with the startup arguments */
panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (external), image);
}
else if (G_UNLIKELY (image != NULL))
{
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, image);
panel_plugin_external_queue_add (external,
PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE,
&value);
g_value_unset (&value);
}
else
{
panel_plugin_external_queue_add_action (external,
PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET);
}
}
GPid
panel_plugin_external_get_pid (PanelPluginExternal *external)
{
panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), 0);
return external->priv->pid;
}