Commit b03980ec authored by Brian Tarricone's avatar Brian Tarricone
Browse files

* settings/session-editor.c: Implement a rudimentary session

	  editor.  Still a lot more to do.
	* settings/xfce4-session-marshal.list: Add marshallers for dbus
	  signals.
	* settings/xfce4-session-settings.glade: Re-enable a few widgets.
	* xfce4-session/xfsm-*-dbus.xml: Add ClientCSymbol annotations.

(Old svn revision: 28320)
parent 60bda431
2008-10-20 Brian Tarricone <bjt23@cornell.edu>
* settings/session-editor.c: Implement a rudimentary session
editor. Still a lot more to do.
* settings/xfce4-session-marshal.list: Add marshallers for dbus
signals.
* settings/xfce4-session-settings.glade: Re-enable a few widgets.
* xfce4-session/xfsm-*-dbus.xml: Add ClientCSymbol annotations.
2008-10-19 Brian Tarricone <bjt23@cornell.edu>
* settings/xfce4-session-settings.glade: Add/update a bunch of
......
......@@ -14,8 +14,12 @@ xfce4_session_settings_SOURCES = \
xfae-model.h \
xfae-window.c \
xfae-window.h \
xfce4-session-marshal.c \
xfce4-session-marshal.h \
xfce4-session-settings-common.h \
xfce4-session-settings_glade.h
xfce4-session-settings_glade.h \
xfsm-client-dbus-client.h \
xfsm-manager-dbus-client.h
xfce4_session_settings_CFLAGS = \
-DLOCALEDIR=\"$(localedir)\" \
......@@ -53,14 +57,33 @@ if MAINTAINER_MODE
BUILT_SOURCES = \
nopreview.h \
xfce4-session-settings_glade.h
xfce4-session-marshal.c \
xfce4-session-marshal.h \
xfce4-session-settings_glade.h \
xfsm-client-dbus-client.h \
xfsm-manager-dbus-client.h
nopreview.h: $(srcdir)/nopreview.png
gdk-pixbuf-csource --struct --name=nopreview $< > $@
xfce4-session-marshal.h: stamp-xfce4-session-marshal.h
@true
stamp-xfce4-session-marshal.h: xfce4-session-marshal.list Makefile
glib-genmarshal --prefix=xfce4_session_marshal --internal xfce4-session-marshal.list --header > xfce4-session-marshal.h
echo timestamp > $(@F)
xfce4-session-marshal.c: xfce4-session-marshal.list Makefile
echo '#include "xfce4-session-marshal.h"' > $@
glib-genmarshal --prefix=xfce4_session_marshal --internal xfce4-session-marshal.list --body >> xfce4-session-marshal.c
xfce4-session-settings_glade.h: xfce4-session-settings.glade
exo-csource --static --strip-comments --strip-content --name=xfce4_session_settings_glade $< >$@
xfsm-client-dbus-client.h: $(top_srcdir)/xfce4-session/xfsm-client-dbus.xml Makefile
dbus-binding-tool --mode=glib-client $(top_srcdir)/xfce4-session/xfsm-client-dbus.xml > $@
xfsm-manager-dbus-client.h: $(top_srcdir)/xfce4-session/xfsm-manager-dbus.xml Makefile
dbus-binding-tool --mode=glib-client $(top_srcdir)/xfce4-session/xfsm-manager-dbus.xml > $@
endif
......
......@@ -19,10 +19,355 @@
#include <config.h>
#endif
#include <X11/SM/SMlib.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <dbus/dbus-glib.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfcegui4/libxfcegui4.h>
#include "xfce4-session-marshal.h"
#include "xfsm-client-dbus-client.h"
#include "xfsm-manager-dbus-client.h"
#define GsmPriority "_GSM_Priority"
#define TREE_ROW_REF_KEY "--tree-row-ref"
enum
{
COL_OBJ_PATH = 0,
COL_NAME,
COL_COMMAND,
COL_RESTART_STYLE,
COL_PRIORITY,
N_COLS,
};
static DBusGConnection *dbus_conn = NULL;
static DBusGProxy *manager_dbus_proxy = NULL;
static gboolean
session_editor_ensure_dbus()
{
if(G_UNLIKELY(!dbus_conn)) {
GError *error = NULL;
dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if(!dbus_conn) {
g_critical("Unable to connect to D-Bus session bus: %s",
error ? error->message : "Unknown error");
if(error)
g_error_free(error);
}
manager_dbus_proxy = dbus_g_proxy_new_for_name(dbus_conn,
"org.xfce.SessionManager",
"/org/xfce/SessionManager",
"org.xfce.Session.Manager");
}
return !!dbus_conn;
}
static void
session_editor_sel_changed_btn(GtkTreeSelection *sel,
GtkWidget *btn)
{
GtkTreeIter iter;
gtk_widget_set_sensitive(btn, gtk_tree_selection_get_selected(sel, NULL,
&iter));
}
static void
session_editor_remove_client(GtkWidget *btn,
GtkWidget *treeview)
{
}
static void
session_editor_quit_client(GtkWidget *btn,
GtkWidget *treeview)
{
GtkTreeSelection *sel;
GtkTreeModel *model = NULL;
GtkTreeIter iter;
gchar *name = NULL, *client_op = NULL;
guchar hint = SmRestartIfRunning;
gchar *primary, *btntext;
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
if(!gtk_tree_selection_get_selected(sel, &model, &iter))
return;
gtk_tree_model_get(model, &iter,
COL_OBJ_PATH, &client_op,
COL_NAME, &name,
COL_RESTART_STYLE, &hint,
-1);
primary = g_strdup_printf(_("Are you sure you want to terminate \"%s\"?"),
name);
btntext = g_strdup_printf(_("Terminate \"%s\""), name);
if(xfce_message_dialog(GTK_WINDOW(gtk_widget_get_toplevel(treeview)),
_("Terminate Program"), GTK_STOCK_DIALOG_QUESTION,
primary,
_("The application will lose any unsaved state and will not be restarted in your next session."),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
XFCE_CUSTOM_STOCK_BUTTON, btntext, GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
NULL) == GTK_RESPONSE_ACCEPT)
{
DBusGProxy *proxy = dbus_g_proxy_new_for_name(dbus_conn,
"org.xfce.SessionManager",
client_op,
"org.xfce.Session.Client");
GError *error = NULL;
if(hint != SmRestartNever) {
GHashTable *properties = g_hash_table_new(g_str_hash, g_str_equal);
GValue val = { 0, };
g_value_init(&val, G_TYPE_UCHAR);
g_value_set_uchar(&val, SmRestartNever);
g_hash_table_insert(properties, SmRestartStyleHint, &val);
if(!xfsm_client_dbus_client_set_sm_properties(proxy, properties, &error)) {
/* FIXME: show error */
}
g_value_unset(&val);
g_hash_table_destroy(properties);
}
if(!xfsm_client_dbus_client_terminate(proxy, &error)) {
xfce_message_dialog(GTK_WINDOW(gtk_widget_get_toplevel(treeview)),
_("Terminate Program"), GTK_STOCK_DIALOG_ERROR,
_("Unable to terminate program."),
error->message,
GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
NULL);
g_error_free(error);
}
g_object_unref(proxy);
}
g_free(primary);
g_free(btntext);
g_free(client_op);
g_free(name);
}
static void
client_sm_property_changed(DBusGProxy *proxy,
const gchar *name,
const GValue *value,
gpointer user_data)
{
GtkTreeView *treeview = user_data;
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreeRowReference *rref = g_object_get_data(G_OBJECT(proxy),
TREE_ROW_REF_KEY);
GtkTreePath *path = gtk_tree_row_reference_get_path(rref);
GtkTreeIter iter;
if(!gtk_tree_model_get_iter(model, &iter, path)) {
gtk_tree_path_free(path);
return;
}
gtk_tree_path_free(path);
if(!strcmp(name, SmProgram) && G_VALUE_HOLDS_STRING(value)) {
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
COL_NAME, g_value_get_string(value),
-1);
} else if(!strcmp(name, SmRestartStyleHint) && G_VALUE_HOLDS_UCHAR(value)) {
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
COL_RESTART_STYLE, g_value_get_uchar(value),
-1);
} else if(!strcmp(name, GsmPriority) && G_VALUE_HOLDS_UCHAR(value)) {
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
COL_PRIORITY, g_value_get_uchar(value),
-1);
}
}
static void
client_state_changed(DBusGProxy *proxy,
guint old_state,
guint new_state,
gpointer user_data)
{
GtkTreeView *treeview = user_data;
if(new_state == 7) { /* disconnected. FIXME: enum this */
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreeRowReference *rref = g_object_get_data(G_OBJECT(proxy),
TREE_ROW_REF_KEY);
GtkTreePath *path;
GtkTreeIter iter;
path = gtk_tree_row_reference_get_path(rref);
if(gtk_tree_model_get_iter(model, &iter, path))
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
gtk_tree_path_free(path);
g_object_unref(proxy);
}
}
static void
manager_client_registered(DBusGProxy *proxy,
const gchar *object_path,
gpointer user_data)
{
GtkTreeView *treeview = user_data;
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreePath *path;
GtkTreeIter iter;
DBusGProxy *client_proxy;
GHashTable *properties = NULL;
const gchar *propnames[] = { SmProgram, SmRestartStyleHint, GsmPriority, NULL };
GValue *val;
const gchar *name = NULL;
guchar hint = SmRestartIfRunning, priority = 50;
GError *error = NULL;
DBG("new client at %s", object_path);
client_proxy = dbus_g_proxy_new_for_name(dbus_conn,
"org.xfce.SessionManager",
object_path,
"org.xfce.Session.Client");
if(!xfsm_client_dbus_client_get_sm_properties(client_proxy, propnames,
&properties, &error))
{
g_warning("Unable to get properties for client at %s: %s",
object_path, error->message);
g_clear_error(&error);
g_object_unref(client_proxy);
return;
}
if((val = g_hash_table_lookup(properties, SmProgram)))
name = g_value_get_string(val);
if((val = g_hash_table_lookup(properties, SmRestartStyleHint)))
hint = g_value_get_uchar(val);
if((val = g_hash_table_lookup(properties, GsmPriority)))
priority = g_value_get_uchar(val);
DBG("adding '%s', obj path %s", name, object_path);
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
COL_OBJ_PATH, object_path,
COL_NAME, name,
COL_RESTART_STYLE, hint,
COL_PRIORITY, priority,
-1);
path = gtk_tree_model_get_path(model, &iter);
g_object_set_data_full(G_OBJECT(client_proxy), TREE_ROW_REF_KEY,
gtk_tree_row_reference_new(model, path),
(GDestroyNotify)gtk_tree_row_reference_free);
gtk_tree_path_free(path);
dbus_g_proxy_add_signal(client_proxy, "SmPropertyChanged",
G_TYPE_STRING, G_TYPE_VALUE,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal(client_proxy, "SmPropertyChanged",
G_CALLBACK(client_sm_property_changed),
treeview, NULL);
/* proxy will live as long as the client does */
dbus_g_proxy_add_signal(client_proxy, "StateChanged",
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal(client_proxy, "StateChanged",
G_CALLBACK(client_state_changed), treeview,
NULL);
g_hash_table_destroy(properties);
}
static void
session_editor_populate_treeview(GtkTreeView *treeview)
{
GtkCellRenderer *render;
GtkTreeViewColumn *col;
GPtrArray *clients = NULL;
GtkListStore *ls;
gint i;
GError *error = NULL;
render = gtk_cell_renderer_text_new();
col = gtk_tree_view_column_new_with_attributes(_("Program"), render,
"text", COL_NAME,
NULL);
gtk_tree_view_append_column(treeview, col);
if(!session_editor_ensure_dbus())
return;
ls = gtk_list_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_STRING, G_TYPE_UCHAR, G_TYPE_UCHAR);
gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(ls));
g_object_unref(ls);
dbus_g_proxy_add_signal(manager_dbus_proxy, "ClientRegistered",
G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal(manager_dbus_proxy, "ClientRegistered",
G_CALLBACK(manager_client_registered),
treeview, NULL);
if(!xfsm_manager_dbus_client_list_clients(manager_dbus_proxy,
&clients, &error))
{
g_critical("Unable to query session manager for client list: %s",
error->message);
g_error_free(error);
return;
}
for(i = 0; i < clients->len; ++i) {
gchar *client_op = g_ptr_array_index(clients, i);
manager_client_registered(manager_dbus_proxy, client_op, treeview);
}
}
void
session_editor_init(GladeXML *gxml)
{
/* FIXME: implementme! */
GtkWidget *treeview, *btn_remove, *btn_quit;
GtkTreeSelection *sel;
dbus_g_object_register_marshaller(g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_object_register_marshaller(xfce4_session_marshal_VOID__STRING_BOXED,
G_TYPE_NONE, G_TYPE_STRING,
G_TYPE_VALUE, G_TYPE_INVALID);
dbus_g_object_register_marshaller(xfce4_session_marshal_VOID__UINT_UINT,
G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT,
G_TYPE_INVALID);
treeview = glade_xml_get_widget(gxml, "treeview_clients");
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
session_editor_populate_treeview(GTK_TREE_VIEW(treeview));
btn_remove = glade_xml_get_widget(gxml, "btn_remove_client");
g_signal_connect(btn_remove, "clicked",
G_CALLBACK(session_editor_remove_client), treeview);
//g_signal_connect(sel, "changed",
// G_CALLBACK(session_editor_sel_changed_btn), btn_remove);
btn_quit = glade_xml_get_widget(gxml, "btn_quit_client");
g_signal_connect(btn_quit, "clicked",
G_CALLBACK(session_editor_quit_client), treeview);
g_signal_connect(sel, "changed",
G_CALLBACK(session_editor_sel_changed_btn), btn_quit);
}
VOID:UINT,UINT
VOID:STRING,BOXED
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Sun Oct 19 14:11:48 2008 -->
<!--Generated with glade3 3.4.5 on Mon Oct 20 00:11:57 2008 -->
<glade-interface>
<requires lib="xfce4"/>
<widget class="XfceTitledDialog" id="xfce4_session_settings_dialog">
......@@ -274,40 +274,57 @@
<property name="column_spacing">12</property>
<property name="row_spacing">2</property>
<child>
<widget class="GtkLabel" id="lbl_splash_desc0">
<widget class="GtkLabel" id="lbl_splash_homepage1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Description:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_version0">
<widget class="GtkLabel" id="lbl_splash_author1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Version:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_version1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
</widget>
<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>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_author0">
<widget class="GtkLabel" id="lbl_splash_desc1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Author:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
......@@ -324,57 +341,40 @@
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_desc1">
<widget class="GtkLabel" id="lbl_splash_author0">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
<property name="label" translatable="yes">&lt;b&gt;Author:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_version1">
<widget class="GtkLabel" id="lbl_splash_version0">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
<property name="label" translatable="yes">&lt;b&gt;Version:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<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>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_author1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="lbl_splash_homepage1">
<widget class="GtkLabel" id="lbl_splash_desc0">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="selectable">True</property>
<property name="label" translatable="yes">&lt;b&gt;Description:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
</widget>
......@@ -422,7 +422,6 @@
<child>
<widget class="GtkVBox" id="vbox8">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="border_width">12</property>
<property name="spacing">6</property>
<child>
......@@ -465,7 +464,7 @@
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkTreeView" id="treeview4">
<widget class="GtkTreeView" id="treeview_clients">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
......@@ -480,8 +479,9 @@
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkButton" id="button8">
<widget class="GtkButton" id="btn_remove_client">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Remove the selected application from the session</property>
......@@ -494,8 +494,9 @@
</packing>
</child>
<child>
<widget class="GtkButton" id="button9">
<widget class="GtkButton" id="btn_quit_client">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Quit the program, and remove it from the session</property>
......@@ -543,7 +544,6 @@
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="sensitive">False</property>