<html>
<head>
<script src="../../resources/js-test.js"></script>
<style>
#square {
display: table-cell;
vertical-align: middle;
background: blue;
width: 128px;
height: 128px;
color: white;
text-align: center;
padding: 10px;
cursor: default;
-webkit-user-drag: none;
-webkit-user-select: none;
}
</style>
<script>
var didFireMousedownForFirstMouseButton;
var didFireMousedownForSecondMouseButton;
var firstMouseButtonElem;
var previouslyChosenFirstMouseButton = 0;
var secondMouseButtonElem;
var square;
// Extracted from the DOM Level 3 Events Mouse Event Types section <http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button>.
var LeftMouseButton = 0;
var MiddleMouseButton = 1;
var RightMouseButton = 2;
window.onload = function()
{
firstMouseButtonElem = document.getElementById("firstMouseButton");
secondMouseButtonElem = document.getElementById("secondMouseButton");
firstMouseButtonElem.onchange = function() {
disableIllogicalSecondMouseButtonOptions();
resetTest();
}
secondMouseButtonElem.onchange = resetTest;
square = document.getElementById("square");
square.onmousedown = checkIfDoneOnMouseDown;
square.onmouseup = checkIfDoneOnMouseUp;
square.oncontextmenu = cancelContextMenu;
resetTest();
runTest();
}
function toIEMouseButton(w3cButton)
{
switch (w3cButton) {
case LeftMouseButton:
return 1;
case MiddleMouseButton:
return 4;
case RightMouseButton:
return 2;
}
return; // We shouldn't get here.
}
function shortMouseButtonName(w3cButton)
{
switch (w3cButton) {
case LeftMouseButton:
return "left";
case MiddleMouseButton:
return "middle";
case RightMouseButton:
return "right";
}
return; // We shouldn't get here.
}
function mouseButtonName(w3cButton)
{
return shortMouseButtonName(w3cButton) + " mouse button";
}
function cancelContextMenu(event)
{
event = event || window.event;
if (event.preventDefault)
event.preventDefault();
else {
// Assume this script is executing within Internet Explorer.
event.returnValue = false;
}
}
function checkIfDoneOnMouseDown(event)
{
var pressedButtons; // A bitmask that represents the combination of buttons that are currently being pressed.
if (event && event.buttons)
pressedButtons = event.buttons; // DOM Level 3 Events (Working Draft 07 September 2010).
else if (event) {
// For browsers than don't support event.buttons (or IE's window.event.button) we convert event.button to
// the corresponding bitmask to simplify the logic below.
pressedButtons = toIEMouseButton(event.button);
} else {
// Assume this script is running within Internet Explorer.
pressedButtons = window.event.button;
}
var chosenFirstMouseButton = firstMouseButtonElem.selectedIndex;
var chosenSecondMouseButton = secondMouseButtonElem.selectedIndex;
if (!didFireMousedownForFirstMouseButton && (pressedButtons & toIEMouseButton(chosenFirstMouseButton)) == toIEMouseButton(chosenFirstMouseButton)) {
didFireMousedownForFirstMouseButton = true;
square.innerHTML = "Now, " + shortMouseButtonName(chosenSecondMouseButton) + " click";
} else if (didFireMousedownForFirstMouseButton && (pressedButtons & toIEMouseButton(chosenSecondMouseButton)) == toIEMouseButton(chosenSecondMouseButton))
didFireMousedownForSecondMouseButton = true;
if (didFireMousedownForFirstMouseButton && didFireMousedownForSecondMouseButton) {
testPassed("received mousedown for the " + mouseButtonName(chosenSecondMouseButton) + " while pressing the " + mouseButtonName(chosenFirstMouseButton) + ".");
resetTest();
}
}
function checkIfDoneOnMouseUp()
{
if (didFireMousedownForFirstMouseButton && !didFireMousedownForSecondMouseButton) {
// Without loss of generality, either the mousedown for the right button button wasn't
// dispatched or the user didn't press the right mouse button while pressing left mouse button.
var chosenFirstMouseButton = firstMouseButtonElem.selectedIndex;
var chosenSecondMouseButton = secondMouseButtonElem.selectedIndex;
testFailed("didn't receive mousedown for the " + mouseButtonName(chosenSecondMouseButton) + " while pressing the " + mouseButtonName(chosenFirstMouseButton) + ".");
resetTest();
}
}
function resetTest()
{
didFireMousedownForFirstMouseButton = false;
didFireMousedownForSecondMouseButton = false;
square.innerHTML = "Press and hold the " + mouseButtonName(firstMouseButtonElem.selectedIndex) + " on me";
}
function disableIllogicalSecondMouseButtonOptions()
{
secondMouseButtonElem.options[previouslyChosenFirstMouseButton].disabled = false;
if (firstMouseButtonElem.selectedIndex === secondMouseButtonElem.selectedIndex)
secondMouseButtonElem.options[(secondMouseButtonElem.selectedIndex + 1) % secondMouseButtonElem.length].selected = true;
secondMouseButtonElem.options[firstMouseButtonElem.selectedIndex].disabled = true;
previouslyChosenFirstMouseButton = firstMouseButtonElem.selectedIndex;
}
function runTest()
{
if (!window.eventSender)
return;
var numFirstMouseButtonOptions = firstMouseButtonElem.options.length;
var numSecondMouseButtonOptions = secondMouseButtonElem.options.length;
eventSender.mouseMoveTo(square.offsetLeft + 10, square.offsetTop + 10);
var firstMouseButton = 0;
var secondMouseButton = 0;
while (firstMouseButton < numFirstMouseButtonOptions) {
if (firstMouseButton === secondMouseButton)
++secondMouseButton;
if (secondMouseButton >= numSecondMouseButtonOptions) {
++firstMouseButton;
secondMouseButton = 0;
}
if (firstMouseButton >= numFirstMouseButtonOptions)
break;
firstMouseButtonElem.options[firstMouseButton].selected = true;
secondMouseButtonElem.options[secondMouseButton].selected = true;
if (secondMouseButton % numSecondMouseButtonOptions === 0)
debug('<br />When pressing and holding the "' + mouseButtonName(firstMouseButton) + '"<br />');
eventSender.mouseDown(firstMouseButton);
eventSender.leapForward(100);
eventSender.mouseDown(secondMouseButton);
eventSender.mouseUp(secondMouseButton);
eventSender.mouseUp(firstMouseButton);
eventSender.leapForward(100);
++secondMouseButton;
resetTest(); // We reset the test here in case neither a mousedown nor mouseup event was fired.
}
document.body.removeChild(document.getElementById("test-container"));
debug('<br /><span class="pass">TEST COMPLETE</span>');
}
</script>
</head>
<body>
<p id="description"></p>
<div id="test-container">
<p>Note: Ensure mouse gestures are disabled when running this test in Opera. In Opera 11.10 you can disable gestures by selecting Opera > Preferences > Advanced > Shortcuts. Then uncheck Enable mouse gestures. Also, to test "pressing-and-holding the right mouse button then clicking the left mouse" (*) ensure that Enable Mouse Flips is disabled. To disable it open <a href="opera:config" target="_blank">opera:config</a> then search for "Enable Mouse Flips" and uncheck it. As of 04/15/2011, for some reason (*) neither <span class="pass">PASS</span>es nor <span class="fail">FAIL</span>s.</p>
<!-- The <option>s in these <select>s are explicitly ordered to match the DOM Level 3 Events mouse button values for Left, Middle, and Right mouse buttons. -->
<label for="firstMouseButton">Will press and hold</label> <select id="firstMouseButton">
<option>Left mouse button</option>
<option>Middle mouse button</option>
<option>Right mouse button</option>
</select>
<span>on blue square then</span>
<label for="secondMouseButton">click</label> <select id="secondMouseButton">
<option disabled>Left mouse button</option>
<option selected>Middle mouse button</option>
<option>Right mouse button</option>
</select>
<br/><br/>
<div id="square"></div>
</div>
<hr/>
<div id="console"></div>
<script>
description("This test verifies that we fire a mousedown event whenever pressing and holding a mouse button A while simultaneously " +
"clicking with mouse button B, where A != B.<br/>" +
"For each mouse button that is pressed and held, iterates through the possible second mouse buttons that can be clicked.");
</script>
</body>
</html>