    /*
    	This file was derived from the p5.js source code at
    	https://github.com/processing/p5.js

    	Copyright (c) the p5.js contributors and Andre Seidelt <superilu@yahoo.com>

        This library is free software; you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public
        License as published by the Free Software Foundation; either
        version 2.1 of the License, or (at your option) any later version.

        This library is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        Lesser General Public License for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with this library; if not, write to the Free Software
        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */

    /**
    * @module p5compat
    */

    /**********************************************************************************************************************
     * mouse
     */
    /*
     * This is a flag which is false until the first time
     * we receive a mouse event. The pmouseX and pmouseY
     * values will match the mouseX and mouseY values until
     * this interaction takes place.
     */
    exports._hasMouseInteracted = false;

    /**
     * The system variable mouseX always contains the current horizontal
     * position of the mouse, relative to (0, 0) of the canvas. If touch is
     * used instead of mouse input, mouseX will hold the x value of the most
     * recent touch point.
     *
     * @property {Number} mouseX
     * @readOnly
     *
     * @example
     * // Move the mouse across the canvas
     * function draw() {
     *   background(244, 248, 252);
     *   line(mouseX, 0, mouseX, 100);
     * }
     */
    exports.mouseX = 0;

    /**
     * The system variable mouseY always contains the current vertical position
     * of the mouse, relative to (0, 0) of the canvas. If touch is
     * used instead of mouse input, mouseY will hold the y value of the most
     * recent touch point.
     *
     * @property {Number} mouseY
     * @readOnly
     *
     * @example
     * // Move the mouse across the canvas
     * function draw() {
     *   background(244, 248, 252);
     *   line(0, mouseY, 100, mouseY);
     * }
     */
    exports.mouseY = 0;

    /**
     * The system variable pmouseX always contains the horizontal position of
     * the mouse or finger in the frame previous to the current frame, relative to
     * (0, 0) of the canvas. Note: pmouseX will be reset to the current mouseX
     * value at the start of each touch event.
     *
     * @property {Number} pmouseX
     * @readOnly
     *
     * @example
     * // Move the mouse across the canvas to leave a trail
     * function setup() {
     *   //slow down the frameRate to make it more visible
     *   frameRate(10);
     * }
     *
     * function draw() {
     *   background(244, 248, 252);
     *   line(mouseX, mouseY, pmouseX, pmouseY);
     *   print(pmouseX + ' -> ' + mouseX);
     * }
     */
    exports.pmouseX = 0;

    /**
     * The system variable pmouseY always contains the vertical position of the
     * mouse or finger in the frame previous to the current frame, relative to
     * (0, 0) of the canvas. Note: pmouseY will be reset to the current mouseY
     * value at the start of each touch event.
     *
     * @property {Number} pmouseY
     * @readOnly
     *
     * @example
     * function draw() {
     *   background(237, 34, 93);
     *   fill(0);
     *   //draw a square only if the mouse is not moving
     *   if (mouseY === pmouseY && mouseX === pmouseX) {
     *     rect(20, 20, 60, 60);
     *   }
     *
     *   print(pmouseY + ' -> ' + mouseY);
     * }
     */
    exports.pmouseY = 0;

    /**
     * The system variable winMouseX always contains the current horizontal
     * position of the mouse, relative to (0, 0) of the window.
     *
     * @property {Number} winMouseX
     * @readOnly
     *
     * @example
     * let myCanvas;
     *
     * function setup() {
     *   //use a variable to store a pointer to the canvas
     *   myCanvas = createCanvas(100, 100);
     *   const body = document.getElementsByTagName('body')[0];
     *   myCanvas.parent(body);
     * }
     *
     * function draw() {
     *   background(237, 34, 93);
     *   fill(0);
     *
     *   //move the canvas to the horizontal mouse position
     *   //relative to the window
     *   myCanvas.position(winMouseX + 1, windowHeight / 2);
     *
     *   //the y of the square is relative to the canvas
     *   rect(20, mouseY, 60, 60);
     * }
     */
    exports.winMouseX = 0;

    /**
     * The system variable winMouseY always contains the current vertical
     * position of the mouse, relative to (0, 0) of the window.
     *
     * @property {Number} winMouseY
     * @readOnly
     *
     * @example
     * let myCanvas;
     *
     * function setup() {
     *   //use a variable to store a pointer to the canvas
     *   myCanvas = createCanvas(100, 100);
     *   const body = document.getElementsByTagName('body')[0];
     *   myCanvas.parent(body);
     * }
     *
     * function draw() {
     *   background(237, 34, 93);
     *   fill(0);
     *
     *   //move the canvas to the vertical mouse position
     *   //relative to the window
     *   myCanvas.position(windowWidth / 2, winMouseY + 1);
     *
     *   //the x of the square is relative to the canvas
     *   rect(mouseX, 20, 60, 60);
     * }
     */
    exports.winMouseY = 0;

    /**
     * The system variable pwinMouseX always contains the horizontal position
     * of the mouse in the frame previous to the current frame, relative to
     * (0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX
     * value at the start of each touch event.
     *
     * @property {Number} pwinMouseX
     * @readOnly
     *
     * @example
     * let myCanvas;
     *
     * function setup() {
     *   //use a variable to store a pointer to the canvas
     *   myCanvas = createCanvas(100, 100);
     *   noStroke();
     *   fill(237, 34, 93);
     * }
     *
     * function draw() {
     *   clear();
     *   //the difference between previous and
     *   //current x position is the horizontal mouse speed
     *   let speed = abs(winMouseX - pwinMouseX);
     *   //change the size of the circle
     *   //according to the horizontal speed
     *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
     *   //move the canvas to the mouse position
     *   myCanvas.position(winMouseX + 1, winMouseY + 1);
     * }
     */
    exports.pwinMouseX = 0;

    /**
     * The system variable pwinMouseY always contains the vertical position of
     * the mouse in the frame previous to the current frame, relative to (0, 0)
     * of the window. Note: pwinMouseY will be reset to the current winMouseY
     * value at the start of each touch event.
     *
     * @property {Number} pwinMouseY
     * @readOnly
     *
     *
     * @example
     * let myCanvas;
     *
     * function setup() {
     *   //use a variable to store a pointer to the canvas
     *   myCanvas = createCanvas(100, 100);
     *   noStroke();
     *   fill(237, 34, 93);
     * }
     *
     * function draw() {
     *   clear();
     *   //the difference between previous and
     *   //current y position is the vertical mouse speed
     *   let speed = abs(winMouseY - pwinMouseY);
     *   //change the size of the circle
     *   //according to the vertical speed
     *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
     *   //move the canvas to the mouse position
     *   myCanvas.position(winMouseX + 1, winMouseY + 1);
     * }
     */
    exports.pwinMouseY = 0;

    /**
     * Processing automatically tracks if the mouse button is pressed and which
     * button is pressed. The value of the system variable mouseButton is either
     * LEFT, RIGHT, or CENTER depending on which button was pressed last.
     * Warning: different browsers may track mouseButton differently.
     *
     * @property {Constant} mouseButton
     * @readOnly
     *
     * @example
     * function draw() {
     *   background(237, 34, 93);
     *   fill(0);
     *
     *   if (mouseIsPressed) {
     *     if (mouseButton === LEFT) {
     *       ellipse(50, 50, 50, 50);
     *     }
     *     if (mouseButton === RIGHT) {
     *       rect(25, 25, 50, 50);
     *     }
     *     if (mouseButton === CENTER) {
     *       triangle(23, 75, 50, 20, 78, 75);
     *     }
     *   }
     *
     *   print(mouseButton);
     * }
     */
    exports.mouseButton = 0;

    /**
     * The boolean system variable mouseIsPressed is true if the mouse is pressed
     * and false if not.
     *
     * @property {Boolean} mouseIsPressed
     * @readOnly
     *
     * @example
     * function draw() {
     *   background(237, 34, 93);
     *   fill(0);
     *
     *   if (mouseIsPressed) {
     *     ellipse(50, 50, 50, 50);
     *   } else {
     *     rect(25, 25, 50, 50);
     *   }
     *
     *   print(mouseIsPressed);
     * }
     */
    exports.mouseIsPressed = false;

    /**
     * The >mouseMoved() function is called every time the mouse moves and a mouse
     * button is not pressed.<br><br>
     * Browsers may have different default
     * behaviors attached to various mouse events. To prevent any default
     * behavior for this event, add "return false" to the end of the method.
     *
     * @method mouseMoved
     * @param  {Object} [event] optional MouseEvent callback argument.
     * @example
     * // Move the mouse across the page
     * // to change its value
     *
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     * function mouseMoved() {
     *   value = value + 5;
     *   if (value > 255) {
     *     value = 0;
     *   }
     * }
     *
     * function mouseMoved() {
     *   ellipse(mouseX, mouseY, 5, 5);
     *   // prevent default
     *   return false;
     * }
     *
     * // returns a MouseEvent object
     * // as a callback argument
     * function mouseMoved(event) {
     *   console.log(event);
     * }
     */

    /**
     * The mousePressed() function is called once after every time a mouse button
     * is pressed. The mouseButton variable (see the related reference entry)
     * can be used to determine which button has been pressed.<br><br>
     * Browsers may have different default
     * behaviors attached to various mouse events. To prevent any default
     * behavior for this event, add "return false" to the end of the method.
     *
     * @method mousePressed
     * @param  {Object} [event] optional MouseEvent callback argument.
     * @example
     * // Click within the image to change
     * // the value of the rectangle
     *
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     * function mousePressed() {
     *   if (value === 0) {
     *     value = 255;
     *   } else {
     *     value = 0;
     *   }
     * }
     *
     * function mousePressed() {
     *   ellipse(mouseX, mouseY, 5, 5);
     *   // prevent default
     *   return false;
     * }
     *
     * // returns a MouseEvent object
     * // as a callback argument
     * function mousePressed(event) {
     *   console.log(event);
     * }
     */

    /**
    * The mouseReleased() function is called every time a mouse button is
    * released. <br><br>
    * Browsers may have different default
    * behaviors attached to various mouse events. To prevent any default
    * behavior for this event, add "return false" to the end of the method.
    *
    *
    * @method mouseReleased
    * @param  {Object} [event] optional MouseEvent callback argument.
    * @example
    * // Click within the image to change
    * // the value of the rectangle
    * // after the mouse has been clicked
    *
    * let value = 0;
    * function draw() {
    *   fill(value);
    *   rect(25, 25, 50, 50);
    * }
    * function mouseReleased() {
    *   if (value === 0) {
    *     value = 255;
    *   } else {
    *     value = 0;
    *   }
    * }
    *
    * function mouseReleased() {
    *   ellipse(mouseX, mouseY, 5, 5);
    *   // prevent default
    *   return false;
    * }
    *
    * // returns a MouseEvent object
    * // as a callback argument
    * function mouseReleased(event) {
    *   console.log(event);
    * }
    */

    /**
     * The mouseClicked() function is called once after a mouse button has been
     * pressed and then released.<br><br>
     * Browsers handle clicks differently, so this function is only guaranteed to be
     * run when the left mouse button is clicked. To handle other mouse buttons
     * being pressed or released, see mousePressed() or mouseReleased().<br><br>
     * Browsers may have different default
     * behaviors attached to various mouse events. To prevent any default
     * behavior for this event, add "return false" to the end of the method.
     *
     * @method mouseClicked
     * @param  {Object} [event] optional MouseEvent callback argument.
     * @example
     * // Click within the image to change
     * // the value of the rectangle
     * // after the mouse has been clicked
     *
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     *
     * function mouseClicked() {
     *   if (value === 0) {
     *     value = 255;
     *   } else {
     *     value = 0;
     *   }
     * }
     *
     * function mouseClicked() {
     *   ellipse(mouseX, mouseY, 5, 5);
     *   // prevent default
     *   return false;
     * }
     *
     * // returns a MouseEvent object
     * // as a callback argument
     * function mouseClicked(event) {
     *   console.log(event);
     * }
     */

    /**********************************************************************************************************************
     * keyboard
     */

    /**
     * The boolean system variable keyIsPressed is true if any key is pressed
     * and false if no keys are pressed.
     *
     * @property {Boolean} keyIsPressed
     * @readOnly
     * @example
     * function draw() {
     *   if (keyIsPressed === true) {
     *     fill(0);
     *   } else {
     *     fill(255);
     *   }
     *   rect(25, 25, 50, 50);
     * }
     */
    exports.keyIsPressed = false;

    /**
     * The system variable key always contains the value of the most recent
     * key on the keyboard that was typed.
     *
     * @property {String} key
     * @readOnly
     * @example
     * // Click any key to display it!
     * // (Not Guaranteed to be Case Sensitive)
     * function setup() {
     *   fill(245, 123, 158);
     *   textSize(50);
     * }
     *
     * function draw() {
     *   background(200);
     *   text(key, 33, 65); // Display last key pressed.
     * }
     */
    exports.key = null;

    /**
     * The variable keyCode is used to detect special keys such as BACKSPACE,
     * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,
     * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
     *
     * @property {Integer} keyCode
     * @readOnly
     * @example
     * let fillVal = 126;
     * function draw() {
     *   fill(fillVal);
     *   rect(25, 25, 50, 50);
     * }
     *
     * function keyPressed() {
     *   if (keyCode === UP_ARROW) {
     *     fillVal = 255;
     *   } else if (keyCode === DOWN_ARROW) {
     *     fillVal = 0;
     *   }
     *   return false; // prevent default
     * }
     */
    exports.keyCode = null;

    /**
     * The keyPressed() function is called once every time a key is pressed. The
     * keyCode for the key that was pressed is stored in the keyCode variable.
     * <br><br>
     *
     * @method keyPressed
     * @example
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     * function keyPressed() {
     *   if (value === 0) {
     *     value = 255;
     *   } else {
     *     value = 0;
     *   }
     * }
     *
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     * function keyPressed() {
     *   if (keyCode === LEFT_ARROW) {
     *     value = 255;
     *   } else if (keyCode === RIGHT_ARROW) {
     *     value = 0;
     *   }
     * }
     */

    /**
    * The keyReleased() function is called once every time a key is released.
    * See key and keyCode for more information.<br><br>
    * Browsers may have different default
    * behaviors attached to various key events. To prevent any default
    * behavior for this event, add "return false" to the end of the method.
    *
    * @method keyReleased
    * @example
    * let value = 0;
    * function draw() {
    *   fill(value);
    *   rect(25, 25, 50, 50);
    * }
    * function keyReleased() {
    *   if (value === 0) {
    *     value = 255;
    *   } else {
    *     value = 0;
    *   }
    *   return false; // prevent any default behavior
    * }
    */

    /**
     * The keyTyped() function is called once every time a key is pressed, but
     * action keys such as Ctrl, Shift, and Alt are ignored. The most recent
     * key pressed will be stored in the key variable.
     * <br><br>
     * Because of how operating systems handle key repeats, holding down a key
     * will cause multiple calls to keyTyped() (and keyReleased() as well). The
     * rate of repeat is set by the operating system and how each computer is
     * configured.<br><br>
     * Browsers may have different default behaviors attached to various key
     * events. To prevent any default behavior for this event, add "return false"
     * to the end of the method.
     *
     * @method keyTyped
     * @example
     * let value = 0;
     * function draw() {
     *   fill(value);
     *   rect(25, 25, 50, 50);
     * }
     * function keyTyped() {
     *   if (key === 'a') {
     *     value = 255;
     *   } else if (key === 'b') {
     *     value = 0;
     *   }
     *   // uncomment to prevent any default behavior
     *   // return false;
     * }
     */