Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <stdlib.h>
  10.  
  11. #include "events/event.h"
  12. #include "events/event_listener.h"
  13. #include "events/event_target.h"
  14.  
  15. #include "core/document.h"
  16. #include "core/node.h"
  17. #include "core/string.h"
  18.  
  19. #include "utils/utils.h"
  20. #include "utils/validate.h"
  21.  
  22. static void event_target_destroy_listeners(struct listener_entry *list)
  23. {
  24.         struct listener_entry *next = NULL;
  25.  
  26.         for (; list != next; list = next) {
  27.                 next = (struct listener_entry *) list->list.next;
  28.  
  29.                 list_del(&list->list);
  30.                 dom_event_listener_unref(list->listener);
  31.                 dom_string_unref(list->type);
  32.                 free(list);
  33.         }
  34. }
  35.  
  36. /* Initialise this EventTarget */
  37. dom_exception _dom_event_target_internal_initialise(
  38.                 dom_event_target_internal *eti)
  39. {
  40.         eti->listeners = NULL;
  41.  
  42.         return DOM_NO_ERR;
  43. }
  44.  
  45. /* Finalise this EventTarget */
  46. void _dom_event_target_internal_finalise(dom_event_target_internal *eti)
  47. {
  48.         if (eti->listeners != NULL)
  49.                 event_target_destroy_listeners(eti->listeners);
  50. }
  51.  
  52. /*-------------------------------------------------------------------------*/
  53. /* The public API */
  54.  
  55. /**
  56.  * Add an EventListener to the EventTarget
  57.  *
  58.  * \param et        The EventTarget object
  59.  * \param type      The event type which this event listener listens for
  60.  * \param listener  The event listener object
  61.  * \param capture   Whether add this listener in the capturing phase
  62.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  63.  */
  64. dom_exception _dom_event_target_add_event_listener(
  65.                 dom_event_target_internal *eti,
  66.                 dom_string *type, struct dom_event_listener *listener,
  67.                 bool capture)
  68. {
  69.         struct listener_entry *le = NULL;
  70.  
  71.         le = malloc(sizeof(struct listener_entry));
  72.         if (le == NULL)
  73.                 return DOM_NO_MEM_ERR;
  74.        
  75.         /* Initialise the listener_entry */
  76.         list_init(&le->list);
  77.         le->type = dom_string_ref(type);
  78.         le->listener = listener;
  79.         dom_event_listener_ref(listener);
  80.         le->capture = capture;
  81.  
  82.         if (eti->listeners == NULL) {
  83.                 eti->listeners = le;
  84.         } else {
  85.                 list_append(&eti->listeners->list, &le->list);
  86.         }
  87.  
  88.         return DOM_NO_ERR;
  89. }
  90.  
  91. /**
  92.  * Remove an EventListener from the EventTarget
  93.  *
  94.  * \param et        The EventTarget object
  95.  * \param type      The event type this listener is registered for
  96.  * \param listener  The listener object
  97.  * \param capture   Whether the listener is registered at the capturing phase
  98.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  99.  */
  100. dom_exception _dom_event_target_remove_event_listener(
  101.                 dom_event_target_internal *eti,
  102.                 dom_string *type, struct dom_event_listener *listener,
  103.                 bool capture)
  104. {
  105.         if (eti->listeners != NULL) {
  106.                 struct listener_entry *le = eti->listeners;
  107.  
  108.                 do {
  109.                         if (dom_string_isequal(le->type, type) &&
  110.                                         le->listener == listener &&
  111.                                         le->capture == capture) {
  112.                                 list_del(&le->list);
  113.                                 dom_event_listener_unref(le->listener);
  114.                                 dom_string_unref(le->type);
  115.                                 free(le);
  116.                                 break;
  117.                         }
  118.  
  119.                         le = (struct listener_entry *) le->list.next;
  120.                 } while (le != eti->listeners);
  121.         }
  122.  
  123.         return DOM_NO_ERR;
  124. }
  125.  
  126. /**
  127.  * Add an EventListener
  128.  *
  129.  * \param et         The EventTarget object
  130.  * \param namespace  The namespace of this listener
  131.  * \param type       The event type which this event listener listens for
  132.  * \param listener   The event listener object
  133.  * \param capture    Whether add this listener in the capturing phase
  134.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  135.  *
  136.  * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR.
  137.  */
  138. dom_exception _dom_event_target_add_event_listener_ns(
  139.                 dom_event_target_internal *eti,
  140.                 dom_string *namespace, dom_string *type,
  141.                 struct dom_event_listener *listener, bool capture)
  142. {
  143.         UNUSED(eti);
  144.         UNUSED(namespace);
  145.         UNUSED(type);
  146.         UNUSED(listener);
  147.         UNUSED(capture);
  148.  
  149.         return DOM_NOT_SUPPORTED_ERR;
  150. }
  151.  
  152. /**
  153.  * Remove an EventListener
  154.  *
  155.  * \param et         The EventTarget object
  156.  * \param namespace  The namespace of this listener
  157.  * \param type       The event type which this event listener listens for
  158.  * \param listener   The event listener object
  159.  * \param capture    Whether add this listener in the capturing phase
  160.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  161.  *
  162.  * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR.
  163.  */
  164. dom_exception _dom_event_target_remove_event_listener_ns(
  165.                 dom_event_target_internal *eti,
  166.                 dom_string *namespace, dom_string *type,
  167.                 struct dom_event_listener *listener, bool capture)
  168. {
  169.         UNUSED(eti);
  170.         UNUSED(namespace);
  171.         UNUSED(type);
  172.         UNUSED(listener);
  173.         UNUSED(capture);
  174.  
  175.         return DOM_NOT_SUPPORTED_ERR;
  176. }
  177.  
  178. /*-------------------------------------------------------------------------*/
  179.  
  180. /**
  181.  * Dispatch an event on certain EventTarget
  182.  *
  183.  * \param et       The EventTarget object
  184.  * \param eti      Internal EventTarget object
  185.  * \param evt      The event object
  186.  * \param success  Indicates whether any of the listeners which handled the
  187.  *                 event called Event.preventDefault(). If
  188.  *                 Event.preventDefault() was called the returned value is
  189.  *                 false, else it is true.
  190.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  191.  */
  192. dom_exception _dom_event_target_dispatch(dom_event_target *et,
  193.                 dom_event_target_internal *eti,
  194.                 struct dom_event *evt, dom_event_flow_phase phase,
  195.                 bool *success)
  196. {
  197.         if (eti->listeners != NULL) {
  198.                 struct listener_entry *le = eti->listeners;
  199.  
  200.                 evt->current = et;
  201.  
  202.                 do {
  203.                         if (dom_string_isequal(le->type, evt->type)) {
  204.                                 assert(le->listener->handler != NULL);
  205.  
  206.                                 if ((le->capture &&
  207.                                                 phase == DOM_CAPTURING_PHASE) ||
  208.                                     (le->capture == false &&
  209.                                                 phase == DOM_BUBBLING_PHASE) ||
  210.                                     (evt->target == evt->current &&
  211.                                                 phase == DOM_AT_TARGET)) {
  212.                                         le->listener->handler(evt,
  213.                                                         le->listener->pw);
  214.                                         /* If the handler called
  215.                                          * stopImmediatePropagation, we should
  216.                                          * break */
  217.                                         if (evt->stop_now == true)
  218.                                                 break;
  219.                                 }
  220.                         }
  221.  
  222.                         le = (struct listener_entry *) le->list.next;
  223.                 } while (le != eti->listeners);
  224.         }
  225.  
  226.         if (evt->prevent_default == true)
  227.                 *success = false;
  228.  
  229.         return DOM_NO_ERR;
  230. }
  231.  
  232.