diff options
author | Michael Drake <tlsa@netsurf-browser.org> | 2017-02-05 13:01:21 +0000 |
---|---|---|
committer | Michael Drake <tlsa@netsurf-browser.org> | 2017-02-05 13:01:21 +0000 |
commit | 1f2942faaf00b22b58747d51c7b186a65f041606 (patch) | |
tree | 0ed97b6035332bf73d3fcb60753f41bf4ceca9a5 | |
parent | 5ab8be1d772f617f505d80e06910ebdd5fdc06ab (diff) | |
download | libnslayout-1f2942faaf00b22b58747d51c7b186a65f041606.tar.gz libnslayout-1f2942faaf00b22b58747d51c7b186a65f041606.tar.bz2 |
dom watcher: Turn the dom watcher into an opaque object.
-rw-r--r-- | src/dom/watcher.c | 137 | ||||
-rw-r--r-- | src/dom/watcher.h | 20 | ||||
-rw-r--r-- | src/layout.c | 6 | ||||
-rw-r--r-- | src/layout.h | 4 |
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 |