summaryrefslogtreecommitdiff
path: root/src/dom/watcher.c
blob: 7de4f3176371cb9e0117be360495d851ef4d7ba8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * This file is part of LibNSLayout
 * Licensed under the ISC License, http://opensource.org/licenses/ISC
 * Copyright 2015 Michael Drake <tlsa@netsurf-browser.org>
 */

/** \file src/dom/watcher.c
 * DOM mutation handling
 */

#include <assert.h>
#include <stdlib.h>
#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"

/**
 * LibDOM event handler
 *
 * \param[in]  evt		The LibDOM event object
 * \param[in]  pw		Pointer to our nslayout_layout object
 */
static void nsl__dom_event_handler(struct dom_event *evt, void *pw)
{
	UNUSED(pw);

	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.
	 */
}

/* Exported function, documented in src/dom/watcher.h */
nslayout_error nsl_dom_watcher_add_for_layout(nslayout_layout *layout)
{
	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.
	 */

	assert(layout->listener == NULL);

	exc = dom_event_listener_create(nsl__dom_event_handler,
			layout, &layout->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);
	if (exc != DOM_NO_ERR) {
		goto error;
	}
	exc = dom_event_target_add_event_listener(
			layout->doc, nsl_dom_str_subtree_modified,
			layout->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);
	if (exc != DOM_NO_ERR) {
		goto error;
	}
	exc = dom_event_target_add_event_listener(
			layout->doc, nsl_dom_str_attr_modified,
			layout->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);
	if (exc != DOM_NO_ERR) {
		goto error;
	}

	return NSLAYOUT_OK;

error:
	nsl_dom_watcher_remove_for_layout(layout);

	return NSL_DOM_ERR(exc);
}

/* Exported function, documented in src/dom/event.h */
nslayout_error nsl_dom_watcher_remove_for_layout(nslayout_layout *layout)
{
	dom_exception exc;

	/* 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);
	}

	dom_event_listener_unref(layout->listener);
	layout->listener = NULL;

	return NSLAYOUT_OK;
}