On Tue, 2009-07-14 at 18:52 +0800, Bo Yang wrote:
> Hi,
> I post this message to discuss the initial design of DOM Events
> module. Generally, the whole Events model will be implemented at
> libdom/src/events. And there are four types of Interface, they are
> DocumentEvent, EventTarget, Event and EventListener. I will describe
> how I will implement these four types of interfaces.
>
> 1. DocumentEvent. This interface is used to create event objects and
> will be implemented as part of dom_document. So, now, dom_document at
> least need to implement two different Interfaces: Document and
> DocumentEvent. And this situation will occur again when we deal with
> other Interfaces such as EventTarget later. So, we should figure out a
> common way to let one type of C struct to implement multiple
> Interface. Generally, I advise a method below:
>
> struct dom_document_event {
> dom_event_listener * (*default_action)(lwc_string *node_name,
> lwc_string *event_type) da;
>
> /* Nearlly all elements have its default handler, such as, an
> Anchor element will cause a new page opened when click event occur.
> And I think Netsurf is the approtiate handler for this event. So, I
> think it is better to let the client of our dom events module pass a
> function to us which we use to fetch the default hanlder for all
> default action */
> };
Seems sensible.
> And then add a new member to dom_document.
>
> struct dom_document {
> /* original members */
> struct dom_document_event de;
> };
Fine.
> And the method createEvent will be defined as macro like:
>
> #define DOM_DOCUMENT_EVENT(d) &(d->de)
>
> #define dom_document_event_create_event(dt, name)
> _dom_document_event_create_event(DOM_DOCUMENT_EVENT(d), name)
>
> This makes all functions of dom_document_event accept
> dom_document_event * as first param, and I think this is better. To
> access the dom_document which contain the dom_document_event, we can :
>
> #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
> #define DOM_DOCUMENT(de) ((struct dom_document *) (de -
> offsetof(dom_document, de)))
Is there a need to do it this way? Is it not simpler just to pass in the
document itself? Certainly, the mechanism for retrieving the document,
above, seems unpleasant.
> So, that's the DocumentEvent Interface.
>
> 2. EventTarget. This interface will be implemented in
> dom_node_internal, using the same method with 1. We got:
>
> sturct dom_node_internal {
> /* original members */
> struct dom_event_target et;
> };
>
> And all the Macroes above are similar.
Agreed, though my commentary above applies here, too.
> 3. Event and its subclasses. Just as Node and its subclasses, I will
> use the same method to implement these classes. But because there is
> no overriden functions, I want to use no vtable in Events class tree.
> And change it to use vtable when necessary.
That seems ok. Certainly, it's not very difficult to migrate to vtables
if needed. That said, there's a good argument that consistency in method
dispatch would be less confusing.
> 4. EventListener. Something like:
>
> struct dom_event_listener {
> void *private;
> bool (*handle)(dom_event *e, void *private) handler;
> };
Looks ok.
> Boostrap:
> The Events module is used to provide a mechanism to dispatch the Event
> on the DOM tree, for most cases, it need its client to provide some
> default action for certain kind of elements (just like what 1 said).
> This may require our client to pass a function pointer (just like pass
> in the allocator) when create the document. So, the create_document
> method may need to be added a new param:
>
> create_document(dom_implementation *impl,
> struct dom_string *namespace,
> struct dom_string *qname,
> struct dom_document_type *doctype,
> dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
> dom_event_listener * (*default_action)(lwc_string
> *node_name, lwc_string *event_type) da,
> struct dom_document **doc);
>
I think that should work, yes.
J.