Bug 461843 - Show indication of where on the page you are when scrolling [r=mark.finkle]

This commit is contained in:
Vivien Nicolas 2010-04-01 17:00:27 -04:00
parent 54fe5bee42
commit 8d8f87e78e
5 changed files with 167 additions and 90 deletions

View File

@ -223,13 +223,12 @@ BrowserView.Util = {
},
initContainer: function initContainer(container, visibleRect) {
container.style.width = visibleRect.width + 'px';
container.style.height = visibleRect.height + 'px';
container.style.overflow = '-moz-hidden-unscrollable';
container.style.width = visibleRect.width + "px";
container.style.height = visibleRect.height + "px";
},
resizeContainerToViewport: function resizeContainerToViewport(container, viewportRect) {
container.style.width = viewportRect.width + 'px';
container.style.width = viewportRect.width + 'px';
container.style.height = viewportRect.height + 'px';
}
};

View File

@ -641,6 +641,10 @@ MouseModule.prototype = {
let dY = dragData.prevPanY - sY;
this._kinetic.addData(-dX, -dY);
this._kinetic.start();
// to avoid regressing performance (on device) by redrawing the
// indicators while kinetically scrolling just removed it
this._targetScrollInterface.element.removeAttribute("panning");
} else {
// now we're done, says our secret 3rd argument
this._dragger.dragStop(0, 0, this._targetScrollInterface);
@ -762,9 +766,12 @@ MouseModule.prototype = {
return sX.value > rect.width || sY.value > rect.height;
},
dragStart: function dragStart(cx, cy, target, scroller) {},
dragStart: function dragStart(cx, cy, target, scroller) {
scroller.element.setAttribute("panning", "true");
},
dragStop : function dragStop(dx, dy, scroller) {
scroller.element.removeAttribute("panning");
return this.dragMove(dx, dy, scroller);
},

View File

@ -1257,8 +1257,6 @@ var Browser = {
* @return Element at position, null if no active browser or no element found
*/
elementFromPoint: function elementFromPoint(x, y) {
//Util.dumpLn("*** elementFromPoint: page ", x, ",", y);
let browser = this._browserView.getBrowser();
if (!browser) return null;
@ -1330,73 +1328,84 @@ Browser.MainDragger = function MainDragger(browserView) {
Browser.MainDragger.prototype = {
isDraggable: function isDraggable(target, scroller) { return true; },
_getScrollableHTMLElement: function _getScrollableHTLMElement(element) {
let win = element.ownerDocument.defaultView;
while (!(element instanceof HTMLBodyElement)) {
let style= win.getComputedStyle(element, null);
let overflow = ["overflow", "overflow-x", "overflow-y"].map(style.getPropertyValue);
let rect = element.getBoundingClientRect();
let isAuto = (overflow.indexOf("auto") != -1 &&
(rect.height < element.scrollHeight || rect.width < element.scrollWidth));
let isScroll = (overflow.indexOf("scroll") != -1);
if (isScroll || isAuto)
return [element, this._createDivScrollBox(element)];
element = element.parentNode;
}
return [null, null];
},
_getScrollableXULElement: function _getScrollableXULElement(element) {
do {
if (element.localName == "treechildren")
return [element.parentNode, this._createTreeScrollBox(element.parentNode)];
let wrapper = element.wrappedJSObject;
try {
let scrollable = (wrapper.scrollBoxObject || wrapper.boxObject.QueryInterface(Ci.nsIScrollBoxObject));
if (scrollable)
return [element, scrollable];
}
catch(e) {}
element = element.parentNode;
} while (element instanceof XULElement);
return [null, null];
},
dragStart: function dragStart(clientX, clientY, target, scroller) {
this.draggedFrame = null;
this.scrolledElement = scroller.element;
this.contentScrollbox = null;
// Make sure pausing occurs before any early returns.
this.bv.pauseRendering();
let [x, y] = Browser.transformClientToBrowser(clientX, clientY);
let element = Browser.elementFromPoint(x, y);
if (!element)
return;
if (element instanceof HTMLElement && element.tagName != "HTML")
[this.scrolledElement, this.contentScrollbox] = this._getScrollableHTMLElement(element);
else if (element instanceof XULElement)
[this.scrolledElement, this.contentScrollbox] = this._getScrollableXULElement(element);
if (!this.contentScrollbox)
this.draggedFrame = element.ownerDocument.defaultView;
let isRootFrame = (element.ownerDocument == Browser.selectedBrowser.contentDocument);
if (isRootFrame && !this.scrolledElement)
this.scrolledElement = scroller.element;
else if (!isRootFrame || !this.scrolledElement)
this.scrolledElement = element.ownerDocument.documentElement
this.scrolledElement.setAttribute("panning", "true");
// XXX shouldn't know about observer
// adding pause in pauseRendering isn't so great, because tiles will hardly ever prefetch while
// loading state is going (and already, the idle timer is bigger during loading so it doesn't fit
// into the aggressive flag).
this.bv._idleServiceObserver.pause();
let [x, y] = Browser.transformClientToBrowser(clientX, clientY);
let element = Browser.elementFromPoint(x, y);
this.draggedFrame = null;
this.contentScrollbox = null;
// Check if we are in a scrollable HTML element
let htmlElement = element;
if (htmlElement && htmlElement instanceof HTMLElement) {
let win = htmlElement.ownerDocument.defaultView;
let oScroll;
let oAuto;
for (; htmlElement; htmlElement = htmlElement.parentNode) {
try {
let cs = win.getComputedStyle(htmlElement, null);
let overflow = cs.getPropertyValue("overflow");
let overflowX = cs.getPropertyValue("overflow-x");
let overflowY = cs.getPropertyValue("overflow-y");
let cbr = htmlElement.getBoundingClientRect();
oScroll = (overflow == "scroll") || (overflowX == "scroll") || (overflowY == "scroll");
oAuto = (overflow == "auto") || (overflowX == "auto") || (overflowY == "auto");
if (oScroll ||
(oAuto && (cbr.height < htmlElement.scrollHeight || cbr.width < htmlElement.scrollWidth))) {
this.contentScrollbox = this._createDivScrollBox(htmlElement);
return;
}
} catch(e) {}
}
}
// Check if we are in XUL land
let xulElement = element;
if (xulElement && xulElement instanceof XULElement) {
for (; xulElement; xulElement = xulElement.parentNode) {
if (xulElement.localName == "treechildren") {
this.contentScrollbox = this._createTreeScrollBox(xulElement.parentNode);
return;
}
let wrapper = xulElement.wrappedJSObject;
let scrollable = false;
try {
scrollable = (wrapper.scrollBoxObject != null) || (wrapper.boxObject.QueryInterface(Ci.nsIScrollBoxObject));
} catch(e) {}
if (scrollable) {
this.contentScrollbox = wrapper.scrollBoxObject || wrapper.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
return;
}
}
}
if (element)
this.draggedFrame = element.ownerDocument.defaultView;
},
dragStop: function dragStop(dx, dy, scroller) {
this.draggedFrame = null;
this.scrolledElement.removeAttribute("panning");
this.dragMove(Browser.snapSidebars(), 0, scroller);
Browser.tryUnfloatToolbar();
@ -1453,25 +1462,25 @@ Browser.MainDragger.prototype = {
*/
_createDivScrollBox: function(div) {
let sbo = {
getScrolledSize: function(width, height) {
width.value = div.scrollWidth;
height.value = div.scrollHeight;
},
getScrolledSize: function(width, height) {
width.value = div.scrollWidth;
height.value = div.scrollHeight;
},
getPosition: function(x, y) {
x.value = div.scrollLeft;
y.value = div.scrollTop;
},
getPosition: function(x, y) {
x.value = div.scrollLeft;
y.value = div.scrollTop;
},
scrollBy: function(dx, dy) {
div.scrollTop += dy;
div.scrollLeft += dx;
}
}
return sbo;
scrollBy: function(dx, dy) {
div.scrollTop += dy;
div.scrollLeft += dx;
}
}
return sbo;
},
/**
/**
* builds a minimal implementation of scrollBoxObject for trees
*/
_createTreeScrollBox: function(tree) {

View File

@ -246,9 +246,9 @@
<!-- Content viewport -->
<vbox class="window-width window-height">
<stack id="tile-stack" class="window-width" flex="1">
<scrollbox id="content-scrollbox" style="overflow: hidden;" class="window-width" flex="1">
<scrollbox id="content-scrollbox" class="window-width" flex="1">
<!-- Content viewport -->
<html:div id="tile-container" style="overflow: hidden;">
<html:div id="tile-container" style="overflow: hidden; z-index: 0 !important;">
<html:canvas id="content-overlay" style="display: none; position: absolute; z-index: 1000;">
</html:canvas>
</html:div>

View File

@ -50,29 +50,91 @@ html *|*:link:focus, *|*:visited:focus {
}
/* Style the scrollbars */
scrollbar {
-moz-appearance: none !important;
display: none !important;
:root > scrollbar {
display: none;
}
scrollbarbutton {
-moz-appearance: none !important;
display: none !important;
scrollbox {
overflow-x: auto;
overflow-y: auto;
}
thumb {
min-width: 10px !important;
div > scrollbar,
scrollbox > scrollbar {
-moz-appearance: none !important;
background-color: gray !important;
border: 1px solid gray !important;
-moz-border-radius: 4px !important;
display: -moz-box;
visibility: hidden;
position: relative;
background-color: transparent !important;
background-image: none !important;
z-index: 99999 !important;
}
div > scrollbar[orient="horizontal"],
div > scrollbar[orient="vertical"],
*[panning] > scrollbar[orient="horizontal"],
*[panning] > scrollbar[orient="vertical"] {
visibility: visible;
}
div > scrollbar[orient="vertical"],
scrollbox > scrollbar[orient="vertical"] {
min-width: 10px;
margin-left: -10px;
}
div > scrollbar[orient="vertical"] thumb,
scrollbox > scrollbar[orient="vertical"] thumb {
max-width: 8px !important;
}
div > scrollbar[orient="horizontal"],
scrollbox > scrollbar[orient="horizontal"] {
min-height: 10px;
margin-top: -10px;
}
div > scrollbar[orient="horizontal"] thumb,
scrollbox > scrollbar[orient="horizontal"] thumb {
max-height: 8px;
}
div > scrollbar > scrollbarbutton,
scrollbox > scrollbar > scrollbarbutton {
-moz-appearance: none;
visibility: hidden;
position: relative;
min-height: 10px;
min-width: 10px;
}
div > scrollbar > scrollbarbutton[sbattr="scrollbar-up-top"],
scrollbox > scrollbar > scrollbarbutton[sbattr="scrollbar-up-top"] {
min-height: 1px;
min-width: 1px;
}
div > scrollbar thumb,
scrollbox > scrollbar thumb {
background-color: rgba(192, 192, 192, 0.8) !important;
border: 1px solid rgb(192, 192, 192) !important;
-moz-border-top-colors: none !important;
-moz-border-bottom-colors: none !important;
-moz-border-right-colors: none !important;
-moz-border-left-colors: none !important;
}
select > scrollbar,
select > scrollbarbutton {
visibility: hidden;
}
select:not([size]) > scrollbar,
select[size="1"] > scrollbar,
select:not([size]) scrollbarbutton,
select[size="1"] scrollbarbutton {
display: block !important;
position: static;
visibility: visible !important;
}
/* Override inverse OS themes */