]> git.meshlink.io Git - catta/blobdiff - avahi-ui/avahi-ui.c
* Don't attempt to treat Known Answer records as potentially
[catta] / avahi-ui / avahi-ui.c
index 9bbf08eb76eea3f19faf29c7d9bc7adab68907bb..402ae9ddd596a9c63164381692c34aac93133e3f 100644 (file)
@@ -23,6 +23,8 @@
 #include <config.h>
 #endif
 
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <string.h>
 #include <stdarg.h>
 #include <net/if.h>
@@ -44,9 +46,7 @@
 
 /* todo: i18n, HIGify */
 
-struct _AuiServiceDialog {
-    GtkDialog parent_instance;
-
+struct _AuiServiceDialogPrivate {
     AvahiGLibPoll *glib_poll;
     AvahiClient *client;
     AvahiServiceBrowser **browsers;
@@ -71,7 +71,6 @@ struct _AuiServiceDialog {
     GtkWidget *domain_button;
     GtkWidget *service_tree_view;
     GtkWidget *service_progress_bar;
-    GtkWidget *service_ok_button;
 
     GtkListStore *service_list_store, *domain_list_store;
 
@@ -87,6 +86,8 @@ struct _AuiServiceDialog {
     GtkWidget *domain_tree_view;
     GtkWidget *domain_progress_bar;
     GtkWidget *domain_ok_button;
+
+    gint forward_response_id;
 };
 
 enum {
@@ -124,6 +125,47 @@ static void aui_service_dialog_finalize(GObject *object);
 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
 static void aui_service_dialog_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
+static int get_default_response(GtkDialog *dlg) {
+    gint ret = GTK_RESPONSE_NONE;
+
+    if (GTK_WINDOW(dlg)->default_widget)
+        /* Use the response of the default widget, if possible */
+        ret = gtk_dialog_get_response_for_widget(dlg, GTK_WINDOW(dlg)->default_widget);
+
+    if (ret == GTK_RESPONSE_NONE) {
+        /* Fall back to finding the first positive response */
+        GList *children, *t;
+        gint bad = GTK_RESPONSE_NONE;
+        
+        t = children = gtk_container_get_children(GTK_CONTAINER(dlg->action_area));
+        
+        while (t) {
+            GtkWidget *child = t->data;
+            
+            ret = gtk_dialog_get_response_for_widget(dlg, child);
+            
+            if (ret == GTK_RESPONSE_ACCEPT ||
+                ret == GTK_RESPONSE_OK ||
+                ret == GTK_RESPONSE_YES ||
+                ret == GTK_RESPONSE_APPLY)
+                break;
+            
+            if (ret != GTK_RESPONSE_NONE && bad == GTK_RESPONSE_NONE)
+                bad = ret;
+            
+            t = t->next;
+        }
+        
+        g_list_free (children);
+
+        /* Fall back to finding the first negative response */
+        if (ret == GTK_RESPONSE_NONE)
+            ret = bad;
+    }
+
+    return ret;
+}
+
 G_DEFINE_TYPE(AuiServiceDialog, aui_service_dialog, GTK_TYPE_DIALOG)
 
 static void aui_service_dialog_class_init(AuiServiceDialogClass *klass) {
@@ -201,25 +243,71 @@ static void aui_service_dialog_class_init(AuiServiceDialogClass *klass) {
 }
 
 
-GtkWidget *aui_service_dialog_new(const gchar *title) {
-    return GTK_WIDGET(g_object_new(
-                              AUI_TYPE_SERVICE_DIALOG,
-                              "has-separator", FALSE,
-                              "title", title,
-                              NULL));
+GtkWidget *aui_service_dialog_new_valist(
+        gchar *title,
+        GtkWindow *parent,
+        const gchar *first_button_text,
+        va_list varargs) {
+    
+    const gchar *button_text;
+    gint dr;
+    
+    GtkWidget *w = GTK_WIDGET(g_object_new(
+                                      AUI_TYPE_SERVICE_DIALOG,
+                                      "has-separator", FALSE,
+                                      "title", title,
+                                      NULL));
+
+    if (parent)
+        gtk_window_set_transient_for(GTK_WINDOW(w), parent);
+
+    button_text = first_button_text;
+    while (button_text) {
+        gint response_id;
+        
+        response_id = va_arg(varargs, gint);
+        gtk_dialog_add_button(GTK_DIALOG(w), button_text, response_id);
+        button_text = va_arg(varargs, const gchar *);
+    }
+    
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT, FALSE);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_OK, FALSE);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_YES, FALSE);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_APPLY, FALSE);
+
+    if ((dr = get_default_response(GTK_DIALOG(w))) != GTK_RESPONSE_NONE)
+        gtk_dialog_set_default_response(GTK_DIALOG(w), dr);
+
+    return w;
+}
+
+GtkWidget* aui_service_dialog_new(
+        const gchar *title,
+        GtkWindow *parent,
+        const gchar *first_button_text,
+        ...) {
+
+    GtkWidget *w;
+    
+    va_list varargs;
+    va_start(varargs, first_button_text);
+    w = aui_service_dialog_new_valist((gchar*) title, parent, first_button_text, varargs);
+    va_end(varargs);
+    
+    return w;
 }
 
 static gboolean service_pulse_callback(gpointer data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
 
-    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->service_progress_bar));
+    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->service_progress_bar));
     return TRUE;
 }
 
 static gboolean domain_pulse_callback(gpointer data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
 
-    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->domain_progress_bar));
+    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->domain_progress_bar));
     return TRUE;
 }
 
@@ -260,31 +348,31 @@ static void resolve_callback(
     switch (event) {
         case AVAHI_RESOLVER_FOUND:
 
-            d->resolve_service_done = 1;
+            d->priv->resolve_service_done = 1;
 
-            g_free(d->service_name);
-            d->service_name = g_strdup(name);
+            g_free(d->priv->service_name);
+            d->priv->service_name = g_strdup(name);
 
-            g_free(d->service_type);
-            d->service_type = g_strdup(type);
+            g_free(d->priv->service_type);
+            d->priv->service_type = g_strdup(type);
 
-            g_free(d->domain);
-            d->domain = g_strdup(domain);
+            g_free(d->priv->domain);
+            d->priv->domain = g_strdup(domain);
 
-            g_free(d->host_name);
-            d->host_name = g_strdup(host_name);
+            g_free(d->priv->host_name);
+            d->priv->host_name = g_strdup(host_name);
 
-            d->port = port;
+            d->priv->port = port;
 
-            avahi_string_list_free(d->txt_data);
-            d->txt_data = avahi_string_list_copy(txt);
+            avahi_string_list_free(d->priv->txt_data);
+            d->priv->txt_data = avahi_string_list_copy(txt);
             
             if (a) {
-                d->resolve_host_name_done = 1;
-                d->address = *a;
+                d->priv->resolve_host_name_done = 1;
+                d->priv->address = *a;
             }
 
-            gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_OK);
+            gtk_dialog_response(GTK_DIALOG(d), d->priv->forward_response_id);
 
             break;
 
@@ -294,7 +382,7 @@ static void resolve_callback(
                                                   GTK_MESSAGE_ERROR,
                                                   GTK_BUTTONS_CLOSE,
                                                   "Avahi resolver failure: %s",
-                                                  avahi_strerror(avahi_client_errno(d->client)));
+                                                  avahi_strerror(avahi_client_errno(d->priv->client)));
             gtk_dialog_run(GTK_DIALOG(m));
             gtk_widget_destroy(m);
             
@@ -338,9 +426,9 @@ static void browse_callback(
             pretty_type = type;
 #endif            
             
-            gtk_list_store_append(d->service_list_store, &iter);
+            gtk_list_store_append(d->priv->service_list_store, &iter);
 
-            gtk_list_store_set(d->service_list_store, &iter,
+            gtk_list_store_set(d->priv->service_list_store, &iter,
                                SERVICE_COLUMN_IFACE, interface,
                                SERVICE_COLUMN_PROTO, protocol,
                                SERVICE_COLUMN_NAME, name,
@@ -351,28 +439,29 @@ static void browse_callback(
 
             g_free(ifs);
                     
-            if (d->common_protocol == AVAHI_PROTO_UNSPEC)
-                d->common_protocol = protocol;
+            if (d->priv->common_protocol == AVAHI_PROTO_UNSPEC)
+                d->priv->common_protocol = protocol;
 
-            if (d->common_interface == AVAHI_IF_UNSPEC)
-                d->common_interface = interface;
+            if (d->priv->common_interface == AVAHI_IF_UNSPEC)
+                d->priv->common_interface = interface;
 
-            if (d->common_interface != interface || d->common_protocol != protocol) {
-                gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->service_tree_view), 0), TRUE);
-                gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->service_tree_view), TRUE);
+            if (d->priv->common_interface != interface || d->priv->common_protocol != protocol) {
+                gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), TRUE);
+                gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), TRUE);
             }
 
-            selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->service_tree_view));
+            selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view));
             if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
 
-                if (d->service_type && d->service_name &&
-                    avahi_domain_equal(d->service_type, type) && strcasecmp(d->service_name, name) == 0) {
+                if (!d->priv->service_type ||
+                    !d->priv->service_name ||
+                    (avahi_domain_equal(d->priv->service_type, type) && strcasecmp(d->priv->service_name, name) == 0)) {
                     GtkTreePath *path;
                     
                     gtk_tree_selection_select_iter(selection, &iter);
 
-                    path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->service_list_store), &iter);
-                    gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->service_tree_view), path, NULL, FALSE);
+                    path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
+                    gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->service_tree_view), path, NULL, FALSE);
                     gtk_tree_path_free(path);
                 }
                 
@@ -385,13 +474,13 @@ static void browse_callback(
             GtkTreeIter iter;
             gboolean valid;
 
-            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->service_list_store), &iter);
+            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
             while (valid) {
                 gint _interface, _protocol;
                 gchar *_name, *_type;
                 gboolean found;
                 
-                gtk_tree_model_get(GTK_TREE_MODEL(d->service_list_store), &iter,
+                gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
                                    SERVICE_COLUMN_IFACE, &_interface,
                                    SERVICE_COLUMN_PROTO, &_protocol,
                                    SERVICE_COLUMN_NAME, &_name,
@@ -402,11 +491,11 @@ static void browse_callback(
                 g_free(_name);
 
                 if (found) {
-                    gtk_list_store_remove(d->service_list_store, &iter);
+                    gtk_list_store_remove(d->priv->service_list_store, &iter);
                     break;
                 }
                 
-                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->service_list_store), &iter);
+                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
             }
             
             break;
@@ -419,7 +508,7 @@ static void browse_callback(
                                                   GTK_BUTTONS_CLOSE,
                                                   "Browsing for service type %s in domain %s failed: %s",
                                                   type, domain,
-                                                  avahi_strerror(avahi_client_errno(d->client)));
+                                                  avahi_strerror(avahi_client_errno(d->priv->client)));
             gtk_dialog_run(GTK_DIALOG(m));
             gtk_widget_destroy(m);
 
@@ -427,10 +516,10 @@ static void browse_callback(
         }
 
         case AVAHI_BROWSER_ALL_FOR_NOW:
-            if (d->service_pulse_timeout > 0) {
-                g_source_remove(d->service_pulse_timeout);
-                d->service_pulse_timeout = 0;
-                gtk_widget_hide(d->service_progress_bar);
+            if (d->priv->service_pulse_timeout > 0) {
+                g_source_remove(d->priv->service_pulse_timeout);
+                d->priv->service_pulse_timeout = 0;
+                gtk_widget_hide(d->priv->service_progress_bar);
             }
             break;
 
@@ -442,16 +531,16 @@ static void browse_callback(
 static void domain_make_default_selection(AuiServiceDialog *d, const gchar *name, GtkTreeIter *iter) {
     GtkTreeSelection *selection;
     
-    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->domain_tree_view));
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view));
     if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
         
-        if (avahi_domain_equal(gtk_entry_get_text(GTK_ENTRY(d->domain_entry)), name)) {
+        if (avahi_domain_equal(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry)), name)) {
             GtkTreePath *path;
             
             gtk_tree_selection_select_iter(selection, iter);
             
-            path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->domain_list_store), iter);
-            gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->domain_tree_view), path, NULL, FALSE);
+            path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->domain_list_store), iter);
+            gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->domain_tree_view), path, NULL, FALSE);
             gtk_tree_path_free(path);
         }
         
@@ -476,11 +565,11 @@ static void domain_browse_callback(
             gboolean found = FALSE, valid;
             gint ref;
 
-            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->domain_list_store), &iter);
+            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
             while (valid) {
                 gchar *_name;
                 
-                gtk_tree_model_get(GTK_TREE_MODEL(d->domain_list_store), &iter,
+                gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
                                    DOMAIN_COLUMN_NAME, &_name,
                                    DOMAIN_COLUMN_REF, &ref,
                                    -1);
@@ -491,15 +580,15 @@ static void domain_browse_callback(
                 if (found)
                     break;
                 
-                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->domain_list_store), &iter);
+                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
             }
 
             if (found) 
-                gtk_list_store_set(d->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref + 1, -1);
+                gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref + 1, -1);
             else {
-                gtk_list_store_append(d->domain_list_store, &iter);
+                gtk_list_store_append(d->priv->domain_list_store, &iter);
                 
-                gtk_list_store_set(d->domain_list_store, &iter,
+                gtk_list_store_set(d->priv->domain_list_store, &iter,
                                    DOMAIN_COLUMN_NAME, name,
                                    DOMAIN_COLUMN_REF, 1,
                                    -1);
@@ -514,13 +603,13 @@ static void domain_browse_callback(
             gboolean valid;
             GtkTreeIter iter;
             
-            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->domain_list_store), &iter);
+            valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
             while (valid) {
                 gint ref;
                 gchar *_name;
                 gboolean found;
                 
-                gtk_tree_model_get(GTK_TREE_MODEL(d->domain_list_store), &iter,
+                gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
                                    DOMAIN_COLUMN_NAME, &_name,
                                    DOMAIN_COLUMN_REF, &ref,
                                    -1);
@@ -530,13 +619,13 @@ static void domain_browse_callback(
 
                 if (found) {
                     if (ref <= 1)
-                        gtk_list_store_remove(d->service_list_store, &iter);
+                        gtk_list_store_remove(d->priv->service_list_store, &iter);
                     else
-                        gtk_list_store_set(d->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref - 1, -1);
+                        gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref - 1, -1);
                     break;
                 }
                 
-                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->domain_list_store), &iter);
+                valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
             }
             
             break;
@@ -549,7 +638,7 @@ static void domain_browse_callback(
                                                   GTK_MESSAGE_ERROR,
                                                   GTK_BUTTONS_CLOSE,
                                                   "Avahi domain browser failure: %s",
-                                                  avahi_strerror(avahi_client_errno(d->client)));
+                                                  avahi_strerror(avahi_client_errno(d->priv->client)));
             gtk_dialog_run(GTK_DIALOG(m));
             gtk_widget_destroy(m);
 
@@ -557,10 +646,10 @@ static void domain_browse_callback(
         }
 
         case AVAHI_BROWSER_ALL_FOR_NOW:
-            if (d->domain_pulse_timeout > 0) {
-                g_source_remove(d->domain_pulse_timeout);
-                d->domain_pulse_timeout = 0;
-                gtk_widget_hide(d->domain_progress_bar);
+            if (d->priv->domain_pulse_timeout > 0) {
+                g_source_remove(d->priv->domain_pulse_timeout);
+                d->priv->domain_pulse_timeout = 0;
+                gtk_widget_hide(d->priv->domain_progress_bar);
             }
             break;
 
@@ -573,17 +662,18 @@ static const gchar *get_domain_name(AuiServiceDialog *d) {
     const gchar *domain;
     
     g_return_val_if_fail(d, NULL);
+    g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
     
-    if (d->domain)
-        return d->domain;
+    if (d->priv->domain)
+        return d->priv->domain;
 
-    if (!(domain = avahi_client_get_domain_name(d->client))) {
+    if (!(domain = avahi_client_get_domain_name(d->priv->client))) {
         GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
                                               GTK_DIALOG_DESTROY_WITH_PARENT,
                                               GTK_MESSAGE_ERROR,
                                               GTK_BUTTONS_CLOSE,
                                               "Failed to read Avahi domain : %s",
-                                              avahi_strerror(avahi_client_errno(d->client)));
+                                              avahi_strerror(avahi_client_errno(d->priv->client)));
         gtk_dialog_run(GTK_DIALOG(m));
         gtk_widget_destroy(m);
 
@@ -601,15 +691,15 @@ static gboolean start_callback(gpointer data) {
     unsigned i;
     const char *domain;
 
-    d->start_idle = 0;
+    d->priv->start_idle = 0;
     
-    if (!d->browse_service_types || !*d->browse_service_types) {
+    if (!d->priv->browse_service_types || !*d->priv->browse_service_types) {
         g_warning("Browse service type list is empty!");
         return FALSE;
     }
 
-    if (!d->client) {
-        if (!(d->client = avahi_client_new(avahi_glib_poll_get(d->glib_poll), 0, client_callback, d, &error))) {
+    if (!d->priv->client) {
+        if (!(d->priv->client = avahi_client_new(avahi_glib_poll_get(d->priv->glib_poll), 0, client_callback, d, &error))) {
             
             GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
                                                   GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -633,47 +723,47 @@ static gboolean start_callback(gpointer data) {
     g_assert(domain);
 
     if (avahi_domain_equal(domain, "local."))
-        gtk_label_set_markup(GTK_LABEL(d->domain_label), "Browsing for services on <b>local network</b>:");
+        gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), "Browsing for services on <b>local network</b>:");
     else {
         gchar *t = g_strdup_printf("Browsing for services in domain <b>%s</b>:", domain);
-        gtk_label_set_markup(GTK_LABEL(d->domain_label), t);
+        gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), t);
         g_free(t);
     }
     
-    if (d->browsers) {
-        for (sb = d->browsers; *sb; sb++)
+    if (d->priv->browsers) {
+        for (sb = d->priv->browsers; *sb; sb++)
             avahi_service_browser_free(*sb);
 
-        g_free(d->browsers);
-        d->browsers = NULL;
+        g_free(d->priv->browsers);
+        d->priv->browsers = NULL;
     }
 
-    gtk_list_store_clear(GTK_LIST_STORE(d->service_list_store));
-    d->common_interface = AVAHI_IF_UNSPEC;
-    d->common_protocol = AVAHI_PROTO_UNSPEC;
+    gtk_list_store_clear(GTK_LIST_STORE(d->priv->service_list_store));
+    d->priv->common_interface = AVAHI_IF_UNSPEC;
+    d->priv->common_protocol = AVAHI_PROTO_UNSPEC;
 
-    gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->service_tree_view), 0), FALSE);
-    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->service_tree_view), gtk_tree_view_column_get_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->service_tree_view), 2)));
-    gtk_widget_show(d->service_progress_bar);
+    gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), FALSE);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), gtk_tree_view_column_get_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2)));
+    gtk_widget_show(d->priv->service_progress_bar);
 
-    if (d->service_pulse_timeout <= 0)
-        d->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
+    if (d->priv->service_pulse_timeout <= 0)
+        d->priv->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
 
-    for (i = 0; d->browse_service_types[i]; i++)
+    for (i = 0; d->priv->browse_service_types[i]; i++)
         ;
     g_assert(i > 0);
 
-    d->browsers = g_new0(AvahiServiceBrowser*, i+1);
-    for (st = d->browse_service_types, sb = d->browsers; *st; st++, sb++) {
+    d->priv->browsers = g_new0(AvahiServiceBrowser*, i+1);
+    for (st = d->priv->browse_service_types, sb = d->priv->browsers; *st; st++, sb++) {
 
-        if (!(*sb = avahi_service_browser_new(d->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, *st, d->domain, 0, browse_callback, d))) {
+        if (!(*sb = avahi_service_browser_new(d->priv->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, *st, d->priv->domain, 0, browse_callback, d))) {
             GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
                                                   GTK_DIALOG_DESTROY_WITH_PARENT,
                                                   GTK_MESSAGE_ERROR,
                                                   GTK_BUTTONS_CLOSE,
                                                   "Failed to create browser for %s: %s",
                                                   *st,
-                                                  avahi_strerror(avahi_client_errno(d->client)));
+                                                  avahi_strerror(avahi_client_errno(d->priv->client)));
             gtk_dialog_run(GTK_DIALOG(m));
             gtk_widget_destroy(m);
             
@@ -689,43 +779,46 @@ static gboolean start_callback(gpointer data) {
 static void aui_service_dialog_finalize(GObject *object) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
 
-    if (d->domain_pulse_timeout > 0)
-        g_source_remove(d->domain_pulse_timeout);
+    if (d->priv->domain_pulse_timeout > 0)
+        g_source_remove(d->priv->domain_pulse_timeout);
 
-    if (d->service_pulse_timeout > 0)
-        g_source_remove(d->service_pulse_timeout);
+    if (d->priv->service_pulse_timeout > 0)
+        g_source_remove(d->priv->service_pulse_timeout);
 
-    if (d->start_idle > 0)
-        g_source_remove(d->start_idle);
+    if (d->priv->start_idle > 0)
+        g_source_remove(d->priv->start_idle);
     
-    g_free(d->host_name);
-    g_free(d->domain);
-    g_free(d->service_name);
+    g_free(d->priv->host_name);
+    g_free(d->priv->domain);
+    g_free(d->priv->service_name);
 
-    avahi_string_list_free(d->txt_data);
+    avahi_string_list_free(d->priv->txt_data);
     
-    g_strfreev(d->browse_service_types);
+    g_strfreev(d->priv->browse_service_types);
 
-    if (d->domain_browser)
-        avahi_domain_browser_free(d->domain_browser);
+    if (d->priv->domain_browser)
+        avahi_domain_browser_free(d->priv->domain_browser);
     
-    if (d->resolver)
-        avahi_service_resolver_free(d->resolver);
+    if (d->priv->resolver)
+        avahi_service_resolver_free(d->priv->resolver);
     
-    if (d->browsers) {
+    if (d->priv->browsers) {
         AvahiServiceBrowser **sb;
 
-        for (sb = d->browsers; *sb; sb++)
+        for (sb = d->priv->browsers; *sb; sb++)
             avahi_service_browser_free(*sb);
 
-        g_free(d->browsers);
+        g_free(d->priv->browsers);
     }
 
-    if (d->client)
-        avahi_client_free(d->client);
+    if (d->priv->client)
+        avahi_client_free(d->priv->client);
+
+    if (d->priv->glib_poll)
+        avahi_glib_poll_free(d->priv->glib_poll);
 
-    if (d->glib_poll)
-        avahi_glib_poll_free(d->glib_poll);
+    g_free(d->priv);
+    d->priv = NULL;
 
     G_OBJECT_CLASS(aui_service_dialog_parent_class)->finalize(object);
 }
@@ -733,21 +826,29 @@ static void aui_service_dialog_finalize(GObject *object) {
 static void service_row_activated_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
 
-    gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_OK);
+    gtk_dialog_response(GTK_DIALOG(d), get_default_response(GTK_DIALOG(d)));
 }
 
 static void service_selection_changed_callback(GtkTreeSelection *selection, gpointer user_data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
+    gboolean b;
 
-    gtk_widget_set_sensitive(d->service_ok_button, gtk_tree_selection_get_selected(selection, NULL, NULL));
+    b = gtk_tree_selection_get_selected(selection, NULL, NULL);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT, b);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_OK, b);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_YES, b);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_APPLY, b);
 }
 
 static void response_callback(GtkDialog *dialog, gint response, gpointer user_data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
 
-    if (response == GTK_RESPONSE_OK &&
-        ((d->resolve_service && !d->resolve_service_done) ||
-         (d->resolve_host_name && !d->resolve_host_name_done))) {
+    if ((response == GTK_RESPONSE_ACCEPT ||
+        response == GTK_RESPONSE_OK ||
+        response == GTK_RESPONSE_YES ||
+        response == GTK_RESPONSE_APPLY) &&
+        ((d->priv->resolve_service && !d->priv->resolve_service_done) ||
+         (d->priv->resolve_host_name && !d->priv->resolve_host_name_done))) {
         
         GtkTreeIter iter;
         gint interface, protocol;
@@ -755,36 +856,37 @@ static void response_callback(GtkDialog *dialog, gint response, gpointer user_da
         GdkCursor *cursor;
 
         g_signal_stop_emission(dialog, g_signal_lookup("response", gtk_dialog_get_type()), 0);
+        d->priv->forward_response_id = response;
 
-        if (d->resolver)
+        if (d->priv->resolver)
             return;
 
-        g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->service_tree_view)), NULL, &iter));
+        g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view)), NULL, &iter));
 
-        gtk_tree_model_get(GTK_TREE_MODEL(d->service_list_store), &iter,
+        gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
                            SERVICE_COLUMN_IFACE, &interface,
                            SERVICE_COLUMN_PROTO, &protocol,
                            SERVICE_COLUMN_NAME, &name,
                            SERVICE_COLUMN_TYPE, &type, -1);
 
-        g_return_if_fail(d->client);
+        g_return_if_fail(d->priv->client);
 
         gtk_widget_set_sensitive(GTK_WIDGET(dialog), FALSE);
         cursor = gdk_cursor_new(GDK_WATCH);
         gdk_window_set_cursor(GTK_WIDGET(dialog)->window, cursor);
         gdk_cursor_unref(cursor);
 
-        if (!(d->resolver = avahi_service_resolver_new(
-                      d->client, interface, protocol, name, type, d->domain,
-                      d->address_family, !d->resolve_host_name ? AVAHI_LOOKUP_NO_ADDRESS : 0, resolve_callback, d))) {
+        if (!(d->priv->resolver = avahi_service_resolver_new(
+                      d->priv->client, interface, protocol, name, type, d->priv->domain,
+                      d->priv->address_family, !d->priv->resolve_host_name ? AVAHI_LOOKUP_NO_ADDRESS : 0, resolve_callback, d))) {
 
             GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
                                                   GTK_DIALOG_DESTROY_WITH_PARENT,
                                                   GTK_MESSAGE_ERROR,
                                                   GTK_BUTTONS_CLOSE,
                                                   "Failed to create resolver for %s of type %s in domain %s: %s",
-                                                  name, type, d->domain,
-                                                  avahi_strerror(avahi_client_errno(d->client)));
+                                                  name, type, d->priv->domain,
+                                                  avahi_strerror(avahi_client_errno(d->priv->client)));
             gtk_dialog_run(GTK_DIALOG(m));
             gtk_widget_destroy(m);
             
@@ -811,8 +913,8 @@ static gboolean is_valid_domain_suffix(const gchar *n) {
 static void domain_row_activated_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
 
-    if (is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->domain_entry))))
-        gtk_dialog_response(GTK_DIALOG(d->domain_dialog), GTK_RESPONSE_OK);
+    if (is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))))
+        gtk_dialog_response(GTK_DIALOG(d->priv->domain_dialog), GTK_RESPONSE_ACCEPT);
 }
 
 static void domain_selection_changed_callback(GtkTreeSelection *selection, gpointer user_data) {
@@ -820,44 +922,45 @@ static void domain_selection_changed_callback(GtkTreeSelection *selection, gpoin
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
     gchar *name;
 
-    g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->domain_tree_view)), NULL, &iter));
+    g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view)), NULL, &iter));
 
-    gtk_tree_model_get(GTK_TREE_MODEL(d->domain_list_store), &iter,
+    gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
                        DOMAIN_COLUMN_NAME, &name, -1);
 
-    gtk_entry_set_text(GTK_ENTRY(d->domain_entry), name);
+    gtk_entry_set_text(GTK_ENTRY(d->priv->domain_entry), name);
 }
 
 static void domain_entry_changed_callback(GtkEditable *editable, gpointer user_data) {
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
 
-    gtk_widget_set_sensitive(d->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->domain_entry))));
+    gtk_widget_set_sensitive(d->priv->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))));
 }
 
-static void domain_button_clicked(GtkButton *button,  gpointer user_data) {
+static void domain_button_clicked(GtkButton *button, gpointer user_data) {
     GtkWidget *vbox, *vbox2, *scrolled_window;
     GtkTreeSelection *selection;
     GtkCellRenderer *renderer;
     GtkTreeViewColumn *column;
     AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
+    AuiServiceDialogPrivate *p = d->priv;
     const gchar *domain;
     GtkTreeIter iter;
 
-    g_return_if_fail(!d->domain_dialog);
-    g_return_if_fail(!d->domain_browser);
+    g_return_if_fail(!p->domain_dialog);
+    g_return_if_fail(!p->domain_browser);
 
     if (!(domain = get_domain_name(d))) {
         gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
         return;
     }
 
-    if (!(d->domain_browser = avahi_domain_browser_new(d->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, domain_browse_callback, d))) {
+    if (!(p->domain_browser = avahi_domain_browser_new(p->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, domain_browse_callback, d))) {
         GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
                                               GTK_DIALOG_DESTROY_WITH_PARENT,
                                               GTK_MESSAGE_ERROR,
                                               GTK_BUTTONS_CLOSE,
                                               "Failed to create domain browser: %s",
-                                              avahi_strerror(avahi_client_errno(d->client)));
+                                              avahi_strerror(avahi_client_errno(p->client)));
         gtk_dialog_run(GTK_DIALOG(m));
         gtk_widget_destroy(m);
         
@@ -865,20 +968,20 @@ static void domain_button_clicked(GtkButton *button,  gpointer user_data) {
         return;
     }
     
-    d->domain_dialog = gtk_dialog_new();
-    gtk_container_set_border_width(GTK_CONTAINER(d->domain_dialog), 5);
-    gtk_window_set_title(GTK_WINDOW(d->domain_dialog), "Change domain");
-    gtk_dialog_set_has_separator(GTK_DIALOG(d->domain_dialog), FALSE);
+    p->domain_dialog = gtk_dialog_new();
+    gtk_container_set_border_width(GTK_CONTAINER(p->domain_dialog), 5);
+    gtk_window_set_title(GTK_WINDOW(p->domain_dialog), "Change domain");
+    gtk_dialog_set_has_separator(GTK_DIALOG(p->domain_dialog), FALSE);
     
     vbox = gtk_vbox_new(FALSE, 8);
     gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d->domain_dialog)->vbox), vbox, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(p->domain_dialog)->vbox), vbox, TRUE, TRUE, 0);
 
-    d->domain_entry = gtk_entry_new_with_max_length(AVAHI_DOMAIN_NAME_MAX);
-    gtk_entry_set_text(GTK_ENTRY(d->domain_entry), domain);
-    gtk_entry_set_activates_default(GTK_ENTRY(d->domain_entry), TRUE);
-    g_signal_connect(d->domain_entry, "changed", G_CALLBACK(domain_entry_changed_callback), d);
-    gtk_box_pack_start(GTK_BOX(vbox), d->domain_entry, FALSE, FALSE, 0);
+    p->domain_entry = gtk_entry_new_with_max_length(AVAHI_DOMAIN_NAME_MAX);
+    gtk_entry_set_text(GTK_ENTRY(p->domain_entry), domain);
+    gtk_entry_set_activates_default(GTK_ENTRY(p->domain_entry), TRUE);
+    g_signal_connect(p->domain_entry, "changed", G_CALLBACK(domain_entry_changed_callback), d);
+    gtk_box_pack_start(GTK_BOX(vbox), p->domain_entry, FALSE, FALSE, 0);
     
     vbox2 = gtk_vbox_new(FALSE, 8);
     gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
@@ -888,98 +991,103 @@ static void domain_button_clicked(GtkButton *button,  gpointer user_data) {
     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
     gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
 
-    d->domain_list_store = gtk_list_store_new(N_DOMAIN_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
+    p->domain_list_store = gtk_list_store_new(N_DOMAIN_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
 
-    d->domain_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(d->domain_list_store));
-    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->domain_tree_view), FALSE);
-    g_signal_connect(d->domain_tree_view, "row-activated", G_CALLBACK(domain_row_activated_callback), d);
-    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->domain_tree_view));
+    p->domain_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->domain_list_store));
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->domain_tree_view), FALSE);
+    g_signal_connect(p->domain_tree_view, "row-activated", G_CALLBACK(domain_row_activated_callback), d);
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->domain_tree_view));
     gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
     g_signal_connect(selection, "changed", G_CALLBACK(domain_selection_changed_callback), d);
 
     renderer = gtk_cell_renderer_text_new();
-    column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", DOMAIN_COLUMN_NAME, NULL);
+    column = gtk_tree_view_column_new_with_attributes("Service Name", renderer, "text", DOMAIN_COLUMN_NAME, NULL);
     gtk_tree_view_column_set_expand(column, TRUE);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(d->domain_tree_view), column);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(p->domain_tree_view), column);
 
-    gtk_tree_view_set_search_column(GTK_TREE_VIEW(d->domain_tree_view), DOMAIN_COLUMN_NAME);
-    gtk_container_add(GTK_CONTAINER(scrolled_window), d->domain_tree_view);
+    gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->domain_tree_view), DOMAIN_COLUMN_NAME);
+    gtk_container_add(GTK_CONTAINER(scrolled_window), p->domain_tree_view);
 
-    d->domain_progress_bar = gtk_progress_bar_new();
-    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(d->domain_progress_bar), "Browsing ...");
-    gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(d->domain_progress_bar), 0.1);
-    gtk_box_pack_end(GTK_BOX(vbox2), d->domain_progress_bar, FALSE, FALSE, 0);
+    p->domain_progress_bar = gtk_progress_bar_new();
+    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->domain_progress_bar), "Browsing ...");
+    gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->domain_progress_bar), 0.1);
+    gtk_box_pack_end(GTK_BOX(vbox2), p->domain_progress_bar, FALSE, FALSE, 0);
     
-    gtk_dialog_add_button(GTK_DIALOG(d->domain_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
-    d->domain_ok_button = GTK_WIDGET(gtk_dialog_add_button(GTK_DIALOG(d->domain_dialog), GTK_STOCK_OK, GTK_RESPONSE_OK));
-    gtk_dialog_set_default_response(GTK_DIALOG(d->domain_dialog), GTK_RESPONSE_OK);
-    gtk_widget_set_sensitive(d->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->domain_entry))));
+    gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+    p->domain_ok_button = GTK_WIDGET(gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT));
+    gtk_dialog_set_default_response(GTK_DIALOG(p->domain_dialog), GTK_RESPONSE_ACCEPT);
+    gtk_widget_set_sensitive(p->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(p->domain_entry))));
 
-    gtk_widget_grab_default(d->domain_ok_button);
-    gtk_widget_grab_focus(d->domain_entry);
+    gtk_widget_grab_default(p->domain_ok_button);
+    gtk_widget_grab_focus(p->domain_entry);
 
-    gtk_window_set_default_size(GTK_WINDOW(d->domain_dialog), 300, 300);
+    gtk_window_set_default_size(GTK_WINDOW(p->domain_dialog), 300, 300);
     
     gtk_widget_show_all(vbox);
 
-    gtk_list_store_append(d->domain_list_store, &iter);
-    gtk_list_store_set(d->domain_list_store, &iter, DOMAIN_COLUMN_NAME, "local", DOMAIN_COLUMN_REF, 1, -1);
+    gtk_list_store_append(p->domain_list_store, &iter);
+    gtk_list_store_set(p->domain_list_store, &iter, DOMAIN_COLUMN_NAME, "local", DOMAIN_COLUMN_REF, 1, -1);
     domain_make_default_selection(d, "local", &iter);
 
-    d->domain_pulse_timeout = g_timeout_add(100, domain_pulse_callback, d);
+    p->domain_pulse_timeout = g_timeout_add(100, domain_pulse_callback, d);
     
-    if (gtk_dialog_run(GTK_DIALOG(d->domain_dialog)) == GTK_RESPONSE_OK)
-        aui_service_dialog_set_domain(d, gtk_entry_get_text(GTK_ENTRY(d->domain_entry)));
+    if (gtk_dialog_run(GTK_DIALOG(p->domain_dialog)) == GTK_RESPONSE_ACCEPT)
+        aui_service_dialog_set_domain(d, gtk_entry_get_text(GTK_ENTRY(p->domain_entry)));
 
-    gtk_widget_destroy(d->domain_dialog);
-    d->domain_dialog = NULL;
+    gtk_widget_destroy(p->domain_dialog);
+    p->domain_dialog = NULL;
 
-    if (d->domain_pulse_timeout > 0) {
-        g_source_remove(d->domain_pulse_timeout);
-        d->domain_pulse_timeout = 0;
+    if (p->domain_pulse_timeout > 0) {
+        g_source_remove(p->domain_pulse_timeout);
+        p->domain_pulse_timeout = 0;
     }
 
-    avahi_domain_browser_free(d->domain_browser);
-    d->domain_browser = NULL;
-
+    avahi_domain_browser_free(p->domain_browser);
+    p->domain_browser = NULL;
 }
 
 static void aui_service_dialog_init(AuiServiceDialog *d) {
-    GtkWidget *vbox, *vbox2, *hbox, *scrolled_window;
+    GtkWidget *vbox, *vbox2, *scrolled_window;
     GtkCellRenderer *renderer;
     GtkTreeViewColumn *column;
     GtkTreeSelection *selection;
+    AuiServiceDialogPrivate *p;
 
-    d->host_name = NULL;
-    d->domain = NULL;
-    d->service_name = NULL;
-    d->txt_data = NULL;
-    d->browse_service_types = NULL;
-    memset(&d->address, 0, sizeof(d->address));
-    d->port = 0;
-    d->resolve_host_name = d->resolve_service = TRUE;
-    d->resolve_host_name_done = d->resolve_service_done = FALSE;
-    d->address_family = AVAHI_PROTO_UNSPEC;
-
-    d->glib_poll = NULL;
-    d->client = NULL;
-    d->browsers = NULL;
-    d->resolver = NULL;
-    d->domain_browser = NULL;
-
-    d->service_pulse_timeout = 0;
-    d->domain_pulse_timeout = 0;
-    d->start_idle = 0;
-    d->common_interface = AVAHI_IF_UNSPEC;
-    d->common_protocol = AVAHI_PROTO_UNSPEC;
-
-    d->domain_dialog = NULL;
-    d->domain_entry = NULL;
-    d->domain_tree_view = NULL;
-    d->domain_progress_bar = NULL;
-    d->domain_ok_button = NULL;
-
-    d->service_list_store = d->domain_list_store = NULL;
+    p = d->priv = g_new(AuiServiceDialogPrivate, 1);
+    
+    p->host_name = NULL;
+    p->domain = NULL;
+    p->service_name = NULL;
+    p->service_type = NULL;
+    p->txt_data = NULL;
+    p->browse_service_types = NULL;
+    memset(&p->address, 0, sizeof(p->address));
+    p->port = 0;
+    p->resolve_host_name = p->resolve_service = TRUE;
+    p->resolve_host_name_done = p->resolve_service_done = FALSE;
+    p->address_family = AVAHI_PROTO_UNSPEC;
+
+    p->glib_poll = NULL;
+    p->client = NULL;
+    p->browsers = NULL;
+    p->resolver = NULL;
+    p->domain_browser = NULL;
+
+    p->service_pulse_timeout = 0;
+    p->domain_pulse_timeout = 0;
+    p->start_idle = 0;
+    p->common_interface = AVAHI_IF_UNSPEC;
+    p->common_protocol = AVAHI_PROTO_UNSPEC;
+
+    p->domain_dialog = NULL;
+    p->domain_entry = NULL;
+    p->domain_tree_view = NULL;
+    p->domain_progress_bar = NULL;
+    p->domain_ok_button = NULL;
+
+    p->forward_response_id = GTK_RESPONSE_NONE;
+
+    p->service_list_store = p->domain_list_store = NULL;
     
     gtk_widget_push_composite_child();
 
@@ -989,17 +1097,11 @@ static void aui_service_dialog_init(AuiServiceDialog *d) {
     gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d)->vbox), vbox, TRUE, TRUE, 0);
 
-    hbox = gtk_hbox_new(FALSE, 8);
-    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-    
-    d->domain_label = gtk_label_new("Initializing...");
-    gtk_label_set_ellipsize(GTK_LABEL(d->domain_label), TRUE);
-    gtk_misc_set_alignment(GTK_MISC(d->domain_label), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(hbox), d->domain_label, TRUE, TRUE, 0);
+    p->domain_label = gtk_label_new("Initializing...");
+    gtk_label_set_ellipsize(GTK_LABEL(p->domain_label), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(p->domain_label), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(vbox), p->domain_label, FALSE, FALSE, 0);
     
-    d->domain_button = gtk_button_new_with_mnemonic("Change _domain...");
-    g_signal_connect(d->domain_button, "clicked", G_CALLBACK(domain_button_clicked), d);
-    gtk_box_pack_end(GTK_BOX(hbox), d->domain_button, FALSE, TRUE, 0);
 
     vbox2 = gtk_vbox_new(FALSE, 8);
     gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
@@ -1009,45 +1111,48 @@ static void aui_service_dialog_init(AuiServiceDialog *d) {
     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
     gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
 
-    d->service_list_store = gtk_list_store_new(N_SERVICE_COLUMNS, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    p->service_list_store = gtk_list_store_new(N_SERVICE_COLUMNS, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 
-    d->service_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(d->service_list_store));
-    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->service_tree_view), FALSE);
-    g_signal_connect(d->service_tree_view, "row-activated", G_CALLBACK(service_row_activated_callback), d);
-    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->service_tree_view));
+    p->service_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->service_list_store));
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->service_tree_view), FALSE);
+    g_signal_connect(p->service_tree_view, "row-activated", G_CALLBACK(service_row_activated_callback), d);
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->service_tree_view));
     gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
     g_signal_connect(selection, "changed", G_CALLBACK(service_selection_changed_callback), d);
     
     renderer = gtk_cell_renderer_text_new();
     column = gtk_tree_view_column_new_with_attributes("Location", renderer, "text", SERVICE_COLUMN_PRETTY_IFACE, NULL);
     gtk_tree_view_column_set_visible(column, FALSE);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(d->service_tree_view), column);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
     
     renderer = gtk_cell_renderer_text_new();
     column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", SERVICE_COLUMN_NAME, NULL);
     gtk_tree_view_column_set_expand(column, TRUE);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(d->service_tree_view), column);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
 
     renderer = gtk_cell_renderer_text_new();
     column = gtk_tree_view_column_new_with_attributes("Type", renderer, "text", SERVICE_COLUMN_PRETTY_TYPE, NULL);
     gtk_tree_view_column_set_visible(column, FALSE);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(d->service_tree_view), column);
-
-    gtk_tree_view_set_search_column(GTK_TREE_VIEW(d->service_tree_view), SERVICE_COLUMN_NAME);
-    gtk_container_add(GTK_CONTAINER(scrolled_window), d->service_tree_view);
-
-    d->service_progress_bar = gtk_progress_bar_new();
-    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(d->service_progress_bar), "Browsing ...");
-    gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(d->service_progress_bar), 0.1);
-    gtk_box_pack_end(GTK_BOX(vbox2), d->service_progress_bar, FALSE, FALSE, 0);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
+
+    gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->service_tree_view), SERVICE_COLUMN_NAME);
+    gtk_container_add(GTK_CONTAINER(scrolled_window), p->service_tree_view);
+
+    p->service_progress_bar = gtk_progress_bar_new();
+    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->service_progress_bar), "Browsing ...");
+    gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->service_progress_bar), 0.1);
+    gtk_box_pack_end(GTK_BOX(vbox2), p->service_progress_bar, FALSE, FALSE, 0);
+
+    p->domain_button = gtk_button_new_with_mnemonic("_Domain..."); 
+    gtk_button_set_image(GTK_BUTTON(p->domain_button), gtk_image_new_from_stock(GTK_STOCK_NETWORK, GTK_ICON_SIZE_BUTTON)); 
+    g_signal_connect(p->domain_button, "clicked", G_CALLBACK(domain_button_clicked), d);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d)->action_area), p->domain_button, FALSE, TRUE, 0);
+    gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(GTK_DIALOG(d)->action_area), p->domain_button, TRUE);
+    gtk_widget_show(p->domain_button); 
     
-    gtk_dialog_add_button(GTK_DIALOG(d), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
-    d->service_ok_button = GTK_WIDGET(gtk_dialog_add_button(GTK_DIALOG(d), GTK_STOCK_OK, GTK_RESPONSE_OK));
-    gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_OK);
-    gtk_widget_set_sensitive(d->service_ok_button, FALSE);
+    gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
 
-    gtk_widget_grab_default(d->service_ok_button);
-    gtk_widget_grab_focus(d->service_tree_view);
+    gtk_widget_grab_focus(p->service_tree_view);
 
     gtk_window_set_default_size(GTK_WINDOW(d), 400, 300);
     
@@ -1055,10 +1160,10 @@ static void aui_service_dialog_init(AuiServiceDialog *d) {
 
     gtk_widget_pop_composite_child();
 
-    d->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
+    p->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
 
-    d->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
-    d->start_idle = g_idle_add(start_callback, d);
+    p->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
+    p->start_idle = g_idle_add(start_callback, d);
 
     g_signal_connect(d, "response", G_CALLBACK(response_callback), d);
 }
@@ -1066,8 +1171,8 @@ static void aui_service_dialog_init(AuiServiceDialog *d) {
 static void restart_browsing(AuiServiceDialog *d) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
 
-    if (d->start_idle <= 0)
-        d->start_idle = g_idle_add(start_callback, d);
+    if (d->priv->start_idle <= 0)
+        d->priv->start_idle = g_idle_add(start_callback, d);
 }
 
 void aui_service_dialog_set_browse_service_types(AuiServiceDialog *d, const char *type, ...) {
@@ -1078,7 +1183,7 @@ void aui_service_dialog_set_browse_service_types(AuiServiceDialog *d, const char
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
     g_return_if_fail(type);
 
-    g_strfreev(d->browse_service_types);
+    g_strfreev(d->priv->browse_service_types);
     
     va_copy(apcopy, ap);
     
@@ -1087,19 +1192,19 @@ void aui_service_dialog_set_browse_service_types(AuiServiceDialog *d, const char
         ;
     va_end(ap);
 
-    d->browse_service_types = g_new0(gchar*, u+1);
-    d->browse_service_types[0] = g_strdup(type);
+    d->priv->browse_service_types = g_new0(gchar*, u+1);
+    d->priv->browse_service_types[0] = g_strdup(type);
     
     va_start(apcopy, type);
     for (u = 1; (t = va_arg(apcopy, const char*)); u++)
-        d->browse_service_types[u] = g_strdup(t);
+        d->priv->browse_service_types[u] = g_strdup(t);
     va_end(apcopy);
 
-    if (d->browse_service_types[0] && d->browse_service_types[1]) {
+    if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
         /* Multiple service types, enable headers */
     
-        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->service_tree_view), TRUE);
-        gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->service_tree_view), 2), TRUE);
+        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), TRUE);
+        gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
     }
 
     restart_browsing(d);
@@ -1111,14 +1216,14 @@ void aui_service_dialog_set_browse_service_typesv(AuiServiceDialog *d, const cha
     g_return_if_fail(types);
     g_return_if_fail(*types);
 
-    g_strfreev(d->browse_service_types);
-    d->browse_service_types = g_strdupv((char**) types);
+    g_strfreev(d->priv->browse_service_types);
+    d->priv->browse_service_types = g_strdupv((char**) types);
 
-    if (d->browse_service_types[0] && d->browse_service_types[1]) {
+    if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
         /* Multiple service types, enable headers */
     
-        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->service_tree_view), TRUE);
-        gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->service_tree_view), 2), TRUE);
+        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), TRUE);
+        gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
     }
 
     restart_browsing(d);
@@ -1127,15 +1232,15 @@ void aui_service_dialog_set_browse_service_typesv(AuiServiceDialog *d, const cha
 const gchar*const* aui_service_dialog_get_browse_service_types(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
 
-    return (const char* const*) d->browse_service_types;
+    return (const char* const*) d->priv->browse_service_types;
 }
 
 void aui_service_dialog_set_domain(AuiServiceDialog *d, const char *domain) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
     g_return_if_fail(!domain || is_valid_domain_suffix(domain));
 
-    g_free(d->domain);
-    d->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
+    g_free(d->priv->domain);
+    d->priv->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
     
     restart_browsing(d);
 }
@@ -1143,98 +1248,98 @@ void aui_service_dialog_set_domain(AuiServiceDialog *d, const char *domain) {
 const char* aui_service_dialog_get_domain(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
     
-    return d->domain;
+    return d->priv->domain;
 }
 
 void aui_service_dialog_set_service_name(AuiServiceDialog *d, const char *name) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
 
-    g_free(d->service_name);
-    d->service_name = g_strdup(name);
+    g_free(d->priv->service_name);
+    d->priv->service_name = g_strdup(name);
 }
 
 const char* aui_service_dialog_get_service_name(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
 
-    return d->service_name;
+    return d->priv->service_name;
 }
 
 void aui_service_dialog_set_service_type(AuiServiceDialog *d, const char*stype) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
 
-    g_free(d->service_type);
-    d->service_type = g_strdup(stype);
+    g_free(d->priv->service_type);
+    d->priv->service_type = g_strdup(stype);
 }
 
 const char* aui_service_dialog_get_service_type(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
 
-    return d->service_type;
+    return d->priv->service_type;
 }
 
 const AvahiAddress* aui_service_dialog_get_address(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
-    g_return_val_if_fail(d->resolve_service_done && d->resolve_host_name_done, NULL);
+    g_return_val_if_fail(d->priv->resolve_service_done && d->priv->resolve_host_name_done, NULL);
 
-    return &d->address;
+    return &d->priv->address;
 }
 
 guint16 aui_service_dialog_get_port(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), 0);
-    g_return_val_if_fail(d->resolve_service_done, 0);
+    g_return_val_if_fail(d->priv->resolve_service_done, 0);
 
-    return d->port;
+    return d->priv->port;
 }
 
 const char* aui_service_dialog_get_host_name(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
-    g_return_val_if_fail(d->resolve_service_done, NULL);
+    g_return_val_if_fail(d->priv->resolve_service_done, NULL);
 
-    return d->host_name;
+    return d->priv->host_name;
 }
 
 const AvahiStringList *aui_service_dialog_get_txt_data(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
-    g_return_val_if_fail(d->resolve_service_done, NULL);
+    g_return_val_if_fail(d->priv->resolve_service_done, NULL);
 
-    return d->txt_data;
+    return d->priv->txt_data;
 }
 
 void aui_service_dialog_set_resolve_service(AuiServiceDialog *d, gboolean resolve) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
     
-    d->resolve_service = resolve;
+    d->priv->resolve_service = resolve;
 }
 
 gboolean aui_service_dialog_get_resolve_service(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
 
-    return d->resolve_service;
+    return d->priv->resolve_service;
 }
 
 void aui_service_dialog_set_resolve_host_name(AuiServiceDialog *d, gboolean resolve) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
     
-    d->resolve_host_name = resolve;
+    d->priv->resolve_host_name = resolve;
 }
 
 gboolean aui_service_dialog_get_resolve_host_name(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
 
-    return d->resolve_host_name;
+    return d->priv->resolve_host_name;
 }
 
 void aui_service_dialog_set_address_family(AuiServiceDialog *d, AvahiProtocol proto) {
     g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
     g_return_if_fail(proto == AVAHI_PROTO_UNSPEC || proto == AVAHI_PROTO_INET || proto == AVAHI_PROTO_INET6);
 
-    d->address_family = proto;
+    d->priv->address_family = proto;
 }
 
 AvahiProtocol aui_service_dialog_get_address_family(AuiServiceDialog *d) {
     g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), AVAHI_PROTO_UNSPEC);
 
-    return d->address_family;
+    return d->priv->address_family;
 }
 
 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
@@ -1308,7 +1413,7 @@ static void aui_service_dialog_get_property(GObject *object, guint prop_id, GVal
             break;
                                
         case PROP_TXT_DATA:
-            g_value_set_pointer(value, aui_service_dialog_get_txt_data(d));
+            g_value_set_pointer(value, (gpointer) aui_service_dialog_get_txt_data(d));
             break;
             
         case PROP_RESOLVE_SERVICE: