summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn-Mark Bell <jmb@netsurf-browser.org>2024-01-21 22:15:04 +0000
committerJohn-Mark Bell <jmb@netsurf-browser.org>2024-01-21 22:48:45 +0000
commit0aeccbf5125c4554cc651453beceb4a3d2551de8 (patch)
treef9d36882d684e73a0e277241f8e0772596ccdfe5
parent968db3366eaf291f91a17a46ad9c27d2004c99b9 (diff)
downloadnetsurf-0aeccbf5125c4554cc651453beceb4a3d2551de8.tar.gz
netsurf-0aeccbf5125c4554cc651453beceb4a3d2551de8.tar.bz2
HTML: track changes on DOM Elements
-rw-r--r--content/handlers/html/box/manager.c95
-rw-r--r--utils/corestringlist.h1
2 files changed, 90 insertions, 6 deletions
diff --git a/content/handlers/html/box/manager.c b/content/handlers/html/box/manager.c
index d8dadf300..6d558e41e 100644
--- a/content/handlers/html/box/manager.c
+++ b/content/handlers/html/box/manager.c
@@ -6,6 +6,17 @@
#include "utils/corestrings.h"
#include "utils/log.h"
+/* Flags for DOM Element nodes */
+
+#define BM_DOM_FLAG_STRUCTURE_CHANGED 0x00000001
+/* Document structure has changed at this node: recompute style information
+ * for it, its descendants, its subsequent siblings, and their descendants.
+ * If styles have changed, rebuild box subtree */
+
+#define BM_DOM_FLAG_TEXT_CONTENTS_CHANGED 0x00000002
+/* Text contents of this node have changed: rebuild box subtree */
+
+
struct box_manager
{
dom_document *doc;
@@ -198,13 +209,65 @@ _find_parent_element_or_document(dom_node *target)
return parent;
}
+static dom_exception
+_foreach_element_sibling(dom_node *cur,
+ dom_exception (*cb)(dom_node *, void *), void *pw)
+{
+ dom_node *sibling = NULL;
+ dom_exception exc;
+
+ dom_node_ref(cur);
+
+ do {
+ exc = dom_node_get_next_sibling(cur, &sibling);
+ dom_node_unref(cur);
+ cur = sibling;
+ sibling = NULL;
+
+ if (exc == DOM_NO_ERR && cur != NULL) {
+ dom_node_type sibling_type;
+
+ exc = dom_node_get_node_type(cur, &sibling_type);
+ if (exc == DOM_NO_ERR &&
+ sibling_type == DOM_ELEMENT_NODE) {
+ exc = cb(cur, pw);
+ }
+ }
+ } while (exc == DOM_NO_ERR && cur != NULL);
+
+ dom_node_unref(cur);
+
+ return exc;
+}
+
+static dom_exception
+_set_node_flags(dom_node *node, void *pw)
+{
+ uintptr_t flags_to_set = (uintptr_t) pw;
+ uintptr_t node_flags = 0;
+ dom_exception exc;
+
+ exc = dom_node_get_user_data(node,
+ corestring_dom___ns_key_bm_node_data,
+ (void **) &node_flags);
+ if (exc == DOM_NO_ERR) {
+ node_flags |= flags_to_set;
+ exc = dom_node_set_user_data(node,
+ corestring_dom___ns_key_bm_node_data,
+ (void *) node_flags,
+ NULL,
+ (void **) &node_flags);
+ }
+ return exc;
+}
+
static void
box_manager_handle_dom_event(dom_event *evt, void *pw)
{
box_manager *mgr = pw;
dom_node *parent = NULL;
dom_event_target *target = NULL;
- dom_node_type node_type;
+ dom_node_type target_type;
dom_string *evt_type = NULL, *computed_type = NULL;
dom_exception exc;
@@ -244,9 +307,9 @@ box_manager_handle_dom_event(dom_event *evt, void *pw)
}
/* 3. The event target must be an Element or Text node */
- exc = dom_node_get_node_type(target, &node_type);
- if (exc != DOM_NO_ERR || (node_type != DOM_ELEMENT_NODE &&
- node_type != DOM_TEXT_NODE)) {
+ exc = dom_node_get_node_type(target, &target_type);
+ if (exc != DOM_NO_ERR || (target_type != DOM_ELEMENT_NODE &&
+ target_type != DOM_TEXT_NODE)) {
dom_node_unref(target);
return;
}
@@ -258,9 +321,29 @@ box_manager_handle_dom_event(dom_event *evt, void *pw)
return;
}
- /* 5. mark target dirty */
- // XXX: we probably want a uintptr_t's worth of user data containing flags for now
+ /* 5. update node flags */
+ if (target_type == DOM_ELEMENT_NODE) {
+ /* Mark nodes as structurally changed */
+ if (computed_type == corestring_dom_DOMNodeRemoved) {
+ /* All subsequent sibling elements */
+ exc = _foreach_element_sibling((dom_node *) target,
+ _set_node_flags,
+ (void *) BM_DOM_FLAG_STRUCTURE_CHANGED);
+ } else {
+ /* Just target itself */
+ exc = _set_node_flags((dom_node *) target,
+ (void *) BM_DOM_FLAG_STRUCTURE_CHANGED);
+ }
+ } else if (target_type == DOM_TEXT_NODE) {
+ /* Mark parent as text content changed */
+ exc = _set_node_flags((dom_node *) parent,
+ (void *) BM_DOM_FLAG_TEXT_CONTENTS_CHANGED);
+ }
dom_node_unref(target);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(parent);
+ return;
+ }
/* 6. Capture parent node (ensuring we keep a ref) into list of
* pending events. */
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index ff8e49a35..b96039b41 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -366,6 +366,7 @@ CORESTRING_DOM_STRING(wheel);
CORESTRING_DOM_STRING(sort);
CORESTRING_DOM_STRING(toggle);
/* DOM userdata keys, not really CSS */
+CORESTRING_DOM_STRING(__ns_key_bm_node_data);
CORESTRING_DOM_STRING(__ns_key_box_node_data);
CORESTRING_DOM_STRING(__ns_key_libcss_node_data);
CORESTRING_DOM_STRING(__ns_key_file_name_node_data);