summaryrefslogtreecommitdiff
path: root/src/dom/watcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dom/watcher.c')
-rw-r--r--src/dom/watcher.c137
1 files changed, 98 insertions, 39 deletions
diff --git a/src/dom/watcher.c b/src/dom/watcher.c
index 7de4f31..c33702e 100644
--- a/src/dom/watcher.c
+++ b/src/dom/watcher.c
@@ -5,7 +5,12 @@
*/
/** \file src/dom/watcher.c
- * DOM mutation handling
+ * Implementation of DOM mutation watching.
+ *
+ * TODO: LibDOM mutation event listeners are really slow.
+ * Need to find a better way to get DOM change notifications.
+ * LibDOM probably needs to gain Mutation Observer support, or
+ * gain a LibDOM-specific extension API.
*/
#include <assert.h>
@@ -13,21 +18,31 @@
#include <stdio.h>
#include <string.h>
-#include "layout.h"
#include "dom/debug.h"
#include "dom/watcher.h"
#include "util/dom-str.h"
#include "util/util.h"
+
+/**
+ * A dom watcher object
+ */
+struct nsl_dom_watcher {
+ dom_document *document;
+ dom_event_listener *listener; /**< DOM event listener object */
+};
+
/**
* LibDOM event handler
*
- * \param[in] evt The LibDOM event object
- * \param[in] pw Pointer to our nslayout_layout object
+ * \param[in] evt The LibDOM event object
+ * \param[in] pw Pointer to our dom watcher object
*/
static void nsl__dom_event_handler(struct dom_event *evt, void *pw)
{
- UNUSED(pw);
+ const struct nsl_dom_watcher *watcher = pw;
+
+ UNUSED(watcher);
nsl_dom_debug_dump_event(evt);
@@ -39,77 +54,121 @@ static void nsl__dom_event_handler(struct dom_event *evt, void *pw)
*/
}
-/* Exported function, documented in src/dom/watcher.h */
-nslayout_error nsl_dom_watcher_add_for_layout(nslayout_layout *layout)
+
+/**
+ * Destroy a DOM document's event listener
+ *
+ * \param[in] listener The listener to destroy
+ * \param[in] document The document that the listener was registerd for.
+ * \return NSLAYOUT_OK on success, appropriate error otherwise.
+ */
+static nslayout_error nsl__dom_listener_destroy(
+ dom_event_listener *listener,
+ dom_document *document)
{
dom_exception exc;
- /* TODO: LibDOM mutation event listeners are really slow.
- * Need to find a better way to get DOM change notifications.
- * LibDOM probably needs to gain Mutation Observer support.
- */
+ /* Passing NULL as type, removes listener for all event types. */
+ exc = dom_event_target_remove_event_listener(
+ document, NULL, listener, false);
+ if (exc != DOM_NO_ERR) {
+ return NSL_DOM_ERR(exc);
+ }
+
+ dom_event_listener_unref(listener);
+
+ return NSLAYOUT_OK;
+}
- assert(layout->listener == NULL);
+/**
+ * Create a dom event listener.
+ *
+ * \param[out] listener_out Returns a dom listener for watcher's document.
+ * \param[in] watcher DOM watcher object that listener is used for.
+ * \return NSLAYOUT_OK on success, appropriate error otherwise.
+ */
+static nslayout_error nsl__dom_listener_create(
+ dom_event_listener **listener_out,
+ const struct nsl_dom_watcher *watcher)
+{
+ dom_event_listener *listener;
+ dom_exception exc;
+
+ /* Create listener */
exc = dom_event_listener_create(nsl__dom_event_handler,
- layout, &layout->listener);
+ (void *) watcher, &listener);
if (exc != DOM_NO_ERR) {
goto error;
}
- exc = dom_event_target_add_event_listener(
- layout->doc, nsl_dom_str_node_inserted,
- layout->listener, false);
+ /* Set the event types it should listen to */
+ exc = dom_event_target_add_event_listener(watcher->document,
+ nsl_dom_str_node_inserted, listener, false);
if (exc != DOM_NO_ERR) {
goto error;
}
- exc = dom_event_target_add_event_listener(
- layout->doc, nsl_dom_str_subtree_modified,
- layout->listener, false);
+ exc = dom_event_target_add_event_listener(watcher->document,
+ nsl_dom_str_subtree_modified, listener, false);
if (exc != DOM_NO_ERR) {
goto error;
}
- exc = dom_event_target_add_event_listener(
- layout->doc, nsl_dom_str_node_removed,
- layout->listener, false);
+ exc = dom_event_target_add_event_listener(watcher->document,
+ nsl_dom_str_node_removed, listener, false);
if (exc != DOM_NO_ERR) {
goto error;
}
- exc = dom_event_target_add_event_listener(
- layout->doc, nsl_dom_str_attr_modified,
- layout->listener, false);
+ exc = dom_event_target_add_event_listener(watcher->document,
+ nsl_dom_str_attr_modified, listener, false);
if (exc != DOM_NO_ERR) {
goto error;
}
- exc = dom_event_target_add_event_listener(
- layout->doc, nsl_dom_str_characterdata_modified,
- layout->listener, false);
+ exc = dom_event_target_add_event_listener(watcher->document,
+ nsl_dom_str_characterdata_modified, listener, false);
if (exc != DOM_NO_ERR) {
goto error;
}
+ *listener_out = listener;
return NSLAYOUT_OK;
error:
- nsl_dom_watcher_remove_for_layout(layout);
+ nsl__dom_listener_destroy(listener, watcher->document);
return NSL_DOM_ERR(exc);
}
-/* Exported function, documented in src/dom/event.h */
-nslayout_error nsl_dom_watcher_remove_for_layout(nslayout_layout *layout)
+/* Exported function, documented in src/dom/watcher.h */
+nslayout_error nsl_dom_watcher_create(
+ struct nsl_dom_watcher **watcher_out,
+ dom_document *document)
{
- dom_exception exc;
+ struct nsl_dom_watcher *watcher;
+ nslayout_error err;
- /* Passing NULL as type, removes listener for all event types. */
- exc = dom_event_target_remove_event_listener(
- layout->doc, NULL, layout->listener, false);
- if (exc != DOM_NO_ERR) {
- return NSL_DOM_ERR(exc);
+ watcher = malloc(sizeof(*watcher));
+ if (watcher == NULL) {
+ return NSLAYOUT_NO_MEM;
+ }
+
+ watcher->document = document;
+
+ err = nsl__dom_listener_create(&watcher->listener, watcher);
+ if (err != NSLAYOUT_OK) {
+ free(watcher);
+ return err;
}
- dom_event_listener_unref(layout->listener);
- layout->listener = NULL;
+ *watcher_out = watcher;
+ return NSLAYOUT_OK;
+}
+
+/* Exported function, documented in src/dom/watcher.h */
+nslayout_error nsl_dom_watcher_destroy(
+ struct nsl_dom_watcher *watcher)
+{
+ nsl__dom_listener_destroy(watcher->listener, watcher->document);
+ free(watcher);
return NSLAYOUT_OK;
}