Bug 1803118 - Snap mouse to <input type=range> tick marks r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D163780
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
|
||||
#include "Units.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
@@ -3276,7 +3277,8 @@ void HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent) {
|
||||
// have changed it by then).
|
||||
GetValue(mFocusedValue, CallerType::System);
|
||||
|
||||
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent));
|
||||
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent),
|
||||
SnapToTickMarks::Yes);
|
||||
}
|
||||
|
||||
void HTMLInputElement::FinishRangeThumbDrag(WidgetGUIEvent* aEvent) {
|
||||
@@ -3287,7 +3289,8 @@ void HTMLInputElement::FinishRangeThumbDrag(WidgetGUIEvent* aEvent) {
|
||||
}
|
||||
if (aEvent) {
|
||||
nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
|
||||
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent));
|
||||
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent),
|
||||
SnapToTickMarks::Yes);
|
||||
}
|
||||
mIsDraggingRange = false;
|
||||
FireChangeEventIfNeeded();
|
||||
@@ -3301,7 +3304,8 @@ void HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent) {
|
||||
PresShell::ReleaseCapturingContent();
|
||||
}
|
||||
if (aIsForUserEvent) {
|
||||
SetValueOfRangeForUserEvent(mRangeThumbDragStartValue);
|
||||
SetValueOfRangeForUserEvent(mRangeThumbDragStartValue,
|
||||
SnapToTickMarks::Yes);
|
||||
} else {
|
||||
// Don't dispatch an 'input' event - at least not using
|
||||
// DispatchTrustedEvent.
|
||||
@@ -3322,8 +3326,12 @@ void HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::SetValueOfRangeForUserEvent(Decimal aValue) {
|
||||
void HTMLInputElement::SetValueOfRangeForUserEvent(
|
||||
Decimal aValue, SnapToTickMarks aSnapToTickMarks) {
|
||||
MOZ_ASSERT(aValue.isFinite());
|
||||
if (aSnapToTickMarks == SnapToTickMarks::Yes) {
|
||||
MaybeSnapToTickMark(aValue);
|
||||
}
|
||||
|
||||
Decimal oldValue = GetValueAsDecimal();
|
||||
|
||||
@@ -4156,7 +4164,8 @@ void HTMLInputElement::PostHandleEventForRangeThumb(
|
||||
break;
|
||||
}
|
||||
SetValueOfRangeForUserEvent(
|
||||
rangeFrame->GetValueAtEventPoint(aVisitor.mEvent->AsInputEvent()));
|
||||
rangeFrame->GetValueAtEventPoint(aVisitor.mEvent->AsInputEvent()),
|
||||
SnapToTickMarks::Yes);
|
||||
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
||||
break;
|
||||
|
||||
@@ -4542,6 +4551,33 @@ void HTMLInputElement::HandleTypeChange(FormControlType aNewType,
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::MaybeSnapToTickMark(Decimal& aValue) {
|
||||
nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
|
||||
if (!rangeFrame) {
|
||||
return;
|
||||
}
|
||||
auto tickMark = rangeFrame->NearestTickMark(aValue);
|
||||
if (tickMark.isNaN()) {
|
||||
return;
|
||||
}
|
||||
auto rangeFrameSize = CSSPixel::FromAppUnits(rangeFrame->GetSize());
|
||||
CSSCoord rangeTrackLength;
|
||||
if (rangeFrame->IsHorizontal()) {
|
||||
rangeTrackLength = rangeFrameSize.width;
|
||||
} else {
|
||||
rangeTrackLength = rangeFrameSize.height;
|
||||
}
|
||||
auto stepBase = GetStepBase();
|
||||
auto distanceToTickMark =
|
||||
rangeTrackLength * float(rangeFrame->GetDoubleAsFractionOfRange(
|
||||
stepBase + (tickMark - aValue).abs()));
|
||||
const CSSCoord magnetEffectRange(
|
||||
StaticPrefs::dom_range_element_magnet_effect_threshold());
|
||||
if (distanceToTickMark <= magnetEffectRange) {
|
||||
aValue = tickMark;
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::SanitizeValue(nsAString& aValue,
|
||||
ForValueGetter aForGetter) {
|
||||
NS_ASSERTION(mDoneCreating, "The element creation should be finished!");
|
||||
|
||||
Reference in New Issue
Block a user