/*
- * $Id: rb_event_handler.c 343 2005-05-07 20:22:56Z tilman $
+ * $Id: rb_event_handler.c 357 2006-02-12 15:40:30Z tilman $
*
* Copyright (C) 2004 ruby-ecore team (see AUTHORS)
*
#include "rb_ecore.h"
#include "rb_event_handler.h"
+typedef struct {
+ Ecore_Event_Handler *real;
+ VALUE callback;
+ bool deleted;
+} RbEventHandler;
+
static int on_ecore_event (void *data, int type, void *event);
VALUE event_classes, cEcoreEvent;
static VALUE handlers;
+static void c_mark (RbEventHandler *h)
+{
+ rb_gc_mark (h->callback);
+}
+
+static void c_free (RbEventHandler *h)
+{
+ RbEventHandler *h2 = NULL;
+ int len = RARRAY (handlers)->len, i;
+ VALUE el;
+
+ if (!h->real || h->deleted) {
+ free (h);
+ return;
+ }
+
+ for (i = 0; i < len; i++) {
+ el = rb_ary_shift (handlers);
+
+ Data_Get_Struct (el, RbEventHandler, h2);
+
+ if (h == h2) {
+ ecore_event_handler_del (h->real);
+ break;
+ }
+
+ rb_ary_push (handlers, el);
+ }
+
+ free (h);
+}
+
+static VALUE c_alloc (VALUE klass)
+{
+ RbEventHandler *h = NULL;
+
+ return Data_Make_Struct (klass, RbEventHandler, c_mark, c_free, h);
+}
+
static VALUE c_init (VALUE self, VALUE type)
{
+ RbEventHandler *h = NULL;
int t;
if (!rb_block_given_p ())
return Qnil;
+ Data_Get_Struct (self, RbEventHandler, h);
+
t = NUM2INT (type);
if (t <= ECORE_EVENT_NONE)
return Qnil;
rb_iv_set (self, "@type", type);
- rb_iv_set (self, "handler", rb_block_proc ());
- rb_ary_push (handlers, self);
+ h->callback = rb_block_proc ();
+ h->deleted = false;
+ h->real = ecore_event_handler_add (t, on_ecore_event, NULL);
- ecore_event_handler_add (t, on_ecore_event, NULL);
+ rb_ary_push (handlers, self);
return self;
}
static VALUE c_delete (VALUE self)
{
+ RbEventHandler *h = NULL;
int len = RARRAY (handlers)->len, i;
VALUE el;
for (i = 0; i < len; i++) {
el = rb_ary_shift (handlers);
- if (el == self)
+ if (el == self) {
+ Data_Get_Struct (self, RbEventHandler, h);
+ ecore_event_handler_del (h->real);
+ h->real = NULL;
+ h->deleted = true;
+
return Qnil;
+ }
rb_ary_push (handlers, el);
}
static int on_ecore_event (void *data, int type, void *event)
{
+ RbEventHandler *h = NULL;
VALUE handler, klass, obj, argv[1], res;
int handler_type, len, i;
bool called = false;
handler_type = NUM2INT (rb_iv_get (handler, "@type"));
if (handler_type == type) {
- res = rb_funcall (rb_iv_get (handler, "handler"),
- rb_intern ("call"), 1, obj);
+ Data_Get_Struct (handler, RbEventHandler, h);
+ res = rb_funcall (h->callback, rb_intern ("call"), 1, obj);
called = true;
/* if the block returned false, don't call the other
cEventHandler = rb_define_class_under (mEcore, "EventHandler",
rb_cObject);
+ rb_define_alloc_func (cEventHandler, c_alloc);
rb_define_method (cEventHandler, "initialize", c_init, 1);
rb_define_method (cEventHandler, "delete", c_delete, 0);