Bug 1802687 - Account for direction:rtl in vertical writing-mode <input type=range> controls. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D171375
This commit is contained in:
Jonathan Kew 2023-07-08 13:19:45 +00:00
Родитель b0c5c2a7bf
Коммит 7d604d33db
13 изменённых файлов: 91 добавлений и 19 удалений

Просмотреть файл

@ -434,8 +434,10 @@ Decimal nsRangeFrame::GetValueAtEventPoint(WidgetGUIEvent* aEvent) {
nscoord posOfPoint = mozilla::clamped(point.y, posAtStart, posAtEnd);
// For a vertical range, the top (posAtStart) is the highest value, so we
// subtract the fraction from 1.0 to get that polarity correct.
fraction = Decimal(1) -
Decimal(posOfPoint - posAtStart) / Decimal(traversableDistance);
fraction = Decimal(posOfPoint - posAtStart) / Decimal(traversableDistance);
if (IsUpwards()) {
fraction = Decimal(1) - fraction;
}
}
MOZ_ASSERT(fraction >= Decimal(0) && fraction <= Decimal(1));
@ -572,7 +574,11 @@ void nsRangeFrame::DoUpdateThumbPosition(nsIFrame* aThumbFrame,
nscoord traversableDistance =
rangeContentBoxSize.height - thumbSize.height;
newPosition.x += (rangeContentBoxSize.width - thumbSize.width) / 2;
newPosition.y += NSToCoordRound((1.0 - fraction) * traversableDistance);
if (IsUpwards()) {
newPosition.y += NSToCoordRound((1.0 - fraction) * traversableDistance);
} else {
newPosition.y += NSToCoordRound(fraction * traversableDistance);
}
}
}
aThumbFrame->SetPosition(newPosition);
@ -613,7 +619,9 @@ void nsRangeFrame::DoUpdateRangeProgressFrame(nsIFrame* aRangeProgressFrame,
} else {
nscoord progLength = NSToCoordRound(fraction * rangeContentBoxSize.height);
progRect.x += (rangeContentBoxSize.width - progSize.width) / 2;
progRect.y += rangeContentBoxSize.height - progLength;
if (IsUpwards()) {
progRect.y += rangeContentBoxSize.height - progLength;
}
progRect.height = progLength;
}
aRangeProgressFrame->SetRect(progRect);

Просмотреть файл

@ -115,6 +115,18 @@ class nsRangeFrame final : public nsContainerFrame,
return GetWritingMode().IsPhysicalRTL();
}
/**
* Returns true if the range progresses upwards (for vertical ranges in
* horizontal writing mode, or for bidi-RTL in vertical mode). Only
* relevant when IsHorizontal() is false.
*/
bool IsUpwards() const {
MOZ_ASSERT(!IsHorizontal());
mozilla::WritingMode wm = GetWritingMode();
return wm.GetBlockDir() == mozilla::WritingMode::eBlockTB ||
wm.GetInlineDir() == mozilla::WritingMode::eInlineBTT;
}
double GetMin() const;
double GetMax() const;
double GetValue() const;

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-lr" orient=inline max=100 value=70>
<input type=range style="writing-mode:vertical-lr;direction:rtl" orient=inline max=100 value=70>

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-lr" orient=vertical max=100 value=70>
<input type=range style="writing-mode:vertical-lr;direction:rtl" orient=vertical max=100 value=70>

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-lr" max=100 value=70>
<input type=range style="writing-mode:vertical-lr;direction:rtl" max=100 value=70>

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-rl" orient=inline max=100 value=70>
<input type=range style="writing-mode:vertical-rl;direction:rtl" orient=inline max=100 value=70>

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-rl" orient=vertical max=100 value=70>
<input type=range style="writing-mode:vertical-rl;direction:rtl" orient=vertical max=100 value=70>

Просмотреть файл

@ -1,3 +1,3 @@
<!DOCTYPE html>
<html>
<input type=range style="writing-mode:vertical-rl" max=100 value=70>
<input type=range style="writing-mode:vertical-rl;direction:rtl" max=100 value=70>

Просмотреть файл

@ -1,2 +0,0 @@
[range-input-appearance-native-vertical-rtl.optional.html]
expected: FAIL

Просмотреть файл

@ -1,2 +0,0 @@
[range-input-appearance-none-vertical-rtl.optional.html]
expected: FAIL

Просмотреть файл

@ -13,6 +13,7 @@
<style>
input[type=range] {
writing-mode: vertical-lr;
direction: rtl; /* so the range progresses upwards, not downwards */
}
</style>
<input type=range list=tickmarks min=-5 max=35>

Просмотреть файл

@ -0,0 +1,48 @@
<!doctype html>
<meta charset=utf-8>
<meta name=viewport content=width=device-width>
<title>Snap to a vertical slider's tick marks by clicking near them</title>
<link rel=help href="https://html.spec.whatwg.org/multipage/rendering.html#the-input-element-as-a-range-control">
<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1803118">
<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-actions.js></script>
<script src=/resources/testdriver-vendor.js></script>
<style>
input[type=range] {
writing-mode: vertical-lr;
}
</style>
<input type=range list=tickmarks min=-5 max=35>
<datalist id=tickmarks>
<option value=0></option>
<option value=3></option>
</datalist>
<script>
const range = document.querySelector("input[type=range]");
promise_test(async function snapToVerticalTickMarks() {
// Same assertions as range-snap-to-tick-marks-03, but without direction:rtl the range
// will progress downwards instead of upwards, so the coord calculation is reversed
// in the y-direction.
const assertions = [[-3, "-3"], [-2, "0"], [1, "0"], [2, "3"], [5, "3"], [6, "6"]];
const rect = range.getBoundingClientRect();
const padding = 10;
const top = rect.top + padding;
const height = rect.height - 2 * padding;
const actions = new test_driver.Actions();
const min = parseInt(range.min);
const max = parseInt(range.max);
for (const assertion of assertions) {
const moveTo = (top + height * (assertion[0] - min) / (max - min)) | 0;
const expected = assertion[1];
await actions
.pointerMove(rect.left, moveTo)
.pointerDown()
.pointerUp()
.send();
assert_equals(range.value, expected);
}
});
</script>

Просмотреть файл

@ -880,11 +880,18 @@ void Theme::PaintRange(nsIFrame* aFrame, PaintBackendData& aPaintData,
tickMarkSize = LayoutDeviceSize(tickMarkHeight, tickMarkWidth);
thumbRect.x = aRect.x + (aRect.width - thumbRect.width) / 2;
thumbRect.y =
aRect.y + (aRect.height - thumbRect.height) * (1.0 - progress);
float midPoint = thumbRect.Center().Y();
trackClipRect.SetBoxY(aRect.Y(), midPoint);
progressClipRect.SetBoxY(midPoint, aRect.YMost());
if (rangeFrame->IsUpwards()) {
thumbRect.y =
aRect.y + (aRect.height - thumbRect.height) * (1.0 - progress);
float midPoint = thumbRect.Center().Y();
trackClipRect.SetBoxY(aRect.Y(), midPoint);
progressClipRect.SetBoxY(midPoint, aRect.YMost());
} else {
thumbRect.y = aRect.y + (aRect.height - thumbRect.height) * progress;
float midPoint = thumbRect.Center().Y();
trackClipRect.SetBoxY(midPoint, aRect.YMost());
progressClipRect.SetBoxY(aRect.Y(), midPoint);
}
}
const CSSCoord borderWidth = 1.0f;