Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/fe95004d2a44100c2650694a37e2243d14323eb4
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/fe95004d2a44100c2650694a37e2243d14323eb4
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/fe95004d2a44100c2650694a37e2243d14323eb4

The branch, jmb/bm has been created
        at  fe95004d2a44100c2650694a37e2243d14323eb4 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=fe95004d2a44100c2650694a37e2243d14323eb4
commit fe95004d2a44100c2650694a37e2243d14323eb4
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    Docs: add some

diff --git a/docs/ideas/boxes.txt b/docs/ideas/boxes.txt
new file mode 100644
index 000000000..f1fa2360a
--- /dev/null
+++ b/docs/ideas/boxes.txt
@@ -0,0 +1,493 @@
+Box tree dynamism
+=================
+
+The first building block needed for event-driven layout is for the box tree
+construction and subsequent maintenance to become event driven and for the
+box tree management implementation to emit events marking parts of the tree
+changed so that the layout calculator can react to them.
+
+We expect the box tree to be in normal form at all times (and certainly
+whenever an event is emitted). The box tree manager must ensure that this is
+the case.
+
+[Note: the box tree manager could be plumbed into the existing content handler
+with a little effort: have the box tree constructed dynamically during the
+parse, but ignore box tree events and perform layout computation at the same
+place as currently. As box tree events are ignored, subsequent changes to the
+tree will not result in updated layout computations -- this might produce weird
+effects, so an option might be to forcibly relayout the entire tree on receipt
+of box tree change events received after the initial layout has been performed.
+This would not be substantially different from the existing reformatting on
+viewport dimension changes, and similarly heavyweight]
+
+The box tree manager needs to know when any of the various inputs that
+determine the shape of the box tree changes. These inputs comprise:
+
+  1. Style changes
+  2. DOM changes
+  3. Dynamic pseudo classes
+  4. Other non-DOM changes (predominantly Media Queries)
+
+The following sections consider the each of these inputs and attempts to scope
+out the impact of changes made to them.
+
+
+Style changes
+-------------
+
+Style information can change as the source document is parsed and as external
+stylesheets are fetched. Script may also modify style information via the CSS
+Object Model or simply injecting its own style attribute values into Elements.
+Changes to any of this information has the potential to cause wide-ranging
+ripples across the box tree structure.
+
+
+DOM changes
+-----------
+
+Given CSS 3 selectors and combinators, the impact of DOM changes is thus:
+
+  1. Adding a new Element node:
+       Selection must be re-run for all children of the new node's parent
+       and their descendants (i.e. all trees derived from the new node and
+       its siblings).
+       [XXX: is this correct?] If it is known that neither the 
:nth-last-child()/:nth-last-of-type()
+       pseudo-classes nor the sibling combinators are in use, the selection
+       re-run can be limited to the preceding siblings and the new node (and
+       their descendants).
+  2. Removing a new Element node:
+       Selection must be re-run for all children of the node's former parent
+       and their descendants (i.e. all trees derived from the node's siblings)
+  3. Moving an Element node:
+       This is effectively a removal (see: 2) followed by an addition (see: 1)
+       There is an optimisation to be had if the node is attached to one of
+       its ancestors: in that case, selection need not be re-run on removal
+       (as all of the affected nodes will be in a subtree of the node's
+       siblings on re-insertion).
+  4. Addition/Removal/Modification of an Element node's Attributes:
+       Selection must be re-run for all children of the Element node's parent
+       and their descendants (i.e. all trees derived from the node and its
+       siblings).
+
+
+Dynamic pseudo classes
+----------------------
+
+These require dynamic re-selection based on user activity. The most
+aggressive of which is :hover (as, in theory, causes changes whenever the
+user moves the mouse). So this probably requires the presence of some
+debouncing logic to avoid excessive reselection every time the mouse
+pointer moves 1px in any direction.
+
+The set of affected nodes is as for node addition (where the directly
+affected node serves as the added node).
+
+
+Other Non-DOM changes
+---------------------
+
+Media queries will require re-selection to happen whenever any of the
+queries properties (e.g. viewport dimension) changes. The impact in this
+case, however, is completely unconstrained -- potentially the entire document
+tree may require reselection.
+
+
+
+Change detection
+----------------
+
+In general we want, wherever possible, to minimise the amount of work performed
+to make the box tree reflect reality. This will be achieved through aggressive
+filtering out of unnecessary work and reuse of existing results where possible.
+
+The following sections consider change detection for each of the information
+sources.
+
+
+Detecting selection context changes
+-----------------------------------
+
+Style selection for a node is performed using a selection context
+(simplistically: an ordered list of stylesheets). If a suitable hashing
+scheme can be devised such that we can detect:
+
+  a. changes to the contents of a stylesheet (e.g. as a result of rules
+     or properties being added/removed/changed via the CSS Object Model)
+  b. addition/removal/reordering of stylesheets within a selection context
+
+and we record the aggregation of this information as a single hash value
+within the selection context and also record this hash value alongside the
+computed style for a node, then it becomes trivial to compare the recorded
+value with the live value within the selection context to determine if there
+is any need to do any work.
+
+If work is necessary, and assuming no ability to determine the differences
+between the prior and current set of input styles, a change to the selection
+context effectively invalidates the computed styles for the entire tree. This
+may require further optimisation, however.
+
+
+Detecting DOM changes
+---------------------
+
+Changes to a given Element node that might affect style selection rules are:
+
+  1. The Element's QName
+  2. The Attributes associated with the Element
+
+Assuming a suitable hashing scheme for this information exists, then we can
+compute a hash for the Element whenever any of these items change. This
+"Node Hash" value is stored on the Element itself.
+
+As described above, the position of a node within the DOM also affects the set
+of selection rules that apply to it. Specifically, there are two sets of
+relevant information:
+
+  a. the chain of ancestor nodes up to the document root (and details of any
+     attributes attached to them) 
+  b. the ordered set of children of a node's parent (and details of any
+     attributes attached to them) -- i.e. the node and its siblings
+
+If a suitable hashing scheme for an ordered list of Node Hashes (the
+"Positional Node Hash") can be devised then, on insertion of a node into the
+DOM we can compute:
+
+  1. The hash of the parent node's children, including the inserted node
+     (the "Children Hash")
+  2. The parent node's (if any -- we may be the document root Element)
+     ancestor chain hash plus the hash of the inserted node (the "Ancestor
+     Chain Hash")
+  3. Recursively, the Ancestor Chain Hash of the inserted node's descendants
+     (taking the inserted node as the initial parent and applying (2) to the
+     children, and updating the parent as we recurse down the tree).
+
+The Children Hash is stored on the inserted node's parent.
+The Ancestor Chain Hash is stored on the inserted node itself.
+
+Note that the positional hashing scheme MUST take the Element order into
+account.
+
+On removal of a node from the DOM we must compute:
+
+  1. The (former) parent node's Children Hash, excluding the removed
+     node.
+  2. An invalidation of the stored Ancestor Chain Hash values on the subtree
+     rooted at the removed node (the Children Hashes are unaffected until
+     nodes within the subtree are moved or altered)
+
+As for insertion, the Children Hash is stored on the former parent of the
+removed node.
+
+If, at the point of selection, we record alongside the computed style for the
+target element:
+
+  a. the target Element's Node Hash
+  b. the target Element's Ancestor Chain Hash
+  c. the target Element's parent node's Children Hash
+
+then, when asked to reselect style information for the target node we can
+compare the recorded values with those found on the live DOM tree to determine
+if anything has changed. [Implementation Note: we can save storage space by
+combining the three separate hash values here into a single value by treating
+them as a list of Node Hashes and feeding them to the Positional Node Hash
+function].
+
+
+Detecting changes to pseudo classes
+-----------------------------------
+
+Changes to structural pseudo classes should fall out of the generic DOM change
+detection described above: the DOM tree will have to change for these to do so.
+
+Dynamic pseudo classes, however, are a right pain, particularly in the case
+where you have rules containing selectors that include combinators in
+conjunction with pseudo classes. In these cases, the pseudo class might become
+engaged on any other element in the tree (be that ancestral or siblings, or
+both) surrounding the target element. Thus, there's no trivial way to
+pre-compute an answer and test against it efficiently.
+
+Consider something like this:
+
+div:first-child + :hover wibble :last-child > foo { ... }
+
+This will match a "foo" element whose parent is the last child of "foo"'s
+grandparent and "foo"'s parent has an ancestor element, "wibble" and "wibble"
+has an ancestor element that the user is hovering over and that ancestor
+element is immediately preceded by a "div" that is the first child of their
+parent. If the user isn't hovering over the intermediate ancestor, this rule
+will not match, regardless of the shape of the document tree.
+
+To make matters even more involved, the user may be considered to be hovering
+over the intermediate ancestor as a result of hovering over some other
+descendant of that ancestor. Also, because any ancestor of "wibble" with a
+preceding first child "div" will do, the identity of that ancestor could
+equally well change but the rule still match.
+
+Perhaps, therefore, it becomes necessary to gather the set of nodes for which
+each dynamic pseudo class is active and record this on the document element.
+Then, for each subsequent selection, gather the set of nodes to which these
+pseudo classes apply at that time. This gives two sets:
+
+  a. The previous set of nodes for which each dynamic pseudo class was active
+  b. The current set of nodes for which each dynamic pseudo class is active
+
+The disjunctive union of these two sets produces a set of nodes for which the
+active state of each dynamic pseudo class has changed between selections. Any
+descendant of any node in this set, or of any sibling of any node in this set,
+will require reselection.
+
+The current set of nodes for which each dynamic pseudo class is active will be
+recorded on the document element each time. [Note: it may be possible to
+minimise the set sizes by taking account of the rules involving the relevant
+pseudo class -- in the extreme case, no rules use the relevant pseudo class and
+so the set will always be empty].
+
+
+Detecting other non-DOM changes
+-------------------------------
+
+Media Queries Level 4 permits testing against a variety of mostly-static
+properties of the rendering device. Some properties may change dynamically
+(e.g. viewport width/height when the window is resized). Assuming that all
+property values are always provided and they do not change regularly, the
+simple approach would be to hash the information provided (i.e. property
+names and values) and store the hash alongside computed styles. If the
+hash value changes, then reselection must occur.
+
+If the hash value changes, a more granular additional test would be to apply
+the input properties to all known media queries and cache the results, thus
+ensuring that range-based properties continue to match until they don't even
+if there are slight changes to their declared values. The assumption is that
+this matching will be performant (if it is not, more intelligence is likely
+required).
+
+
+Construction nuances
+--------------------
+
+Avoiding repetitious selection during document construction (assuming no
+scripting causing DOM changes) would be desireable. Given the rules above,
+performing selection for the Element node children of a node is best done
+after the last child of the parent has been added to the document (i.e. when
+the parser encounters the parent Element's closing tag in well-formed
+document source).
+
+This may, however, be difficult to detect reliably from the DOM event stream
+(where only node insertion/removal events are emitted). In a well-formed
+document, we know that a node's subtree is complete once either:
+
+  a) a subsequent sibling is inserted into the node's parent; or
+  b) a subsequent relation is inserted into one of the node's ancestors
+
+In the case of the document root node, the completion of the parse is the
+relevant point (as, until then, children may be changing).
+
+Where the source document is not well-formed (i.e. the likes of the HTML5
+adoption agency are in play), it is possible for nodes to be moved around
+the tree or inserted in unlikely locations in the first place. Where this
+happens, it will be difficult to avoid repetitious selection in a reliable
+manner.
+
+In either case, if repetitious selection is avoided at all, the box tree
+will not be complete until the entire document parse has ended (and the
+event-based box tree builder must take great care to ensure the tree is
+in normal form at all times).
+
+Assuming a well-formed input, all stylesheet references and inline styles
+should be known when the Body Element is inserted into the document. There
+is no point attempting to build any part of the box tree until all the style
+information is available, so waiting until all of the external stylesheets
+have been fetched is probably sensible (perhaps with some timeout to avoid
+waiting forever -- if style information arrives late, then too bad, you get
+to enjoy a load of repetitious selection).
+
+
+Migration considerations
+------------------------
+
+The existing box tree structure conflates a variety of things. Specifically,
+the box tree is not "just" a structure containing nodes to be laid out but it
+also contains large swathes of information that is already stored in the DOM,
+and also pieces of information that have no bearing on how the document is
+laid out or displayed (e.g. form gadgets, which really belong on the DOM, and
+object parameters).
+
+Additionally, there are special-case box types for floated boxes (even using
+different types to distinguish between left and right floated boxes),
+linebreaks, and flex-layout boxes. There are also custom INLINE_CONTAINER
+boxes (which serve as a transparent container for INLINE boxes when the
+containing block only contains INLINE children, but act as a BLOCK box when
+the containing block has both BLOCK and INLINE children). There's also the
+magical INLINE_END box type which represents the far end of a fragmented
+INLINE box.
+
+Retaining the myriad box types (including the special cases) is possible, but
+care will need to be taken to ensure that the box tree remains in normal form
+as and when the type of a box changes (i.e. because the display or float
+property values change).
+
+Boxes also contain various pieces of information created by the layout
+calculator and stashed away for future use. Some generic mechanism to permit
+the layout calculator to associate state with a box is is probably needed
+(with such information being invalidated whenever the relevant section of the
+tree changes).
+
+There is some magic handling of trailing space characters in text elements
+(simplistically: they're flagged on the preceding text box). This was probably
+an optimisation at the time (as the box structure is relatively large), but
+makes many things more complex. This optimisation should be removed entirely
+and, instead, the boxes should reference the underlying text data attached to
+the source DOM nodes (Note: some consideration needs to be given to whitespace
+squashing here, to ensure that continues to happen in a sensible way,
+preferably without duplicating the entire textual contents of the DOM into the
+box tree).
+
+Ideally, then, the box tree contents will be reduced to solely the information
+needed to lay the document out and render it. Where possible, anything that is
+already stored on the DOM should not be duplicated (as it is easy to obtain the
+corresponding DOM node from the box and then query that).
+
+It would be nice to retire talloc, too, as object lifetimes are now
+well-defined.
+
+
+Outwith the HTML content handler, there are several parts of the code that
+expect to be able to access box objects and their contents:
+
+  1. iframe handling
+
+     This involves unpleasant collusion between the HTML content handler and
+     the desktop UI. This layering violation should be cleaned up by
+     introducing a proper orthogonal interface (if needed, or something else,
+     if not). The public "html_redraw_a_box" API should die with it.
+
+  2. save as text
+
+     This is a similar layering violation -- the code is simply in the wrong
+     place. It should be moved down into the HTML content handler and the
+     higher level code should simply dispatch the operation through the content
+     system.
+
+There are also the following things that grub around inside the DOM to fish
+out the box pointer:
+
+  1. The JavaScript Canvas binding
+
+     This is done so it can then call html__redraw_a_box, which is an API
+     private to the HTML content implementation. Bad Daniel, no biscuit.
+
+     The fix here is probably to have the binding fire a "redraw needed" event
+     at the canvas dom_node (which it already knows) and for that to be caught
+     and handled by the HTML content handler itself.
+
+Additionally there are a few places that leak box pointers through APIs:
+
+  1. The content_html_object struct contains the box pointer
+
+     This is used by:
+
+       a. save complete
+
+          This simply checks that the pointer is non-NULL to determine whether
+          to save the corresponding content for the object. Like save as text
+          (described above), this arises as a result of a layering violation.
+          The implementation should be pushed down into the HTML content
+          handler and the higher level code should simply dispatch the
+          operation through the content system. (This would also permit
+          retirement of the similarly anachronistic html_get_document API).
+
+       b. reload
+
+          This cares not about the box pointer, but does process the objects to
+          invalidate their caching status. Again, a layering violation: push
+          the implementation down and invoke it via the content system.
+
+  2. The textsearch_bounds content interface accepts box pointers (as does
+     content_textsearch_add_match)
+
+     While this is internal to the content infrastructure it would be better
+     all round for the exposure of box pointers here to go away and be replaced
+     with something more orthogonal.
+
+There are also places where box pointers might once have been used and no
+longer are, but where vestiges remain:
+
+  1. The core text selection object contains a pointless box pointer field
+     (it is initialised to NULL and never used)
+  2. The Windows frontend's browser_mouse object contains a pointless box
+     pointer field (it is never used).
+
+  These should just be cleaned up.
+
+
+Layout calculation
+------------------
+
+The layout calculators will be notified about changes to the box tree. Change
+events will report the containing block-boxes in which the alterations were
+made. This is analogous to the DOM's SubtreeModified event which is targetted
+at the parent Element containing the modified subtree. (TBD whether one event
+per containing block or one fat event, or some combination of the two -- in the
+situation where positioned and/or floated boxes are involved, changes to the
+in-flow box tree structure may result in *multiple* parent containing blocks
+being affected).
+
+The layout calculators will operate on the box tree to lay it out for a given
+viewport width (where possible, only needing to reflow the altered containing
+block contents, thus performing the minimal amount of work). The resulting
+layout information should be cached on each box tree element (potentially with
+some magic for inlines, as they get (de)fragmented depending upon available
+space).
+
+Once the position and dimensions of all boxes have been determined, the entire
+document should be rendered *unclipped* to produce the intermediate structure
+used for redraw. We expect this step to produce a stack of device-independent
+render operations (one stack level per layer).
+
+"Pictorally":
+
+  [canvas] -> [command, ...]
+  [     1] -> [command, ...]
+  [     2] -> [command, ...]
+  [     3] -> [command, ...]
+  [     4] -> [command, ...]
+
+where the document is then drawn layer-by-layer (canonically: starting at the
+canvas and moving down the stack, overdrawing each layer on top of what has
+been drawn before). [Note: the layers in this structure may not directly
+reflect the z-indexes specified in the source stylesheets in part as a result
+of the magical handling of elements which can create new stack levels -- see
+Appendix E of CSS2.1 for the gory details].
+
+With the exception of text plotting commands, the render operations are
+entirely independent of the originating document and box tree. Text commands
+will necessarily reference the source text data by holding references to the
+relevant DOM string data, and whatever metadata is needed to index into it.
+(As this data is referenced, if the DOM changes, the old text will continue
+to be rendered safely until the redraw stack is updated).
+
+To ensure that the document may be redrawn at any time, regardless of the
+underlying state of the DOM, box tree, or layout calculation, and to ensure
+that redraw output is consistent the redraw stack must be updated atomically
+(simplistically: build a new one, flip the old and new pointers, and destroy
+the old one; more optimised solutions are likely available).
+
+[Note: we omit the precise detail about how the layout calculation is perfomed
+as this is left for future work. The overall event flow and decoupling of
+layout from rendering is, however, important to record].
+
+
+Redraw
+------
+
+Redraw operates solely using the render stack. This is the point that clipping
+is applied (e.g. to skip over any commands that would render outside the clip
+boundary). Additionally, if output scaling is desired, it can be applied at
+this point, too (i.e. by transforming the device-independent render operations
+into device-dependent ones -- just apply a transformation matrix, right?).
+
+Multiple buffering, if desired, is left up to the plotter implementation
+provided by the client (as different frontends may wish to do things
+differently).
+
+[Note: again, the precise detail is omitted here].


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=4edb140c98c8f8918f43c2b670d1a89badf92277
commit 4edb140c98c8f8918f43c2b670d1a89badf92277
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    HTML: skeletal box tree manager

diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index e41cc1d22..4662c0571 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -1,6 +1,7 @@
 # HTML content handler sources
 
-S_HTML := box_construct.c      \
+S_HTML := box/manager.c                \
+       box_construct.c         \
        box_inspect.c           \
        box_manipulate.c        \
        box_normalise.c         \
diff --git a/content/handlers/html/box/manager.c 
b/content/handlers/html/box/manager.c
new file mode 100644
index 000000000..9fe5269d6
--- /dev/null
+++ b/content/handlers/html/box/manager.c
@@ -0,0 +1,175 @@
+#include <stdlib.h>
+
+#include "desktop/gui_internal.h"
+#include "html/box/manager.h"
+#include "netsurf/misc.h"
+#include "utils/corestrings.h"
+
+struct box_manager
+{
+       dom_document *doc;
+       dom_event_listener *listener;
+
+       /* Whether we have been told that stylesheets are available */
+       bool have_styles;
+       /* Whether there is an outstanding callback pending */
+       bool callback_pending;
+
+       dom_node **pending_queue;
+       size_t pending_queue_idx;
+       size_t pending_queue_slots;
+};
+
+static void
+box_manager_process_events(void *pw)
+{
+       box_manager *mgr = pw;
+
+       mgr->callback_pending = false;
+
+       //XXX: implement
+
+       /* Just release references for now */
+       while (mgr->pending_queue_idx > 0) {
+               mgr->pending_queue_idx--;
+               dom_node_unref(mgr->pending_queue[mgr->pending_queue_idx]);
+       }
+
+       // 1. Eliminate nodes which are no longer in our document, or in a 
detached tree (we expect to have received a corresponding event for their 
parent)
+       // 2. Eliminate duplicate nodes from the list
+       // 3. Eliminate nodes which are descendants of other nodes in the list
+       // 4. For every remaining node: (re)build the structural box tree 
segment rooted at each of node's children
+       // 5. For each modified box tree segment:
+       //    a. find the immediate containing block(s) for the segment
+       //       (there may be more than one if posititioned/out-of-flow 
elements are in play)
+       //    b. emit (a) "box tree modified" event(s) referencing the 
containing block(s)
+       //
+       // The box tree must always be in normal form so it may be necessary to 
insert (or remove?) elements between the segment root and its parent box
+       // Layout calculators will receive the "box tree modified" events and 
deal with them
+
+       // XXX: need an API for stylesheet change notifications
+       // On receipt, mark entire tree invalid (synthesise a subtree modified 
event? -- not fired at DOM, for obvious reasons, but could be thrown at our 
event handler)
+}
+
+static void
+box_manager_capture_event(box_manager *mgr, dom_event *evt)
+{
+       dom_exception exc;
+       dom_event_target *target = NULL;
+
+       if (mgr->pending_queue_idx == mgr->pending_queue_slots) {
+               dom_node **tmp;
+               if (mgr->pending_queue == NULL) {
+                       tmp = malloc(sizeof(*tmp) * 32);
+               } else {
+                       tmp = realloc(mgr->pending_queue,
+                               sizeof(*tmp) * (mgr->pending_queue_slots + 32));
+               }
+               if (tmp == NULL) {
+                       /* ENOMEM, but no way to deal with it? */
+                       return;
+               }
+
+               mgr->pending_queue = tmp;
+               mgr->pending_queue_slots += 32;
+       }
+
+       exc = dom_event_get_target(evt, &target);
+       if (exc != DOM_NO_ERR || target == NULL) {
+               /* DOM error, but no way to deal with it? */
+               return;
+       }
+
+       mgr->pending_queue[mgr->pending_queue_idx++] = (dom_node *) target;
+}
+
+static void
+box_manager_handle_dom_event(dom_event *evt, void *pw)
+{
+       box_manager *mgr = pw;
+
+       /* 0. During DOM construction, ignore events until we have all
+        * known stylesheets */
+       if (mgr->have_styles == false) {
+               return;
+       }
+
+       /* 1. Ignore non subtree modified events; ignore events for non-Element
+        * targets (these should be a no-op, by construction) */
+
+       /* 2. Capture event target (ensuring we keep a ref) into list of
+        * pending events */
+       box_manager_capture_event(mgr, evt);
+
+       /* 3. Schedule a callback to process the list (if no callback already
+        * scheduled) */
+       if (mgr->callback_pending == false) {
+               // XXX: 20ms ~= 50Hz -- enough?
+               guit->misc->schedule(20, box_manager_process_events, mgr);
+               mgr->callback_pending = true;
+       }
+}
+
+nserror
+box_manager_create(dom_document *doc, box_manager **manager)
+{
+       box_manager *mgr;
+       dom_exception exc;
+
+       mgr = malloc(sizeof(*mgr));
+       if (mgr == NULL) {
+               return NSERROR_NOMEM;
+       }
+
+       exc = dom_event_listener_create(box_manager_handle_dom_event, mgr,
+                       &mgr->listener);
+       if (exc != DOM_NO_ERR) {
+               free(mgr);
+               return NSERROR_DOM;
+       }
+
+       //XXX: do we need to care about other mutation events?
+       //XXX: or need to do this via the default handlers?
+       exc = dom_event_target_add_event_listener(doc,
+                       corestring_dom_DOMSubtreeModified,
+                       mgr->listener,
+                       true);
+       if (exc != DOM_NO_ERR) {
+               dom_event_listener_unref(mgr->listener);
+               free(mgr);
+               return NSERROR_DOM;
+       }
+
+       mgr->doc = (dom_document *) dom_node_ref(doc);
+       mgr->have_styles = false;
+       mgr->callback_pending = false;
+       mgr->pending_queue = NULL;
+       mgr->pending_queue_idx = mgr->pending_queue_slots = 0;
+
+       *manager = mgr;
+
+       return NSERROR_OK;
+}
+
+nserror
+box_manager_destroy(box_manager *manager)
+{
+       if (manager->callback_pending) {
+               guit->misc->schedule(-1, box_manager_process_events, manager);
+       }
+       while (manager->pending_queue_idx > 0) {
+               manager->pending_queue_idx--;
+               dom_node_unref(
+                       manager->pending_queue[manager->pending_queue_idx]);
+       }
+       free(manager->pending_queue);
+       (void) dom_event_target_remove_event_listener(manager->doc,
+                       corestring_dom_DOMSubtreeModified,
+                       manager->listener,
+                       true);
+       dom_event_listener_unref(manager->listener);
+       dom_node_unref(manager->doc);
+       free(manager);
+
+       return NSERROR_OK;
+}
diff --git a/content/handlers/html/box/manager.h 
b/content/handlers/html/box/manager.h
new file mode 100644
index 000000000..7a98d2182
--- /dev/null
+++ b/content/handlers/html/box/manager.h
@@ -0,0 +1,21 @@
+#ifndef BOX_H_
+#define BOX_H_
+
+#include <dom/dom.h>
+
+#include "utils/errors.h"
+
+typedef struct box_manager box_manager;
+
+//XXX: presumably, this will be a library, so can't use NS types
+nserror box_manager_create(dom_document *doc, box_manager **manager);
+
+nserror box_manager_destroy(box_manager *manager);
+
+//XXX: sane? or should the box manager register its own handlers directly?
+//XXX: if registering, then will only reliably receive events in the CAPTURE 
phase
+//XXX: if not (i.e. using the default handler), will reliably get 
START/FINISHED
+//void box_manager_handle_dom_event(box_manager *manager,
+//             const dom_event *event);
+
+#endif
diff --git a/content/handlers/html/css.c b/content/handlers/html/css.c
index 0bc38844f..ccc78548f 100644
--- a/content/handlers/html/css.c
+++ b/content/handlers/html/css.c
@@ -115,6 +115,7 @@ html_convert_css_callback(hlcache_handle *css,
                      nsurl_access(hlcache_handle_get_url(css)));
                parent->base.active--;
                NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
+               //XXX: tell box tree manager styles have changed?
                break;
 
        case CONTENT_MSG_ERROR:
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 82f5f1388..e53b94af9 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -64,6 +64,7 @@
 #include "html/object.h"
 #include "html/html_save.h"
 #include "html/interaction.h"
+#include "html/box/manager.h"
 #include "html/box.h"
 #include "html/box_construct.h"
 #include "html/box_inspect.h"
@@ -473,6 +474,7 @@ html_create_html_data(html_content *c, const http_parameter 
*params)
        c->refresh = false;
        c->reflowing = false;
        c->title = NULL;
+       c->box_manager = NULL;
        c->bctx = NULL;
        c->layout = NULL;
        c->background_colour = NS_TRANSPARENT;
@@ -569,11 +571,29 @@ html_create_html_data(html_content *c, const 
http_parameter *params)
                return libdom_hubbub_error_to_nserror(error);
        }
 
+       nerror = box_manager_create(c->document, &c->box_manager);
+       if (nerror != NSERROR_OK) {
+               dom_hubbub_parser_destroy(c->parser);
+               c->parser = NULL;
+               nsurl_unref(c->base_url);
+               c->base_url = NULL;
+
+               lwc_string_unref(c->universal);
+               c->universal = NULL;
+               lwc_string_unref(c->media.prefers_color_scheme);
+               c->media.prefers_color_scheme = NULL;
+
+               return nerror;
+       }
+
        err = dom_node_set_user_data(c->document,
                                     corestring_dom___ns_key_html_content_data,
                                     c, html_document_user_data_handler,
                                     (void *) &old_node_data);
        if (err != DOM_NO_ERR) {
+               (void) box_manager_destroy(c->box_manager);
+               c->box_manager = NULL;
+
                dom_hubbub_parser_destroy(c->parser);
                c->parser = NULL;
                nsurl_unref(c->base_url);
@@ -656,6 +676,7 @@ html_process_encoding_change(struct content *c,
        const char *encoding;
        const uint8_t *source_data;
        size_t source_size;
+       nserror nerror;
 
        /* Retrieve new encoding */
        encoding = dom_hubbub_parser_get_encoding(html->parser,
@@ -677,10 +698,12 @@ html_process_encoding_change(struct content *c,
        /* Destroy binding */
        dom_hubbub_parser_destroy(html->parser);
        html->parser = NULL;
-
        if (html->document != NULL) {
                dom_node_unref(html->document);
        }
+       if (html->box_manager != NULL) {
+               box_manager_destroy(html->box_manager);
+       }
 
        parse_params.enc = html->encoding;
        parse_params.fix_enc = true;
@@ -714,6 +737,11 @@ html_process_encoding_change(struct content *c,
 
        }
 
+       nerror = box_manager_create(html->document, &html->box_manager);
+       if (nerror != NSERROR_OK) {
+               return nerror;
+       }
+
        source_data = content__get_source_data(c, &source_size);
 
        /* Reprocess all the data.  This is safe because
@@ -1248,6 +1276,11 @@ static void html_destroy(struct content *c)
                html->document = NULL;
        }
 
+       if (html->box_manager != NULL) {
+               box_manager_destroy(html->box_manager);
+               html->box_manager = NULL;
+       }
+
        if (html->title != NULL) {
                dom_node_unref(html->title);
                html->title = NULL;
diff --git a/content/handlers/html/private.h b/content/handlers/html/private.h
index 56cd957d5..d31b0a885 100644
--- a/content/handlers/html/private.h
+++ b/content/handlers/html/private.h
@@ -31,6 +31,7 @@
 #include "content/handlers/css/utils.h"
 
 
+struct box_manager;
 struct gui_layout_table;
 struct scrollbar_msg_data;
 struct content_redraw_data;
@@ -130,6 +131,9 @@ typedef struct html_content {
        /* Title element node */
        dom_node *title;
 
+       /** Box tree manager */
+       struct box_manager *box_manager;
+
        /** A talloc context purely for the render box tree */
        int *bctx;
        /** A context pointer for the box conversion, NULL if no conversion


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=0b28c94f4f8d14c09fcd5396698c791c506286ad
commit 0b28c94f4f8d14c09fcd5396698c791c506286ad
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    Clean up redundant includes

diff --git a/desktop/print.c b/desktop/print.c
index e90e322ac..118e2e0b6 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -34,7 +34,6 @@
 #include "netsurf/plotters.h"
 #include "content/hlcache.h"
 #include "css/utils.h"
-#include "html/box.h"
 
 #include "desktop/print.h"
 #include "desktop/printer.h"
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index e4fadd274..62c8bf5c6 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -43,7 +43,6 @@
 #include "netsurf/content.h"
 #include "content/hlcache.h"
 #include "css/css.h"
-#include "html/box.h"
 #include "html/html_save.h"
 #include "html/html.h"
 
diff --git a/frontends/amiga/dt_sound.c b/frontends/amiga/dt_sound.c
index 16b4f7c62..11d5e79d5 100644
--- a/frontends/amiga/dt_sound.c
+++ b/frontends/amiga/dt_sound.c
@@ -35,7 +35,6 @@
 #include "utils/messages.h"
 #include "netsurf/plotters.h"
 #include "netsurf/content.h"
-#include "html/box.h"
 #include "content/llcache.h"
 #include "content/content_protected.h"
 #include "content/content_factory.h"


-----------------------------------------------------------------------


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to