171 lines
4.4 KiB
JavaScript
171 lines
4.4 KiB
JavaScript
const logger = require('../utils/logger');
|
|
const MessageTypes = require('./messageTypes');
|
|
const { clipboardService } = require('../services/clipboard');
|
|
|
|
class InputHandler {
|
|
constructor(inputService) {
|
|
this.inputService = inputService;
|
|
this.clipboardService = clipboardService;
|
|
this.eventQueue = [];
|
|
this.isProcessingQueue = false;
|
|
this.lastMouseMove = null;
|
|
this.mouseMovePending = false;
|
|
}
|
|
|
|
handleMessage(message, ws) {
|
|
const { type, ...data } = message;
|
|
|
|
switch (type) {
|
|
case MessageTypes.MOUSE_MOVE:
|
|
this.queueMouseMove(data.x, data.y);
|
|
break;
|
|
case MessageTypes.MOUSE_DOWN:
|
|
this.queueEvent('mouseDown', data.button || 'left');
|
|
break;
|
|
case MessageTypes.MOUSE_UP:
|
|
this.queueEvent('mouseUp', data.button || 'left');
|
|
break;
|
|
case MessageTypes.MOUSE_WHEEL:
|
|
this.queueEvent('mouseWheel', data.delta);
|
|
break;
|
|
case MessageTypes.KEY_DOWN:
|
|
this.queueEvent('keyDown', data.key);
|
|
break;
|
|
case MessageTypes.KEY_UP:
|
|
this.queueEvent('keyUp', data.key);
|
|
break;
|
|
case MessageTypes.CLIPBOARD_GET:
|
|
this.handleClipboardGet(ws);
|
|
break;
|
|
case MessageTypes.CLIPBOARD_SET:
|
|
this.handleClipboardSet(ws, data);
|
|
break;
|
|
default:
|
|
logger.debug('Unknown message type', { type });
|
|
}
|
|
}
|
|
|
|
async handleClipboardGet(ws) {
|
|
try {
|
|
const content = await this.clipboardService.read();
|
|
if (this.clipboardService.isSmallContent(content.size)) {
|
|
ws.send(JSON.stringify({
|
|
type: MessageTypes.CLIPBOARD_DATA,
|
|
contentType: content.type,
|
|
data: content.data,
|
|
size: content.size
|
|
}));
|
|
} else {
|
|
ws.send(JSON.stringify({
|
|
type: MessageTypes.CLIPBOARD_TOO_LARGE,
|
|
size: content.size
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
logger.error('Failed to get clipboard', { error: error.message });
|
|
ws.send(JSON.stringify({
|
|
type: MessageTypes.CLIPBOARD_RESULT,
|
|
success: false
|
|
}));
|
|
}
|
|
}
|
|
|
|
async handleClipboardSet(ws, data) {
|
|
try {
|
|
const success = await this.clipboardService.set({
|
|
type: data.contentType,
|
|
data: data.data
|
|
});
|
|
ws.send(JSON.stringify({
|
|
type: MessageTypes.CLIPBOARD_RESULT,
|
|
success
|
|
}));
|
|
} catch (error) {
|
|
logger.error('Failed to set clipboard', { error: error.message });
|
|
ws.send(JSON.stringify({
|
|
type: MessageTypes.CLIPBOARD_RESULT,
|
|
success: false
|
|
}));
|
|
}
|
|
}
|
|
|
|
queueMouseMove(x, y) {
|
|
this.lastMouseMove = { x, y };
|
|
|
|
if (!this.mouseMovePending) {
|
|
this.mouseMovePending = true;
|
|
setImmediate(() => {
|
|
if (this.lastMouseMove) {
|
|
this.eventQueue.push({
|
|
type: 'mouseMove',
|
|
x: this.lastMouseMove.x,
|
|
y: this.lastMouseMove.y
|
|
});
|
|
this.mouseMovePending = false;
|
|
this.processQueue();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
queueEvent(type, data) {
|
|
this.eventQueue.push({ type, data });
|
|
this.processQueue();
|
|
}
|
|
|
|
async processQueue() {
|
|
if (this.isProcessingQueue || this.eventQueue.length === 0) {
|
|
return;
|
|
}
|
|
|
|
this.isProcessingQueue = true;
|
|
|
|
while (this.eventQueue.length > 0) {
|
|
const event = this.eventQueue.shift();
|
|
await this.executeEvent(event);
|
|
}
|
|
|
|
this.isProcessingQueue = false;
|
|
}
|
|
|
|
async executeEvent(event) {
|
|
try {
|
|
switch (event.type) {
|
|
case 'mouseMove':
|
|
await this.inputService.mouseMove(event.x, event.y);
|
|
break;
|
|
case 'mouseDown':
|
|
await this.inputService.mouseDown(event.data);
|
|
break;
|
|
case 'mouseUp':
|
|
await this.inputService.mouseUp(event.data);
|
|
break;
|
|
case 'mouseWheel':
|
|
await this.inputService.mouseWheel(event.data);
|
|
break;
|
|
case 'keyDown':
|
|
await this.inputService.keyDown(event.data);
|
|
break;
|
|
case 'keyUp':
|
|
await this.inputService.keyUp(event.data);
|
|
break;
|
|
}
|
|
} catch (error) {
|
|
logger.error('Failed to execute event', {
|
|
type: event.type,
|
|
error: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
logger.info('Stopping InputHandler');
|
|
this.eventQueue = [];
|
|
this.isProcessingQueue = false;
|
|
this.lastMouseMove = null;
|
|
this.mouseMovePending = false;
|
|
}
|
|
}
|
|
|
|
module.exports = InputHandler;
|