+
+static void
+login_to_wui (GtkWidget *widget, gpointer data)
+{
+ const char *username, *password;
+
+ username = gtk_entry_get_text (GTK_ENTRY (la_username));
+ if (STREQ (username, "")) return;
+ password = gtk_entry_get_text (GTK_ENTRY (la_password));
+
+ wui_thread_send_login (username, password);
+}
+
+/* Remove all menu items from the Connect menu. */
+static void
+remove_menu_item (GtkWidget *menu_item, gpointer data)
+{
+ gtk_container_remove (GTK_CONTAINER (connectmenu), menu_item);
+}
+
+static void
+clear_connectmenu (void)
+{
+ DEBUG ("clear Connect menu");
+ gtk_container_foreach (GTK_CONTAINER (connectmenu), remove_menu_item, NULL);
+}
+
+/* The WUI thread has changed its state to connected. */
+gboolean
+main_connected (gpointer data)
+{
+ DEBUG ("connected");
+ ASSERT_IS_MAIN_THREAD ();
+
+ gtk_label_set_text (GTK_LABEL (ca_error), NULL);
+
+ gtk_widget_hide (connection_area);
+ if (!wui_thread_is_logged_in ())
+ gtk_widget_show (login_area);
+ return FALSE;
+}
+
+/* The WUI thread has changed its state to disconnected. */
+gboolean
+main_disconnected (gpointer data)
+{
+ DEBUG ("disconnected");
+ ASSERT_IS_MAIN_THREAD ();
+
+ gtk_widget_show (connection_area);
+ gtk_widget_hide (login_area);
+
+ clear_connectmenu ();
+ gtk_menu_append (GTK_MENU (connectmenu), no_connections);
+ gtk_widget_show_all (connectmenu);
+
+ return FALSE;
+}
+
+/* The WUI thread has changed its state to logged in. */
+gboolean
+main_logged_in (gpointer data)
+{
+ DEBUG ("logged in");
+ ASSERT_IS_MAIN_THREAD ();
+
+ gtk_widget_hide (login_area);
+ return FALSE;
+}
+
+/* The WUI thread has changed its state to logged out. */
+gboolean
+main_logged_out (gpointer data)
+{
+ DEBUG ("logged out");
+ ASSERT_IS_MAIN_THREAD ();
+
+ if (wui_thread_is_connected ())
+ gtk_widget_show (login_area);
+ return FALSE;
+}
+
+/* The WUI thread has changed its state to busy. */
+gboolean
+main_busy (gpointer data)
+{
+ GdkWindow *gdk_window;
+
+ DEBUG ("busy");
+ ASSERT_IS_MAIN_THREAD ();
+
+ gdk_window = gtk_widget_get_window (window);
+ if (gdk_window) {
+ gdk_window_set_cursor (gdk_window, busy_cursor);
+ gdk_flush ();
+ }
+
+ return FALSE;
+}
+
+/* The WUI thread has changed its state to idle. */
+gboolean
+main_idle (gpointer data)
+{
+ GdkWindow *gdk_window;
+
+ DEBUG ("idle");
+ ASSERT_IS_MAIN_THREAD ();
+
+ gdk_window = gtk_widget_get_window (window);
+ if (gdk_window) {
+ gdk_window_set_cursor (gdk_window, NULL);
+ gdk_flush ();
+ }
+
+ return FALSE;
+}
+
+/* The WUI thread had a connection error. This function must
+ * free the string.
+ */
+gboolean
+main_connection_error (gpointer _str)
+{
+ char *str = (char *) _str;
+
+ DEBUG ("connection error: %s", str);
+ ASSERT_IS_MAIN_THREAD ();
+
+ gtk_label_set_text (GTK_LABEL (ca_error), str);
+ g_free (str);
+
+ return FALSE;
+}
+
+/* The WUI thread had a login error. This function must
+ * free the string.
+ */
+gboolean
+main_login_error (gpointer _str)
+{
+ char *str = (char *) _str;
+
+ DEBUG ("login error: %s", str);
+ ASSERT_IS_MAIN_THREAD ();
+
+ /*
+ gtk_label_set_text (GTK_LABEL (la_error), str);
+ */
+ g_free (str);
+
+ return FALSE;
+}
+
+/* The WUI thread reports a general status error. This function
+ * must free the string.
+ */
+gboolean
+main_status_error (gpointer _str)
+{
+ char *str = (char *) _str;
+
+ DEBUG ("status error: %s", str);
+ ASSERT_IS_MAIN_THREAD ();
+
+ /*
+ gtk_label_set_text (GTK_LABEL (...), str);
+ */
+ g_free (str);
+
+ return FALSE;
+}
+
+/* The WUI thread has updated the vm list. */
+static void
+add_vm_to_connectmenu (gpointer _vm, gpointer data)
+{
+ struct vm *vm = (struct vm *) _vm;
+ GtkWidget *item;
+
+ DEBUG ("adding %s to Connect menu", vm->description);
+
+ item = gtk_menu_item_new_with_label (vm->description);
+ gtk_menu_append (GTK_MENU (connectmenu), item);
+}
+
+gboolean
+main_vmlist_updated (gpointer data)
+{
+ GSList *vmlist;
+
+ DEBUG ("vmlist updated");
+ ASSERT_IS_MAIN_THREAD ();
+
+ /* Get the new vmlist. */
+ if (wui_thread_get_vmlist (&vmlist)) {
+ clear_connectmenu ();
+
+ gtk_menu_append (GTK_MENU (connectmenu), refresh_vmlist);
+
+ if (vmlist != NULL) {
+ gtk_menu_append (GTK_MENU (connectmenu), refresh_vmlist_separator);
+ g_slist_foreach (vmlist, add_vm_to_connectmenu, NULL);
+ }
+ free_vmlist (vmlist);
+
+ /* Grrrr Gtk is stupid. */
+ gtk_widget_show_all (connectmenu);
+ }
+
+ return FALSE;
+}