зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1392460 - Add a couple prefs to expose DOM_DELTA_PIXEL rather than DOM_DELTA_LINES to the web. r=masayuki,smaug
And use them to disable DOM_DELTA_LINES on Nightly builds, to see the impact, since this is pretty hard to measure just with telemetry. Differential Revision: https://phabricator.services.mozilla.com/D95388
This commit is contained in:
Родитель
771dd03229
Коммит
0d187533ef
|
@ -18,6 +18,11 @@ WheelEvent::WheelEvent(EventTarget* aOwner, nsPresContext* aPresContext,
|
|||
? aWheelEvent
|
||||
: new WidgetWheelEvent(false, eVoidEvent, nullptr)),
|
||||
mAppUnitsPerDevPixel(0) {
|
||||
|
||||
if (StaticPrefs::dom_event_wheel_deltaMode_lines_always_disabled()) {
|
||||
mDeltaModeCheckingState = DeltaModeCheckingState::Unchecked;
|
||||
}
|
||||
|
||||
if (aWheelEvent) {
|
||||
mEventIsInternal = false;
|
||||
// If the delta mode is pixel, the WidgetWheelEvent's delta values are in
|
||||
|
@ -55,31 +60,55 @@ void WheelEvent::InitWheelEvent(
|
|||
wheelEvent->mDeltaMode = aDeltaMode;
|
||||
}
|
||||
|
||||
double WheelEvent::DeltaX() {
|
||||
if (!mAppUnitsPerDevPixel) {
|
||||
return mEvent->AsWheelEvent()->mDeltaX;
|
||||
double WheelEvent::ToWebExposedDelta(const WidgetWheelEvent& aWidgetEvent,
|
||||
double aDelta, CallerType aCallerType) {
|
||||
if (aCallerType != CallerType::System) {
|
||||
if (mDeltaModeCheckingState == DeltaModeCheckingState::Unknown) {
|
||||
mDeltaModeCheckingState = DeltaModeCheckingState::Unchecked;
|
||||
}
|
||||
if (mDeltaModeCheckingState == DeltaModeCheckingState::Unchecked &&
|
||||
aWidgetEvent.mDeltaMode == WheelEvent_Binding::DOM_DELTA_LINE &&
|
||||
StaticPrefs::dom_event_wheel_deltaMode_lines_disabled()) {
|
||||
// TODO(emilio, bug 1675949): Consider not using a fixed multiplier here?
|
||||
return aDelta *
|
||||
StaticPrefs::dom_event_wheel_deltaMode_lines_to_pixel_scale();
|
||||
}
|
||||
}
|
||||
return mEvent->AsWheelEvent()->mDeltaX * mAppUnitsPerDevPixel /
|
||||
AppUnitsPerCSSPixel();
|
||||
if (!mAppUnitsPerDevPixel) {
|
||||
return aDelta;
|
||||
}
|
||||
return aDelta * mAppUnitsPerDevPixel / AppUnitsPerCSSPixel();
|
||||
}
|
||||
|
||||
double WheelEvent::DeltaY() {
|
||||
if (!mAppUnitsPerDevPixel) {
|
||||
return mEvent->AsWheelEvent()->mDeltaY;
|
||||
}
|
||||
return mEvent->AsWheelEvent()->mDeltaY * mAppUnitsPerDevPixel /
|
||||
AppUnitsPerCSSPixel();
|
||||
double WheelEvent::DeltaX(CallerType aCallerType) {
|
||||
WidgetWheelEvent* ev = mEvent->AsWheelEvent();
|
||||
return ToWebExposedDelta(*ev, ev->mDeltaX, aCallerType);
|
||||
}
|
||||
|
||||
double WheelEvent::DeltaZ() {
|
||||
if (!mAppUnitsPerDevPixel) {
|
||||
return mEvent->AsWheelEvent()->mDeltaZ;
|
||||
}
|
||||
return mEvent->AsWheelEvent()->mDeltaZ * mAppUnitsPerDevPixel /
|
||||
AppUnitsPerCSSPixel();
|
||||
double WheelEvent::DeltaY(CallerType aCallerType) {
|
||||
WidgetWheelEvent* ev = mEvent->AsWheelEvent();
|
||||
return ToWebExposedDelta(*ev, ev->mDeltaY, aCallerType);
|
||||
}
|
||||
|
||||
uint32_t WheelEvent::DeltaMode() { return mEvent->AsWheelEvent()->mDeltaMode; }
|
||||
double WheelEvent::DeltaZ(CallerType aCallerType) {
|
||||
WidgetWheelEvent* ev = mEvent->AsWheelEvent();
|
||||
return ToWebExposedDelta(*ev, ev->mDeltaZ, aCallerType);
|
||||
}
|
||||
|
||||
uint32_t WheelEvent::DeltaMode(CallerType aCallerType) {
|
||||
uint32_t mode = mEvent->AsWheelEvent()->mDeltaMode;
|
||||
if (aCallerType != CallerType::System) {
|
||||
if (mDeltaModeCheckingState == DeltaModeCheckingState::Unknown) {
|
||||
mDeltaModeCheckingState = DeltaModeCheckingState::Checked;
|
||||
} else if (mDeltaModeCheckingState == DeltaModeCheckingState::Unchecked &&
|
||||
mode == WheelEvent_Binding::DOM_DELTA_LINE &&
|
||||
StaticPrefs::dom_event_wheel_deltaMode_lines_disabled()) {
|
||||
return WheelEvent_Binding::DOM_DELTA_PIXEL;
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
already_AddRefed<WheelEvent> WheelEvent::Constructor(
|
||||
const GlobalObject& aGlobal, const nsAString& aType,
|
||||
|
|
|
@ -33,10 +33,10 @@ class WheelEvent : public MouseEvent {
|
|||
// NOTE: DeltaX(), DeltaY() and DeltaZ() return CSS pixels when deltaMode is
|
||||
// DOM_DELTA_PIXEL. (The internal event's delta values are device pixels
|
||||
// if it's dispatched by widget)
|
||||
double DeltaX();
|
||||
double DeltaY();
|
||||
double DeltaZ();
|
||||
uint32_t DeltaMode();
|
||||
double DeltaX(CallerType);
|
||||
double DeltaY(CallerType);
|
||||
double DeltaZ(CallerType);
|
||||
uint32_t DeltaMode(CallerType);
|
||||
|
||||
void InitWheelEvent(const nsAString& aType, bool aCanBubble, bool aCancelable,
|
||||
nsGlobalWindowInner* aView, int32_t aDetail,
|
||||
|
@ -49,8 +49,26 @@ class WheelEvent : public MouseEvent {
|
|||
protected:
|
||||
~WheelEvent() = default;
|
||||
|
||||
double ToWebExposedDelta(const WidgetWheelEvent&, double aDelta, CallerType);
|
||||
|
||||
private:
|
||||
int32_t mAppUnitsPerDevPixel;
|
||||
enum class DeltaModeCheckingState : uint8_t {
|
||||
// Neither deltaMode nor the delta values have been accessed.
|
||||
Unknown,
|
||||
// The delta values have been accessed, without checking deltaMode first.
|
||||
Unchecked,
|
||||
// The deltaMode has been checked.
|
||||
Checked,
|
||||
};
|
||||
|
||||
// For compat reasons, we might expose a DOM_DELTA_LINE event as
|
||||
// DOM_DELTA_PIXEL instead. Whether we do that depends on whether the event
|
||||
// has been asked for the deltaMode before the deltas. If it has, we assume
|
||||
// that the page will correctly handle DOM_DELTA_LINE. This variable tracks
|
||||
// that state. See bug 1392460.
|
||||
DeltaModeCheckingState mDeltaModeCheckingState =
|
||||
DeltaModeCheckingState::Unknown;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -2494,6 +2494,26 @@ function* testContinuousTrustedEvents()
|
|||
horizontal: { expected: true, preventDefault: true, detail: gHorizontalLine },
|
||||
vertical: { expected: true, preventDefault: true, detail: gLineHeight } },
|
||||
},
|
||||
{ description: "modifier key tests without content checking mode (alt, line)",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 1.0, isMomentum: false,
|
||||
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1, isNoLineOrPageDelta: false,
|
||||
isCustomizedByPrefs: false,
|
||||
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
|
||||
wheel: {
|
||||
expected: true, preventDefault: false,
|
||||
skipDeltaModeCheck: true,
|
||||
deltaX: SpecialPowers.getIntPref("dom.event.wheel-deltaMode-lines-to-pixel-scale"),
|
||||
deltaY: SpecialPowers.getIntPref("dom.event.wheel-deltaMode-lines-to-pixel-scale"),
|
||||
deltaZ: SpecialPowers.getIntPref("dom.event.wheel-deltaMode-lines-to-pixel-scale"),
|
||||
},
|
||||
DOMMouseScroll: {
|
||||
horizontal: { expected: true, preventDefault: false, detail: 1 },
|
||||
vertical: { expected: true, preventDefault: false, detail: 1 } },
|
||||
MozMousePixelScroll: {
|
||||
horizontal: { expected: true, preventDefault: true, detail: gHorizontalLine },
|
||||
vertical: { expected: true, preventDefault: true, detail: gLineHeight } },
|
||||
},
|
||||
{ description: "modifier key tests (alt, page)",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 1.0, isMomentum: false,
|
||||
|
@ -3058,14 +3078,24 @@ function* testContinuousTrustedEvents()
|
|||
|
||||
is(aEvent.target, gScrolledElement,
|
||||
description + "target was invalid");
|
||||
is(aEvent.deltaMode, currentWheelEventTest.event.deltaMode,
|
||||
description + "deltaMode was invalid");
|
||||
is(aEvent.deltaX, currentWheelEventTest.wheel.deltaX,
|
||||
description + "deltaX was invalid");
|
||||
is(aEvent.deltaY, currentWheelEventTest.wheel.deltaY,
|
||||
description + "deltaY was invalid");
|
||||
is(aEvent.deltaZ, currentWheelEventTest.wheel.deltaZ,
|
||||
description + "deltaZ was invalid");
|
||||
if (!currentWheelEventTest.wheel.skipDeltaModeCheck) {
|
||||
is(aEvent.deltaMode, currentWheelEventTest.event.deltaMode,
|
||||
description + "deltaMode was invalid");
|
||||
}
|
||||
is(SpecialPowers.wrap(aEvent).deltaMode, currentWheelEventTest.event.deltaMode,
|
||||
description + "deltaMode is raw value from privileged script");
|
||||
for (let prop of ["deltaX", "deltaY", "deltaZ"]) {
|
||||
is(aEvent[prop], currentWheelEventTest.wheel[prop],
|
||||
description + prop + " was invalid");
|
||||
if (currentWheelEventTest.wheel.skipDeltaModeCheck) {
|
||||
is(aEvent.deltaMode, WheelEvent.DOM_DELTA_PIXEL,
|
||||
description + "deltaMode should become pixels for line scrolling if unchecked by content")
|
||||
if (aEvent[prop] != 0) {
|
||||
isnot(aEvent[prop], SpecialPowers.wrap(aEvent)[prop],
|
||||
description + "should keep returning raw value for privileged script");
|
||||
}
|
||||
}
|
||||
}
|
||||
is(aEvent.shiftKey, currentWheelEventTest.event.shiftKey,
|
||||
description + "shiftKey was invalid");
|
||||
is(aEvent.ctrlKey, currentWheelEventTest.event.ctrlKey,
|
||||
|
@ -3225,6 +3255,12 @@ function* testBody()
|
|||
function runTests()
|
||||
{
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
// FIXME(emilio): This test is broken in HiDPI, unclear if
|
||||
// MozMousePixelScroll is not properly converting to CSS pixels, or
|
||||
// whether sendWheelAndWait expectes device rather than CSS pixels, or
|
||||
// something else.
|
||||
["layout.css.devPixelsPerPx", 1.0],
|
||||
|
||||
["mousewheel.transaction.timeout", 100000],
|
||||
["mousewheel.default.delta_multiplier_x", 100],
|
||||
["mousewheel.default.delta_multiplier_y", 100],
|
||||
|
|
|
@ -183,6 +183,8 @@ function* testDeltaMultiplierPrefs()
|
|||
deltaX: -gHorizontalLine, deltaY: -gLineHeight, deltaZ: -gLineHeight, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: -1.0, deltaY: -1.0, deltaZ: -1.0, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE, skipDeltaModeCheck: true,
|
||||
deltaX: -1.0, deltaY: -1.0, deltaZ: -1.0, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: -1.0, deltaY: -1.0, deltaZ: -1.0, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
];
|
||||
|
@ -222,9 +224,20 @@ function* testDeltaMultiplierPrefs()
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (currentEvent.skipDeltaModeCheck) {
|
||||
let linesToPixel = SpecialPowers.getIntPref("dom.event.wheel-deltaMode-lines-to-pixel-scale");
|
||||
expectedDeltaX *= linesToPixel;
|
||||
expectedDeltaY *= linesToPixel;
|
||||
expectedDeltaZ *= linesToPixel;
|
||||
} else {
|
||||
is(aEvent.deltaMode, currentEvent.deltaMode, description + "deltaMode (" + currentEvent.deltaMode + ") was invalid");
|
||||
}
|
||||
is(aEvent.deltaX, expectedDeltaX, description + "deltaX (" + currentEvent.deltaX + ") was invalid");
|
||||
is(aEvent.deltaY, expectedDeltaY, description + "deltaY (" + currentEvent.deltaY + ") was invalid");
|
||||
is(aEvent.deltaZ, expectedDeltaZ, description + "deltaZ (" + currentEvent.deltaZ + ") was invalid");
|
||||
if (currentEvent.skipDeltaModeCheck) {
|
||||
isnot(SpecialPowers.wrap(aEvent).deltaMode, aEvent.deltaMode, description + "deltaMode should be changed for content if unchecked");
|
||||
}
|
||||
|
||||
if (expectedAsyncHandlerCalls > 0 && --expectedAsyncHandlerCalls == 0) {
|
||||
setTimeout(continueTest, 0);
|
||||
|
@ -785,6 +798,12 @@ function continueTest()
|
|||
function runTest()
|
||||
{
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
// FIXME(emilio): This test is broken in HiDPI, unclear if
|
||||
// MozMousePixelScroll is not properly converting to CSS pixels, or
|
||||
// whether sendWheelAndWait expectes device rather than CSS pixels, or
|
||||
// something else.
|
||||
["layout.css.devPixelsPerPx", 1.0],
|
||||
|
||||
["mousewheel.default.delta_multiplier_x", 100],
|
||||
["mousewheel.default.delta_multiplier_y", 100],
|
||||
["mousewheel.default.delta_multiplier_z", 100],
|
||||
|
|
|
@ -19,11 +19,10 @@ interface WheelEvent : MouseEvent
|
|||
const unsigned long DOM_DELTA_LINE = 0x01;
|
||||
const unsigned long DOM_DELTA_PAGE = 0x02;
|
||||
|
||||
readonly attribute double deltaX;
|
||||
readonly attribute double deltaY;
|
||||
readonly attribute double deltaZ;
|
||||
readonly attribute unsigned long deltaMode;
|
||||
|
||||
[NeedsCallerType] readonly attribute double deltaX;
|
||||
[NeedsCallerType] readonly attribute double deltaY;
|
||||
[NeedsCallerType] readonly attribute double deltaZ;
|
||||
[NeedsCallerType] readonly attribute unsigned long deltaMode;
|
||||
};
|
||||
|
||||
dictionary WheelEventInit : MouseEventInit
|
||||
|
|
|
@ -1670,6 +1670,33 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether WheelEvent should return pixels instead of lines for
|
||||
# WheelEvent.deltaX/Y/Z, when deltaMode hasn't been checked.
|
||||
#
|
||||
# Other browsers don't use line deltas and websites forget to check for it, see
|
||||
# bug 1392460.
|
||||
- name: dom.event.wheel-deltaMode-lines.disabled
|
||||
type: bool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Mostly for debugging. Whether we should do the same as
|
||||
# dom.event.wheel-deltaMode-lines.disabled, but unconditionally rather than
|
||||
# only when deltaMode hasn't been checked.
|
||||
- name: dom.event.wheel-deltaMode-lines.always-disabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# When dom.event.wheel-deltaMode-lines.disabled is true, this is the lines to
|
||||
# pixels multiplier that gets used.
|
||||
#
|
||||
# The value here is taken from PIXELS_PER_LINE_SCALE from pdf.js.
|
||||
- name: dom.event.wheel-deltaMode-lines-to-pixel-scale
|
||||
type: uint32_t
|
||||
value: 30
|
||||
mirror: always
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
# Whether to disable treating ctrl click as right click
|
||||
- name: dom.event.treat_ctrl_click_as_right_click.disabled
|
||||
|
|
Загрузка…
Ссылка в новой задаче