mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-11 00:05:36 +02:00
141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
import { WebRTCStream } from "./webrtc-stream";
|
|
import {
|
|
ProtoMouseKeyDownSchema,
|
|
ProtoMouseKeyUpSchema,
|
|
ProtoMouseMoveSchema,
|
|
ProtoMouseWheelSchema,
|
|
} from "./proto/types_pb";
|
|
import { mouseButtonToLinuxEventCode } from "./codes";
|
|
import { create, toBinary } from "@bufbuild/protobuf";
|
|
import { createMessage } from "./utils";
|
|
import { ProtoMessageSchema } from "./proto/messages_pb";
|
|
|
|
interface Props {
|
|
webrtc: WebRTCStream;
|
|
canvas: HTMLCanvasElement;
|
|
}
|
|
|
|
export class Mouse {
|
|
protected wrtc: WebRTCStream;
|
|
protected canvas: HTMLCanvasElement;
|
|
protected connected!: boolean;
|
|
|
|
private sendInterval = 10; // 100 updates per second
|
|
|
|
// Store references to event listeners
|
|
private readonly mousemoveListener: (e: MouseEvent) => void;
|
|
private movementX: number = 0;
|
|
private movementY: number = 0;
|
|
|
|
private readonly mousedownListener: (e: MouseEvent) => void;
|
|
private readonly mouseupListener: (e: MouseEvent) => void;
|
|
private readonly mousewheelListener: (e: WheelEvent) => void;
|
|
|
|
constructor({ webrtc, canvas }: Props) {
|
|
this.wrtc = webrtc;
|
|
this.canvas = canvas;
|
|
|
|
this.mousemoveListener = (e: MouseEvent) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.movementX += e.movementX;
|
|
this.movementY += e.movementY;
|
|
};
|
|
|
|
this.mousedownListener = this.createMouseListener((e: any) =>
|
|
create(ProtoMouseKeyDownSchema, {
|
|
key: this.keyToVirtualKeyCode(e.button),
|
|
}),
|
|
);
|
|
this.mouseupListener = this.createMouseListener((e: any) =>
|
|
create(ProtoMouseKeyUpSchema, {
|
|
key: this.keyToVirtualKeyCode(e.button),
|
|
}),
|
|
);
|
|
this.mousewheelListener = this.createMouseListener((e: any) =>
|
|
create(ProtoMouseWheelSchema, {
|
|
x: Math.round(e.deltaX),
|
|
y: Math.round(e.deltaY),
|
|
}),
|
|
);
|
|
|
|
this.run();
|
|
this.startProcessing();
|
|
}
|
|
|
|
private run() {
|
|
//calls all the other functions
|
|
if (!document.pointerLockElement) {
|
|
console.log("no pointerlock");
|
|
if (this.connected) {
|
|
this.stop();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (document.pointerLockElement == this.canvas) {
|
|
this.connected = true;
|
|
this.canvas.addEventListener("mousemove", this.mousemoveListener);
|
|
this.canvas.addEventListener("mousedown", this.mousedownListener);
|
|
this.canvas.addEventListener("mouseup", this.mouseupListener);
|
|
this.canvas.addEventListener("wheel", this.mousewheelListener);
|
|
} else {
|
|
if (this.connected) {
|
|
this.stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
private stop() {
|
|
this.canvas.removeEventListener("mousemove", this.mousemoveListener);
|
|
this.canvas.removeEventListener("mousedown", this.mousedownListener);
|
|
this.canvas.removeEventListener("mouseup", this.mouseupListener);
|
|
this.canvas.removeEventListener("wheel", this.mousewheelListener);
|
|
this.connected = false;
|
|
}
|
|
|
|
private startProcessing() {
|
|
setInterval(() => {
|
|
if (this.connected) {
|
|
this.sendAggregatedMouseMove();
|
|
this.movementX = 0;
|
|
this.movementY = 0;
|
|
}
|
|
}, this.sendInterval);
|
|
}
|
|
|
|
private sendAggregatedMouseMove() {
|
|
const data = create(ProtoMouseMoveSchema, {
|
|
x: Math.round(this.movementX),
|
|
y: Math.round(this.movementY),
|
|
});
|
|
|
|
const message = createMessage(data, "input");
|
|
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, message));
|
|
}
|
|
|
|
// Helper function to create and return mouse listeners
|
|
private createMouseListener(
|
|
dataCreator: (e: Event) => any,
|
|
): (e: Event) => void {
|
|
return (e: Event) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const data = dataCreator(e as any);
|
|
|
|
const message = createMessage(data, "input");
|
|
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, message));
|
|
};
|
|
}
|
|
|
|
public dispose() {
|
|
document.exitPointerLock();
|
|
this.stop();
|
|
this.connected = false;
|
|
}
|
|
|
|
private keyToVirtualKeyCode(code: number) {
|
|
return mouseButtonToLinuxEventCode[code] || undefined;
|
|
}
|
|
}
|