diff options
author | William Jon McCann <mccann@jhu.edu> | 2007-09-04 23:44:23 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2007-09-04 23:44:23 +0000 |
commit | 243384bac597df60851980e19f02f8c7e399a5cc (patch) | |
tree | e36802bdf495903442b284cfd9c588e4e08c502e | |
parent | 72032e59f014210f7d93b3934a5bce37b18db204 (diff) | |
download | gdm-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-- | ChangeLog | 17 | ||||
-rw-r--r-- | common/gdm-address.c | 1 | ||||
-rw-r--r-- | daemon/gdm-xdmcp-display-factory.c | 4 | ||||
-rw-r--r-- | gui/simple-chooser/chooser-main.c | 2 | ||||
-rw-r--r-- | gui/simple-chooser/gdm-host-chooser-widget.c | 514 | ||||
-rw-r--r-- | gui/simple-chooser/gdm-host-chooser-widget.h | 3 |
6 files changed, 488 insertions, 53 deletions
@@ -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); |