mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 654352: Implement (blassey) and fix (jwir3) document.caretPositionFromPoint so that it utilizes frame-relative coordinates to get caret position. (original: [r=smaug,roc]) (fixes: [r=blassey,Ms2ger])
This commit is contained in:
parent
778b4c1b2b
commit
b39f9fb583
@ -74,6 +74,7 @@ CPPSRCS = \
|
||||
nsDOMAttribute.cpp \
|
||||
nsDOMAttributeMap.cpp \
|
||||
nsDOMBlobBuilder.cpp \
|
||||
nsDOMCaretPosition.cpp \
|
||||
nsDOMDocumentType.cpp \
|
||||
nsDOMFile.cpp \
|
||||
nsDOMFileReader.cpp \
|
||||
|
40
content/base/src/nsDOMCaretPosition.cpp
Normal file
40
content/base/src/nsDOMCaretPosition.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDOMCaretPosition.h"
|
||||
#include "mozilla/dom/CaretPositionBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
nsDOMCaretPosition::nsDOMCaretPosition(nsINode* aNode, uint32_t aOffset)
|
||||
: mOffset(aOffset), mOffsetNode(aNode)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
nsDOMCaretPosition::~nsDOMCaretPosition()
|
||||
{
|
||||
}
|
||||
|
||||
nsINode* nsDOMCaretPosition::GetOffsetNode() const
|
||||
{
|
||||
return mOffsetNode;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsDOMCaretPosition::WrapObject(JSContext *aCx, JSObject *aScope,
|
||||
bool *aTried)
|
||||
{
|
||||
return mozilla::dom::CaretPositionBinding::Wrap(aCx, aScope, this, aTried);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsDOMCaretPosition, mOffsetNode)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCaretPosition)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCaretPosition)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCaretPosition)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
63
content/base/src/nsDOMCaretPosition.h
Normal file
63
content/base/src/nsDOMCaretPosition.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsDOMCaretPosition_h
|
||||
#define nsDOMCaretPosition_h
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
/**
|
||||
* Implementation of a DOM Caret Position, which is a node and offset within
|
||||
* that node, in the DOM tree.
|
||||
*
|
||||
* http://www.w3.org/TR/cssom-view/#dom-documentview-caretrangefrompoint
|
||||
*
|
||||
* @see Document::mozCaretPositionFromPoint(float x, float y)
|
||||
*/
|
||||
class nsDOMCaretPosition : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMCaretPosition)
|
||||
|
||||
nsDOMCaretPosition(nsINode* aNode, uint32_t aOffset);
|
||||
|
||||
/**
|
||||
* Retrieve the offset (character position within the DOM node) of the
|
||||
* CaretPosition.
|
||||
*
|
||||
* @returns The offset within the DOM node.
|
||||
*/
|
||||
uint32_t Offset() const { return mOffset; }
|
||||
|
||||
/**
|
||||
* Retrieve the DOM node with which this CaretPosition was established.
|
||||
* Normally, this will be created from a point, so it will be the DOM
|
||||
* node that lies at the point specified.
|
||||
*
|
||||
* @returns The DOM node of the CaretPosition.
|
||||
*
|
||||
* @see Document::mozCaretPositionFromPoint(float x, float y)
|
||||
*/
|
||||
nsINode* GetOffsetNode() const;
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return GetOffsetNode();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *aCx, JSObject *aScope, bool *aTried)
|
||||
MOZ_OVERRIDE MOZ_FINAL;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMCaretPosition();
|
||||
uint32_t mOffset;
|
||||
nsCOMPtr<nsINode> mOffsetNode;
|
||||
};
|
||||
#endif
|
||||
|
@ -181,6 +181,10 @@
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
#include "nsFrame.h"
|
||||
#include "nsDOMCaretPosition.h"
|
||||
#include "nsIDOMHTMLTextAreaElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -8650,6 +8654,64 @@ ResetFullScreen(nsIDocument* aDocument, void* aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::MozCaretPositionFromPoint(float aX, float aY, nsISupports** aCaretPos)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaretPos);
|
||||
*aCaretPos = nullptr;
|
||||
|
||||
nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
|
||||
nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
|
||||
nsPoint pt(x, y);
|
||||
|
||||
nsIPresShell *ps = GetShell();
|
||||
if (!ps) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame *rootFrame = ps->GetRootFrame();
|
||||
|
||||
// XUL docs, unlike HTML, have no frame tree until everything's done loading
|
||||
if (!rootFrame) {
|
||||
return NS_OK; // return null to premature XUL callers as a reminder to wait
|
||||
}
|
||||
|
||||
nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, pt, true,
|
||||
false);
|
||||
if (!ptFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// GetContentOffsetsFromPoint requires frame-relative coordinates, so we need
|
||||
// to adjust to frame-relative coordinates before we can perform this call.
|
||||
// It should also not take into account the padding of the frame.
|
||||
nsPoint adjustedPoint = pt - ptFrame->GetOffsetTo(rootFrame);
|
||||
|
||||
nsFrame::ContentOffsets offsets =
|
||||
ptFrame->GetContentOffsetsFromPoint(adjustedPoint);
|
||||
|
||||
nsCOMPtr<nsIContent> node = offsets.content;
|
||||
uint32_t offset = offsets.offset;
|
||||
if (node && node->IsInNativeAnonymousSubtree()) {
|
||||
nsIContent* nonanon = node->FindFirstNonChromeOnlyAccessContent();
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(nonanon);
|
||||
nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea = do_QueryInterface(nonanon);
|
||||
bool isText;
|
||||
if (textArea || (input &&
|
||||
NS_SUCCEEDED(input->MozIsTextField(false, &isText)) &&
|
||||
isText)) {
|
||||
node = nonanon;
|
||||
} else {
|
||||
node = nullptr;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*aCaretPos = new nsDOMCaretPosition(node, offset);
|
||||
NS_ADDREF(*aCaretPos);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDocument::ExitFullScreen()
|
||||
|
@ -503,6 +503,8 @@ MOCHITEST_FILES_B = \
|
||||
file_html_in_xhr3.html \
|
||||
file_html_in_xhr.sjs \
|
||||
test_bug647518.html \
|
||||
test_bug654352.html \
|
||||
test_bug654352-2.html \
|
||||
test_bug664916.html \
|
||||
test_bug666604.html \
|
||||
test_bug675121.html \
|
||||
|
64
content/base/test/test_bug654352-2.html
Normal file
64
content/base/test/test_bug654352-2.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=654352
|
||||
-->
|
||||
<head>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<title>Test for Bug 654352</title>
|
||||
<style>
|
||||
#a {
|
||||
padding: 10px;
|
||||
border: 8px solid black;
|
||||
width: 600px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function checkOffsetsFromPoint(aX, aY, aExpected) {
|
||||
var cp = document.mozCaretPositionFromPoint(aX, aY);
|
||||
ok(aExpected == cp.offset, 'expected offset at (' + aX + ', ' + aY + '): ' + aExpected + ', got: ' + cp.offset);
|
||||
}
|
||||
|
||||
function doTesting() {
|
||||
// Tests at the beginning of the lines in the div
|
||||
checkOffsetsFromPoint(27, 35, 0);
|
||||
checkOffsetsFromPoint(25, 49, 1);
|
||||
|
||||
// Test within the lines in the div
|
||||
checkOffsetsFromPoint(47, 57, 3);
|
||||
checkOffsetsFromPoint(115, 35, 11);
|
||||
|
||||
/*
|
||||
* These next two are questionably incorrect, as they both occur
|
||||
* at the end of the two lines within the div. BUT, the
|
||||
* new code matches the old code (focusOffset) for these,
|
||||
* so it seems correct...
|
||||
*/
|
||||
checkOffsetsFromPoint(143, 34, 1);
|
||||
checkOffsetsFromPoint(145, 51, 3);
|
||||
|
||||
// Tests within the text area and input
|
||||
checkOffsetsFromPoint(45, 77, 2);
|
||||
checkOffsetsFromPoint(204, 106, 2);
|
||||
|
||||
// Tests within the marquee
|
||||
checkOffsetsFromPoint(44, 148, 1);
|
||||
checkOffsetsFromPoint(103, 144, 7);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</head>
|
||||
<body onload="doTesting();">
|
||||
<div id="a" contenteditable>abc, abc, abc<br>
|
||||
abc, abc, abc<br>
|
||||
<textarea>abc</textarea><input value="abc"><br><br>
|
||||
<marquee>marquee</marquee>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
50
content/base/test/test_bug654352.html
Normal file
50
content/base/test/test_bug654352.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=654352
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 654352</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=654352">Mozilla Bug 654352</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 654352 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function afterLoad() {
|
||||
var testpre = document.getElementById("testpre");
|
||||
var rect1 = testpre.getBoundingClientRect();
|
||||
dump(rect1 + "\n");
|
||||
var caret1 = document.mozCaretPositionFromPoint(rect1.left + 30, rect1.top + 10);
|
||||
ok(caret1.offsetNode == testpre.firstChild, "node in CaretPosition not correct (" + caret1.offsetNode + " == " + testpre.firstChild + ")")
|
||||
ok(caret1.offset == 4, "offset in CaretPosition not correct (" + caret1.offset + "== 4)")
|
||||
|
||||
var testinput = document.getElementById("testinput");
|
||||
var rect2 = testinput.getBoundingClientRect();
|
||||
dump(rect2.top +", " + rect2.left + "\n");
|
||||
var caret2 = document.mozCaretPositionFromPoint( rect2.left + 30, rect2.top + 10);
|
||||
ok(caret2.offsetNode == testinput, "node in CaretPosition not correct (" + caret2.offsetNode + " == " + testinput + ")")
|
||||
ok(caret2.offset == 4, "offset in CaretPosition not correct (" + caret2.offset + "== 4)")
|
||||
SimpleTest.finish();
|
||||
};
|
||||
addLoadEvent(afterLoad);
|
||||
</script>
|
||||
</pre>
|
||||
<span id="testdiv">
|
||||
<pre id="testpre">test text</pre>
|
||||
</span>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<input id="testinput" type="text" value="test text"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -180,6 +180,10 @@ DOMInterfaces = {
|
||||
'skipGen': True
|
||||
}],
|
||||
|
||||
'CaretPosition' : {
|
||||
'nativeType': 'nsDOMCaretPosition',
|
||||
},
|
||||
|
||||
'DOMParser': {
|
||||
'nativeType': 'nsDOMParser',
|
||||
},
|
||||
|
@ -27,7 +27,7 @@ interface nsIDOMLocation;
|
||||
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
|
||||
*/
|
||||
|
||||
[scriptable, uuid(6f3aac2e-ae11-487a-9eb0-0e12c66b3b21)]
|
||||
[scriptable, uuid(d19897dc-948a-42e7-8ac6-d8a0bd141b85)]
|
||||
interface nsIDOMDocument : nsIDOMNode
|
||||
{
|
||||
readonly attribute nsIDOMDocumentType doctype;
|
||||
@ -330,7 +330,7 @@ interface nsIDOMDocument : nsIDOMNode
|
||||
*/
|
||||
void mozSetImageElement(in DOMString aImageElementId,
|
||||
in nsIDOMElement aImageElement);
|
||||
|
||||
|
||||
/**
|
||||
* Element which is currently the full-screen element as per the DOM
|
||||
* full-screen api.
|
||||
@ -372,6 +372,17 @@ interface nsIDOMDocument : nsIDOMNode
|
||||
*/
|
||||
readonly attribute nsIDOMElement mozPointerLockElement;
|
||||
|
||||
/**
|
||||
* Retrieve the location of the caret position (DOM node and character
|
||||
* offset within that node), given a point.
|
||||
*
|
||||
* @param x Horizontal point at which to determine the caret position, in
|
||||
* page coordinates.
|
||||
* @param y Vertical point at which to determine the caret position, in
|
||||
* page coordinates.
|
||||
*/
|
||||
nsISupports /* CaretPosition */ mozCaretPositionFromPoint(in float x, in float y);
|
||||
|
||||
/**
|
||||
* Exit pointer is lock if locked, as per the DOM pointer lock api.
|
||||
*
|
||||
|
12
dom/webidl/CaretPosition.webidl
Normal file
12
dom/webidl/CaretPosition.webidl
Normal file
@ -0,0 +1,12 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
interface CaretPosition {
|
||||
|
||||
/**
|
||||
* The offsetNode could potentially be null due to anonymous content.
|
||||
*/
|
||||
readonly attribute Node? offsetNode;
|
||||
readonly attribute unsigned long offset;
|
||||
};
|
@ -26,6 +26,7 @@ webidl_files = \
|
||||
CSSValue.webidl \
|
||||
CSSValueList.webidl \
|
||||
DelayNode.webidl \
|
||||
CaretPosition.webidl \
|
||||
DOMImplementation.webidl \
|
||||
DOMParser.webidl \
|
||||
DOMSettableTokenList.webidl \
|
||||
|
Loading…
Reference in New Issue
Block a user