On Tue, 29 May 2001, Patrik Sundberg wrote: > So, I want to have functionality similair to the gtk_input_add_* functions in > my ruby-gtk application. I want to update the GUI depending on data from a UDP > socket and the data is sent asynchronous - how would I accomplish this? Hi Patrik, I needed exactly the same functionality, searched through this list via google, but all that I found were your two postings. I really wonder why nobody has implemented it yet -- you really need this for any single thread GUI application that communicates over the net. There are basically two solutions to this problem: Either get the file descriptor for X11 somehow out of Gtk, then implement the application main loop yourself, adding this file descriptor to your select call, and then call Gtk::main_iteration() from there when apropriate, avoiding Gtk::main() completely. Or implement the missing input_add functions youself. It seems both solutions require that you extend the current ruby/gtk binding, and the second sounds like less effort. I tried to implement the missing functions, and it seems to work. See the diff below, but beware: I only know about ruby since 3 weeks. I've got a question to the group regarding the handling of a block argument in a ruby extension: The code in the idle_add, idle_remove, timeout_add, timeout_remove methods looks to me like a memory leak. (File src/rbgtkmain.c) The *_add functions contain a call to a function add_relative that basically stores a reference to the block in an Array which is an instance variable of "self". (BTW what does self mean in this context? Gtk is a module, and these are module functions.) I suppose this saves the block and its scope from the garbage collection? This reference is not removed by the corresponding *_remove functions. So, if I was right with the garbage collection thing, periodic calls to *_add and *_remove functions would eat up memory that is never freed again, right? Greetings, Tobias This is a diff against ruby/gtk version 0.24. The new input_add/remove functions are modified versions of the timeout functions, so if there is really a memory leak problem in these, then the input functions will have it too. Below the diff is a small example script, which uses the new Gtk::input_add method to wait for input on stdin. *** rbgtkmain.c.orig Sun Oct 22 13:31:08 2000 --- rbgtkmain.c Wed May 30 21:06:00 2001 *************** *** 80,85 **** --- 80,118 ---- return Qnil; } + static void + exec_input (gpointer data, + gint source, + GdkInputCondition condition) + { + rb_funcall((VALUE)data, id_call, 0); + } + + static VALUE + input_add(self, filedescriptor, gdk_input_condition) + VALUE self, filedescriptor, gdk_input_condition; + { + int id; + VALUE func; + + func = rb_f_lambda(); + add_relative(self, func); + + id = gdk_input_add(NUM2INT(rb_funcall(filedescriptor, rb_intern("to_i"), 0)), + (GdkInputCondition)NUM2INT(gdk_input_condition), + (GdkInputFunction)exec_input, + (gpointer)func); + return INT2FIX(id); + } + + static VALUE + input_remove(self, id) + VALUE self, id; + { + gdk_input_remove(NUM2INT(id)); + return Qnil; + } + static VALUE idle_add(self) VALUE self; *************** *** 187,192 **** --- 220,227 ---- rb_define_module_function(mGtk, "main_iteration", gtk_m_main_iteration, 0); rb_define_module_function(mGtk, "timeout_add", timeout_add, 1); rb_define_module_function(mGtk, "timeout_remove", timeout_remove, 1); + rb_define_module_function(mGtk, "input_add", input_add, 2); + rb_define_module_function(mGtk, "input_remove", input_remove, 1); rb_define_module_function(mGtk, "idle_add", idle_add, 0); rb_define_module_function(mGtk, "idle_remove", idle_remove, 1); rb_define_module_function(mGtk, "get_current_event", gtk_m_get_current_event, 0); require "gtk" GDK_INPUT_READ = 1 << 0 GDK_INPUT_WRITE = 1 << 1 GDK_INPUT_EXCEPTION = 1 << 2 STDIN_FILENO = 0 Gtk::input_add($stdin, GDK_INPUT_READ) { chars = $stdin.sysread(5) puts("input pending! Reading no more than 5 chars: <<#{chars.dump()}>>") if (chars[0,4] == "quit") Gtk::main_quit() end } Gtk::main()