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 */
};
And then add a new member to dom_document.
struct dom_document {
/* original members */
struct dom_document_event de;
};
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)))
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.
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.
4. EventListener. Something like:
struct dom_event_listener {
void *private;
bool (*handle)(dom_event *e, void *private) handler;
};
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);
That's all about my idea of Events model, please post any questions
about this. And any advice is welcomed!
Regards!
Bo