Bug 489127 - nodesFromRect required for better usability on mobile devices (part 4) [r=roc]

This commit is contained in:
Felipe Gomes 2010-04-07 20:31:26 -04:00
Родитель 69d7a7be69
Коммит 4d0643de3d
5 изменённых файлов: 144 добавлений и 3 удалений

Просмотреть файл

@ -115,8 +115,8 @@ class Link;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x5a428059, 0x4f29, 0x4d7c, \
{ 0x93, 0xae, 0x7c, 0x68, 0xd6, 0x5a, 0x86, 0x45 } }
{ 0x3e162645, 0x4827, 0x4600, \
{ 0x9c, 0xaa, 0xe8, 0xdd, 0xcb, 0x05, 0xfd, 0x85 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -990,6 +990,13 @@ public:
PRBool aFlushLayout,
nsIDOMElement** aReturn) = 0;
virtual nsresult NodesFromRectHelper(float aX, float aY,
float aTopSize, float aRightSize,
float aBottomSize, float aLeftSize,
PRBool aIgnoreRootScrollFrame,
PRBool aFlushLayout,
nsIDOMNodeList** aReturn) = 0;
/**
* See FlushSkinBindings on nsBindingManager
*/

Просмотреть файл

@ -2690,6 +2690,94 @@ nsDocument::ElementFromPointHelper(float aX, float aY,
return NS_OK;
}
nsresult
nsDocument::NodesFromRectHelper(float aX, float aY,
float aTopSize, float aRightSize,
float aBottomSize, float aLeftSize,
PRBool aIgnoreRootScrollFrame,
PRBool aFlushLayout,
nsIDOMNodeList** aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
nsBaseContentList* elements = new nsBaseContentList();
NS_ADDREF(elements);
*aReturn = elements;
// Following the same behavior of elementFromPoint,
// we don't return anything if either coord is negative
if (!aIgnoreRootScrollFrame && (aX < 0 || aY < 0))
return NS_OK;
nscoord x = nsPresContext::CSSPixelsToAppUnits(aX - aLeftSize);
nscoord y = nsPresContext::CSSPixelsToAppUnits(aY - aTopSize);
nscoord w = nsPresContext::CSSPixelsToAppUnits(aLeftSize + aRightSize) + 1;
nscoord h = nsPresContext::CSSPixelsToAppUnits(aTopSize + aBottomSize) + 1;
nsRect rect(x, y, w, h);
// Make sure the layout information we get is up-to-date, and
// ensure we get a root frame (for everything but XUL)
if (aFlushLayout) {
FlushPendingNotifications(Flush_Layout);
}
nsIPresShell *ps = GetPrimaryShell();
NS_ENSURE_STATE(ps);
nsIFrame *rootFrame = ps->GetRootFrame();
// XUL docs, unlike HTML, have no frame tree until everything's done loading
if (!rootFrame)
return NS_OK; // return nothing to premature XUL callers as a reminder to wait
nsTArray<nsIFrame*> outFrames;
nsLayoutUtils::GetFramesForArea(rootFrame, rect, outFrames,
PR_TRUE, aIgnoreRootScrollFrame);
PRInt32 length = outFrames.Length();
if (!length)
return NS_OK;
// Used to filter out repeated elements in sequence.
nsIContent* lastAdded = nsnull;
for (PRInt32 i = 0; i < length; i++) {
nsIContent* ptContent = outFrames.ElementAt(i)->GetContent();
NS_ENSURE_STATE(ptContent);
// If the content is in a subdocument, try to get the element from |this| doc
nsIDocument *currentDoc = ptContent->GetCurrentDoc();
if (currentDoc && (currentDoc != this)) {
// XXX felipe: I can't get this type right without the intermediate vars
nsCOMPtr<nsIDOMElement> x = CheckAncestryAndGetFrame(currentDoc);
nsCOMPtr<nsIContent> elementDoc = do_QueryInterface(x);
if (elementDoc != lastAdded) {
elements->AppendElement(elementDoc);
lastAdded = elementDoc;
}
continue;
}
// If we have an anonymous element (such as an internal div from a textbox),
// or a node that isn't an element or a text node,
// replace it with the first non-anonymous parent node.
while (ptContent &&
(!(ptContent->IsNodeOfType(nsINode::eELEMENT) ||
ptContent->IsNodeOfType(nsINode::eTEXT)) ||
ptContent->IsInAnonymousSubtree())) {
// XXXldb: Faster to jump to GetBindingParent if non-null?
ptContent = ptContent->GetParent();
}
if (ptContent && ptContent != lastAdded) {
elements->AppendElement(ptContent);
lastAdded = ptContent;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetElementsByClassName(const nsAString& aClasses,
nsIDOMNodeList** aReturn)

Просмотреть файл

@ -878,6 +878,13 @@ public:
PRBool aFlushLayout,
nsIDOMElement** aReturn);
virtual NS_HIDDEN_(nsresult) NodesFromRectHelper(float aX, float aY,
float aTopSize, float aRightSize,
float aBottomSize, float aLeftSize,
PRBool aIgnoreRootScrollFrame,
PRBool aFlushLayout,
nsIDOMNodeList** aReturn);
virtual NS_HIDDEN_(void) FlushSkinBindings();
virtual NS_HIDDEN_(nsresult) InitializeFrameLoader(nsFrameLoader* aLoader);

Просмотреть файл

@ -621,6 +621,21 @@ nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
aReturn);
}
NS_IMETHODIMP
nsDOMWindowUtils::NodesFromRect(float aX, float aY,
float aTopSize, float aRightSize,
float aBottomSize, float aLeftSize,
PRBool aIgnoreRootScrollFrame,
PRBool aFlushLayout,
nsIDOMNodeList** aReturn)
{
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
NS_ENSURE_STATE(doc);
return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
aIgnoreRootScrollFrame, aFlushLayout, aReturn);
}
static already_AddRefed<gfxImageSurface>
CanvasToImageSurface(nsIDOMHTMLCanvasElement *canvas)
{

Просмотреть файл

@ -46,13 +46,14 @@
*/
interface nsIDOMNode;
interface nsIDOMNodeList;
interface nsIDOMElement;
interface nsIDOMHTMLCanvasElement;
interface nsIDOMEvent;
interface nsITransferable;
interface nsIQueryContentEventResult;
[scriptable, uuid(25ada920-d727-45b6-ac70-847a3aa9c7cf)]
[scriptable, uuid(22a62b54-bcf5-422a-a329-fed4de5e78b2)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -303,6 +304,29 @@ interface nsIDOMWindowUtils : nsISupports {
in boolean aIgnoreRootScrollFrame,
in boolean aFlushLayout);
/**
* Retrieve all nodes that intersect a rect in the window's document.
*
* @param aX x reference for the rectangle in CSS pixels
* @param aY y reference for the rectangle in CSS pixels
* @param aTopSize How much to expand up the rectangle
* @param aRightSize How much to expand right the rectangle
* @param aBottomSize How much to expand down the rectangle
* @param aLeftSize How much to expand left the rectangle
* @param aIgnoreRootScrollFrame whether or not to ignore the root scroll
* frame when retrieving the element. If false, this method returns
* null for coordinates outside of the viewport.
* @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
*/
nsIDOMNodeList nodesFromRect(in float aX,
in float aY,
in float aTopSize,
in float aRightSize,
in float aBottomSize,
in float aLeftSize,
in boolean aIgnoreRootScrollFrame,
in boolean aFlushLayout);
/**
* Compare the two canvases, returning the number of differing pixels and
* the maximum difference in a channel. This will throw an error if