mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWeb: Fix hit-testing by excluding CSS transform from clip rect check
Transforms are applied to both clip rectangle and position, so we need to remove the transform from clip rectangle before checking if position falls within the clip rectangle. In this change, the removal of transform is moved into `Paintable::clip_rect()` that is shared between hit-testing and painting. This change fixes hit-testing in Discord's multifactor authentication form.
This commit is contained in:
parent
309259aeb6
commit
9968c9f7a6
Notes:
sideshowbarker
2024-07-17 08:25:15 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/9968c9f7a6 Pull-request: https://github.com/SerenityOS/serenity/pull/23303
3 changed files with 45 additions and 8 deletions
|
@ -0,0 +1 @@
|
|||
<DIV id="box" >
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html><style type="text/css">
|
||||
body {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
position: relative;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
#translation {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 300px;
|
||||
transform: translate(0px, -50%);
|
||||
}
|
||||
|
||||
#box {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background-color: magenta;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#hidden-overflow {
|
||||
overflow: hidden;
|
||||
}
|
||||
</style><div id="translation"><div id="hidden-overflow"><div id="empty-wrapper"><div id="box">
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
printElement(internals.hitTest(100, 400).node);
|
||||
});
|
||||
</script>
|
|
@ -214,8 +214,17 @@ Optional<CSSPixelPoint> PaintableBox::enclosing_scroll_frame_offset() const
|
|||
|
||||
Optional<CSSPixelRect> PaintableBox::clip_rect() const
|
||||
{
|
||||
if (m_enclosing_clip_frame)
|
||||
return m_enclosing_clip_frame->rect();
|
||||
if (m_enclosing_clip_frame) {
|
||||
auto rect = m_enclosing_clip_frame->rect();
|
||||
// NOTE: Since the painting command executor applies a CSS transform and the clip rect is calculated
|
||||
// with this transform in account, we need to remove the transform from the clip rect.
|
||||
// Otherwise, the transform will be applied twice to the clip rect.
|
||||
// Similarly, for hit-testing, the transform must be removed from the clip rectangle since the position
|
||||
// includes the transform.
|
||||
auto combined_transform = compute_combined_css_transform();
|
||||
rect.translate_by(-combined_transform.translation().to_type<CSSPixels>());
|
||||
return rect;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -435,17 +444,12 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph
|
|||
|
||||
if (clip_rect().has_value()) {
|
||||
auto overflow_clip_rect = clip_rect().value();
|
||||
// NOTE: Since the painting command executor applies a CSS transform and the clip rect is calculated
|
||||
// with this transform in account, we need to remove the transform from the clip rect.
|
||||
// Otherwise, the transform will be applied twice to the clip rect.
|
||||
auto combined_transform = compute_combined_css_transform();
|
||||
overflow_clip_rect.translate_by(-combined_transform.translation().to_type<CSSPixels>());
|
||||
|
||||
m_clipping_overflow = true;
|
||||
context.recording_painter().save();
|
||||
context.recording_painter().add_clip_rect(context.enclosing_device_rect(overflow_clip_rect).to_type<int>());
|
||||
auto const& border_radii_clips = this->border_radii_clips();
|
||||
m_corner_clipper_ids.resize(border_radii_clips.size());
|
||||
auto combined_transform = compute_combined_css_transform();
|
||||
for (size_t corner_clip_index = 0; corner_clip_index < border_radii_clips.size(); ++corner_clip_index) {
|
||||
auto const& corner_clip = border_radii_clips[corner_clip_index];
|
||||
auto corners = corner_clip.radii.as_corners(context);
|
||||
|
|
Loading…
Reference in a new issue