summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dom/watcher.c137
-rw-r--r--src/dom/watcher.h20
-rw-r--r--src/layout.c6
-rw-r--r--src/layout.h4
4 files changed, 116 insertions, 51 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;
}
diff --git a/src/dom/watcher.h b/src/dom/watcher.h
index 87f0a1b..2894db6 100644
--- a/src/dom/watcher.h
+++ b/src/dom/watcher.h
@@ -5,7 +5,7 @@
*/
/** \file src/dom/watcher.h
- * Layout object handling
+ * Interface to DOM mutation watching.
*/
#ifndef nslayout_dom_watcher_h_
@@ -13,20 +13,26 @@
#include <libnslayout/nslayout.h>
+struct nsl_dom_watcher;
+
/**
- * Add DOM change watchers to the layout's document.'
+ * Create DOM change watcher for a DOM document.
*
- * \param[in] layout nslayout_layout object to set watchers for.
+ * \param[out] watcher_out Returns a dom watcher object for layout.
+ * \param[in] document DOM document to create watcher for.
* \return NSLAYOUT_OK on success, appropriate error otherwise.
*/
-nslayout_error nsl_dom_watcher_add_for_layout(nslayout_layout *layout);
+nslayout_error nsl_dom_watcher_create(
+ struct nsl_dom_watcher **watcher_out,
+ dom_document *document);
/**
- * Remove DOM change watchers from the layout's document.
+ * Destroy a document change DOM change watcher.
*
- * \param[in] layout nslayout_layout object remove watchers from.
+ * \param[in] watcher DOM change watcher to destroy.
* \return NSLAYOUT_OK on success, appropriate error otherwise.
*/
-nslayout_error nsl_dom_watcher_remove_for_layout(nslayout_layout *layout);
+nslayout_error nsl_dom_watcher_destroy(
+ struct nsl_dom_watcher *watcher);
#endif
diff --git a/src/layout.c b/src/layout.c
index c660c82..6921a4d 100644
--- a/src/layout.c
+++ b/src/layout.c
@@ -53,13 +53,13 @@ nslayout_error nslayout_layout_create(
}
/* TODO: Decide: ownership will probably be passed to libnslayout */
- l->doc = doc;
+ l->document = doc;
l->css_ctx = css_ctx;
l->media = media;
l->cb = cb;
l->pw = pw;
- err = nsl_dom_watcher_add_for_layout(l);
+ err = nsl_dom_watcher_create(&l->watcher, l->document);
if (err != NSLAYOUT_OK) {
return err;
}
@@ -78,7 +78,7 @@ nslayout_error nslayout_layout_destroy(
assert(layout != NULL);
/* TODO: free/unref the stuff we own in the layout */
- err = nsl_dom_watcher_remove_for_layout(layout);
+ err = nsl_dom_watcher_destroy(layout->watcher);
if (err != NSLAYOUT_OK) {
return err;
}
diff --git a/src/layout.h b/src/layout.h
index 3549174..3bc9a30 100644
--- a/src/layout.h
+++ b/src/layout.h
@@ -17,13 +17,13 @@
* The layout object for a DOM document
*/
struct nslayout_layout {
- dom_document *doc;
+ dom_document *document;
css_select_ctx *css_ctx;
css_media_type *media;
nslayout_callback cb;
void *pw;
- dom_event_listener *listener;
+ struct nsl_dom_watcher *watcher;
};
#endif