tProvide glib event loop equivalents for Windows - vaccinewars - be a doctor an… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 54b9e74c81e0dc4bb786f7de94d96bda1569e101 | |
parent 9041057b524e7631a4095a3ad36f12bd0c337e81 | |
Author: Ben Webb <[email protected]> | |
Date: Wed, 11 Nov 2020 15:25:04 -0800 | |
Provide glib event loop equivalents for Windows | |
We use the glib event loop to handle metaserver socket events | |
on Unix (g_timeout_add, g_io_add_watch, g_source_remove). | |
These functions don't do anything on Windows because we use | |
tthe Windows event loop instead. Provide dp_* equivalents | |
which, on Windows, tie into the Windows event loop instead. | |
This should make metaserver connections work again on Windows | |
from the GUI client and server. Closes #48. | |
Diffstat: | |
M src/gtkport/gtkport.c | 116 ++++++++++++++++++++++++++++++ | |
M src/gtkport/gtkport.h | 6 ++++++ | |
M src/gui_client/newgamedia.c | 2 +- | |
M src/network.c | 10 +++++----- | |
M src/network.h | 9 +++++++++ | |
M src/serverside.c | 2 +- | |
6 files changed, 138 insertions(+), 7 deletions(-) | |
--- | |
diff --git a/src/gtkport/gtkport.c b/src/gtkport/gtkport.c | |
t@@ -254,6 +254,21 @@ struct _GtkTimeout { | |
guint id; | |
}; | |
+struct _OurSource { | |
+ guint id; /* Unique identifier */ | |
+ | |
+ /* Used for timeouts (dp_g_timeout_add()) */ | |
+ GSourceFunc timeout_function; | |
+ | |
+ /* Used for IO channels (dp_g_io_watch()) */ | |
+ GIOChannel *io_channel; | |
+ GIOFunc io_function; | |
+ int socket; | |
+ | |
+ gpointer data; /* Data passed to callback function */ | |
+}; | |
+typedef struct _OurSource OurSource; | |
+ | |
typedef struct _GtkItemFactoryChild GtkItemFactoryChild; | |
struct _GtkItemFactoryChild { | |
t@@ -638,6 +653,7 @@ HFONT defFont; | |
static HFONT urlFont; | |
static GSList *WindowList = NULL; | |
static GSList *GdkInputs = NULL; | |
+static GSList *OurSources = NULL; | |
static GSList *GtkTimeouts = NULL; | |
static HWND TopLevel = NULL; | |
t@@ -663,6 +679,7 @@ static void DispatchSocketEvent(SOCKET sock, long event) | |
{ | |
GSList *list; | |
GdkInput *input; | |
+ OurSource *s; | |
for (list = GdkInputs; list; list = g_slist_next(list)) { | |
input = (GdkInput *)(list->data); | |
t@@ -675,11 +692,23 @@ static void DispatchSocketEvent(SOCKET sock, long event) | |
break; | |
} | |
} | |
+ for (list = OurSources; list; list = g_slist_next(list)) { | |
+ s = (OurSource *)(list->data); | |
+ if (s->socket == sock) { | |
+ (*s->io_function) (s->io_channel, | |
+ (event & (FD_READ | FD_CLOSE | FD_ACCEPT) ? | |
+ G_IO_IN : 0) | | |
+ (event & (FD_WRITE | FD_CONNECT) ? | |
+ G_IO_OUT : 0), s->data); | |
+ break; | |
+ } | |
+ } | |
} | |
static void DispatchTimeoutEvent(UINT id) | |
{ | |
GSList *list; | |
+ OurSource *s; | |
GtkTimeout *timeout; | |
for (list = GtkTimeouts; list; list = g_slist_next(list)) { | |
t@@ -693,6 +722,17 @@ static void DispatchTimeoutEvent(UINT id) | |
break; | |
} | |
} | |
+ for (list = OurSources; list; list = g_slist_next(list)) { | |
+ s = (OurSource *)list->data; | |
+ if (s->id == id) { | |
+ if (s->timeout_function) { | |
+ if (!(*s->timeout_function) (s->data)) { | |
+ dp_g_source_remove(s->id); | |
+ } | |
+ } | |
+ break; | |
+ } | |
+ } | |
} | |
static HWND gtk_get_window_hwnd(GtkWidget *widget) | |
t@@ -5315,6 +5355,82 @@ gint GtkMessageBox(GtkWidget *parent, const gchar *Text, | |
return retval; | |
} | |
+ | |
+/* Add a new source and return a unique ID */ | |
+static guint add_our_source(OurSource *source) | |
+{ | |
+ GSList *list; | |
+ guint id = 1; | |
+ | |
+ /* Get an unused ID */ | |
+ list = OurSources; | |
+ while (list) { | |
+ OurSource *s = (OurSource *)list->data; | |
+ if (s->id == id) { | |
+ id++; | |
+ list = OurSources; /* Back to the start */ | |
+ } else { | |
+ list = g_slist_next(list); | |
+ } | |
+ } | |
+ | |
+ source->id = id; | |
+ OurSources = g_slist_append(OurSources, source); | |
+ return source->id; | |
+} | |
+ | |
+/* Like g_timeout_add(), but uses the Windows event loop */ | |
+guint dp_g_timeout_add(guint interval, GSourceFunc function, gpointer data) | |
+{ | |
+ guint id; | |
+ OurSource *source = g_new0(OurSource, 1); | |
+ source->timeout_function = function; | |
+ source->data = data; | |
+ id = add_our_source(source); | |
+ if (SetTimer(TopLevel, id, interval, NULL) == 0) { | |
+ g_warning("Failed to create timer!"); | |
+ } | |
+ return id; | |
+} | |
+ | |
+/* Like g_io_add_watch(), but uses the Windows event loop */ | |
+guint dp_g_io_add_watch(GIOChannel *channel, GIOCondition condition, | |
+ GIOFunc func, gpointer user_data) | |
+{ | |
+ OurSource *source = g_new0(OurSource, 1); | |
+ source->io_channel = channel; | |
+ source->io_function = func; | |
+ source->socket = g_io_channel_unix_get_fd(channel); | |
+ source->data = user_data; | |
+ WSAAsyncSelect(source->socket, TopLevel, MYWM_SOCKETDATA, | |
+ (condition & G_IO_IN ? FD_READ | FD_CLOSE | FD_ACCEPT : 0) | |
+ | (condition & G_IO_OUT ? FD_WRITE | FD_CONNECT : 0)); | |
+ return add_our_source(source); | |
+} | |
+ | |
+/* Like g_source_remove(), but uses the Windows event loop */ | |
+gboolean dp_g_source_remove(guint tag) | |
+{ | |
+ GSList *list; | |
+ OurSource *s; | |
+ for (list = OurSources; list; list = g_slist_next(list)) { | |
+ s = (OurSource *)list->data; | |
+ if (s->id == tag) { | |
+ if (s->timeout_function) { | |
+ if (KillTimer(TopLevel, s->id) == 0) { | |
+ g_warning("Failed to kill timer!"); | |
+ } | |
+ } else { | |
+ WSAAsyncSelect(s->socket, TopLevel, 0, 0); | |
+ } | |
+ OurSources = g_slist_remove(OurSources, s); | |
+ g_free(s); | |
+ break; | |
+ } | |
+ } | |
+ return TRUE; | |
+} | |
+ | |
guint gtk_timeout_add(guint32 interval, GtkFunction function, | |
gpointer data) | |
{ | |
diff --git a/src/gtkport/gtkport.h b/src/gtkport/gtkport.h | |
t@@ -620,6 +620,12 @@ GtkWidget *gtk_spin_button_new(GtkAdjustment *adjustment, | |
void gdk_input_remove(gint tag); | |
gint gdk_input_add(gint source, GdkInputCondition condition, | |
GdkInputFunction function, gpointer data); | |
+ | |
+guint dp_g_io_add_watch(GIOChannel *channel, GIOCondition condition, | |
+ GIOFunc func, gpointer user_data); | |
+guint dp_g_timeout_add(guint interval, GSourceFunc function, gpointer data); | |
+gboolean dp_g_source_remove(guint tag); | |
+ | |
GtkWidget *gtk_hseparator_new(); | |
GtkWidget *gtk_vseparator_new(); | |
void gtk_object_set_data(GtkObject *object, const gchar *key, | |
diff --git a/src/gui_client/newgamedia.c b/src/gui_client/newgamedia.c | |
t@@ -108,7 +108,7 @@ static gboolean glib_socket(GIOChannel *ch, GIOCondition c… | |
return TRUE; | |
} else { | |
if (g->timer_event) { | |
- g_source_remove(g->timer_event); | |
+ dp_g_source_remove(g->timer_event); | |
g->timer_event = 0; | |
} | |
if (!err) | |
diff --git a/src/network.c b/src/network.c | |
t@@ -1288,13 +1288,13 @@ static int timer_function(CURLM *multi, long timeout_m… | |
CurlConnection *g = userp; | |
if (g->timer_event) { | |
- g_source_remove(g->timer_event); | |
+ dp_g_source_remove(g->timer_event); | |
g->timer_event = 0; | |
} | |
/* -1 means we should just delete our timer. */ | |
if (timeout_ms >= 0) { | |
- g->timer_event = g_timeout_add(timeout_ms, g->timer_cb, g); | |
+ g->timer_event = dp_g_timeout_add(timeout_ms, g->timer_cb, g); | |
} | |
return 0; | |
} | |
t@@ -1306,7 +1306,7 @@ static void remsock(SockData *f) | |
return; | |
} | |
if (f->ev) { | |
- g_source_remove(f->ev); | |
+ dp_g_source_remove(f->ev); | |
} | |
g_free(f); | |
} | |
t@@ -1320,9 +1320,9 @@ static void setsock(SockData *f, curl_socket_t s, CURL *… | |
((act & CURL_POLL_OUT) ? G_IO_OUT : 0); | |
if (f->ev) { | |
- g_source_remove(f->ev); | |
+ dp_g_source_remove(f->ev); | |
} | |
- f->ev = g_io_add_watch(f->ch, kind, g->socket_cb, g); | |
+ f->ev = dp_g_io_add_watch(f->ch, kind, g->socket_cb, g); | |
} | |
/* Initialize a new SockData structure */ | |
diff --git a/src/network.h b/src/network.h | |
t@@ -62,6 +62,15 @@ | |
#define SOCKET_ERROR -1 | |
#endif | |
+#ifdef CYGWIN | |
+/* Need GUI main loop to handle timers/events */ | |
+#include "gtkport/gtkport.h" | |
+#else | |
+#define dp_g_source_remove g_source_remove | |
+#define dp_g_io_add_watch g_io_add_watch | |
+#define dp_g_timeout_add g_timeout_add | |
+#endif | |
+ | |
typedef struct _CurlConnection { | |
CURLM *multi; | |
CURL *h; | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -1144,7 +1144,7 @@ static gboolean glib_socket(GIOChannel *ch, GIOCondition… | |
return TRUE; | |
} else { | |
if (g->timer_event) { | |
- g_source_remove(g->timer_event); | |
+ dp_g_source_remove(g->timer_event); | |
g->timer_event = 0; | |
} | |
LogMetaReply(g); |