summaryrefslogtreecommitdiff
path: root/src/dom/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dom/event.c')
-rw-r--r--src/dom/event.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/dom/event.c b/src/dom/event.c
new file mode 100644
index 0000000..152fd34
--- /dev/null
+++ b/src/dom/event.c
@@ -0,0 +1,164 @@
+/*
+ * 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/event.c
+ * DOM mutation handling
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "layout.h"
+#include "dom/event.h"
+#include "util/dom-str.h"
+#include "util/util.h"
+
+static const char *nsl__dom_node_type_to_string(dom_node_type type)
+{
+ const char *str[] = {
+ "ELEMENT_NODE",
+ "ATTRIBUTE_NODE",
+ "TEXT_NODE",
+ "CDATA_SECTION_NODE",
+ "ENTITY_REFERENCE_NODE",
+ "ENTITY_NODE",
+ "PROCESSING_INSTRUCTION_NODE",
+ "COMMENT_NODE",
+ "DOCUMENT_NODE",
+ "DOCUMENT_TYPE_NODE",
+ "DOCUMENT_FRAGMENT_NODE",
+ "NOTATION_NODE"
+ };
+ assert(DOM_NODE_TYPE_COUNT == 12);
+
+ return str[type - 1];
+}
+
+static void nsl__dom_event_handler(struct dom_event *evt, void *pw)
+{
+ dom_event_target *node = NULL;
+ dom_node_type node_type;
+ dom_string *name = NULL;
+ dom_string *type = NULL;
+ dom_exception exc;
+
+ UNUSED(pw);
+
+ printf(" DOM Event: ");
+
+ /* Ugly test to see what events come out */
+ 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;
+ }
+
+ if (node_type == DOM_ELEMENT_NODE) {
+ exc = dom_node_get_node_name(node, &name);
+ if ((exc != DOM_NO_ERR) || (name == NULL)) {
+ printf("FAILED to get target node name!\n");
+ goto fail;
+ }
+ }
+
+ exc = dom_event_get_type(evt, &type);
+ if ((exc != DOM_NO_ERR) || (type == NULL)) {
+ printf("FAILED to get event type!\n");
+ goto fail;
+ }
+
+ if (node_type == DOM_ELEMENT_NODE) {
+ printf("<%s> %s",
+ dom_string_data(name),
+ dom_string_data(type));
+ } else {
+ printf("%s %s",
+ nsl__dom_node_type_to_string(node_type),
+ dom_string_data(type));
+ }
+
+fail:
+ if (type != NULL) dom_string_unref(type);
+ if (name != NULL) dom_string_unref(name);
+ if (node != NULL) dom_node_unref(node);
+
+ printf("\n");
+}
+
+/* Exported function, documented in src/dom/event.h */
+nslayout_error nsl_dom_event_layout_init(nslayout_layout *layout)
+{
+ dom_exception exc;
+
+ /* TODO: Somehow register with libdom to get DOM change notifications.
+ *
+ * At the moment, for testing, the client calls our event
+ * handler directly. It looks as though libdom needs its
+ * DOM event handling improved. Either add DOM mutation
+ * observer support, or add some specific client notification
+ * system, like other rendering engines.
+ */
+
+ exc = dom_event_listener_create(layout->doc, nsl__dom_event_handler,
+ layout, &layout->listener);
+ if (exc != DOM_NO_ERR) {
+ /* TODO: free stuff, return value */
+ printf("Failed to register event handler!\n");
+ return NSLAYOUT_NO_MEM;
+ }
+ exc = dom_event_target_add_event_listener(
+ layout->doc, nsl_dom_str_node_inserted,
+ layout->listener, false);
+ if (exc != DOM_NO_ERR) {
+ /* TODO: free stuff, return value */
+ printf("Failed to register event handler!\n");
+ return NSLAYOUT_NO_MEM;
+ }
+ exc = dom_event_target_add_event_listener(
+ layout->doc, nsl_dom_str_subtree_modified,
+ layout->listener, false);
+ if (exc != DOM_NO_ERR) {
+ /* TODO: free stuff, return value */
+ printf("Failed to register event handler!\n");
+ return NSLAYOUT_NO_MEM;
+ }
+
+ return NSLAYOUT_OK;
+}
+
+/* Exported function, documented in src/dom/event.h */
+nslayout_error nsl_dom_event_layout_fini(nslayout_layout *layout)
+{
+ dom_exception exc;
+
+ exc = dom_event_target_remove_event_listener(
+ layout->doc, nsl_dom_str_node_inserted,
+ layout->listener, false);
+ if (exc != DOM_NO_ERR) {
+ /* TODO: free stuff, return value */
+ printf("Failed to remove event handler!\n");
+ return NSLAYOUT_NO_MEM;
+ }
+ exc = dom_event_target_remove_event_listener(
+ layout->doc, nsl_dom_str_subtree_modified,
+ layout->listener, false);
+ if (exc != DOM_NO_ERR) {
+ /* TODO: free stuff, return value */
+ printf("Failed to remove event handler!\n");
+ return NSLAYOUT_NO_MEM;
+ }
+ dom_event_listener_unref(layout->listener);
+
+ return NSLAYOUT_OK;
+}