'static' for a function means that the symbol shall not be made public
for the result of the current compilation unit. This does not make sense
in a header, especially not if it's a large function that is used in
more than one place and not that performance-sensitive.
Previously: Length (and all nearly all of its inline method
definitions) depended on the definition of class CalculatedStyleValue.
Meanwhile, CalculatedStyleValue (and nearly all of its namespaced
structs) depended on the definition of class Length.
Thus, a compilation unit that (for example) only contains
#include <Userland/Libraries/LibWeb/CSS/Length.h>
would fail to compile.
This patch resolves this issue by pushing the inline definition of
various Web::CSS::Length methods into a different file.
Previously: CSSImportRule::loaded_style_sheet() (and others) depend on
the definition of class CSSStyleSheet. Meanwhile,
CSSStyleSheet::template for_each_effective_style_rule (and others)
depend on the definition of class CSSImportRule.
This hasn't caused any problems so far because CSSStyleSheet.h happened
to be always included after CSSImportRule.h (in part due to alphabetical
ordering).
However, a compilation unit that (for example) only contains
#include <Userland/Libraries/LibWeb/CSSImportRule.h>
would fail to compile.
This patch resolves this issue by pushing the inline definition of
Web::CSS::CSSStyleSheet::for_each_effective_style_rule and
for_first_not_loaded_import_rule into a different file, and adding the
missing headers.
Per the spec, only a BlockContainer" can have line boxes, so let's not
clutter up every Layout::Box with line boxes.
This also allows us to establish an invariant that BFC and IFC always
operate on a Layout::BlockContainer.
Note that if BlockContainer has all block-level children, its line boxes
are not used for anything. They are only used in the all inline-level
children scenario.
List item markers will never have children, so let's mark them as such,
which now allows our layout system to skip over their "insides" and
going straight to positioning instead.
Some boxes cannot have children (most commonly replaced elements),
and so there is nothing meaningful inside them to layout.
We now use the can_have_children() flag to quickly skip over such boxes
instead of creating a formatting context and other pointless busywork.
There's a subtle difference here. A "block box" in the spec is a
block-level box, while a "block container" is a box whose children are
either all inline-level boxes in an IFC, or all block-level boxes
participating in a BFC.
Notably, an "inline-block" box is a "block container" but not a "block
box" since it is itself inline-level.
The CSS spec uses the name "block formatting context root" when talking
about a box that establishes a BFC. So let's call it BFC::root() in our
code as well, instead of the less specific BFC::context_box().
Until now, we've internally thought of the CSS "display" property as a
single-value property. In practice, "display" is a much more complex
property that comes in a number of configurations.
The most interesting one is the two-part format that describes the
outside and inside behavior of a box. Switching our own internal
representation towards this model will allow for much cleaner
abstractions around layout and the various formatting contexts.
Note that we don't *parse* two-part "display" yet, this is only about
changing the internal representation of the property.
Spec: https://drafts.csswg.org/css-display
Instead of doing layout synchronously whenever something changes,
we now use a basic event loop timer to defer and coalesce relayouts.
If you did something that requires a relayout of the page, make sure
to call Document::set_needs_layout() and it will get coalesced with all
the other layout updates.
There's lots of room for improvement here, but this already makes many
web pages significantly snappier. :^)
Also, note that this exposes a number of layout bugs where we have been
relying on multiple relayouts to calculate the correct dimensions for
things. Now that we only do a single layout in many cases, these kind of
problems are much more noticeable. That should also make them easier to
figure out and fix. :^)
Currently, `evaluate()` recalculates whether the MediaQuery matches or
not, and stores it in `m_matches`, which users can query using
`matches()`. This allows us to know when the match-state changes, which
is required to fire MediaQueryList's change event.
In cases where we know the Length is absolute, we know we don't need to
pass in a Layout::Node or FontMetrics etc, and yet we were required to
before. Splitting it means jumping through less hoops that we don't have
to. :^)
This method provides the needed information to evaluate media queries.
Every feature in Media Queries Level 4 is present, either as code or as
a FIXME: https://www.w3.org/TR/mediaqueries-4/#media-descriptor-table
There's a draft Level 5 which I have ignored for now.
Some are unimplemented for now since we do not have access to the
requested information. Some require StyleValue types that we do not yet
support. Many are hard-coded for now since we do not (and may never)
support monochrome or text-only displays for Browser.
If the specified value for these properties is "none", we end up storing
it as an "undefined" CSS::Length in the computed values.
We need to convert it back into "none" for getComputedStyle().
Auto margins are still not supported at all, but this is a good start
into supporting margins on flex items.
The way cross-before (top for row, left for column) is handled is very
naive.
Previously, if the parent of the container had a definite main size, it
would've been disregarded when calculating the main size of the
container if it had no definite size and neither min- nor max-main-size
constraints.
This patch fixes that behavior by additionally checking whether the main
size is not only not constrained but also infinite.
This was incorrectly calling DOM::Window::clear_timeout(). In practice,
these functions are interchangeable, but let's have things looking
correct regardless.
Instead of passing a function it is also possible to pass a string,
which is then evaluated as a classic script.
This means we now support the following example from the "timer
initialization steps", step 16 - except that it runs the timers in
reverse order, so the `log` result is `"TWO ONE "`.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps
var log = '';
function logger(s) { log += s + ' '; }
setTimeout({ toString: function () {
setTimeout("logger('ONE')", 100);
return "logger('TWO')";
} }, 100);
Since we expose these strings to web content via LengthStyleValue,
let's not have non-standard brackets in there to confuse anyone trying
to parse these values. :^)
This patch adds the "has a rendering opportunity" concept from the spec
to BrowsingContext and uses it to filter out contexts that are unable
to render right now when doing the event loop's rendering updates.
Note that we actually consider all contexts to have a rendering
opportunity at all times right now. Coming up with reasons to avoid
rendering is left as a FIXME. :^)