summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@jhu.edu>2007-09-04 23:44:23 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2007-09-04 23:44:23 +0000
commit243384bac597df60851980e19f02f8c7e399a5cc (patch)
treee36802bdf495903442b284cfd9c588e4e08c502e
parent72032e59f014210f7d93b3934a5bce37b18db204 (diff)
downloadgdm-243384bac597df60851980e19f02f8c7e399a5cc.tar.gz
Make the chooser kinda work.
2007-09-04 William Jon McCann <mccann@jhu.edu> * common/gdm-address.c: (gdm_address_peek_local_list): * daemon/gdm-xdmcp-display-factory.c: (do_bind), (gdm_xdmcp_send_failed): * gui/simple-chooser/chooser-main.c: (main): * gui/simple-chooser/gdm-host-chooser-widget.c: (chooser_host_add), (chooser_host_remove), (chooser_host_free), (find_known_host), (browser_add_host), (decode_packet), (do_ping), (xdmcp_discover), (find_broadcast_addresses), (add_hosts), (xdmcp_init), (gdm_host_chooser_widget_get_current_hostname), (gdm_host_chooser_widget_dispose), (gdm_host_chooser_widget_class_init), (on_host_selected), (on_row_activated), (gdm_host_chooser_widget_init): * gui/simple-chooser/gdm-host-chooser-widget.h: Make the chooser kinda work. svn path=/branches/mccann-gobject/; revision=5223
-rw-r--r--ChangeLog17
-rw-r--r--common/gdm-address.c1
-rw-r--r--daemon/gdm-xdmcp-display-factory.c4
-rw-r--r--gui/simple-chooser/chooser-main.c2
-rw-r--r--gui/simple-chooser/gdm-host-chooser-widget.c514
-rw-r--r--gui/simple-chooser/gdm-host-chooser-widget.h3
6 files changed, 488 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 74b2853e..6654cf25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2007-09-04 William Jon McCann <mccann@jhu.edu>
+
+ * common/gdm-address.c: (gdm_address_peek_local_list):
+ * daemon/gdm-xdmcp-display-factory.c: (do_bind),
+ (gdm_xdmcp_send_failed):
+ * gui/simple-chooser/chooser-main.c: (main):
+ * gui/simple-chooser/gdm-host-chooser-widget.c: (chooser_host_add),
+ (chooser_host_remove), (chooser_host_free), (find_known_host),
+ (browser_add_host), (decode_packet), (do_ping), (xdmcp_discover),
+ (find_broadcast_addresses), (add_hosts), (xdmcp_init),
+ (gdm_host_chooser_widget_get_current_hostname),
+ (gdm_host_chooser_widget_dispose),
+ (gdm_host_chooser_widget_class_init), (on_host_selected),
+ (on_row_activated), (gdm_host_chooser_widget_init):
+ * gui/simple-chooser/gdm-host-chooser-widget.h:
+ Make the chooser kinda work.
+
2007-08-31 William Jon McCann <mccann@jhu.edu>
* gui/simple-chooser/Makefile.am:
diff --git a/common/gdm-address.c b/common/gdm-address.c
index 356e9159..370d672a 100644
--- a/common/gdm-address.c
+++ b/common/gdm-address.c
@@ -305,6 +305,7 @@ gdm_address_peek_local_list (void)
hints.ai_family |= AF_INET6;
#endif
+ result = NULL;
if (getaddrinfo (hostbuf, NULL, &hints, &result) != 0) {
g_debug ("%s: Could not get address from hostname!", "gdm_peek_local_address_list");
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index 6fb91d3f..862ffb84 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -427,6 +427,8 @@ do_bind (guint port,
hints.ai_flags = AI_PASSIVE;
snprintf (strport, sizeof (strport), "%u", port);
+
+ ai_list = NULL;
if ((gaierr = getaddrinfo (NULL, strport, &hints, &ai_list)) != 0) {
g_error ("Unable to connect to socket: %s", gai_strerror (gaierr));
return -1;
@@ -2180,7 +2182,7 @@ gdm_xdmcp_send_failed (GdmXdmcpDisplayFactory *factory,
header.version = XDM_PROTOCOL_VERSION;
header.opcode = (CARD16) FAILED;
- header.length = 6+status.length;
+ header.length = 6 + status.length;
XdmcpWriteHeader (&factory->priv->buf, &header);
XdmcpWriteCARD32 (&factory->priv->buf, sessid);
diff --git a/gui/simple-chooser/chooser-main.c b/gui/simple-chooser/chooser-main.c
index 053121bb..b042274e 100644
--- a/gui/simple-chooser/chooser-main.c
+++ b/gui/simple-chooser/chooser-main.c
@@ -65,7 +65,7 @@ main (int argc, char *argv[])
gtk_init (&argc, &argv);
chooser = gdm_host_chooser_dialog_new ();
- if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) {
+ if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
char *hostname;
hostname = gdm_host_chooser_dialog_get_current_hostname (GDM_HOST_CHOOSER_DIALOG (chooser));
diff --git a/gui/simple-chooser/gdm-host-chooser-widget.c b/gui/simple-chooser/gdm-host-chooser-widget.c
index 4263d225..f7dae20b 100644
--- a/gui/simple-chooser/gdm-host-chooser-widget.c
+++ b/gui/simple-chooser/gdm-host-chooser-widget.c
@@ -1,5 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
+ * Copyright (C) 1998, 1999, 2000 Martin K, Petersen <mkp@mkp.net>
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +25,13 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
#include <X11/Xmd.h>
#include <X11/Xdmcp.h>
@@ -39,18 +46,33 @@
#define GDM_HOST_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_HOST_CHOOSER_WIDGET, GdmHostChooserWidgetPrivate))
+typedef struct _GdmChooserHost {
+ GdmAddress *address;
+ char *description;
+ gboolean willing;
+} GdmChooserHost;
+
struct GdmHostChooserWidgetPrivate
{
- GtkWidget *treeview;
+ GtkWidget *treeview;
+
+ char **hosts;
+
+ XdmcpBuffer broadcast_buf;
+ XdmcpBuffer query_buf;
+ gboolean have_ipv6;
+ int socket_fd;
+ guint io_watch_id;
+ guint scan_time_id;
+ guint ping_try_id;
- XdmcpBuffer buf;
- gboolean have_ipv6;
- int socket_fd;
- guint io_watch_id;
- guint scan_time_id;
- guint ping_try_id;
+ int ping_tries;
- int ping_tries;
+ GSList *broadcast_addresses;
+ GSList *query_addresses;
+ GSList *chooser_hosts;
+
+ GdmChooserHost *current_host;
};
enum {
@@ -58,7 +80,7 @@ enum {
};
enum {
- HOSTNAME_ACTIVATED,
+ HOST_ACTIVATED,
LAST_SIGNAL
};
@@ -70,21 +92,106 @@ static void gdm_host_chooser_widget_finalize (GObject *
G_DEFINE_TYPE (GdmHostChooserWidget, gdm_host_chooser_widget, GTK_TYPE_VBOX)
-typedef struct _XdmAuth {
- ARRAY8 authentication;
- ARRAY8 authorization;
-} XdmAuthRec, *XdmAuthPtr;
-
-static XdmAuthRec authlist = {
- { (CARD16) 0, (CARD8 *) 0 },
- { (CARD16) 0, (CARD8 *) 0 }
-};
-
#define GDM_XDMCP_PROTOCOL_VERSION 1001
#define SCAN_TIMEOUT 30000
#define PING_TIMEOUT 2000
#define PING_TRIES 3
+enum {
+ CHOOSER_LIST_ICON_COLUMN = 0,
+ CHOOSER_LIST_LABEL_COLUMN,
+ CHOOSER_LIST_HOST_COLUMN
+};
+
+static void
+chooser_host_add (GdmHostChooserWidget *widget,
+ GdmChooserHost *host)
+{
+ widget->priv->chooser_hosts = g_slist_prepend (widget->priv->chooser_hosts, host);
+}
+
+static void
+chooser_host_remove (GdmHostChooserWidget *widget,
+ GdmChooserHost *host)
+{
+ widget->priv->chooser_hosts = g_slist_remove (widget->priv->chooser_hosts, host);
+}
+
+static void
+chooser_host_free (GdmChooserHost *host)
+{
+ if (host == NULL) {
+ return;
+ }
+
+ g_free (host->description);
+ gdm_address_free (host->address);
+ g_free (host);
+}
+
+static GdmChooserHost *
+find_known_host (GdmHostChooserWidget *widget,
+ GdmAddress *address)
+{
+ GSList *li;
+ GdmChooserHost *host;
+
+ for (li = widget->priv->chooser_hosts; li != NULL; li = li->next) {
+ host = li->data;
+ if (gdm_address_equal (host->address, address)) {
+ goto out;
+ }
+ }
+
+ host = NULL;
+ out:
+
+ return host;
+}
+
+static void
+browser_add_host (GdmHostChooserWidget *widget,
+ GdmChooserHost *host)
+{
+ char *hostname;
+ char *name;
+ char *desc;
+ char *label;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean res;
+
+ g_assert (host != NULL);
+
+ if (! host->willing) {
+ gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
+ return;
+ }
+
+ res = gdm_address_get_hostname (host->address, &hostname);
+ if (! res) {
+ gdm_address_get_numeric_info (host->address, &hostname, NULL);
+ }
+
+ name = g_markup_escape_text (hostname, -1);
+ desc = g_markup_escape_text (host->description, -1);
+ label = g_strdup_printf ("<b>%s</b>\n%s", name, desc);
+ g_free (name);
+ g_free (desc);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget->priv->treeview));
+
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ CHOOSER_LIST_ICON_COLUMN, NULL,
+ CHOOSER_LIST_LABEL_COLUMN, label,
+ CHOOSER_LIST_HOST_COLUMN, host,
+ -1);
+ g_free (label);
+
+}
+
static gboolean
decode_packet (GIOChannel *source,
GIOCondition condition,
@@ -92,9 +199,18 @@ decode_packet (GIOChannel *source,
{
struct sockaddr_storage clnt_ss;
GdmAddress *address;
- gint ss_len;
+ int ss_len;
XdmcpHeader header;
int res;
+ static XdmcpBuffer buf;
+ ARRAY8 auth = {0};
+ ARRAY8 host = {0};
+ ARRAY8 stat = {0};
+ char *status;
+ GdmChooserHost *chooser_host;
+
+ status = NULL;
+ address = NULL;
g_debug ("decode_packet: GIOCondition %d", (int)condition);
@@ -103,13 +219,13 @@ decode_packet (GIOChannel *source,
}
ss_len = sizeof (clnt_ss);
- res = XdmcpFill (widget->priv->socket_fd, &widget->priv->buf, (XdmcpNetaddr)&clnt_ss, &ss_len);
+ res = XdmcpFill (widget->priv->socket_fd, &buf, (XdmcpNetaddr)&clnt_ss, &ss_len);
if G_UNLIKELY (! res) {
g_debug (_("XMCP: Could not create XDMCP buffer!"));
return TRUE;
}
- res = XdmcpReadHeader (&widget->priv->buf, &header);
+ res = XdmcpReadHeader (&buf, &header);
if G_UNLIKELY (! res) {
g_warning (_("XDMCP: Could not read XDMCP header!"));
return TRUE;
@@ -129,6 +245,56 @@ decode_packet (GIOChannel *source,
gdm_address_debug (address);
+ if (header.opcode == WILLING) {
+ if (! XdmcpReadARRAY8 (&buf, &auth)) {
+ goto done;
+ }
+
+ if (! XdmcpReadARRAY8 (&buf, &host)) {
+ goto done;
+ }
+
+ if (! XdmcpReadARRAY8 (&buf, &stat)) {
+ goto done;
+ }
+
+ status = g_strndup ((char *) stat.data, MIN (stat.length, 256));
+ } else if (header.opcode == UNWILLING) {
+ /* immaterial, will not be shown */
+ status = NULL;
+ } else {
+ goto done;
+ }
+
+ g_debug ("STATUS: %s", status);
+
+ chooser_host = find_known_host (widget, address);
+ if (chooser_host == NULL) {
+
+ chooser_host = g_new0 (GdmChooserHost, 1);
+ chooser_host->address = gdm_address_copy (address);
+ chooser_host->description = g_strdup (status);
+ chooser_host->willing = (header.opcode == WILLING);
+ chooser_host_add (widget, chooser_host);
+ browser_add_host (widget, chooser_host);
+ } else {
+ /* server changed it's mind */
+ if (header.opcode == WILLING && ! chooser_host->willing) {
+ chooser_host->willing = TRUE;
+ browser_add_host (widget, chooser_host);
+ }
+ }
+
+ done:
+ if (header.opcode == WILLING) {
+ XdmcpDisposeARRAY8 (&auth);
+ XdmcpDisposeARRAY8 (&host);
+ XdmcpDisposeARRAY8 (&stat);
+ }
+
+ g_free (status);
+ gdm_address_free (address);
+
return TRUE;
}
@@ -136,7 +302,45 @@ static void
do_ping (GdmHostChooserWidget *widget,
gboolean full)
{
+ GSList *l;
+
g_debug ("do ping full:%d", full);
+
+ for (l = widget->priv->broadcast_addresses; l != NULL; l = l->next) {
+ GdmAddress *address;
+ int res;
+
+ address = l->data;
+
+ gdm_address_debug (address);
+ errno = 0;
+ g_debug ("fd:%d", widget->priv->socket_fd);
+ res = XdmcpFlush (widget->priv->socket_fd,
+ &widget->priv->broadcast_buf,
+ (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
+ (int)sizeof (struct sockaddr_storage));
+ if (! res) {
+ g_warning ("Unable to flush the XDMCP broadcast packet: %s", g_strerror (errno));
+ }
+ }
+
+ if (full) {
+ for (l = widget->priv->query_addresses; l != NULL; l = l->next) {
+ GdmAddress *address;
+ int res;
+
+ address = l->data;
+
+ gdm_address_debug (address);
+ res = XdmcpFlush (widget->priv->socket_fd,
+ &widget->priv->query_buf,
+ (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
+ (int)sizeof (struct sockaddr_storage));
+ if (! res) {
+ g_warning ("Unable to flush the XDMCP query packet");
+ }
+ }
+ }
}
static gboolean
@@ -192,17 +396,150 @@ xdmcp_discover (GdmHostChooserWidget *widget)
}
widget->priv->ping_try_id = g_timeout_add (PING_TIMEOUT,
- ping_try,
+ (GSourceFunc)ping_try,
widget);
}
+/* Find broadcast address for all active, non pointopoint interfaces */
+static void
+find_broadcast_addresses (GdmHostChooserWidget *widget)
+{
+ int i;
+ int num;
+ int sock;
+ struct ifconf ifc;
+ char *buf;
+ struct ifreq *ifr;
+
+ g_debug ("Finding broadcast addresses");
+
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+#ifdef SIOCGIFNUM
+ if (ioctl (sock, SIOCGIFNUM, &num) < 0) {
+ num = 64;
+ }
+#else
+ num = 64;
+#endif
+
+ ifc.ifc_len = sizeof (struct ifreq) * num;
+ ifc.ifc_buf = buf = g_malloc0 (ifc.ifc_len);
+ if (ioctl (sock, SIOCGIFCONF, &ifc) < 0) {
+ g_warning ("Could not get local addresses!");
+ goto out;
+ }
+
+ ifr = ifc.ifc_req;
+ num = ifc.ifc_len / sizeof (struct ifreq);
+ for (i = 0 ; i < num ; i++) {
+ const char *name;
+
+ name = ifr[i].ifr_name;
+ g_debug ("Checking if %s", name);
+ if (name != NULL && name[0] != '\0') {
+ struct ifreq ifreq;
+ GdmAddress *address;
+ struct sockaddr_in sin;
+
+ memset (&ifreq, 0, sizeof (ifreq));
+
+ strncpy (ifreq.ifr_name,
+ ifr[i].ifr_name,
+ sizeof (ifreq.ifr_name));
+ /* paranoia */
+ ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0';
+
+ if (ioctl (sock, SIOCGIFFLAGS, &ifreq) < 0) {
+ g_warning ("Could not get SIOCGIFFLAGS for %s", ifr[i].ifr_name);
+ }
+
+ if ((ifreq.ifr_flags & IFF_UP) == 0 ||
+ (ifreq.ifr_flags & IFF_BROADCAST) == 0 ||
+ ioctl (sock, SIOCGIFBRDADDR, &ifreq) < 0) {
+ g_debug ("Skipping if %s", name);
+ continue;
+ }
+
+ g_memmove (&sin, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
+ sin.sin_port = htons (XDM_UDP_PORT);
+ address = gdm_address_new_from_sockaddr_storage ((struct sockaddr_storage *)&sin);
+ if (address != NULL) {
+ g_debug ("Adding if %s", name);
+ gdm_address_debug (address);
+
+ widget->priv->broadcast_addresses = g_slist_append (widget->priv->broadcast_addresses, address);
+ }
+ }
+ }
+ out:
+ g_free (buf);
+ close (sock);
+}
+
+static void
+add_hosts (GdmHostChooserWidget *widget)
+{
+ int i;
+
+ for (i = 0; widget->priv->hosts != NULL && widget->priv->hosts[i] != NULL; i++) {
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct addrinfo *ai;
+ int gaierr;
+ const char *name;
+ char serv_buf [NI_MAXSERV];
+ const char *serv;
+
+ name = widget->priv->hosts[i];
+
+ if (strcmp (name, "BROADCAST") == 0) {
+ find_broadcast_addresses (widget);
+ continue;
+ }
+
+ if (strcmp (name, "MULTICAST") == 0) {
+ /*gdm_chooser_find_mcaddr ();*/
+ continue;
+ }
+
+ result = NULL;
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = SOCK_STREAM;
+
+ snprintf (serv_buf, sizeof (serv_buf), "%u", XDM_UDP_PORT);
+ serv = serv_buf;
+
+ gaierr = getaddrinfo (name, serv, &hints, &result);
+ if (gaierr != 0) {
+ g_warning ("Unable to get address info for name %s: %s", name, gai_strerror (gaierr));
+ continue;
+ }
+
+ for (ai = result; ai != NULL; ai = ai->ai_next) {
+ GdmAddress *address;
+
+ address = gdm_address_new_from_sockaddr_storage ((struct sockaddr_storage *)ai->ai_addr);
+ if (address != NULL) {
+ widget->priv->query_addresses = g_slist_append (widget->priv->query_addresses, address);
+ }
+ }
+
+ freeaddrinfo (result);
+ }
+
+ if (widget->priv->broadcast_addresses == NULL && widget->priv->query_addresses == NULL) {
+ find_broadcast_addresses (widget);
+ }
+}
+
static void
xdmcp_init (GdmHostChooserWidget *widget)
{
- static XdmcpHeader header;
- int sockopts;
- int res;
- GIOChannel *ioc;
+ XdmcpHeader header;
+ int sockopts;
+ int res;
+ GIOChannel *ioc;
+ ARRAYofARRAY8 aanames;
sockopts = 1;
@@ -232,28 +569,32 @@ xdmcp_init (GdmHostChooserWidget *widget)
}
/* Assemble XDMCP BROADCAST_QUERY packet in static buffer */
+ memset (&header, 0, sizeof (XdmcpHeader));
header.opcode = (CARD16) BROADCAST_QUERY;
header.length = 1;
header.version = XDM_PROTOCOL_VERSION;
- XdmcpWriteHeader (&widget->priv->buf, &header);
- XdmcpWriteARRAY8 (&widget->priv->buf, &authlist.authentication);
+ aanames.length = 0;
+ XdmcpWriteHeader (&widget->priv->broadcast_buf, &header);
+ XdmcpWriteARRAYofARRAY8 (&widget->priv->broadcast_buf, &aanames);
/* Assemble XDMCP QUERY packet in static buffer */
+ memset (&header, 0, sizeof (XdmcpHeader));
header.opcode = (CARD16) QUERY;
header.length = 1;
header.version = XDM_PROTOCOL_VERSION;
- XdmcpWriteHeader (&widget->priv->buf, &header);
- XdmcpWriteARRAY8 (&widget->priv->buf, &authlist.authentication);
+ memset (&widget->priv->query_buf, 0, sizeof (XdmcpBuffer));
+ XdmcpWriteHeader (&widget->priv->query_buf, &header);
+ XdmcpWriteARRAYofARRAY8 (&widget->priv->query_buf, &aanames);
- /*gdm_chooser_add_hosts (hosts);*/
+ add_hosts (widget);
ioc = g_io_channel_unix_new (widget->priv->socket_fd);
g_io_channel_set_encoding (ioc, NULL, NULL);
g_io_channel_set_buffered (ioc, FALSE);
- widget->priv->io_watch_id = g_io_add_watch(ioc,
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc)decode_packet,
- widget);
+ widget->priv->io_watch_id = g_io_add_watch (ioc,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc)decode_packet,
+ widget);
g_io_channel_unref (ioc);
xdmcp_discover (widget);
@@ -273,6 +614,9 @@ gdm_host_chooser_widget_get_current_hostname (GdmHostChooserWidget *widget)
g_return_val_if_fail (GDM_IS_HOST_CHOOSER_WIDGET (widget), NULL);
hostname = NULL;
+ if (widget->priv->current_host != NULL) {
+ gdm_address_get_hostname (widget->priv->current_host->address, &hostname);
+ }
return hostname;
}
@@ -331,12 +675,36 @@ gdm_host_chooser_widget_constructor (GType type,
static void
gdm_host_chooser_widget_dispose (GObject *object)
{
- GdmHostChooserWidget *host_chooser_widget;
+ GdmHostChooserWidget *widget;
- host_chooser_widget = GDM_HOST_CHOOSER_WIDGET (object);
+ widget = GDM_HOST_CHOOSER_WIDGET (object);
g_debug ("Disposing host_chooser_widget");
+ if (widget->priv->broadcast_addresses != NULL) {
+ g_slist_foreach (widget->priv->broadcast_addresses,
+ (GFunc)gdm_address_free,
+ NULL);
+ g_slist_free (widget->priv->broadcast_addresses);
+ widget->priv->broadcast_addresses = NULL;
+ }
+ if (widget->priv->query_addresses != NULL) {
+ g_slist_foreach (widget->priv->query_addresses,
+ (GFunc)gdm_address_free,
+ NULL);
+ g_slist_free (widget->priv->query_addresses);
+ widget->priv->query_addresses = NULL;
+ }
+ if (widget->priv->chooser_hosts != NULL) {
+ g_slist_foreach (widget->priv->chooser_hosts,
+ (GFunc)chooser_host_free,
+ NULL);
+ g_slist_free (widget->priv->chooser_hosts);
+ widget->priv->chooser_hosts = NULL;
+ }
+
+ widget->priv->current_host = NULL;
+
G_OBJECT_CLASS (gdm_host_chooser_widget_parent_class)->dispose (object);
}
@@ -351,32 +719,52 @@ gdm_host_chooser_widget_class_init (GdmHostChooserWidgetClass *klass)
object_class->dispose = gdm_host_chooser_widget_dispose;
object_class->finalize = gdm_host_chooser_widget_finalize;
- signals [HOSTNAME_ACTIVATED] = g_signal_new ("hostname-activated",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GdmHostChooserWidgetClass, hostname_activated),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1, G_TYPE_STRING);
+ signals [HOST_ACTIVATED] = g_signal_new ("host-activated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdmHostChooserWidgetClass, host_activated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
g_type_class_add_private (klass, sizeof (GdmHostChooserWidgetPrivate));
}
static void
+on_host_selected (GtkTreeSelection *selection,
+ GdmHostChooserWidget *widget)
+{
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter = {0};
+ GdmChooserHost *curhost;
+
+ curhost = NULL;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ gtk_tree_model_get (model, &iter, CHOOSER_LIST_HOST_COLUMN, &curhost, -1);
+ }
+
+ widget->priv->current_host = curhost;
+}
+
+static void
on_row_activated (GtkTreeView *tree_view,
GtkTreePath *tree_path,
GtkTreeViewColumn *tree_column,
GdmHostChooserWidget *widget)
{
+ g_signal_emit (widget, signals[HOST_ACTIVATED], 0);
}
-
static void
gdm_host_chooser_widget_init (GdmHostChooserWidget *widget)
{
- GtkWidget *scrolled;
+ GtkWidget *scrolled;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *model;
widget->priv = GDM_HOST_CHOOSER_WIDGET_GET_PRIVATE (widget);
@@ -395,6 +783,34 @@ gdm_host_chooser_widget_init (GdmHostChooserWidget *widget)
widget);
gtk_container_add (GTK_CONTAINER (scrolled), widget->priv->treeview);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (on_host_selected),
+ widget);
+
+ model = (GtkTreeModel *)gtk_list_store_new (3,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget->priv->treeview), model);
+
+ column = gtk_tree_view_column_new_with_attributes ("Icon",
+ gtk_cell_renderer_pixbuf_new (),
+ "pixbuf", CHOOSER_LIST_ICON_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->treeview), column);
+
+ column = gtk_tree_view_column_new_with_attributes ("Hostname",
+ gtk_cell_renderer_text_new (),
+ "markup", CHOOSER_LIST_LABEL_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->treeview), column);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+ CHOOSER_LIST_LABEL_COLUMN,
+ GTK_SORT_ASCENDING);
+
xdmcp_init (widget);
}
diff --git a/gui/simple-chooser/gdm-host-chooser-widget.h b/gui/simple-chooser/gdm-host-chooser-widget.h
index 7b74bef0..9aea0374 100644
--- a/gui/simple-chooser/gdm-host-chooser-widget.h
+++ b/gui/simple-chooser/gdm-host-chooser-widget.h
@@ -46,8 +46,7 @@ typedef struct
GtkVBoxClass parent_class;
/* signals */
- void (* hostname_activated) (GdmHostChooserWidget *widget,
- const char *hostname);
+ void (* host_activated) (GdmHostChooserWidget *widget);
} GdmHostChooserWidgetClass;
GType gdm_host_chooser_widget_get_type (void);