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.
 
 
 
 
 

379 lines
13 KiB

  1. /*
  2. * Copyright (C) 2008-2010 Nick Schermer <nick@xfce.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #ifdef HAVE_SYS_TYPES_H
  22. #include <sys/types.h>
  23. #endif
  24. #ifdef HAVE_SIGNAL_H
  25. #include <signal.h>
  26. #endif
  27. #ifdef HAVE_SYS_WAIT_H
  28. #include <sys/wait.h>
  29. #endif
  30. #include <exo/exo.h>
  31. #include <gdk/gdk.h>
  32. #include <gdk/gdkx.h>
  33. #include <libxfce4util/libxfce4util.h>
  34. #include <common/panel-private.h>
  35. #include <common/panel-dbus.h>
  36. #include <common/panel-debug.h>
  37. #include <libxfce4panel/libxfce4panel.h>
  38. #include <libxfce4panel/xfce-panel-plugin-provider.h>
  39. #include <panel/panel-module.h>
  40. #include <panel/panel-plugin-external.h>
  41. #include <panel/panel-plugin-external-wrapper.h>
  42. #include <panel/panel-window.h>
  43. #include <panel/panel-dialogs.h>
  44. #include <panel/panel-marshal.h>
  45. #define WRAPPER_BIN HELPERDIR G_DIR_SEPARATOR_S "wrapper"
  46. static GObject *panel_plugin_external_wrapper_constructor (GType type,
  47. guint n_construct_params,
  48. GObjectConstructParam *construct_params);
  49. static void panel_plugin_external_wrapper_set_properties (PanelPluginExternal *external,
  50. GSList *properties);
  51. static gchar **panel_plugin_external_wrapper_get_argv (PanelPluginExternal *external,
  52. gchar **arguments);
  53. static gboolean panel_plugin_external_wrapper_remote_event (PanelPluginExternal *external,
  54. const gchar *name,
  55. const GValue *value,
  56. guint *handle);
  57. static gboolean panel_plugin_external_wrapper_dbus_provider_signal (PanelPluginExternalWrapper *external,
  58. XfcePanelPluginProviderSignal provider_signal,
  59. GError **error);
  60. static gboolean panel_plugin_external_wrapper_dbus_remote_event_result (PanelPluginExternalWrapper *external,
  61. guint handle,
  62. gboolean result,
  63. GError **error);
  64. /* include the dbus glue generated by dbus-binding-tool */
  65. #include <panel/panel-plugin-external-wrapper-infos.h>
  66. struct _PanelPluginExternalWrapperClass
  67. {
  68. PanelPluginExternalClass __parent__;
  69. };
  70. struct _PanelPluginExternalWrapper
  71. {
  72. PanelPluginExternal __parent__;
  73. };
  74. enum
  75. {
  76. SET,
  77. REMOTE_EVENT,
  78. REMOTE_EVENT_RESULT,
  79. LAST_SIGNAL
  80. };
  81. static guint external_signals[LAST_SIGNAL];
  82. G_DEFINE_TYPE (PanelPluginExternalWrapper, panel_plugin_external_wrapper, PANEL_TYPE_PLUGIN_EXTERNAL)
  83. static void
  84. panel_plugin_external_wrapper_class_init (PanelPluginExternalWrapperClass *klass)
  85. {
  86. GObjectClass *gobject_class;
  87. PanelPluginExternalClass *plugin_external_class;
  88. gobject_class = G_OBJECT_CLASS (klass);
  89. gobject_class->constructor = panel_plugin_external_wrapper_constructor;
  90. plugin_external_class = PANEL_PLUGIN_EXTERNAL_CLASS (klass);
  91. plugin_external_class->get_argv = panel_plugin_external_wrapper_get_argv;
  92. plugin_external_class->set_properties = panel_plugin_external_wrapper_set_properties;
  93. plugin_external_class->remote_event = panel_plugin_external_wrapper_remote_event;
  94. external_signals[SET] =
  95. g_signal_new (g_intern_static_string ("set"),
  96. G_TYPE_FROM_CLASS (gobject_class),
  97. G_SIGNAL_RUN_LAST,
  98. 0, NULL, NULL,
  99. g_cclosure_marshal_VOID__BOXED,
  100. G_TYPE_NONE, 1,
  101. PANEL_TYPE_DBUS_SET_SIGNAL);
  102. external_signals[REMOTE_EVENT] =
  103. g_signal_new (g_intern_static_string ("remote-event"),
  104. G_TYPE_FROM_CLASS (gobject_class),
  105. G_SIGNAL_RUN_LAST,
  106. 0, NULL, NULL,
  107. _panel_marshal_VOID__STRING_BOXED_UINT,
  108. G_TYPE_NONE, 3,
  109. G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_UINT);
  110. external_signals[REMOTE_EVENT_RESULT] =
  111. g_signal_new (g_intern_static_string ("remote-event-result"),
  112. G_TYPE_FROM_CLASS (gobject_class),
  113. G_SIGNAL_RUN_LAST,
  114. 0, NULL, NULL,
  115. _panel_marshal_VOID__UINT_BOOLEAN,
  116. G_TYPE_NONE, 2,
  117. G_TYPE_UINT, G_TYPE_BOOLEAN);
  118. /* add dbus type info for plugins */
  119. dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
  120. &dbus_glib_panel_plugin_external_wrapper_object_info);
  121. }
  122. static void
  123. panel_plugin_external_wrapper_init (PanelPluginExternalWrapper *external)
  124. {
  125. }
  126. static GObject *
  127. panel_plugin_external_wrapper_constructor (GType type,
  128. guint n_construct_params,
  129. GObjectConstructParam *construct_params)
  130. {
  131. GObject *object;
  132. gchar *path;
  133. DBusGConnection *connection;
  134. GError *error = NULL;
  135. object = G_OBJECT_CLASS (panel_plugin_external_wrapper_parent_class)->constructor (type,
  136. n_construct_params,
  137. construct_params);
  138. connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
  139. if (G_LIKELY (connection != NULL))
  140. {
  141. /* register the object in dbus, the wrapper will monitor this object */
  142. panel_return_val_if_fail (PANEL_PLUGIN_EXTERNAL (object)->unique_id != -1, NULL);
  143. path = g_strdup_printf (PANEL_DBUS_WRAPPER_PATH, PANEL_PLUGIN_EXTERNAL (object)->unique_id);
  144. dbus_g_connection_register_g_object (connection, path, object);
  145. panel_debug (PANEL_DEBUG_EXTERNAL, "register dbus path %s", path);
  146. g_free (path);
  147. dbus_g_connection_unref (connection);
  148. }
  149. else
  150. {
  151. g_critical ("Failed to get D-Bus session bus: %s", error->message);
  152. g_error_free (error);
  153. }
  154. return object;
  155. }
  156. static gchar **
  157. panel_plugin_external_wrapper_get_argv (PanelPluginExternal *external,
  158. gchar **arguments)
  159. {
  160. guint i, argc = PLUGIN_ARGV_ARGUMENTS;
  161. gchar **argv;
  162. panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_WRAPPER (external), NULL);
  163. panel_return_val_if_fail (PANEL_IS_MODULE (external->module), NULL);
  164. panel_return_val_if_fail (GTK_IS_SOCKET (external), NULL);
  165. /* add the number of arguments to the argc count */
  166. if (G_UNLIKELY (arguments != NULL))
  167. argc += g_strv_length (arguments);
  168. /* setup the basic argv */
  169. argv = g_new0 (gchar *, argc + 1);
  170. argv[PLUGIN_ARGV_0] = g_strdup (WRAPPER_BIN);
  171. argv[PLUGIN_ARGV_FILENAME] = g_strdup (panel_module_get_filename (external->module));
  172. argv[PLUGIN_ARGV_UNIQUE_ID] = g_strdup_printf ("%d", external->unique_id);;
  173. argv[PLUGIN_ARGV_SOCKET_ID] = g_strdup_printf ("%u", gtk_socket_get_id (GTK_SOCKET (external)));;
  174. argv[PLUGIN_ARGV_NAME] = g_strdup (panel_module_get_name (external->module));
  175. argv[PLUGIN_ARGV_DISPLAY_NAME] = g_strdup (panel_module_get_display_name (external->module));
  176. argv[PLUGIN_ARGV_COMMENT] = g_strdup (panel_module_get_comment (external->module));
  177. argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = g_strdup (""); /* unused, for 4.6 plugins only */
  178. /* append the arguments */
  179. if (G_UNLIKELY (arguments != NULL))
  180. {
  181. for (i = 0; arguments[i] != NULL; i++)
  182. argv[i + PLUGIN_ARGV_ARGUMENTS] = g_strdup (arguments[i]);
  183. }
  184. return argv;
  185. }
  186. static void
  187. panel_plugin_external_wrapper_set_properties (PanelPluginExternal *external,
  188. GSList *properties)
  189. {
  190. GPtrArray *array;
  191. GValue message = { 0, };
  192. PluginProperty *property;
  193. GSList *li;
  194. guint i;
  195. array = g_ptr_array_sized_new (1);
  196. g_value_init (&message, PANEL_TYPE_DBUS_SET_PROPERTY);
  197. g_value_take_boxed (&message, dbus_g_type_specialized_construct (G_VALUE_TYPE (&message)));
  198. /* put properties in a dbus-suitable array for the wrapper */
  199. for (li = properties; li != NULL; li = li->next)
  200. {
  201. property = li->data;
  202. dbus_g_type_struct_set (&message,
  203. DBUS_SET_TYPE, property->type,
  204. DBUS_SET_VALUE, &property->value,
  205. G_MAXUINT);
  206. g_ptr_array_add (array, g_value_dup_boxed (&message));
  207. }
  208. /* send array to the wrapper */
  209. g_signal_emit (G_OBJECT (external), external_signals[SET], 0, array);
  210. G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  211. for (i = 0; i < array->len; i++)
  212. g_value_array_free (g_ptr_array_index (array, i));
  213. G_GNUC_END_IGNORE_DEPRECATIONS
  214. g_ptr_array_free (array, TRUE);
  215. g_value_unset (&message);
  216. }
  217. static gboolean
  218. panel_plugin_external_wrapper_remote_event (PanelPluginExternal *external,
  219. const gchar *name,
  220. const GValue *value,
  221. guint *handle)
  222. {
  223. static guint handle_counter = 0;
  224. GValue dummy_value = { 0, };
  225. const GValue *real_value = value;
  226. panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_WRAPPER (external), TRUE);
  227. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), TRUE);
  228. panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
  229. if (G_UNLIKELY (handle_counter > G_MAXUINT - 2))
  230. handle_counter = 0;
  231. *handle = ++handle_counter;
  232. if (value == NULL)
  233. {
  234. /* we send a dummy value over dbus */
  235. g_value_init (&dummy_value, G_TYPE_UCHAR);
  236. g_value_set_uchar (&dummy_value, '\0');
  237. real_value = &dummy_value;
  238. }
  239. g_signal_emit (G_OBJECT (external), external_signals[REMOTE_EVENT], 0,
  240. name, real_value, *handle);
  241. if (real_value != value)
  242. g_value_unset (&dummy_value);
  243. return TRUE;
  244. }
  245. static gboolean
  246. panel_plugin_external_wrapper_dbus_provider_signal (PanelPluginExternalWrapper *external,
  247. XfcePanelPluginProviderSignal provider_signal,
  248. GError **error)
  249. {
  250. panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
  251. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), FALSE);
  252. switch (provider_signal)
  253. {
  254. case PROVIDER_SIGNAL_SHOW_CONFIGURE:
  255. PANEL_PLUGIN_EXTERNAL (external)->show_configure = TRUE;
  256. break;
  257. case PROVIDER_SIGNAL_SHOW_ABOUT:
  258. PANEL_PLUGIN_EXTERNAL (external)->show_about = TRUE;
  259. break;
  260. default:
  261. /* other signals are handled in panel-applications.c */
  262. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
  263. provider_signal);
  264. break;
  265. }
  266. return TRUE;
  267. }
  268. static gboolean
  269. panel_plugin_external_wrapper_dbus_remote_event_result (PanelPluginExternalWrapper *external,
  270. guint handle,
  271. gboolean result,
  272. GError **error)
  273. {
  274. panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
  275. g_signal_emit (G_OBJECT (external), external_signals[REMOTE_EVENT_RESULT], 0,
  276. handle, result);
  277. return TRUE;
  278. }
  279. GtkWidget *
  280. panel_plugin_external_wrapper_new (PanelModule *module,
  281. gint unique_id,
  282. gchar **arguments)
  283. {
  284. panel_return_val_if_fail (PANEL_IS_MODULE (module), NULL);
  285. panel_return_val_if_fail (unique_id != -1, NULL);
  286. return g_object_new (PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER,
  287. "module", module,
  288. "unique-id", unique_id,
  289. "arguments", arguments, NULL);
  290. }