ergedEvents = {};
    const mergeEvents = event => {
      if (event.type === "touchstart") {
        mergedEvents.touch = event;
      } else {
        mergedEvents.pointer = event;
      }

      // Resolve the promise if we got pointerdown
      if (mergedEvents.pointer) {
        resolve(mergedEvents);
      }
    };

    promise.then(e => {
      const map = new Map([
        ["pointerPressure", e.pointer.pressure],
        ["pointerTangentinalPressure", e.pointer.tangentialPressure],
        ["pointerTiltx", e.pointer.tiltX],
        ["pointerTilty", e.pointer.tiltY],
        ["pointerTwist", e.pointer.twist],
        ["pointerWidth", e.pointer.width],
        ["pointerHeight", e.pointer.height],
        ["touchRotationAngle", e.touch?.rotationAngle || 0],
      ]);
      this.sendMessage("PointerInfo:Populated", map);
      this.propertyCollected("PointerInfo");
    });

    this.handlers.touchstart = touchStartHandler;
    this.handlers.pointerdown = pointerDownHandler;

    if (Cu.isInAutomation) {
      // Just simulate the events if we are in automation
      const pointerEvent = new PointerEvent("pointerdown");
      this.contentWindow.windowRoot.dispatchEvent(pointerEvent);
    }
  }

  sendMessage(name, obj, transferables) {
    if (this.destroyed) {
      return;
    }

    this.sendAsyncMessage(name, obj, transferables);
  }

  propertyCollected(name) {
    this.collectedProperties.add(name);
    if (this.targetProperties.difference(this.collectedProperties).size === 0) {
      this.sendMessage("WindowInfo::Done");
    }
  }

  didDestroy() {
    this.destroyed = true;
    for (const [type, handler] of Object.entries(this.handlers)) {
      this.contentWindow?.windowRoot?.removeEventListener(type, handler);
    }
  }

  async receiveMessage(msg) {
    lazy.console.debug("Actor Child: Got ", msg.name);
    switch (msg.name) {
      case "WindowInfo:PopulateFromDocument":
        if (this.document.readyState == "complete") {
          this.populateScreenInfo();
          this.populatePointerInfo();
        }
        break;
    }

    return null;
  }

  async handleEvent(event) {
    lazy.console.debug("Actor Child: Got ", event.type);
    switch (event.type) {
      case "DOMContentLoaded":
        this.populateScreenInfo();
        this.populatePointerInfo();
        break;
    }
  }
}
PK