From f18b7ad86fe25e32cac7d9bca1abe92c46437535 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 5 Feb 2017 22:41:04 +0000 Subject: dom watcher: Add callback for dom mutation watching. --- src/dom/watcher.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/dom/watcher.h | 36 +++++++++++++++++++++++++- src/layout.c | 38 +++++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 13 deletions(-) diff --git a/src/dom/watcher.c b/src/dom/watcher.c index cb775c6..d515cf6 100644 --- a/src/dom/watcher.c +++ b/src/dom/watcher.c @@ -31,8 +31,10 @@ * A dom watcher object */ struct nsl_dom_watcher { - dom_document *document; - dom_event_listener *listener; /**< DOM event listener object */ + dom_document *document; /**< DOM document */ + dom_event_listener *listener; /**< DOM event listener object */ + nsl_dom_watcher_cb watcher_cb; /**< Client callback */ + void *pw; /**< Client data */ }; /** @@ -44,17 +46,65 @@ struct nsl_dom_watcher { static void nsl__dom_event_handler(struct dom_event *evt, void *pw) { const struct nsl_dom_watcher *watcher = pw; - - UNUSED(watcher); + enum nsl_dom_watcher_type type; + dom_event_target *node = NULL; + dom_string *evt_type = NULL; + dom_node_type node_type; + dom_exception exc; nsl_dom_debug_dump_event(evt); - /* TODO: Based on event type: - * 1. call to do (re)selection: - * a. all nodes? - * b. just this node? - * 2. call to update layout, if needed. - */ + exc = dom_event_get_target(evt, &node); + if ((exc != DOM_NO_ERR) || (node == NULL)) { + printf("FAILED to get target node!\n"); + goto fail; + } + + exc = dom_node_get_node_type(node, &node_type); + if (exc != DOM_NO_ERR) { + printf("FAILED to get target node type!\n"); + goto fail; + } + + exc = dom_event_get_type(evt, &evt_type); + if ((exc != DOM_NO_ERR) || (evt_type == NULL)) { + printf("FAILED to get event type!\n"); + goto fail; + } + + if (dom_string_isequal(evt_type, + nsl_dom_str_node_inserted)) { + type = NSL_DOM_WATCHER_NODE_INSERTED; + + } else if (dom_string_isequal(evt_type, + nsl_dom_str_node_removed)) { + type = NSL_DOM_WATCHER_NODE_REMOVED; + + } else if (dom_string_isequal(evt_type, + nsl_dom_str_subtree_modified)) { + type = NSL_DOM_WATCHER_SUBTREE_MODIFIED; + + } else if (dom_string_isequal(evt_type, + nsl_dom_str_attr_modified)) { + type = NSL_DOM_WATCHER_ATTR_MODIFIED; + + } else if (dom_string_isequal(evt_type, + nsl_dom_str_characterdata_modified)) { + type = NSL_DOM_WATCHER_CHAR_DATA_MODIFIED; + } else { + printf("FAILED: unrecognised event type: '%s'", + dom_string_data(evt_type)); + goto fail; + } + + dom_string_unref(evt_type); + + watcher->watcher_cb(type, node, node_type, watcher->pw); + return; + +fail: + if (evt_type != NULL) dom_string_unref(evt_type); + if (node != NULL) dom_node_unref(node); } @@ -144,7 +194,9 @@ error: /* Exported function, documented in src/dom/watcher.h */ nslayout_error nsl_dom_watcher_create( struct nsl_dom_watcher **watcher_out, - dom_document *document) + dom_document *document, + nsl_dom_watcher_cb watcher_cb, + void *pw) { struct nsl_dom_watcher *watcher; nslayout_error err; @@ -155,6 +207,8 @@ nslayout_error nsl_dom_watcher_create( } watcher->document = document; + watcher->watcher_cb = watcher_cb; + watcher->pw = pw; err = nsl__dom_listener_create(&watcher->listener, watcher); if (err != NSLAYOUT_OK) { diff --git a/src/dom/watcher.h b/src/dom/watcher.h index a6f2568..0883fd2 100644 --- a/src/dom/watcher.h +++ b/src/dom/watcher.h @@ -14,16 +14,50 @@ struct dom_document; struct nsl_dom_watcher; +/** + * DOM watcher's mutation types + */ +enum nsl_dom_watcher_type { + NSL_DOM_WATCHER_NODE_INSERTED, + NSL_DOM_WATCHER_NODE_REMOVED, + NSL_DOM_WATCHER_SUBTREE_MODIFIED, + NSL_DOM_WATCHER_ATTR_MODIFIED, + NSL_DOM_WATCHER_CHAR_DATA_MODIFIED, + NSL_DOM_WATCHER__COUNT, +}; + + +/** + * Callback function for dom modifications. + * + * \param[in] type The mutation type. + * \param[in] node The target node. (Caller yields ownership.) + * \param[in] node_type The type of node. + * \param[in] pw The dom watcher owner's private data. + * \return NSLAYOUT_OK on success, appropriate error otherwise. + */ +typedef nslayout_error (*nsl_dom_watcher_cb)( + enum nsl_dom_watcher_type type, + dom_event_target *node, + dom_node_type node_type, + void *pw); + + /** * Create DOM change watcher for a DOM document. * * \param[out] watcher_out Returns a dom watcher object for layout. * \param[in] document DOM document to create watcher for. + * \param[in] watcher_cb Function to call when dom modification happens. + * \param[in] pw Private data passed back to `watcher_cb`. * \return NSLAYOUT_OK on success, appropriate error otherwise. */ nslayout_error nsl_dom_watcher_create( struct nsl_dom_watcher **watcher_out, - dom_document *document); + dom_document *document, + nsl_dom_watcher_cb watcher_cb, + void *pw); + /** * Destroy a document change DOM change watcher. diff --git a/src/layout.c b/src/layout.c index d894f13..e4824bf 100644 --- a/src/layout.c +++ b/src/layout.c @@ -14,6 +14,7 @@ #include "libnslayout/nslayout.h" #include "layout.h" +#include "util/util.h" #include "dom/watcher.h" #include "util/dom-str.h" @@ -46,6 +47,40 @@ nslayout_error nslayout_fini(void) } +/** + * Callback function for dom modifications. + * + * \param[in] type The mutation type. + * \param[in] node The target node. (Caller yields ownership.) + * \param[in] node_type The type of node. + * \param[in] pw The layout object. + * \return NSLAYOUT_OK on success, appropriate error otherwise. + */ +static nslayout_error nsl_layout_dom_watcher_cb( + enum nsl_dom_watcher_type type, + dom_event_target *node, + dom_node_type node_type, + void *pw) +{ + nslayout_layout *layout = pw; + + UNUSED(type); + UNUSED(layout); + UNUSED(node_type); + + /* TODO: Based on event type: + * 1. call to do (re)selection: + * a. all nodes? + * b. just this node? + * 2. call to update layout, if needed. + */ + + dom_node_unref(node); + + return NSLAYOUT_OK; +} + + /* Publically exported function, documented in include/libnslayout/nslayout.h */ nslayout_error nslayout_layout_create( dom_document *doc, @@ -75,7 +110,8 @@ nslayout_error nslayout_layout_create( l->cb = cb; l->pw = pw; - err = nsl_dom_watcher_create(&l->watcher, l->document); + err = nsl_dom_watcher_create(&l->watcher, l->document, + nsl_layout_dom_watcher_cb, l); if (err != NSLAYOUT_OK) { return err; } -- cgit v1.2.3