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

Re: [E-devel] evas object event callback API



[the delay is because I wanted to have working code before I comment
 further, and work intervened]

Carsten Haitzler:
> On Sat, 05 Aug 2006 12:45:39 +0200 Jan Rychter <jan@rychter.com> babbled:
> In ecore_evas - you do have a problem as it expects ONE callabck only per
> ecore_evas canvas wrapper and events 

I maintain a table of callbacks anyway and register only one dispatching
function (that in turn calls the real callback functions), so ecore_evas
only knows about one callback: the dispatching function. I delete that
callback when the last callback in my table gets deleted. It's simple
enough: about 30 lines of code to deal with all ecore_evas callbacks.

> - BUT for evas this is not the case. you
> can attach N event callbacks to any objects for an event type. as you hve a
> generic void *data pointer for all of these, you can use this to differentiate,
> pass extra data for your binding (pass in an allocated struct ptr that then
> contains all of the data you could/would need - even like event type). the void
> *data pointer should be sufficient for all your needs - if used right. what
> about this makes it not possible to bind to another language? i have bound
> identical callbacks for timers for example in embryo for scripting - a timer
> gets passed only 1 parameter - a void * pointer.

Right. The *data pointer is a very neat and smart idea. I was just
hoping I wouldn't have to allocate/deallocate structures and use the
pointer just so that I can stick the event type in there. I really
expected the event type to be part of the callback signature, after all
you need it to decode the event info.

> if your point is that you want to create the "1 callback does all" thing and
> only ever bind that 1 function to everything using the event type to then
> switch off internally - then you just are wanting to do things in a way evas
> was not intended to work. yes - it expects a callback to be set and specialized
> for at least that TYPE of event. so you will need N callbacks in the binding
> api - 1 per event type you  wish to handle, and then use the void *data to
> piggyback whatever extra info you need :) changing the callback api will
> basically break a few hundred thousand lines of code and i'd need a reason why
> the current api CANNOT do what you NEED - not just a "it doesn't work the way i
> wanted to do this" :)

Well, I still believe that the event type should be passed to the
callback function, but yes, I can work around it. I have to define 9
functions, one per event structure (plus one for all the NULL event
pointer cases). One could argue that I have to decode all these event
structures anyway, so I might as well do it in separate functions. It
makes my code larger, but if you really don't want to change the APIs,
it's fair enough. The code I've written now works.

I guess it isn't a question of "possible", but a question of
"elegant". Fundametally, everything is possible.

BTW, I was wrong about deleting callbacks, please disregard this part. I
looked into evas_object_event_callback_del again and it does take the
event type into account when deleting callbacks.

--J.

> > Context: writing foreign language bindings to Evas
> > 
> > I've encountered some snags with Evas callbacks and thought I'd ask
> > for advice (and possibly suggest a better API).
> > 
> > Overall, the problem is that Evas assumes in a number of places that
> > one object event callback == exactly one C function.
> > 
> > When writing bindings for any dynamic language one would usually want
> > to pass all events through one or two C-level callback functions, so
> > as to decode and convert the event structures. But the current API
> > pretty much requires that there be exactly one C function per event
> > handled: event type is not passed to the callback, so the function
> > called needs to be specialized in advance for that one particular
> > type.
> > 
> > In dynamic languages there is usually no "compile" step (or it is
> > optional), so there is no way of knowing ahead if time which callbacks
> > will be needed. At a certain point in time the program may request a
> > certain type of callback to be added. It would be good to be able to
> > do it without necessarily needing to create a completely separate C
> > function to handle just this one particular callback case.
> > 
> > The other issue is how to delete unwanted callbacks. At present
> > callbacks are uniquely identified by the C function pointer. This
> > makes it impossible to have one function handle several events --
> > evas_object_event_callback_delete removes by comparing function
> > pointers.
> > 
> > So, on to humble suggestions:
> > 
> > 1. IMHO evas object event callbacks should be uniquely identified by
> > the triplet (Evas_Object, Event_Type, function_ptr). That's what you
> > pass in when you call evas_object_event_callback_add, so that's what
> > you should pass when deleting the callback. I'm not sure if an object
> > can belong to multiple Evases, so I don't know if Evas should be used
> > as well.
> > 
> > 2. IMHO the callback function should receive the event type as one of
> > its parameters.
> > 
> > 3. Overall, IMHO we should not assume that one callback always equals
> > one C function. I can imagine a number of cases where I'd want to have
> > a dispatching function handling multiple event types or events from
> > multiple objects (or even Evases).
> > 
> > --J.
> >