blob: 572f546b5272199b56587e32c68d3333d3c69ade [file] [log] [blame]
// Contains helpers for calculating the dimensions for the various
// scrollbar parts.
// Helper to calculate track-width for non-custom standard
// scrollbars.
function calculateScrollbarThickness() {
var container = document.createElement("div");
container.style.width = "100px";
container.style.height = "100px";
container.style.position = "absolute";
container.style.visibility = "hidden";
container.style.overflow = "auto";
document.body.appendChild(container);
var widthBefore = container.clientWidth;
var longContent = document.createElement("div");
longContent.style.height = "1000px";
container.appendChild(longContent);
var widthAfter = container.clientWidth;
container.remove();
return widthBefore - widthAfter;
}
// Returns the width of a acrollbar button. On platforms where there are no
// scrollbar buttons (i.e. there are overlay scrollbars) returns 0.
function calculateScrollbarButtonWidth() {
if (internals.overlayScrollbarsEnabled)
return 0;
return calculateScrollbarThickness();
}
// Resets scroll offsets (only supports LTR for now).
function resetScrollOffset(scrollElement) {
if(scrollElement !== undefined) {
if(scrollElement.scrollLeft !== undefined) {
scrollElement.scrollLeft = 0;
}
if(scrollElement.scrollTop !== undefined) {
scrollElement.scrollTop = 0;
}
}
}
// Returns the expected CSS pixels delta of a percent-based scroll of a
// |scroller| element.
function getScrollbarButtonScrollDelta(scroller) {
if (!internals.runtimeFlags.percentBasedScrollingEnabled) {
return { x: SCROLLBAR_SCROLL_PIXELS, y: SCROLLBAR_SCROLL_PIXELS };
}
percentBasedDelta = (size) => {
return internals.runtimeFlags.percentBasedScrollingEnabled ? {
x: SCROLLBAR_SCROLL_PERCENTAGE * size.x,
y: SCROLLBAR_SCROLL_PERCENTAGE * size.y
} : {
x: Math.floor(SCROLLBAR_SCROLL_PERCENTAGE * size.x),
y: Math.floor(SCROLLBAR_SCROLL_PERCENTAGE * size.y)
}
};
clamp = (x, min, max) => Math.min(Math.max(x, min), max)
scroller_size = {x: scroller.clientWidth, y: scroller.clientHeight};
// All percent-based scroll clamping is made in physical pixels.
pixel_delta = percentBasedDelta(scaleCssToPhysicalPixels(scroller_size));
// Note that, window.inner* matches the size of the innerViewport, and won't
// match the VisualViewport's dimensions at the C++ code in the presence of
// UI elements that resize it (e.g. chromeOS OSKs).
// Note also that window.inner* isn't affected by pinch-zoom, so converting
// to Blink pixels is enough to get its actual size in Physical pixels.
max_delta = percentBasedDelta(scaleCssToBlinkPixels({
x: window.innerWidth, y: window.innerHeight}));
pixel_delta.x = Math.min(pixel_delta.x, max_delta.x);
pixel_delta.y = Math.min(pixel_delta.y, max_delta.y);
return scalePhysicalToCssPixels(pixel_delta);
}
// The percentage scrollbar arrows will scroll, if percent-based scrolling
// is enabled.
const SCROLLBAR_SCROLL_PERCENTAGE = 0.125;
// The number of pixels scrollbar arrows will scroll when percent-based
// scrolling is not enabled.
const SCROLLBAR_SCROLL_PIXELS = 40;
// TODO(arakeri): Add helpers for arrow widths.
/*
Getters for the center point in a scroller's scrollbar buttons (CSS visual
coordinates). An empty argument requests the point for the main frame's
scrollbars.
*/
function downArrow(scroller) {
assert_true(!internals.overlayScrollbarsEnabled);
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = TRACK_WIDTH;
const SCROLL_CORNER = TRACK_WIDTH;
if (typeof(scroller) == 'undefined') {
// The main frame's scrollbars don't scale with pinch zoom so there's no
// need to convert from client to visual.
return { x: window.innerWidth - BUTTON_WIDTH / 2,
y: window.innerHeight - SCROLL_CORNER - BUTTON_WIDTH / 2 }
}
const scrollerRect = scroller.getBoundingClientRect();
const down_arrow = {
x: scrollerRect.right - BUTTON_WIDTH / 2,
y: scrollerRect.bottom - SCROLL_CORNER - BUTTON_WIDTH / 2
};
return cssClientToCssVisual(down_arrow);
}
function upArrow(scroller) {
assert_true(!internals.overlayScrollbarsEnabled);
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = TRACK_WIDTH;
if (typeof(scroller) == 'undefined') {
// The main frame's scrollbars don't scale with pinch zoom so there's no
// need to convert from client to visual.
return { x: window.innerWidth - BUTTON_WIDTH / 2,
y: BUTTON_WIDTH / 2 }
}
const scrollerRect = scroller.getBoundingClientRect();
const up_arrow = {
x: scrollerRect.right - BUTTON_WIDTH / 2,
y: scrollerRect.top + BUTTON_WIDTH / 2
};
return cssClientToCssVisual(up_arrow);
}
function leftArrow(scroller) {
assert_true(!internals.overlayScrollbarsEnabled);
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = TRACK_WIDTH;
if (typeof(scroller) == 'undefined') {
// The main frame's scrollbars don't scale with pinch zoom so there's no
// need to convert from client to visual.
return { x: BUTTON_WIDTH / 2,
y: window.innerHeight - BUTTON_WIDTH / 2 }
}
const scrollerRect = scroller.getBoundingClientRect();
const left_arrow = {
x: scrollerRect.left + BUTTON_WIDTH / 2,
y: scrollerRect.bottom - BUTTON_WIDTH / 2
};
return cssClientToCssVisual(left_arrow);
}
function rightArrow(scroller) {
assert_true(!internals.overlayScrollbarsEnabled);
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = TRACK_WIDTH;
const SCROLL_CORNER = TRACK_WIDTH;
if (typeof(scroller) == 'undefined') {
// The main frame's scrollbars don't scale with pinch zoom so there's no
// need to convert from client to visual.
return { x: window.innerWidth - SCROLL_CORNER - BUTTON_WIDTH / 2,
y: window.innerHeight - BUTTON_WIDTH / 2 }
}
const scrollerRect = scroller.getBoundingClientRect();
const right_arrow = {
x: scrollerRect.right - SCROLL_CORNER - BUTTON_WIDTH / 2,
y: scrollerRect.bottom - BUTTON_WIDTH / 2
};
return cssClientToCssVisual(right_arrow);
}
// Returns a point that falls within the given scroller's vertical thumb part.
function verticalThumb(scroller) {
assert_equals(scroller.scrollTop, 0, "verticalThumb() requires scroller to have scrollTop of 0");
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = calculateScrollbarButtonWidth();
if (scroller === document.documentElement || typeof(scroller) == 'undefined') {
// HTML element is special, since scrollbars are not part of its client rect
// and page scale doesn't affect the scrollbars. Use window properties instead.
let x = window.innerWidth - TRACK_WIDTH / 2;
let y = BUTTON_WIDTH + 6;
return {x: x, y: y};
}
const scrollerRect = scroller.getBoundingClientRect();
const thumbPoint = { x : scrollerRect.right - TRACK_WIDTH / 2,
y : scrollerRect.top + BUTTON_WIDTH + 2 };
return cssClientToCssVisual(thumbPoint);
}
// Returns a point that falls within the given scroller's horizontal thumb part.
function horizontalThumb(scroller) {
assert_equals(scroller.scrollLeft, 0,
"horizontalThumb() requires scroller to have scrollLeft of 0");
const TRACK_WIDTH = calculateScrollbarThickness();
const BUTTON_WIDTH = calculateScrollbarButtonWidth();
if (scroller === document.documentElement || typeof(scroller) == 'undefined') {
// HTML element is special, since scrollbars are not part of its client rect
// and page scale doesn't affect the scrollbars. Use window properties instead.
let x = BUTTON_WIDTH + 6;
let y = window.innerHeight - TRACK_WIDTH / 2;
return {x: x, y: y};
}
const scrollerRect = scroller.getBoundingClientRect();
const thumbPoint = { x: scrollerRect.left + BUTTON_WIDTH + 2,
y: scrollerRect.bottom - TRACK_WIDTH / 2 };
return cssClientToCssVisual(thumbPoint);
}