From 13fadb12fb400818e0ccb4c38b3bfce70ccfdad2 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Thu, 13 Aug 2009 09:33:24 +0000 Subject: Merge the Events module (branches/struggleyb/libdom-events) back to trunk. :) svn path=/trunk/dom/; revision=9236 --- src/events/Makefile | 7 + src/events/custom_event.c | 99 +++++ src/events/custom_event.h | 36 ++ src/events/document_event.c | 188 ++++++++ src/events/document_event.h | 62 +++ src/events/event.c | 354 +++++++++++++++ src/events/event.h | 81 ++++ src/events/event_listener.c | 62 +++ src/events/event_listener.h | 28 ++ src/events/event_target.c | 812 +++++++++++++++++++++++++++++++++++ src/events/event_target.h | 88 ++++ src/events/keyboard_event.c | 354 +++++++++++++++ src/events/keyboard_event.h | 55 +++ src/events/mouse_event.c | 366 ++++++++++++++++ src/events/mouse_event.h | 49 +++ src/events/mouse_multi_wheel_event.c | 152 +++++++ src/events/mouse_multi_wheel_event.h | 44 ++ src/events/mouse_wheel_event.c | 115 +++++ src/events/mouse_wheel_event.h | 40 ++ src/events/mutation_event.c | 226 ++++++++++ src/events/mutation_event.h | 45 ++ src/events/mutation_name_event.c | 159 +++++++ src/events/mutation_name_event.h | 42 ++ src/events/text_event.c | 125 ++++++ src/events/text_event.h | 40 ++ src/events/ui_event.c | 138 ++++++ src/events/ui_event.h | 54 +++ 27 files changed, 3821 insertions(+) create mode 100644 src/events/Makefile create mode 100644 src/events/custom_event.c create mode 100644 src/events/custom_event.h create mode 100644 src/events/document_event.c create mode 100644 src/events/document_event.h create mode 100644 src/events/event.c create mode 100644 src/events/event.h create mode 100644 src/events/event_listener.c create mode 100644 src/events/event_listener.h create mode 100644 src/events/event_target.c create mode 100644 src/events/event_target.h create mode 100644 src/events/keyboard_event.c create mode 100644 src/events/keyboard_event.h create mode 100644 src/events/mouse_event.c create mode 100644 src/events/mouse_event.h create mode 100644 src/events/mouse_multi_wheel_event.c create mode 100644 src/events/mouse_multi_wheel_event.h create mode 100644 src/events/mouse_wheel_event.c create mode 100644 src/events/mouse_wheel_event.h create mode 100644 src/events/mutation_event.c create mode 100644 src/events/mutation_event.h create mode 100644 src/events/mutation_name_event.c create mode 100644 src/events/mutation_name_event.h create mode 100644 src/events/text_event.c create mode 100644 src/events/text_event.h create mode 100644 src/events/ui_event.c create mode 100644 src/events/ui_event.h (limited to 'src/events') diff --git a/src/events/Makefile b/src/events/Makefile new file mode 100644 index 0000000..5b881b7 --- /dev/null +++ b/src/events/Makefile @@ -0,0 +1,7 @@ +# Sources +DIR_SOURCES := event.c event_target.c document_event.c \ + custom_event.c keyboard_event.c mouse_wheel_event.c \ + text_event.c event_listener.c mouse_event.c mutation_event.c \ + ui_event.c mouse_multi_wheel_event.c mutation_name_event.c + +include build/makefiles/Makefile.subdir diff --git a/src/events/custom_event.c b/src/events/custom_event.c new file mode 100644 index 0000000..920c23e --- /dev/null +++ b/src/events/custom_event.c @@ -0,0 +1,99 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/custom_event.h" + +#include "core/document.h" + +static void _virtual_dom_custom_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_custom_event_destroy +}; + +/* Constructor */ +dom_exception _dom_custom_event_create(struct dom_document *doc, + struct dom_custom_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_custom_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_custom_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_custom_event_destroy(struct dom_document *doc, + struct dom_custom_event *evt) +{ + _dom_custom_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_custom_event_initialise(struct dom_document *doc, + struct dom_custom_event *evt) +{ + evt->detail = NULL; + return _dom_event_initialise(doc, &evt->base); +} + +/* Finalise function */ +void _dom_custom_event_finalise(struct dom_document *doc, + struct dom_custom_event *evt) +{ + evt->detail = NULL; + _dom_event_finalise(doc, &evt->base); +} + +/* The virtual destroy function */ +void _virtual_dom_custom_event_destroy(struct dom_event *evt) +{ + _dom_custom_event_destroy(evt->doc, (dom_custom_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the detail object of this custom event + * + * \param evt The Event object + * \param detail The returned detail object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_custom_event_get_detail(dom_custom_event *evt, + void **detail) +{ + *detail = evt->detail; + + return DOM_NO_ERR; +} + +/** + * Initialise this custom event + * + * \param evt The Event object + * \param namespace The namespace of this new Event + * \param type The Event type + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param detail The detail object of this custom event + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_custom_event_init_ns(dom_custom_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, void *detail) +{ + evt->detail = detail; + return _dom_event_init_ns(&evt->base, namespace, type, bubble, + cancelable); +} + diff --git a/src/events/custom_event.h b/src/events/custom_event.h new file mode 100644 index 0000000..a50bc23 --- /dev/null +++ b/src/events/custom_event.h @@ -0,0 +1,36 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_custom_event_h_ +#define dom_interntal_events_custom_event_h_ + +#include + +#include "events/event.h" + +struct dom_custom_event { + struct dom_event base; + void *detail; +}; + +/* Constructor */ +dom_exception _dom_custom_event_create(struct dom_document *doc, + struct dom_custom_event **evt); + +/* Destructor */ +void _dom_custom_event_destroy(struct dom_document *doc, + struct dom_custom_event *evt); + +/* Initialise function */ +dom_exception _dom_custom_event_initialise(struct dom_document *doc, + struct dom_custom_event *evt); + +/* Finalise function */ +void _dom_custom_event_finalise(struct dom_document *doc, + struct dom_custom_event *evt); + +#endif diff --git a/src/events/document_event.c b/src/events/document_event.c new file mode 100644 index 0000000..47afed6 --- /dev/null +++ b/src/events/document_event.c @@ -0,0 +1,188 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include + +#include + +#include "core/string.h" +#include "core/node.h" +#include "core/document.h" +#include "events/document_event.h" +#include "events/event.h" +#include "events/ui_event.h" +#include "events/custom_event.h" +#include "events/text_event.h" +#include "events/keyboard_event.h" +#include "events/mouse_event.h" +#include "events/mouse_multi_wheel_event.h" +#include "events/mouse_wheel_event.h" +#include "events/mutation_event.h" +#include "events/mutation_name_event.h" + +#include "utils/utils.h" + +static const char *__event_types[] = { + "Event", + "CustomEvent", + "UIEvent", + "TextEvent", + "KeyboardEvent", + "MouseEvent", + "MouseMultiWheelEvent", + "MouseWheelEvent", + "MutationEvent", + "MutationNameEvent" +}; + +/** + * Initialise this DocumentEvent + * + * \param doc The document object + * \param dei The DocumentEvent internal object + * \param actions The default action fetcher, the browser should provide such + * a function to Event module. + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_document_event_internal_initialise(struct dom_document *doc, + dom_document_event_internal *dei, + dom_events_default_action_fetcher actions) +{ + lwc_error err; + lwc_context *ctx = _dom_document_get_intern_context(doc); + int i = 0; + + for (; i < DOM_EVENT_COUNT; i++) { + err = lwc_context_intern(ctx, __event_types[i], + SLEN(__event_types[i]), &dei->event_types[i]); + if (err != lwc_error_ok) + return _dom_exception_from_lwc_error(err); + } + + dei->actions = actions; + + return DOM_NO_ERR; +} + +/* Finalise this DocumentEvent */ +void _dom_document_event_internal_finalise(struct dom_document *doc, + dom_document_event_internal *dei) +{ + /* Nothing to do here */ + UNUSED(doc); + UNUSED(dei); + return; +} + +/*-------------------------------------------------------------------------*/ +/* Public API */ + +/** + * Create an Event object + * + * \param de The DocumentEvent object + * \param type The Event type + * \param evt The returned Event object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_document_event_create_event(dom_document_event *de, + struct dom_string *type, struct dom_event **evt) +{ + lwc_context *ctx = NULL; + lwc_string *t = NULL; + dom_exception err; + struct dom_document *doc = de; + + dom_string_get_intern(type, &ctx, &t); + if (t == NULL) { + ctx = _dom_document_get_intern_context(doc); + err = _dom_string_intern(type, ctx, &t); + if (err != DOM_NO_ERR) + return err; + } + + assert(t != NULL); + + int i, et = 0; + dom_document_event_internal *dei = &de->dei; + for (i = 0; i < DOM_EVENT_COUNT; i++) { + if (dei->event_types[i] == t) { + et = i; + break; + } + } + lwc_context_string_unref(ctx, t); + + switch (et) { + case DOM_EVENT: + err = _dom_event_create(doc, evt); + break; + case DOM_CUSTOM_EVENT: + err = _dom_custom_event_create(doc, + (dom_custom_event **) evt); + break; + case DOM_UI_EVENT: + err = _dom_ui_event_create(doc, (dom_ui_event **) evt); + break; + case DOM_TEXT_EVENT: + err = _dom_text_event_create(doc, + (dom_text_event **) evt); + break; + case DOM_KEYBOARD_EVENT: + err = _dom_keyboard_event_create(doc, + (dom_keyboard_event **) evt); + break; + case DOM_MOUSE_EVENT: + err = _dom_mouse_event_create(doc, + (dom_mouse_event **) evt); + break; + case DOM_MOUSE_MULTI_WHEEL_EVENT: + err = _dom_mouse_multi_wheel_event_create(doc, + (dom_mouse_multi_wheel_event **) evt); + break; + case DOM_MOUSE_WHEEL_EVENT: + err = _dom_mouse_wheel_event_create(doc, + (dom_mouse_wheel_event **) evt); + break; + case DOM_MUTATION_EVENT: + err = _dom_mutation_event_create(doc, + (dom_mutation_event **) evt); + break; + case DOM_MUTATION_NAME_EVENT: + err = _dom_mutation_name_event_create(doc, + (dom_mutation_name_event **) evt); + break; + default: + assert("Should never be here" == NULL); + } + + return err; +} + +/** + * Tests if the implementation can generate events of a specified type + * + * \param de The DocumentEvent + * \param namespace The namespace of the event + * \param type The type of the event + * \param can True if we can generate such an event, false otherwise + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * + * We don't support this API now, so the return value should always + * DOM_NO_SUPPORTED_ERR. + */ +dom_exception _dom_document_event_can_dispatch(dom_document_event *de, + struct dom_string *namespace, struct dom_string *type, + bool *can) +{ + UNUSED(de); + UNUSED(namespace); + UNUSED(type); + UNUSED(can); + + return DOM_NOT_SUPPORTED_ERR; +} diff --git a/src/events/document_event.h b/src/events/document_event.h new file mode 100644 index 0000000..2458508 --- /dev/null +++ b/src/events/document_event.h @@ -0,0 +1,62 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_internal_events_document_event_h_ +#define dom_internal_events_document_event_h_ + +#include + +struct dom_event_listener; +struct lwc_string_s; +struct dom_document; + +/** + * Type of Events + */ +typedef enum { + DOM_EVENT = 0, + DOM_CUSTOM_EVENT, + DOM_UI_EVENT, + DOM_TEXT_EVENT, + DOM_KEYBOARD_EVENT, + DOM_MOUSE_EVENT, + DOM_MOUSE_MULTI_WHEEL_EVENT, + DOM_MOUSE_WHEEL_EVENT, + DOM_MUTATION_EVENT, + DOM_MUTATION_NAME_EVENT, + + DOM_EVENT_COUNT +} dom_event_type; + +/** + * The DocumentEvent internal class + */ +struct dom_document_event_internal { + dom_events_default_action_fetcher actions; + /**< The default action fetecher */ + struct lwc_string_s *event_types[DOM_EVENT_COUNT]; + /**< Events type names */ +}; + +typedef struct dom_document_event_internal dom_document_event_internal; + +/** + * Constructor and destructor: Since this object is not intended to be + * allocated alone, it should be embedded into the Document object, there + * is no constructor and destructor for it. + */ + +/* Initialise this DocumentEvent */ +dom_exception _dom_document_event_internal_initialise(struct dom_document *doc, + dom_document_event_internal *dei, + dom_events_default_action_fetcher actions); + +/* Finalise this DocumentEvent */ +void _dom_document_event_internal_finalise(struct dom_document *doc, + dom_document_event_internal *dei); + +#endif diff --git a/src/events/event.c b/src/events/event.c new file mode 100644 index 0000000..f9caa0b --- /dev/null +++ b/src/events/event.c @@ -0,0 +1,354 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include +#include + +#include "events/event.h" + +#include + +#include "core/string.h" +#include "core/node.h" +#include "core/document.h" + +static void _virtual_dom_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_event_destroy +}; + +/* Constructor */ +dom_exception _dom_event_create(struct dom_document *doc, + struct dom_event **evt) +{ + *evt = (dom_event *) _dom_document_alloc(doc, NULL, sizeof(dom_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + (*evt)->vtable = &_event_vtable; + + return _dom_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_event_destroy(struct dom_document *doc, struct dom_event *evt) +{ + _dom_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, sizeof(dom_event)); +} + +/* Initialise function */ +dom_exception _dom_event_initialise(struct dom_document *doc, + struct dom_event *evt) +{ + assert(doc != NULL); + + evt->doc = doc; + evt->stop = false; + evt->stop_now = false; + evt->prevent_default = false; + evt->custom = false; + + evt->type = NULL; + + evt->namespace = NULL; + + evt->timestamp = time(NULL); + + evt->refcnt = 1; + evt->in_dispatch = false; + + return DOM_NO_ERR; +} + +/* Finalise function */ +void _dom_event_finalise(struct dom_document *doc, struct dom_event *evt) +{ + assert(doc != NULL); + lwc_context *ctx = _dom_document_get_intern_context(doc); + assert(ctx != NULL); + + if (evt->type != NULL) + lwc_context_string_unref(ctx, evt->type); + if (evt->namespace != NULL) + lwc_context_string_unref(ctx, evt->namespace); +} + +/* The virtual destroy function */ +void _virtual_dom_event_destroy(struct dom_event *evt) +{ + _dom_event_destroy(evt->doc, evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Claim a reference on this event object + * + * \param evt The Event object + */ +void _dom_event_ref(dom_event *evt) +{ + evt->refcnt++; +} + +/** + * Release a reference on this event object + * + * \param evt The Event object + */ +void _dom_event_unref(dom_event *evt) +{ + if (evt->refcnt > 0) + evt->refcnt--; + + if (evt->refcnt == 0) + dom_event_destroy(evt); +} + + +/** + * Get the event type + * + * \param evt The event object + * \parnm type The returned event type + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_get_type(dom_event *evt, struct dom_string **type) +{ + struct dom_document *doc = evt->doc; + dom_exception err; + + err = _dom_document_create_string_from_lwcstring(doc, evt->type, type); + if (err != DOM_NO_ERR) + return err; + + return DOM_NO_ERR; +} + +/** + * Get the target node of this event + * + * \param evt The event object + * \param target The target node + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_get_target(dom_event *evt, dom_event_target **target) +{ + *target = evt->target; + dom_node_ref(*target); + + return DOM_NO_ERR; +} + +/** + * Get the current target of this event + * + * \param evt The event object + * \param current The current event target node + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_get_current_target(dom_event *evt, + dom_event_target **current) +{ + *current = evt->current; + dom_node_ref(*current); + + return DOM_NO_ERR; +} + +/** + * Get whether this event can bubble + * + * \param evt The Event object + * \param bubbles The returned value + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_get_bubbles(dom_event *evt, bool *bubbles) +{ + *bubbles = evt->bubble; + return DOM_NO_ERR; +} + +/** + * Get whether this event can be cancelable + * + * \param evt The Event object + * \param cancelable The returned value + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_get_cancelable(dom_event *evt, bool *cancelable) +{ + *cancelable = evt->cancelable; + return DOM_NO_ERR; +} + +/** + * Get the event's generation timestamp + * + * \param evt The Event object + * \param timestamp The returned value + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_get_timestamp(dom_event *evt, unsigned int *timestamp) +{ + *timestamp = evt->timestamp; + return DOM_NO_ERR; +} + +/** + * Stop propagation of the event + * + * \param evt The Event object + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_stop_propagation(dom_event *evt) +{ + evt->stop = true; + + return DOM_NO_ERR; +} + +/** + * Prevent the default action of this event + * + * \param evt The Event object + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_prevent_default(dom_event *evt) +{ + evt->prevent_default = true; + return DOM_NO_ERR; +} + +/** + * Initialise the event object + * + * \param evt The event object + * \param type The type of this event + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_init(dom_event *evt, struct dom_string *type, + bool bubble, bool cancelable) +{ + assert(evt->doc != NULL); + lwc_context *ctx = _dom_document_get_intern_context(evt->doc); + lwc_string *str = NULL; + dom_exception err; + + err = _dom_string_intern(type, ctx, &str); + if (err != DOM_NO_ERR) + return err; + + evt->type = str; + evt->bubble = bubble; + evt->cancelable = cancelable; + + return DOM_NO_ERR; +} + +/** + * Get the namespace of this event + * + * \param evt The event object + * \param namespace The returned namespace of this event + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_get_namespace(dom_event *evt, + struct dom_string **namespace) +{ + struct dom_document *doc = evt->doc; + dom_exception err; + + err = _dom_document_create_string_from_lwcstring(doc, evt->namespace, + namespace); + if (err != DOM_NO_ERR) + return err; + + return DOM_NO_ERR; +} + +/** + * Whether this is a custom event + * + * \param evt The event object + * \param custom The returned value + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_is_custom(dom_event *evt, bool *custom) +{ + *custom = evt->custom; + + return DOM_NO_ERR; +} + +/** + * Stop the event propagation immediately + * + * \param evt The event object + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_stop_immediate_propagation(dom_event *evt) +{ + evt->stop_now = true; + + return DOM_NO_ERR; +} + +/** + * Whether the default action is prevented + * + * \param evt The event object + * \param prevented The returned value + * \return DOM_NO_ERR. + */ +dom_exception _dom_event_is_default_prevented(dom_event *evt, bool *prevented) +{ + *prevented = evt->prevent_default; + + return DOM_NO_ERR; +} + +/** + * Initialise the event with namespace + * + * \param evt The event object + * \param namespace The namespace of this event + * \param type The event type + * \param bubble Whether this event has a bubble phase + * \param cancelable Whether this event is cancelable + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_init_ns(dom_event *evt, struct dom_string *namespace, + struct dom_string *type, bool bubble, bool cancelable) +{ + assert(evt->doc != NULL); + lwc_context *ctx = _dom_document_get_intern_context(evt->doc); + lwc_string *str = NULL; + dom_exception err; + + err = _dom_string_intern(type, ctx, &str); + if (err != DOM_NO_ERR) + return err; + evt->type = str; + + err = _dom_string_intern(namespace, ctx, &str); + if (err != DOM_NO_ERR) + return err; + evt->namespace = str; + + evt->bubble = bubble; + evt->cancelable = cancelable; + + return DOM_NO_ERR; +} + diff --git a/src/events/event.h b/src/events/event.h new file mode 100644 index 0000000..4d094e9 --- /dev/null +++ b/src/events/event.h @@ -0,0 +1,81 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_internal_events_event_h_ +#define dom_internal_events_event_h_ + +#include + +#include +#include + +#include "utils/list.h" + +struct lwc_string_s; +struct dom_document; + +/* The private virtual table */ +struct dom_event_private_vtable { + void (*destroy)(dom_event *evt); +}; + +/** + * The Event Ojbect + */ +struct dom_event { + struct lwc_string_s *type; /**< The type of the event */ + dom_event_target *target; /**< The event target */ + dom_event_target *current; /**< The current event target */ + dom_event_flow_phase phase; /**< The event phase */ + bool bubble; /**< Whether this event is a bubbling event */ + bool cancelable; /**< Whether this event is cancelable */ + unsigned int timestamp; + /**< The timestamp this event is created */ + + struct lwc_string_s *namespace; + /**< The namespace of this event */ + + struct dom_document *doc; + /**< The document which create this event */ + + bool stop; /**< Whether stopPropagation is called */ + bool stop_now; /**< Whether stopImmediatePropagation is called */ + bool prevent_default; + /**< Whether the default action is prevented */ + + bool custom; /**< Whether this is a custom event */ + + uint32_t refcnt; /**< The reference count of this object */ + + struct dom_event_private_vtable *vtable; + /**< The private virtual function table of Event */ + bool in_dispatch; /**< Whether this event is in dispatch */ +}; + +/* Constructor */ +dom_exception _dom_event_create(struct dom_document *doc, + struct dom_event **evt); + +/* Destructor */ +void _dom_event_destroy(struct dom_document *doc, struct dom_event *evt); + +/* Initialise function */ +dom_exception _dom_event_initialise(struct dom_document *doc, + struct dom_event *evt); + +/* Finalise function */ +void _dom_event_finalise(struct dom_document *doc, struct dom_event *evt); + + +static inline void dom_event_destroy(struct dom_event *evt) +{ + evt->vtable->destroy(evt); +} +#define dom_event_destroy(e) dom_event_destroy((struct dom_event *) (e)) + +#endif + diff --git a/src/events/event_listener.c b/src/events/event_listener.c new file mode 100644 index 0000000..3c3c14c --- /dev/null +++ b/src/events/event_listener.c @@ -0,0 +1,62 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/event_listener.h" +#include "core/document.h" + +/** + * Create an EventListener + * + * \param doc The document object + * \param handler The event function + * \param pw The private data + * \param listener The returned EventListener + * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion. + */ +dom_exception dom_event_listener_create(struct dom_document *doc, + handle_event handler, void *pw, dom_event_listener **listener) +{ + dom_event_listener *ret = (dom_event_listener *) _dom_document_alloc( + doc, NULL, sizeof(dom_event_listener)); + if (ret == NULL) + return DOM_NO_MEM_ERR; + + ret->handler = handler; + ret->pw = pw; + ret->refcnt = 1; + ret->doc = doc; + + *listener = ret; + + return DOM_NO_ERR; +} + +/** + * Claim a new reference on the listener object + * + * \param listener The EventListener object + */ +void dom_event_listener_ref(dom_event_listener *listener) +{ + listener->refcnt++; +} + +/** + * Release a reference on the listener object + * + * \param listener The EventListener object + */ +void dom_event_listener_unref(dom_event_listener *listener) +{ + if (listener->refcnt > 0) + listener->refcnt--; + + if (listener->refcnt == 0) + _dom_document_alloc(listener->doc, listener, + sizeof(dom_event_listener)); +} + diff --git a/src/events/event_listener.h b/src/events/event_listener.h new file mode 100644 index 0000000..c85be85 --- /dev/null +++ b/src/events/event_listener.h @@ -0,0 +1,28 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_internal_events_event_listener_h_ +#define dom_internal_events_event_listener_h_ + +#include + +#include "utils/list.h" + +/** + * The EventListener class + */ +struct dom_event_listener { + handle_event handler; /**< The event handler function */ + void *pw; /**< The private data of this listener */ + + unsigned int refcnt; /**< The reference count of this listener */ + struct dom_document *doc; + /**< The document which create this listener */ +}; + +#endif + diff --git a/src/events/event_target.c b/src/events/event_target.c new file mode 100644 index 0000000..e17aa9c --- /dev/null +++ b/src/events/event_target.c @@ -0,0 +1,812 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include + +#include + +#include "events/event.h" +#include "events/event_listener.h" +#include "events/event_target.h" + +#include "core/document.h" +#include "core/node.h" +#include "core/string.h" + +#include "utils/utils.h" +#include "utils/validate.h" + +/* The number of chains in the hash table used for hash event types */ +#define CHAINS 11 + +/* Entry for a EventTarget, used to record the bubbling list */ +typedef struct dom_event_target_entry { + struct list_entry entry; /**< The list entry */ + dom_event_target *et; /**< The node */ +} dom_event_target_entry; + +/* Hash key/value functions */ +static void *_key(void *key, void *key_pw, dom_alloc alloc, void *pw, + bool clone); +static void *_value(void *value, void *value_pw, dom_alloc alloc, + void *pw, bool clone); + + +/* Initialise this EventTarget */ +dom_exception _dom_event_target_internal_initialise(struct dom_document *doc, + dom_event_target_internal *eti) +{ + UNUSED(doc); + eti->listeners = NULL; + eti->ns_listeners = NULL; + + return DOM_NO_ERR; +} + +/* Finalise this EventTarget */ +void _dom_event_target_internal_finalise(struct dom_document *doc, + dom_event_target_internal *eti) +{ + lwc_context *ctx = _dom_document_get_intern_context(doc); + + if (eti->listeners != NULL) + _dom_hash_destroy(eti->listeners, _key, ctx, _value, doc); + /* TODO: Now, we did not support the EventListener with namespace, + * when we support it, we should deal with the ns_listeners hash + * table, too. + */ +} + +/*-------------------------------------------------------------------------*/ +/* The public API */ + +/** + * Add an EventListener to the EventTarget + * + * \param et The EventTarget object + * \param type The event type which this event listener listens for + * \param listener The event listener object + * \param capture Whether add this listener in the capturing phase + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_target_add_event_listener(dom_event_target *et, + struct dom_string *type, struct dom_event_listener *listener, + bool capture) +{ + struct listener_entry *le = NULL; + struct dom_document *doc = dom_node_get_owner(et); + assert(doc != NULL); + + struct dom_event_target_internal *eti = &et->eti; + lwc_string *t = NULL; + lwc_context *ctx = NULL; + dom_exception err; + + /* If there is no hash table, we should create one firstly */ + if (eti->listeners == NULL) { + err = _dom_document_create_hashtable(doc, CHAINS, + _dom_hash_hash_lwcstring, &eti->listeners); + if (err != DOM_NO_ERR) + return err; + } + + err = dom_string_get_intern(type, &ctx, &t); + if (err != DOM_NO_ERR) + return err; + + ctx = _dom_document_get_intern_context(doc); + if (t == NULL) { + err = _dom_string_intern(type, ctx, &t); + if (err != DOM_NO_ERR) + return err; + } else { + lwc_context_string_ref(ctx, t); + } + + assert(t != NULL); + + le = (struct listener_entry *) _dom_document_alloc(doc, NULL, + sizeof(struct listener_entry)); + if (le == NULL) + return DOM_NO_MEM_ERR; + + /* Initialise the listener_entry */ + list_init(&le->list); + le->listener = listener; + dom_event_listener_ref(listener); + le->capture = capture; + + /* Find the type of this event */ + struct list_entry *item = (struct list_entry *) _dom_hash_get( + eti->listeners, t); + if (item == NULL) { + /* If there is no item in the hash table, we should add the + * first */ + _dom_hash_add(eti->listeners, t, &le->list, false); + } else { + /* Append this listener to the end of the list */ + list_append(item, &le->list); + } + + return DOM_NO_ERR; +} + +/** + * Remove an EventListener from the EventTarget + * + * \param et The EventTarget object + * \param type The event type this listener is registered for + * \param listener The listener object + * \param capture Whether the listener is registered at the capturing phase + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_target_remove_event_listener(dom_event_target *et, + struct dom_string *type, struct dom_event_listener *listener, + bool capture) +{ + struct listener_entry *le = NULL; + struct dom_document *doc = dom_node_get_owner(et); + if (doc == NULL) { + /* TODO: In the progress of parsing, many Nodes in the DTD + * has no document at all, do nothing for this kind of node */ + return DOM_NO_ERR; + } + + struct dom_event_target_internal *eti = &et->eti; + lwc_string *t = NULL; + lwc_context *ctx = NULL; + dom_exception err; + + err = dom_string_get_intern(type, &ctx, &t); + if (err != DOM_NO_ERR) + return err; + + ctx = _dom_document_get_intern_context(doc); + if (t == NULL) { + err = _dom_string_intern(type, ctx, &t); + if (err != DOM_NO_ERR) + return err; + } else { + lwc_context_string_ref(ctx, t); + } + + assert(t != NULL); + + /* Find the type of this event */ + struct list_entry *item = (struct list_entry *) _dom_hash_get( + eti->listeners, t); + if (item == NULL) { + /* There is no such event listener */ + lwc_context_string_unref(ctx, t); + return DOM_NO_ERR; + } else { + struct list_entry *i = item; + do { + le = (struct listener_entry *) i; + if (le->listener == listener && + le->capture == capture) { + /* We found the listener */ + list_del(i); + dom_event_listener_unref(le->listener); + _dom_document_alloc(doc, le, + sizeof(struct listener_entry)); + break; + } + i = i->next; + } while(i != item); + } + + return DOM_NO_ERR; +} + +/** + * Dispatch an event into the implementation's event model + * + * \param et The EventTarget object + * \param evt The event object + * \param success Indicates whether any of the listeners which handled the + * event called Event.preventDefault(). If + * Event.preventDefault() was called the returned value is + * false, else it is true. + * \return DOM_NO_ERR on success + * DOM_DISPATCH_REQUEST_ERR If the event is already in dispatch + * DOM_UNSPECIFIED_EVENT_TYPE_ERR If the type of the event is Null or + * empty string. + * DOM_NOT_SUPPORTED_ERR If the event is not created by + * Document.createEvent + * DOM_INVALID_CHARACTER_ERR If the type of this event is not a + * valid NCName. + */ +dom_exception _dom_event_target_dispatch_event(dom_event_target *et, + struct dom_event *evt, bool *success) +{ + assert(et != NULL); + + dom_exception err, ret = DOM_NO_ERR; + + /* To test whether this event is in dispatch */ + if (evt->in_dispatch == true) { + return DOM_DISPATCH_REQUEST_ERR; + } else { + evt->in_dispatch = true; + } + + if (evt->type == NULL || lwc_string_length(evt->type) == 0) { + return DOM_UNSPECIFIED_EVENT_TYPE_ERR; + } + + if (evt->doc == NULL) + return DOM_NOT_SUPPORTED_ERR; + + struct dom_document *doc = dom_node_get_owner(et); + if (doc == NULL) { + /* TODO: In the progress of parsing, many Nodes in the DTD has + * no document at all, do nothing for this kind of node */ + return DOM_NO_ERR; + } + + struct dom_string *type = NULL; + err = _dom_document_create_string_from_lwcstring(doc, evt->type, &type); + if (err != DOM_NO_ERR) + return err; + + if (_dom_validate_ncname(type) == false) { + dom_string_unref(type); + return DOM_INVALID_CHARACTER_ERR; + } + dom_string_unref(type); + + lwc_string *t = evt->type; + lwc_context *ctx = NULL; + dom_event_target_entry list; + dom_event_target *target = et; + + ctx = _dom_document_get_intern_context(doc); + assert(t != NULL); + + *success = true; + + /* Compose the event target list */ + list_init(&list.entry); + list.et = et; + dom_node_ref(et); + target = target->parent; + + while (target != NULL) { + dom_event_target_entry *l = (dom_event_target_entry *) + _dom_document_alloc(doc, NULL, + sizeof(dom_event_target_entry)); + if (l == NULL) { + ret = DOM_NO_MEM_ERR; + goto cleanup; + } + list_append(&list.entry, &l->entry); + l->et = target; + dom_node_ref(target); + target = target->parent; + } + + /* Fill the target of the event */ + evt->target = et; + evt->phase = DOM_CAPTURING_PHASE; + + /* The capture phase */ + struct list_entry *e = list.entry.prev; + for (; e != &list.entry; e = e->prev) { + dom_event_target_entry *l = (dom_event_target_entry *) e; + err = _dom_event_target_dispatch(l->et, evt, + DOM_CAPTURING_PHASE, success); + if (err != DOM_NO_ERR) { + ret = err; + goto cleanup; + } + /* If the stopImmediatePropagation or stopPropagation is + * called, we should break */ + if (evt->stop_now == true || evt->stop == true) + goto cleanup; + } + + /* Target phase */ + evt->phase = DOM_AT_TARGET; + evt->current = et; + err = _dom_event_target_dispatch(et, evt, DOM_AT_TARGET, + success); + if (evt->stop_now == true || evt->stop == true) + goto cleanup; + + /* Bubbling phase */ + evt->phase = DOM_BUBBLING_PHASE; + + e = list.entry.next; + for (; e != &list.entry; e = e->next) { + dom_event_target_entry *l = (dom_event_target_entry *) e; + err = _dom_event_target_dispatch(l->et, evt, + DOM_BUBBLING_PHASE, success); + if (err != DOM_NO_ERR) { + ret = err; + goto cleanup; + } + /* If the stopImmediatePropagation or stopPropagation is + * called, we should break */ + if (evt->stop_now == true || evt->stop == true) + goto cleanup; + } + + struct dom_document_event_internal *dei = &doc->dei; + if (dei->actions == NULL || evt->prevent_default == true) + goto cleanup; + + /* The default action */ + struct dom_string *nodename; + err = dom_node_get_node_name(et, &nodename); + if (err != DOM_NO_ERR) { + ret = err; + goto cleanup; + } + lwc_string *lnodename = NULL; + lwc_context *lctx = NULL; + err = dom_string_get_intern(nodename, &lctx, &lnodename); + if (err != DOM_NO_ERR) { + dom_string_unref(nodename); + ret = err; + goto cleanup; + } + + dom_event_listener *da = dei->actions(lnodename, t); + if (da != NULL) { + da->handler(evt, da->pw); + } + + dom_string_unref(nodename); + lwc_context_string_unref(lctx, lnodename); + lwc_context_unref(lctx); + +cleanup: + if (evt->prevent_default == true) { + *success = false; + } + + while (list.entry.next != &list.entry) { + dom_event_target_entry *e = (dom_event_target_entry *) + list.entry.next; + dom_node_unref(e->et); + list_del(list.entry.next); + _dom_document_alloc(doc, e, 0); + } + + dom_node_unref(et); + + return ret; +} + +/** + * Add an EventListener + * + * \param et The EventTarget object + * \param namespace The namespace of this listener + * \param type The event type which this event listener listens for + * \param listener The event listener object + * \param capture Whether add this listener in the capturing phase + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * + * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR. + */ +dom_exception _dom_event_target_add_event_listener_ns(dom_event_target *et, + struct dom_string *namespace, struct dom_string *type, + struct dom_event_listener *listener, bool capture) +{ + UNUSED(et); + UNUSED(namespace); + UNUSED(type); + UNUSED(listener); + UNUSED(capture); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Remove an EventListener + * + * \param et The EventTarget object + * \param namespace The namespace of this listener + * \param type The event type which this event listener listens for + * \param listener The event listener object + * \param capture Whether add this listener in the capturing phase + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * + * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR. + */ +dom_exception _dom_event_target_remove_event_listener_ns(dom_event_target *et, + struct dom_string *namespace, struct dom_string *type, + struct dom_event_listener *listener, bool capture) +{ + UNUSED(et); + UNUSED(namespace); + UNUSED(type); + UNUSED(listener); + UNUSED(capture); + + return DOM_NOT_SUPPORTED_ERR; +} + +/*-------------------------------------------------------------------------*/ + +/* The key process function of the hash table, see utils/hash_table.h for + * detail */ +static void *_key(void *key, void *key_pw, dom_alloc alloc, void *pw, + bool clone) +{ + UNUSED(alloc); + UNUSED(pw); + /* There should never be the requirement of clone the event listener + * list */ + assert(clone == false); + UNUSED(clone); + + lwc_context *ctx = (lwc_context *) key_pw; + lwc_context_string_unref(ctx, (lwc_string *) key); + + return NULL; +} + +/* The value process function of the hash table, see utils/hash_table.h for + * detail */ +static void *_value(void *value, void *value_pw, dom_alloc alloc, + void *pw, bool clone) +{ + UNUSED(alloc); + UNUSED(pw); + /* There should never be the requirement of clone the event listener + * list */ + assert(clone == false); + UNUSED(clone); + + struct listener_entry *le = NULL; + struct dom_document *doc = (struct dom_document *) value_pw; + struct list_entry *i = (struct list_entry *) value; + + while(i != i->next) { + le = (struct listener_entry *) i->next; + list_del(i->next); + dom_event_listener_unref(le->listener); + _dom_document_alloc(doc, le, sizeof(struct listener_entry)); + } + + le = (struct listener_entry *) i; + list_del(i); + dom_event_listener_unref(le->listener); + _dom_document_alloc(doc, le, sizeof(struct listener_entry)); + + return NULL; +} + +/*-------------------------------------------------------------------------*/ + +/** + * Dispatch an event on certain EventTarget + * + * \param et The EventTarget object + * \param evt The event object + * \param success Indicates whether any of the listeners which handled the + * event called Event.preventDefault(). If + * Event.preventDefault() was called the returned value is + * false, else it is true. + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_event_target_dispatch(dom_event_target *et, + struct dom_event *evt, dom_event_flow_phase phase, + bool *success) +{ + struct dom_event_target_internal *eti = &et->eti; + lwc_string *t = evt->type; + + struct list_entry *item = (struct list_entry *) _dom_hash_get( + eti->listeners, t); + if (item == NULL) { + /* There is no such event listener */ + return DOM_NO_ERR; + } else { + /* Call the handler for each listener */ + struct list_entry *i = item; + /* Fill the Event fields */ + evt->current = et; + do { + struct listener_entry *le = + (struct listener_entry *) i; + assert(le->listener->handler != NULL); + if ((le->capture == true && + phase == DOM_CAPTURING_PHASE) || + (le->capture == false && + phase == DOM_BUBBLING_PHASE) || + (evt->target == evt->current && + phase == DOM_AT_TARGET)) { + /* We found the listener */ + le->listener->handler(evt, le->listener->pw); + /* If the handler call + * stopImmediatedPropagation, we should + * break */ + if (evt->stop_now == true) + break; + } + i = i->next; + } while(i != item); + } + + if (evt->prevent_default == true) + *success = false; + + return DOM_NO_ERR; +} + +/** + * Dispatch a DOMNodeInserted/DOMNodeRemoved event + * + * \param doc The document object + * \param et The EventTarget object + * \param type "DOMNodeInserted" or "DOMNodeRemoved" + * \param related The parent of the removed/inserted node + * \param success Whether this event's default action get called + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_dispatch_node_change_event(struct dom_document *doc, + dom_event_target *et, dom_event_target *related, + dom_mutation_type change, bool *success) +{ + struct dom_mutation_event *evt; + dom_exception err; + + err = _dom_mutation_event_create(doc, &evt); + if (err != DOM_NO_ERR) + return err; + + lwc_string *type = NULL; + if (change == DOM_MUTATION_ADDITION) { + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMNodeInserted", + SLEN("DOMNodeInserted"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + } else if (change == DOM_MUTATION_REMOVAL) { + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMNodeRemoval", + SLEN("DOMNodeRemoved"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + } else { + assert("Should never be here" == NULL); + } + + dom_string *t = NULL; + err = _dom_document_create_string_from_lwcstring(doc, type, &t); + _dom_document_unref_lwcstring(doc, type); + if (err != DOM_NO_ERR) + goto cleanup; + + /* Initiliase the event with corresponding parameters */ + err = dom_mutation_event_init(evt, t, true, false, related, NULL, NULL, + NULL, change); + dom_string_unref(t); + if (err != DOM_NO_ERR) { + goto cleanup; + } + + err = dom_event_target_dispatch_event(et, evt, success); + if (err != DOM_NO_ERR) + goto cleanup; + + /* Finalise the evt, and reuse it */ + _dom_mutation_event_finalise(doc, evt); + /* Dispatch the DOMNodeInsertedIntoDocument/DOMNodeRemovedFromDocument + * event */ + if (change == DOM_MUTATION_ADDITION) { + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) + "DOMNodeInsertedIntoDocument", + SLEN("DOMNodeInsertedIntoDocument"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + } else if (change == DOM_MUTATION_REMOVAL) { + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMNodeRemovedFromDocument", + SLEN("DOMNodeRemovedFromDocument"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + } else { + assert("Should never be here" == NULL); + } + + err = _dom_document_create_string_from_lwcstring(doc, type, &t); + _dom_document_unref_lwcstring(doc, type); + if (err != DOM_NO_ERR) + goto cleanup; + + dom_event_target *target = et; + while (target != NULL) { + err = dom_mutation_event_init(evt, t, true, false, NULL, + NULL, NULL, NULL, change); + if (err != DOM_NO_ERR) + goto cleanup; + + err = dom_event_target_dispatch_event(target, evt, success); + if (err != DOM_NO_ERR) + goto cleanup; + + dom_event_target *p = dom_node_get_parent(target); + if (target->first_child != NULL) { + target = target->first_child; + } else if (target->next != NULL) { + target = target->next; + } else { + while (p != et && target == p->first_child) { + target = p; + p = dom_node_get_parent(p); + } + + target = target->next; + } + /* Finalise the event for reuse in next iteration */ + _dom_mutation_event_finalise(doc, evt); + } + +cleanup: + _dom_mutation_event_destroy(doc, evt); + + return err; +} + +/** + * Dispatch a DOMAttrModified event + * + * \param doc The Document object + * \param et The EventTarget + * \param prev The previous value before change + * \param new The new value after change + * \param related The related EventTarget + * \param attr_name The Attribute name + * \param change How this attribute change + * \param success Whether this event's default handler get called + * \return DOM_NO_ERR on success, appropirate dom_exception on failure. + */ +dom_exception _dom_dispatch_attr_modified_event(struct dom_document *doc, + dom_event_target *et, dom_string *prev, dom_string *new, + dom_event_target *related, dom_string *attr_name, + dom_mutation_type change, bool *success) +{ + struct dom_mutation_event *evt; + dom_exception err; + + err = _dom_mutation_event_create(doc, &evt); + if (err != DOM_NO_ERR) + return err; + + lwc_string *type = NULL; + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMAttrModified", + SLEN("DOMAttrModified"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + + dom_string *t = NULL; + err = _dom_document_create_string_from_lwcstring(doc, type, &t); + _dom_document_unref_lwcstring(doc, type); + if (err != DOM_NO_ERR) + goto cleanup; + + /* Initiliase the event with corresponding parameters */ + err = dom_mutation_event_init(evt, t, true, false, related, prev, new, + attr_name, change); + dom_string_unref(t); + if (err != DOM_NO_ERR) { + goto cleanup; + } + + err = dom_event_target_dispatch_event(et, evt, success); + +cleanup: + _dom_mutation_event_destroy(doc, evt); + + return err; +} + +/** + * Dispatch a DOMCharacterDataModified event + * + * \param et The EventTarget object + * \param prev The preValue of the DOMCharacterData + * \param new The newValue of the DOMCharacterData + * \return DOM_NO_ERR on success, appropirate dom_exception on failure. + * + * TODO: + * The character_data object may be a part of a Attr node, if so, another + * DOMAttrModified event should be dispatched, too. But for now, we did not + * support any XML feature, so just leave it as this. + */ +dom_exception _dom_dispatch_characterdata_modified_event( + struct dom_document *doc, dom_event_target *et, + dom_string *prev, dom_string *new, bool *success) +{ + struct dom_mutation_event *evt; + dom_exception err; + + err = _dom_mutation_event_create(doc, &evt); + if (err != DOM_NO_ERR) + return err; + + lwc_string *type = NULL; + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMCharacterDataModified", + SLEN("DOMCharacterDataModified"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + + dom_string *t = NULL; + err = _dom_document_create_string_from_lwcstring(doc, type, &t); + _dom_document_unref_lwcstring(doc, type); + if (err != DOM_NO_ERR) + goto cleanup; + + err = dom_mutation_event_init(evt, t, true, false, et, prev, new, NULL, + DOM_MUTATION_MODIFICATION); + dom_string_unref(t); + if (err != DOM_NO_ERR) { + goto cleanup; + } + + err = dom_event_target_dispatch_event(et, evt, success); + +cleanup: + _dom_mutation_event_destroy(doc, evt); + + return err; +} + +/** + * Dispatch a DOMSubtreeModified event + * + * \param doc The Document + * \param et The EventTarget object + * \param success The newValue of the DOMCharacterData + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_dispatch_subtree_modified_event(struct dom_document *doc, + dom_event_target *et, bool *success) +{ + struct dom_mutation_event *evt; + dom_exception err; + + err = _dom_mutation_event_create(doc, &evt); + if (err != DOM_NO_ERR) + return err; + + lwc_string *type = NULL; + err = _dom_document_create_lwcstring(doc, + (const uint8_t *) "DOMSubtreeModified", + SLEN("DOMSubtreeModified"), &type); + if (err != DOM_NO_ERR) + goto cleanup; + + dom_string *t = NULL; + err = _dom_document_create_string_from_lwcstring(doc, type, &t); + _dom_document_unref_lwcstring(doc, type); + if (err != DOM_NO_ERR) + goto cleanup; + + err = dom_mutation_event_init(evt, t, true, false, et, NULL, NULL, NULL, + DOM_MUTATION_MODIFICATION); + dom_string_unref(t); + if (err != DOM_NO_ERR) { + goto cleanup; + } + + err = dom_event_target_dispatch_event(et, evt, success); + +cleanup: + _dom_mutation_event_destroy(doc, evt); + + return err; +} + diff --git a/src/events/event_target.h b/src/events/event_target.h new file mode 100644 index 0000000..a92963e --- /dev/null +++ b/src/events/event_target.h @@ -0,0 +1,88 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_internal_events_event_target_h_ +#define dom_internal_events_event_target_h_ + +#include +#include +#include +#include + +#include "utils/list.h" +#include "utils/hashtable.h" + +struct dom_document; +struct dom_string; + +/** + * Listener Entry + */ +struct listener_entry { + struct list_entry list; + /**< The listener list registered at the same + * EventTarget */ + dom_event_listener *listener; /**< The EventListener */ + bool capture; /**< Whether this listener is in capture phase */ +}; + +/** + * EventTarget internal class + */ +struct dom_event_target_internal { + struct dom_hash_table *listeners; + /**< The listeners of this EventTarget. + * The listeners are organized by the + * type of events they listen for + */ + struct dom_hash_table *ns_listeners; + /**< The listeners with namespace of thie EventTarget */ +}; + +typedef struct dom_event_target_internal dom_event_target_internal; + +/** + * Constructor and destructor: Since this object is not intended to be + * allocated alone, it should be embedded into the Node object, there is + * no constructor and destructor for it. + */ + +/* Initialise this EventTarget */ +dom_exception _dom_event_target_internal_initialise(struct dom_document *doc, + dom_event_target_internal *eti); + +/* Finalise this EventTarget */ +void _dom_event_target_internal_finalise(struct dom_document *doc, + dom_event_target_internal *eti); + +/* Dispatch the event on this node */ +dom_exception _dom_event_target_dispatch(dom_event_target *et, + struct dom_event *evt, dom_event_flow_phase phase, + bool *success); + +/* Dispatch a DOMNodeInserted/DOMNodeRemoved event */ +dom_exception _dom_dispatch_node_change_event(struct dom_document *doc, + dom_event_target *et, dom_event_target *related, + dom_mutation_type change, bool *success); + +/* Dispatch a DOMCharacterDataModified event */ +dom_exception _dom_dispatch_characterdata_modified_event( + struct dom_document *doc, dom_event_target *et, + struct dom_string *prev, struct dom_string *new, bool *success); + +/* Dispatch a DOMAttrModified event */ +dom_exception _dom_dispatch_attr_modified_event(struct dom_document *doc, + dom_event_target *et, struct dom_string *prev, + struct dom_string *new, dom_event_target *related, + struct dom_string *attr_name, dom_mutation_type change, + bool *success); + +/* Dispatch a DOMSubtreeModified event */ +dom_exception _dom_dispatch_subtree_modified_event(struct dom_document *doc, + dom_event_target *et, bool *success); + +#endif diff --git a/src/events/keyboard_event.c b/src/events/keyboard_event.c new file mode 100644 index 0000000..b8fc3ba --- /dev/null +++ b/src/events/keyboard_event.c @@ -0,0 +1,354 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include + +#include "events/keyboard_event.h" +#include "core/document.h" + +#include "utils/utils.h" + +static void _virtual_dom_keyboard_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_keyboard_event_destroy +}; + +/* Constructor */ +dom_exception _dom_keyboard_event_create(struct dom_document *doc, + struct dom_keyboard_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_keyboard_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_keyboard_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_keyboard_event_destroy(struct dom_document *doc, + struct dom_keyboard_event *evt) +{ + _dom_keyboard_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_keyboard_event_initialise(struct dom_document *doc, + struct dom_keyboard_event *evt) +{ + evt->key_ident = NULL; + evt->modifier_state = 0; + + return _dom_ui_event_initialise(doc, &evt->base); +} + +/* Finalise function */ +void _dom_keyboard_event_finalise(struct dom_document *doc, + struct dom_keyboard_event *evt) +{ + _dom_ui_event_finalise(doc, &evt->base); +} + +/* The virtual destroy function */ +void _virtual_dom_keyboard_event_destroy(struct dom_event *evt) +{ + _dom_keyboard_event_destroy(evt->doc, (dom_keyboard_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the key identifier + * + * \param evt The Event object + * \param ident The returned key identifier + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt, + struct dom_string **ident) +{ + *ident = evt->key_ident; + dom_string_ref(*ident); + + return DOM_NO_ERR; +} + +/** + * Get the key location + * + * \param evt The Event object + * \param loc The returned key location + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_key_location(dom_keyboard_event *evt, + dom_key_location *loc) +{ + *loc = evt->key_loc; + + return DOM_NO_ERR; +} + +/** + * Get the ctrl key state + * + * \param evt The Event object + * \param key Whether the Control key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_ctrl_key(dom_keyboard_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_CTRL) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the shift key state + * + * \param evt The Event object + * \param key Whether the Shift key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_shift_key(dom_keyboard_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the alt key state + * + * \param evt The Event object + * \param key Whether the Alt key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_alt_key(dom_keyboard_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_ALT) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the meta key state + * + * \param evt The Event object + * \param key Whether the Meta key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_meta_key(dom_keyboard_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_META) != 0); + + return DOM_NO_ERR; +} + +/** + * Query the state of a modifier using a key identifier + * + * \param evt The event object + * \param ml The modifier identifier, such as "Alt", "Control", "Meta", + * "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift". + * \param state Whether the modifier key is pressed + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * + * @note: If an application wishes to distinguish between right and left + * modifiers, this information could be deduced using keyboard events and + * KeyboardEvent.keyLocation. + */ +dom_exception _dom_keyboard_event_get_modifier_state(dom_keyboard_event *evt, + struct dom_string *m, bool *state) +{ + if (m == NULL) { + *state = false; + return DOM_NO_ERR; + } + + const char *data = _dom_string_data(m); + size_t len = _dom_string_length(m); + + if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0); + } else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_ALT) != 0); + } else if (len == SLEN("CapsLock") && + strncmp(data, "CapsLock", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0); + } else if (len == SLEN("Control") && + strncmp(data, "Control", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_CTRL) != 0); + } else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_META) != 0); + } else if (len == SLEN("NumLock") && + strncmp(data, "NumLock", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0); + } else if (len == SLEN("Scroll") && + strncmp(data, "Scroll", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0); + } else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0); + } + + return DOM_NO_ERR; +} + +/** + * Initialise the keyboard event + * + * \param evt The Event object + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param key_indent The key identifier of pressed key + * \param key_loc The key location of the preesed key + * \param modifier_list A string of modifier key identifiers, separated with + * space + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_keyboard_event_init(dom_keyboard_event *evt, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_abstract_view *view, struct dom_string *key_ident, + dom_key_location key_loc, struct dom_string *modifier_list) +{ + dom_exception err; + + evt->key_ident = key_ident; + dom_string_ref(evt->key_ident); + evt->key_loc = key_loc; + + err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state); + if (err != DOM_NO_ERR) + return err; + + return _dom_ui_event_init(&evt->base, type, bubble, cancelable, + view, 0); +} + +/** + * Initialise the keyboard event with namespace + * + * \param evt The Event object + * \param namespace The namespace of this event + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param key_indent The key identifier of pressed key + * \param key_loc The key location of the preesed key + * \param modifier_list A string of modifier key identifiers, separated with + * space + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_keyboard_event_init_ns(dom_keyboard_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_abstract_view *view, + struct dom_string *key_ident, dom_key_location key_loc, + struct dom_string *modifier_list) +{ + dom_exception err; + + evt->key_ident = key_ident; + dom_string_ref(evt->key_ident); + evt->key_loc = key_loc; + + err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state); + if (err != DOM_NO_ERR) + return err; + + return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble, + cancelable, view, 0); +} + + +/*-------------------------------------------------------------------------*/ + +/** + * Parse the modifier list string to corresponding bool variable state + * + * \param modifier_list The modifier list string + * \param modifier_state The returned state + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_parse_modifier_list(struct dom_string *modifier_list, + uint32_t *modifier_state) +{ + *modifier_state = 0; + + if (modifier_list == NULL) + return DOM_NO_ERR; + + char *data = _dom_string_data(modifier_list); + char *m = data; + size_t len = 0; + + while (true) { + /* If we reach a space or end of the string, we should parse + * the new token. */ + if (*data == ' ' || *data == '\0') { + if (len == SLEN("AltGraph") && + strncmp(data, "AltGraph", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_ALT_GRAPH; + } else if (len == SLEN("Alt") && + strncmp(data, "Alt", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_ALT; + } else if (len == SLEN("CapsLock") && + strncmp(data, "CapsLock", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_CAPS_LOCK; + } else if (len == SLEN("Control") && + strncmp(data, "Control", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_CTRL; + } else if (len == SLEN("Meta") && + strncmp(data, "Meta", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_META; + } else if (len == SLEN("NumLock") && + strncmp(data, "NumLock", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_NUM_LOCK; + } else if (len == SLEN("Scroll") && + strncmp(data, "Scroll", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_SCROLL; + } else if (len == SLEN("Shift") && + strncmp(data, "Shift", len) == 0) { + *modifier_state = *modifier_state | + DOM_MOD_SHIFT; + } + + while (*data == ' ') { + data++; + } + /* Finished parsing and break */ + if (*data == '\0') + break; + + m = data; + len = 0; + } + + data++; + len++; + } + + return DOM_NO_ERR; +} + diff --git a/src/events/keyboard_event.h b/src/events/keyboard_event.h new file mode 100644 index 0000000..4d2777c --- /dev/null +++ b/src/events/keyboard_event.h @@ -0,0 +1,55 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_keyboard_event_h_ +#define dom_interntal_events_keyboard_event_h_ + +#include + +#include "events/ui_event.h" + +/** + * The keyboard event + */ +struct dom_keyboard_event { + struct dom_ui_event base; /**< The base class */ + + struct dom_string *key_ident; /**< The identifier of the key in this + * event, please refer: + * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set + * for detail + */ + + dom_key_location key_loc; /**< Indicate the location of the key on + * the keyboard + */ + + uint32_t modifier_state; /**< The modifier keys state */ +}; + +/* Constructor */ +dom_exception _dom_keyboard_event_create(struct dom_document *doc, + struct dom_keyboard_event **evt); + +/* Destructor */ +void _dom_keyboard_event_destroy(struct dom_document *doc, + struct dom_keyboard_event *evt); + +/* Initialise function */ +dom_exception _dom_keyboard_event_initialise(struct dom_document *doc, + struct dom_keyboard_event *evt); + +/* Finalise function */ +void _dom_keyboard_event_finalise(struct dom_document *doc, + struct dom_keyboard_event *evt); + + +/* Parse the modifier list string to corresponding bool variable state */ +dom_exception _dom_parse_modifier_list(struct dom_string *modifier_list, + uint32_t *modifier_state); + +#endif diff --git a/src/events/mouse_event.c b/src/events/mouse_event.c new file mode 100644 index 0000000..1b31012 --- /dev/null +++ b/src/events/mouse_event.c @@ -0,0 +1,366 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include + +#include "events/mouse_event.h" +#include "core/document.h" + +#include "utils/utils.h" + +static void _virtual_dom_mouse_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_mouse_event_destroy +}; + +/* Constructor */ +dom_exception _dom_mouse_event_create(struct dom_document *doc, + struct dom_mouse_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mouse_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_mouse_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_mouse_event_destroy(struct dom_document *doc, + struct dom_mouse_event *evt) +{ + _dom_mouse_event_finalise(doc, (dom_ui_event *) evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_mouse_event_initialise(struct dom_document *doc, + struct dom_mouse_event *evt) +{ + evt->modifier_state = 0; + + return _dom_ui_event_initialise(doc, (dom_ui_event *) evt); +} + +/* The virtual destroy function */ +void _virtual_dom_mouse_event_destroy(struct dom_event *evt) +{ + _dom_mouse_event_destroy(evt->doc, (dom_mouse_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get screenX + * + * \param evt The Event object + * \param x The returned screenX + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_screen_x(dom_mouse_event *evt, + long *x) +{ + *x = evt->sx; + + return DOM_NO_ERR; +} + +/** + * Get screenY + * + * \param evt The Event object + * \param y The returned screenY + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_screen_y(dom_mouse_event *evt, + long *y) +{ + *y = evt->sy; + + return DOM_NO_ERR; +} + +/** + * Get clientX + * + * \param evt The Event object + * \param x The returned clientX + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_client_x(dom_mouse_event *evt, + long *x) +{ + *x = evt->cx; + + return DOM_NO_ERR; +} + +/** + * Get clientY + * + * \param evt The Event object + * \param y The returned clientY + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_client_y(dom_mouse_event *evt, + long *y) +{ + *y = evt->cy; + + return DOM_NO_ERR; +} + +/** + * Get the ctrl key state + * + * \param evt The Event object + * \param key Whether the Control key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_ctrl_key(dom_mouse_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_CTRL) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the shift key state + * + * \param evt The Event object + * \param key Whether the Shift key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_shift_key(dom_mouse_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the alt key state + * + * \param evt The Event object + * \param key Whether the Alt key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_alt_key(dom_mouse_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_ALT) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the meta key state + * + * \param evt The Event object + * \param key Whether the Meta key is pressed down + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_meta_key(dom_mouse_event *evt, + bool *key) +{ + *key = ((evt->modifier_state & DOM_MOD_META) != 0); + + return DOM_NO_ERR; +} + +/** + * Get the button which get pressed + * + * \param evt The Event object + * \param button The pressed mouse button + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_button(dom_mouse_event *evt, + unsigned short *button) +{ + *button = evt->button; + + return DOM_NO_ERR; +} + +/** + * Get the related target + * + * \param evt The Event object + * \param et The related EventTarget + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_event_get_related_target(dom_mouse_event *evt, + dom_event_target **et) +{ + *et = evt->related_target; + + return DOM_NO_ERR; +} + +/** + * Query the state of a modifier using a key identifier + * + * \param evt The event object + * \param ml The modifier identifier, such as "Alt", "Control", "Meta", + * "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift". + * \param state Whether the modifier key is pressed + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * + * @note: If an application wishes to distinguish between right and left + * modifiers, this information could be deduced using keyboard events and + * KeyboardEvent.keyLocation. + */ +dom_exception _dom_mouse_event_get_modifier_state(dom_mouse_event *evt, + struct dom_string *m, bool *state) +{ + if (m == NULL) { + *state = false; + return DOM_NO_ERR; + } + + const char *data = _dom_string_data(m); + size_t len = _dom_string_length(m); + + if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0); + } else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_ALT) != 0); + } else if (len == SLEN("CapsLock") && + strncmp(data, "CapsLock", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0); + } else if (len == SLEN("Control") && + strncmp(data, "Control", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_CTRL) != 0); + } else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_META) != 0); + } else if (len == SLEN("NumLock") && + strncmp(data, "NumLock", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0); + } else if (len == SLEN("Scroll") && + strncmp(data, "Scroll", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0); + } else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) { + *state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0); + } + + return DOM_NO_ERR; +} + +/** + * Initialise this mouse event + * + * \param evt The Event object + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param detail The detail information of this mouse event + * \param screen_x The x position of the mouse pointer in screen + * \param screen_y The y position of the mouse pointer in screen + * \param client_x The x position of the mouse pointer in client window + * \param client_y The y position of the mouse pointer in client window + * \param alt The state of Alt key, true for pressed, false otherwise + * \param shift The state of Shift key, true for pressed, false otherwise + * \param mata The state of Meta key, true for pressed, false otherwise + * \param button The mouse button pressed + * \param et The related target of this event, may be NULL + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mouse_event_init(dom_mouse_event *evt, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_abstract_view *view, long detail, long screen_x, + long screen_y, long client_x, long client_y, bool ctrl, + bool alt, bool shift, bool meta, unsigned short button, + dom_event_target *et) +{ + evt->sx = screen_x; + evt->sy = screen_y; + evt->cx = client_x; + evt->cy = client_y; + + evt->modifier_state = 0; + if (ctrl == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL; + } + if (alt == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_ALT; + } + if (shift == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT; + } + if (meta == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_META; + } + + evt->button = button; + evt->related_target = et; + + return _dom_ui_event_init(&evt->base, type, bubble, cancelable, view, + detail); +} + +/** + * Initialise the event with namespace + * + * \param evt The Event object + * \param namespace The namespace of this event + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param detail The detail information of this mouse event + * \param screen_x The x position of the mouse pointer in screen + * \param screen_y The y position of the mouse pointer in screen + * \param client_x The x position of the mouse pointer in client window + * \param client_y The y position of the mouse pointer in client window + * \param alt The state of Alt key, true for pressed, false otherwise + * \param shift The state of Shift key, true for pressed, false otherwise + * \param mata The state of Meta key, true for pressed, false otherwise + * \param button The mouse button pressed + * \param et The related target of this event, may be NULL + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mouse_event_init_ns(dom_mouse_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_abstract_view *view, + long detail, long screen_x, long screen_y, long client_x, + long client_y, bool ctrl, bool alt, bool shift, bool meta, + unsigned short button, dom_event_target *et) +{ + evt->sx = screen_x; + evt->sy = screen_y; + evt->cx = client_x; + evt->cy = client_y; + + evt->modifier_state = 0; + if (ctrl == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL; + } + if (alt == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_ALT; + } + if (shift == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT; + } + if (meta == true) { + evt->modifier_state = evt->modifier_state | DOM_MOD_META; + } + + evt->button = button; + evt->related_target = et; + + return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble, + cancelable, view, detail); +} + diff --git a/src/events/mouse_event.h b/src/events/mouse_event.h new file mode 100644 index 0000000..f5117a1 --- /dev/null +++ b/src/events/mouse_event.h @@ -0,0 +1,49 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_mouse_event_h_ +#define dom_interntal_events_mouse_event_h_ + +#include + +#include "events/ui_event.h" + +/** + * The mouse event + */ +struct dom_mouse_event { + struct dom_ui_event base; /**< Base class */ + + long sx; /**< ScreenX */ + long sy; /**< ScreenY */ + long cx; /**< ClientX */ + long cy; /**< ClientY */ + + uint32_t modifier_state; /**< The modifier keys state */ + + unsigned short button; /**< Which button is clicked */ + dom_event_target *related_target; /**< The related target */ +}; + +/* Constructor */ +dom_exception _dom_mouse_event_create(struct dom_document *doc, + struct dom_mouse_event **evt); + +/* Destructor */ +void _dom_mouse_event_destroy(struct dom_document *doc, + struct dom_mouse_event *evt); + +/* Initialise function */ +dom_exception _dom_mouse_event_initialise(struct dom_document *doc, + struct dom_mouse_event *evt); + +/* Finalise function */ +#define _dom_mouse_event_finalise _dom_ui_event_finalise + + +#endif + diff --git a/src/events/mouse_multi_wheel_event.c b/src/events/mouse_multi_wheel_event.c new file mode 100644 index 0000000..bca9c97 --- /dev/null +++ b/src/events/mouse_multi_wheel_event.c @@ -0,0 +1,152 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/mouse_multi_wheel_event.h" +#include "events/keyboard_event.h" +#include "core/document.h" + +#include "utils/utils.h" + +static void _virtual_dom_mouse_multi_wheel_event_destroy( + struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_mouse_multi_wheel_event_destroy +}; + +/* Constructor */ +dom_exception _dom_mouse_multi_wheel_event_create(struct dom_document *doc, + struct dom_mouse_multi_wheel_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, + sizeof(dom_mouse_multi_wheel_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_mouse_multi_wheel_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_mouse_multi_wheel_event_destroy(struct dom_document *doc, + struct dom_mouse_multi_wheel_event *evt) +{ + _dom_mouse_multi_wheel_event_finalise(doc, (dom_ui_event *) evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_mouse_multi_wheel_event_initialise(struct dom_document *doc, + struct dom_mouse_multi_wheel_event *evt) +{ + return _dom_mouse_event_initialise(doc, (dom_mouse_event *) evt); +} + +/* The virtual destroy function */ +void _virtual_dom_mouse_multi_wheel_event_destroy(struct dom_event *evt) +{ + _dom_mouse_multi_wheel_event_destroy(evt->doc, + (dom_mouse_multi_wheel_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get wheelDeltaX + * + * \param evt The Event object + * \param x The returned wheelDeltaX + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_x( + dom_mouse_multi_wheel_event *evt, long *x) +{ + *x = evt->x; + + return DOM_NO_ERR; +} + +/** + * Get wheelDeltaY + * + * \param evt The Event object + * \param y The returned wheelDeltaY + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_y( + dom_mouse_multi_wheel_event *evt, long *y) +{ + *y = evt->y; + + return DOM_NO_ERR; +} + +/** + * Get wheelDeltaZ + * + * \param evt The Event object + * \param z The returned wheelDeltaZ + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_z( + dom_mouse_multi_wheel_event *evt, long *z) +{ + *z = evt->z; + + return DOM_NO_ERR; +} + +/** + * Intialise this event with namespace + * + * \param evt The Event object + * \param namespace The namespace of this event + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param detail The detail information of this mouse event + * \param screen_x The x position of the mouse pointer in screen + * \param screen_y The y position of the mouse pointer in screen + * \param client_x The x position of the mouse pointer in client window + * \param client_y The y position of the mouse pointer in client window + * \param button The mouse button pressed + * \param et The related target of this event, may be NULL + * \param modifier_list The string contains the modifier identifier strings + * \param wheel_delta_x The wheelDeltaX + * \param wheel_delta_y The wheelDeltaY + * \param wheel_delta_z The wheelDeltaZ + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mouse_multi_wheel_event_init_ns( + dom_mouse_multi_wheel_event *evt, struct dom_string *namespace, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_abstract_view *view, long detail, long screen_x, + long screen_y, long client_x, long client_y, + unsigned short button, dom_event_target *et, + struct dom_string *modifier_list, long wheel_delta_x, + long wheel_delta_y, long wheel_delta_z) +{ + dom_exception err; + evt->x = wheel_delta_x; + evt->y = wheel_delta_y; + evt->z = wheel_delta_z; + + dom_mouse_event *e = (dom_mouse_event *) evt; + + err = _dom_parse_modifier_list(modifier_list, &e->modifier_state); + if (err != DOM_NO_ERR) + return err; + + return _dom_mouse_event_init_ns(&evt->base, namespace, type, bubble, + cancelable, view, detail ,screen_x, screen_y, client_x, + client_y, false, false, false, false, button, et); +} + diff --git a/src/events/mouse_multi_wheel_event.h b/src/events/mouse_multi_wheel_event.h new file mode 100644 index 0000000..043efb8 --- /dev/null +++ b/src/events/mouse_multi_wheel_event.h @@ -0,0 +1,44 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_events_internal_mouse_multi_wheel_event_h_ +#define dom_events_internal_mouse_multi_wheel_event_h_ + +#include + +#include "events/mouse_event.h" + +/** + * The MouseMultiWheelEvent + */ +struct dom_mouse_multi_wheel_event { + struct dom_mouse_event base; /**< The base class */ + + long x; /**< The wheelDeltaX */ + long y; /**< The wheelDeltaY */ + long z; /**< The wheelDeltaZ */ +}; + +/* Constructor */ +dom_exception _dom_mouse_multi_wheel_event_create(struct dom_document *doc, + struct dom_mouse_multi_wheel_event **evt); + +/* Destructor */ +void _dom_mouse_multi_wheel_event_destroy(struct dom_document *doc, + struct dom_mouse_multi_wheel_event *evt); + +/* Initialise function */ +dom_exception _dom_mouse_multi_wheel_event_initialise(struct dom_document *doc, + struct dom_mouse_multi_wheel_event *evt); + +/* Finalise function */ +#define _dom_mouse_multi_wheel_event_finalise _dom_mouse_event_finalise + + +#endif + + diff --git a/src/events/mouse_wheel_event.c b/src/events/mouse_wheel_event.c new file mode 100644 index 0000000..c38ae3e --- /dev/null +++ b/src/events/mouse_wheel_event.c @@ -0,0 +1,115 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/mouse_wheel_event.h" +#include "events/keyboard_event.h" +#include "core/document.h" + +#include "utils/utils.h" + +static void _virtual_dom_mouse_wheel_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_mouse_wheel_event_destroy +}; + +/* Constructor */ +dom_exception _dom_mouse_wheel_event_create(struct dom_document *doc, + struct dom_mouse_wheel_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mouse_wheel_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_mouse_wheel_event_initialise(doc, + (dom_mouse_wheel_event *) *evt); +} + +/* Destructor */ +void _dom_mouse_wheel_event_destroy(struct dom_document *doc, + struct dom_mouse_wheel_event *evt) +{ + _dom_mouse_wheel_event_finalise(doc, (dom_ui_event *) evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_mouse_wheel_event_initialise(struct dom_document *doc, + struct dom_mouse_wheel_event *evt) +{ + return _dom_mouse_event_initialise(doc, (dom_mouse_event *) evt); +} + +/* The virtual destroy function */ +void _virtual_dom_mouse_wheel_event_destroy(struct dom_event *evt) +{ + _dom_mouse_wheel_event_destroy(evt->doc, (dom_mouse_wheel_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get wheelDelta + * + * \param evt The Event object + * \param d The wheelDelta + * \return DOM_NO_ERR. + */ +dom_exception _dom_mouse_wheel_event_get_wheel_delta( + dom_mouse_wheel_event *evt, long *d) +{ + *d = evt->delta; + + return DOM_NO_ERR; +} + +/** + * Intialise this event with namespace + * + * \param evt The Event object + * \param namespace The namespace of this event + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param detail The detail information of this mouse event + * \param screen_x The x position of the mouse pointer in screen + * \param screen_y The y position of the mouse pointer in screen + * \param client_x The x position of the mouse pointer in client window + * \param client_y The y position of the mouse pointer in client window + * \param button The mouse button pressed + * \param et The related target of this event, may be NULL + * \param modifier_list The string contains the modifier identifier strings + * \param wheel_delta The wheelDelta + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mouse_wheel_event_init_ns( + dom_mouse_wheel_event *evt, struct dom_string *namespace, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_abstract_view *view, long detail, long screen_x, + long screen_y, long client_x, long client_y, + unsigned short button, dom_event_target *et, + struct dom_string *modifier_list, long wheel_delta) +{ + dom_exception err; + evt->delta = wheel_delta; + dom_mouse_event *e = (dom_mouse_event *) evt; + + err = _dom_parse_modifier_list(modifier_list, &e->modifier_state); + if (err != DOM_NO_ERR) + return err; + + return _dom_mouse_event_init_ns(&evt->base, namespace, type, bubble, + cancelable, view, detail ,screen_x, screen_y, + client_x, client_y, false, false, false, false, + button, et); +} + diff --git a/src/events/mouse_wheel_event.h b/src/events/mouse_wheel_event.h new file mode 100644 index 0000000..ba613e5 --- /dev/null +++ b/src/events/mouse_wheel_event.h @@ -0,0 +1,40 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_events_internal_mouse_wheel_event_h_ +#define dom_events_internal_mouse_wheel_event_h_ + +#include + +#include "events/mouse_event.h" + +/** + * The MouseWheelEvent + */ +struct dom_mouse_wheel_event { + struct dom_mouse_event base; /**< The base class */ + + long delta; /**< The wheelDelta */ +}; + +/* Constructor */ +dom_exception _dom_mouse_wheel_event_create(struct dom_document *doc, + struct dom_mouse_wheel_event **evt); + +/* Destructor */ +void _dom_mouse_wheel_event_destroy(struct dom_document *doc, + struct dom_mouse_wheel_event *evt); + +/* Initialise function */ +dom_exception _dom_mouse_wheel_event_initialise(struct dom_document *doc, + struct dom_mouse_wheel_event *evt); + +/* Finalise function */ +#define _dom_mouse_wheel_event_finalise _dom_mouse_event_finalise + +#endif + diff --git a/src/events/mutation_event.c b/src/events/mutation_event.c new file mode 100644 index 0000000..ea7163c --- /dev/null +++ b/src/events/mutation_event.c @@ -0,0 +1,226 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/mutation_event.h" +#include "core/document.h" + +static void _virtual_dom_mutation_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_mutation_event_destroy +}; + +/* Constructor */ +dom_exception _dom_mutation_event_create(struct dom_document *doc, + struct dom_mutation_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mutation_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_mutation_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_mutation_event_destroy(struct dom_document *doc, + struct dom_mutation_event *evt) +{ + _dom_mutation_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_mutation_event_initialise(struct dom_document *doc, + struct dom_mutation_event *evt) +{ + evt->related_node = NULL; + evt->prev_value = NULL; + evt->new_value = NULL; + evt->attr_name = NULL; + + return _dom_event_initialise(doc, &evt->base); +} + +/* Finalise function */ +void _dom_mutation_event_finalise(struct dom_document *doc, + struct dom_mutation_event *evt) +{ + dom_node_unref(evt->related_node); + dom_string_unref(evt->prev_value); + dom_string_unref(evt->new_value); + dom_string_unref(evt->attr_name); + + _dom_event_finalise(doc, &evt->base); +} + +/* The virtual destroy function */ +void _virtual_dom_mutation_event_destroy(struct dom_event *evt) +{ + _dom_mutation_event_destroy(evt->doc, (dom_mutation_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the related node + * + * \param evt The Event object + * \param node The related node + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_event_get_related_node(dom_mutation_event *evt, + struct dom_node **node) +{ + *node = evt->related_node; + dom_node_ref(*node); + + return DOM_NO_ERR; +} + +/** + * Get the old value + * + * \param evt The Event object + * \param ret The old value + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_event_get_prev_value(dom_mutation_event *evt, + struct dom_string **ret) +{ + *ret = evt->prev_value; + dom_string_ref(*ret); + + return DOM_NO_ERR; +} + +/** + * Get the new value + * + * \param evt The Event object + * \param ret The new value + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_event_get_new_value(dom_mutation_event *evt, + struct dom_string **ret) +{ + *ret = evt->new_value; + dom_string_ref(*ret); + + return DOM_NO_ERR; +} + +/** + * Get the attr name + * + * \param evt The Event object + * \param ret The attribute name + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_event_get_attr_name(dom_mutation_event *evt, + struct dom_string **ret) +{ + *ret = evt->attr_name; + dom_string_ref(*ret); + + return DOM_NO_ERR; +} + +/** + * Get the way the attribute change + * + * \param evt The Event object + * \param type The change type + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_event_get_attr_change(dom_mutation_event *evt, + dom_mutation_type *type) +{ + *type = evt->change; + + return DOM_NO_ERR; +} + +/** + * Initialise the MutationEvent + * + * \param evt The Event object + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param node The mutation node + * \param prev_value The old value + * \param new_value The new value + * \param attr_name The attribute's name + * \param change The change type + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mutation_event_init(dom_mutation_event *evt, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_node *node, struct dom_string *prev_value, + struct dom_string *new_value, struct dom_string *attr_name, + dom_mutation_type change) +{ + evt->related_node = node; + dom_node_ref(node); + + evt->prev_value = prev_value; + dom_string_ref(prev_value); + + evt->new_value = new_value; + dom_string_ref(new_value); + + evt->attr_name = attr_name; + dom_string_ref(attr_name); + + evt->change = change; + + return _dom_event_init(&evt->base, type, bubble, cancelable); +} + +/** + * Initialise the MutationEvent with namespace + * + * \param evt The Event object + * \param namespace The namespace + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param node The mutation node + * \param prev_value The old value + * \param new_value The new value + * \param attr_name The attribute's name + * \param change The change type + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mutation_event_init_ns(dom_mutation_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_node *node, + struct dom_string *prev_value, struct dom_string *new_value, + struct dom_string *attr_name, dom_mutation_type change) +{ + evt->related_node = node; + dom_node_ref(node); + + evt->prev_value = prev_value; + dom_string_ref(prev_value); + + evt->new_value = new_value; + dom_string_ref(new_value); + + evt->attr_name = attr_name; + dom_string_ref(attr_name); + + evt->change = change; + + return _dom_event_init_ns(&evt->base, namespace, type, bubble, + cancelable); +} + diff --git a/src/events/mutation_event.h b/src/events/mutation_event.h new file mode 100644 index 0000000..d6cd733 --- /dev/null +++ b/src/events/mutation_event.h @@ -0,0 +1,45 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_mutation_event_h_ +#define dom_interntal_events_mutation_event_h_ + +#include + +#include "events/event.h" + +/** + * The MutationEvent + */ +struct dom_mutation_event { + struct dom_event base; + + struct dom_node *related_node; + struct dom_string *prev_value; + struct dom_string *new_value; + struct dom_string *attr_name; + dom_mutation_type change; +}; + +/* Constructor */ +dom_exception _dom_mutation_event_create(struct dom_document *doc, + struct dom_mutation_event **evt); + +/* Destructor */ +void _dom_mutation_event_destroy(struct dom_document *doc, + struct dom_mutation_event *evt); + +/* Initialise function */ +dom_exception _dom_mutation_event_initialise(struct dom_document *doc, + struct dom_mutation_event *evt); + +/* Finalise function */ +void _dom_mutation_event_finalise(struct dom_document *doc, + struct dom_mutation_event *evt); + +#endif + diff --git a/src/events/mutation_name_event.c b/src/events/mutation_name_event.c new file mode 100644 index 0000000..34b9288 --- /dev/null +++ b/src/events/mutation_name_event.c @@ -0,0 +1,159 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/mutation_name_event.h" +#include "core/document.h" + +#include "utils/utils.h" + +static void _virtual_dom_mutation_name_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_mutation_name_event_destroy +}; + +/* Constructor */ +dom_exception _dom_mutation_name_event_create(struct dom_document *doc, + struct dom_mutation_name_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mutation_name_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_mutation_name_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_mutation_name_event_destroy(struct dom_document *doc, + struct dom_mutation_name_event *evt) +{ + _dom_mutation_name_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_mutation_name_event_initialise(struct dom_document *doc, + struct dom_mutation_name_event *evt) +{ + evt->prev_namespace = NULL; + evt->prev_nodename = NULL; + + return _dom_event_initialise(doc, (dom_event *) evt); +} + +/* Finalise function */ +void _dom_mutation_name_event_finalise(struct dom_document *doc, + struct dom_mutation_name_event *evt) +{ + dom_string_unref(evt->prev_namespace); + dom_string_unref(evt->prev_nodename); + + _dom_event_finalise(doc, (dom_event *) evt); +} + +/* The virtual destroy function */ +void _virtual_dom_mutation_name_event_destroy(struct dom_event *evt) +{ + _dom_mutation_name_event_destroy(evt->doc, + (dom_mutation_name_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the previous namespace + * + * \param evt The Event object + * \param namespace The previous namespace of this event + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_name_event_get_prev_namespace( + dom_mutation_name_event *evt, struct dom_string **namespace) +{ + *namespace = evt->prev_namespace; + dom_string_ref(*namespace); + + return DOM_NO_ERR; +} + +/** + * Get the previous node name + * + * \param evt The Event object + * \param name The previous node name + * \return DOM_NO_ERR. + */ +dom_exception _dom_mutation_name_event_get_prev_node_name( + dom_mutation_name_event *evt, struct dom_string **name) +{ + *name = evt->prev_nodename; + dom_string_ref(*name); + + return DOM_NO_ERR; +} + +/** + * Initialise the MutationNameEvent + * + * \param evt The Event object + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param node The node whose name change + * \param prev_ns The old namespace + * \param prev_name The old name + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mutation_name_event_init(dom_mutation_name_event *evt, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_node *node, struct dom_string *prev_ns, + struct dom_string *prev_name) +{ + evt->prev_namespace = prev_ns; + dom_string_ref(prev_ns); + + evt->prev_nodename = prev_name; + dom_string_ref(prev_name); + + return _dom_mutation_event_init((dom_mutation_event *) evt, type, + bubble, cancelable, node, NULL, NULL, NULL, + DOM_MUTATION_MODIFICATION); +} + +/** + * Initialise the MutationNameEvent with namespace + * + * \param evt The Event object + * \param namespace The namespace + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param node The node whose name change + * \param prev_ns The old namespace + * \param prev_name The old name + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_mutation_name_event_init_ns(dom_mutation_name_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_node *node, + struct dom_string *prev_ns, struct dom_string *prev_name) +{ + evt->prev_namespace = prev_ns; + dom_string_ref(prev_ns); + + evt->prev_nodename = prev_name; + dom_string_ref(prev_name); + + return _dom_mutation_event_init_ns((dom_mutation_event *) evt, + namespace, type, bubble, cancelable, node, NULL, + NULL, NULL, DOM_MUTATION_MODIFICATION); +} + diff --git a/src/events/mutation_name_event.h b/src/events/mutation_name_event.h new file mode 100644 index 0000000..2ba74de --- /dev/null +++ b/src/events/mutation_name_event.h @@ -0,0 +1,42 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_mutation_name_event_h_ +#define dom_interntal_events_mutation_name_event_h_ + +#include + +#include "events/mutation_event.h" + +/** + * The MutationName event + */ +struct dom_mutation_name_event { + struct dom_mutation_event base; + + struct dom_string *prev_namespace; + struct dom_string *prev_nodename; +}; + +/* Constructor */ +dom_exception _dom_mutation_name_event_create(struct dom_document *doc, + struct dom_mutation_name_event **evt); + +/* Destructor */ +void _dom_mutation_name_event_destroy(struct dom_document *doc, + struct dom_mutation_name_event *evt); + +/* Initialise function */ +dom_exception _dom_mutation_name_event_initialise(struct dom_document *doc, + struct dom_mutation_name_event *evt); + +/* Finalise function */ +void _dom_mutation_name_event_finalise(struct dom_document *doc, + struct dom_mutation_name_event *evt); + +#endif + diff --git a/src/events/text_event.c b/src/events/text_event.c new file mode 100644 index 0000000..24c921a --- /dev/null +++ b/src/events/text_event.c @@ -0,0 +1,125 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/text_event.h" +#include "core/document.h" + +static void _virtual_dom_text_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_text_event_destroy +}; + +/* Constructor */ +dom_exception _dom_text_event_create(struct dom_document *doc, + struct dom_text_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_text_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_text_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_text_event_destroy(struct dom_document *doc, + struct dom_text_event *evt) +{ + _dom_text_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_text_event_initialise(struct dom_document *doc, + struct dom_text_event *evt) +{ + evt->data = NULL; + return _dom_ui_event_initialise(doc, &evt->base); +} + +/* Finalise function */ +void _dom_text_event_finalise(struct dom_document *doc, + struct dom_text_event *evt) +{ + dom_string_unref(evt->data); + _dom_ui_event_finalise(doc, &evt->base); +} + +/* The virtual destroy function */ +void _virtual_dom_text_event_destroy(struct dom_event *evt) +{ + _dom_text_event_destroy(evt->doc, (dom_text_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the internal data of this event + * + * \param evt The Event object + * \param data The internal data of this Event + * \return DOM_NO_ERR. + */ +dom_exception _dom_text_event_get_data(dom_text_event *evt, + struct dom_string **data) +{ + *data = evt->data; + dom_string_ref(*data); + + return DOM_NO_ERR; +} + +/** + * Initialise the TextEvent + * + * \param evt The Event object + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param view The AbstractView of this UIEvent + * \param data The text data + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_text_event_init(dom_text_event *evt, + struct dom_string *type, bool bubble, bool cancelable, + struct dom_abstract_view *view, struct dom_string *data) +{ + evt->data = data; + dom_string_ref(data); + + return _dom_ui_event_init(&evt->base, type, bubble, cancelable, + view, 0); +} + +/** + * Initialise the TextEvent with namespace + * + * \param evt The Event object + * \param namespace The namespace of this Event + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param view The AbstractView of this UIEvent + * \param data The text data + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_text_event_init_ns(dom_text_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_abstract_view *view, + struct dom_string *data) +{ + evt->data = data; + dom_string_ref(data); + + return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble, + cancelable, view, 0); +} + diff --git a/src/events/text_event.h b/src/events/text_event.h new file mode 100644 index 0000000..754a4f6 --- /dev/null +++ b/src/events/text_event.h @@ -0,0 +1,40 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_internal_events_text_event_h_ +#define dom_internal_events_text_event_h_ + +#include + +#include "events/ui_event.h" + +/** + * The TextEvent + */ +struct dom_text_event { + struct dom_ui_event base; + struct dom_string *data; +}; + +/* Constructor */ +dom_exception _dom_text_event_create(struct dom_document *doc, + struct dom_text_event **evt); + +/* Destructor */ +void _dom_text_event_destroy(struct dom_document *doc, + struct dom_text_event *evt); + +/* Initialise function */ +dom_exception _dom_text_event_initialise(struct dom_document *doc, + struct dom_text_event *evt); + +/* Finalise function */ +void _dom_text_event_finalise(struct dom_document *doc, + struct dom_text_event *evt); + +#endif + diff --git a/src/events/ui_event.c b/src/events/ui_event.c new file mode 100644 index 0000000..f18e44f --- /dev/null +++ b/src/events/ui_event.c @@ -0,0 +1,138 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include "events/ui_event.h" +#include "core/document.h" + +static void _virtual_dom_ui_event_destroy(struct dom_event *evt); + +static struct dom_event_private_vtable _event_vtable = { + _virtual_dom_ui_event_destroy +}; + +/* Constructor */ +dom_exception _dom_ui_event_create(struct dom_document *doc, + struct dom_ui_event **evt) +{ + *evt = _dom_document_alloc(doc, NULL, sizeof(dom_ui_event)); + if (*evt == NULL) + return DOM_NO_MEM_ERR; + + ((struct dom_event *) *evt)->vtable = &_event_vtable; + + return _dom_ui_event_initialise(doc, *evt); +} + +/* Destructor */ +void _dom_ui_event_destroy(struct dom_document *doc, + struct dom_ui_event *evt) +{ + _dom_ui_event_finalise(doc, evt); + + _dom_document_alloc(doc, evt, 0); +} + +/* Initialise function */ +dom_exception _dom_ui_event_initialise(struct dom_document *doc, + struct dom_ui_event *evt) +{ + evt->view = NULL; + return _dom_event_initialise(doc, &evt->base); +} + +/* Finalise function */ +void _dom_ui_event_finalise(struct dom_document *doc, + struct dom_ui_event *evt) +{ + evt->view = NULL; + _dom_event_finalise(doc, &evt->base); +} + +/* The virtual destroy function */ +void _virtual_dom_ui_event_destroy(struct dom_event *evt) +{ + _dom_ui_event_destroy(evt->doc, (dom_ui_event *) evt); +} + +/*----------------------------------------------------------------------*/ +/* The public API */ + +/** + * Get the AbstractView inside this event + * + * \param evt The Event object + * \param view The returned AbstractView + * \return DOM_NO_ERR. + */ +dom_exception _dom_ui_event_get_view(dom_ui_event *evt, + struct dom_abstract_view **view) +{ + *view = evt->view; + + return DOM_NO_ERR; +} + +/** + * Get the detail param of this event + * + * \param evt The Event object + * \param detail The detail object + * \return DOM_NO_ERR. + */ +dom_exception _dom_ui_event_get_detail(dom_ui_event *evt, + long *detail) +{ + *detail = evt->detail; + + return DOM_NO_ERR; +} + +/** + * Initialise the UIEvent + * + * \param evt The Event object + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param view The AbstractView of this UIEvent + * \param detail The detail object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_ui_event_init(dom_ui_event *evt, struct dom_string *type, + bool bubble, bool cancelable, struct dom_abstract_view *view, + long detail) +{ + evt->view = view; + evt->detail = detail; + + return _dom_event_init(&evt->base, type, bubble, cancelable); +} + +/** + * Initialise the UIEvent with namespace + * + * \param evt The Event object + * \param namespace The namespace of this Event + * \param type The type of this UIEvent + * \param bubble Whether this event can bubble + * \param cancelable Whether this event is cancelable + * \param view The AbstractView of this UIEvent + * \param detail The detail object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_ui_event_init_ns(dom_ui_event *evt, + struct dom_string *namespace, struct dom_string *type, + bool bubble, bool cancelable, struct dom_abstract_view *view, + long detail) +{ + evt->view = view; + evt->detail = detail; + + return _dom_event_init_ns(&evt->base, namespace, type, bubble, + cancelable); +} + diff --git a/src/events/ui_event.h b/src/events/ui_event.h new file mode 100644 index 0000000..3a245ab --- /dev/null +++ b/src/events/ui_event.h @@ -0,0 +1,54 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#ifndef dom_interntal_events_ui_event_h_ +#define dom_interntal_events_ui_event_h_ + +#include + +#include "events/event.h" + +/** + * The modifier key state + */ +typedef enum { + DOM_MOD_CTRL = (1<<0), + DOM_MOD_META = (1<<1), + DOM_MOD_SHIFT = (1<<2), + DOM_MOD_ALT = (1<<3), + DOM_MOD_ALT_GRAPH = (1<<4), + DOM_MOD_CAPS_LOCK = (1<<5), + DOM_MOD_NUM_LOCK = (1<<6), + DOM_MOD_SCROLL = (1<<7) +} dom_modifier_key; + +/** + * The UIEvent + */ +struct dom_ui_event { + struct dom_event base; /**< The base class */ + struct dom_abstract_view *view; /**< The AbstractView */ + long detail; /**< Some private data for this event */ +}; + +/* Constructor */ +dom_exception _dom_ui_event_create(struct dom_document *doc, + struct dom_ui_event **evt); + +/* Destructor */ +void _dom_ui_event_destroy(struct dom_document *doc, + struct dom_ui_event *evt); + +/* Initialise function */ +dom_exception _dom_ui_event_initialise(struct dom_document *doc, + struct dom_ui_event *evt); + +/* Finalise function */ +void _dom_ui_event_finalise(struct dom_document *doc, + struct dom_ui_event *evt); + +#endif -- cgit v1.2.3