[Xfce4-commits] <xfce4-panel:nick/actions-plugin> Actions: Merge functionality of xfce4-session plugin.
Nick Schermer
noreply at xfce.org
Sun Jul 24 21:32:02 CEST 2011
Updating branch refs/heads/nick/actions-plugin
to 8ebc45bc6e5f49a15fa59692ea0e7e5ad5d3e995 (commit)
from 389ff734e4cc54c68dd87b884b9b5aa8562e6dae (commit)
commit 8ebc45bc6e5f49a15fa59692ea0e7e5ad5d3e995
Author: Nick Schermer <nick at xfce.org>
Date: Tue Jul 12 17:56:14 2011 +0200
Actions: Merge functionality of xfce4-session plugin.
Add support of the functionality of xfswitch and xfce4-session
plugin in a single plugin.
docs/README.gtkrc-2.0 | 5 +-
plugins/actions/Makefile.am | 2 +
plugins/actions/actions-dialog.glade | 322 +++++++----
plugins/actions/actions.c | 1155 ++++++++++++++++++++++++++--------
plugins/actions/actions.desktop.in | 2 +-
5 files changed, 1127 insertions(+), 359 deletions(-)
diff --git a/docs/README.gtkrc-2.0 b/docs/README.gtkrc-2.0
index 0f8b874..17d7276 100644
--- a/docs/README.gtkrc-2.0
+++ b/docs/README.gtkrc-2.0
@@ -27,8 +27,9 @@ class "XfcePanelWindow" style "xfce-panel-window-style"
XfceActionsPlugin
-----------------
-Special widget names in this plugin are actions-first-button and
-actions-second-button.
+You can set a custom icon size in gtk-icon-sizes with the name
+panel-actions-menu. The default icon size is 16px.
+Special widget name in this plugin is actions-button.
diff --git a/plugins/actions/Makefile.am b/plugins/actions/Makefile.am
index 1bd65c4..ddad990 100644
--- a/plugins/actions/Makefile.am
+++ b/plugins/actions/Makefile.am
@@ -23,6 +23,7 @@ libactions_la_CFLAGS = \
$(LIBXFCE4UI_CFLAGS) \
$(EXO_CFLAGS) \
$(XFCONF_CFLAGS) \
+ $(DBUS_CFLAGS) \
$(PLATFORM_CFLAGS)
libactions_la_LDFLAGS = \
@@ -39,6 +40,7 @@ libactions_la_LIBADD = \
$(LIBXFCE4UTIL_LIBS) \
$(LIBXFCE4UI_LIBS) \
$(EXO_LIBS) \
+ $(DBUS_LIBS) \
$(XFCONF_LIBS)
libactions_la_DEPENDENCIES = \
diff --git a/plugins/actions/actions-dialog.glade b/plugins/actions/actions-dialog.glade
index 384f522..c39d4bb 100644
--- a/plugins/actions/actions-dialog.glade
+++ b/plugins/actions/actions-dialog.glade
@@ -1,120 +1,24 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="2.14"/>
+ <requires lib="gtk+" version="2.20"/>
<!-- interface-requires libxfce4ui 4.5 -->
<!-- interface-naming-policy project-wide -->
<object class="XfceTitledDialog" id="dialog">
+ <property name="can_focus">False</property>
<property name="title" translatable="yes">Action Buttons</property>
+ <property name="default_width">300</property>
+ <property name="default_height">450</property>
<property name="icon_name">gtk-properties</property>
<property name="type_hint">normal</property>
- <property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<property name="spacing">2</property>
- <child>
- <object class="GtkFrame" id="frame5">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="alignment5">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkTable" id="table5">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">6</property>
- <child>
- <object class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_First button:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">first-action</property>
- </object>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label9">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Second button:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">second-action</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="first-action">
- <property name="visible">True</property>
- <property name="model">first-action-model</property>
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext2"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="second-action">
- <property name="visible">True</property>
- <property name="model">second-action-model</property>
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext1"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label7">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Button Actions</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="close-button">
@@ -122,6 +26,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@@ -136,6 +41,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@@ -148,10 +54,202 @@
</object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Appeara_nce:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo-mode</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="invert-orientation">
+ <property name="label" translatable="yes">Invert buttons _orientation</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo-mode">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">mode-store</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="confirmation-dialog">
+ <property name="label" translatable="yes">_Show confirmation dialog</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Show a confirmation dialog with a 30 second timeout for some of the actions.</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">General</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">6</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTreeView" id="actions-treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">items-store</property>
+ <property name="headers_clickable">False</property>
+ <property name="reorderable">True</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <property name="title" translatable="yes">Visible</property>
+ <child>
+ <object class="GtkCellRendererToggle" id="visible-toggle"/>
+ <attributes>
+ <attribute name="active">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="title" translatable="yes">Action</property>
+ <child>
+ <object class="GtkCellRendererText" id="text-renderer"/>
+ <attributes>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Actions</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">actions-treeview</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
</child>
<action-widgets>
@@ -159,16 +257,28 @@
<action-widget response="0">help-button</action-widget>
</action-widgets>
</object>
- <object class="GtkListStore" id="first-action-model">
+ <object class="GtkListStore" id="items-store">
<columns>
- <!-- column-name title -->
+ <!-- column-name hidden -->
+ <column type="gboolean"/>
+ <!-- column-name name -->
<column type="gchararray"/>
+ <!-- column-name type -->
+ <column type="guint"/>
</columns>
</object>
- <object class="GtkListStore" id="second-action-model">
+ <object class="GtkListStore" id="mode-store">
<columns>
<!-- column-name title -->
<column type="gchararray"/>
</columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Action Buttons</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Session Menu</col>
+ </row>
+ </data>
</object>
</interface>
diff --git a/plugins/actions/actions.c b/plugins/actions/actions.c
index 2e58540..6b50486 100644
--- a/plugins/actions/actions.c
+++ b/plugins/actions/actions.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009-2010 Nick Schermer <nick at xfce.org>
+ * Copyright (C) 2009-2011 Nick Schermer <nick at xfce.org>
+ * Copyright (c) 2009 Brian Tarricone <brian at tarricone.org>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,6 +26,7 @@
#include <libxfce4util/libxfce4util.h>
#include <libxfce4ui/libxfce4ui.h>
#include <exo/exo.h>
+#include <dbus/dbus-glib.h>
#include <common/panel-private.h>
#include <common/panel-xfconf.h>
@@ -35,45 +37,55 @@
-static void actions_plugin_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void actions_plugin_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void actions_plugin_construct (XfcePanelPlugin *panel_plugin);
-static gboolean actions_plugin_size_changed (XfcePanelPlugin *panel_plugin,
- gint size);
-static void actions_plugin_configure_plugin (XfcePanelPlugin *panel_plugin);
-static void actions_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
- GtkOrientation orientation);
-static void actions_plugin_button_clicked (GtkWidget *button,
- ActionsPlugin *plugin);
+#define DEFAULT_ICON_SIZE (16)
+#define DEFAULT_TIMEOUT (30)
+
+
+
+static void actions_plugin_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void actions_plugin_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void actions_plugin_construct (XfcePanelPlugin *panel_plugin);
+static void actions_plugin_free_data (XfcePanelPlugin *panel_plugin);
+static gboolean actions_plugin_size_changed (XfcePanelPlugin *panel_plugin,
+ gint size);
+static void actions_plugin_configure_plugin (XfcePanelPlugin *panel_plugin);
+static void actions_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
+ GtkOrientation orientation);
+static void actions_plugin_pack (ActionsPlugin *plugin);
+static GPtrArray *actions_plugin_default_array (void);
+static void actions_plugin_menu (GtkWidget *button,
+ ActionsPlugin *plugin);
typedef enum
{
- ACTION_DISABLED = 0,
- ACTION_LOG_OUT_DIALOG,
- ACTION_LOG_OUT,
- ACTION_LOCK_SCREEN,
- ACTION_SHUT_DOWN,
- ACTION_RESTART,
- ACTION_SUSPEND,
- ACTION_HIBERNATE
+ APPEARANCE_TYPE_BUTTONS,
+ APPEARANCE_TYPE_MENU
}
-ActionType;
+AppearanceType;
-typedef struct
+enum
{
- ActionType type;
- const gchar *title;
- const gchar *icon_name;
-}
-ActionEntry;
+ PROP_0,
+ PROP_ITEMS,
+ PROP_APPEARANCE,
+ PROP_INVERT_ORIENTATION,
+ PROP_ASK_CONFIRMATION
+};
+
+enum
+{
+ COLUMN_VISIBLE,
+ COLUMN_NAME,
+ COLUMN_TYPE
+};
struct _ActionsPluginClass
{
@@ -84,35 +96,118 @@ struct _ActionsPlugin
{
XfcePanelPlugin __parent__;
- /* widgets */
- GtkWidget *box;
- GtkWidget *first_button;
- GtkWidget *first_image;
- GtkWidget *second_button;
- GtkWidget *second_image;
-
- /* settings */
- ActionType first_action;
- ActionType second_action;
+ AppearanceType type;
+ GPtrArray *items;
+ GtkWidget *menu;
+ guint invert_orientation : 1;
+ guint ask_confirmation : 1;
+ guint pack_idle_id;
};
-enum
+typedef enum
{
- PROP_0,
- PROP_FIRST_ACTION,
- PROP_SECOND_ACTION
-};
+ ACTION_TYPE_0,
+ ACTION_TYPE_SEPARATOR,
+ ACTION_TYPE_LOGOUT,
+ ACTION_TYPE_LOGOUT_DIALOG,
+ ACTION_TYPE_SWITCH_USER,
+ ACTION_TYPE_LOCK_SCREEN,
+ ACTION_TYPE_HIBERNATE,
+ ACTION_TYPE_SUSPEND,
+ ACTION_TYPE_RESTART,
+ ACTION_TYPE_SHUTDOWN,
+ N_ACTION_TYPES
+}
+ActionType;
+
+/* copied from xfce4-session/shutdown.h -- ORDER MATTERS.
+ * The numbers correspond to the 'type' parameter of
+ * org.xfce.Session.Manager.Shutdown */
+typedef enum
+{
+ ACTION_SHUTDOWN_ASK = 0,
+ ACTION_SHUTDOWN_LOGOUT,
+ ACTION_SHUTDOWN_HALT,
+ ACTION_SHUTDOWN_REBOOT,
+ ACTION_SHUTDOWN_SUSPEND,
+ ACTION_SHUTDOWN_HIBERNATE,
+} ActionShutdownType;
+
+typedef struct
+{
+ ActionType type;
+ const gchar *name;
+ const gchar *name_mnemonic;
+ const gchar *question;
+ const gchar *status;
+ const gchar *icon_name;
+}
+ActionEntry;
+
+typedef struct
+{
+ ActionEntry *entry;
+ GtkWidget *dialog;
+ gint time_left;
+ guint unattended : 1;
+}
+ActionTimeout;
static ActionEntry action_entries[] =
{
- { ACTION_DISABLED, N_("Disabled"), NULL },
- { ACTION_LOG_OUT_DIALOG, N_("Log Out Dialog"), "system-log-out" },
- { ACTION_LOG_OUT, N_("Log Out"), "system-log-out" },
- { ACTION_LOCK_SCREEN, N_("Lock Screen"), "system-lock-screen" },
- { ACTION_SHUT_DOWN, N_("Shut Down"), "system-shutdown"},
- { ACTION_RESTART, N_("Restart"), "xfsm-reboot" },
- { ACTION_SUSPEND, N_("Suspend"), "system-suspend" },
- { ACTION_HIBERNATE, N_("Hibernate"), "system-hibernate" }
+ { ACTION_TYPE_LOGOUT,
+ N_("Log Out"),
+ N_("_Log Out"),
+ N_("Are you sure you want to log out?"),
+ N_("Logging out in %d seconds."),
+ "system-log-out"
+ },
+ { ACTION_TYPE_LOGOUT_DIALOG,
+ N_("Log Out..."),
+ N_("Log _Out..."),
+ NULL, NULL, /* already shows a dialog */
+ "system-log-out"
+ },
+ { ACTION_TYPE_SWITCH_USER,
+ N_("Switch User"),
+ N_("_Switch User"),
+ NULL, NULL, /* not needed */
+ "system-users"
+ },
+ { ACTION_TYPE_LOCK_SCREEN,
+ N_("Lock Screen"),
+ N_("L_ock Screen"),
+ NULL, NULL, /* not needed */
+ "system-lock-screen"
+ },
+ { ACTION_TYPE_HIBERNATE,
+ N_("Hibernate"),
+ N_("_Hibernate"),
+ N_("Do you want to suspend to disk?"),
+ N_("Hibernating computer in %d seconds."),
+ "system-hibernate"
+ },
+ { ACTION_TYPE_SUSPEND,
+ N_("Suspend"),
+ N_("Sus_pend"),
+ N_("Do you want to suspend to RAM?"),
+ N_("Suspending computer in %d seconds."),
+ "system-suspend"
+ },
+ { ACTION_TYPE_RESTART,
+ N_("Restart"),
+ N_("_Restart"),
+ N_("Are you sure you want to restart?"),
+ N_("Restarting computer in %d seconds."),
+ "xfsm-reboot"
+ },
+ { ACTION_TYPE_SHUTDOWN,
+ N_("Shut Down"),
+ N_("Shut _Down"),
+ N_("Are you sure you want to shut down?"),
+ N_("Turning off computer in %d seconds."),
+ "system-shutdown"
+ }
};
@@ -122,6 +217,11 @@ XFCE_PANEL_DEFINE_PLUGIN (ActionsPlugin, actions_plugin)
+static GtkIconSize menu_icon_size = GTK_ICON_SIZE_INVALID;
+static GQuark action_quark = 0;
+
+
+
static void
actions_plugin_class_init (ActionsPluginClass *klass)
{
@@ -134,27 +234,48 @@ actions_plugin_class_init (ActionsPluginClass *klass)
plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
plugin_class->construct = actions_plugin_construct;
+ plugin_class->free_data = actions_plugin_free_data;
plugin_class->size_changed = actions_plugin_size_changed;
plugin_class->configure_plugin = actions_plugin_configure_plugin;
plugin_class->orientation_changed = actions_plugin_orientation_changed;
g_object_class_install_property (gobject_class,
- PROP_FIRST_ACTION,
- g_param_spec_uint ("first-action",
- NULL, NULL,
- ACTION_DISABLED,
- ACTION_HIBERNATE - 1,
- ACTION_LOG_OUT_DIALOG,
- EXO_PARAM_READWRITE));
+ PROP_ITEMS,
+ g_param_spec_boxed ("items",
+ NULL, NULL,
+ PANEL_PROPERTIES_TYPE_VALUE_ARRAY,
+ EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
- PROP_SECOND_ACTION,
- g_param_spec_uint ("second-action",
+ PROP_APPEARANCE,
+ g_param_spec_uint ("appearance",
NULL, NULL,
- ACTION_DISABLED,
- ACTION_HIBERNATE,
- ACTION_DISABLED,
+ APPEARANCE_TYPE_BUTTONS,
+ APPEARANCE_TYPE_MENU,
+ APPEARANCE_TYPE_MENU,
EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_INVERT_ORIENTATION,
+ g_param_spec_boolean ("invert-orientation",
+ NULL, NULL,
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ASK_CONFIRMATION,
+ g_param_spec_boolean ("ask-confirmation",
+ NULL, NULL,
+ TRUE,
+ EXO_PARAM_READWRITE));
+
+ menu_icon_size = gtk_icon_size_from_name ("panel-actions-menu");
+ if (menu_icon_size == GTK_ICON_SIZE_INVALID)
+ menu_icon_size = gtk_icon_size_register ("panel-actions-menu",
+ DEFAULT_ICON_SIZE,
+ DEFAULT_ICON_SIZE);
+
+ action_quark = g_quark_from_string ("panel-action-quark");
}
@@ -162,40 +283,9 @@ actions_plugin_class_init (ActionsPluginClass *klass)
static void
actions_plugin_init (ActionsPlugin *plugin)
{
- GtkWidget *widget;
- ActionEntry *entry = &action_entries[ACTION_LOG_OUT_DIALOG];
-
- plugin->first_action = ACTION_LOG_OUT_DIALOG;
- plugin->second_action = ACTION_DISABLED;
-
- plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, TRUE, 0);
- gtk_container_add (GTK_CONTAINER (plugin), plugin->box);
-
- plugin->first_button = widget = xfce_panel_create_button ();
- gtk_box_pack_start (GTK_BOX (plugin->box), widget, TRUE, TRUE, 0);
- gtk_widget_set_name (widget, "actions-first-button");
- g_signal_connect (G_OBJECT (widget), "clicked",
- G_CALLBACK (actions_plugin_button_clicked), plugin);
- gtk_widget_set_tooltip_text (widget, _(entry->title));
- xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), widget);
- gtk_widget_show (widget);
-
- panel_utils_set_atk_info (widget, _(entry->title), NULL);
-
- plugin->first_image = xfce_panel_image_new_from_source (entry->icon_name);
- gtk_container_add (GTK_CONTAINER (widget), plugin->first_image);
- gtk_widget_show (plugin->first_image);
-
- plugin->second_button = widget = xfce_panel_create_button ();
- gtk_box_pack_start (GTK_BOX (plugin->box), widget, TRUE, TRUE, 0);
- gtk_widget_set_name (widget, "actions-second-button");
- g_signal_connect (G_OBJECT (widget), "clicked",
- G_CALLBACK (actions_plugin_button_clicked), plugin);
- xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), widget);
-
- plugin->second_image = xfce_panel_image_new ();
- gtk_container_add (GTK_CONTAINER (widget), plugin->second_image);
- gtk_widget_show (plugin->second_image);
+ plugin->type = APPEARANCE_TYPE_MENU;
+ plugin->invert_orientation = FALSE;
+ plugin->ask_confirmation = TRUE;
}
@@ -210,12 +300,20 @@ actions_plugin_get_property (GObject *object,
switch (prop_id)
{
- case PROP_FIRST_ACTION:
- g_value_set_uint (value, plugin->first_action - 1);
+ case PROP_ITEMS:
+ g_value_set_boxed (value, plugin->items);
break;
- case PROP_SECOND_ACTION:
- g_value_set_uint (value, plugin->second_action);
+ case PROP_APPEARANCE:
+ g_value_set_uint (value, plugin->type);
+ break;
+
+ case PROP_INVERT_ORIENTATION:
+ g_value_set_boolean (value, plugin->invert_orientation);
+ break;
+
+ case PROP_ASK_CONFIRMATION:
+ g_value_set_boolean (value, plugin->ask_confirmation);
break;
default:
@@ -233,49 +331,28 @@ actions_plugin_set_property (GObject *object,
GParamSpec *pspec)
{
ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (object);
- ActionType action;
switch (prop_id)
{
- case PROP_FIRST_ACTION:
- /* set new value and update icon */
- action = plugin->first_action = g_value_get_uint (value) + 1;
- gtk_widget_set_tooltip_text (plugin->first_button,
- _(action_entries[action].title));
- xfce_panel_image_set_from_source (
- XFCE_PANEL_IMAGE (plugin->first_image),
- action_entries[action].icon_name);
-
- panel_utils_set_atk_info (plugin->first_button,
- _(action_entries[action].title), NULL);
+ case PROP_ITEMS:
+ if (plugin->items != NULL)
+ xfconf_array_free (plugin->items);
+ plugin->items = g_value_dup_boxed (value);
+ actions_plugin_pack (plugin);
break;
- case PROP_SECOND_ACTION:
- /* set new value */
- action = plugin->second_action = g_value_get_uint (value);
-
- /* update button visibility and icon */
- if (action == ACTION_DISABLED)
- {
- gtk_widget_hide (plugin->second_button);
- }
- else
- {
- gtk_widget_show (plugin->second_button);
- gtk_widget_set_tooltip_text (plugin->second_button,
- _(action_entries[action].title));
- xfce_panel_image_set_from_source (
- XFCE_PANEL_IMAGE (plugin->second_image),
- action_entries[action].icon_name);
-
- panel_utils_set_atk_info (plugin->second_button,
- _(action_entries[action].title), NULL);
- }
+ case PROP_APPEARANCE:
+ plugin->type = g_value_get_uint (value);
+ actions_plugin_pack (plugin);
+ break;
- /* update plugin size */
- actions_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
- xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
+ case PROP_INVERT_ORIENTATION:
+ plugin->invert_orientation = g_value_get_boolean (value);
+ actions_plugin_pack (plugin);
+ break;
+ case PROP_ASK_CONFIRMATION:
+ plugin->ask_confirmation = g_value_get_boolean (value);
break;
default:
@@ -292,8 +369,10 @@ actions_plugin_construct (XfcePanelPlugin *panel_plugin)
ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (panel_plugin);
const PanelProperty properties[] =
{
- { "first-action", G_TYPE_UINT },
- { "second-action", G_TYPE_UINT },
+ { "items", PANEL_PROPERTIES_TYPE_VALUE_ARRAY },
+ { "appearance", G_TYPE_UINT },
+ { "invert-orientation", G_TYPE_BOOLEAN },
+ { "ask-confirmation", G_TYPE_BOOLEAN },
{ NULL }
};
@@ -305,12 +384,40 @@ actions_plugin_construct (XfcePanelPlugin *panel_plugin)
xfce_panel_plugin_get_property_base (panel_plugin),
properties, FALSE);
+ actions_plugin_pack (plugin);
+
/* set orientation and size */
actions_plugin_orientation_changed (panel_plugin,
xfce_panel_plugin_get_orientation (panel_plugin));
+}
- /* show the plugin */
- gtk_widget_show (plugin->box);
+
+
+static void
+actions_plugin_free_data (XfcePanelPlugin *panel_plugin)
+{
+ ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (panel_plugin);
+
+ if (plugin->pack_idle_id != 0)
+ g_source_remove (plugin->pack_idle_id);
+
+ if (plugin->items != NULL)
+ xfconf_array_free (plugin->items);
+
+ if (plugin->menu != NULL)
+ gtk_widget_destroy (plugin->menu);
+}
+
+
+
+static void
+actions_plugin_size_changed_child (GtkWidget *child,
+ gpointer data)
+{
+ gint size = GPOINTER_TO_INT (data);
+
+ if (!GTK_IS_SEPARATOR (child))
+ gtk_widget_set_size_request (child, size, size);
}
@@ -320,27 +427,124 @@ actions_plugin_size_changed (XfcePanelPlugin *panel_plugin,
gint size)
{
ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (panel_plugin);
- gint width = size;
- gint height = size;
+ GtkWidget *box;
+ GList *children, *li;
+ gint n_children;
+ gint child_size;
- if (plugin->second_action != ACTION_DISABLED)
+ if (plugin->type == APPEARANCE_TYPE_BUTTONS)
{
- if (xfce_panel_plugin_get_orientation (panel_plugin) ==
- GTK_ORIENTATION_HORIZONTAL)
- width /= 2;
- else
- height /= 2;
+ box = gtk_bin_get_child (GTK_BIN (plugin));
+ if (box != NULL)
+ {
+ if (plugin->invert_orientation)
+ {
+ children = gtk_container_get_children (GTK_CONTAINER (box));
+ if (G_UNLIKELY (children == NULL))
+ return TRUE;
+ n_children = g_list_length (children);
+
+ for (li = children; li != NULL; li = li->next)
+ {
+ child_size = size / n_children--;
+ size -= child_size;
+
+ gtk_widget_set_size_request (GTK_WIDGET (li->data),
+ child_size, child_size);
+ }
+ }
+ else
+ {
+ gtk_container_foreach (GTK_CONTAINER (box),
+ actions_plugin_size_changed_child,
+ GINT_TO_POINTER (size));
+ }
+ }
}
- /* set the plugin size */
- gtk_widget_set_size_request (GTK_WIDGET (panel_plugin),
- width, height);
-
return TRUE;
}
+static gboolean
+actions_plugin_configure_store (gpointer data)
+{
+ ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (data);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GPtrArray *array;
+ gboolean visible;
+ guint type;
+ GValue *val;
+
+ model = g_object_get_data (G_OBJECT (plugin), "items-store");
+ panel_return_val_if_fail (GTK_IS_LIST_STORE (model), FALSE);
+
+ array = g_ptr_array_new ();
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ for (;;)
+ {
+ gtk_tree_model_get (model, &iter,
+ COLUMN_VISIBLE, &visible,
+ COLUMN_TYPE, &type, -1);
+
+ val = g_new0 (GValue, 1);
+ g_value_init (val, G_TYPE_INT);
+ g_value_set_int (val, visible ? type : -type);
+ g_ptr_array_add (array, val);
+
+ if (!gtk_tree_model_iter_next (model, &iter))
+ break;
+ }
+ }
+
+ /* Store the new array */
+ if (plugin->items != NULL)
+ xfconf_array_free (plugin->items);
+ plugin->items = array;
+ g_object_notify (G_OBJECT (plugin), "items");
+
+ return FALSE;
+}
+
+
+
+static void
+actions_plugin_configure_store_idle (ActionsPlugin *plugin)
+{
+ g_idle_add (actions_plugin_configure_store, plugin);
+}
+
+
+
+static void
+actions_plugin_configure_visible_toggled (GtkCellRendererToggle *renderer,
+ const gchar *path_string,
+ ActionsPlugin *plugin)
+{
+ GtkTreeIter iter;
+ gboolean visible;
+ GtkTreeModel *model;
+
+ panel_return_if_fail (XFCE_IS_ACTIONS_PLUGIN (plugin));
+
+ model = g_object_get_data (G_OBJECT (plugin), "items-store");
+ panel_return_if_fail (GTK_IS_LIST_STORE (model));
+ if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
+ {
+ gtk_tree_model_get (model, &iter, COLUMN_VISIBLE, &visible, -1);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ COLUMN_VISIBLE, !visible, -1);
+
+ actions_plugin_configure_store (plugin);
+ }
+}
+
+
+
static void
actions_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
{
@@ -348,9 +552,20 @@ actions_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
GtkBuilder *builder;
GObject *dialog;
GObject *object;
+ GObject *combo;
+ ActionEntry *entry;
guint i;
+ const GValue *val;
+ gint type;
+ ActionType real_type;
+ guint n;
+ GObject *store;
+ gboolean found;
+ GtkTreeIter iter;
+ gchar *sep_str;
panel_return_if_fail (XFCE_IS_ACTIONS_PLUGIN (plugin));
+ panel_return_if_fail (plugin->items != NULL);
/* setup the dialog */
PANEL_UTILS_LINK_4UI
@@ -359,25 +574,106 @@ actions_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
if (G_UNLIKELY (builder == NULL))
return;
- /* populate the first store */
- object = gtk_builder_get_object (builder, "first-action-model");
- for (i = 1; i < G_N_ELEMENTS (action_entries); i++)
- gtk_list_store_insert_with_values (GTK_LIST_STORE (object), NULL, i - 1,
- 0, _(action_entries[i].title), -1);
+ combo = gtk_builder_get_object (builder, "combo-mode");
+ exo_mutual_binding_new (G_OBJECT (plugin), "appearance",
+ G_OBJECT (combo), "active");
+
+ object = gtk_builder_get_object (builder, "invert-orientation");
+ exo_mutual_binding_new (G_OBJECT (plugin), "invert-orientation",
+ G_OBJECT (object), "active");
+ exo_binding_new_with_negation (G_OBJECT (combo), "active",
+ G_OBJECT (object), "sensitive");
- object = gtk_builder_get_object (builder, "first-action");
- exo_mutual_binding_new (G_OBJECT (plugin), "first-action",
+ object = gtk_builder_get_object (builder, "confirmation-dialog");
+ exo_mutual_binding_new (G_OBJECT (plugin), "ask-confirmation",
G_OBJECT (object), "active");
- /* populate the second store */
- object = gtk_builder_get_object (builder, "second-action-model");
+ store = gtk_builder_get_object (builder, "items-store");
+ panel_return_if_fail (GTK_IS_LIST_STORE (store));
+ g_object_set_data (G_OBJECT (plugin), "items-store", store);
+
+ object = gtk_builder_get_object (builder, "visible-toggle");
+ panel_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (object));
+ g_signal_connect (G_OBJECT (object), "toggled",
+ G_CALLBACK (actions_plugin_configure_visible_toggled), plugin);
+
+ sep_str = g_markup_printf_escaped ("<span color='grey' style='italic'>%s</span>", _("Separator"));
+
+ /* add items from the settings */
+ for (i = 0; i < plugin->items->len; i++)
+ {
+ /* get the value and check if it is within range */
+ val = g_ptr_array_index (plugin->items, i);
+ type = g_value_get_int (val);
+ real_type = ABS (type);
+ if (type == 0 || real_type > N_ACTION_TYPES)
+ continue;
+
+ /* find the entry in the available actions */
+ entry = NULL;
+ for (n = 0; n < G_N_ELEMENTS (action_entries); n++)
+ {
+ if (action_entries[n].type == real_type)
+ {
+ entry = &action_entries[n];
+ break;
+ }
+ }
+
+ if (entry == NULL)
+ {
+ if (real_type == ACTION_TYPE_SEPARATOR)
+ {
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (store), NULL, i,
+ COLUMN_VISIBLE, type > 0,
+ COLUMN_NAME, sep_str,
+ COLUMN_TYPE, ACTION_TYPE_SEPARATOR,
+ -1);
+ }
+ }
+ else
+ {
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (store), NULL, i,
+ COLUMN_VISIBLE, type > 0,
+ COLUMN_NAME, _(entry->name),
+ COLUMN_TYPE, entry->type,
+ -1);
+ }
+ }
+
+ g_free (sep_str);
+
+ /* check if there are known actions not in the settings */
for (i = 0; i < G_N_ELEMENTS (action_entries); i++)
- gtk_list_store_insert_with_values (GTK_LIST_STORE (object), NULL, i,
- 0, _(action_entries[i].title), -1);
+ {
+ entry = &action_entries[i];
+ found = FALSE;
- object = gtk_builder_get_object (builder, "second-action");
- exo_mutual_binding_new (G_OBJECT (plugin), "second-action",
- G_OBJECT (object), "active");
+ for (n = 0; n < plugin->items->len; n++)
+ {
+ val = g_ptr_array_index (plugin->items, n);
+ type = g_value_get_int (val);
+ if (ABS (type) == (gint) entry->type)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ gtk_list_store_append (GTK_LIST_STORE (store), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ COLUMN_VISIBLE, FALSE,
+ COLUMN_NAME, _(entry->name),
+ COLUMN_TYPE, entry->type,
+ -1);
+ }
+ }
+
+ /* save on dnd changes */
+ g_signal_connect_swapped (G_OBJECT (store), "row-inserted",
+ G_CALLBACK (actions_plugin_configure_store_idle), plugin);
gtk_widget_show (GTK_WIDGET (dialog));
}
@@ -388,120 +684,479 @@ static void
actions_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
GtkOrientation orientation)
{
- ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (panel_plugin);
- GtkOrientation box_orientation;
+ actions_plugin_pack (XFCE_ACTIONS_PLUGIN (panel_plugin));
+}
- /* box orientation is opposite to the panel orientation */
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- box_orientation = GTK_ORIENTATION_VERTICAL;
- else
- box_orientation = GTK_ORIENTATION_HORIZONTAL;
- /* set orientation */
- xfce_hvbox_set_orientation (XFCE_HVBOX (plugin->box), box_orientation);
- /* update the plugin size */
- actions_plugin_size_changed (panel_plugin,
- xfce_panel_plugin_get_size (panel_plugin));
+static gboolean
+actions_plugin_action_confirmation_time (gpointer data)
+{
+ ActionTimeout *timeout = data;
+
+ panel_return_val_if_fail (timeout->entry != NULL, FALSE);
+
+ if (timeout->time_left == 0)
+ {
+ /* unattended shutdown, so don't allow apps to cancel shutdown */
+ timeout->unattended = TRUE;
+
+ gtk_dialog_response (GTK_DIALOG (timeout->dialog),
+ GTK_RESPONSE_ACCEPT);
+ }
+ else
+ {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (timeout->dialog),
+ timeout->entry->status, timeout->time_left);
+ }
+
+ return --timeout->time_left >= 0;
}
-static void
-actions_plugin_button_spawn_command (const gchar *command)
+static gboolean
+actions_plugin_action_confirmation (ActionsPlugin *plugin,
+ ActionEntry *entry,
+ gboolean *unattended)
{
- GError *error = NULL;
+ GtkWidget *dialog;
+ GtkWidget *button;
+ gint result;
+ GtkWidget *image;
+ ActionTimeout *timeout;
+ guint timeout_id;
+
+ panel_return_val_if_fail (entry->question != NULL, FALSE);
+ panel_return_val_if_fail (entry->status != NULL, FALSE);
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
+ "%s", entry->question);
+ gtk_window_set_keep_above (GTK_WINDOW (dialog), TRUE);
+ gtk_window_stick (GTK_WINDOW (dialog));
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_title (GTK_WINDOW (dialog), _(entry->name));
+
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog), _(entry->name_mnemonic), GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ image = gtk_image_new_from_icon_name (entry->icon_name, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+
+ timeout = g_slice_new0 (ActionTimeout);
+ timeout->entry = entry;
+ timeout->time_left = DEFAULT_TIMEOUT;
+ timeout->dialog = dialog;
+ timeout->unattended = FALSE;
+
+ /* first second looks out of sync with a second timer */
+ timeout_id = g_timeout_add (1000, actions_plugin_action_confirmation_time, timeout);
+ actions_plugin_action_confirmation_time (timeout);
+
+ result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (unattended != NULL)
+ *unattended = timeout->unattended;
+
+ g_source_remove (timeout_id);
+ gtk_widget_destroy (dialog);
+ g_slice_free (ActionTimeout, timeout);
+
+ return result == GTK_RESPONSE_ACCEPT;
+}
+
- if (g_getenv ("SESSION_MANAGER") == NULL)
- {
- /* TRANSLATORS: no session manager is launched, so avoid any
- * problems and ask the user to quit the panel so users without
- * xfce4-session can still close the xserver */
- if (xfce_dialog_confirm (NULL, GTK_STOCK_QUIT, NULL,
- _("You have started X without session manager. Clicking Quit will close the X server."),
- _("Are you sure you want to quit the panel?")))
- command = "xfce4-panel --quit";
- else
- return;
- }
- if (!g_spawn_command_line_async (command, &error))
+static gboolean
+actions_plugin_action_activate_dbus (ActionShutdownType type,
+ gboolean allow_save,
+ GError **error)
+{
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ gboolean retval;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+ if (connection == NULL)
+ return FALSE;
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.xfce.SessionManager",
+ "/org/xfce/SessionManager",
+ "org.xfce.Session.Manager");
+ if (G_LIKELY (proxy != NULL))
{
- xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\""), command);
- g_error_free (error);
+ retval = dbus_g_proxy_call (proxy, "Shutdown", error,
+ G_TYPE_UINT, type,
+ G_TYPE_BOOLEAN, allow_save,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+
+ g_object_unref (G_OBJECT (proxy));
}
+
+ return retval;
}
static void
-actions_plugin_button_clicked (GtkWidget *button,
- ActionsPlugin *plugin)
+actions_plugin_action_activate (GtkWidget *widget,
+ ActionsPlugin *plugin)
{
- ActionType action;
- XfceSMClient *sm_client = NULL;
-
- panel_return_if_fail (XFCE_IS_ACTIONS_PLUGIN (plugin));
-
- /* get the action to execute */
- if (button == plugin->first_button)
- action = plugin->first_action;
- else
- action = plugin->second_action;
-
-#if 0
- /* get the active session */
- /* TODO this is not implemented in XfceSMClient */
- sm_client = xfce_sm_client_get ();
- if (!xfce_sm_client_is_connected (sm_client))
- sm_client = NULL;
-#endif
+ ActionEntry *entry;
+ gboolean unattended = FALSE;
+ GError *error = NULL;
+ gboolean succeed = FALSE;
+
+ entry = g_object_get_qdata (G_OBJECT (widget), action_quark);
+ panel_return_if_fail (entry != NULL);
+
+ if (plugin->ask_confirmation
+ && entry->question != NULL
+ && entry->status != NULL
+ && !actions_plugin_action_confirmation (plugin, entry, &unattended))
+ return;
- switch (action)
+ switch (entry->type)
{
- case ACTION_DISABLED:
- /* foo */
+ case ACTION_TYPE_LOGOUT:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_LOGOUT,
+ unattended, &error);
break;
- case ACTION_LOG_OUT_DIALOG:
- if (G_LIKELY (sm_client != NULL))
- xfce_sm_client_request_shutdown (sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
- else
- actions_plugin_button_spawn_command ("xfce4-session-logout");
+ case ACTION_TYPE_LOGOUT_DIALOG:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_ASK,
+ unattended, &error);
break;
- case ACTION_LOG_OUT:
- if (G_LIKELY (sm_client != NULL))
- xfce_sm_client_request_shutdown (sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_LOGOUT);
- else
- actions_plugin_button_spawn_command ("xfce4-session-logout --logout");
+ case ACTION_TYPE_SWITCH_USER:
+ succeed = g_spawn_command_line_async ("gdmflexiserver", &error);
break;
- case ACTION_SHUT_DOWN:
- if (G_LIKELY (sm_client != NULL))
- xfce_sm_client_request_shutdown (sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_HALT);
- else
- actions_plugin_button_spawn_command ("xfce4-session-logout --halt");
+ case ACTION_TYPE_LOCK_SCREEN:
+ succeed = g_spawn_command_line_async ("xflock4", &error);
break;
- case ACTION_RESTART:
- if (G_LIKELY (sm_client != NULL))
- xfce_sm_client_request_shutdown (sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_REBOOT);
- else
- actions_plugin_button_spawn_command ("xfce4-session-logout --reboot");
+ case ACTION_TYPE_HIBERNATE:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_HIBERNATE,
+ unattended, &error);
break;
- case ACTION_LOCK_SCREEN:
- actions_plugin_button_spawn_command ("xflock4");
+ case ACTION_TYPE_SUSPEND:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_SUSPEND,
+ unattended, &error);
break;
- case ACTION_SUSPEND:
- actions_plugin_button_spawn_command ("xfce4-session-logout --suspend");
+ case ACTION_TYPE_RESTART:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_REBOOT,
+ unattended, &error);
break;
- case ACTION_HIBERNATE:
- actions_plugin_button_spawn_command ("xfce4-session-logout --hibernate");
+ case ACTION_TYPE_SHUTDOWN:
+ succeed = actions_plugin_action_activate_dbus (ACTION_SHUTDOWN_HALT,
+ unattended, &error);
break;
+
+ default:
+ panel_assert_not_reached ();
+ return;
+ }
+
+ if (!succeed)
+ {
+ xfce_dialog_show_error (NULL, error,
+ _("Failed to run action \"%s\""),
+ _(entry->name));
+ }
+}
+
+
+
+static GtkWidget *
+actions_plugin_action_button (ActionsPlugin *plugin,
+ guint type,
+ GtkOrientation orientation)
+{
+ GtkWidget *widget;
+ GtkWidget *image;
+ guint i;
+ ActionEntry *entry = NULL;
+
+ if (type == ACTION_TYPE_SEPARATOR)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ widget = gtk_vseparator_new ();
+ else
+ widget = gtk_hseparator_new ();
}
+ else
+ {
+ /* lookup the action entry */
+ for (i = 0; i < G_N_ELEMENTS (action_entries); i++)
+ if (action_entries[i].type == type)
+ entry = &action_entries[i];
+ if (entry == NULL)
+ return NULL;
+
+ widget = xfce_panel_create_button ();
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ g_object_set_qdata (G_OBJECT (widget), action_quark, entry);
+ gtk_widget_set_tooltip_text (widget, _(entry->name));
+ g_signal_connect (G_OBJECT (widget), "clicked",
+ G_CALLBACK (actions_plugin_action_activate), plugin);
+
+ image = xfce_panel_image_new_from_source (entry->icon_name);
+ gtk_container_add (GTK_CONTAINER (widget), image);
+ gtk_widget_show (image);
+ }
+
+ xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), widget);
+ return widget;
}
+
+
+static GtkWidget *
+actions_plugin_action_menu_item (ActionsPlugin *plugin,
+ guint type,
+ gint size)
+{
+ GtkWidget *mi;
+ GtkWidget *image;
+ guint i;
+ ActionEntry *entry = NULL;
+
+ if (type == ACTION_TYPE_SEPARATOR)
+ return gtk_separator_menu_item_new ();
+
+ /* lookup the action entry */
+ for (i = 0; i < G_N_ELEMENTS (action_entries); i++)
+ if (action_entries[i].type == type)
+ entry = &action_entries[i];
+ if (entry == NULL)
+ return NULL;
+
+ mi = gtk_image_menu_item_new_with_mnemonic (_(entry->name_mnemonic));
+ g_object_set_qdata (G_OBJECT (mi), action_quark, entry);
+ g_signal_connect (G_OBJECT (mi), "activate",
+ G_CALLBACK (actions_plugin_action_activate), plugin);
+
+ if (size > 0)
+ {
+ image = xfce_panel_image_new_from_source (entry->icon_name);
+ xfce_panel_image_set_size (XFCE_PANEL_IMAGE (image), size);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+ gtk_widget_show (image);
+ }
+
+ return mi;
+}
+
+
+
+static gboolean
+actions_plugin_pack_idle (gpointer data)
+{
+ ActionsPlugin *plugin = XFCE_ACTIONS_PLUGIN (data);
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *widget;
+ const gchar *username;
+ GtkWidget *child;
+ GtkWidget *box;
+ guint i;
+ const GValue *val;
+ gint type;
+ GtkOrientation orientation;
+
+ child = gtk_bin_get_child (GTK_BIN (plugin));
+ if (child != NULL)
+ gtk_widget_destroy (child);
+
+ if (plugin->menu != NULL)
+ gtk_widget_destroy (plugin->menu);
+
+ if (plugin->items == NULL)
+ plugin->items = actions_plugin_default_array ();
+
+ orientation = xfce_panel_plugin_get_orientation (XFCE_PANEL_PLUGIN (plugin));
+
+ if (plugin->type == APPEARANCE_TYPE_BUTTONS)
+ {
+ if (plugin->invert_orientation)
+ orientation = !orientation;
+ box = xfce_hvbox_new (orientation, FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (plugin), box);
+ gtk_widget_show (box);
+
+ for (i = 0; i < plugin->items->len; i++)
+ {
+ val = g_ptr_array_index (plugin->items, i);
+ type = g_value_get_int (val);
+ if (type <= 0)
+ continue;
+
+ /* skip separators when packing buttons in the opposite
+ * orientation */
+ if (plugin->invert_orientation
+ && type == ACTION_TYPE_SEPARATOR)
+ continue;
+
+ widget = actions_plugin_action_button (plugin, type, orientation);
+ if (widget != NULL)
+ {
+ gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ }
+ }
+
+ actions_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
+ xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
+ }
+ else
+ {
+ /* get a decent username, not the glib defaults */
+ username = g_get_real_name ();
+ if (exo_str_is_empty (username)
+ || strcmp (username, "Unknown") == 0)
+ {
+ username = g_get_user_name ();
+ if (exo_str_is_empty (username)
+ || strcmp (username, "somebody") == 0)
+ username = _("John Doo");
+ }
+
+ button = xfce_arrow_button_new (GTK_ARROW_NONE);
+ gtk_widget_set_name (button, "actions-button");
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), button);
+ gtk_container_add (GTK_CONTAINER (plugin), button);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (actions_plugin_menu), plugin);
+ gtk_widget_show (button);
+
+ label = gtk_label_new (username);
+ gtk_container_add (GTK_CONTAINER (button), label);
+ gtk_label_set_angle (GTK_LABEL (label),
+ orientation == GTK_ORIENTATION_HORIZONTAL ? 0 : 270);
+ gtk_widget_show (label);
+ }
+
+ return FALSE;
+}
+
+
+
+static void
+actions_plugin_pack_idle_destoyed (gpointer data)
+{
+ XFCE_ACTIONS_PLUGIN (data)->pack_idle_id = 0;
+}
+
+
+
+static void
+actions_plugin_pack (ActionsPlugin *plugin)
+{
+ if (plugin->pack_idle_id == 0)
+ {
+ plugin->pack_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, actions_plugin_pack_idle,
+ plugin, actions_plugin_pack_idle_destoyed);
+ }
+}
+
+
+
+static GPtrArray *
+actions_plugin_default_array (void)
+{
+ GPtrArray *array;
+ GValue *val;
+ guint i;
+ gint defaults[] =
+ {
+ ACTION_TYPE_LOCK_SCREEN,
+ ACTION_TYPE_SWITCH_USER,
+ ACTION_TYPE_SEPARATOR,
+ ACTION_TYPE_SUSPEND,
+ -ACTION_TYPE_HIBERNATE, /*hidden */
+ -ACTION_TYPE_SEPARATOR, /*hidden */
+ ACTION_TYPE_SHUTDOWN,
+ -ACTION_TYPE_RESTART,
+ ACTION_TYPE_SEPARATOR, /*hidden */
+ ACTION_TYPE_LOGOUT
+ };
+
+ array = g_ptr_array_sized_new (G_N_ELEMENTS (defaults));
+ for (i = 0; i < G_N_ELEMENTS (defaults); i++)
+ {
+ val = g_new0 (GValue, 1);
+ g_value_init (val, G_TYPE_INT);
+ g_value_set_int (val, defaults[i]);
+ g_ptr_array_add (array, val);
+ }
+
+ return array;
+}
+
+
+
+static void
+actions_plugin_menu_deactivate (GtkWidget *menu,
+ GtkWidget *button)
+{
+ panel_return_if_fail (button == NULL || GTK_IS_TOGGLE_BUTTON (button));
+ panel_return_if_fail (GTK_IS_MENU (menu));
+
+ /* button is NULL when we popup the menu under the cursor position */
+ if (button != NULL)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+
+ gtk_menu_popdown (GTK_MENU (menu));
+}
+
+
+
+static void
+actions_plugin_menu (GtkWidget *button,
+ ActionsPlugin *plugin)
+{
+ guint i;
+ const GValue *val;
+ gint type;
+ GtkWidget *mi;
+ gint w, h, size;
+
+ panel_return_if_fail (XFCE_IS_ACTIONS_PLUGIN (plugin));
+
+ if (plugin->menu == NULL)
+ {
+ plugin->menu = gtk_menu_new ();
+ g_signal_connect (G_OBJECT (plugin->menu), "selection-done",
+ G_CALLBACK (actions_plugin_menu_deactivate), button);
+ g_object_add_weak_pointer (G_OBJECT (plugin->menu), (gpointer) &plugin->menu);
+
+ if (gtk_icon_size_lookup (menu_icon_size, &w, &h))
+ size = MIN (w, h);
+
+ for (i = 0; i < plugin->items->len; i++)
+ {
+ val = g_ptr_array_index (plugin->items, i);
+ type = g_value_get_int (val);
+ if (type <= 0)
+ continue;
+
+ mi = actions_plugin_action_menu_item (plugin, type, size);
+ if (mi != NULL)
+ {
+ gtk_menu_shell_append (GTK_MENU_SHELL (plugin->menu), mi);
+ gtk_widget_show (mi);
+ }
+ }
+ }
+
+ gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
+ button != NULL ? xfce_panel_plugin_position_menu : NULL,
+ plugin, 1, gtk_get_current_event_time ());
+}
diff --git a/plugins/actions/actions.desktop.in b/plugins/actions/actions.desktop.in
index 52e83ad..158b024 100644
--- a/plugins/actions/actions.desktop.in
+++ b/plugins/actions/actions.desktop.in
@@ -4,4 +4,4 @@ _Name=Action Buttons
_Comment=Log out, lock or other system actions
Icon=system-log-out
X-XFCE-Module=actions
-X-XFCE-Internal=TRUE
+X-XFCE-Internal=FALSE
More information about the Xfce4-commits
mailing list