Do not set it modal as ... who knows. At least in the fully static build during
[udpgate.git] / src / ui-gnome.c
index f706abc..75182f9 100644 (file)
@@ -41,7 +41,7 @@
 
 #include "network.h"
 #include "packet.h"
-#include "startup.h"
+#include "static-startup.h"
 
 
 /* Config: */
@@ -49,6 +49,7 @@
 #define EXTERNAL_STARTUP_CHECK_INTERVAL_MS 1000
 #define PORT_RANGE_BEGIN 2048
 #define PORT_RANGE_END 10240
+#define UI_GNOME_PROBE_TIMEOUT_SEC 10
 
 
 static GnomeApp *App;
@@ -89,6 +90,9 @@ static gboolean last_daemon_running,last_daemon_running_set=FALSE;
 
 static gboolean daemon_check_timeout_func(gpointer data /* unused */)
 {
+       if (!App)       /* Quitting? */
+               return FALSE;   /* stop running */
+
        state_start_stop();
        return TRUE;    /* continue running */
 }
@@ -97,11 +101,21 @@ static gboolean external_startup_check_timeout_func(gpointer data /* unused */)
 {
 gboolean state_startup_is_on;
 
-       if (startup_query(&state_startup_is_on))
+       if (!App)       /* Quitting? */
+               return FALSE;   /* stop running */
+
+       if (static_startup_query(&state_startup_is_on))
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(AutostartCheckButton),state_startup_is_on);
        return TRUE;    /* continue running */
 }
 
+static void buttonstart(void)
+{
+       if (!optarg_port_set_string(gtk_entry_get_text(PortEntry)))
+               return;
+       network_start(optarg_port);
+}
+
 void on_PortButtonRandom_clicked(GtkButton *button,gpointer user_data)
 {
        g_return_if_fail(GTK_IS_BUTTON(button));
@@ -111,26 +125,38 @@ void on_PortButtonRandom_clicked(GtkButton *button,gpointer user_data)
                return;
        gtk_entry_set_text(PortEntry,
                        udpgate_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
+       buttonstart();
 }
 
 void on_AutostartCheckButton_toggled(GtkToggleButton *togglebutton,gpointer user_data)
 {
+static gint inside=0;
+
        g_return_if_fail(GTK_IS_TOGGLE_BUTTON(togglebutton));
 
+       /* Avoid reentrancy to prevent segfault during failed registration.
+        * FIXME: Who knows why? Some forbidden GTK recursion occurs.
+        */
+       g_assert(inside>=0);
+       if (inside)
+               return;
+       inside++;
+
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AutostartCheckButton)))
-               startup_on();
+               static_startup_on();
        else
-               startup_off();
+               static_startup_off();
        external_startup_check_timeout_func(NULL);      /* data; unused */
+
+       g_assert(inside==1);
+       inside--;
 }
 
 void on_ButtonStart_clicked(GtkButton *button,gpointer user_data)
 {
        g_return_if_fail(GTK_IS_BUTTON(button));
 
-       if (!optarg_port_set_string(gtk_entry_get_text(PortEntry)))
-               return;
-       network_start(optarg_port);
+       buttonstart();
 }
 
 void on_ButtonStop_clicked(GtkButton *button,gpointer user_data)
@@ -142,6 +168,8 @@ void on_ButtonStop_clicked(GtkButton *button,gpointer user_data)
 
 void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
 {
+GnomeApp *App_local;
+
        g_return_if_fail(GTK_IS_BUTTON(button));
 
        /* update config file */
@@ -150,16 +178,30 @@ void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
        /* Do not: gtk_main_quit();
         * as 'App' widget will quit our gtk_main() automatically.
         */
-       gtk_widget_destroy(GTK_WIDGET(App));
+       /* Do not: gtk_widget_destroy(App); App=NULL;
+        * as it would race with g_timeout_add()ed function which check
+        * 'if (!App)' first and expect there fully valid tree afterwards.
+        */
+       App_local=App;
+       App=NULL;
+       gtk_widget_destroy(GTK_WIDGET(App_local));
 }
 
 static void ui_gnome_network_notify_hostip(guint32 hostip_guint32)
 {
+       if (!App)       /* Quitting? */
+               return;
+
        if (!hostip_guint32) {
-               if (is_daemon_running()==(pid_t)-1)
+pid_t daemon_pid;
+
+               daemon_pid=is_daemon_running();
+               if ((pid_t)-1==daemon_pid)
                        gtk_entry_set_text(HostIPEntry,_("(unknown; Start the daemon)"));
-               else
+               else if (getpid()==daemon_pid)
                        gtk_entry_set_text(HostIPEntry,_("(unknown; detecting...)"));
+               else
+                       gtk_entry_set_text(HostIPEntry,_("(unknown; Kill the daemon and start your own)"));
                }
        else {
                gtk_entry_set_text(HostIPEntry,HOSTIP_GUINT32_TO_STRING(hostip_guint32));
@@ -171,6 +213,9 @@ static void ui_gnome_g_log_handler(const gchar *log_domain,GLogLevelFlags log_le
 {
 GtkWidget *dialog;
 
+       if (!App)       /* Quitting? */
+               return;
+
        /**/ if (log_level & G_LOG_LEVEL_ERROR)
                dialog=gnome_app_error(App,message);
        else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING))
@@ -178,14 +223,22 @@ GtkWidget *dialog;
        else
                dialog=gnome_app_message(App,message);
 
+       /* Do not set it modal as ... who knows. At least in the fully static
+        * build during on_AutostartCheckButton_toggled() we get reported
+        * the messages twice and application immediately gtk_main_quit()
+        * even the second (toplevel) gtk_main().
+        */
+#if 0
        gtk_window_set_modal(GTK_WINDOW(dialog),TRUE);
        g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL);
        gtk_main();
        /* 'dialog' gets destroyed automatically */
+#endif
 }
 
 static void ui_gnome_interactive(void)
 {
+       probe_timeout_sec_max=UI_GNOME_PROBE_TIMEOUT_SEC;
        gtk_main();
        network_notify_hostip=NULL;
        g_log_remove_handler(
@@ -224,11 +277,12 @@ gboolean ui_gnome_init(void)
 
        ui_gnome_network_notify_hostip(0);
        gtk_entry_set_text(PortEntry,udpgate_printf_alloca("%d",(int)optarg_port));
-       if (!startup_init()) {
-               gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(AutostartCheckButton),TRUE);
+       if (!static_startup_supported()) {
                gtk_widget_set_sensitive(GTK_WIDGET(AutostartLabel),FALSE);
                gtk_widget_set_sensitive(GTK_WIDGET(AutostartCheckButton),FALSE);
                }
+       if (!static_startup_query(NULL))
+               gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(AutostartCheckButton),TRUE);
        daemon_check_timeout_func(NULL);        /* data; unused */
        external_startup_check_timeout_func(NULL);      /* data; unused */