blob: ab835254a00991e9ca48d4f1f1ae2a2c4f5bed10 [file] [log] [blame]
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {
font-family: Ahem;
font-size: 10px;
}
#testArea {
position: absolute;
right: 50px;
top: 50px;
}
#target {
width: 10px;
height: 10px;
}
#frame {
width: 100px;
height: 100px;
margin-top: 30px;
}
</style>
<div id=testArea>
<div id=target></div>
<iframe id=frame srcdoc='<body style="margin: 5px"><iframe width=75 height=75></iframe></body>'></iframe>
</div>
<script src="../../resources/js-test.js"></script>
<script>
setPrintTestResultsLazily();
if (window.internals) {
internals.settings.setViewportEnabled(true);
internals.settings.setMockScrollbarsEnabled(true);
}
var unique_event_id = 1;
description("Count how many hit tests are required for various event scenarios. Hit tests can be expensive and it's often tempting to add more. These values should only ever be changed to go down, not up.");
function hitTestCountDelta(doc)
{
var lastCount = 0;
if ('lastHitTestCount' in doc)
lastCount = doc.lastHitTestCount;
var newCount = internals.hitTestCount(doc);
doc.lastHitTestCount = newCount;
return newCount - lastCount;
}
function hitTestCacheHitsDelta(doc)
{
var lastCount = 0;
if ('lastHitTestCacheHits' in doc)
lastCount = doc.lastHitTestCacheHits;
var newCount = internals.hitTestCacheHits(doc);
doc.lastHitTestCacheHits = newCount;
return newCount - lastCount;
}
function logCounts(label, documents, multiTapNotification, eventSenderFunction)
{
if (eventSenderFunction)
eventSenderFunction();
var countStr = '';
for(var i = 0; i < documents.length; i++) {
var hits = hitTestCountDelta(documents[i]);
var cacheHits = hitTestCacheHitsDelta(documents[i]);
countStr += ' ' + (hits - cacheHits) + "+" + cacheHits;
}
if (multiTapNotification) {
debug(label + ':' + eventCounts[label]
+ ((countStr == eventCounts[label])? '': ' [with multiTargetTapNotification:' + countStr + ']'));
} else {
// store the count for later; to be compared when the
// multiTapNotification test is run.
eventCounts[label] = countStr;
}
}
function clearCounts(documents)
{
for(var i = 0; i < documents.length; i++) {
documents[i].lastHitTestCount = internals.hitTestCount(documents[i]);
documents[i].lastHitTestCacheHits = internals.hitTestCacheHits(documents[i]);
}
}
function sendEvents(targetX, targetY, documents, multiTapNotification)
{
logCounts('Initial', documents, multiTapNotification);
logCounts('MouseMove', documents, multiTapNotification, function() {
eventSender.mouseMoveTo(targetX, targetY);
});
logCounts('MouseDown', documents, multiTapNotification, function() {
eventSender.mouseDown();
});
logCounts('MouseUp', documents, multiTapNotification, function() {
eventSender.mouseUp();
});
logCounts('Wheel', documents, multiTapNotification, function() {
eventSender.mouseScrollBy(0, 5, false, false, 0, false);
});
logCounts('TouchStart', documents, multiTapNotification, function() {
eventSender.addTouchPoint(targetX, targetY, 15, 15);
eventSender.touchStart(unique_event_id + 1);
});
logCounts('TouchMove', documents, multiTapNotification, function() {
eventSender.updateTouchPoint(0, targetX + 1, targetY, 15, 15);
eventSender.touchMove(unique_event_id + 2);
});
logCounts('TouchEnd', documents, multiTapNotification, function() {
eventSender.releaseTouchPoint(0);
eventSender.touchEnd(unique_event_id + 3);
});
logCounts('GestureTapDown', documents, multiTapNotification, function() {
eventSender.gestureTapDown(targetX, targetY, 30, 30, unique_event_id + 1);
});
logCounts('GestureShowPress', documents, multiTapNotification, function() {
eventSender.gestureShowPress(targetX, targetY, 30, 30, unique_event_id + 3);
});
logCounts('GestureTap', documents, multiTapNotification, function() {
// We don't want to tap on an existing selection so we clear selections.
window.getSelection().empty();
eventSender.gestureTap(targetX, targetY, 1, 30, 30, unique_event_id + 3);
});
logCounts('GestureScrollBegin', documents, multiTapNotification, function() {
eventSender.gestureTapDown(targetX, targetY, 30, 30);
clearCounts(documents);
eventSender.gestureScrollBegin(targetX, targetY);
});
logCounts('GestureTapCancel', documents, multiTapNotification, function() {
eventSender.gestureTapCancel(targetX, targetY);
});
logCounts('GestureScrollUpdate', documents, multiTapNotification, function() {
eventSender.gestureScrollUpdate(0, 5);
});
logCounts('GestureScrollEnd', documents, multiTapNotification, function() {
eventSender.gestureScrollEnd(0, 5);
});
logCounts('DoubleFingerTouch', documents, multiTapNotification, function() {
eventSender.addTouchPoint(targetX+1, targetY+1);
eventSender.touchStart();
eventSender.addTouchPoint(targetX+4, targetY+4);
eventSender.touchStart();
eventSender.releaseTouchPoint(0);
eventSender.releaseTouchPoint(1);
eventSender.touchEnd();
});
unique_event_id = unique_event_id + 3;
// Leap forward to reset click count, so mouse down will not generate a double click.
eventSender.leapForward(1000);
}
function runTestForDocuments(targetX, targetY, documents)
{
clearCounts(documents);
sendEvents(targetX, targetY, documents, false);
internals.settings.setMultiTargetTapNotificationEnabled(true);
for(var i = 0; i < documents.length; i++) {
internals.clearHitTestCache(documents[i]);
}
sendEvents(targetX, targetY, documents, true);
internals.settings.setMultiTargetTapNotificationEnabled(false);
}
function centerOf(element) {
var targetRect = element.getBoundingClientRect();
return {
x: targetRect.left + targetRect.width / 2,
y: targetRect.top + targetRect.height / 2
};
}
eventCounts = {};
onload = function() {
internals.settings.setMultiTargetTapNotificationEnabled(false);
debug('Event on a simple div');
debug('---------------------');
var point = centerOf(document.getElementById('target'));
runTestForDocuments(point.x, point.y, [document]);
debug('');
debug('Event entirely over one iframe nested in another');
debug('---------------------');
var frame = document.getElementById('frame');
var doc2 = frame.contentDocument;
var doc3 = doc2.querySelector('iframe').contentDocument;
var point = centerOf(frame);
runTestForDocuments(point.x, point.y, [document, doc2, doc3]);
debug('');
debug('Event near boundary of two iframes');
debug('---------------------');
var rect = frame.getBoundingClientRect();
runTestForDocuments(rect.left + 3, rect.top + 3, [document, doc2, doc3]);
debug('');
internals.settings.setViewportEnabled(false);
debug('Event on a simple div (desktop viewport)');
debug('---------------------');
var point = centerOf(document.getElementById('target'));
runTestForDocuments(point.x, point.y, [document]);
debug('');
internals.settings.setViewportEnabled(true);
finishJSTest();
}
</script>