XInitThreads causing problems to GTK windows.



/*

Hello there!

      Can someone tell me if there's something I need to know before calling
Xlib code directly, within GTK programs? I'm trying to write a proggy that
will have one thread that does some graphics stuff, talking directly to XLib
(with it's own connection to the X server). Because that means that there
might
be two threads calling XLib concurrently I need to call XInitThreads() -
it's
man page states..:-

	This function must be the first Xlib
	function a multi-threaded program calls,
	and it must complete before any other
	Xlib call is made.

	However - I've found that if I call XInitThreads BEFORE gtk_init, then
pressing a key with a fileselection on the screen causes the program to hang
somewhere inside gtk_main_iteration().

    If I call XInitThreads after gtk_init then everything appears fine, but
I don't know what affects that'll have on XLib. I'm not really too bothered
about GTK / GDK or GLIB being thread safe - the second thread need not call
any of those functions. But I've tried inserting g_threads_init() here and
there, without any luck.

	Anyone have any ideas?

Cheers...

Chris Wilson

cdw22@cam.ac.uk

----------------- Cut here ;] -------------------*/

// Little proggy to demonstrate GTK+ bug [?] ...
// ... I think... ;[
//
//
// Compile and run this, notice that the fileselector works fine with the
// mouse - but if you try to type something into the box - the progam hangs.

/*

Save as gtkbug.c and compile me:-

gcc -O2 -Wall gtkbug.c `gtk-config --cflags gthread` \
`gtk-config --libs gthread` -o gtkbug

*/

#include <X11/X.h>
#include <X11/Xlib.h>
#include <glib.h>
#include <gtk/gtk.h>

typedef struct
{
	GtkWidget *fs;
	gchar *filename;
	gboolean cancelled;
	gboolean done;
} fileselector;

// Prototypes [yawn]

fileselector *make_fileselector(gchar *title, gchar *dir, gchar *pattern);
void fileselector_wait(fileselector *fs);
int main(int argc, char *argv[]);

// Signal & event handlers

static void filesel_ok(GtkWidget *w, fileselector *fs);
static void filesel_canc(GtkWidget *w, fileselector *fs);
static gboolean filesel_deleteevent (GtkWidget *w, GdkEvent *e, fileselector
*fs);

// Code

int main(int argc, char *argv[])
{
	fileselector *fs;

	if(!XInitThreads())
	{
		g_print("XLib is not thread safe. Bailing...\n");
		exit(-1);
	}

	gtk_init(&argc, &argv);

	fs=make_fileselector("blah blah", "/home/chris", "*");

	fileselector_wait(fs);

	if(fs->cancelled)
	{
		g_print("Cancelled\n");
		return 0;
	}

	g_print("Filename selected %s\n",fs->filename);

	return 0;
}

fileselector *make_fileselector(gchar *title, gchar *dir, gchar *pattern)
{
	fileselector *fs;

	fs = g_malloc(sizeof(fileselector));

	fs->fs=gtk_file_selection_new(title);
	gtk_window_set_position(GTK_WINDOW(fs->fs), GTK_WIN_POS_MOUSE);

	gtk_file_selection_set_filename(GTK_FILE_SELECTION (fs->fs), dir);
	gtk_file_selection_complete(GTK_FILE_SELECTION (fs->fs), pattern);
	fs->filename=NULL;
	fs->cancelled=FALSE;
	fs->done=FALSE;

	gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION (fs->fs)->ok_button),
"clicked", GTK_SIGNAL_FUNC (filesel_ok), fs);
	gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION (fs->fs)->cancel_button),
"clicked", GTK_SIGNAL_FUNC (filesel_canc), fs);
	gtk_signal_connect(GTK_OBJECT (fs->fs), "delete_event", GTK_SIGNAL_FUNC
(filesel_deleteevent), fs);

	gtk_widget_show(fs->fs);

	return fs;
}

void fileselector_wait(fileselector *fs)
{
	while(!fs->done)
		gtk_main_iteration();
}


static void filesel_ok(GtkWidget *w, fileselector *fs)
{
	gchar *filename;

	filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs->fs));
	fs->filename=g_malloc(strlen(filename)+1);
	strcpy(fs->filename, filename);

	fs->done=TRUE;

	gtk_widget_hide(fs->fs);
	gtk_widget_destroy(fs->fs);
}

static void filesel_canc(GtkWidget *w, fileselector *fs)
{
	fs->cancelled=TRUE;
	fs->done=TRUE;

	gtk_widget_hide(fs->fs);
	gtk_widget_destroy(fs->fs);
}

static gboolean filesel_deleteevent (GtkWidget *w, GdkEvent *e, fileselector
*fs)
{
	fs->cancelled=TRUE;
	fs->done=TRUE;

	gtk_widget_hide(fs->fs);
	gtk_widget_destroy(fs->fs);

	return TRUE;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]