diff options
-rw-r--r-- | binary/src/dactylIUtils.idl | 7 | ||||
-rw-r--r-- | binary/src/dactylUtils.cpp | 46 | ||||
-rw-r--r-- | common/content/buffer.js | 27 | ||||
-rw-r--r-- | common/modules/dom.jsm | 7 |
4 files changed, 84 insertions, 3 deletions
diff --git a/binary/src/dactylIUtils.idl b/binary/src/dactylIUtils.idl index 0a1aa9ae..36adf343 100644 --- a/binary/src/dactylIUtils.idl +++ b/binary/src/dactylIUtils.idl @@ -8,9 +8,12 @@ %} -[scriptable, uuid(29d1c61f-5959-42b3-8a13-4b473b2b47bf)] +[scriptable, uuid(d8ef4492-8f4a-4f5d-8f19-1d71f7f895ed)] interface dactylIUtils : nsISupports { + const PRUint32 DIRECTION_HORIZONTAL = 1 << 0; + const PRUint32 DIRECTION_VERTICAL = 1 << 1; + [implicit_jscontext] jsval createGlobal(); @@ -25,6 +28,8 @@ interface dactylIUtils : nsISupports [implicit_jscontext] jsval getGlobalForObject(in jsval object); + PRUint32 getScrollable(in nsIDOMElement element); + void loadSubScript (in wstring url /* [optional] in jsval context, */ /* [optional] in wstring charset */); diff --git a/binary/src/dactylUtils.cpp b/binary/src/dactylUtils.cpp index 86a4d46a..230a06d3 100644 --- a/binary/src/dactylUtils.cpp +++ b/binary/src/dactylUtils.cpp @@ -40,6 +40,23 @@ #include "jsdbgapi.h" #include "jsobj.h" +#include "nsStringAPI.h" + +/* + * Evil. Evil, evil, evil. + */ +#define MOZILLA_INTERNAL_API +# define nsAString_h___ +# define nsString_h___ +# define nsStringFwd_h___ +# define nsStringGlue_h__ +class nsAFlatCString; +typedef nsString nsSubstring; +# include "nsIScrollableFrame.h" +#undef MOZILLA_INTERNAL_API +#include "nsPresContext.h" +#include "nsQueryFrame.h" + #include "nsIContent.h" #include "nsIDOMXULElement.h" #include "nsIXULTemplateBuilder.h" @@ -49,7 +66,6 @@ #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" -#include "nsStringAPI.h" class autoDropPrincipals { @@ -322,4 +338,32 @@ dactylUtils::GetGlobalForObject(const jsval &aObject, return NS_OK; } +NS_IMETHODIMP +dactylUtils::GetScrollable(nsIDOMElement *aElement, PRUint32 *rval) +{ + nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); + + nsIFrame *frame = content->GetPrimaryFrame(); + nsIScrollableFrame *scrollFrame = do_QueryFrame(frame); + + *rval = 0; + if (scrollFrame) { + nsPresContext::ScrollbarStyles ss = scrollFrame->GetScrollbarStyles(); + PRUint32 scrollbarVisibility = scrollFrame->GetScrollbarVisibility(); + nsRect scrollRange = scrollFrame->GetScrollRange(); + + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN && + ((scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) || + scrollRange.width > 0)) + *rval |= dactylIUtils::DIRECTION_HORIZONTAL; + + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN && + ((scrollbarVisibility & nsIScrollableFrame::VERTICAL) || + scrollRange.height > 0)) + *rval |= dactylIUtils::DIRECTION_VERTICAL; + } + + return NS_OK; +} + /* vim:se sts=4 sw=4 et ft=cpp: */ diff --git a/common/content/buffer.js b/common/content/buffer.js index 00c96972..2a403ed8 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -784,9 +784,29 @@ var Buffer = Module("buffer", { function find(elem) { while (elem && !(elem instanceof Element) && elem.parentNode) elem = elem.parentNode; - for (; elem && elem.parentNode instanceof Element; elem = elem.parentNode) + for (; elem instanceof Element; elem = elem.parentNode) if (Buffer.isScrollable(elem, dir, horizontal)) break; + + if (!(elem instanceof Element)) + return { + __proto__: elem.documentElement || elem.ownerDocument.documentElement, + + win: elem.defaultView || elem.ownerDocument.defaultView, + + get clientWidth() this.win.innerWidth, + get clientHeight() this.win.innerHeight, + + get scrollWidth() this.win.scrollMaxX + this.win.innerWidth, + get scrollHeight() this.win.scrollMaxY + this.win.innerHeight, + + get scrollLeft() this.win.scrollX, + set scrollLeft(val) { this.win.scrollTo(val, this.win.scrollY) }, + + get scrollTop() this.win.scrollY, + set scrollTop(val) { this.win.scrollTo(this.win.scrollX, val) } + }; + return elem; } @@ -1263,6 +1283,9 @@ var Buffer = Module("buffer", { findScrollable: deprecated("buffer.findScrollable", function findScrollable() buffer.findScrollable.apply(buffer, arguments)), isScrollable: function isScrollable(elem, dir, horizontal) { + if (!DOM(elem).isScrollable(horizontal ? "horizontal" : "vertical")) + return false; + let pos = "scrollTop", size = "clientHeight", max = "scrollHeight", layoutSize = "offsetHeight", overflow = "overflowX", border1 = "borderTopWidth", border2 = "borderBottomWidth"; if (horizontal) @@ -1272,9 +1295,11 @@ var Buffer = Module("buffer", { let style = DOM(elem).style; let borderSize = Math.round(parseFloat(style[border1]) + parseFloat(style[border2])); let realSize = elem[size]; + // Stupid Gecko eccentricities. May fail for quirks mode documents. if (elem[size] + borderSize == elem[max] || elem[size] == 0) // Stupid, fallible heuristic. return false; + if (style[overflow] == "hidden") realSize += borderSize; return dir < 0 && elem[pos] > 0 || dir > 0 && elem[pos] + realSize < elem[max] || !dir && realSize < elem[max]; diff --git a/common/modules/dom.jsm b/common/modules/dom.jsm index ccb7e7ca..5a7a9a29 100644 --- a/common/modules/dom.jsm +++ b/common/modules/dom.jsm @@ -691,6 +691,9 @@ var DOM = Class("DOM", { createContents: function createContents() this.each(DOM.createContents, this), + isScrollable: function isScrollable(direction) + this.length && DOM.isScrollable(this[0], direction), + getSet: function getSet(args, get, set) { if (!args.length) return this[0] && get.call(this, this[0]); @@ -1246,6 +1249,10 @@ var DOM = Class("DOM", { createContents: Class.Memoize(function () services.has("dactyl") && services.dactyl.createContents || function (elem) {}), + isScrollable: Class.Memoize(function () services.has("dactyl") && services.dactyl.getScrollable + ? function (elem, dir) services.dactyl.getScrollable(elem) & (dir ? services.dactyl["DIRECTION_" + dir.toUpperCase()] : ~0) + : function (elem, dir) true), + /** * The set of input element type attribute values that mark the element as * an editable field. |