`MouseEvent.offsetX` and `MouseEvent.offsetY` should return `pageX` and `pageY` values after dispatching
Categories
(Core :: DOM: Events, defect)
Tracking
()
People
(Reporter: reza.bakhshi1381r, Assigned: masayuki)
References
(Regression, )
Details
(Keywords: regression, webcompat:platform-bug, webcompat:site-report)
User Story
platform:windows,mac,linux,android impact:feature-broken configuration:general affects:all branch:release diagnosis-team:dom
Attachments
(4 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
Steps to reproduce:
https://fazayesh.spaceomid.com
This is the website that I develope myself, I'm using React-leaflet to display png images of NDVI value in a tooltip by mousemove event handler from ImageOverlay. I use Canvas API for getting pixel RGB data and a Map to give the color and return related NDVI value, the feature works correct in Chrome and Edge as I checked.
you can see an example code in stack overflow: https://stackoverflow.com/questions/77631436/how-to-read-pixel-values-of-an-imageoverlay-in-react-leaflet-by-mousemove-event
Actual results:
When I move the mouse over the image, it should open a tooltip and show a different value for each RGB pixel, but it only shows the default Map object string value.
Expected results:
It should read each pixel value and extract RGB and then give it to the Map object of predefined colors and return value to be displayed in a tooltip. please check the stack overflow link which I put in first text area.
React.js component:
import { useRef, useState } from "react"
import { ImageOverlay, SVGOverlay, Tooltip } from "react-leaflet"
import { useSelector } from "react-redux"
import { ndmiMap, ndviMap } from "./utils/statics"
export default function ImageEvents() {
const activeField = useSelector(store => store.userFarms.activeField)
const socketData = useSelector(store => store.socketCluster)
const selectedDay = useSelector(store => store.userFarms.selectedDay)
const imageRef = useRef()
const [tooltip, setTooltip] = useState(1)
function rgbToHex(rgb) {
const hex = rgb.replace(/[^\d,]/g, "").split(",")
const r = parseInt(hex[0], 10).toString(16).padStart(2, "0")
const g = parseInt(hex[1], 10).toString(16).padStart(2, "0")
const b = parseInt(hex[2], 10).toString(16).padStart(2, "0")
return `#${r}${g}${b}`
}
const onHover = event => {
const canvas = document.createElement("canvas")
canvas.style.display = "none"
const ctx = canvas.getContext("2d")
const image = imageRef.current._image
const width = image.width
const height = image.height
const x = event.originalEvent.offsetX
const y = event.originalEvent.offsetY
image.crossOrigin = "Anonymous" // Set the crossOrigin attribute of the image
canvas.width = width
canvas.height = height
ctx.drawImage(image, 0, 0, width, height)
const pixelData = ctx.getImageData(x, y, 1, 1).data
const hexColor = rgbToHex(`rgb(${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]})`)
socketData.imageIndicator === "ndvi"
? setTooltip(ndviValue => ndviMap.get(hexColor) ?? ndviValue)
: setTooltip(ndmiValue => ndmiMap.get(hexColor) ?? ndmiValue)
}
const debounce = (func, delay) => {
let timeoutId
return (...args) => {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
func(...args)
}, delay)
}
}
const debouncedOnHover = debounce(onHover, 10) // Adjust the debounce delay as needed
return (
<>
{socketData.data &&
activeField &&
activeField.farm_id &&
selectedDay &&
socketData.data[activeField.farm_id] &&
socketData.data[activeField.farm_id][selectedDay] &&
socketData.data[activeField.farm_id][selectedDay].base64_encode ? (
<ImageOverlay
url={socketData.data[activeField.farm_id][selectedDay].base64_encode}
crossOrigin={"anonymous"}
bounds={activeField.bbox}
key={activeField.bbox[0][0]}
ref={imageRef}
id={"image-ndvi"}
opacity={socketData.imageIndicator === "nolayer" ? 0 : 1}
interactive={true}
eventHandlers={{
mousemove: debouncedOnHover,
click: onHover,
}}
>
{(tooltip !== undefined || tooltip !== 0) && <Tooltip sticky>{tooltip}</Tooltip>}
</ImageOverlay>
) : activeField.bbox && socketData.imageIndicator !== "nolayer" ? (
<SVGOverlay
attributes={{
width: "40",
height: "40",
viewBox: "-30 -30 100 100",
}}
bounds={activeField.bbox}
>
<defs>
<linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a">
<stop stopColor="#D6AD60" stopOpacity="0" offset="0%" />
<stop stopColor="#D6AD60" stopOpacity=".631" offset="63.146%" />
<stop stopColor="#D6AD60" offset="100%" />
</linearGradient>
</defs>
<g fill="none" fillRule="evenodd">
<g transform="translate(1 1)">
<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke="url(#a)" strokeWidth="2">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="0.9s"
repeatCount="indefinite"
/>
</path>
<circle fill="#D6AD60" cx="36" cy="18" r="1">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="0.9s"
repeatCount="indefinite"
/>
</circle>
</g>
</g>
</SVGOverlay>
) : null}
</>
)
}
Map variable values:
export const ndviMap = new Map([
["#ffffff", "ابر"],
["#000000", "وارد محدوده رنگی شوید"],
["#ff0303", "0.01, بدون پوشش"],
["#ff0b05", "0.02, بدون پوشش"],
["#ff1308", "0.03, بدون پوشش"],
["#ff1b0b", "0.04, بدون پوشش"],
["#ff230d", "0.05, بدون پوشش"],
["#ff2b10", "0.06, بدون پوشش"],
["#ff3313", "0.07, بدون پوشش"],
["#ff3413", "0.07, بدون پوشش"],
["#ff3a15", "0.08, بدون پوشش"],
["#fe4a1a", "0.08, بدون پوشش"],
["#ff3212", "0.08, بدون پوشش"],
["#ff4318", "0.09, بدون پوشش"],
["#ff4b1b", "0.1, بدون پوشش"], // 0.1
["#ff531e", "0.11, بدون پوشش"],
["#fd5c20", "0.12, بدون پوشش"],
["#fc6722", "0.11, بدون پوشش"],
["#fc6522", "0.13, بدون پوشش"],
["#fb6e24", "0.14, بدون پوشش"],
["#f97726", "0.15, بدون پوشش"],
["#f88128", "0.16, بدون پوشش"],
["#f78a2a", "0.17, بدون پوشش"],
["#f5932c", "0.18, بدون پوشش"],
["#f49c2e", "0.19, بدون پوشش"],
["#f3a530", "0.2, تراکم پایین"], // 0.2
["#f0aa2f", "0.21, تراکم پایین"],
["#f2af33", "0.21, تراکم پایین"],
["#efb331", "0.21, تراکم پایین"],
["#eeb530", "0.22, تراکم پایین"],
["#eabc2e", "0.23, تراکم پایین"],
["#ebb92f", "0.23, تراکم پایین"],
["#e6c32b", "0.24, تراکم پایین"],
["#e9bd2d", "0.24, تراکم پایین"],
["#e2c929", "0.25, تراکم پایین"],
["#e2c829", "0.25, تراکم پایین"],
["#ded027", "0.26, تراکم پایین"],
["#e1ca29", "0.26, تراکم پایین"],
["#dfce28", "0.27, تراکم پایین"],
["#dad724", "0.27, تراکم پایین"],
["#d6dd22", "0.28, تراکم پایین"],
["#d2e41f", "0.29, تراکم پایین"],
["#ceeb1d", "0.3, تراکم متوسط"], // 0.3
["#cbf21b", "0.31, تراکم متوسط"],
["#c3ef1a", "0.32, تراکم متوسط"],
["#bced1a", "0.33, تراکم متوسط"],
["#b5eb19", "0.34, تراکم متوسط"],
["#ade819", "0.35, تراکم متوسط"],
["#a6e618", "0.36, تراکم متوسط"],
["#9fe418", "0.37, تراکم متوسط"],
["#97e117", "0.38, تراکم متوسط"],
["#90df17", "0.39, تراکم متوسط"],
["#89dd16", "0.4, تراکم متوسط"], // 0.4
["#82db16", "0.41, تراکم متوسط"],
["#7ad715", "0.42, تراکم متوسط"],
["#72d415", "0.43, تراکم متوسط"],
["#6ad114", "0.44, تراکم متوسط"],
["#63cd14", "0.45, تراکم متوسط"],
["#5bca13", "0.46, تراکم متوسط"],
["#53c713", "0.47, تراکم متوسط"],
["#4cc312", "0.48, تراکم متوسط"],
["#44c012", "0.49, تراکم متوسط"],
["#3cbd11", "0.5, تراکم بالا"], // 0.5
["#35ba11", "0.51, تراکم بالا"],
["#32b310", "0.52, تراکم بالا"],
["#2fad0f", "0.53, تراکم بالا"],
["#2ca70d", "0.54, تراکم بالا"],
["#29a10d", "0.55, تراکم بالا"],
["#279b0c", "0.56, تراکم بالا"],
["#24950b", "0.57, تراکم بالا"],
["#218f0a", "0.58, تراکم بالا"],
["#1e8909", "0.59, تراکم بالا"],
["#1b8308", "0.6, تراکم بالا"], // 0.6
["#45a10b", "0.61, تراکم بالا"],
["#409d0a", "0.62, تراکم بالا"],
["#3c990a", "0.63, تراکم بالا"],
["#379609", "0.64, تراکم بالا"],
["#339209", "0.65, تراکم بالا"],
["#2f8f09", "0.66, تراکم بالا"],
["#2a8b08", "0.67, تراکم بالا"],
["#268708", "0.68, تراکم بالا"],
["#218407", "0.69, تراکم بالا"],
["#1d8007", "0.7, تراکم بالا"], // 0.7
["#197d07", "0.71, تراکم بالا"],
["#177806", "0.72, تراکم بالا"],
["#157305", "0.73, تراکم بالا"],
["#136e04", "0.74, تراکم بالا"],
["#116904", "0.75, تراکم بالا"],
["#0f6503", "0.76, تراکم بالا"],
["#0d6002", "0.77, تراکم بالا"],
["#0b5b02", "0.78, تراکم بالا"],
["#095601", "0.79, تراکم بالا"],
["#075100", "0.8, تراکم بالا"], // 0.8
["#064d00", "0.81, تراکم بالا"],
["#054b00", "0.82, تراکم بالا"],
["#054a00", "0.83, تراکم بالا"],
["#054800", "0.84, تراکم بالا"],
["#054700", "0.85, تراکم بالا"],
["#054600", "0.86, تراکم بالا"],
["#054400", "0.87, تراکم بالا"],
["#054300", "0.88, تراکم بالا"],
["#054100", "0.89, تراکم بالا"],
["#054000", "0.9, تراکم بالا"], // 0.9
["#053f00", "0.91, تراکم بالا"],
["#053d00", "0.92, تراکم بالا"],
["#053c00", "0.93, تراکم بالا"],
["#053a00", "0.94, تراکم بالا"],
["#053900", "0.95, تراکم بالا"],
["#053800", "0.96, تراکم بالا"],
["#053600", "0.97, تراکم بالا"],
["#053500", "0.98, تراکم بالا"],
["#053300", "0.99, تراکم بالا"],
["#053200", "1.0, تراکم بالا"], // 1.0
])
export const ndmiMap = new Map([
["#ffffff", "ابر"],
["#b29f99", "0.00"],
["#b3a09b", "0.01"],
["#b4a19d", "0.02"],
["#b5a29f", "0.03"],
["#b6a4a1", "0.04"],
["#b8a5a3", "0.05"],
["#b9a6a5", "0.06"],
["#baa8a7", "0.07"],
["#bba9a9", "0.08"],
["#bcaaab", "0.09"],
["#beacad", "0.10"],
["#bfadae", "0.11"],
["#c1aeb0", "0.12"],
["#c2afb1", "0.13"],
["#c4b0b3", "0.14"],
["#c5b2b4", "0.15"],
["#c7b3b6", "0.16"],
["#c8b4b7", "0.17"],
["#cab5b9", "0.18"],
["#cbb6ba", "0.19"],
["#cdb8bc", "0.20"],
["#ceb8bd", "0.21"],
["#cfb9bf", "0.22"],
["#d0bac1", "0.23"],
["#d1bbc3", "0.24"],
["#d3bcc5", "0.25"],
["#d4bdc6", "0.26"],
["#d5bec8", "0.27"],
["#d6bfca", "0.28"],
["#d7c0cc", "0.29"],
["#d9c1ce", "0.30"],
["#d6bfcf", "0.31"],
["#d3bdd0", "0.32"],
["#d0bbd1", "0.33"],
["#cdb9d2", "0.34"],
["#cab7d3", "0.35"],
["#c7b5d4", "0.36"],
["#c4b3d5", "0.37"],
["#c1b1d6", "0.38"],
["#beafd7", "0.39"],
["#bcaed9", "0.40"],
["#b8abd9", "0.41"],
["#b4a9d9", "0.42"],
["#b1a7d9", "0.43"],
["#ada5d9", "0.44"],
["#aaa3d9", "0.45"],
["#a6a0d9", "0.46"],
["#a29ed9", "0.47"],
["#9f9cd9", "0.48"],
["#9b9ad9", "0.49"],
["#9898d9", "0.51"],
["#9495d9", "0.52"],
["#9192d9", "0.53"],
["#8d8fd9", "0.54"],
["#8a8cd9", "0.55"],
["#8789d9", "0.56"],
["#8386d9", "0.57"],
["#8083d9", "0.58"],
["#7c80d9", "0.59"],
["#797dd9", "0.60"],
["#767ada", "0.61"],
["#7277da", "0.62"],
["#6f75da", "0.63"],
["#6c72da", "0.64"],
["#6870db", "0.65"],
["#656edb", "0.66"],
["#626bdb", "0.67"],
["#5e69dc", "0.68"],
["#5b66dc", "0.69"],
["#5864dc", "0.70"],
["#5562dd", "0.71"],
["#515fdd", "0.72"],
["#4e5cdd", "0.73"],
["#4a5ade", "0.74"],
["#4757de", "0.75"],
["#4455df", "0.76"],
["#4052df", "0.77"],
["#3d4fdf", "0.78"],
["#394de0", "0.79"],
["#364ae0", "0.80"],
["#3348e1", "0.81"],
["#2f45e0", "0.82"],
["#2c42e0", "0.83"],
["#293fe0", "0.84"],
["#263de0", "0.85"],
["#233ae0", "0.86"],
["#2037e0", "0.87"],
["#1d35e0", "0.88"],
["#1a32e0", "0.89"],
["#172fe0", "0.90"],
["#142de0", "0.91"],
["#142be0", "0.92"],
["#142ae0", "0.93"],
["#1429e0", "0.94"],
["#1428e0", "0.95"],
["#1427e0", "0.96"],
["#1426e0", "0.97"],
["#1425e0", "0.98"],
["#1424e0", "0.99"],
["#1423e0", "1"],
])
Comment 3•1 year ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::Graphics: Canvas2D' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Updated•1 year ago
|
Comment 5•1 year ago
|
||
Is it possible to get a standalone test case that shows the problem?
(In reply to Jeff Muizelaar [:jrmuizel] from comment #5)
Is it possible to get a standalone test case that shows the problem?
Here is a standalone test case to view the error on FireFox, You can fork the repo and run it on your desktop.
Github rep: Link
Comment 7•1 year ago
|
||
I can reproduce it with that test case. It looks like problem might be that offsetX and offsetY are always 0
There are two warnings in the console, which indicate:
- MouseEvent.mozPressure is deprecated. Use PointerEvent.pressure instead. (Util.js:15:3)
- MouseEvent.mozInputSource is deprecated. Use PointerEvent.pointerType instead. (Util.js:15:3)
Comment 9•1 year ago
|
||
Tom, is this related to the TikTok captcha thing?
Comment 10•1 year ago
|
||
https://bugzilla.mozilla.org/show_bug.cgi?id=505521 is a candidate bug here.
Updated•1 year ago
|
Comment 11•1 year ago
|
||
@jrmuizel: What do you want to do here? Sounds like this isn't GFX then?
Updated•1 year ago
|
Comment 12•1 year ago
|
||
The component has been changed since the backlog priority was decided, so we're resetting it.
For more information, please visit BugBot documentation.
Comment 13•1 year ago
|
||
Masayuki, please help out investigating this issue. Thank you.
| Assignee | ||
Comment 14•1 year ago
|
||
Currently, Event::mPresContext is cleared after the propagation.
https://searchfox.org/mozilla-central/rev/2493c256dbff4e3c7e51a7fc61115df887b87e9e/dom/events/Event.cpp#574
However, MouseEvent::OffsetPoint() calls Event::GetOffsetCoords() with nullptr of mPresContext.
https://searchfox.org/mozilla-central/rev/2493c256dbff4e3c7e51a7fc61115df887b87e9e/dom/events/MouseEvent.cpp#403-405
And Event::GetOffsetCoords() returns 0 and 0 in the case.
https://searchfox.org/mozilla-central/rev/2493c256dbff4e3c7e51a7fc61115df887b87e9e/dom/events/Event.cpp#707-708
CSSOM defines that offsetX and offsetY should be pageX and pageY` values after dispatching.
www.w3.org/TR/cssom-view-1/#dom-mouseevent-offsetx
| Assignee | ||
Comment 15•1 year ago
|
||
Oops, I canceled a needinfo request for twisniewski, sorry.
Comment 16•1 year ago
|
||
This doesn't seem related to drag events so we can drop Tom's needinfo request
Updated•1 year ago
|
| Assignee | ||
Updated•1 year ago
|
| Assignee | ||
Updated•1 year ago
|
Comment 17•1 year ago
|
||
Set release status flags based on info from the regressing bug 1203404
| Assignee | ||
Comment 18•1 year ago
|
||
Hmm, but looks like that both Blink and WebKit computes offsetX and offsetY only one time and cache them for further calls. So, they may not return pageX and pageY values as the spec defines.
| Assignee | ||
Comment 19•1 year ago
|
||
(In reply to Jeff Muizelaar [:jrmuizel] from comment #16)
This doesn't seem related to drag events so we can drop Tom's needinfo request
Well, DragEvent inherits MouseEvent. So, if TikTok refers offsetX and offsetY of DragEvent after the event propagation, the issue may be caused by this bug.
Updated•1 year ago
|
| Assignee | ||
Comment 20•1 year ago
|
||
Currently, offsetX and offsetY are defined by CSSOM spec [1]. The spec
defines that when the event is not being dispatched, these values should be
same as pageX and pageY. However, we started computing the values with
the latest data since bug 1203404 for compatibility with the other browsers.
However, the test does not check the trusted event behavior. When the event
is a trusted event, Event::DuplicatePrivateData() clears
Event::mPresContext. Then, calling Event::GetOffsetCoords with specifying
mPresContext aborts to compute it [2]. Therefore, our mouse events return
0 for offsetX and offsetY after propagation.
Blink and WebKit caches offsetX and offsetY values when they are referred
first time [3][4]. Therefore, their values depend on when they are
referred. I don't think we should follow their tricky behavior immediately.
However, at least, we should return same computed result until the layout and
scroll position are not changed. Therefore, this patch makes MouseEvent
caches mPresContext with new WeakPtr (for avoiding the cycle collector
to run longer) and use it when calling Event::GetOffsetCoords.
Finally, this adds a WPT under uievents to check current behavior in the
simplest case (i.e., neither scroll position nor layout is not changed after
starting the propagation).
- https://drafts.csswg.org/cssom-view/#extensions-to-the-mouseevent-interface
- https://searchfox.org/mozilla-central/rev/2493c256dbff4e3c7e51a7fc61115df887b87e9e/dom/events/Event.cpp#707-708
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/events/mouse_event.cc;l=518;drc=0aa8c88324c762d0907de203da053c4545c4fd6b
- https://searchfox.org/wubkat/rev/d46c14cf9008c4385cf0ac7919561b278d047e85/Source/WebCore/dom/MouseRelatedEvent.cpp#220
Updated•1 year ago
|
Comment 21•1 year ago
|
||
Comment 23•1 year ago
|
||
Backed out for causing leaks @ nsGlobalWindowInner
- Backout link
- Push with failures
- Failure Log
- Failure line:
TEST-UNEXPECTED-FAIL | leakcheck large nsGlobalWindowInner | toolkit/components/passwordmgr/test/browser/browser.toml
| Assignee | ||
Comment 24•1 year ago
|
||
(In reply to amarc from comment #23)
Backed out for causing leaks @ nsGlobalWindowInner
- Backout link
- Push with failures
- Failure Log
- Failure line:
TEST-UNEXPECTED-FAIL | leakcheck large nsGlobalWindowInner | toolkit/components/passwordmgr/test/browser/browser.toml
Hmm, then, like the first patch, MouseEvent should store mOriginalPresContext as WeakPtr. Smaug, WDYT?
| Assignee | ||
Comment 26•1 year ago
|
||
Making MouseEvent keep grabbing mPresContext caused memory leak after
mochitest-browser-chrome. I think that we can make Event::mPresContext
as a WeakPtr<nsPresContext> because:
- While the event is being dispatched, it should be grabbed by
EventDispatcher::Dispatchor its callers. - Once it's gone,
OffsetPointcan returnPagePointinstead.
So, I think that this change should affects only to the offsetX and offsetY
values after dispatching, but it must be enough for them in the most cases.
Depends on D232589
| Assignee | ||
Updated•1 year ago
|
Comment 27•1 year ago
|
||
Comment 28•1 year ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/cfb7d95a6f12
https://hg.mozilla.org/mozilla-central/rev/32a3dce926f1
Comment 29•1 year ago
|
||
Masayuki, the changes here are causing two types of security issues as in the following logs:
- https://treeherder.mozilla.org/logviewer?job_id=488255943&repo=mozilla-central
- https://treeherder.mozilla.org/logviewer?job_id=488105612&repo=autoland&lineNumber=25380
Tracked in Bug 1939095 and Bug 1939056 (probably don't have access to them since they're security bugs).
Could you please have a look over those failures and try to fix them? Thank you.
| Assignee | ||
Comment 30•1 year ago
|
||
Hmm, unfortunately, I'm away until 6-Jan, could you back them out for now? And could you cc me to the security bugs?
| Assignee | ||
Comment 31•1 year ago
|
||
It seems that it's caused by a bug of nsBaseWidget. Anyway, it should not be worked on this kind of open bugs.
Comment 32•1 year ago
|
||
Here's the backout: https://hg.mozilla.org/integration/autoland/rev/f275e46eb1c21a09599eacc63dd8566976b6bbd7
It will be merged to central later on.
Unfortunately, I'm not cc'ed on those bugs but maybe Donal can do that when he's around.
Updated•1 year ago
|
Comment 34•1 year ago
|
||
Backout merged to central: https://hg.mozilla.org/mozilla-central/rev/f275e46eb1c2
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 35•1 year ago
|
||
Comment 36•1 year ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/518ebab9baba
https://hg.mozilla.org/mozilla-central/rev/5393e3f76959
Comment 37•1 year ago
|
||
Since nightly and release are affected, beta will likely be affected too.
For more information, please visit BugBot documentation.
| Assignee | ||
Comment 39•1 year ago
|
||
This is not a recent regression, so, let's just ride the train. And this changes the behavior and changing the cycle collection, so perhaps, we should not uplift this to ESR too.
Updated•1 year ago
|
| Assignee | ||
Updated•1 year ago
|
Description
•