﻿<!doctype html>
<html>
    <head>
        <title>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</title>
        <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
        <meta name="variant" content="?mouse">
        <meta name="variant" content="?touch">
        <meta name="variant" content="?pen">
        <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
        <meta name="assert" content="After invoking the releasePointerCapture method on an element, subsequent events for the specified pointer must follow normal hit testing mechanisms for determining the event target"/>
        <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>
        <script type="text/javascript">
            var inputSource = location.search.substring(1);
            var test_pointerEvent;
            var detected_pointertypes = {};
            var captured_event = null;
            var test_done = false;
            var overEnterEventsFail = false;
            var outLeaveEventsFail = false;
            var f_gotPointerCapture = false;
            var f_lostPointerCapture = false;
            var actions_promise;

            function resetTestState() {
              captured_event = null;
              test_done = false;
              overEnterEventsFail = false;
              outLeaveEventsFail = false;
              f_gotPointerCapture = false;
              f_lostPointerCapture = false;
            }

            function listenerEventHandler(event) {
                if (test_done)
                    return;
                detected_pointertypes[event.pointerType] = true;
                if (event.type == "gotpointercapture") {
                    f_gotPointerCapture = true;
                    check_PointerEvent(event);
                }
                else if (event.type == "lostpointercapture") {
                    f_lostPointerCapture = true;
                    f_gotPointerCapture = false;
                    check_PointerEvent(event);
                }
                else if(event.type == "pointerover" || event.type == "pointerenter") {
                    if(captured_event && !overEnterEventsFail) {
                        test(function() {
                            assert_false(f_gotPointerCapture, "pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
                        }, expectedPointerType + " pointerover/enter should be received before the target receives gotpointercapture even when the pointer is not over it.");
                        overEnterEventsFail = true;
                    }
                }
                else if(event.type == "pointerout" || event.type == "pointerleave") {
                    if(!outLeaveEventsFail) {
                        test(function() {
                            assert_true(f_lostPointerCapture, "pointerout/leave should not be received unless the target just lost the capture.");
                        }, expectedPointerType + " pointerout/leave should not be received unless the target just lost the capture.");
                        outLeaveEventsFail = true;
                    }
                }
                else if (event.pointerId == captured_event.pointerId) {
                    if (f_gotPointerCapture && event.type == "pointermove") {
                        // on first event received for capture, release capture
                        listener.releasePointerCapture(event.pointerId);
                    }
                    else {
                        // if any other events are received after releaseCapture, then the test fails
                        test(function () {
                            assert_unreached(event.target.id + "-" + event.type + " should be handled by target element handler");
                        }, expectedPointerType + " No other events should be recieved by capturing node after release");
                    }
                }
            }

            function targetEventHandler(event) {
                if (test_done)
                    return;
                if (f_gotPointerCapture) {
                    if(event.type != "pointerout" && event.type != "pointerleave") {
                        test(function () {
                            assert_unreached("The Target element should not have received any events while capture is active. Event recieved:" + event.type + ".  ");
                        }, expectedPointerType + " The target element should not receive any events while capture is active");
                    }
                }

                if (event.type == "pointerdown") {
                    // pointerdown event received will be used to capture events.
                    listener.setPointerCapture(event.pointerId);
                    captured_event = event;
                }

                if (f_lostPointerCapture) {
                    test_pointerEvent.step(function () {
                        assert_equals(event.pointerId, captured_event.pointerId, "pointerID is same for event captured and after release");
                    });
                    if (event.type == "pointerup") {
                        test_done = true;
                        // Make sure the test finishes after all the input actions are completed.
                        actions_promise.then( () => {
                            test_pointerEvent.done();
                        });
                    }
                }
            }

            function run() {
                test_pointerEvent = setup_pointerevent_test("got/lost pointercapture: subsequent events to target", [inputSource]);  // set up test harness
                var listener = document.getElementById("listener");
                var target0 = document.getElementById("target0");
                target0.style["touchAction"] = "none";

                // target0 and listener - handle all events
                for (var i = 0; i < All_Pointer_Events.length; i++) {
                    on_event(target0, All_Pointer_Events[i], targetEventHandler);
                    on_event(listener, All_Pointer_Events[i], listenerEventHandler);
                }

                // Inject pointer inputs.
                actions_promise = pointerDragInTarget(inputSource, target0, 'right');
            }
        </script>
    </head>
    <body onload="run()">
        <h2 id="pointerTypeDescription"></h2>
        <div id="listener"></div>
        <h1>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</h1>
        <h4>
            Test Description:
            Use your pointer and press down in the black box. Then move around in the box and release your pointer.
            After invoking the releasePointerCapture method on an element, subsequent events for the specified
            pointer must follow normal hit testing mechanisms for determining the event target.
        </h4>
        <br />
        <div id="target0">
        </div>
        <div id="complete-notice">
            <p>Test complete:  Scroll to Summary to view Pass/Fail Results.</p>
            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
            <p>Refresh the page to run the tests again with a different pointer type.</p>
        </div>
        <div id="log"></div>
    </body>
</html>
