<!doctype html>
<html>
    <head>
        <title>Pointermove on button state changes</title>
        <meta name="viewport" content="width=device-width">
        <meta name="assert" content="When a pointer changes button state and does not produce a different event, the pointermove event must be dispatched."/>
        <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
        <script src="/resources/testharness.js"></script>
        <script src="/resources/testharnessreport.js"></script>
        <script src="/resources/testdriver.js"></script>
        <script src="/resources/testdriver-actions.js"></script>
        <script src="/resources/testdriver-vendor.js"></script>
        <!-- Additional helper script for common checks across event types -->
        <script type="text/javascript" src="../pointerevent_support.js"></script>
    </head>
    <body onload="run()">
        <h2>PointerMove</h2>
        <h4>Test Description: This test checks if pointermove event are triggered by button state changes
            <ol>
                <li>Click on the black rectangle to lock the pointer </li>
                <li>Press a button and hold it</li>
                <li>Press a second button</li>
                <li>Release the second button</li>
                <li>Release the first button to complete the test</li>
            </ol>
        </h4>
        <div id="target0" style="background:black"></div>
        <script>
            var detected_pointertypes = {};
            var test_pointermove = async_test("pointer locked pointermove events received for button state changes");
            add_completion_callback(showPointerTypes);
            var actions_promise;

            var step = 0;
            var firstButton = 0;
            var pointer_locked = false;

            async function run() {
                var target0 = document.getElementById("target0");

                // When a pointer changes button state and the circumstances produce no other pointer event, the pointermove event must be dispatched.
                // 5.2.6

                on_event(target0, "pointerdown", function (event) {
                    if (pointer_locked) {
                        detected_pointertypes[event.pointerType] = true;
                        test_pointermove.step(function() {
                            assert_equals(step, 0, "There must not be more than one pointer down event.");
                        });
                        if (step == 0) {
                            step = 1;
                            firstButton = event.buttons;
                        }
                    }
                });
                on_event(target0, "pointermove", function (event) {
                    if (pointer_locked) {
                        detected_pointertypes[event.pointerType] = true;

                        if (step == 1 && event.button != -1) { // second button pressed
                            test_pointermove.step(function() {
                                assert_not_equals(event.buttons, firstButton, "The pointermove event must be triggered by pressing a second button.");
                            });
                            test_pointermove.step(function() {
                                assert_true((event.buttons & firstButton) != 0, "The first button must still be reported pressed.");
                            });
                            step = 2;
                        } else if (step == 2 && event.button != -1) { // second button released
                            test_pointermove.step(function() {
                                assert_equals(event.buttons, firstButton, "The pointermove event must be triggered by releasing the second button.");
                            });
                            step = 3;
                        }
                    }
                });
                on_event(target0, "pointerup", function (event) {
                    if (pointer_locked) {
                        detected_pointertypes[event.pointerType] = true;
                        test_pointermove.step(function() {
                            assert_equals(step, 3, "The pointerup event must be triggered after pressing and releasing the second button.");
                        });
                        test_pointermove.step(function() {
                            assert_equals(event.buttons, 0, "The pointerup event must be triggered by releasing the last pressed button.");
                        });
                        document.exitPointerLock();
                    } else {
                        target0.requestPointerLock();
                    }
                });
                on_event(document, 'pointerlockchange', function(event) {
                    if (document.pointerLockElement == target0)
                        pointer_locked = true;
                    else{
                        pointer_locked = false;
                        actions_promise.then( () => {
                           test_pointermove.done();
                        });
                    }
                });
                on_event(target0, "mouseup", function (event) {
                    event.preventDefault();
                });
                on_event(target0, "contextmenu", function (event) {
                    event.preventDefault();
                });

                // Inject mouse input
                var actions = new test_driver.Actions();
                actions_promise = actions
                       .pointerMove(0, 0, {origin: target0})
                       .pointerDown({button: actions.ButtonType.LEFT})
                       .pointerUp({button: actions.ButtonType.LEFT})
                       .send();
                await actions_promise;
                await resolveWhen(()=>pointer_locked);
                actions = new test_driver.Actions();
                actions_promise = actions
                       .pointerMove(0, 0, {origin: target0})
                       .pointerDown({button: actions.ButtonType.LEFT})
                       .pointerDown({button: actions.ButtonType.MIDDLE})
                       .pointerUp({button: actions.ButtonType.MIDDLE})
                       .pointerUp({button: actions.ButtonType.LEFT})
                       .send();
            }
        </script>
        <h1>Pointer Lock Pointer Events pointermove on button state changes Tests</h1>
        <div id="complete-notice">
            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
            <p>Refresh the page to run the tests again.</p>
        </div>
        <div id="log"></div>
    </body>
</html>
