From f8a2782f3a849b1e04dae803064456e45746228d Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Sun, 17 Nov 2024 23:54:14 +0530 Subject: [PATCH 01/11] Replaced mouse with pointer handlers --- src/events/mouse.js | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/events/mouse.js b/src/events/mouse.js index 6e9f4a661e..58404fd79b 100644 --- a/src/events/mouse.js +++ b/src/events/mouse.js @@ -1054,7 +1054,7 @@ function mouse(p5, fn){ * * */ - fn._onmousemove = function(e) { + fn._onpointermove = function(e) { const context = this._isGlobal ? window : this; let executeDefault; this._updateNextMouseCoords(e); @@ -1225,18 +1225,13 @@ function mouse(p5, fn){ * * */ - fn._onmousedown = function(e) { + fn._onpointerdown = function(e) { const context = this._isGlobal ? window : this; let executeDefault; this.mouseIsPressed = true; this._setMouseButton(e); this._updateNextMouseCoords(e); - // _ontouchstart triggers first and sets this._touchstart - if (this._touchstart) { - return; - } - if (typeof context.mousePressed === 'function') { executeDefault = context.mousePressed(e); if (executeDefault === false) { @@ -1248,8 +1243,6 @@ function mouse(p5, fn){ e.preventDefault(); } } - - this._touchstart = false; }; /** @@ -1398,16 +1391,11 @@ function mouse(p5, fn){ * * */ - fn._onmouseup = function(e) { + fn._onpointerup = function(e) { const context = this._isGlobal ? window : this; let executeDefault; this.mouseIsPressed = false; - // _ontouchend triggers first and sets this._touchend - if (this._touchend) { - return; - } - if (typeof context.mouseReleased === 'function') { executeDefault = context.mouseReleased(e); if (executeDefault === false) { @@ -1419,11 +1407,10 @@ function mouse(p5, fn){ e.preventDefault(); } } - this._touchend = false; }; - fn._ondragend = fn._onmouseup; - fn._ondragover = fn._onmousemove; + fn._ondragend = fn._onpointerup; + fn._ondragover = fn._onpointermove; /** * A function that's called once after a mouse button is pressed and released. From 1a46f540356995ca75fa5946e688920150bbe115 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Sun, 17 Nov 2024 23:54:58 +0530 Subject: [PATCH 02/11] Registering events --- src/core/main.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/main.js b/src/core/main.js index 6914a754da..0e2492a158 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -62,6 +62,10 @@ class p5 { mousemove: null, mousedown: null, mouseup: null, + pointerdown: null, + pointerup: null, + pointermove: null, + pointercancle:null, dragend: null, dragover: null, click: null, @@ -238,6 +242,7 @@ class p5 { k.style.visibility = ''; delete k.dataset.hidden; } + k.style.touchAction = 'none'; } this._lastTargetFrameTime = window.performance.now(); From c6d40b8141057ca3f8b4073e44c39911951f1de9 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Mon, 18 Nov 2024 00:25:23 +0530 Subject: [PATCH 03/11] updated tests --- test/unit/events/mouse.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/unit/events/mouse.js b/test/unit/events/mouse.js index e17e7fef77..aefe2822c7 100644 --- a/test/unit/events/mouse.js +++ b/test/unit/events/mouse.js @@ -47,8 +47,8 @@ suite('Mouse Events', function() { myp5.remove(); }); - let mouseEvent1 = new MouseEvent('mousemove', { clientX: 100, clientY: 100 }); - let mouseEvent2 = new MouseEvent('mousemove', { clientX: 200, clientY: 200 }); + let mouseEvent1 = new PointerEvent('pointermove', { clientX: 100, clientY: 100 }); + let mouseEvent2 = new PointerEvent('pointermove', { clientX: 200, clientY: 200 }); suite('p5.prototype._hasMouseInteracted', function() { test('_hasMouseInteracted should be a boolean', function() { @@ -223,17 +223,17 @@ suite('Mouse Events', function() { }); test('mouseButton should be "left" on left mouse button click', function() { - window.dispatchEvent(new MouseEvent('mousedown', { button: 0 })); + window.dispatchEvent(new PointerEvent('pointerdown', { button: 0 })); assert.strictEqual(myp5.mouseButton, 'left'); }); test('mouseButton should be "center" on auxillary mouse button click', function() { - window.dispatchEvent(new MouseEvent('mousedown', { button: 1 })); + window.dispatchEvent(new PointerEvent('pointerdown', { button: 1 })); assert.strictEqual(myp5.mouseButton, 'center'); }); test('mouseButton should be "right" on right mouse button click', function() { - window.dispatchEvent(new MouseEvent('mousedown', { button: 2 })); + window.dispatchEvent(new PointerEvent('pointerdown', { button: 2 })); assert.strictEqual(myp5.mouseButton, 'right'); }); }); @@ -280,7 +280,7 @@ suite('Mouse Events', function() { }; let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new MouseEvent('mousemove')); //dispatch a mouse event to trigger the mouseMoved functions + window.dispatchEvent(new PointerEvent('pointermove')); //dispatch a mouse event to trigger the mouseMoved functions sketches.end(); //resolve all sketches by calling their finish functions let counts = await sketches.result; //get array holding number of times mouseMoved was called. Rejected sketches also thrown here assert.deepEqual(counts, [1, 1]); @@ -295,8 +295,8 @@ suite('Mouse Events', function() { count += 1; }; - window.dispatchEvent(new MouseEvent('mousedown')); //dispatch a mousedown event - window.dispatchEvent(new MouseEvent('mousemove')); //dispatch mousemove event while mouse is down to trigger mouseDragged + window.dispatchEvent(new PointerEvent('pointerdown')); //dispatch a mousedown event + window.dispatchEvent(new PointerEvent('pointermove')); //dispatch mousemove event while mouse is down to trigger mouseDragged assert.deepEqual(count, 1); }); @@ -314,8 +314,8 @@ suite('Mouse Events', function() { }; let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new MouseEvent('mousedown')); //dispatch a mousedown event - window.dispatchEvent(new MouseEvent('mousemove')); //dispatch mousemove event while mouse is down to trigger mouseDragged + window.dispatchEvent(new PointerEvent('pointerdown')); //dispatch a mousedown event + window.dispatchEvent(new PointerEvent('pointermove')); //dispatch mousemove event while mouse is down to trigger mouseDragged sketches.end(); //resolve all sketches by calling their finish functions let counts = await sketches.result; //get array holding number of times mouseDragged was called. Rejected sketches also thrown here assert.deepEqual(counts, [1, 1]); @@ -330,7 +330,7 @@ suite('Mouse Events', function() { count += 1; }; - window.dispatchEvent(new MouseEvent('mousedown')); + window.dispatchEvent(new PointerEvent('pointerdown')); assert.deepEqual(count, 1); }); @@ -348,7 +348,7 @@ suite('Mouse Events', function() { }; let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new MouseEvent('mousedown')); + window.dispatchEvent(new PointerEvent('pointerdown')); sketches.end(); //resolve all sketches by calling their finish functions let counts = await sketches.result; //get array holding number of times mouseDragged was called. Rejected sketches also thrown here assert.deepEqual(counts, [1, 1]); @@ -363,7 +363,7 @@ suite('Mouse Events', function() { count += 1; }; - window.dispatchEvent(new MouseEvent('mouseup')); + window.dispatchEvent(new PointerEvent('pointerup')); assert.deepEqual(count, 1); }); @@ -381,7 +381,7 @@ suite('Mouse Events', function() { }; let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new MouseEvent('mouseup')); + window.dispatchEvent(new PointerEvent('pointerup')); sketches.end(); //resolve all sketches by calling their finish functions let counts = await sketches.result; //get array holding number of times mouseReleased was called. Rejected sketches also thrown here assert.deepEqual(counts, [1, 1]); From b6c096781c6fced724afed0f971a9c97b6fdb4f8 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Tue, 19 Nov 2024 00:10:18 +0530 Subject: [PATCH 04/11] Removed touchStarted/Ended --- src/core/main.js | 2 +- src/events/mouse.js | 39 +-- src/events/touch.js | 489 +------------------------------------- test/unit/events/touch.js | 124 ---------- 4 files changed, 8 insertions(+), 646 deletions(-) diff --git a/src/core/main.js b/src/core/main.js index 0e2492a158..c0c9948e07 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -65,7 +65,7 @@ class p5 { pointerdown: null, pointerup: null, pointermove: null, - pointercancle:null, + pointercancel:null, dragend: null, dragover: null, click: null, diff --git a/src/events/mouse.js b/src/events/mouse.js index 58404fd79b..a000448461 100644 --- a/src/events/mouse.js +++ b/src/events/mouse.js @@ -1004,10 +1004,7 @@ function mouse(p5, fn){ * ``` * * On touchscreen devices, `mouseDragged()` will run when a user moves a touch - * point if touchMoved() isn’t declared. If - * touchMoved() is declared, then - * touchMoved() will run when a user moves a - * touch point and `mouseDragged()` won’t. + * point. * * Browsers may have default behaviors attached to various mouse events. For * example, some browsers highlight text when the user moves the mouse while @@ -1071,12 +1068,7 @@ function mouse(p5, fn){ if (executeDefault === false) { e.preventDefault(); } - } else if (typeof context.touchMoved === 'function') { - executeDefault = context.touchMoved(e); - if (executeDefault === false) { - e.preventDefault(); - } - } + } } }; @@ -1120,10 +1112,7 @@ function mouse(p5, fn){ * ``` * * On touchscreen devices, `mousePressed()` will run when a user’s touch - * begins if touchStarted() isn’t declared. If - * touchStarted() is declared, then - * touchStarted() will run when a user’s touch - * begins and `mousePressed()` won’t. + * begins. * * Browsers may have default behaviors attached to various mouse events. For * example, some browsers highlight text when the user moves the mouse while @@ -1237,12 +1226,7 @@ function mouse(p5, fn){ if (executeDefault === false) { e.preventDefault(); } - } else if (typeof context.touchStarted === 'function') { - executeDefault = context.touchStarted(e); - if (executeDefault === false) { - e.preventDefault(); - } - } + } }; /** @@ -1286,10 +1270,7 @@ function mouse(p5, fn){ * ``` * * On touchscreen devices, `mouseReleased()` will run when a user’s touch - * ends if touchEnded() isn’t declared. If - * touchEnded() is declared, then - * touchEnded() will run when a user’s touch - * ends and `mouseReleased()` won’t. + * ends. * * Browsers may have default behaviors attached to various mouse events. For * example, some browsers highlight text when the user moves the mouse while @@ -1401,11 +1382,6 @@ function mouse(p5, fn){ if (executeDefault === false) { e.preventDefault(); } - } else if (typeof context.touchEnded === 'function') { - executeDefault = context.touchEnded(e); - if (executeDefault === false) { - e.preventDefault(); - } } }; @@ -1453,10 +1429,7 @@ function mouse(p5, fn){ * ``` * * On touchscreen devices, `mouseClicked()` will run when a user’s touch - * ends if touchEnded() isn’t declared. If - * touchEnded() is declared, then - * touchEnded() will run when a user’s touch - * ends and `mouseClicked()` won’t. + * ends. * * Browsers may have default behaviors attached to various mouse events. For * example, some browsers highlight text when the user moves the mouse while diff --git a/src/events/touch.js b/src/events/touch.js index 9a9254a511..4d21696377 100644 --- a/src/events/touch.js +++ b/src/events/touch.js @@ -120,343 +120,19 @@ function touch(p5, fn){ id: touch.identifier }; } - - /** - * A function that's called once each time the user touches the screen. - * - * Declaring a function called `touchStarted()` sets a code block to run - * automatically each time the user begins touching a touchscreen device: - * - * ```js - * function touchStarted() { - * // Code to run. - * } - * ``` - * - * The touches array will be updated with the most - * recent touch points when `touchStarted()` is called by p5.js: - * - * ```js - * function touchStarted() { - * // Paint over the background. - * background(200); - * - * // Mark each touch point once with a circle. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * ``` - * - * The parameter, event, is optional. `touchStarted()` will be passed a - * TouchEvent - * object with properties that describe the touch event: - * - * ```js - * function touchStarted(event) { - * // Code to run that uses the event. - * console.log(event); - * } - * ``` - * - * On touchscreen devices, mousePressed() will - * run when a user’s touch starts if `touchStarted()` isn’t declared. If - * `touchStarted()` is declared, then `touchStarted()` will run when a user’s - * touch starts and mousePressed() won’t. - * - * Note: `touchStarted()`, touchEnded(), and - * touchMoved() are all related. - * `touchStarted()` runs as soon as the user touches a touchscreen device. - * touchEnded() runs as soon as the user ends a - * touch. touchMoved() runs repeatedly as the - * user moves any touch points. - * - * @method touchStarted - * @param {TouchEvent} [event] optional `TouchEvent` argument. - * - * @example - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let value = 0; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with a black square at its center. The inner square switches color between black and white each time the user touches the screen.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Style the square. - * fill(value); - * - * // Draw the square. - * square(25, 25, 50); - * } - * - * // Toggle colors with each touch. - * function touchStarted() { - * if (value === 0) { - * value = 255; - * } else { - * value = 0; - * } - * } - * - *
- * - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let bgColor = 50; - * let fillColor = 255; - * let borderWidth = 0.5; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' - * ); - * } - * - * function draw() { - * background(bgColor); - * - * // Style the text. - * textAlign(CENTER); - * textSize(16); - * fill(0); - * noStroke(); - * - * // Display the number of touch points. - * text(touches.length, 50, 20); - * - * // Style the touch points. - * fill(fillColor); - * stroke(0); - * strokeWeight(borderWidth); - * - * // Display the touch points as circles. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * - * // Set the background color to a random grayscale value. - * function touchStarted() { - * bgColor = random(80, 255); - * } - * - * // Set the fill color to a random grayscale value. - * function touchEnded() { - * fillColor = random(0, 255); - * } - * - * // Set the stroke weight. - * function touchMoved() { - * // Increment the border width. - * borderWidth += 0.1; - * - * // Reset the border width once it's too thick. - * if (borderWidth > 20) { - * borderWidth = 0.5; - * } - * } - * - *
- */ fn._ontouchstart = function(e) { - const context = this._isGlobal ? window : this; - let executeDefault; this.mouseIsPressed = true; this._updateTouchCoords(e); this._updateNextMouseCoords(e); this._updateMouseCoords(); // reset pmouseXY at the start of each touch event - - if (typeof context.touchStarted === 'function') { - executeDefault = context.touchStarted(e); - if (executeDefault === false) { - e.preventDefault(); - } - this._touchstart = true; - } }; - /** - * A function that's called when the user touches the screen and moves. - * - * Declaring the function `touchMoved()` sets a code block to run - * automatically when the user touches a touchscreen device and moves: - * - * ```js - * function touchMoved() { - * // Code to run. - * } - * ``` - * - * The touches array will be updated with the most - * recent touch points when `touchMoved()` is called by p5.js: - * - * ```js - * function touchMoved() { - * // Paint over the background. - * background(200); - * - * // Mark each touch point while the user moves. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * ``` - * - * The parameter, event, is optional. `touchMoved()` will be passed a - * TouchEvent - * object with properties that describe the touch event: - * - * ```js - * function touchMoved(event) { - * // Code to run that uses the event. - * console.log(event); - * } - * ``` - * - * On touchscreen devices, mouseDragged() will - * run when the user’s touch points move if `touchMoved()` isn’t declared. If - * `touchMoved()` is declared, then `touchMoved()` will run when a user’s - * touch points move and mouseDragged() won’t. - * - * Note: touchStarted(), - * touchEnded(), and - * `touchMoved()` are all related. - * touchStarted() runs as soon as the user - * touches a touchscreen device. touchEnded() - * runs as soon as the user ends a touch. `touchMoved()` runs repeatedly as - * the user moves any touch points. - * - * @method touchMoved - * @param {TouchEvent} [event] optional TouchEvent argument. - * - * @example - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let value = 0; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with a black square at its center. The inner square becomes lighter when the user touches the screen and moves.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Style the square. - * fill(value); - * - * // Draw the square. - * square(25, 25, 50); - * } - * - * function touchMoved() { - * // Update the grayscale value. - * value += 5; - * - * // Reset the grayscale value. - * if (value > 255) { - * value = 0; - * } - * } - * - *
- * - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let bgColor = 50; - * let fillColor = 255; - * let borderWidth = 0.5; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' - * ); - * } - * - * function draw() { - * background(bgColor); - * - * // Style the text. - * textAlign(CENTER); - * textSize(16); - * fill(0); - * noStroke(); - * - * // Display the number of touch points. - * text(touches.length, 50, 20); - * - * // Style the touch points. - * fill(fillColor); - * stroke(0); - * strokeWeight(borderWidth); - * - * // Display the touch points as circles. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * - * // Set the background color to a random grayscale value. - * function touchStarted() { - * bgColor = random(80, 255); - * } - * - * // Set the fill color to a random grayscale value. - * function touchEnded() { - * fillColor = random(0, 255); - * } - * - * // Set the stroke weight. - * function touchMoved() { - * // Increment the border width. - * borderWidth += 0.1; - * - * // Reset the border width once it's too thick. - * if (borderWidth > 20) { - * borderWidth = 0.5; - * } - * } - * - *
- */ fn._ontouchmove = function(e) { const context = this._isGlobal ? window : this; let executeDefault; this._updateTouchCoords(e); this._updateNextMouseCoords(e); - if (typeof context.touchMoved === 'function') { - executeDefault = context.touchMoved(e); - if (executeDefault === false) { - e.preventDefault(); - } - } else if (typeof context.mouseDragged === 'function') { + if (typeof context.mouseDragged === 'function') { executeDefault = context.mouseDragged(e); if (executeDefault === false) { e.preventDefault(); @@ -464,173 +140,10 @@ function touch(p5, fn){ } }; - /** - * A function that's called once each time a screen touch ends. - * - * Declaring the function `touchEnded()` sets a code block to run - * automatically when the user stops touching a touchscreen device: - * - * ```js - * function touchEnded() { - * // Code to run. - * } - * ``` - * - * The touches array will be updated with the most - * recent touch points when `touchEnded()` is called by p5.js: - * - * ```js - * function touchEnded() { - * // Paint over the background. - * background(200); - * - * // Mark each remaining touch point when the user stops - * // a touch. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * ``` - * - * The parameter, event, is optional. `touchEnded()` will be passed a - * TouchEvent - * object with properties that describe the touch event: - * - * ```js - * function touchEnded(event) { - * // Code to run that uses the event. - * console.log(event); - * } - * ``` - * - * On touchscreen devices, mouseReleased() will - * run when the user’s touch ends if `touchEnded()` isn’t declared. If - * `touchEnded()` is declared, then `touchEnded()` will run when a user’s - * touch ends and mouseReleased() won’t. - * - * Note: touchStarted(), - * `touchEnded()`, and touchMoved() are all - * related. touchStarted() runs as soon as the - * user touches a touchscreen device. `touchEnded()` runs as soon as the user - * ends a touch. touchMoved() runs repeatedly as - * the user moves any touch points. - * - * @method touchEnded - * @param {TouchEvent} [event] optional `TouchEvent` argument. - * - * @example - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let value = 0; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with a black square at its center. The inner square switches color between black and white each time the user stops touching the screen.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Style the square. - * fill(value); - * - * // Draw the square. - * square(25, 25, 50); - * } - * - * // Toggle colors when a touch ends. - * function touchEnded() { - * if (value === 0) { - * value = 255; - * } else { - * value = 0; - * } - * } - * - *
- * - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * let bgColor = 50; - * let fillColor = 255; - * let borderWidth = 0.5; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' - * ); - * } - * - * function draw() { - * background(bgColor); - * - * // Style the text. - * textAlign(CENTER); - * textSize(16); - * fill(0); - * noStroke(); - * - * // Display the number of touch points. - * text(touches.length, 50, 20); - * - * // Style the touch points. - * fill(fillColor); - * stroke(0); - * strokeWeight(borderWidth); - * - * // Display the touch points as circles. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * - * // Set the background color to a random grayscale value. - * function touchStarted() { - * bgColor = random(80, 255); - * } - * - * // Set the fill color to a random grayscale value. - * function touchEnded() { - * fillColor = random(0, 255); - * } - * - * // Set the stroke weight. - * function touchMoved() { - * // Increment the border width. - * borderWidth += 0.1; - * - * // Reset the border width once it's too thick. - * if (borderWidth > 20) { - * borderWidth = 0.5; - * } - * } - * - *
- */ fn._ontouchend = function(e) { this.mouseIsPressed = false; this._updateTouchCoords(e); this._updateNextMouseCoords(e); - const context = this._isGlobal ? window : this; - let executeDefault; - if (typeof context.touchEnded === 'function') { - executeDefault = context.touchEnded(e); - if (executeDefault === false) { - e.preventDefault(); - } - this._touchend = true; - } }; } diff --git a/test/unit/events/touch.js b/test/unit/events/touch.js index 72d3dd20c6..d7d5f12b9b 100644 --- a/test/unit/events/touch.js +++ b/test/unit/events/touch.js @@ -56,128 +56,4 @@ suite('Touch Events', function() { assert.strictEqual(myp5.touches[0].id, 35); }); }); - - suite('touchStarted', function() { - test('touchStarted should be fired when a touch is registered', function() { - let count = 0; - myp5.touchStarted = function() { - count += 1; - }; - window.dispatchEvent(new TouchEvent('touchstart')); - assert.strictEqual(count, 1); - }); - - test('should be fired when a touch starts over the element', function() { - let count = 0; - let div = myp5.createDiv(); - let divTouchStarted = function() { - count += 1; - }; - div.touchStarted(divTouchStarted); - div.elt.dispatchEvent(new TouchEvent('touchstart')); - assert.strictEqual(count, 1); - }); - - // NOTE: Required review of parallel sketches test method - test('touchStarted functions on multiple instances must run once', async function() { - let sketchFn = function(sketch, resolve, reject) { - let count = 0; - sketch.touchStarted = function() { - count += 1; - }; - - sketch.finish = function() { - resolve(count); - }; - }; - let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches - await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new TouchEvent('touchstart')); - sketches.end(); //resolve all sketches by calling their finish functions - let counts = await sketches.result; - assert.deepEqual(counts, [1, 1]); - }); - }); - - suite('touchMoved', function() { - test('touchMoved should be fired when a touchmove is registered', function() { - let count = 0; - myp5.touchMoved = function() { - count += 1; - }; - window.dispatchEvent(touchEvent2); - assert.strictEqual(count, 1); - }); - - test('should be fired when a touchmove is registered over the element', function() { - let count = 0; - let div = myp5.createDiv(); - let divTouchMoved = function() { - count += 1; - }; - div.touchMoved(divTouchMoved); - div.elt.dispatchEvent(touchEvent2); - assert.strictEqual(count, 1); - }); - - test('touchMoved functions on multiple instances must run once', async function() { - let sketchFn = function(sketch, resolve, reject) { - let count = 0; - sketch.touchMoved = function() { - count += 1; - }; - - sketch.finish = function() { - resolve(count); - }; - }; - let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches - await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(touchEvent2); - sketches.end(); //resolve all sketches by calling their finish functions - let counts = await sketches.result; - assert.deepEqual(counts, [1, 1]); - }); - }); - - suite('touchEnded', function() { - test('touchEnded must run when a touch is registered', function() { - let count = 0; - myp5.touchEnded = function() { - count += 1; - }; - window.dispatchEvent(new TouchEvent('touchend')); - assert.strictEqual(count, 1); - }); - - test('should be fired when a touch starts over the element', function() { - let count = 0; - let div = myp5.createDiv(); - let divTouchEnded = function() { - count += 1; - }; - div.touchEnded(divTouchEnded); - div.elt.dispatchEvent(new TouchEvent('touchend')); - assert.strictEqual(count, 1); - }); - - test('touchEnded functions on multiple instances must run once', async function() { - let sketchFn = function(sketch, resolve, reject) { - let count = 0; - sketch.touchEnded = function() { - count += 1; - }; - - sketch.finish = function() { - resolve(count); - }; - }; - let sketches = parallelSketches([sketchFn, sketchFn]); //create two sketches - await sketches.setup; //wait for all sketches to setup - window.dispatchEvent(new TouchEvent('touchend')); - sketches.end(); //resolve all sketches by calling their finish functions - let counts = await sketches.result; - assert.deepEqual(counts, [1, 1]); - }); - }); }); From 6f3603747c46c002d78582213eb858c08ea1e512 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Tue, 19 Nov 2024 19:42:19 +0530 Subject: [PATCH 05/11] cleanup --- src/core/main.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/core/main.js b/src/core/main.js index c0c9948e07..90acb5096f 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -59,13 +59,9 @@ class p5 { this._initializeInstanceVariables(); this._events = { // keep track of user-events for unregistering later - mousemove: null, - mousedown: null, - mouseup: null, pointerdown: null, pointerup: null, pointermove: null, - pointercancel:null, dragend: null, dragover: null, click: null, @@ -84,8 +80,6 @@ class p5 { }; this._millisStart = -1; this._recording = false; - this._touchstart = false; - this._touchend = false; // States used in the custom random generators this._lcg_random_state = null; // NOTE: move to random.js From 946cb8c2766bc7bf5d0ce26d7a42365cdc3ed50b Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Thu, 21 Nov 2024 18:35:20 +0530 Subject: [PATCH 06/11] added pointer events for mouse and touch --- src/events/index.js | 6 +- src/events/{mouse.js => pointer.js} | 205 +++++++++++++++++++++------- src/events/touch.js | 154 --------------------- 3 files changed, 156 insertions(+), 209 deletions(-) rename src/events/{mouse.js => pointer.js} (92%) delete mode 100644 src/events/touch.js diff --git a/src/events/index.js b/src/events/index.js index 773424d42b..447f3d0d10 100644 --- a/src/events/index.js +++ b/src/events/index.js @@ -1,11 +1,9 @@ import acceleration from './acceleration.js'; import keyboard from './keyboard.js'; -import mouse from './mouse.js'; -import touch from './touch.js'; +import pointer from './pointer.js'; export default function(p5){ p5.registerAddon(acceleration); p5.registerAddon(keyboard); - p5.registerAddon(mouse); - p5.registerAddon(touch); + p5.registerAddon(pointer); } diff --git a/src/events/mouse.js b/src/events/pointer.js similarity index 92% rename from src/events/mouse.js rename to src/events/pointer.js index a000448461..48fad5c280 100644 --- a/src/events/mouse.js +++ b/src/events/pointer.js @@ -1,6 +1,6 @@ /** * @module Events - * @submodule Mouse + * @submodule Pointer * @for p5 * @requires core * @requires constants @@ -8,7 +8,7 @@ import * as constants from '../core/constants'; -function mouse(p5, fn){ +function pointer(p5, fn){ /** * A `Number` system variable that tracks the mouse's horizontal movement. * @@ -758,6 +758,92 @@ function mouse(p5, fn){ */ fn.mouseButton = 0; + /** + * An `Array` of all the current touch points on a touchscreen device. + * + * The `touches` array is empty by default. When the user touches their + * screen, a new touch point is tracked and added to the array. Touch points + * are `Objects` with the following properties: + * + * ```js + * // Iterate over the touches array. + * for (let touch of touches) { + * // x-coordinate relative to the top-left + * // corner of the canvas. + * console.log(touch.x); + * + * // y-coordinate relative to the top-left + * // corner of the canvas. + * console.log(touch.y); + * + * // x-coordinate relative to the top-left + * // corner of the browser. + * console.log(touch.winX); + * + * // y-coordinate relative to the top-left + * // corner of the browser. + * console.log(touch.winY); + * + * // ID number + * console.log(touch.id); + * } + * ``` + * + * @property {Object[]} touches + * @readOnly + * + * @example + *
+ * + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. White circles appear where the user touches the square.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a circle at each touch point. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * + *
+ * + *
+ * + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. Labels appear where the user touches the square, displaying the coordinates.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a label above each touch point. + * for (let touch of touches) { + * text(`${touch.x}, ${touch.y}`, touch.x, touch.y - 40); + * } + * } + * + *
+ */ + fn.touches = []; + fn._activeTouches = new Map(); + /** * A `Boolean` system variable that's `true` if the mouse is pressed and * `false` if not. @@ -817,27 +903,35 @@ function mouse(p5, fn){ */ fn.mouseIsPressed = false; - fn._updateNextMouseCoords = function(e) { - if (this._curElement !== null && (!e.touches || e.touches.length > 0)) { - const mousePos = getMousePos( - this._curElement.elt, - this.width, - this.height, - e - ); - this.movedX = e.movementX; - this.movedY = e.movementY; - this.mouseX = mousePos.x; - this.mouseY = mousePos.y; - this.winMouseX = mousePos.winX; - this.winMouseY = mousePos.winY; - } - if (!this._hasMouseInteracted) { - // For first draw, make previous and next equal - this._updateMouseCoords(); - this._hasMouseInteracted = true; + fn._updatePointerCoords = function (e) { + if (this._curElement !== null) { + const canvas = this._curElement.elt; + const rect = canvas.getBoundingClientRect(); + const sx = canvas.scrollWidth / this.width || 1; + const sy = canvas.scrollHeight / this.height || 1; + + if (e.pointerType == 'touch') { + const touches = []; + for (const touch of this._activeTouches.values()) { + touches.push(getTouchInfo(canvas, sx, sy, touch)); + } + this.touches = touches; + } else { + const mousePos = getMouseInfo(canvas, sx, sy, e); + this.movedX = e.movementX || 0; + this.movedY = e.movementY || 0; + this.mouseX = mousePos.x; + this.mouseY = mousePos.y; + this.winMouseX = mousePos.winX; + this.winMouseY = mousePos.winY; + } + + if (!this._hasMouseInteracted) { + this._updateMouseCoords(); + this._hasMouseInteracted = true; + } } - }; + }; fn._updateMouseCoords = function() { this.pmouseX = this.mouseX; @@ -847,26 +941,26 @@ function mouse(p5, fn){ this._pmouseWheelDeltaY = this._mouseWheelDeltaY; }; - function getMousePos(canvas, w, h, evt) { - if (evt && !evt.clientX) { - // use touches if touch and not mouse - if (evt.touches) { - evt = evt.touches[0]; - } else if (evt.changedTouches) { - evt = evt.changedTouches[0]; - } - } + function getMouseInfo(canvas, sx, sy, evt) { const rect = canvas.getBoundingClientRect(); - const sx = canvas.scrollWidth / w || 1; - const sy = canvas.scrollHeight / h || 1; return { - x: (evt.clientX - rect.left) / sx, - y: (evt.clientY - rect.top) / sy, - winX: evt.clientX, - winY: evt.clientY, - id: evt.identifier + x: (evt.clientX - rect.left) / sx, + y: (evt.clientY - rect.top) / sy, + winX: evt.clientX, + winY: evt.clientY, }; - } + } + + function getTouchInfo(canvas, sx, sy, touch) { + const rect = canvas.getBoundingClientRect(); + return { + x: (touch.clientX - rect.left) / sx, + y: (touch.clientY - rect.top) / sy, + winX: touch.clientX, + winY: touch.clientY, + id: touch.pointerId, + }; +} fn._setMouseButton = function(e) { if (e.button === 1) { @@ -1054,22 +1148,19 @@ function mouse(p5, fn){ fn._onpointermove = function(e) { const context = this._isGlobal ? window : this; let executeDefault; - this._updateNextMouseCoords(e); - if (!this.mouseIsPressed) { - if (typeof context.mouseMoved === 'function') { + this._updatePointerCoords(e); + + if (!this.mouseIsPressed && typeof context.mouseMoved === 'function') { executeDefault = context.mouseMoved(e); if (executeDefault === false) { e.preventDefault(); } - } - } else { - if (typeof context.mouseDragged === 'function') { + } else if (typeof context.mouseDragged === 'function') { executeDefault = context.mouseDragged(e); if (executeDefault === false) { e.preventDefault(); } } - } }; /** @@ -1218,8 +1309,14 @@ function mouse(p5, fn){ const context = this._isGlobal ? window : this; let executeDefault; this.mouseIsPressed = true; - this._setMouseButton(e); - this._updateNextMouseCoords(e); + + if (e.pointerType === 'touch') { + this._activeTouches.set(e.pointerId, e); + } else { + this._setMouseButton(e); + } + + this._updatePointerCoords(e); if (typeof context.mousePressed === 'function') { executeDefault = context.mousePressed(e); @@ -1377,6 +1474,12 @@ function mouse(p5, fn){ let executeDefault; this.mouseIsPressed = false; + if(e.pointerType == 'touch'){ + this._activeTouches.delete(e.pointerId); + } + + this._updatePointerCoords(e); + if (typeof context.mouseReleased === 'function') { executeDefault = context.mouseReleased(e); if (executeDefault === false) { @@ -1949,8 +2052,8 @@ function mouse(p5, fn){ }; } -export default mouse; +export default pointer; if(typeof p5 !== 'undefined'){ - mouse(p5, p5.prototype); -} + pointer(p5, p5.prototype); +} \ No newline at end of file diff --git a/src/events/touch.js b/src/events/touch.js deleted file mode 100644 index 4d21696377..0000000000 --- a/src/events/touch.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @module Events - * @submodule Touch - * @for p5 - * @requires core - */ - -function touch(p5, fn){ - /** - * An `Array` of all the current touch points on a touchscreen device. - * - * The `touches` array is empty by default. When the user touches their - * screen, a new touch point is tracked and added to the array. Touch points - * are `Objects` with the following properties: - * - * ```js - * // Iterate over the touches array. - * for (let touch of touches) { - * // x-coordinate relative to the top-left - * // corner of the canvas. - * console.log(touch.x); - * - * // y-coordinate relative to the top-left - * // corner of the canvas. - * console.log(touch.y); - * - * // x-coordinate relative to the top-left - * // corner of the browser. - * console.log(touch.winX); - * - * // y-coordinate relative to the top-left - * // corner of the browser. - * console.log(touch.winY); - * - * // ID number - * console.log(touch.id); - * } - * ``` - * - * @property {Object[]} touches - * @readOnly - * - * @example - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square. White circles appear where the user touches the square.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Draw a circle at each touch point. - * for (let touch of touches) { - * circle(touch.x, touch.y, 40); - * } - * } - * - *
- * - *
- * - * // On a touchscreen device, touch the canvas using one or more fingers - * // at the same time. - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square. Labels appear where the user touches the square, displaying the coordinates.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Draw a label above each touch point. - * for (let touch of touches) { - * text(`${touch.x}, ${touch.y}`, touch.x, touch.y - 40); - * } - * } - * - *
- */ - fn.touches = []; - - fn._updateTouchCoords = function(e) { - if (this._curElement !== null) { - const touches = []; - for (let i = 0; i < e.touches.length; i++) { - touches[i] = getTouchInfo( - this._curElement.elt, - this.width, - this.height, - e, - i - ); - } - this.touches = touches; - } - }; - - function getTouchInfo(canvas, w, h, e, i = 0) { - const rect = canvas.getBoundingClientRect(); - const sx = canvas.scrollWidth / w || 1; - const sy = canvas.scrollHeight / h || 1; - const touch = e.touches[i] || e.changedTouches[i]; - return { - x: (touch.clientX - rect.left) / sx, - y: (touch.clientY - rect.top) / sy, - winX: touch.clientX, - winY: touch.clientY, - id: touch.identifier - }; - } - fn._ontouchstart = function(e) { - this.mouseIsPressed = true; - this._updateTouchCoords(e); - this._updateNextMouseCoords(e); - this._updateMouseCoords(); // reset pmouseXY at the start of each touch event - }; - - fn._ontouchmove = function(e) { - const context = this._isGlobal ? window : this; - let executeDefault; - this._updateTouchCoords(e); - this._updateNextMouseCoords(e); - if (typeof context.mouseDragged === 'function') { - executeDefault = context.mouseDragged(e); - if (executeDefault === false) { - e.preventDefault(); - } - } - }; - - fn._ontouchend = function(e) { - this.mouseIsPressed = false; - this._updateTouchCoords(e); - this._updateNextMouseCoords(e); - }; -} - -export default touch; - -if(typeof p5 !== 'undefined'){ - touch(p5, p5.prototype); -} From 37e431a05754c4aec0806b6ee69e9d1849cf274f Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Thu, 21 Nov 2024 18:37:00 +0530 Subject: [PATCH 07/11] touch tests to pointer tests --- test/unit/events/touch.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/test/unit/events/touch.js b/test/unit/events/touch.js index d7d5f12b9b..54677a59cc 100644 --- a/test/unit/events/touch.js +++ b/test/unit/events/touch.js @@ -4,9 +4,6 @@ import { parallelSketches } from '../../js/p5_helpers'; suite('Touch Events', function() { let myp5; - let canvas; - let touchObj1; - let touchObj2; let touchEvent1; let touchEvent2; @@ -14,24 +11,19 @@ suite('Touch Events', function() { new p5(function(p) { p.setup = function() { myp5 = p; - canvas = myp5._curElement.elt; - touchObj1 = new Touch({ - target: canvas, + touchEvent1 = new PointerEvent('pointerdown', { + pointerId: 1, clientX: 100, clientY: 100, - identifier: 36 + pointerType: 'touch' }); - touchObj2 = new Touch({ - target: canvas, + + // Simulate second touch event + touchEvent2 = new PointerEvent('pointerdown', { + pointerId: 2, clientX: 200, clientY: 200, - identifier: 35 - }); - touchEvent1 = new TouchEvent('touchmove', { - touches: [touchObj1, touchObj2] - }); - touchEvent2 = new TouchEvent('touchmove', { - touches: [touchObj2] + pointerType: 'touch' }); }; }); @@ -48,12 +40,12 @@ suite('Touch Events', function() { test('should be an array of multiple touches', function() { window.dispatchEvent(touchEvent1); + window.dispatchEvent(touchEvent2); assert.strictEqual(myp5.touches.length, 2); }); test('should contain the touch registered', function() { - window.dispatchEvent(touchEvent2); - assert.strictEqual(myp5.touches[0].id, 35); + assert.strictEqual(myp5.touches[0].id, 1); }); }); }); From dcaa55a140e3bc3018c777ca6d1ab1352040ae26 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Thu, 21 Nov 2024 18:37:51 +0530 Subject: [PATCH 08/11] nit --- src/core/main.js | 3 --- src/events/pointer.js | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/main.js b/src/core/main.js index 54a4f0f955..9dcdede5d1 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -72,9 +72,6 @@ class p5 { keyup: null, keypress: null, wheel: null, - touchstart: null, - touchmove: null, - touchend: null, resize: null, blur: null }; diff --git a/src/events/pointer.js b/src/events/pointer.js index 48fad5c280..6c5f94864d 100644 --- a/src/events/pointer.js +++ b/src/events/pointer.js @@ -1150,6 +1150,14 @@ function pointer(p5, fn){ let executeDefault; this._updatePointerCoords(e); + if(e.pointerType === 'touch') { + this._activeTouches.set(e.pointerId, e); + const touches = Array.from(this._activeTouches.values()).map((touch)=> + getTouchInfo(this._curElement.elt, this.width, this.height, touch) + ); + this.touches = touches; + } + if (!this.mouseIsPressed && typeof context.mouseMoved === 'function') { executeDefault = context.mouseMoved(e); if (executeDefault === false) { From effb4b245cd37d9fb61b0044a5775972907a3612 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Tue, 26 Nov 2024 02:39:22 +0530 Subject: [PATCH 09/11] updating touches on pointer up --- src/events/pointer.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/events/pointer.js b/src/events/pointer.js index 6c5f94864d..ea7d3902fe 100644 --- a/src/events/pointer.js +++ b/src/events/pointer.js @@ -906,7 +906,6 @@ function pointer(p5, fn){ fn._updatePointerCoords = function (e) { if (this._curElement !== null) { const canvas = this._curElement.elt; - const rect = canvas.getBoundingClientRect(); const sx = canvas.scrollWidth / this.width || 1; const sy = canvas.scrollHeight / this.height || 1; @@ -1152,10 +1151,6 @@ function pointer(p5, fn){ if(e.pointerType === 'touch') { this._activeTouches.set(e.pointerId, e); - const touches = Array.from(this._activeTouches.values()).map((touch)=> - getTouchInfo(this._curElement.elt, this.width, this.height, touch) - ); - this.touches = touches; } if (!this.mouseIsPressed && typeof context.mouseMoved === 'function') { @@ -1484,6 +1479,9 @@ function pointer(p5, fn){ if(e.pointerType == 'touch'){ this._activeTouches.delete(e.pointerId); + this.touches = Array.from(this._activeTouches.values()).map((touch) => + getTouchInfo(this._curElement.elt, this.width, this.height, touch) + ); } this._updatePointerCoords(e); From a9526be0836861a2ebf0face9c273f9baf4066a8 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Sat, 30 Nov 2024 15:23:48 +0530 Subject: [PATCH 10/11] touch-Actions none for only when pointer events are used --- src/core/main.js | 9 ++++++++- src/events/pointer.js | 3 --- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/main.js b/src/core/main.js index 9dcdede5d1..37aae7c13f 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -228,12 +228,19 @@ class p5 { // unhide any hidden canvases that were created const canvases = document.getElementsByTagName('canvas'); + // Apply touchAction = 'none' to canvases if pointer events exist + if (Object.keys(this._events).some(event => event.startsWith('pointer'))) { + for (const k of canvases) { + k.style.touchAction = 'none'; + } + } + + for (const k of canvases) { if (k.dataset.hidden === 'true') { k.style.visibility = ''; delete k.dataset.hidden; } - k.style.touchAction = 'none'; } this._lastTargetFrameTime = window.performance.now(); diff --git a/src/events/pointer.js b/src/events/pointer.js index ea7d3902fe..05e051792f 100644 --- a/src/events/pointer.js +++ b/src/events/pointer.js @@ -1479,9 +1479,6 @@ function pointer(p5, fn){ if(e.pointerType == 'touch'){ this._activeTouches.delete(e.pointerId); - this.touches = Array.from(this._activeTouches.values()).map((touch) => - getTouchInfo(this._curElement.elt, this.width, this.height, touch) - ); } this._updatePointerCoords(e); From 4632483d05f6ac608cc01ddc096b7aafc37c5035 Mon Sep 17 00:00:00 2001 From: Diya Solanki Date: Tue, 3 Dec 2024 02:15:41 +0530 Subject: [PATCH 11/11] nit --- src/events/pointer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/pointer.js b/src/events/pointer.js index 05e051792f..5d75349899 100644 --- a/src/events/pointer.js +++ b/src/events/pointer.js @@ -1158,7 +1158,7 @@ function pointer(p5, fn){ if (executeDefault === false) { e.preventDefault(); } - } else if (typeof context.mouseDragged === 'function') { + } else if (this.mouseIsPressed && typeof context.mouseDragged === 'function') { executeDefault = context.mouseDragged(e); if (executeDefault === false) { e.preventDefault();