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.
 
 
 
 
 

2733 lines
89 KiB

  1. /*
  2. * Copyright (C) 2008-2010 Nick Schermer <nick@xfce.org>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library 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 GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 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_LIBINTL_H
  22. #include <libintl.h>
  23. #endif
  24. #ifdef HAVE_LOCALE_H
  25. #include <locale.h>
  26. #endif
  27. #include <gtk/gtk.h>
  28. #include <glib.h>
  29. #include <libxfce4util/libxfce4util.h>
  30. #include <common/panel-private.h>
  31. #include <libxfce4panel/xfce-panel-macros.h>
  32. #include <libxfce4panel/xfce-panel-plugin.h>
  33. #include <libxfce4panel/xfce-panel-plugin-provider.h>
  34. #include <libxfce4panel/libxfce4panel-marshal.h>
  35. #include <libxfce4panel/libxfce4panel-alias.h>
  36. /**
  37. * SECTION: xfce-panel-plugin
  38. * @title: XfcePanelPlugin
  39. * @short_description: Interface for panel plugins
  40. * @include: libxfce4panel/libxfce4panel.h
  41. *
  42. * The interface plugin developers used to interact with the plugin and
  43. * the panel.
  44. **/
  45. #define XFCE_PANEL_PLUGIN_CONSTRUCTED(plugin) \
  46. PANEL_HAS_FLAG (XFCE_PANEL_PLUGIN (plugin)->priv->flags, \
  47. PLUGIN_FLAG_CONSTRUCTED)
  48. typedef const gchar *(*ProviderToPluginChar) (XfcePanelPluginProvider *provider);
  49. typedef gint (*ProviderToPluginInt) (XfcePanelPluginProvider *provider);
  50. static void xfce_panel_plugin_provider_init (XfcePanelPluginProviderInterface *iface);
  51. static GObject *xfce_panel_plugin_constructor (GType type,
  52. guint n_props,
  53. GObjectConstructParam *props);
  54. static void xfce_panel_plugin_get_property (GObject *object,
  55. guint prop_id,
  56. GValue *value,
  57. GParamSpec *pspec);
  58. static void xfce_panel_plugin_set_property (GObject *object,
  59. guint prop_id,
  60. const GValue *value,
  61. GParamSpec *pspec);
  62. static void xfce_panel_plugin_dispose (GObject *object);
  63. static void xfce_panel_plugin_finalize (GObject *object);
  64. static void xfce_panel_plugin_realize (GtkWidget *widget);
  65. static gboolean xfce_panel_plugin_button_press_event (GtkWidget *widget,
  66. GdkEventButton *event);
  67. static void xfce_panel_plugin_menu_move (XfcePanelPlugin *plugin);
  68. static void xfce_panel_plugin_menu_remove (XfcePanelPlugin *plugin);
  69. static void xfce_panel_plugin_menu_add_items (XfcePanelPlugin *plugin);
  70. static void xfce_panel_plugin_menu_panel_preferences (XfcePanelPlugin *plugin);
  71. static GtkMenu *xfce_panel_plugin_menu_get (XfcePanelPlugin *plugin);
  72. static inline gchar *xfce_panel_plugin_relative_filename (XfcePanelPlugin *plugin);
  73. static void xfce_panel_plugin_unregister_menu (GtkMenu *menu,
  74. XfcePanelPlugin *plugin);
  75. static void xfce_panel_plugin_set_size (XfcePanelPluginProvider *provider,
  76. gint size);
  77. static void xfce_panel_plugin_set_mode (XfcePanelPluginProvider *provider,
  78. XfcePanelPluginMode mode);
  79. static void xfce_panel_plugin_set_nrows (XfcePanelPluginProvider *provider,
  80. guint nrows);
  81. static void xfce_panel_plugin_set_screen_position (XfcePanelPluginProvider *provider,
  82. XfceScreenPosition screen_position);
  83. static void xfce_panel_plugin_save (XfcePanelPluginProvider *provider);
  84. static gboolean xfce_panel_plugin_get_show_configure (XfcePanelPluginProvider *provider);
  85. static void xfce_panel_plugin_show_configure (XfcePanelPluginProvider *provider);
  86. static gboolean xfce_panel_plugin_get_show_about (XfcePanelPluginProvider *provider);
  87. static void xfce_panel_plugin_show_about (XfcePanelPluginProvider *provider);
  88. static void xfce_panel_plugin_removed (XfcePanelPluginProvider *provider);
  89. static gboolean xfce_panel_plugin_remote_event (XfcePanelPluginProvider *provider,
  90. const gchar *name,
  91. const GValue *value,
  92. guint *handle);
  93. static void xfce_panel_plugin_set_locked (XfcePanelPluginProvider *provider,
  94. gboolean locked);
  95. static void xfce_panel_plugin_ask_remove (XfcePanelPluginProvider *provider);
  96. static void xfce_panel_plugin_take_window_notify (gpointer data,
  97. GObject *where_the_object_was);
  98. static void xfce_panel_plugin_menu_item_destroy (GtkWidget *item,
  99. XfcePanelPlugin *plugin);
  100. enum
  101. {
  102. PROP_0,
  103. PROP_NAME,
  104. PROP_DISPLAY_NAME,
  105. PROP_COMMENT,
  106. PROP_ARGUMENTS,
  107. PROP_UNIQUE_ID,
  108. PROP_ORIENTATION,
  109. PROP_SIZE,
  110. PROP_SMALL,
  111. PROP_SCREEN_POSITION,
  112. PROP_EXPAND,
  113. PROP_MODE,
  114. PROP_NROWS,
  115. PROP_SHRINK
  116. };
  117. enum
  118. {
  119. ABOUT,
  120. CONFIGURE_PLUGIN,
  121. FREE_DATA,
  122. ORIENTATION_CHANGED,
  123. REMOTE_EVENT,
  124. REMOVED,
  125. SAVE,
  126. SIZE_CHANGED,
  127. SCREEN_POSITION_CHANGED,
  128. MODE_CHANGED,
  129. NROWS_CHANGED,
  130. LAST_SIGNAL
  131. };
  132. typedef enum
  133. {
  134. PLUGIN_FLAG_DISPOSED = 1 << 0,
  135. PLUGIN_FLAG_CONSTRUCTED = 1 << 1,
  136. PLUGIN_FLAG_REALIZED = 1 << 2,
  137. PLUGIN_FLAG_SHOW_CONFIGURE = 1 << 3,
  138. PLUGIN_FLAG_SHOW_ABOUT = 1 << 4,
  139. PLUGIN_FLAG_BLOCK_AUTOHIDE = 1 << 5
  140. }
  141. PluginFlags;
  142. struct _XfcePanelPluginPrivate
  143. {
  144. /* plugin information */
  145. gchar *name;
  146. gchar *display_name;
  147. gchar *comment;
  148. gint unique_id;
  149. gchar *property_base;
  150. gchar **arguments;
  151. gint size; /* single row size */
  152. guint expand : 1;
  153. guint shrink : 1;
  154. guint nrows;
  155. XfcePanelPluginMode mode;
  156. guint small : 1;
  157. XfceScreenPosition screen_position;
  158. guint locked : 1;
  159. GSList *menu_items;
  160. /* flags for rembering states */
  161. PluginFlags flags;
  162. /* plugin right-click menu */
  163. GtkMenu *menu;
  164. /* menu block counter (configure insensitive) */
  165. gint menu_blocked;
  166. /* autohide block counter */
  167. gint panel_lock;
  168. };
  169. static guint plugin_signals[LAST_SIGNAL];
  170. static GQuark item_properties = 0;
  171. static GQuark item_about = 0;
  172. G_DEFINE_TYPE_WITH_CODE (XfcePanelPlugin, xfce_panel_plugin, GTK_TYPE_EVENT_BOX,
  173. G_IMPLEMENT_INTERFACE (XFCE_TYPE_PANEL_PLUGIN_PROVIDER,
  174. xfce_panel_plugin_provider_init));
  175. static void
  176. xfce_panel_plugin_class_init (XfcePanelPluginClass *klass)
  177. {
  178. GObjectClass *gobject_class;
  179. GtkWidgetClass *gtkwidget_class;
  180. g_type_class_add_private (klass, sizeof (XfcePanelPluginPrivate));
  181. klass->construct = NULL;
  182. gobject_class = G_OBJECT_CLASS (klass);
  183. gobject_class->constructor = xfce_panel_plugin_constructor;
  184. gobject_class->get_property = xfce_panel_plugin_get_property;
  185. gobject_class->set_property = xfce_panel_plugin_set_property;
  186. gobject_class->dispose = xfce_panel_plugin_dispose;
  187. gobject_class->finalize = xfce_panel_plugin_finalize;
  188. gtkwidget_class = GTK_WIDGET_CLASS (klass);
  189. gtkwidget_class->realize = xfce_panel_plugin_realize;
  190. gtkwidget_class->button_press_event = xfce_panel_plugin_button_press_event;
  191. /**
  192. * XfcePanelPlugin::about
  193. * @plugin : an #XfcePanelPlugin.
  194. *
  195. * This signal is emmitted when the About entry in the right-click
  196. * menu is clicked. Plugin writes can use it to show information
  197. * about the plugin and display credits of the developers, translators
  198. * and other contributors.
  199. *
  200. * See also: xfce_panel_plugin_menu_show_about().
  201. **/
  202. plugin_signals[ABOUT] =
  203. g_signal_new (g_intern_static_string ("about"),
  204. G_TYPE_FROM_CLASS (klass),
  205. G_SIGNAL_RUN_LAST,
  206. G_STRUCT_OFFSET (XfcePanelPluginClass, about),
  207. NULL, NULL,
  208. g_cclosure_marshal_VOID__VOID,
  209. G_TYPE_NONE, 0);
  210. /**
  211. * XfcePanelPlugin::configure-plugin
  212. * @plugin : an #XfcePanelPlugin.
  213. *
  214. * This signal is emmitted when the Properties entry in the right-click
  215. * menu is clicked. Plugin writes can use this signal to open a
  216. * plugin settings dialog.
  217. *
  218. * See also: xfce_panel_plugin_menu_show_configure() and
  219. * xfce_titled_dialog_new ().
  220. **/
  221. plugin_signals[CONFIGURE_PLUGIN] =
  222. g_signal_new (g_intern_static_string ("configure-plugin"),
  223. G_TYPE_FROM_CLASS (klass),
  224. G_SIGNAL_RUN_LAST,
  225. G_STRUCT_OFFSET (XfcePanelPluginClass, configure_plugin),
  226. NULL, NULL,
  227. g_cclosure_marshal_VOID__VOID,
  228. G_TYPE_NONE, 0);
  229. /**
  230. * XfcePanelPlugin::free-data
  231. * @plugin : an #XfcePanelPlugin.
  232. *
  233. * This signal is emmitted when the plugin is closing. Plugin
  234. * writers should use this signal to free any allocated resources.
  235. *
  236. * See also #XfceHVBox.
  237. **/
  238. plugin_signals[FREE_DATA] =
  239. g_signal_new (g_intern_static_string ("free-data"),
  240. G_TYPE_FROM_CLASS (klass),
  241. G_SIGNAL_RUN_LAST,
  242. G_STRUCT_OFFSET (XfcePanelPluginClass, free_data),
  243. NULL, NULL,
  244. g_cclosure_marshal_VOID__VOID,
  245. G_TYPE_NONE, 0);
  246. /**
  247. * XfcePanelPlugin::orientation-changed
  248. * @plugin : an #XfcePanelPlugin.
  249. * @orientation : new #GtkOrientation of the panel.
  250. *
  251. * This signal is emmitted whenever the orientation of the panel
  252. * the @plugin is on changes. Plugins writers can for example use
  253. * this signal to change the order of widgets in the plugin.
  254. *
  255. * See also: #XfceHVBox.
  256. **/
  257. plugin_signals[ORIENTATION_CHANGED] =
  258. g_signal_new (g_intern_static_string ("orientation-changed"),
  259. G_TYPE_FROM_CLASS (klass),
  260. G_SIGNAL_RUN_LAST,
  261. G_STRUCT_OFFSET (XfcePanelPluginClass, orientation_changed),
  262. NULL, NULL,
  263. g_cclosure_marshal_VOID__ENUM,
  264. G_TYPE_NONE, 1, GTK_TYPE_ORIENTATION);
  265. /**
  266. * XfcePanelPlugin::mode-changed
  267. * @plugin : an #XfcePanelPlugin.
  268. * @mode : new #XfcePanelPluginMode of the panel.
  269. *
  270. * This signal is emmitted whenever the mode of the panel
  271. * the @plugin is on changes.
  272. *
  273. * Since: 4.10
  274. **/
  275. plugin_signals[MODE_CHANGED] =
  276. g_signal_new (g_intern_static_string ("mode-changed"),
  277. G_TYPE_FROM_CLASS (klass),
  278. G_SIGNAL_RUN_LAST,
  279. G_STRUCT_OFFSET (XfcePanelPluginClass, mode_changed),
  280. NULL, NULL,
  281. g_cclosure_marshal_VOID__ENUM,
  282. G_TYPE_NONE, 1, XFCE_TYPE_PANEL_PLUGIN_MODE);
  283. /**
  284. * XfcePanelPlugin::nrows-changed
  285. * @plugin : an #XfcePanelPlugin.
  286. * @rows : new number of rows of the panel
  287. *
  288. * This signal is emmitted whenever the nrows of the panel
  289. * the @plugin is on changes.
  290. *
  291. * Since: 4.10
  292. **/
  293. plugin_signals[NROWS_CHANGED] =
  294. g_signal_new (g_intern_static_string ("nrows-changed"),
  295. G_TYPE_FROM_CLASS (klass),
  296. G_SIGNAL_RUN_LAST,
  297. G_STRUCT_OFFSET (XfcePanelPluginClass, nrows_changed),
  298. NULL, NULL,
  299. g_cclosure_marshal_VOID__UINT,
  300. G_TYPE_NONE, 1, G_TYPE_UINT);
  301. /**
  302. * XfcePanelPlugin::remote-event
  303. * @plugin : an #XfcePanelPlugin.
  304. * @name : name of the signal.
  305. * @value : value of the signal.
  306. *
  307. * This signal is emmitted by the user by running
  308. * xfce4-panel --plugin-event=plugin-name:name:type:value. It can be
  309. * used for remote communication, like for example to popup a menu.
  310. *
  311. * Returns: %TRUE to stop signal emission to other plugins, %FALSE
  312. * to send the signal also to other plugins with the same
  313. * name.
  314. **/
  315. plugin_signals[REMOTE_EVENT] =
  316. g_signal_new (g_intern_static_string ("remote-event"),
  317. G_TYPE_FROM_CLASS (klass),
  318. G_SIGNAL_RUN_LAST,
  319. G_STRUCT_OFFSET (XfcePanelPluginClass, remote_event),
  320. NULL, NULL,
  321. _libxfce4panel_marshal_BOOLEAN__STRING_BOXED,
  322. G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_VALUE);
  323. /**
  324. * XfcePanelPlugin::removed
  325. * @plugin : an #XfcePanelPlugin.
  326. *
  327. * This signal is emmitted when the plugin is permanently removed from
  328. * the panel configuration by the user. Developers can use this signal
  329. * to cleanup custom setting locations that for example store passwords.
  330. *
  331. * The free-data signal is emitted after this signal!
  332. *
  333. * Note that if you use the xfconf channel and base property provided
  334. * by xfce_panel_plugin_get_property_base() or the rc file location
  335. * returned by xfce_panel_plugin_save_location(), the panel will take
  336. * care of removing those settings.
  337. *
  338. * Since: 4.8
  339. **/
  340. plugin_signals[REMOVED] =
  341. g_signal_new (g_intern_static_string ("removed"),
  342. G_TYPE_FROM_CLASS (klass),
  343. G_SIGNAL_RUN_LAST,
  344. G_STRUCT_OFFSET (XfcePanelPluginClass, removed),
  345. NULL, NULL,
  346. g_cclosure_marshal_VOID__VOID,
  347. G_TYPE_NONE, 0);
  348. /**
  349. * XfcePanelPlugin::save
  350. * @plugin : an #XfcePanelPlugin.
  351. *
  352. * This signal is emitted when the plugin should save it's
  353. * configuration. The signal is always emmitted before the plugin
  354. * closes (before the "free-data" signal) and also once in 10
  355. * minutes or so.
  356. *
  357. * See also: xfce_panel_plugin_save_location().
  358. **/
  359. plugin_signals[SAVE] =
  360. g_signal_new (g_intern_static_string ("save"),
  361. G_TYPE_FROM_CLASS (klass),
  362. G_SIGNAL_RUN_LAST,
  363. G_STRUCT_OFFSET (XfcePanelPluginClass, save),
  364. NULL, NULL,
  365. g_cclosure_marshal_VOID__VOID,
  366. G_TYPE_NONE, 0);
  367. /**
  368. * XfcePanelPlugin::size-changed
  369. * @plugin : an #XfcePanelPlugin.
  370. * @size : the new size of the panel.
  371. *
  372. * This signal is emmitted whenever the size of the panel
  373. * the @plugin is on changes. Plugins writers can for example use
  374. * this signal to update their icon size.
  375. *
  376. * If the function returns %FALSE or is not used, the panel will force
  377. * a square size to the plugin. If you want non-square plugins and you
  378. * don't need this signal you can use something like this:
  379. *
  380. * g_signal_connect (plugin, "size-changed", G_CALLBACK (gtk_true), NULL);
  381. **/
  382. plugin_signals[SIZE_CHANGED] =
  383. g_signal_new (g_intern_static_string ("size-changed"),
  384. G_TYPE_FROM_CLASS (klass),
  385. G_SIGNAL_RUN_LAST,
  386. G_STRUCT_OFFSET (XfcePanelPluginClass, size_changed),
  387. g_signal_accumulator_true_handled, NULL,
  388. _libxfce4panel_marshal_BOOLEAN__INT,
  389. G_TYPE_BOOLEAN, 1, G_TYPE_INT);
  390. /**
  391. * XfcePanelPlugin::screen-position-changed
  392. * @plugin : an #XfcePanelPlugin.
  393. * @position : the new #XfceScreenPosition of the panel.
  394. *
  395. * This signal is emmitted whenever the screen position of the panel
  396. * the @plugin is on changes. Plugins writers can for example use
  397. * this signal to change the arrow direction of buttons.
  398. **/
  399. plugin_signals[SCREEN_POSITION_CHANGED] =
  400. g_signal_new (g_intern_static_string ("screen-position-changed"),
  401. G_TYPE_FROM_CLASS (klass),
  402. G_SIGNAL_RUN_LAST,
  403. G_STRUCT_OFFSET (XfcePanelPluginClass, screen_position_changed),
  404. NULL, NULL,
  405. g_cclosure_marshal_VOID__ENUM,
  406. G_TYPE_NONE, 1, XFCE_TYPE_SCREEN_POSITION);
  407. /**
  408. * XfcePanelPlugin:name:
  409. *
  410. * The internal, unstranslated, name of the #XfcePanelPlugin. Plugin
  411. * writer can use it to read the plugin name, but
  412. * xfce_panel_plugin_get_name() is recommended since that returns
  413. * a const string.
  414. **/
  415. g_object_class_install_property (gobject_class,
  416. PROP_NAME,
  417. g_param_spec_string ("name",
  418. "Name",
  419. "Plugin internal name",
  420. NULL,
  421. G_PARAM_READWRITE
  422. | G_PARAM_STATIC_STRINGS
  423. | G_PARAM_CONSTRUCT_ONLY));
  424. /**
  425. * XfcePanelPlugin:display-name:
  426. *
  427. * The translated display name of the #XfcePanelPlugin. This property is set
  428. * during plugin construction and can't be set twice. Plugin writer can use
  429. * it to read the plugin display name, but xfce_panel_plugin_get_display_name()
  430. * is recommended.
  431. **/
  432. g_object_class_install_property (gobject_class,
  433. PROP_DISPLAY_NAME,
  434. g_param_spec_string ("display-name",
  435. "Display Name",
  436. "Plugin display name",
  437. NULL,
  438. G_PARAM_READWRITE
  439. | G_PARAM_STATIC_STRINGS
  440. | G_PARAM_CONSTRUCT_ONLY));
  441. /**
  442. * XfcePanelPlugin:comment:
  443. *
  444. * The translated description of the #XfcePanelPlugin. This property is set
  445. * during plugin construction and can't be set twice. Plugin writer can use
  446. * it to read the plugin description, but xfce_panel_plugin_get_comment()
  447. * is recommended.
  448. *
  449. * Since: 4.8
  450. **/
  451. g_object_class_install_property (gobject_class,
  452. PROP_COMMENT,
  453. g_param_spec_string ("comment",
  454. "Comment",
  455. "Plugin comment",
  456. NULL,
  457. G_PARAM_READWRITE
  458. | G_PARAM_STATIC_STRINGS
  459. | G_PARAM_CONSTRUCT_ONLY));
  460. /**
  461. * XfcePanelPlugin:id:
  462. *
  463. * The unique id of the #XfcePanelPlugin. This property is set during plugin
  464. * construction and can't be set twice. Plugin writer can use it to read the
  465. * plugin display name, but xfce_panel_plugin_get_unique_id() is recommended.
  466. *
  467. * Since: 4.8
  468. **/
  469. g_object_class_install_property (gobject_class,
  470. PROP_UNIQUE_ID,
  471. g_param_spec_int ("unique-id",
  472. "Unique ID",
  473. "Unique plugin ID",
  474. -1, G_MAXINT, -1,
  475. G_PARAM_READWRITE
  476. | G_PARAM_STATIC_STRINGS
  477. | G_PARAM_CONSTRUCT_ONLY));
  478. /**
  479. * XfcePanelPlugin:arguments:
  480. *
  481. * The arguments the plugin was started with. If the plugin was not
  482. * started with any arguments this value is %NULL. Plugin writer can
  483. * use it to read the arguments array, but
  484. * xfce_panel_plugin_get_arguments() is recommended.
  485. **/
  486. g_object_class_install_property (gobject_class,
  487. PROP_ARGUMENTS,
  488. g_param_spec_boxed ("arguments",
  489. "Arguments",
  490. "Startup arguments for the plugin",
  491. G_TYPE_STRV,
  492. G_PARAM_READWRITE
  493. | G_PARAM_STATIC_STRINGS
  494. | G_PARAM_CONSTRUCT_ONLY));
  495. /**
  496. * XfcePanelPlugin:orientation:
  497. *
  498. * The #GtkOrientation of the #XfcePanelPlugin. Plugin writer can use it to read the
  499. * plugin orientation, but xfce_panel_plugin_get_orientation() is recommended.
  500. **/
  501. g_object_class_install_property (gobject_class,
  502. PROP_ORIENTATION,
  503. g_param_spec_enum ("orientation",
  504. "Orientation",
  505. "Orientation of the plugin's panel",
  506. GTK_TYPE_ORIENTATION,
  507. GTK_ORIENTATION_HORIZONTAL,
  508. G_PARAM_READABLE
  509. | G_PARAM_STATIC_STRINGS));
  510. /**
  511. * XfcePanelPlugin:size:
  512. *
  513. * The size in pixels of the #XfcePanelPlugin. Plugin writer can use it to read the
  514. * plugin size, but xfce_panel_plugin_get_size() is recommended.
  515. **/
  516. g_object_class_install_property (gobject_class,
  517. PROP_SIZE,
  518. g_param_spec_int ("size",
  519. "Size",
  520. "Size of the plugin's panel",
  521. 0, (128 * 6), 0,
  522. G_PARAM_READABLE
  523. | G_PARAM_STATIC_STRINGS));
  524. /**
  525. * XfcePanelPlugin:screen-position:
  526. *
  527. * The #XfceScreenPosition of the #XfcePanelPlugin. Plugin writer can use it
  528. * to read the plugin's screen position, but xfce_panel_plugin_get_screen_psotion()
  529. * is recommended.
  530. **/
  531. g_object_class_install_property (gobject_class,
  532. PROP_SCREEN_POSITION,
  533. g_param_spec_enum ("screen-position",
  534. "Screen Position",
  535. "Screen position of the plugin's panel",
  536. XFCE_TYPE_SCREEN_POSITION,
  537. XFCE_SCREEN_POSITION_NONE,
  538. G_PARAM_READABLE
  539. | G_PARAM_STATIC_STRINGS));
  540. /**
  541. * XfcePanelPlugin:small:
  542. *
  543. * Wether the #XfcePanelPlugin is small enough to fit a single row of a multi-row panel.
  544. * Plugin writes can use it to read or set this property, but xfce_panel_plugin_set_small()
  545. * is recommended.
  546. *
  547. * Since: 4.10
  548. **/
  549. g_object_class_install_property (gobject_class,
  550. PROP_SMALL,
  551. g_param_spec_boolean ("small",
  552. "Small",
  553. "Is this plugin small, e.g. a single button?",
  554. FALSE,
  555. G_PARAM_READWRITE
  556. | G_PARAM_STATIC_STRINGS));
  557. /**
  558. * XfcePanelPlugin:expand:
  559. *
  560. * Wether the #XfcePanelPlugin expands on the panel. Plugin writes can use it
  561. * to read or set this property, but xfce_panel_plugin_set_expand()
  562. * is recommended.
  563. **/
  564. g_object_class_install_property (gobject_class,
  565. PROP_EXPAND,
  566. g_param_spec_boolean ("expand",
  567. "Expand",
  568. "Whether this plugin is expanded",
  569. FALSE,
  570. G_PARAM_READWRITE
  571. | G_PARAM_STATIC_STRINGS));
  572. /**
  573. * XfcePanelPlugin:shrink:
  574. *
  575. * Wether the #XfcePanelPlugin can shrink when there is no space left on the panel.
  576. * Plugin writes can use it to read or set this property, but xfce_panel_plugin_set_shrink()
  577. * is recommended.
  578. *
  579. * Since: 4.10
  580. **/
  581. g_object_class_install_property (gobject_class,
  582. PROP_SHRINK,
  583. g_param_spec_boolean ("shrink",
  584. "Shrink",
  585. "Whether this plugin can shrink",
  586. FALSE,
  587. G_PARAM_READWRITE
  588. | G_PARAM_STATIC_STRINGS));
  589. /**
  590. * XfcePanelPlugin:mode:
  591. *
  592. * Display mode of the plugin.
  593. *
  594. * Since: 4.10
  595. **/
  596. g_object_class_install_property (gobject_class,
  597. PROP_MODE,
  598. g_param_spec_enum ("mode",
  599. "Mode",
  600. "Disply mode of the plugin",
  601. XFCE_TYPE_PANEL_PLUGIN_MODE,
  602. XFCE_PANEL_PLUGIN_MODE_HORIZONTAL,
  603. G_PARAM_READABLE
  604. | G_PARAM_STATIC_STRINGS));
  605. /**
  606. * XfcePanelPlugin:nrows:
  607. *
  608. * Number of rows the plugin is embedded on.
  609. *
  610. * Since: 4.10
  611. **/
  612. g_object_class_install_property (gobject_class,
  613. PROP_NROWS,
  614. g_param_spec_uint ("nrows",
  615. "Nrows",
  616. "Number of rows of the panel",
  617. 1, 6, 1,
  618. G_PARAM_READABLE
  619. | G_PARAM_STATIC_STRINGS));
  620. item_properties = g_quark_from_static_string ("item-properties");
  621. item_about = g_quark_from_static_string ("item-about");
  622. }
  623. static void
  624. xfce_panel_plugin_init (XfcePanelPlugin *plugin)
  625. {
  626. plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin, XFCE_TYPE_PANEL_PLUGIN, XfcePanelPluginPrivate);
  627. plugin->priv->name = NULL;
  628. plugin->priv->display_name = NULL;
  629. plugin->priv->comment = NULL;
  630. plugin->priv->unique_id = -1;
  631. plugin->priv->property_base = NULL;
  632. plugin->priv->arguments = NULL;
  633. plugin->priv->size = 0;
  634. plugin->priv->small = FALSE;
  635. plugin->priv->expand = FALSE;
  636. plugin->priv->shrink = FALSE;
  637. plugin->priv->mode = XFCE_PANEL_PLUGIN_MODE_HORIZONTAL;
  638. plugin->priv->screen_position = XFCE_SCREEN_POSITION_NONE;
  639. plugin->priv->menu = NULL;
  640. plugin->priv->menu_blocked = 0;
  641. plugin->priv->panel_lock = 0;
  642. plugin->priv->flags = 0;
  643. plugin->priv->locked = TRUE;
  644. plugin->priv->menu_items = NULL;
  645. plugin->priv->nrows = 1;
  646. /* bind the text domain of the panel so our strings
  647. * are properly translated in the old 4.6 panel plugins */
  648. bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
  649. #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  650. bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  651. #endif
  652. /* hide the event box window to make the plugin transparent */
  653. gtk_event_box_set_visible_window (GTK_EVENT_BOX (plugin), FALSE);
  654. }
  655. static void
  656. xfce_panel_plugin_provider_init (XfcePanelPluginProviderInterface *iface)
  657. {
  658. iface->get_name = (ProviderToPluginChar) xfce_panel_plugin_get_name;
  659. iface->get_unique_id = (ProviderToPluginInt) xfce_panel_plugin_get_unique_id;
  660. iface->set_size = xfce_panel_plugin_set_size;
  661. iface->set_mode = xfce_panel_plugin_set_mode;
  662. iface->set_nrows = xfce_panel_plugin_set_nrows;
  663. iface->set_screen_position = xfce_panel_plugin_set_screen_position;
  664. iface->save = xfce_panel_plugin_save;
  665. iface->get_show_configure = xfce_panel_plugin_get_show_configure;
  666. iface->show_configure = xfce_panel_plugin_show_configure;
  667. iface->get_show_about = xfce_panel_plugin_get_show_about;
  668. iface->show_about = xfce_panel_plugin_show_about;
  669. iface->removed = xfce_panel_plugin_removed;
  670. iface->remote_event = xfce_panel_plugin_remote_event;
  671. iface->set_locked = xfce_panel_plugin_set_locked;
  672. iface->ask_remove = xfce_panel_plugin_ask_remove;
  673. }
  674. static GObject *
  675. xfce_panel_plugin_constructor (GType type,
  676. guint n_props,
  677. GObjectConstructParam *props)
  678. {
  679. GObject *plugin;
  680. plugin = G_OBJECT_CLASS (xfce_panel_plugin_parent_class)->constructor (type, n_props, props);
  681. /* all the properties are set and can be used in public */
  682. PANEL_SET_FLAG (XFCE_PANEL_PLUGIN (plugin)->priv->flags, PLUGIN_FLAG_CONSTRUCTED);
  683. return plugin;
  684. }
  685. static void
  686. xfce_panel_plugin_get_property (GObject *object,
  687. guint prop_id,
  688. GValue *value,
  689. GParamSpec *pspec)
  690. {
  691. XfcePanelPluginPrivate *private = XFCE_PANEL_PLUGIN (object)->priv;
  692. switch (prop_id)
  693. {
  694. case PROP_NAME:
  695. g_value_set_static_string (value, private->name);
  696. break;
  697. case PROP_DISPLAY_NAME:
  698. g_value_set_static_string (value, private->display_name);
  699. break;
  700. case PROP_COMMENT:
  701. g_value_set_static_string (value, private->comment);
  702. break;
  703. case PROP_UNIQUE_ID:
  704. g_value_set_int (value, private->unique_id);
  705. break;
  706. case PROP_ARGUMENTS:
  707. g_value_set_boxed (value, private->arguments);
  708. break;
  709. case PROP_ORIENTATION:
  710. g_value_set_enum (value, xfce_panel_plugin_get_orientation (XFCE_PANEL_PLUGIN (object)));
  711. break;
  712. case PROP_SIZE:
  713. g_value_set_int (value, private->size * private->nrows);
  714. break;
  715. case PROP_NROWS:
  716. g_value_set_uint (value, private->nrows);
  717. break;
  718. case PROP_MODE:
  719. g_value_set_enum (value, private->mode);
  720. break;
  721. case PROP_SMALL:
  722. g_value_set_boolean (value, private->small);
  723. break;
  724. case PROP_SCREEN_POSITION:
  725. g_value_set_enum (value, private->screen_position);
  726. break;
  727. case PROP_EXPAND:
  728. g_value_set_boolean (value, private->expand);
  729. break;
  730. case PROP_SHRINK:
  731. g_value_set_boolean (value, private->shrink);
  732. break;
  733. default:
  734. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  735. break;
  736. }
  737. }
  738. static void
  739. xfce_panel_plugin_set_property (GObject *object,
  740. guint prop_id,
  741. const GValue *value,
  742. GParamSpec *pspec)
  743. {
  744. XfcePanelPluginPrivate *private = XFCE_PANEL_PLUGIN (object)->priv;
  745. gchar *name;
  746. switch (prop_id)
  747. {
  748. case PROP_NAME:
  749. case PROP_UNIQUE_ID:
  750. if (prop_id == PROP_NAME)
  751. private->name = g_value_dup_string (value);
  752. else
  753. private->unique_id = g_value_get_int (value);
  754. if (private->unique_id != -1 && private->name != NULL)
  755. {
  756. /* give the widget a unique name for theming */
  757. name = g_strdup_printf ("%s-%d", private->name, private->unique_id);
  758. gtk_widget_set_name (GTK_WIDGET (object), name);
  759. g_free (name);
  760. }
  761. break;
  762. case PROP_DISPLAY_NAME:
  763. private->display_name = g_value_dup_string (value);
  764. break;
  765. case PROP_COMMENT:
  766. private->comment = g_value_dup_string (value);
  767. break;
  768. case PROP_ARGUMENTS:
  769. private->arguments = g_value_dup_boxed (value);
  770. break;
  771. case PROP_SMALL:
  772. xfce_panel_plugin_set_small (XFCE_PANEL_PLUGIN (object),
  773. g_value_get_boolean (value));
  774. break;
  775. case PROP_EXPAND:
  776. xfce_panel_plugin_set_expand (XFCE_PANEL_PLUGIN (object),
  777. g_value_get_boolean (value));
  778. break;
  779. case PROP_SHRINK:
  780. xfce_panel_plugin_set_shrink (XFCE_PANEL_PLUGIN (object),
  781. g_value_get_boolean (value));
  782. break;
  783. default:
  784. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  785. break;
  786. }
  787. }
  788. static void
  789. xfce_panel_plugin_dispose (GObject *object)
  790. {
  791. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (object);
  792. if (!PANEL_HAS_FLAG (plugin->priv->flags, PLUGIN_FLAG_DISPOSED))
  793. {
  794. /* allow the plugin to cleanup */
  795. g_signal_emit (G_OBJECT (object), plugin_signals[FREE_DATA], 0);
  796. /* plugin disposed, don't try this again */
  797. PANEL_SET_FLAG (plugin->priv->flags, PLUGIN_FLAG_DISPOSED);
  798. }
  799. (*G_OBJECT_CLASS (xfce_panel_plugin_parent_class)->dispose) (object);
  800. }
  801. static void
  802. xfce_panel_plugin_finalize (GObject *object)
  803. {
  804. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (object);
  805. GSList *li;
  806. /* destroy the menu */
  807. if (plugin->priv->menu != NULL)
  808. {
  809. gtk_widget_destroy (GTK_WIDGET (plugin->priv->menu));
  810. panel_assert (plugin->priv->menu_items == NULL);
  811. }
  812. else
  813. {
  814. /* release custom menu items */
  815. for (li = plugin->priv->menu_items; li != NULL; li = li->next)
  816. {
  817. g_signal_handlers_disconnect_by_func (G_OBJECT (li->data),
  818. G_CALLBACK (xfce_panel_plugin_menu_item_destroy), plugin);
  819. g_object_unref (G_OBJECT (li->data));
  820. }
  821. g_slist_free (plugin->priv->menu_items);
  822. }
  823. g_free (plugin->priv->name);
  824. g_free (plugin->priv->display_name);
  825. g_free (plugin->priv->comment);
  826. g_free (plugin->priv->property_base);
  827. g_strfreev (plugin->priv->arguments);
  828. (*G_OBJECT_CLASS (xfce_panel_plugin_parent_class)->finalize) (object);
  829. }
  830. static void
  831. xfce_panel_plugin_realize (GtkWidget *widget)
  832. {
  833. XfcePanelPluginClass *klass;
  834. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (widget);
  835. /* let gtk realize the plugin */
  836. (*GTK_WIDGET_CLASS (xfce_panel_plugin_parent_class)->realize) (widget);
  837. /* launch the construct function for object oriented plugins, but
  838. * do this only once */
  839. if (!PANEL_HAS_FLAG (plugin->priv->flags, PLUGIN_FLAG_REALIZED))
  840. {
  841. PANEL_SET_FLAG (plugin->priv->flags, PLUGIN_FLAG_REALIZED);
  842. /* whether this is an object plugin */
  843. klass = XFCE_PANEL_PLUGIN_GET_CLASS (widget);
  844. if (klass->construct != NULL)
  845. (*klass->construct) (XFCE_PANEL_PLUGIN (widget));
  846. }
  847. }
  848. static gboolean
  849. xfce_panel_plugin_button_press_event (GtkWidget *widget,
  850. GdkEventButton *event)
  851. {
  852. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (widget);
  853. guint modifiers;
  854. GtkMenu *menu;
  855. GtkWidget *item;
  856. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (widget), FALSE);
  857. /* get the default accelerator modifier mask */
  858. modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
  859. if (event->button == 3
  860. || (event->button == 1 && modifiers == GDK_CONTROL_MASK))
  861. {
  862. /* get the panel menu */
  863. menu = xfce_panel_plugin_menu_get (plugin);
  864. /* if the menu is block, some items are insensitive */
  865. item = g_object_get_qdata (G_OBJECT (menu), item_properties);
  866. if (item != NULL)
  867. gtk_widget_set_sensitive (item, plugin->priv->menu_blocked == 0);
  868. /* popup the menu */
  869. gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time);
  870. return TRUE;
  871. }
  872. return FALSE;
  873. }
  874. static void
  875. xfce_panel_plugin_menu_move (XfcePanelPlugin *plugin)
  876. {
  877. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  878. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  879. /* move the plugin */
  880. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  881. PROVIDER_SIGNAL_MOVE_PLUGIN);
  882. }
  883. static void
  884. xfce_panel_plugin_menu_remove (XfcePanelPlugin *plugin)
  885. {
  886. GtkWidget *dialog;
  887. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  888. /* create question dialog (same code is also in panel-preferences-dialog.c) */
  889. dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
  890. GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
  891. /* I18N: %s is the name of the plugin */
  892. _("Are you sure that you want to remove \"%s\"?"),
  893. xfce_panel_plugin_get_display_name (plugin));
  894. gtk_window_set_screen (GTK_WINDOW (dialog),
  895. gtk_widget_get_screen (GTK_WIDGET (plugin)));
  896. gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
  897. _("If you remove the item from the panel, it is permanently lost."));
  898. gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
  899. GTK_RESPONSE_NO, GTK_STOCK_REMOVE, GTK_RESPONSE_YES, NULL);
  900. gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
  901. if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
  902. {
  903. gtk_widget_hide (dialog);
  904. /* ask the panel or wrapper to remove the plugin */
  905. xfce_panel_plugin_remove (plugin);
  906. }
  907. gtk_widget_destroy (dialog);
  908. }
  909. static void
  910. xfce_panel_plugin_menu_add_items (XfcePanelPlugin *plugin)
  911. {
  912. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  913. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  914. panel_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  915. /* open items dialog */
  916. if (!xfce_panel_plugin_get_locked (plugin))
  917. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  918. PROVIDER_SIGNAL_ADD_NEW_ITEMS);
  919. }
  920. static void
  921. xfce_panel_plugin_menu_panel_preferences (XfcePanelPlugin *plugin)
  922. {
  923. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  924. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  925. panel_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  926. /* open preferences dialog */
  927. if (!xfce_panel_plugin_get_locked (plugin))
  928. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  929. PROVIDER_SIGNAL_PANEL_PREFERENCES);
  930. }
  931. static void
  932. xfce_panel_plugin_menu_panel_logout (XfcePanelPlugin *plugin)
  933. {
  934. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  935. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  936. panel_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  937. /* logout the session */
  938. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  939. PROVIDER_SIGNAL_PANEL_LOGOUT);
  940. }
  941. static void
  942. xfce_panel_plugin_menu_panel_about (XfcePanelPlugin *plugin)
  943. {
  944. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  945. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  946. panel_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  947. /* open the about dialog of the panel */
  948. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  949. PROVIDER_SIGNAL_PANEL_ABOUT);
  950. }
  951. static void
  952. xfce_panel_plugin_menu_panel_help (XfcePanelPlugin *plugin)
  953. {
  954. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  955. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (plugin));
  956. panel_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  957. /* open the manual of the panel */
  958. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  959. PROVIDER_SIGNAL_PANEL_HELP);
  960. }
  961. static void
  962. xfce_panel_plugin_menu_destroy (XfcePanelPlugin *plugin)
  963. {
  964. GSList *li;
  965. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  966. if (plugin->priv->menu != NULL)
  967. {
  968. /* remove custom items before they get destroyed */
  969. for (li = plugin->priv->menu_items; li != NULL; li = li->next)
  970. gtk_container_remove (GTK_CONTAINER (plugin->priv->menu), GTK_WIDGET (li->data));
  971. gtk_widget_destroy (GTK_WIDGET (plugin->priv->menu));
  972. plugin->priv->menu = NULL;
  973. }
  974. }
  975. static GtkMenu *
  976. xfce_panel_plugin_menu_get (XfcePanelPlugin *plugin)
  977. {
  978. GtkWidget *menu, *submenu;
  979. GtkWidget *item;
  980. GtkWidget *image;
  981. gboolean locked;
  982. GSList *li;
  983. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  984. if (G_UNLIKELY (plugin->priv->menu == NULL))
  985. {
  986. locked = xfce_panel_plugin_get_locked (plugin);
  987. menu = gtk_menu_new ();
  988. gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (plugin), NULL);
  989. /* item with plugin name */
  990. item = gtk_menu_item_new_with_label (xfce_panel_plugin_get_display_name (plugin));
  991. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  992. gtk_widget_set_sensitive (item, FALSE);
  993. gtk_widget_show (item);
  994. /* separator */
  995. item = gtk_separator_menu_item_new ();
  996. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  997. gtk_widget_show (item);
  998. if (!locked)
  999. {
  1000. /* properties item */
  1001. item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PROPERTIES, NULL);
  1002. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1003. G_CALLBACK (xfce_panel_plugin_show_configure), plugin);
  1004. g_object_set_qdata (G_OBJECT (menu), item_properties, item);
  1005. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1006. if (PANEL_HAS_FLAG (plugin->priv->flags, PLUGIN_FLAG_SHOW_CONFIGURE))
  1007. gtk_widget_show (item);
  1008. /* about item */
  1009. item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
  1010. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1011. G_CALLBACK (xfce_panel_plugin_show_about), plugin);
  1012. g_object_set_qdata (G_OBJECT (menu), item_about, item);
  1013. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1014. if (PANEL_HAS_FLAG (plugin->priv->flags, PLUGIN_FLAG_SHOW_ABOUT))
  1015. gtk_widget_show (item);
  1016. /* move item */
  1017. item = gtk_image_menu_item_new_with_mnemonic (_("_Move"));
  1018. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1019. G_CALLBACK (xfce_panel_plugin_menu_move), plugin);
  1020. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1021. gtk_widget_show (item);
  1022. image = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU);
  1023. gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
  1024. gtk_widget_show (image);
  1025. /* add custom menu items */
  1026. for (li = plugin->priv->menu_items; li != NULL; li = li->next)
  1027. gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (li->data));
  1028. /* separator */
  1029. item = gtk_separator_menu_item_new ();
  1030. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1031. gtk_widget_show (item);
  1032. /* remove */
  1033. item = gtk_image_menu_item_new_from_stock (GTK_STOCK_REMOVE, NULL);
  1034. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1035. G_CALLBACK (xfce_panel_plugin_menu_remove), plugin);
  1036. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1037. gtk_widget_show (item);
  1038. /* separator */
  1039. item = gtk_separator_menu_item_new ();
  1040. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1041. gtk_widget_show (item);
  1042. }
  1043. /* create a panel submenu item */
  1044. submenu = gtk_menu_new ();
  1045. item = gtk_menu_item_new_with_mnemonic (_("Pane_l"));
  1046. gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
  1047. gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
  1048. gtk_widget_show (item);
  1049. if (!locked)
  1050. {
  1051. /* add new items */
  1052. item = gtk_image_menu_item_new_with_mnemonic (_("Add _New Items..."));
  1053. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1054. G_CALLBACK (xfce_panel_plugin_menu_add_items), plugin);
  1055. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1056. gtk_widget_show (item);
  1057. image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
  1058. gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
  1059. gtk_widget_show (image);
  1060. /* customize panel */
  1061. item = gtk_image_menu_item_new_with_mnemonic (_("Panel Pr_eferences..."));
  1062. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1063. G_CALLBACK (xfce_panel_plugin_menu_panel_preferences), plugin);
  1064. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1065. gtk_widget_show (item);
  1066. image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
  1067. gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
  1068. gtk_widget_show (image);
  1069. /* separator */
  1070. item = gtk_separator_menu_item_new ();
  1071. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1072. gtk_widget_show (item);
  1073. }
  1074. /* logout item */
  1075. item = gtk_image_menu_item_new_with_mnemonic (_("Log _Out"));
  1076. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1077. G_CALLBACK (xfce_panel_plugin_menu_panel_logout), plugin);
  1078. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1079. gtk_widget_show (item);
  1080. image = gtk_image_new_from_icon_name ("system-log-out", GTK_ICON_SIZE_MENU);
  1081. gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
  1082. gtk_widget_show (image);
  1083. /* separator */
  1084. item = gtk_separator_menu_item_new ();
  1085. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1086. gtk_widget_show (item);
  1087. /* help item */
  1088. item = gtk_image_menu_item_new_from_stock (GTK_STOCK_HELP, NULL);
  1089. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1090. G_CALLBACK (xfce_panel_plugin_menu_panel_help), plugin);
  1091. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1092. gtk_widget_show (item);
  1093. /* about item */
  1094. item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
  1095. g_signal_connect_swapped (G_OBJECT (item), "activate",
  1096. G_CALLBACK (xfce_panel_plugin_menu_panel_about), plugin);
  1097. gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
  1098. gtk_widget_show (item);
  1099. /* set panel menu */
  1100. plugin->priv->menu = GTK_MENU (menu);
  1101. }
  1102. /* block autohide when this menu is shown */
  1103. xfce_panel_plugin_register_menu (plugin, GTK_MENU (plugin->priv->menu));
  1104. return plugin->priv->menu;
  1105. }
  1106. static inline gchar *
  1107. xfce_panel_plugin_relative_filename (XfcePanelPlugin *plugin)
  1108. {
  1109. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1110. panel_return_val_if_fail (xfce_panel_plugin_get_name (plugin) != NULL, NULL);
  1111. panel_return_val_if_fail (xfce_panel_plugin_get_unique_id (plugin) != -1, NULL);
  1112. /* return the relative configuration filename */
  1113. return g_strdup_printf (PANEL_PLUGIN_RC_RELATIVE_PATH,
  1114. plugin->priv->name, plugin->priv->unique_id);
  1115. }
  1116. static void
  1117. xfce_panel_plugin_unregister_menu (GtkMenu *menu,
  1118. XfcePanelPlugin *plugin)
  1119. {
  1120. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1121. panel_return_if_fail (plugin->priv->panel_lock > 0);
  1122. panel_return_if_fail (GTK_IS_MENU (menu));
  1123. /* disconnect this signal */
  1124. g_signal_handlers_disconnect_by_func (G_OBJECT (menu),
  1125. G_CALLBACK (xfce_panel_plugin_unregister_menu), plugin);
  1126. if (G_LIKELY (plugin->priv->panel_lock > 0))
  1127. {
  1128. /* decrease the counter */
  1129. plugin->priv->panel_lock--;
  1130. /* emit signal to unlock the panel */
  1131. if (plugin->priv->panel_lock == 0)
  1132. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1133. PROVIDER_SIGNAL_UNLOCK_PANEL);
  1134. }
  1135. }
  1136. static void
  1137. xfce_panel_plugin_set_size (XfcePanelPluginProvider *provider,
  1138. gint size)
  1139. {
  1140. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1141. gboolean handled = FALSE;
  1142. gint real_size;
  1143. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1144. /* check if update is required, -1 for forced property emit
  1145. * by xfce_panel_plugin_set_nrows */
  1146. if (G_LIKELY (plugin->priv->size != size))
  1147. {
  1148. if (size != -1)
  1149. plugin->priv->size = size;
  1150. real_size = plugin->priv->size * plugin->priv->nrows;
  1151. g_signal_emit (G_OBJECT (plugin),
  1152. plugin_signals[SIZE_CHANGED], 0, real_size, &handled);
  1153. /* handle the size when not done by the plugin */
  1154. if (!handled)
  1155. gtk_widget_set_size_request (GTK_WIDGET (plugin), real_size, real_size);
  1156. g_object_notify (G_OBJECT (plugin), "size");
  1157. }
  1158. }
  1159. static void
  1160. xfce_panel_plugin_set_mode (XfcePanelPluginProvider *provider,
  1161. XfcePanelPluginMode mode)
  1162. {
  1163. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1164. GtkOrientation old_orientation;
  1165. GtkOrientation new_orientation;
  1166. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1167. /* check if update is required */
  1168. if (G_LIKELY (plugin->priv->mode != mode))
  1169. {
  1170. old_orientation = xfce_panel_plugin_get_orientation (plugin);
  1171. plugin->priv->mode = mode;
  1172. g_signal_emit (G_OBJECT (plugin),
  1173. plugin_signals[MODE_CHANGED], 0, mode);
  1174. g_object_notify (G_OBJECT (plugin), "mode");
  1175. /* emit old orientation property for compatibility */
  1176. new_orientation = xfce_panel_plugin_get_orientation (plugin);
  1177. if (old_orientation != new_orientation)
  1178. {
  1179. g_signal_emit (G_OBJECT (plugin),
  1180. plugin_signals[ORIENTATION_CHANGED], 0, new_orientation);
  1181. g_object_notify (G_OBJECT (plugin), "orientation");
  1182. }
  1183. }
  1184. }
  1185. static void
  1186. xfce_panel_plugin_set_nrows (XfcePanelPluginProvider *provider,
  1187. guint nrows)
  1188. {
  1189. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1190. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1191. nrows = MAX (nrows, 1);
  1192. /* check if update is required */
  1193. if (G_LIKELY (plugin->priv->nrows != nrows))
  1194. {
  1195. plugin->priv->nrows = nrows;
  1196. g_signal_emit (G_OBJECT (plugin),
  1197. plugin_signals[NROWS_CHANGED], 0, nrows);
  1198. g_object_notify (G_OBJECT (plugin), "nrows");
  1199. /* also the size changed */
  1200. xfce_panel_plugin_set_size (provider, -1);
  1201. }
  1202. }
  1203. static void
  1204. xfce_panel_plugin_set_screen_position (XfcePanelPluginProvider *provider,
  1205. XfceScreenPosition screen_position)
  1206. {
  1207. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1208. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1209. /* check if update is required */
  1210. if (G_LIKELY (plugin->priv->screen_position != screen_position
  1211. || xfce_screen_position_is_floating (screen_position)))
  1212. {
  1213. plugin->priv->screen_position = screen_position;
  1214. g_signal_emit (G_OBJECT (plugin),
  1215. plugin_signals[SCREEN_POSITION_CHANGED], 0,
  1216. screen_position);
  1217. g_object_notify (G_OBJECT (plugin), "screen-position");
  1218. }
  1219. }
  1220. static void
  1221. xfce_panel_plugin_save (XfcePanelPluginProvider *provider)
  1222. {
  1223. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1224. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1225. /* only send the save signal if the plugin is not locked */
  1226. if (XFCE_PANEL_PLUGIN (provider)->priv->menu_blocked == 0
  1227. && !xfce_panel_plugin_get_locked (plugin))
  1228. g_signal_emit (G_OBJECT (provider), plugin_signals[SAVE], 0);
  1229. }
  1230. static gboolean
  1231. xfce_panel_plugin_get_show_configure (XfcePanelPluginProvider *provider)
  1232. {
  1233. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (provider), FALSE);
  1234. /* TODO, not sure, but maybe return FALSE when menu_blocked > 0 */
  1235. return PANEL_HAS_FLAG (XFCE_PANEL_PLUGIN (provider)->priv->flags,
  1236. PLUGIN_FLAG_SHOW_CONFIGURE);
  1237. }
  1238. static void
  1239. xfce_panel_plugin_show_configure (XfcePanelPluginProvider *provider)
  1240. {
  1241. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1242. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1243. if (plugin->priv->menu_blocked == 0
  1244. && !xfce_panel_plugin_get_locked (plugin))
  1245. g_signal_emit (G_OBJECT (plugin), plugin_signals[CONFIGURE_PLUGIN], 0);
  1246. }
  1247. static gboolean
  1248. xfce_panel_plugin_get_show_about (XfcePanelPluginProvider *provider)
  1249. {
  1250. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (provider), FALSE);
  1251. /* TODO, not sure, but maybe return FALSE when menu_blocked > 0 */
  1252. return PANEL_HAS_FLAG (XFCE_PANEL_PLUGIN (provider)->priv->flags,
  1253. PLUGIN_FLAG_SHOW_ABOUT);
  1254. }
  1255. static void
  1256. xfce_panel_plugin_show_about (XfcePanelPluginProvider *provider)
  1257. {
  1258. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1259. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1260. if (G_LIKELY (plugin->priv->menu_blocked == 0))
  1261. g_signal_emit (G_OBJECT (provider), plugin_signals[ABOUT], 0);
  1262. }
  1263. static void
  1264. xfce_panel_plugin_removed (XfcePanelPluginProvider *provider)
  1265. {
  1266. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1267. if (!xfce_panel_plugin_get_locked (XFCE_PANEL_PLUGIN (provider)))
  1268. g_signal_emit (G_OBJECT (provider), plugin_signals[REMOVED], 0);
  1269. }
  1270. static gboolean
  1271. xfce_panel_plugin_remote_event (XfcePanelPluginProvider *provider,
  1272. const gchar *name,
  1273. const GValue *value,
  1274. guint *handle)
  1275. {
  1276. gboolean stop_emission;
  1277. panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (provider), TRUE);
  1278. panel_return_val_if_fail (name != NULL, TRUE);
  1279. panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), TRUE);
  1280. g_signal_emit (G_OBJECT (provider), plugin_signals[REMOTE_EVENT], 0,
  1281. name, value, &stop_emission);
  1282. return stop_emission;
  1283. }
  1284. static void
  1285. xfce_panel_plugin_set_locked (XfcePanelPluginProvider *provider,
  1286. gboolean locked)
  1287. {
  1288. XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (provider);
  1289. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1290. if (G_LIKELY (plugin->priv->locked != locked))
  1291. {
  1292. plugin->priv->locked = locked;
  1293. /* destroy the menu if it exists */
  1294. xfce_panel_plugin_menu_destroy (plugin);
  1295. }
  1296. }
  1297. static void
  1298. xfce_panel_plugin_ask_remove (XfcePanelPluginProvider *provider)
  1299. {
  1300. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (provider));
  1301. xfce_panel_plugin_menu_remove (XFCE_PANEL_PLUGIN (provider));
  1302. }
  1303. static void
  1304. xfce_panel_plugin_take_window_notify (gpointer data,
  1305. GObject *where_the_object_was)
  1306. {
  1307. panel_return_if_fail (GTK_IS_WINDOW (data) || XFCE_IS_PANEL_PLUGIN (data));
  1308. /* release the opposite weak ref */
  1309. g_object_weak_unref (G_OBJECT (data),
  1310. xfce_panel_plugin_take_window_notify, where_the_object_was);
  1311. /* destroy the dialog if the plugin was finalized */
  1312. if (GTK_IS_WINDOW (data))
  1313. gtk_widget_destroy (GTK_WIDGET (data));
  1314. }
  1315. static void
  1316. xfce_panel_plugin_menu_item_destroy (GtkWidget *item,
  1317. XfcePanelPlugin *plugin)
  1318. {
  1319. panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1320. panel_return_if_fail (GTK_IS_MENU_ITEM (item));
  1321. panel_return_if_fail (g_slist_find (plugin->priv->menu_items, item) != NULL);
  1322. /* remote the item from the list and release it */
  1323. plugin->priv->menu_items = g_slist_remove (plugin->priv->menu_items, item);
  1324. g_object_unref (G_OBJECT (item));
  1325. }
  1326. /**
  1327. * xfce_panel_plugin_get_name:
  1328. * @plugin : an #XfcePanelPlugin.
  1329. *
  1330. * The internal name of the panel plugin.
  1331. *
  1332. * Returns: the name of the panel plugin.
  1333. **/
  1334. const gchar *
  1335. xfce_panel_plugin_get_name (XfcePanelPlugin *plugin)
  1336. {
  1337. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1338. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  1339. return plugin->priv->name;
  1340. }
  1341. /**
  1342. * xfce_panel_plugin_get_display_name:
  1343. * @plugin : an #XfcePanelPlugin.
  1344. *
  1345. * This returns the translated name of the plugin set in the .desktop
  1346. * file of the plugin.
  1347. *
  1348. * Returns: the (translated) display name of the plugin.
  1349. **/
  1350. const gchar *
  1351. xfce_panel_plugin_get_display_name (XfcePanelPlugin *plugin)
  1352. {
  1353. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1354. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  1355. if (G_LIKELY (plugin->priv->display_name))
  1356. return plugin->priv->display_name;
  1357. return plugin->priv->name;
  1358. }
  1359. /**
  1360. * xfce_panel_plugin_get_comment:
  1361. * @plugin : an #XfcePanelPlugin.
  1362. *
  1363. * This returns the translated comment of the plugin set in
  1364. * the .desktop file of the plugin.
  1365. *
  1366. * Returns: the (translated) comment of the plugin.
  1367. *
  1368. * Since: 4.8
  1369. **/
  1370. const gchar *
  1371. xfce_panel_plugin_get_comment (XfcePanelPlugin *plugin)
  1372. {
  1373. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1374. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  1375. return plugin->priv->comment;
  1376. }
  1377. /**
  1378. * xfce_panel_plugin_get_unique_id:
  1379. * @plugin : an #XfcePanelPlugin.
  1380. *
  1381. * The internal unique id of the plugin. Each plugin in the panel has
  1382. * a unique number that is for example used for the config file name
  1383. * or property base in the xfconf channel.
  1384. *
  1385. * Returns: the unique id of the plugin.
  1386. *
  1387. * Since 4.8
  1388. **/
  1389. gint
  1390. xfce_panel_plugin_get_unique_id (XfcePanelPlugin *plugin)
  1391. {
  1392. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), -1);
  1393. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), -1);
  1394. return plugin->priv->unique_id;
  1395. }
  1396. /**
  1397. * xfce_panel_plugin_get_property_base:
  1398. * @plugin : an #XfcePanelPlugin.
  1399. *
  1400. * The property base for this plugin in the xfce4-panel XfconfChannel,
  1401. * this name is something like /plugins/plugin-1.
  1402. *
  1403. * Returns: the property base for the xfconf channel userd by a plugin.
  1404. *
  1405. * See also: xfconf_channel_new_with_property_base.
  1406. * XFCE_PANEL_PLUGIN_CHANNEL_NAME and
  1407. * xfce_panel_get_channel_name
  1408. **/
  1409. const gchar *
  1410. xfce_panel_plugin_get_property_base (XfcePanelPlugin *plugin)
  1411. {
  1412. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1413. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  1414. /* create the propert if needed */
  1415. if (plugin->priv->property_base == NULL)
  1416. plugin->priv->property_base = g_strdup_printf (PANEL_PLUGIN_PROPERTY_BASE,
  1417. plugin->priv->unique_id);
  1418. return plugin->priv->property_base;
  1419. }
  1420. /**
  1421. * xfce_panel_plugin_get_arguments:
  1422. * @plugin : an #XfcePanelPlugin.
  1423. *
  1424. * Argument vector passed to the plugin when it was added. Most of the
  1425. * time the return value will be %NULL, but if could for example contain
  1426. * a list of filenames when the user added the plugin with
  1427. *
  1428. * xfce4-panel --add=launcher *.desktop
  1429. *
  1430. * see the code of the launcher plugin how to use this.
  1431. *
  1432. * Returns: the argument vector. The vector is owned by the plugin and
  1433. * should not be freed.
  1434. *
  1435. * Since: 4.8
  1436. **/
  1437. const gchar * const *
  1438. xfce_panel_plugin_get_arguments (XfcePanelPlugin *plugin)
  1439. {
  1440. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  1441. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  1442. return (const gchar * const *) plugin->priv->arguments;
  1443. }
  1444. /**
  1445. * xfce_panel_plugin_get_size:
  1446. * @plugin : an #XfcePanelPlugin.
  1447. *
  1448. * The size of the panel in which the plugin is embedded.
  1449. *
  1450. * Returns: the current size of the panel.
  1451. **/
  1452. gint
  1453. xfce_panel_plugin_get_size (XfcePanelPlugin *plugin)
  1454. {
  1455. gint real_size;
  1456. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), -1);
  1457. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), -1);
  1458. /* always return a 'positive' size that makes sence */
  1459. real_size = plugin->priv->size * plugin->priv->nrows;
  1460. return MAX (16, real_size);
  1461. }
  1462. /**
  1463. * xfce_panel_plugin_get_expand:
  1464. * @plugin : an #XfcePanelPlugin.
  1465. *
  1466. * Whether the plugin is expanded or not. This set by the plugin using
  1467. * xfce_panel_plugin_set_expand().
  1468. *
  1469. * Returns: %TRUE when the plugin should expand,
  1470. * %FALSE otherwise.
  1471. **/
  1472. gboolean
  1473. xfce_panel_plugin_get_expand (XfcePanelPlugin *plugin)
  1474. {
  1475. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), FALSE);
  1476. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), FALSE);
  1477. return plugin->priv->expand;
  1478. }
  1479. /**
  1480. * xfce_panel_plugin_set_expand:
  1481. * @plugin : an #XfcePanelPlugin.
  1482. * @expand : whether to expand the plugin.
  1483. *
  1484. * Wether the plugin should expand of not
  1485. **/
  1486. void
  1487. xfce_panel_plugin_set_expand (XfcePanelPlugin *plugin,
  1488. gboolean expand)
  1489. {
  1490. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1491. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1492. /* normalize the value */
  1493. expand = !!expand;
  1494. /* check if update is required */
  1495. if (G_LIKELY (plugin->priv->expand != expand))
  1496. {
  1497. plugin->priv->expand = expand;
  1498. /* emit signal (in provider) */
  1499. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1500. expand ? PROVIDER_SIGNAL_EXPAND_PLUGIN :
  1501. PROVIDER_SIGNAL_COLLAPSE_PLUGIN);
  1502. g_object_notify (G_OBJECT (plugin), "expand");
  1503. }
  1504. }
  1505. /**
  1506. * xfce_panel_plugin_get_shrink:
  1507. * @plugin : an #XfcePanelPlugin.
  1508. *
  1509. * Whether the plugin can shrink if the size on the panel is limited. This
  1510. * is effective with plugins that do not have expand set, but can accept
  1511. * a smaller size when needed.
  1512. *
  1513. * Returns: %TRUE when the plugin can shrink,
  1514. * %FALSE otherwise.
  1515. *
  1516. * Since: 4.10
  1517. **/
  1518. gboolean
  1519. xfce_panel_plugin_get_shrink (XfcePanelPlugin *plugin)
  1520. {
  1521. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), FALSE);
  1522. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), FALSE);
  1523. return plugin->priv->shrink;
  1524. }
  1525. /**
  1526. * xfce_panel_plugin_set_shrink:
  1527. * @plugin : an #XfcePanelPlugin.
  1528. * @shrink : whether the plugin can shrink.
  1529. *
  1530. * Wether the plugin can shrink if the size on the panel
  1531. * is limited. This does not work if the plugin is expanded.
  1532. **/
  1533. void
  1534. xfce_panel_plugin_set_shrink (XfcePanelPlugin *plugin,
  1535. gboolean shrink)
  1536. {
  1537. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1538. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1539. /* normalize the value */
  1540. shrink = !!shrink;
  1541. /* check if update is required */
  1542. if (G_LIKELY (plugin->priv->shrink != shrink))
  1543. {
  1544. plugin->priv->shrink = shrink;
  1545. /* emit signal (in provider) */
  1546. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1547. shrink ? PROVIDER_SIGNAL_SHRINK_PLUGIN :
  1548. PROVIDER_SIGNAL_UNSHRINK_PLUGIN);
  1549. g_object_notify (G_OBJECT (plugin), "shrink");
  1550. }
  1551. }
  1552. /**
  1553. * xfce_panel_plugin_get_small:
  1554. * @plugin : an #XfcePanelPlugin.
  1555. *
  1556. * Whether the plugin is small enough to fit in a single row of
  1557. * a multi-row panel. E.g. if it is a button-like applet.
  1558. *
  1559. * Returns: %TRUE when the plugin is small,
  1560. * %FALSE otherwise.
  1561. *
  1562. * Since: 4.10
  1563. **/
  1564. gboolean
  1565. xfce_panel_plugin_get_small (XfcePanelPlugin *plugin)
  1566. {
  1567. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), FALSE);
  1568. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), FALSE);
  1569. return plugin->priv->small;
  1570. }
  1571. /**
  1572. * xfce_panel_plugin_set_small:
  1573. * @plugin : an #XfcePanelPlugin.
  1574. * @small : whether the plugin is a small button-like applet.
  1575. *
  1576. * Whether the plugin is small enough to fit in a single row of
  1577. * a multi-row panel. E.g. if it is a button-like applet.
  1578. **/
  1579. void
  1580. xfce_panel_plugin_set_small (XfcePanelPlugin *plugin,
  1581. gboolean small)
  1582. {
  1583. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1584. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1585. /* normalize the value */
  1586. small = !!small;
  1587. /* check if update is required */
  1588. if (G_LIKELY (plugin->priv->small != small))
  1589. {
  1590. plugin->priv->small = small;
  1591. /* emit signal (in provider) */
  1592. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1593. small ? PROVIDER_SIGNAL_SMALL_PLUGIN :
  1594. PROVIDER_SIGNAL_UNSMALL_PLUGIN);
  1595. g_object_notify (G_OBJECT (plugin), "small");
  1596. }
  1597. }
  1598. /**
  1599. * xfce_panel_plugin_get_orientation:
  1600. * @plugin : an #XfcePanelPlugin.
  1601. *
  1602. * The orientation of the panel in which the plugin is embedded.
  1603. *
  1604. * Returns: the current #GtkOrientation of the panel.
  1605. **/
  1606. GtkOrientation
  1607. xfce_panel_plugin_get_orientation (XfcePanelPlugin *plugin)
  1608. {
  1609. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), GTK_ORIENTATION_HORIZONTAL);
  1610. if (plugin->priv->mode == XFCE_PANEL_PLUGIN_MODE_HORIZONTAL)
  1611. return GTK_ORIENTATION_HORIZONTAL;
  1612. else
  1613. return GTK_ORIENTATION_VERTICAL;
  1614. }
  1615. /**
  1616. * xfce_panel_plugin_get_mode:
  1617. * @plugin : an #XfcePanelPlugin.
  1618. *
  1619. * The mode of the panel in which the plugin is embedded.
  1620. *
  1621. * Returns: the current #XfcePanelPluginMode of the panel.
  1622. *
  1623. * Since: 4.10
  1624. **/
  1625. XfcePanelPluginMode
  1626. xfce_panel_plugin_get_mode (XfcePanelPlugin *plugin)
  1627. {
  1628. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), XFCE_PANEL_PLUGIN_MODE_HORIZONTAL);
  1629. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), XFCE_PANEL_PLUGIN_MODE_HORIZONTAL);
  1630. return plugin->priv->mode;
  1631. }
  1632. /**
  1633. * xfce_panel_plugin_get_nrows:
  1634. * @plugin : an #XfcePanelPlugin.
  1635. *
  1636. * The number of rows of the panel in which the plugin is embedded.
  1637. *
  1638. * Returns: the current number of rows of the panel.
  1639. *
  1640. * Since: 4.10
  1641. **/
  1642. guint
  1643. xfce_panel_plugin_get_nrows (XfcePanelPlugin *plugin)
  1644. {
  1645. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), 1);
  1646. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), 1);
  1647. return plugin->priv->nrows;
  1648. }
  1649. /**
  1650. * xfce_panel_plugin_get_screen_position:
  1651. * @plugin : an #XfcePanelPlugin.
  1652. *
  1653. * The screen position of the panel in which the plugin is embedded.
  1654. *
  1655. * Returns: the current #XfceScreenPosition of the panel.
  1656. **/
  1657. XfceScreenPosition
  1658. xfce_panel_plugin_get_screen_position (XfcePanelPlugin *plugin)
  1659. {
  1660. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), XFCE_SCREEN_POSITION_NONE);
  1661. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), XFCE_SCREEN_POSITION_NONE);
  1662. return plugin->priv->screen_position;
  1663. }
  1664. /**
  1665. * xfce_panel_plugin_take_window:
  1666. * @plugin : an #XfcePanelPlugin.
  1667. * @window : a #GtkWindow.
  1668. *
  1669. * Connect a dialog to a plugin. When the @plugin is closed, it will
  1670. * destroy the @window.
  1671. *
  1672. * Since: 4.8
  1673. **/
  1674. void
  1675. xfce_panel_plugin_take_window (XfcePanelPlugin *plugin,
  1676. GtkWindow *window)
  1677. {
  1678. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1679. g_return_if_fail (GTK_IS_WINDOW (window));
  1680. gtk_window_set_screen (window, gtk_widget_get_screen (GTK_WIDGET (plugin)));
  1681. /* monitor both objects */
  1682. g_object_weak_ref (G_OBJECT (plugin),
  1683. xfce_panel_plugin_take_window_notify, window);
  1684. g_object_weak_ref (G_OBJECT (window),
  1685. xfce_panel_plugin_take_window_notify, plugin);
  1686. }
  1687. /**
  1688. * xfce_panel_plugin_add_action_widget:
  1689. * @plugin : an #XfcePanelPlugin.
  1690. * @widget : a #GtkWidget that receives mouse events.
  1691. *
  1692. * Attach the plugin menu to this widget. Plugin writers should call this
  1693. * for every widget that can receive mouse events. If you forget to call this
  1694. * the plugin will not have a right-click menu and the user won't be able to
  1695. * remove it.
  1696. **/
  1697. void
  1698. xfce_panel_plugin_add_action_widget (XfcePanelPlugin *plugin,
  1699. GtkWidget *widget)
  1700. {
  1701. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1702. g_return_if_fail (GTK_IS_WIDGET (widget));
  1703. g_signal_connect_swapped (G_OBJECT (widget), "button-press-event",
  1704. G_CALLBACK (xfce_panel_plugin_button_press_event), plugin);
  1705. }
  1706. /**
  1707. * xfce_panel_plugin_menu_insert_item:
  1708. * @plugin : an #XfcePanelPlugin.
  1709. * @item : a #GtkMenuItem.
  1710. *
  1711. * Insert a custom menu item to the plugin's right click menu. This item
  1712. * is packed below the "Move" menu item.
  1713. **/
  1714. void
  1715. xfce_panel_plugin_menu_insert_item (XfcePanelPlugin *plugin,
  1716. GtkMenuItem *item)
  1717. {
  1718. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1719. g_return_if_fail (GTK_IS_MENU_ITEM (item));
  1720. /* take the item and add to internal list */
  1721. plugin->priv->menu_items = g_slist_append (plugin->priv->menu_items,
  1722. g_object_ref_sink (item));
  1723. g_signal_connect (G_OBJECT (item), "destroy",
  1724. G_CALLBACK (xfce_panel_plugin_menu_item_destroy), plugin);
  1725. /* destroy the menu */
  1726. xfce_panel_plugin_menu_destroy (plugin);
  1727. }
  1728. /**
  1729. * xfce_panel_plugin_menu_show_configure:
  1730. * @plugin : an #XfcePanelPlugin.
  1731. *
  1732. * Show the "Properties" item in the menu. Clicking on the menu item
  1733. * will emit the "configure-plugin" signal.
  1734. **/
  1735. void
  1736. xfce_panel_plugin_menu_show_configure (XfcePanelPlugin *plugin)
  1737. {
  1738. GtkMenu *menu;
  1739. GtkWidget *item;
  1740. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1741. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1742. PANEL_SET_FLAG (plugin->priv->flags, PLUGIN_FLAG_SHOW_CONFIGURE);
  1743. /* show the menu item if the menu is already generated */
  1744. if (G_UNLIKELY (plugin->priv->menu != NULL))
  1745. {
  1746. /* get and show the properties item */
  1747. menu = xfce_panel_plugin_menu_get (plugin);
  1748. item = g_object_get_qdata (G_OBJECT (menu), item_properties);
  1749. if (G_LIKELY (item != NULL))
  1750. gtk_widget_show (item);
  1751. }
  1752. /* emit signal, used by the external plugin */
  1753. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1754. PROVIDER_SIGNAL_SHOW_CONFIGURE);
  1755. }
  1756. /**
  1757. * xfce_panel_plugin_menu_show_about:
  1758. * @plugin : an #XfcePanelPlugin.
  1759. *
  1760. * Show the "About" item in the menu. Clicking on the menu item
  1761. * will emit the "about" signal.
  1762. **/
  1763. void
  1764. xfce_panel_plugin_menu_show_about (XfcePanelPlugin *plugin)
  1765. {
  1766. GtkMenu *menu;
  1767. GtkWidget *item;
  1768. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1769. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1770. PANEL_SET_FLAG (plugin->priv->flags, PLUGIN_FLAG_SHOW_ABOUT);
  1771. /* show the menu item if the menu is already generated */
  1772. if (G_UNLIKELY (plugin->priv->menu != NULL))
  1773. {
  1774. /* get and show the about item */
  1775. menu = xfce_panel_plugin_menu_get (plugin);
  1776. item = g_object_get_qdata (G_OBJECT (menu), item_about);
  1777. if (G_LIKELY (item != NULL))
  1778. gtk_widget_show (item);
  1779. }
  1780. /* emit signal, used by the external plugin */
  1781. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1782. PROVIDER_SIGNAL_SHOW_ABOUT);
  1783. }
  1784. /**
  1785. * xfce_panel_plugin_get_locked:
  1786. * @plugin : an #XfcePanelPlugin.
  1787. *
  1788. * Whether the plugin is locked (not allowing customization). This
  1789. * is emitted through the panel based on the Xfconf locking of the
  1790. * panel window the plugin is embedded on.
  1791. *
  1792. * It is however possible to send a fake signal to the plugin to
  1793. * override this propery, so you should only use this for interface
  1794. * elements and (if you use Xfconf) check the locking yourself
  1795. * before you write any values or query the kiosk mode using the
  1796. * api in libxfce4util.
  1797. *
  1798. * Returns: %TRUE if the user is not allowed to modify the plugin,
  1799. * %FALSE is customization is allowed.
  1800. *
  1801. * Since: 4.8
  1802. **/
  1803. gboolean
  1804. xfce_panel_plugin_get_locked (XfcePanelPlugin *plugin)
  1805. {
  1806. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), TRUE);
  1807. return plugin->priv->locked;
  1808. }
  1809. /**
  1810. * xfce_panel_plugin_remove:
  1811. * @plugin : an #XfcePanelPlugin.
  1812. *
  1813. * Remove this plugin from the panel and remove all its configuration.
  1814. *
  1815. * Plugins should not use this function to implement their own
  1816. * menu item or button to remove theirselfs from the panel, but only
  1817. * in case the there are problems with the plugin in the panel. Always
  1818. * try to inform the user why this occured.
  1819. *
  1820. * Since: 4.8
  1821. **/
  1822. void
  1823. xfce_panel_plugin_remove (XfcePanelPlugin *plugin)
  1824. {
  1825. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1826. /* ask the panel or wrapper to remove the plugin */
  1827. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1828. PROVIDER_SIGNAL_REMOVE_PLUGIN);
  1829. }
  1830. /**
  1831. * xfce_panel_plugin_block_menu:
  1832. * @plugin : an #XfcePanelPlugin.
  1833. *
  1834. * Block configuring the plugin. This will make the "Properties" menu
  1835. * item insensitive.
  1836. **/
  1837. void
  1838. xfce_panel_plugin_block_menu (XfcePanelPlugin *plugin)
  1839. {
  1840. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1841. /* increase block counter */
  1842. plugin->priv->menu_blocked++;
  1843. }
  1844. /**
  1845. * xfce_panel_plugin_unblock_menu:
  1846. * @plugin : an #XfcePanelPlugin.
  1847. *
  1848. * Unblock configuring the plugin. This will make the "Properties" menu
  1849. * item sensitive.
  1850. **/
  1851. void
  1852. xfce_panel_plugin_unblock_menu (XfcePanelPlugin *plugin)
  1853. {
  1854. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1855. g_return_if_fail (plugin->priv->menu_blocked > 0);
  1856. /* decrease block counter */
  1857. if (G_LIKELY (plugin->priv->menu_blocked > 0))
  1858. plugin->priv->menu_blocked--;
  1859. }
  1860. /**
  1861. * xfce_panel_plugin_register_menu:
  1862. * @plugin : an #XfcePanelPlugin.
  1863. * @menu : a #GtkMenu that will be opened
  1864. *
  1865. * Register a menu that is about to popup. This will make sure the panel
  1866. * will properly handle its autohide behaviour. You have to call this
  1867. * function every time the menu is opened (e.g. using gtk_popup_menu()).
  1868. *
  1869. * If you want to open the menu aligned to the side of the panel (and the
  1870. * plugin), you should use xfce_panel_plugin_position_menu() as
  1871. * #GtkMenuPositionFunc. This callback function will take care of calling
  1872. * xfce_panel_plugin_register_menu() as well.
  1873. *
  1874. * See also: xfce_panel_plugin_position_menu() and xfce_panel_plugin_block_autohide().
  1875. **/
  1876. void
  1877. xfce_panel_plugin_register_menu (XfcePanelPlugin *plugin,
  1878. GtkMenu *menu)
  1879. {
  1880. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1881. g_return_if_fail (GTK_IS_MENU (menu));
  1882. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1883. /* increase the counter */
  1884. plugin->priv->panel_lock++;
  1885. /* connect signal to menu to decrease counter */
  1886. g_signal_connect (G_OBJECT (menu), "deactivate",
  1887. G_CALLBACK (xfce_panel_plugin_unregister_menu), plugin);
  1888. g_signal_connect (G_OBJECT (menu), "destroy",
  1889. G_CALLBACK (xfce_panel_plugin_unregister_menu), plugin);
  1890. /* tell panel it needs to lock */
  1891. if (plugin->priv->panel_lock == 1)
  1892. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  1893. PROVIDER_SIGNAL_LOCK_PANEL);
  1894. }
  1895. /**
  1896. * xfce_panel_plugin_arrow_type:
  1897. * @plugin : an #XfcePanelPlugin.
  1898. *
  1899. * Determine the #GtkArrowType for a widget that opens a menu and uses
  1900. * xfce_panel_plugin_position_menu() to position the menu.
  1901. *
  1902. * Returns: the #GtkArrowType to use.
  1903. **/
  1904. GtkArrowType
  1905. xfce_panel_plugin_arrow_type (XfcePanelPlugin *plugin)
  1906. {
  1907. XfceScreenPosition screen_position;
  1908. GdkScreen *screen;
  1909. gint monitor_num;
  1910. GdkRectangle monitor;
  1911. gint x, y;
  1912. GdkWindow *window;
  1913. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), GTK_ARROW_NONE);
  1914. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), GTK_ARROW_NONE);
  1915. /* get the plugin screen position */
  1916. screen_position = xfce_panel_plugin_get_screen_position (plugin);
  1917. /* detect the arrow type */
  1918. if (xfce_screen_position_is_top (screen_position))
  1919. return GTK_ARROW_DOWN;
  1920. else if (xfce_screen_position_is_bottom (screen_position))
  1921. return GTK_ARROW_UP;
  1922. else if (xfce_screen_position_is_left (screen_position))
  1923. return GTK_ARROW_RIGHT;
  1924. else if (xfce_screen_position_is_right (screen_position))
  1925. return GTK_ARROW_LEFT;
  1926. else /* floating */
  1927. {
  1928. window = gtk_widget_get_window (GTK_WIDGET (plugin));
  1929. if (G_UNLIKELY (window == NULL))
  1930. return GTK_ARROW_NONE;
  1931. /* get the monitor geometry */
  1932. screen = gtk_widget_get_screen (GTK_WIDGET (plugin));
  1933. monitor_num = gdk_screen_get_monitor_at_window (screen, window);
  1934. gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
  1935. /* get the plugin root origin */
  1936. gdk_window_get_root_origin (window, &x, &y);
  1937. /* detect arrow type */
  1938. if (screen_position == XFCE_SCREEN_POSITION_FLOATING_H)
  1939. return (y < (monitor.y + monitor.height / 2)) ? GTK_ARROW_DOWN : GTK_ARROW_UP;
  1940. else
  1941. return (x < (monitor.x + monitor.width / 2)) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
  1942. }
  1943. }
  1944. /**
  1945. * xfce_panel_plugin_position_widget:
  1946. * @plugin : an #XfcePanelPlugin.
  1947. * @menu_widget : a #GtkWidget that will be used as popup menu.
  1948. * @attach_widget : a #GtkWidget relative to which the menu should be positioned.
  1949. * @x : return location for the x coordinate.
  1950. * @y : return location for the x coordinate.
  1951. *
  1952. * The menu widget is positioned relative to @attach_widget.
  1953. * If @attach_widget is NULL, the menu widget is instead positioned
  1954. * relative to @panel_plugin.
  1955. *
  1956. * This function is intended for custom menu widgets.
  1957. * For a regular #GtkMenu you should use xfce_panel_plugin_position_menu()
  1958. * instead (as callback argument to gtk_menu_popup()).
  1959. *
  1960. * See also: xfce_panel_plugin_position_menu().
  1961. **/
  1962. void
  1963. xfce_panel_plugin_position_widget (XfcePanelPlugin *plugin,
  1964. GtkWidget *menu_widget,
  1965. GtkWidget *attach_widget,
  1966. gint *x,
  1967. gint *y)
  1968. {
  1969. GtkRequisition requisition;
  1970. GdkScreen *screen;
  1971. GdkRectangle monitor;
  1972. gint monitor_num;
  1973. GTimeVal now_t, end_t;
  1974. GtkWidget *toplevel, *plug;
  1975. gint px, py;
  1976. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  1977. g_return_if_fail (GTK_IS_WIDGET (menu_widget));
  1978. g_return_if_fail (attach_widget == NULL || GTK_IS_WIDGET (attach_widget));
  1979. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  1980. /* if the attach widget is null, use the panel plugin */
  1981. if (attach_widget == NULL)
  1982. attach_widget = GTK_WIDGET (plugin);
  1983. /* make sure the menu is realized to get valid rectangle sizes */
  1984. if (!GTK_WIDGET_REALIZED (menu_widget))
  1985. gtk_widget_realize (menu_widget);
  1986. /* make sure the attach widget is realized for the gdkwindow */
  1987. if (!GTK_WIDGET_REALIZED (attach_widget))
  1988. gtk_widget_realize (attach_widget);
  1989. /* get the menu/widget size request */
  1990. gtk_widget_size_request (menu_widget, &requisition);
  1991. /* get the root position of the attach widget */
  1992. toplevel = gtk_widget_get_toplevel (attach_widget);
  1993. gtk_window_get_position (GTK_WINDOW (toplevel), x, y);
  1994. /* correct position for external plugins */
  1995. plug = gtk_widget_get_ancestor (attach_widget, GTK_TYPE_PLUG);
  1996. if (plug != NULL)
  1997. {
  1998. gdk_window_get_geometry (gtk_plug_get_socket_window (GTK_PLUG (plug)),
  1999. &px, &py, NULL, NULL, NULL);
  2000. *x += px;
  2001. *y += py;
  2002. }
  2003. /* if the panel is hidden (auto hide is enabled) and we requested a
  2004. * panel lock, wait for gtk to position the panel before we actually
  2005. * use the coordinates */
  2006. if (plugin->priv->panel_lock > 0)
  2007. {
  2008. g_get_current_time (&end_t);
  2009. g_time_val_add (&end_t, G_USEC_PER_SEC / 2);
  2010. while (*x == -9999 && *y == -9999)
  2011. {
  2012. while (gtk_events_pending ())
  2013. gtk_main_iteration ();
  2014. gdk_window_get_position (GDK_WINDOW (attach_widget->window), x, y);
  2015. /* don't try longer then 1/2 a second */
  2016. g_get_current_time (&now_t);
  2017. if (now_t.tv_sec > end_t.tv_sec
  2018. || (now_t.tv_sec == end_t.tv_sec
  2019. && now_t.tv_usec > end_t.tv_usec))
  2020. break;
  2021. }
  2022. }
  2023. /* add the widgets allocation */
  2024. *x += attach_widget->allocation.x;
  2025. *y += attach_widget->allocation.y;
  2026. switch (xfce_panel_plugin_arrow_type (plugin))
  2027. {
  2028. case GTK_ARROW_UP:
  2029. *y -= requisition.height;
  2030. break;
  2031. case GTK_ARROW_DOWN:
  2032. *y += attach_widget->allocation.height;
  2033. break;
  2034. case GTK_ARROW_LEFT:
  2035. *x -= requisition.width;
  2036. break;
  2037. default: /* GTK_ARROW_RIGHT and GTK_ARROW_NONE */
  2038. *x += attach_widget->allocation.width;
  2039. break;
  2040. }
  2041. /* get the monitor geometry */
  2042. screen = gtk_widget_get_screen (attach_widget);
  2043. monitor_num = gdk_screen_get_monitor_at_window (screen, attach_widget->window);
  2044. gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
  2045. /* keep the menu inside the screen */
  2046. if (*x > monitor.x + monitor.width - requisition.width)
  2047. *x = monitor.x + monitor.width - requisition.width;
  2048. if (*x < monitor.x)
  2049. *x = monitor.x;
  2050. if (*y > monitor.y + monitor.height - requisition.height)
  2051. *y = monitor.y + monitor.height - requisition.height;
  2052. if (*y < monitor.y)
  2053. *y = monitor.y;
  2054. /* popup on the correct screen */
  2055. if (G_LIKELY (GTK_IS_MENU (menu_widget)))
  2056. gtk_menu_set_screen (GTK_MENU (menu_widget), screen);
  2057. else if (GTK_IS_WINDOW (menu_widget))
  2058. gtk_window_set_screen (GTK_WINDOW (menu_widget), screen);
  2059. }
  2060. /**
  2061. * xfce_panel_plugin_position_menu:
  2062. * @menu : a #GtkMenu.
  2063. * @x : return location for the x coordinate.
  2064. * @y : return location for the y coordinate.
  2065. * @push_in : keep inside the screen (see #GtkMenuPositionFunc)
  2066. * @panel_plugin : an #XfcePanelPlugin.
  2067. *
  2068. * Function to be used as #GtkMenuPositionFunc in a call to gtk_menu_popup().
  2069. * As data argument it needs an #XfcePanelPlugin.
  2070. *
  2071. * The menu is normally positioned relative to @panel_plugin. If you want the
  2072. * menu to be positioned relative to another widget, you can use
  2073. * gtk_menu_attach_to_widget() to explicitly set a 'parent' widget.
  2074. *
  2075. * As a convenience, xfce_panel_plugin_position_menu() calls
  2076. * xfce_panel_plugin_register_menu() for the menu.
  2077. *
  2078. * <example>
  2079. * void
  2080. * myplugin_popup_menu (XfcePanelPlugin *plugin,
  2081. * GtkMenu *menu,
  2082. * GdkEventButton *ev)
  2083. * {
  2084. * gtk_menu_popup (menu, NULL, NULL,
  2085. * xfce_panel_plugin_position_menu, plugin,
  2086. * ev->button, ev->time );
  2087. * }
  2088. * </example>
  2089. *
  2090. * For a custom widget that will be used as a popup menu, use
  2091. * xfce_panel_plugin_position_widget() instead.
  2092. *
  2093. * See also: gtk_menu_popup().
  2094. **/
  2095. void
  2096. xfce_panel_plugin_position_menu (GtkMenu *menu,
  2097. gint *x,
  2098. gint *y,
  2099. gboolean *push_in,
  2100. gpointer panel_plugin)
  2101. {
  2102. GtkWidget *attach_widget;
  2103. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (panel_plugin));
  2104. g_return_if_fail (GTK_IS_MENU (menu));
  2105. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (panel_plugin));
  2106. /* register the menu */
  2107. xfce_panel_plugin_register_menu (XFCE_PANEL_PLUGIN (panel_plugin), menu);
  2108. /* calculate the coordinates */
  2109. attach_widget = gtk_menu_get_attach_widget (menu);
  2110. xfce_panel_plugin_position_widget (XFCE_PANEL_PLUGIN (panel_plugin),
  2111. GTK_WIDGET (menu), attach_widget, x, y);
  2112. /* keep the menu inside screen */
  2113. *push_in = TRUE;
  2114. }
  2115. /**
  2116. * xfce_panel_plugin_focus_widget:
  2117. * @plugin : an #XfcePanelPlugin.
  2118. * @widget : a #GtkWidget inside the plugins that should be focussed.
  2119. *
  2120. * Grab the focus on @widget. Asks the panel to allow focus on its items
  2121. * and set the focus to the requested widget.
  2122. **/
  2123. void
  2124. xfce_panel_plugin_focus_widget (XfcePanelPlugin *plugin,
  2125. GtkWidget *widget)
  2126. {
  2127. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  2128. g_return_if_fail (GTK_IS_WIDGET (widget));
  2129. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  2130. /* focus the panel window */
  2131. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  2132. PROVIDER_SIGNAL_FOCUS_PLUGIN);
  2133. /* let the widget grab focus */
  2134. gtk_widget_grab_focus (widget);
  2135. }
  2136. /**
  2137. * xfce_panel_plugin_block_autohide:
  2138. * @plugin : an #XfcePanelPlugin.
  2139. * @blocked : new blocking state of this plugin.
  2140. *
  2141. * Wether this plugin blocks the autohide functality of the panel. Use
  2142. * this when you 'popup' something that is visually attached to the
  2143. * plugin at it will look weird for a user if the panel will hide while
  2144. * he/she is working in the popup.
  2145. *
  2146. * For menus it there is xfce_panel_plugin_register_menu() which will
  2147. * take care of this.
  2148. **/
  2149. void
  2150. xfce_panel_plugin_block_autohide (XfcePanelPlugin *plugin,
  2151. gboolean blocked)
  2152. {
  2153. g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  2154. g_return_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin));
  2155. /* leave when requesting the same block state */
  2156. if (PANEL_HAS_FLAG (plugin->priv->flags, PLUGIN_FLAG_BLOCK_AUTOHIDE) == blocked)
  2157. return;
  2158. if (blocked)
  2159. {
  2160. /* increase the counter */
  2161. panel_return_if_fail (plugin->priv->panel_lock >= 0);
  2162. plugin->priv->panel_lock++;
  2163. PANEL_SET_FLAG (plugin->priv->flags, PLUGIN_FLAG_BLOCK_AUTOHIDE);
  2164. /* tell panel it needs to lock */
  2165. if (plugin->priv->panel_lock == 1)
  2166. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  2167. PROVIDER_SIGNAL_LOCK_PANEL);
  2168. }
  2169. else
  2170. {
  2171. /* decrease the counter */
  2172. panel_return_if_fail (plugin->priv->panel_lock > 0);
  2173. plugin->priv->panel_lock--;
  2174. PANEL_UNSET_FLAG (plugin->priv->flags, PLUGIN_FLAG_BLOCK_AUTOHIDE);
  2175. /* tell panel it needs to unlock */
  2176. if (plugin->priv->panel_lock == 0)
  2177. xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (plugin),
  2178. PROVIDER_SIGNAL_UNLOCK_PANEL);
  2179. }
  2180. }
  2181. /**
  2182. * xfce_panel_plugin_lookup_rc_file:
  2183. * @plugin : an #XfcePanelPlugin.
  2184. *
  2185. * Looks for the plugin resource file. This should be used to get the
  2186. * plugin read location of the config file. You should only use the
  2187. * returned path to read information from, since it might point to a
  2188. * not-writable file (in kiosk mode for example).
  2189. *
  2190. * See also: xfce_panel_plugin_save_location() and xfce_resource_lookup()
  2191. *
  2192. * Returns: The path to a config file or %NULL if no file was found.
  2193. * The returned string must be freed using g_free()
  2194. **/
  2195. gchar *
  2196. xfce_panel_plugin_lookup_rc_file (XfcePanelPlugin *plugin)
  2197. {
  2198. gchar *filename, *path;
  2199. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  2200. g_return_val_if_fail (XFCE_PANEL_PLUGIN_CONSTRUCTED (plugin), NULL);
  2201. filename = xfce_panel_plugin_relative_filename (plugin);
  2202. path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, filename);
  2203. g_free (filename);
  2204. return path;
  2205. }
  2206. /**
  2207. * xfce_panel_plugin_save_location:
  2208. * @plugin : an #XfcePanelPlugin.
  2209. * @create : whether to create missing directories.
  2210. *
  2211. * Returns the path that can be used to store configuration information.
  2212. * Don't use this function if you want to read from the config file, but
  2213. * use xfce_panel_plugin_lookup_rc_file() instead.
  2214. *
  2215. * See also: xfce_panel_plugin_lookup_rc_file() and xfce_resource_save_location()
  2216. *
  2217. * Returns: The path to a config file or %NULL if no file was found.
  2218. * The returned string must be freed u sing g_free().
  2219. **/
  2220. gchar *
  2221. xfce_panel_plugin_save_location (XfcePanelPlugin *plugin,
  2222. gboolean create)
  2223. {
  2224. gchar *filename, *path;
  2225. g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
  2226. filename = xfce_panel_plugin_relative_filename (plugin);
  2227. path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, filename, create);
  2228. g_free (filename);
  2229. return path;
  2230. }
  2231. #define __XFCE_PANEL_PLUGIN_C__
  2232. #include <libxfce4panel/libxfce4panel-aliasdef.c>