LibWeb: Add hit testing API in internals object

Introduces `internals.hitTest(x, y)` that is going to allow us write
tests for hit testing :)
This commit is contained in:
Aliaksandr Kalenik 2023-08-08 22:44:52 +02:00 committed by Andreas Kling
parent 22a858a0cb
commit bf4e2f3e9c
Notes: sideshowbarker 2024-07-16 23:34:49 +09:00
7 changed files with 60 additions and 0 deletions

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu ante est. Integer ipsum sem, tincidunt quis felis quis, efficitur fringilla neque. Aliquam erat volutpat. Donec feugiat euismod sapien. Donec vel egestas arcu. Suspendisse luctus rhoncus mi quis elementum. Maecenas vel nisi maximus, viverra tellus quis, ultrices elit. Quisque congue velit quis lectus congue, ut consectetur nulla pharetra. Nullam euismod leo eget magna auctor, et bibendum urna tincidunt. Morbi molestie gravida ex ac consectetur. Duis pretium gravida augue eu sagittis. 193

View file

@ -0,0 +1,17 @@
<style>
* {
border: 1px solid black;
}
#box {
width: 100px;
height: 100px;
}
</style>
<div id="box"></div>
<script src="../include.js"></script>
<script>
test(() => {
println(internals.hitTest(50, 50).node === document.getElementById("box"));
});
</script>

View file

@ -0,0 +1,18 @@
<style>
* {
border: 1px solid black;
}
</style>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu ante est. Integer ipsum sem,
tincidunt quis felis quis, efficitur fringilla neque. Aliquam erat volutpat. Donec feugiat euismod
sapien. Donec vel egestas arcu. Suspendisse luctus rhoncus mi quis elementum. Maecenas vel nisi
maximus, viverra tellus quis, ultrices elit. Quisque congue velit quis lectus congue, ut consectetur
nulla pharetra. Nullam euismod leo eget magna auctor, et bibendum urna tincidunt. Morbi molestie
gravida ex ac consectetur. Duis pretium gravida augue eu sagittis.
<script src="../include.js"></script>
<script>
test(() => {
const hitTestingResult = internals.hitTest(50, 50);
println(hitTestingResult.indexInNode);
});
</script>

View file

@ -7,7 +7,11 @@
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/InternalsPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Internals/Internals.h>
#include <LibWeb/Painting/PaintableBox.h>
namespace Web::Internals {
@ -29,4 +33,21 @@ void Internals::gc()
vm().heap().collect_garbage();
}
JS::Object* Internals::hit_test(double x, double y)
{
auto* active_document = global_object().browsing_context()->top_level_browsing_context().active_document();
// NOTE: Force a layout update just before hit testing. This is because the current layout tree, which is required
// for stacking context traversal, might not exist if this call occurs between the tear_down_layout_tree()
// and update_layout() calls
active_document->update_layout();
auto result = active_document->paintable_box()->hit_test({ x, y }, Painting::HitTestType::Exact);
if (result.has_value()) {
auto hit_tеsting_result = JS::Object::create(realm(), nullptr);
hit_tеsting_result->define_direct_property("node", result->dom_node(), JS::default_attributes);
hit_tеsting_result->define_direct_property("indexInNode", JS::Value(result->index_in_node), JS::default_attributes);
return hit_tеsting_result;
}
return nullptr;
}
}

View file

@ -17,6 +17,7 @@ public:
virtual ~Internals() override;
void gc();
JS::Object* hit_test(double x, double y);
private:
explicit Internals(JS::Realm&);

View file

@ -1,5 +1,6 @@
[Exposed=Nobody] interface Internals {
undefined gc();
object hitTest(double x, double y);
};