implement mouse wheel handling and clean up mouse handling in general

This commit is contained in:
modeco80 2024-03-11 21:24:40 -04:00
parent f981a661da
commit b59ebe2466
2 changed files with 55 additions and 22 deletions

View File

@ -1,4 +1,4 @@
import {createNanoEvents } from "nanoevents";
import {createNanoEvents, Emitter, DefaultEvents } from "nanoevents";
import * as Guacutils from './Guacutils.js';
import VM from "./VM.js";
import { User } from "./User.js";
@ -24,9 +24,9 @@ export default class CollabVMClient {
private voteStatus : VoteStatus | null = null;
private node : string | null = null;
// events that are used internally and not exposed
private emitter;
private emitter : Emitter<DefaultEvents>;
// public events
private publicEmitter;
private publicEmitter : Emitter<DefaultEvents>;
constructor(url : string) {
// Save the URL
@ -45,28 +45,32 @@ export default class CollabVMClient {
if (this.users.find(u => u.username === this.username)?.turn === -1)
this.turn(true);
});
// Bind keyboard and mouse
this.canvas.addEventListener('mousedown', (e : MouseEvent) => {
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
this.mouse.processEvent(e, true);
this.mouse.initFromMouseEvent(e);
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
}, {
capture: true
});
this.canvas.addEventListener('mouseup', (e : MouseEvent) => {
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
this.mouse.processEvent(e, false);
this.mouse.initFromMouseEvent(e);
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
}, {
capture: true
});
this.canvas.addEventListener('mousemove', (e : MouseEvent) => {
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
this.mouse.processEvent(e, null);
this.mouse.initFromMouseEvent(e);
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
}, {
capture: true
});
this.canvas.addEventListener('keydown', (e : KeyboardEvent) => {
e.preventDefault();
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
@ -76,6 +80,7 @@ export default class CollabVMClient {
}, {
capture: true
});
this.canvas.addEventListener('keyup', (e : KeyboardEvent) => {
e.preventDefault();
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
@ -85,6 +90,23 @@ export default class CollabVMClient {
}, {
capture: true
});
this.canvas.addEventListener('wheel', (ev: WheelEvent) => {
ev.preventDefault();
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
this.mouse.initFromWheelEvent(ev);
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
// this is a very, very ugly hack but it seems to work so /shrug
if(this.mouse.scrollUp)
this.mouse.scrollUp = false;
else if(this.mouse.scrollDown)
this.mouse.scrollDown = false;
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
}, { capture: true });
this.canvas.addEventListener('contextmenu', e => e.preventDefault());
// Create the WebSocket
this.socket = new WebSocket(url, "guacamole");

View File

@ -1,9 +1,13 @@
function maskContains(mask: number, bit: number): boolean {
return (mask & bit) == bit;
}
export default class Mouse {
left : boolean = false;
middle : boolean = false;
right : boolean = false;
scrolldown : boolean = false;
scrollup : boolean = false;
scrollDown : boolean = false;
scrollUp : boolean = false;
x : number = 0;
y : number = 0;
constructor() {}
@ -13,24 +17,31 @@ export default class Mouse {
if (this.left) mask |= 1;
if (this.middle) mask |= 2;
if (this.right) mask |= 4;
if (this.scrollup) mask |= 8;
if (this.scrolldown) mask |= 16;
if (this.scrollUp) mask |= 8;
if (this.scrollDown) mask |= 16;
return mask;
}
processEvent(e : MouseEvent, down : boolean | null = null) {
if (down !== null) switch (e.button) {
case 0:
this.left = down;
break;
case 1:
this.middle = down;
break;
case 2:
this.right = down;
break;
}
initFromMouseEvent(e: MouseEvent) {
this.left = maskContains(e.buttons, 1);
this.right = maskContains(e.buttons, 2);
this.middle = maskContains(e.buttons, 4);
this.x = e.offsetX;
this.y = e.offsetY;
}
// don't think there's a good way of shoehorning this in processEvent so ..
// (I guess could union e to be MouseEvent|WheelEvent and put this in there, but it'd be a
// completely unnesscary runtime check for a one-event situation, so having it be seperate
// and even call the MouseEvent implementation is more than good enough)
initFromWheelEvent(ev: WheelEvent) {
this.initFromMouseEvent(ev as MouseEvent);
// Now do the actual wheel handling
if (ev.deltaY < 0)
this.scrollUp = true;
else if (ev.deltaY > 0)
this.scrollDown = true;
}
}