Skip to content

Commit

Permalink
Allow server code to listen for pointer events that are forwarded by …
Browse files Browse the repository at this point in the history
…the WAMS client (#39)
  • Loading branch information
mvanderkamp authored Apr 30, 2023
1 parent 749385d commit 223cd29
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 124 deletions.
2 changes: 1 addition & 1 deletion dist/wams/client.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/wams/client.js.map

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions examples/confetti-custom-event.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@

const WAMS = require('..');
const path = require('path');
const app = new WAMS.Application({
clientScripts: ['confetti-custom-event.js'],
staticDir: path.join(__dirname, './client'),
});
const app = new WAMS.Application();

// create a custom square
// with a random color
Expand Down Expand Up @@ -40,33 +37,38 @@ function square(x, y, view, color) {
function spawnSquare(event, color) {
const item = app.spawn(square(event.x, event.y, event.view, color));
item.on('drag', WAMS.predefined.actions.drag);
return item;
}

function handleConnect({ view }) {
view.on('pinch', WAMS.predefined.actions.pinch);
view.on('drag', WAMS.predefined.actions.drag);
view.on('rotate', WAMS.predefined.actions.rotate);
// view.on('click', spawnSquare);
view.on('pointerdown', lock);
view.on('pointerup', release);
}

app.on('mousedown', (event) => {
function lock(event) {
const item = app.workspace.findItemByCoordinates(event.x, event.y);
if (item) {
event.x = item.x;
event.y = item.y;
app.workspace.removeItem(item);
}
spawnSquare(event, '#FFBF00');
});
const newItem = spawnSquare(event, '#FFBF00');
event.view.obtainLockOnItem(newItem);
}

app.on('mouseup', (event) => {
const item = app.workspace.findItemByCoordinates(event.x, event.y);
function release(event) {
const item = event.view.lockedItem;
if (item) {
event.x = item.x;
event.y = item.y;
app.workspace.removeItem(item);
}
spawnSquare(event);
});
}

app.on('connect', handleConnect);
app.listen(9000);
82 changes: 15 additions & 67 deletions src/client/ClientController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const io = require('socket.io-client');

const { constants, DataReporter, TouchReporter, IdStamper, Message, NOP } = require('../shared.js');
const { constants, DataReporter, PointerReporter, IdStamper, Message, NOP } = require('../shared.js');
const Interactor = require('./Interactor.js');

// Symbols to identify these methods as intended only for internal use
Expand Down Expand Up @@ -345,29 +345,24 @@ class ClientController {
* gestures. Default is to use client-side gestures.
*/
setupInteractor(useMultiScreenGestures = false) {
if (useMultiScreenGestures) {
this.setupInputForwarding();
} else {
// eslint-disable-next-line
new Interactor(this.rootElement, {
swipe: this.forward.bind(this, Message.SWIPE),
tap: this.forward.bind(this, Message.CLICK),
track: this.forward.bind(this, Message.TRACK),
transform: this.forward.bind(this, Message.TRANSFORM),
});
}
// if (useMultiScreenGestures) {
// this.setupInputForwarding();
// } else {
// eslint-disable-next-line
this.setupInputForwarding();
return new Interactor(this.rootElement, {
swipe: this.forward.bind(this, Message.SWIPE),
tap: this.forward.bind(this, Message.CLICK),
track: this.forward.bind(this, Message.TRACK),
transform: this.forward.bind(this, Message.TRANSFORM),
});
}

/**
* Set up input event forwarding.
*/
setupInputForwarding() {
if (window.MouseEvent || window.TouchEvent) {
this.forwardTouchEvents();
this.forwardMouseEvents();
} else {
this.forwardPointerEvents();
}
this.forwardPointerEvents();
this.forwardBlurEvents();
}

Expand All @@ -391,8 +386,7 @@ class ClientController {
* Forward blur and cancel events.
*/
forwardBlurEvents() {
this.forwardEvents(['touchcancel', 'pointercancel', 'blur'], (event) => {
event.preventDefault();
this.forwardEvents(['pointercancel', 'blur'], (event) => {
const breport = new DataReporter();
new Message(Message.BLUR, breport).emitWith(this.socket);
});
Expand All @@ -403,53 +397,7 @@ class ClientController {
*/
forwardPointerEvents() {
this.forwardEvents(['pointerdown', 'pointermove', 'pointerup'], (event) => {
event.preventDefault();
const treport = new TouchReporter(event);
treport.changedTouches = [
{
identifier: event.pointerId,
clientX: event.clientX,
clientY: event.clientY,
},
];
new Message(Message.POINTER, treport).emitWith(this.socket);
});
}

/**
* Forward mouse events.
*/
forwardMouseEvents() {
this.forwardEvents(['mousedown', 'mousemove', 'mouseup'], (event) => {
event.preventDefault();
if (event.button === 0) {
const treport = new TouchReporter(event);
treport.changedTouches = [
{
identifier: 0,
clientX: event.clientX,
clientY: event.clientY,
},
];
new Message(Message.POINTER, treport).emitWith(this.socket);
}
});
}

/**
* Forward touch events.
*/
forwardTouchEvents() {
this.forwardEvents(['touchstart', 'touchmove', 'touchend'], (event) => {
event.preventDefault();
const treport = new TouchReporter(event);
treport.changedTouches = Array.from(event.changedTouches).map((touch) => {
return {
identifier: touch.identifier,
clientX: touch.clientX,
clientY: touch.clientY,
};
});
const treport = new PointerReporter(event);
new Message(Message.POINTER, treport).emitWith(this.socket);
});
}
Expand Down
43 changes: 18 additions & 25 deletions src/client/Interactor.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,32 +49,28 @@ class Interactor {
this._scheduled = false;

// Begin listening activities immediately.
this.bindRegions(root);
this.addGestures(root);
window.addEventListener('wheel', this.wheel.bind(this), false);
}

/**
* Westures uses Gesture objects, and expects those objects to be bound to an
* element, along with a handler for responding to that gesture. This method
* takes care of those activities.
* Sets up gesture listeners via westures.
*/
bindRegions(root) {
const pan = new Westures.Pan(root, this.coalesce.bind(this), { disableKeys: ['ctrlKey'] });
const pinch = new Westures.Pinch(root, this.coalesce.bind(this));
const rotate = new Westures.Rotate(root, this.coalesce.bind(this));
const swipe = new Westures.Swipe(root, this.handlers.swipe);
const swivel = new Westures.Swivel(root, this.swivel.bind(this), { enableKeys: ['ctrlKey'] });
const tap = new Westures.Tap(root, this.handlers.tap);
const track = new Westures.Track(root, this.handlers.track, { phases: ['start', 'end'] });

const region = new Westures.Region(root);
region.addGesture(pan);
region.addGesture(pinch);
region.addGesture(rotate);
region.addGesture(tap);
region.addGesture(swipe);
region.addGesture(swivel);
region.addGesture(track);
addGestures(root) {
const region = new Westures.Region(root, { preventDefault: false });
region.addGesture(new Westures.Pan(root, this.coalesce.bind(this), { disableKeys: ['ctrlKey'] }));
region.addGesture(new Westures.Pinch(root, this.coalesce.bind(this)));
region.addGesture(new Westures.Rotate(root, this.coalesce.bind(this)));
region.addGesture(new Westures.Swipe(root, this.handlers.swipe));
region.addGesture(
new Westures.Swivel(root, this.swivel.bind(this), {
enableKeys: ['ctrlKey'],
dynamicPivot: true,
maxInputs: 1,
})
);
region.addGesture(new Westures.Tap(root, this.handlers.tap));
region.addGesture(new Westures.Track(root, this.handlers.track, { phases: ['start', 'end'] }));
}

_resetChanges() {
Expand Down Expand Up @@ -122,10 +118,7 @@ class Interactor {
* Send a swivel event through as a transformation.
*/
swivel({ rotation, pivot }) {
this.handlers.transform({
centroid: pivot,
delta: { rotation },
});
this.coalesce({ rotation, centroid: pivot });
}

/**
Expand Down
14 changes: 8 additions & 6 deletions src/server/ServerController.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,15 @@ class ServerController {
* @param {TouchEvent} event - The event to forward.
*/
pointerEvent(event) {
event.view = this.view;
event.source = this.view.id;
event.changedTouches.forEach((touch) => {
touch.identifier = `${String(this.view.id)}-${touch.identifier}`;
const { x, y } = this.device.transformPoint(touch.clientX, touch.clientY);
touch.clientX = x;
touch.clientY = y;
});
event.pointerId = `${String(this.view.id)}-${event.pointerId}`;
const { x, y } = this.device.transformPoint(event.clientX, event.clientY);
event.clientX = x;
event.clientY = y;
event.x = x;
event.y = y;
this.view.dispatchEvent(event.type, event);
// FIXME TODO: reinstate support for server-side gestures
// this.group.gestureController.process(event);
}
Expand Down
50 changes: 36 additions & 14 deletions src/shared/Reporters.js
Original file line number Diff line number Diff line change
Expand Up @@ -546,40 +546,62 @@ const FullStateReporter = ReporterFactory({
/**
* Enables forwarding of TouchEvents from the client to the server.
*
* @class TouchReporter
* @class PointerReporter
* @memberof module:shared
* @extends module:shared.Reporter
*/
const TouchReporter = ReporterFactory({
const PointerReporter = ReporterFactory({
/**
* The type of event. (e.g. 'pointerdown', 'pointermove', etc.)
*
* @name type
* @type {string}
* @default null
* @memberof module:shared.TouchReporter
* @memberof module:shared.PointerReporter
* @instance
*/
type: null,

/**
* Array of changed touches.
* The pointer ID.
*
* @name changedTouches
* @type {Touch[]}
* @default []
* @memberof module:shared.TouchReporter
* @name pointerId
* @type {number}
* @default null
* @memberof module:shared.PointerReporter
* @instance
*/
pointerId: null,

/**
* The X coordinate of the pointer relative to the viewport.
*
* @name clientX
* @type {number}
* @default null
* @memberof module:shared.PointerReporter
* @instance
*/
clientX: null,

/**
* The Y coordinate of the pointer relative to the viewport.
*
* @name clientY
* @type {number}
* @default null
* @memberof module:shared.PointerReporter
* @instance
*/
changedTouches: [],
clientY: null,

/**
* Whether the CTRL key was pressed at the time of the event.
*
* @name ctrlKey
* @type {boolean}
* @default false
* @memberof module:shared.TouchReporter
* @memberof module:shared.PointerReporter
* @instance
*/
ctrlKey: false,
Expand All @@ -590,7 +612,7 @@ const TouchReporter = ReporterFactory({
* @name altKey
* @type {boolean}
* @default false
* @memberof module:shared.TouchReporter
* @memberof module:shared.PointerReporter
* @instance
*/
altKey: false,
Expand All @@ -601,7 +623,7 @@ const TouchReporter = ReporterFactory({
* @name shiftKey
* @type {boolean}
* @default false
* @memberof module:shared.TouchReporter
* @memberof module:shared.PointerReporter
* @instance
*/
shiftKey: false,
Expand All @@ -612,7 +634,7 @@ const TouchReporter = ReporterFactory({
* @name metaKey
* @type {boolean}
* @default false
* @memberof module:shared.TouchReporter
* @memberof module:shared.PointerReporter
* @instance
*/
metaKey: false,
Expand All @@ -623,7 +645,7 @@ module.exports = {
View,
DataReporter,
FullStateReporter,
TouchReporter,
PointerReporter,
WamsElement,
WamsImage,
};

0 comments on commit 223cd29

Please sign in to comment.