mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1669158 - Fix the offset of nested iframe by considering the border and padding size. r=mats,geckoview-reviewers,TYLin,agi
Differential Revision: https://phabricator.services.mozilla.com/D92375
This commit is contained in:
parent
9bd206cdff
commit
803b368879
@ -1438,12 +1438,6 @@ void AccessibleCaretManager::DispatchCaretStateChangedEvent(
|
||||
init.mSelectionVisible = true;
|
||||
}
|
||||
|
||||
// The rect computed above is relative to rootFrame, which is the (layout)
|
||||
// viewport frame. However, the consumers of this event expect the bounds
|
||||
// of the selection relative to the screen (visual viewport origin), so
|
||||
// translate between the two.
|
||||
rect -= mPresShell->GetVisualViewportOffsetRelativeToLayoutViewport();
|
||||
|
||||
domRect->SetLayoutRect(rect);
|
||||
|
||||
// Send isEditable info w/ event detail. This info can help determine
|
||||
|
@ -125,11 +125,21 @@ class GeckoViewSelectionActionChild extends GeckoViewChildModule {
|
||||
|
||||
let currentWindow = aEvent.target.defaultView;
|
||||
while (currentWindow.realFrameElement) {
|
||||
const currentRect = currentWindow.realFrameElement.getBoundingClientRect();
|
||||
currentWindow = currentWindow.realFrameElement.ownerGlobal;
|
||||
const frameElement = currentWindow.realFrameElement;
|
||||
currentWindow = frameElement.ownerGlobal;
|
||||
|
||||
offset.left += currentRect.left;
|
||||
offset.top += currentRect.top;
|
||||
// The offset of the iframe window relative to the parent window
|
||||
// includes the iframe's border, and the iframe's origin in its
|
||||
// containing document.
|
||||
const currentRect = frameElement.getBoundingClientRect();
|
||||
const style = currentWindow.getComputedStyle(frameElement);
|
||||
const borderLeft = parseFloat(style.borderLeftWidth) || 0;
|
||||
const borderTop = parseFloat(style.borderTopWidth) || 0;
|
||||
const paddingLeft = parseFloat(style.paddingLeft) || 0;
|
||||
const paddingTop = parseFloat(style.paddingTop) || 0;
|
||||
|
||||
offset.left += currentRect.left + borderLeft + paddingLeft;
|
||||
offset.top += currentRect.top + borderTop + paddingTop;
|
||||
|
||||
const targetDocShell = currentWindow.docShell;
|
||||
if (targetDocShell.isMozBrowser) {
|
||||
@ -137,6 +147,19 @@ class GeckoViewSelectionActionChild extends GeckoViewChildModule {
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have coordinates relative to the root content document's
|
||||
// layout viewport. Subtract the offset of the visual viewport
|
||||
// relative to the layout viewport, to get coordinates relative to
|
||||
// the visual viewport.
|
||||
var offsetX = {};
|
||||
var offsetY = {};
|
||||
currentWindow.windowUtils.getVisualViewportOffsetRelativeToLayoutViewport(
|
||||
offsetX,
|
||||
offsetY
|
||||
);
|
||||
offset.left -= offsetX.value;
|
||||
offset.top -= offsetY.value;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import org.mozilla.geckoview.test.util.Callbacks
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.RectF;
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.filters.MediumTest
|
||||
|
||||
@ -182,6 +183,20 @@ class SelectionActionDelegateTest : BaseSessionTest() {
|
||||
counter, equalTo(1))
|
||||
}
|
||||
|
||||
@Test fun compareClientRect() {
|
||||
val jsCssReset = """(function() {
|
||||
document.querySelector('${id}').style.display = "block";
|
||||
document.querySelector('${id}').style.border = "0";
|
||||
document.querySelector('${id}').style.padding = "0";
|
||||
})()"""
|
||||
val jsBorder10pxPadding10px = """(function() {
|
||||
document.querySelector('${id}').style.display = "block";
|
||||
document.querySelector('${id}').style.border = "10px solid";
|
||||
document.querySelector('${id}').style.padding = "10px";
|
||||
})()"""
|
||||
val expectedDiff = RectF(20f, 20f, 20f, 20f) // left, top, right, bottom
|
||||
testClientRect(selectedContent, jsCssReset, jsBorder10pxPadding10px, expectedDiff)
|
||||
}
|
||||
|
||||
/** Interface that defines behavior for a particular type of content */
|
||||
private interface SelectedContent {
|
||||
@ -228,6 +243,52 @@ class SelectionActionDelegateTest : BaseSessionTest() {
|
||||
sideEffects.forEach { it(content) }
|
||||
}
|
||||
|
||||
private fun testClientRect(content: SelectedContent,
|
||||
initialJsA: String,
|
||||
initialJsB: String,
|
||||
expectedDiff: RectF) {
|
||||
|
||||
// Show selection actions for collapsed selections, so we can test them.
|
||||
// Also, always show accessible carets / selection actions for changes due to JS calls.
|
||||
sessionRule.setPrefsUntilTestEnd(mapOf(
|
||||
"geckoview.selection_action.show_on_focus" to true,
|
||||
"layout.accessiblecaret.script_change_update_mode" to 2))
|
||||
|
||||
mainSession.loadTestPath(INPUTS_PATH)
|
||||
mainSession.waitForPageStop()
|
||||
|
||||
val requestClientRect: (String) -> RectF = {
|
||||
mainSession.reload()
|
||||
mainSession.waitForPageStop()
|
||||
|
||||
mainSession.evaluateJS(it)
|
||||
content.focus()
|
||||
|
||||
var clientRect = RectF()
|
||||
content.select()
|
||||
mainSession.waitUntilCalled(object : Callbacks.SelectionActionDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onShowActionRequest(session: GeckoSession, selection: Selection) {
|
||||
clientRect = selection.clientRect!!
|
||||
}
|
||||
})
|
||||
|
||||
clientRect
|
||||
}
|
||||
|
||||
val clientRectA = requestClientRect(initialJsA)
|
||||
val clientRectB = requestClientRect(initialJsB)
|
||||
|
||||
val fuzzyEqual = { a: Float, b: Float, e: Float -> Math.abs(a + e - b) <= 1 }
|
||||
val result = fuzzyEqual(clientRectA.top, clientRectB.top, expectedDiff.top)
|
||||
&& fuzzyEqual(clientRectA.left, clientRectB.left, expectedDiff.left)
|
||||
&& fuzzyEqual(clientRectA.width(), clientRectB.width(), expectedDiff.width())
|
||||
&& fuzzyEqual(clientRectA.height(), clientRectB.height(), expectedDiff.height())
|
||||
|
||||
assertThat("Selection rect is not at expected location. a$clientRectA b$clientRectB",
|
||||
result, equalTo(true))
|
||||
}
|
||||
|
||||
|
||||
/** Helpers. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user