diff --git a/chrome/content/browser.js b/chrome/content/browser.js --- a/chrome/content/browser.js +++ b/chrome/content/browser.js @@ -1350,27 +1350,29 @@ var Browser = { let dummy = getComputedStyle(document.documentElement, "").width; } }; Browser.MainDragger = function MainDragger(browserView) { this.bv = browserView; this.draggedFrame = null; this.contentScrollbox = null; + this.scrolledElement = null; }; Browser.MainDragger.prototype = { isDraggable: function isDraggable(target, scroller) { return true; }, dragStart: function dragStart(clientX, clientY, target, scroller) { let [x, y] = Browser.transformClientToBrowser(clientX, clientY); let element = Browser.elementFromPoint(x, y); this.draggedFrame = null; this.contentScrollbox = null; + this.scrolledElement = 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) { @@ -1380,67 +1382,146 @@ Browser.MainDragger.prototype = { 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 < target.scrollHeight || cbr.width < target.scrollWidth))) { + this.scrolledElement = htmlElement; + this.scrolledElement.setAttribute("panning", "true"); 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.scrolledElement = xulElement.parentNode; + this.scrolledElement.setAttribute("panning", "true"); 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.scrolledElement = xulElement; + this.scrolledElement.setAttribute("panning", "true"); this.contentScrollbox = wrapper.scrollBoxObject || wrapper.boxObject.QueryInterface(Ci.nsIScrollBoxObject); return; } } } + this.showScrollBars(); + this.drawScrollBars(); if (element) this.draggedFrame = element.ownerDocument.defaultView; this.bv.pauseRendering(); // 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(); }, dragStop: function dragStop(dx, dy, scroller) { + if (this.scrolledElement) + this.scrolledElement.removeAttribute("panning"); + this.scrolledElement = null; this.draggedFrame = null; this.dragMove(Browser.snapSidebars(), 0, scroller); Browser.tryUnfloatToolbar(); + this.hideScrollBars(); + this.bv.resumeRendering(); // XXX shouldn't know about observer this.bv._idleServiceObserver.resume(); }, + kScrollBarWidth : 8, + + showScrollBars: function showScrollBars() { + let [vpWidth, vpHeight] = Browser._browserView.getViewportDimensions(); + let visibleRect = Browser._browserView.getVisibleRect(); + if (vpHeight > visibleRect.height) { + let scroll = document.getElementById("scrollbar-y"); + scroll.setAttribute("left", visibleRect.width - this.kScrollBarWidth - 4); + scroll.setAttribute("top", 0); + scroll.width = this.kScrollBarWidth; + scroll.height = visibleRect.height; + scroll.style.display = "block"; + } + if (vpWidth > visibleRect.width) { + let scroll = document.getElementById("scrollbar-x"); + scroll.setAttribute("left", 0); + scroll.setAttribute("top", visibleRect.height - this.kScrollBarWidth - 4); + scroll.width = visibleRect.width; + scroll.height = this.kScrollBarWidth; + scroll.style.display = "block"; + } + }, + + drawScrollBars: function drawScrollBars() { + let [vpWidth, vpHeight] = Browser._browserView.getViewportDimensions(); + let visibleRect = Browser._browserView.getVisibleRect(); + let scrollpoint = Browser.getScrollboxPosition(Browser.contentScrollboxScroller); + + // vertical scrollbar + if (vpHeight > visibleRect.height) { + let scroll = document.getElementById("scrollbar-y"); + let y = Math.round(scrollpoint.y * visibleRect.height / vpHeight); + let height = Math.round(visibleRect.height * visibleRect.height / vpHeight); + let width = this.kScrollBarWidth; + let ctx = scroll.getContext("2d"); + ctx.save(); + ctx.clearRect(0, 0, scroll.width, scroll.height); + ctx.fillStyle = "rgba(192, 192, 192, 0.75)"; + ctx.strokeStyle = "rgb(192, 192, 192)"; + ctx.strokeRect(0, y, width, height); + ctx.fillRect(0, y, width, height); + ctx.restore(); + } + + // horizontal scrollbar + if (vpWidth > visibleRect.width) { + let scroll = document.getElementById("scrollbar-x"); + x = Math.round(scrollpoint.x * visibleRect.width / vpWidth); + let width = Math.round(visibleRect.width * visibleRect.width / vpWidth); + let height = this.kScrollBarWidth; + let ctx = scroll.getContext("2d"); + ctx.save(); + ctx.clearRect(0, 0, scroll.width, scroll.height); + ctx.fillStyle = "rgba(192, 192, 192, 0.75)"; + ctx.strokeStyle = "rgb(192, 192, 192)"; + ctx.strokeRect(x, 0, width, height); + ctx.fillRect(x, 0, width, height); + ctx.restore(); + } + }, + + hideScrollBars: function hideScrollBars() { + document.getElementById("scrollbar-y").style.display = "none"; + document.getElementById("scrollbar-x").style.display = "none"; + }, + dragMove: function dragMove(dx, dy, scroller) { let elem = this.draggedFrame; let doffset = new Point(dx, dy); let render = false; this.bv.onBeforeVisibleMove(dx, dy); // First calculate any panning to take sidebars out of view @@ -1464,16 +1545,18 @@ Browser.MainDragger.prototype = { // Any leftover panning in doffset would bring controls into view. Add to sidebar // away panning for the total scroll offset. doffset.add(panOffset); Browser.tryFloatToolbar(doffset.x, 0); this._panScroller(Browser.controlsScrollboxScroller, doffset); this._panScroller(Browser.pageScrollboxScroller, doffset); + this.drawScrollBars(); + this.bv.onAfterVisibleMove(); if (render) this.bv.renderNow(); return !doffset.equals(dx, dy); }, diff --git a/chrome/content/browser.xul b/chrome/content/browser.xul --- a/chrome/content/browser.xul +++ b/chrome/content/browser.xul @@ -238,22 +238,22 @@ - + - +