summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
blob: 8aff3103ddc97b63f2296efab4e04d45b781094e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<!DOCTYPE HTML>
<html>
<head>
  <title>Test APZ hit-testing while overscrolled</title>
  <script type="application/javascript" src="apz_test_utils.js"></script>
  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
  <script src="/tests/SimpleTest/paint_listener.js"></script>
  <meta name="viewport" content="width=device-width"/>
  <style>
    html, body {
      margin: 0;
      padding: 0;
    }
    .spacer {
      height: 5000px;
    }
    #target {
      margin-left: 100px;
      margin-top: 2px;
      height: 4px;
      width: 4px;
      background: red;
    }
  </style>
</head>
<body>
 <div id="target"></div>
 <div class="spacer"></div>
</body>
<script type="application/javascript">

// Some helper functions for listening for contextmenu events in the browser chrome.

// A handle used to interact with the chrome script used to implement
// [start|stop]ListeningForContextmenuEventsInChrome().
let chromeScriptHandle = null;

function startListeningForContextmenuEventsInChrome() {
  function chromeScript() {
    /* eslint-env mozilla/chrome-script */
    let topWin = Services.wm.getMostRecentWindow("navigator:browser");
    if (!topWin) {
      topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
    }
    let chromeReceivedContextmenu = false;
    function chromeListener(e) {
      chromeReceivedContextmenu = true;
    }
    topWin.addEventListener("contextmenu", chromeListener);
    function queryContextmenu() {
      sendAsyncMessage("query-contextmenu-response", { chromeReceivedContextmenu });
    }
    function cleanup() {
      topWin.removeEventListener("contextmenu", chromeListener);
      removeMessageListener("query-contextmenu", queryContextmenu);
      removeMessageListener("cleanup", cleanup);
    }
    addMessageListener("query-contextmenu", queryContextmenu);
    addMessageListener("cleanup", cleanup);
  }
  chromeScriptHandle = SpecialPowers.loadChromeScript(chromeScript);
}

async function didChromeReceiveContextmenu() {
  chromeScriptHandle.sendAsyncMessage("query-contextmenu", null);
  let response = await chromeScriptHandle.promiseOneMessage("query-contextmenu-response");
  ok(response && ("chromeReceivedContextmenu" in response),
     "Received a well-formed response from chrome script");
  return response.chromeReceivedContextmenu;
}

function stopListeningForContextmenuEventsInChrome() {
  chromeScriptHandle.sendAsyncMessage("cleanup", null);
  chromeScriptHandle.destroy();
}

async function test() {
  var config = getHitTestConfig();
  var utils = config.utils;

  // Overscroll the root scroll frame at the top, creating a gutter.
  // Note that the size of the gutter will only be 8px, because
  // setAsyncScrollOffset() applies the overscroll as a single delta,
  // and current APZ logic that transforms a delta into an overscroll
  // amount limits each delta to at most 8px.
  utils.setAsyncScrollOffset(document.documentElement, 0, -200);

  // Now, perform a right-click in the gutter and check that APZ prevents
  // the contextevent from reaching Gecko.
  // To be sure that no event was dispatched to Gecko, install listeners
  // on both the browser chrome window and the content window.
  // This makes sure we catch the case where the overscroll transform causes
  // the event to incorrectly target the browser chrome.
  let deviceScale = window.devicePixelRatio;
  let midGutter = 4 / deviceScale;  // gutter is 8 *screen* pixels
  startListeningForContextmenuEventsInChrome();
  let contentReceivedContextmenu = false;
  let contentListener = function(e) {
    contentReceivedContextmenu = true;
  };
  document.addEventListener("contextmenu", contentListener);
  await synthesizeNativeMouseEventWithAPZ({
    type: "click",
    button: 2,  // eSecondary (= "right mouse button")
    target: window,
    offsetX: 100,
    offsetY: midGutter
  });
  // Wait 10 frames for the event to maybe arrive, and if it
  // hasn't, assume it won't.
  for (let i = 0; i < 10; i++) {
    await promiseFrame();
  }
  info("Finished waiting around for contextmenu event");
  let chromeReceivedContextmenu = await didChromeReceiveContextmenu();
  ok(!chromeReceivedContextmenu,
     "Gecko received contextmenu event in browser chrome when it shouldn't have");
  ok(!contentReceivedContextmenu,
     "Gecko received contextmenu event targeting web content when it shouldn't have");
  stopListeningForContextmenuEventsInChrome();
  document.removeEventListener("contextmenu", contentListener);
}

waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);

</script>
</html>