From: Philip Chimento <philip.chimento@gmail.com>
Date: Sun, 13 Sep 2009 17:07:59 +0000 (+0000)
Subject: Started using thread-private data. Multisession still doesn't work, but regular opera... 
X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;h=db8dde85ef01518d74df205d083ba1fb501b21c9;p=rodin%2Fchimara.git

Started using thread-private data. Multisession still doesn't work, but regular operation does.

git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@121 ddfedd41-794f-dd11-ae45-00112f111e67
---

diff --git a/libchimara/abort.c b/libchimara/abort.c
index 61234a0..18b2725 100644
--- a/libchimara/abort.c
+++ b/libchimara/abort.c
@@ -4,7 +4,7 @@
 
 #include "chimara-glk-private.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_set_interrupt_handler:
@@ -29,6 +29,7 @@ extern ChimaraGlkPrivate *glk_data;
 void
 glk_set_interrupt_handler(void (*func)(void))
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	glk_data->interrupt_handler = func;
 }
 
@@ -37,30 +38,18 @@ user's interrupt handler. */
 static void
 abort_glk()
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	if(glk_data->interrupt_handler)
 		(*(glk_data->interrupt_handler))();
 	g_signal_emit_by_name(glk_data->self, "stopped");
 	g_thread_exit(NULL);
 }
 
-/* Internal function: Signal this Glk thread to abort. Does nothing if the abort
-mutex has already been freed. (That means the thread already ended.) */
-void
-signal_abort()
-{
-	if(glk_data && glk_data->abort_lock) {
-		g_mutex_lock(glk_data->abort_lock);
-		glk_data->abort_signalled = TRUE;
-		g_mutex_unlock(glk_data->abort_lock);
-		/* Stop blocking on the event queue condition */
-		event_throw(evtype_Abort, NULL, 0, 0);
-	}
-}
-
 /* Internal function: check if the Glk program has been interrupted. */
 void
 check_for_abort()
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	g_mutex_lock(glk_data->abort_lock);
 	if(glk_data->abort_signalled) 
 	{
diff --git a/libchimara/abort.h b/libchimara/abort.h
index 1ba2bcc..f075550 100644
--- a/libchimara/abort.h
+++ b/libchimara/abort.h
@@ -2,7 +2,6 @@
 #define ABORT_H
 
 G_GNUC_INTERNAL void check_for_abort();
-G_GNUC_INTERNAL void signal_abort();
 
 #endif
 
diff --git a/libchimara/chimara-glk.c b/libchimara/chimara-glk.c
index b9e0437..f7887a9 100644
--- a/libchimara/chimara-glk.c
+++ b/libchimara/chimara-glk.c
@@ -484,7 +484,7 @@ chimara_glk_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 		if(!priv->ignore_next_arrange_event)
 		{
 			if(arrange)
-				event_throw(evtype_Arrange, arrange == priv->root_window->data? NULL : arrange, 0, 0);
+				event_throw(CHIMARA_GLK(widget), evtype_Arrange, arrange == priv->root_window->data? NULL : arrange, 0, 0);
 		}
 		else
 			priv->ignore_next_arrange_event = FALSE;
@@ -929,19 +929,21 @@ struct StartupData {
 	glk_main_t glk_main;
 	glkunix_startup_code_t glkunix_startup_code;
 	glkunix_startup_t args;
+	ChimaraGlkPrivate *glk_data;
 };
 
 /* glk_enter() is the actual function called in the new thread in which glk_main() runs.  */
 static gpointer
 glk_enter(struct StartupData *startup)
 {
-    extern ChimaraGlkPrivate *glk_data;
+	extern GPrivate *glk_data_key;
+	g_private_set(glk_data_key, startup->glk_data);
 	
 	/* Run startup function */
 	if(startup->glkunix_startup_code) {
-		glk_data->in_startup = TRUE;
+		startup->glk_data->in_startup = TRUE;
 		int result = startup->glkunix_startup_code(&startup->args);
-		glk_data->in_startup = FALSE;
+		startup->glk_data->in_startup = FALSE;
 		
 		int i = 0;
 		while(i < startup->args.argc)
@@ -953,10 +955,10 @@ glk_enter(struct StartupData *startup)
 	}
 	
 	/* Run main function */
-    g_signal_emit_by_name(glk_data->self, "started");
+    g_signal_emit_by_name(startup->glk_data->self, "started");
 	(startup->glk_main)();
-	g_slice_free(struct StartupData, startup);	
-	g_signal_emit_by_name(glk_data->self, "stopped");
+	g_signal_emit_by_name(startup->glk_data->self, "stopped");
+	g_slice_free(struct StartupData, startup);
 	return NULL;
 }
 
@@ -1020,10 +1022,10 @@ chimara_glk_run(ChimaraGlk *glk, gchar *plugin, int argc, char *argv[], GError *
 		startup->args.argv[0] = g_strdup(plugin);
     }
 
-	extern ChimaraGlkPrivate *glk_data;
-    /* Set the thread's private data */
-    /* TODO: Do this with a GPrivate */
-    glk_data = priv;
+	/* Initialize thread-private data */
+	extern GPrivate *glk_data_key;
+	glk_data_key = g_private_new(NULL);
+	startup->glk_data = priv;
 	
     /* Run in a separate thread */
 	priv->thread = g_thread_create((GThreadFunc)glk_enter, startup, TRUE, error);
@@ -1044,7 +1046,14 @@ chimara_glk_stop(ChimaraGlk *glk)
 {
     g_return_if_fail(glk || CHIMARA_IS_GLK(glk));
     /* TODO: check if glk is actually running a program */
-	signal_abort();
+	ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+	if(priv->abort_lock) {
+		g_mutex_lock(priv->abort_lock);
+		priv->abort_signalled = TRUE;
+		g_mutex_unlock(priv->abort_lock);
+		/* Stop blocking on the event queue condition */
+		event_throw(glk, evtype_Abort, NULL, 0, 0);
+	}
 }
 
 /**
diff --git a/libchimara/event.c b/libchimara/event.c
index 1a24f28..4bbb391 100644
--- a/libchimara/event.c
+++ b/libchimara/event.c
@@ -3,9 +3,10 @@
 #include "glk.h"
 #include <string.h>
 
+#include "chimara-glk.h"
 #include "chimara-glk-private.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 #define EVENT_TIMEOUT_MICROSECONDS (3000000)
 
@@ -13,23 +14,25 @@ extern ChimaraGlkPrivate *glk_data;
 full, wait for max three seconds and then drop the event. If the event queue is
 NULL, i.e. freed, then fail silently. */
 void
-event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
+event_throw(ChimaraGlk *glk, glui32 type, winid_t win, glui32 val1, glui32 val2)
 {
-	if(!glk_data->event_queue)
+	ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk);
+	
+	if(!priv->event_queue)
 		return;
 
 	GTimeVal timeout;
 	g_get_current_time(&timeout);
 	g_time_val_add(&timeout, EVENT_TIMEOUT_MICROSECONDS);
 
-	g_mutex_lock(glk_data->event_lock);
+	g_mutex_lock(priv->event_lock);
 
 	/* Wait for room in the event queue */
-	while( g_queue_get_length(glk_data->event_queue) >= EVENT_QUEUE_MAX_LENGTH )
-		if( !g_cond_timed_wait(glk_data->event_queue_not_full, glk_data->event_lock, &timeout) ) 
+	while( g_queue_get_length(priv->event_queue) >= EVENT_QUEUE_MAX_LENGTH )
+		if( !g_cond_timed_wait(priv->event_queue_not_full, priv->event_lock, &timeout) ) 
 		{
 			/* Drop the event after 3 seconds */
-			g_mutex_unlock(glk_data->event_lock);
+			g_mutex_unlock(priv->event_lock);
 			return;
 		}
 
@@ -38,12 +41,12 @@ event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2)
 	event->win = win;
 	event->val1 = val1;
 	event->val2 = val2;
-	g_queue_push_head(glk_data->event_queue, event);
+	g_queue_push_head(priv->event_queue, event);
 
 	/* Signal that there is an event */
-	g_cond_signal(glk_data->event_queue_not_empty);
+	g_cond_signal(priv->event_queue_not_empty);
 
-	g_mutex_unlock(glk_data->event_lock);
+	g_mutex_unlock(priv->event_lock);
 }
 
 /**
@@ -64,6 +67,8 @@ glk_select(event_t *event)
 {
 	g_return_if_fail(event != NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	g_mutex_lock(glk_data->event_lock);
 
 	/* Wait for an event */
@@ -154,6 +159,8 @@ glk_select_poll(event_t *event)
 {
 	g_return_if_fail(event != NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	event->type = evtype_None;
 	
 	g_mutex_lock(glk_data->event_lock);
diff --git a/libchimara/event.h b/libchimara/event.h
index 7cf80bd..32e5bb9 100644
--- a/libchimara/event.h
+++ b/libchimara/event.h
@@ -3,10 +3,11 @@
 
 #include <glib.h>
 #include "glk.h"
+#include "chimara-glk.h"
 
 #define EVENT_QUEUE_MAX_LENGTH (100)
 #define evtype_Abort (-1)
 
-G_GNUC_INTERNAL void event_throw(glui32 type, winid_t win, glui32 val1, glui32 val2);
+G_GNUC_INTERNAL void event_throw(ChimaraGlk *glk, glui32 type, winid_t win, glui32 val1, glui32 val2);
 
 #endif
diff --git a/libchimara/fileref.c b/libchimara/fileref.c
index d20e1f2..97c6e48 100644
--- a/libchimara/fileref.c
+++ b/libchimara/fileref.c
@@ -7,7 +7,7 @@
 #include "magic.h"
 #include "chimara-glk-private.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_fileref_iterate:
@@ -24,7 +24,8 @@ frefid_t
 glk_fileref_iterate(frefid_t fref, glui32 *rockptr)
 {
 	VALID_FILEREF_OR_NULL(fref, return NULL);
-	
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	GList *retnode;
 	
 	if(fref == NULL)
@@ -62,6 +63,8 @@ fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
 {
 	g_return_val_if_fail(filename != NULL, NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	frefid_t f = g_new0(struct glk_fileref_struct, 1);
 	f->magic = MAGIC_FILEREF;
 	f->rock = rock;
@@ -185,6 +188,8 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
 	for each usage */
 	GtkWidget *chooser;
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	gdk_threads_enter();
 
 	switch(fmode)
@@ -289,13 +294,11 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock)
 {
 	g_return_val_if_fail(name != NULL && strlen(name) > 0, NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	/* Do any string-munging here to remove illegal Latin-1 characters from 
 	filename. On ext3, the only illegal characters are '/' and '\0'. */
-	
-	char *ptr = name;
-	while(*ptr++)
-		if(*ptr == '/')
-			*ptr = '_';
+	g_strdelimit(name, "/", '_');
 	
 	/* Find out what encoding filenames are in */
 	const gchar **charsets; /* Do not free */
@@ -377,6 +380,8 @@ void
 glk_fileref_destroy(frefid_t fref)
 {
 	VALID_FILEREF(fref, return);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
 	if(fref->filename)
diff --git a/libchimara/glk.c b/libchimara/glk.c
index 2f7e10f..27e3007 100644
--- a/libchimara/glk.c
+++ b/libchimara/glk.c
@@ -6,7 +6,7 @@
 #include "chimara-glk-private.h"
 #include "gi_blorb.h"
 
-G_GNUC_INTERNAL ChimaraGlkPrivate *glk_data = NULL;
+G_GNUC_INTERNAL GPrivate *glk_data_key = NULL;
 
 /**
  * glk_exit:
@@ -42,6 +42,8 @@ G_GNUC_INTERNAL ChimaraGlkPrivate *glk_data = NULL;
 void
 glk_exit(void)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	if(!glk_data->in_startup)
 		g_signal_emit_by_name(glk_data->self, "stopped");
 
@@ -54,7 +56,6 @@ glk_exit(void)
 		glk_stream_close(glk_data->resource_file, NULL);
 	}
 
-    glk_data = NULL;
 	g_thread_exit(NULL);
 }
 
diff --git a/libchimara/glkunix.c b/libchimara/glkunix.c
index ee11943..704ac0c 100644
--- a/libchimara/glkunix.c
+++ b/libchimara/glkunix.c
@@ -7,7 +7,7 @@
 #include "fileref.h"
 #include "stream.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glkunix_stream_open_pathname:
@@ -25,6 +25,8 @@ extern ChimaraGlkPrivate *glk_data;
 strid_t
 glkunix_stream_open_pathname(char *pathname, glui32 usage, glui32 rock)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	if(!glk_data->in_startup)
 		ILLEGAL("glkunix_stream_open_pathname() may only be called from "
 				"glkunix_startup_code().");
@@ -53,6 +55,8 @@ glkunix_set_base_file(char *filename)
 {
 	g_return_if_fail(filename);
 	g_return_if_fail(strlen(filename) > 0);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	gchar *dirname = g_path_get_dirname(filename);
 	if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
diff --git a/libchimara/input.c b/libchimara/input.c
index 8400998..ab1eef5 100644
--- a/libchimara/input.c
+++ b/libchimara/input.c
@@ -400,7 +400,7 @@ on_window_key_press_event(GtkWidget *widget, GdkEventKey *event, winid_t win)
 				keycode = keycode_Unknown;	
 	}
 
-	event_throw(evtype_CharInput, win, keycode, 0);
+	event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(widget, CHIMARA_TYPE_GLK)), evtype_CharInput, win, keycode, 0);
 	
 	/* Only one keypress will be handled */
 	win->input_request_type = INPUT_REQUEST_NONE;
@@ -542,7 +542,7 @@ after_window_insert_text(GtkTextBuffer *textbuffer, GtkTextIter *location, gchar
         gtk_text_view_set_editable(GTK_TEXT_VIEW(win->widget), FALSE);
 
         int chars_written = flush_text_buffer(win);
-		event_throw(evtype_LineInput, win, chars_written, 0);
+		event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
 	}
 }
 
@@ -554,6 +554,6 @@ on_input_entry_activate(GtkEntry *input_entry, winid_t win)
 	g_signal_handler_block( G_OBJECT(win->widget), win->keypress_handler );
 
 	int chars_written = flush_text_grid(win);
-	event_throw(evtype_LineInput, win, chars_written, 0);
+	event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(GTK_WIDGET(input_entry), CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
 }
 
diff --git a/libchimara/resource.c b/libchimara/resource.c
index ad5dbf1..b3c98ec 100644
--- a/libchimara/resource.c
+++ b/libchimara/resource.c
@@ -1,6 +1,6 @@
 #include "resource.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * giblorb_set_resource_map:
@@ -19,6 +19,7 @@ extern ChimaraGlkPrivate *glk_data;
 giblorb_err_t
 giblorb_set_resource_map(strid_t file)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	giblorb_map_t *newmap; /* create map allocates memory */
 	giblorb_err_t error = giblorb_create_map(file, &newmap);
 
@@ -50,6 +51,8 @@ giblorb_set_resource_map(strid_t file)
 giblorb_map_t*
 giblorb_get_resource_map()
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	if(glk_data->resource_map == NULL) {
 		WARNING("Resource map not set yet.\n");
 	}
diff --git a/libchimara/stream.c b/libchimara/stream.c
index aa27a39..72b36a8 100644
--- a/libchimara/stream.c
+++ b/libchimara/stream.c
@@ -7,12 +7,14 @@
 #include <glib/gstdio.h>
 
 #include "chimara-glk-private.h"
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /* Internal function: create a stream with a specified rock value */
 static strid_t
 stream_new_common(glui32 rock, glui32 fmode, enum StreamType type)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	strid_t str = g_new0(struct glk_stream_struct, 1);
 	str->magic = MAGIC_STREAM;
 	str->rock = rock;
@@ -52,7 +54,8 @@ strid_t
 glk_stream_iterate(strid_t str, glui32 *rockptr)
 {
 	VALID_STREAM_OR_NULL(str, return NULL);
-	
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	GList *retnode;
 	
 	if(str == NULL)
@@ -96,6 +99,8 @@ void
 glk_stream_set_current(strid_t str)
 {
 	VALID_STREAM_OR_NULL(str, return);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	if(str != NULL && str->file_mode == filemode_Read)
 	{
@@ -116,6 +121,7 @@ glk_stream_set_current(strid_t str)
 strid_t
 glk_stream_get_current()
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	return glk_data->current_stream;
 }
 
@@ -130,6 +136,7 @@ glk_stream_get_current()
 void
 glk_put_char(unsigned char ch)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_char_stream(glk_data->current_stream, ch);
 }
@@ -145,6 +152,7 @@ glk_put_char(unsigned char ch)
 void
 glk_put_char_uni(glui32 ch)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_char_stream_uni(glk_data->current_stream, ch);
 }
@@ -164,6 +172,7 @@ glk_put_char_uni(glui32 ch)
 void
 glk_put_string(char *s)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_string_stream(glk_data->current_stream, s);
 }
@@ -179,6 +188,7 @@ glk_put_string(char *s)
 void
 glk_put_string_uni(glui32 *s)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_string_stream_uni(glk_data->current_stream, s);
 }
@@ -199,6 +209,7 @@ glk_put_string_uni(glui32 *s)
 void
 glk_put_buffer(char *buf, glui32 len)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_buffer_stream(glk_data->current_stream, buf, len);
 }
@@ -214,6 +225,7 @@ glk_put_buffer(char *buf, glui32 len)
 void
 glk_put_buffer_uni(glui32 *buf, glui32 len)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	VALID_STREAM(glk_data->current_stream, return);
 	glk_put_buffer_stream_uni(glk_data->current_stream, buf, len);
 }
@@ -452,6 +464,8 @@ glk_stream_close(strid_t str, stream_result_t *result)
 void
 stream_close_common(strid_t str, stream_result_t *result)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	/* Remove the stream from the global stream list */
 	glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
 	
diff --git a/libchimara/style.c b/libchimara/style.c
index 2db2e09..3826ebf 100644
--- a/libchimara/style.c
+++ b/libchimara/style.c
@@ -1,6 +1,6 @@
 #include "style.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_set_style:
@@ -18,6 +18,7 @@ extern ChimaraGlkPrivate *glk_data;
 void
 glk_set_style(glui32 styl)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	g_return_if_fail(glk_data->current_stream != NULL);
 	glk_set_style_stream(glk_data->current_stream, styl);
 }
@@ -62,6 +63,8 @@ style_init_textbuffer(GtkTextBuffer *buffer)
 {
 	g_return_if_fail(buffer != NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
 	gtk_text_buffer_create_tag(buffer, "normal", NULL);
 	gtk_text_buffer_create_tag(buffer, "emphasized", "style", PANGO_STYLE_ITALIC, NULL);
 	gtk_text_buffer_create_tag(buffer, "preformatted", "font-desc", glk_data->monospace_font_desc, NULL);
@@ -91,6 +94,7 @@ apply_stylehint_to_tag(GtkTextTag *tag, glui32 hint, glsi32 val)
 {
 	g_return_if_fail(tag != NULL);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	GObject *tag_object = G_OBJECT(tag);
 	gint reverse_color = 0;
 
diff --git a/libchimara/timer.c b/libchimara/timer.c
index f063def..400f506 100644
--- a/libchimara/timer.c
+++ b/libchimara/timer.c
@@ -1,6 +1,6 @@
 #include "timer.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_request_timer_events:
@@ -46,6 +46,8 @@ extern ChimaraGlkPrivate *glk_data;
 void
 glk_request_timer_events(glui32 millisecs)
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	// Stop any existing timer
 	if(glk_data->timer_id != 0) {
 		g_source_remove(glk_data->timer_id);
@@ -55,7 +57,7 @@ glk_request_timer_events(glui32 millisecs)
 	if(millisecs == 0)
 		return;
 	
-	glk_data->timer_id = g_timeout_add(millisecs, push_timer_event, NULL);
+	glk_data->timer_id = g_timeout_add(millisecs, (GSourceFunc)push_timer_event, glk_data->self);
 }
 
 /*
@@ -63,9 +65,9 @@ glk_request_timer_events(glui32 millisecs)
  * Will always return TRUE
  */
 gboolean
-push_timer_event(gpointer data)
+push_timer_event(ChimaraGlk *glk)
 {
-	event_throw(evtype_Timer, NULL, 0, 0);
+	event_throw(glk, evtype_Timer, NULL, 0, 0);
 
 	return TRUE;
 }
diff --git a/libchimara/timer.h b/libchimara/timer.h
index 1edb670..b3baf7b 100644
--- a/libchimara/timer.h
+++ b/libchimara/timer.h
@@ -3,8 +3,9 @@
 
 #include <glib.h>
 #include "event.h"
+#include "chimara-glk.h"
 #include "chimara-glk-private.h"
 
-G_GNUC_INTERNAL gboolean push_timer_event(gpointer  data);
+G_GNUC_INTERNAL gboolean push_timer_event(ChimaraGlk *glk);
 
 #endif
diff --git a/libchimara/window.c b/libchimara/window.c
index 5e0ec50..bbfe49d 100644
--- a/libchimara/window.c
+++ b/libchimara/window.c
@@ -1,8 +1,9 @@
+#include <glib.h>
 #include "window.h"
 #include "magic.h"
 #include "chimara-glk-private.h"
 
-extern ChimaraGlkPrivate *glk_data;
+extern GPrivate *glk_data_key;
 
 /**
  * glk_window_iterate:
@@ -25,6 +26,7 @@ glk_window_iterate(winid_t win, glui32 *rockptr)
 {
 	VALID_WINDOW_OR_NULL(win, return NULL);
 	
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	GNode *retnode;
 	
 	if(win == NULL)
@@ -135,6 +137,7 @@ glk_window_get_sibling(winid_t win)
 winid_t
 glk_window_get_root()
 {
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	if(glk_data->root_window == NULL)
 		return NULL;
 	return (winid_t)glk_data->root_window->data;
@@ -377,6 +380,8 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
 	g_return_val_if_fail(method == (method & (winmethod_DirMask | winmethod_DivisionMask)), NULL);
 	g_return_val_if_fail(!(((method & winmethod_DivisionMask) == winmethod_Proportional) && size > 100), NULL);	
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
 	if(split == NULL && glk_data->root_window != NULL)
 	{
 		ILLEGAL("Tried to open a new root window, but there is already a root window");
@@ -701,6 +706,8 @@ void
 glk_window_close(winid_t win, stream_result_t *result)
 {
 	VALID_WINDOW(win, return);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	gdk_threads_enter(); /* Prevent redraw while we're trashing the window */
 	
@@ -810,6 +817,8 @@ glk_window_clear(winid_t win)
 {
 	VALID_WINDOW(win, return);
 	g_return_if_fail(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	switch(win->type)
 	{
@@ -976,6 +985,8 @@ glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr)
 {
 	VALID_WINDOW(win, return);
 
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+	
     switch(win->type)
     {
         case wintype_Blank:
@@ -1103,6 +1114,8 @@ glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keyw
 	}
 	g_return_if_fail(method == (method & (winmethod_DirMask | winmethod_DivisionMask)));
 	g_return_if_fail(!(((method & winmethod_DivisionMask) == winmethod_Proportional) && size > 100));
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	win->split_method = method;
 	win->constraint_size = size;
@@ -1177,6 +1190,8 @@ glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos)
 {
 	VALID_WINDOW(win, return);
 	g_return_if_fail(win->type == wintype_TextGrid);
+
+	ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
 	
 	/* Wait until the window's size is current */
 	g_mutex_lock(glk_data->arrange_lock);