Unable to interact with elements who have large transform / translate values

RESOLVED FIXED in Firefox 45

Status

()

Core
Graphics: Layers
RESOLVED FIXED
2 years ago
2 years ago

People

(Reporter: Langdon Oliver, Assigned: mattwoodrow)

Tracking

({regression})

33 Branch
mozilla45
regression
Points:
---

Firefox Tracking Flags

(firefox41- wontfix, firefox42- wontfix, firefox43 wontfix, firefox44 affected, firefox45 fixed, firefox-esr38 wontfix)

Details

(Whiteboard: [gfx-noted])

Attachments

(1 attachment)

(Reporter)

Description

2 years ago
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36

Steps to reproduce:

Using large transform+translate values in SVG or CSS make elements non-interactive:

http://jsfiddle.net/langdonx/xvpachv9/2/

In case you're wondering why someone would do this -- I'm using D3js to position a flag element based on time.  The goal was to have the flag pole disappear off the screen, but to anchor the flag itself on the right edge.  If the user goes way back in time to where the translate value is large, the element becomes non-interactive.

I can obviously get around this with code (hide the pole, set the translate value to container width - element width), but this approach works in every other browser.


Actual results:

Sometimes, depending on where the flag is positioned, you cannot click on it (or see any hover effects).  Visually it's there, but as far as interaction goes, it's as if it's not there.


Expected results:

The element should be clickable and your cursor should change when you hover it.

Comment 1

2 years ago
Regression window;
https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=93b66a3f8e7d&tochange=15b924cf6eab

Regressed by:
15b924cf6eab	Matt Woodrow — Bug 1031948 - Cull points that have w <= 0 when untransforming layer coordinates. r=bjacob
Blocks: 1031948
Status: UNCONFIRMED → NEW
status-firefox41: --- → affected
status-firefox42: --- → affected
status-firefox43: --- → affected
status-firefox44: --- → affected
status-firefox-esr38: --- → affected
Component: Untriaged → Graphics: Layers
Ever confirmed: true
Keywords: regression
Product: Firefox → Core
Version: 41 Branch → 33 Branch
Matt, this was introduced with a patch you landed. Can you please look in to this?
tracking-firefox41: --- → ?
Flags: needinfo?(matt)
Whiteboard: [gfx-noted]

Comment 3

2 years ago
[Tracking Requested - why for this release]: Nom'ing for tracking for 42 and 43 as it seems to be a regression. While this is a valid issue, I do not think we will be fixing this in 41.
status-firefox41: affected → wontfix
tracking-firefox41: ? → -
tracking-firefox42: --- → ?
tracking-firefox43: --- → ?

Comment 4

2 years ago
Wrong Matt on the ticket - I'm Matt Woodward not Matt Woodrow. Trying to add the right Matt.
Flags: needinfo?(matt.woodrow)
We shipped this regression a while ago. We are going to build 42 rc1 today => wontfix
(ditto for esr38 as it doesn't match our uplift criteria). However, happy to take a patch to 43 (in aurora currently).
status-firefox42: affected → wontfix
status-firefox-esr38: affected → wontfix
tracking-firefox42: ? → -
tracking-firefox43: ? → +
Not the type of thing we'd let skip the trains.
status-firefox43: affected → wontfix
tracking-firefox43: + → ---
(Assignee)

Updated

2 years ago
Flags: needinfo?(matt)
(Assignee)

Comment 7

2 years ago
This is an issue with using single precision matrices, I believe Kip was looking into some other bugs of this nature.

When we get into Matrix4x4::ProjectRectBounds I see these values:

(lldb) p aRect
(mozilla::gfx::Rect) $270 = {
  mozilla::gfx::BaseRect<float, mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::SizeTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::MarginTyped<mozilla::gfx::UnknownUnits, float> > = (x = 659, y = 100, width = 0.0333333351, height = 0.0333333351)
}
(lldb) p aClip
(mozilla::gfx::Rect) $271 = {
  mozilla::gfx::BaseRect<float, mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::SizeTyped<mozilla::gfx::UnknownUnits, float>, mozilla::gfx::MarginTyped<mozilla::gfx::UnknownUnits, float> > = (x = -1048718, y = 0, width = 1048720, height = 240)
}
(lldb) p *this
(mozilla::gfx::Matrix4x4) $272 = (_11 = 1, _12 = 0, _13 = 0, _14 = 0, _21 = 0, _22 = 1, _23 = 0, _24 = 0, _31 = 0, _32 = 0, _33 = 1, _34 = 0, _41 = -1049318, _42 = 0, _43 = 0, _44 = 1)
(lldb) p points
(Point4D [4]) $273 = {
  [0] = {
    mozilla::gfx::BasePoint4D<float, mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x = -1048659, y = 100, z = 0, w = 1)
  }
  [1] = {
    mozilla::gfx::BasePoint4D<float, mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x = -1048659, y = 100, z = 0, w = 1)
  }
  [2] = {
    mozilla::gfx::BasePoint4D<float, mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x = -1048659, y = 100.033333, z = 0, w = 1)
  }
  [3] = {
    mozilla::gfx::BasePoint4D<float, mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x = -1048659, y = 100.033333, z = 0, w = 1)
  }
}
(lldb) p 659 + 1049318
(int) $274 = 1049977
(lldb) p 659.033333 + 1049318
(double) $275 = 1049977.033333
(lldb) p (float)659.033333 + 1049318
(float) $276 = 1049977

Using single precision points 0 and 1 (TopLeft and TopRight) end up with the same value, so we compute an empty rect and don't build display items for hit testing. This is specific to hit testing since the input rect is 1x1 (app units) in that case, instead of the window size.
Flags: needinfo?(matt.woodrow) → needinfo?(kgilbert)
Indeed, this does appear to be a precision issue.

Perhaps this could be fixed by changing some Point4D's to PointDouble4D's?

Matrix4x4::ProjectRectBounds is a template now, which can perform the transforms with double precision even if the matrix is composed of single precision values.

Alternately, perhaps intermediate transformations could be done as integers somewhere in the call stack?

(In reply to Matt Woodrow (:mattwoodrow) from comment #7)
> This is an issue with using single precision matrices, I believe Kip was
> looking into some other bugs of this nature.
> 
> When we get into Matrix4x4::ProjectRectBounds I see these values:
> 
> (lldb) p aRect
> (mozilla::gfx::Rect) $270 = {
>   mozilla::gfx::BaseRect<float,
> mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::SizeTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::MarginTyped<mozilla::gfx::UnknownUnits, float> > = (x = 659, y
> = 100, width = 0.0333333351, height = 0.0333333351)
> }
> (lldb) p aClip
> (mozilla::gfx::Rect) $271 = {
>   mozilla::gfx::BaseRect<float,
> mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::SizeTyped<mozilla::gfx::UnknownUnits, float>,
> mozilla::gfx::MarginTyped<mozilla::gfx::UnknownUnits, float> > = (x =
> -1048718, y = 0, width = 1048720, height = 240)
> }
> (lldb) p *this
> (mozilla::gfx::Matrix4x4) $272 = (_11 = 1, _12 = 0, _13 = 0, _14 = 0, _21 =
> 0, _22 = 1, _23 = 0, _24 = 0, _31 = 0, _32 = 0, _33 = 1, _34 = 0, _41 =
> -1049318, _42 = 0, _43 = 0, _44 = 1)
> (lldb) p points
> (Point4D [4]) $273 = {
>   [0] = {
>     mozilla::gfx::BasePoint4D<float,
> mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x =
> -1048659, y = 100, z = 0, w = 1)
>   }
>   [1] = {
>     mozilla::gfx::BasePoint4D<float,
> mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x =
> -1048659, y = 100, z = 0, w = 1)
>   }
>   [2] = {
>     mozilla::gfx::BasePoint4D<float,
> mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x =
> -1048659, y = 100.033333, z = 0, w = 1)
>   }
>   [3] = {
>     mozilla::gfx::BasePoint4D<float,
> mozilla::gfx::Point4DTyped<mozilla::gfx::UnknownUnits, float> > = (x =
> -1048659, y = 100.033333, z = 0, w = 1)
>   }
> }
> (lldb) p 659 + 1049318
> (int) $274 = 1049977
> (lldb) p 659.033333 + 1049318
> (double) $275 = 1049977.033333
> (lldb) p (float)659.033333 + 1049318
> (float) $276 = 1049977
> 
> Using single precision points 0 and 1 (TopLeft and TopRight) end up with the
> same value, so we compute an empty rect and don't build display items for
> hit testing. This is specific to hit testing since the input rect is 1x1
> (app units) in that case, instead of the window size.
Flags: needinfo?(kgilbert)
(Assignee)

Comment 9

2 years ago
Created attachment 8686997 [details] [diff] [review]
project-point-double

Good thinking, thanks Kip!
Assignee: nobody → matt.woodrow
Attachment #8686997 - Flags: review?(kgilbert)
Comment on attachment 8686997 [details] [diff] [review]
project-point-double

Review of attachment 8686997 [details] [diff] [review]:
-----------------------------------------------------------------

Looks good
Attachment #8686997 - Flags: review?(kgilbert) → review+

Comment 11

2 years ago
https://hg.mozilla.org/integration/mozilla-inbound/rev/c13d0478272f

Comment 12

2 years ago
bugherder
https://hg.mozilla.org/mozilla-central/rev/c13d0478272f
Status: NEW → RESOLVED
Last Resolved: 2 years ago
status-firefox45: --- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla45

Updated

2 years ago
Duplicate of this bug: 1253468
You need to log in before you can comment on or make changes to this bug.