/* * Copyright (C) 2008-2010 Nick Schermer * * 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 #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SIGNAL_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 void panel_plugin_external_child_respawn_schedule (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_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_mode (XfcePanelPluginProvider *provider, XfcePanelPluginMode mode); static void panel_plugin_external_set_nrows (XfcePanelPluginProvider *provider, guint rows); 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, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_MODULE, g_param_spec_object ("module", NULL, NULL, PANEL_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_ARGUMENTS, g_param_spec_boxed ("arguments", NULL, NULL, G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | 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_mode = panel_plugin_external_set_mode; iface->set_nrows = panel_plugin_external_set_nrows; 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); } else { /* the child was asked to quit during unrealize and there is * still an pid, so wait for the child to quit and then * spawn it again */ panel_plugin_external_child_respawn_schedule (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; quitting 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), _("Execute"), GTK_RESPONSE_OK, _("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_child_setup (gpointer data) { PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (data); GdkDisplay *display; const gchar *name; /* this is what gdk_spawn_on_screen does */ display = gtk_widget_get_display (GTK_WIDGET (external)); name = gdk_display_get_name (display); g_setenv ("DISPLAY", name, 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_get_realized (GTK_WIDGET (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 (×tamp); 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 = g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, panel_plugin_external_child_spawn_child_setup, external, &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_get_realized (GTK_WIDGET (external))) return FALSE; /* delay startup if the old child is still embedded */ if (external->priv->embedded || external->priv->pid != 0) { 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), FALSE); 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_respawn_schedule (PanelPluginExternal *external) { panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external)); if (external->priv->spawn_timeout_id == 0) { 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); } } 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); /* reset the pid, it can't be embedded as well */ external->priv->pid = 0; external->priv->embedded = FALSE; 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 */ panel_utils_destroy_later (GTK_WIDGET (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_get_realized (GTK_WIDGET (external)) && (auto_restart || panel_plugin_external_child_ask_restart (external))) { panel_plugin_external_child_respawn_schedule (external); } 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_mode (XfcePanelPluginProvider *provider, XfcePanelPluginMode mode) { 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, mode); panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider), PROVIDER_PROP_TYPE_SET_MODE, &value); g_value_unset (&value); } static void panel_plugin_external_set_nrows (XfcePanelPluginProvider *provider, guint rows) { 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, rows); panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider), PROVIDER_PROP_TYPE_SET_NROWS, &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 (GTK_WIDGET (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_opacity (PanelPluginExternal *external, gdouble opacity) { GValue value = { 0, }; panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external)); g_value_init (&value, G_TYPE_DOUBLE); g_value_set_double (&value, opacity); panel_plugin_external_queue_add (external, PROVIDER_PROP_TYPE_SET_OPACITY, &value); g_value_unset (&value); } void panel_plugin_external_set_background_color (PanelPluginExternal *external, const GdkRGBA *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_rgba_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; }