<!doctype html>
<html>
  <head>
    <title>Pointer Event: Suppress compatibility mouse events on drag</title>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
    <link rel="author" title="Google" href="http://www.google.com "/>
    <meta name="assert" content="When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events."/>
    <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>
    <script type="text/javascript" src="pointerevent_support.js"></script>
    <script type="text/javascript">
      var test_pointerEvent = async_test("Suppress compat mouse events on drag");
      add_completion_callback(end_of_test);

      var detected_pointertypes = {};
      var event_log = [];

      function end_of_test() {
          showLoggedEvents();
          showPointerTypes();
      }

      var include_next_mousemove = false;

      // Limits logging/testing of mousemove.
      function drop_event(event_type) {
          return (event_type == "mousemove" && !include_next_mousemove);
      }

      function end_of_interaction() {
          test(function () {
              assert_equals(event_log.join(", "),
                  "mousedown@target1, mousemove@target1, mouseup@target1");
          }, "Event log");

          test_pointerEvent.done(); // complete test
      }

      function run() {
          on_event(document.getElementById("done"), "click", end_of_interaction);

          var target_list = ["target0", "target1"];
          var pointer_event_list = ["pointerdown" , "pointermove", "pointerup"];
          var mouse_event_list = ["mousedown", "mouseup", "mousemove"];

          target_list.forEach(function(targetId) {
              var target = document.getElementById(targetId);

              pointer_event_list.forEach(function(eventName) {
                  on_event(target, eventName, function (event) {
                      detected_pointertypes[event.pointerType] = true;
                      var label = event.type + "@" + targetId;

                      if (event.type == "pointerdown") {
                          test(function () {
                              assert_true(event.isPrimary);
                          }, "primary pointer " + label);
                      }

                      if (label === "pointerdown@target0")
                          event.preventDefault();
                  });
              });

              mouse_event_list.forEach(function(eventName) {
                  on_event(target, eventName, function (event) {
                      if (drop_event(event.type))
                          return;

                      event_log.push(event.type + "@" + targetId);

                      include_next_mousemove = (event.type == "mousedown");
                  });
              });
          });

          // Inject mouse inputs.
          var target0 = document.getElementById('target0');
          var target1 = document.getElementById('target1');
          var targetDone = document.getElementById('done');
          new test_driver.Actions()
              .pointerMove(0, 0, {origin: target0})
              .pointerDown()
              .pointerMove(10, 0, {origin: target0})
              .pointerUp()
              .pointerMove(0, 0, {origin: target1})
              .pointerDown()
              .pointerMove(10, 0, {origin: target1})
              .pointerUp()
              .pointerMove(0, 0, {origin: targetDone})
              .pointerDown()
              .pointerUp()
              .send();
      }
    </script>
    <style>
      #target0, #target1 {
        margin: 20px;
        touch-action: none;
      }

      #done {
        margin: 20px;
        border: 2px solid black;
      }
    </style>
  </head>
  <body onload="run()">
    <h1>Pointer Event: Suppress compatibility mouse events on drag</h1>
    <h4>
      When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events.
    </h4>
    <ol>
      <li> Drag mouse within Target0 &amp; release.</li>
      <li> Drag mouse within Target1 &amp; release.</li>
      <li> Click Done.</li>
    </ol>
    <div id="target0">
      Target0
    </div>
    <div id="target1">
      Target1
    </div>
    <div id="done">
      Done
    </div>
    <div id="complete-notice">
      <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
      <p>The following events were logged: <span id="event-log"></span>.</p>
    </div>
    <div id="log"></div>
  </body>
</html>
