Move mouse event handling to RFB class

Move the last remaining bits to the RFB class to keep things simple, as
the Mouse class no longer provides any real value.
This commit is contained in:
Pierre Ossman
2020-06-10 16:13:03 +02:00
committed by Samuel Mannehed
parent 88589a44f7
commit 50cde2faab
5 changed files with 324 additions and 352 deletions
-127
View File
@@ -1,127 +0,0 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/
import * as Log from '../util/logging.js';
import { setCapture, stopEvent, getPointerEvent } from '../util/events.js';
export default class Mouse {
constructor(target) {
this._target = target || document;
this._pos = null;
this._eventHandlers = {
'mousedown': this._handleMouseDown.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mousedisable': this._handleMouseDisable.bind(this)
};
// ===== EVENT HANDLERS =====
this.onmousebutton = () => {}; // Handler for mouse button press/release
this.onmousemove = () => {}; // Handler for mouse movement
}
// ===== PRIVATE METHODS =====
_resetDoubleClickTimer() {
this._doubleClickTimer = null;
}
_handleMouseButton(e, down) {
this._updateMousePosition(e);
let pos = this._pos;
let bmask = 1 << e.button;
Log.Debug("onmousebutton " + (down ? "down" : "up") +
", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask);
this.onmousebutton(pos.x, pos.y, down, bmask);
stopEvent(e);
}
_handleMouseDown(e) {
setCapture(this._target);
this._handleMouseButton(e, 1);
}
_handleMouseUp(e) {
this._handleMouseButton(e, 0);
}
_handleMouseMove(e) {
this._updateMousePosition(e);
this.onmousemove(this._pos.x, this._pos.y);
stopEvent(e);
}
_handleMouseDisable(e) {
/*
* Stop propagation if inside canvas area
* Note: This is only needed for the 'click' event as it fails
* to fire properly for the target element so we have
* to listen on the document element instead.
*/
if (e.target == this._target) {
stopEvent(e);
}
}
// Update coordinates relative to target
_updateMousePosition(e) {
e = getPointerEvent(e);
const bounds = this._target.getBoundingClientRect();
let x;
let y;
// Clip to target bounds
if (e.clientX < bounds.left) {
x = 0;
} else if (e.clientX >= bounds.right) {
x = bounds.width - 1;
} else {
x = e.clientX - bounds.left;
}
if (e.clientY < bounds.top) {
y = 0;
} else if (e.clientY >= bounds.bottom) {
y = bounds.height - 1;
} else {
y = e.clientY - bounds.top;
}
this._pos = {x: x, y: y};
}
// ===== PUBLIC METHODS =====
grab() {
const t = this._target;
t.addEventListener('mousedown', this._eventHandlers.mousedown);
t.addEventListener('mouseup', this._eventHandlers.mouseup);
t.addEventListener('mousemove', this._eventHandlers.mousemove);
// Prevent middle-click pasting (see above for why we bind to document)
document.addEventListener('click', this._eventHandlers.mousedisable);
// preventDefault() on mousedown doesn't stop this event for some
// reason so we have to explicitly block it
t.addEventListener('contextmenu', this._eventHandlers.mousedisable);
}
ungrab() {
const t = this._target;
t.removeEventListener('mousedown', this._eventHandlers.mousedown);
t.removeEventListener('mouseup', this._eventHandlers.mouseup);
t.removeEventListener('mousemove', this._eventHandlers.mousemove);
document.removeEventListener('click', this._eventHandlers.mousedisable);
t.removeEventListener('contextmenu', this._eventHandlers.mousedisable);
}
}
+62 -10
View File
@@ -12,12 +12,12 @@ import * as Log from './util/logging.js';
import { encodeUTF8, decodeUTF8 } from './util/strings.js';
import { dragThreshold } from './util/browser.js';
import { clientToElement } from './util/element.js';
import { setCapture } from './util/events.js';
import EventTargetMixin from './util/eventtarget.js';
import Display from "./display.js";
import Inflator from "./inflator.js";
import Deflator from "./deflator.js";
import Keyboard from "./input/keyboard.js";
import Mouse from "./input/mouse.js";
import GestureHandler from "./input/gesturehandler.js";
import Cursor from "./util/cursor.js";
import Websock from "./websock.js";
@@ -129,7 +129,6 @@ export default class RFB extends EventTargetMixin {
this._display = null; // Display object
this._flushing = false; // Display flushing state
this._keyboard = null; // Keyboard input handler object
this._mouse = null; // Mouse input handler object
this._gestures = null; // Gesture input handler object
// Timers
@@ -169,6 +168,7 @@ export default class RFB extends EventTargetMixin {
this._eventHandlers = {
focusCanvas: this._focusCanvas.bind(this),
windowResize: this._windowResize.bind(this),
handleMouse: this._handleMouse.bind(this),
handleWheel: this._handleWheel.bind(this),
handleGesture: this._handleGesture.bind(this),
};
@@ -229,10 +229,6 @@ export default class RFB extends EventTargetMixin {
this._keyboard = new Keyboard(this._canvas);
this._keyboard.onkeyevent = this._handleKeyEvent.bind(this);
this._mouse = new Mouse(this._canvas);
this._mouse.onmousebutton = this._handleMouseButton.bind(this);
this._mouse.onmousemove = this._handleMouseMove.bind(this);
this._gestures = new GestureHandler();
this._sock = new Websock();
@@ -321,10 +317,8 @@ export default class RFB extends EventTargetMixin {
this._rfbConnectionState === "connected") {
if (viewOnly) {
this._keyboard.ungrab();
this._mouse.ungrab();
} else {
this._keyboard.grab();
this._mouse.grab();
}
}
}
@@ -539,6 +533,16 @@ export default class RFB extends EventTargetMixin {
this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas);
this._canvas.addEventListener("touchstart", this._eventHandlers.focusCanvas);
// Mouse events
this._canvas.addEventListener('mousedown', this._eventHandlers.handleMouse);
this._canvas.addEventListener('mouseup', this._eventHandlers.handleMouse);
this._canvas.addEventListener('mousemove', this._eventHandlers.handleMouse);
// Prevent middle-click pasting (see handler for why we bind to document)
this._canvas.addEventListener('click', this._eventHandlers.handleMouse);
// preventDefault() on mousedown doesn't stop this event for some
// reason so we have to explicitly block it
this._canvas.addEventListener('contextmenu', this._eventHandlers.handleMouse);
// Wheel events
this._canvas.addEventListener("wheel", this._eventHandlers.handleWheel);
@@ -557,11 +561,15 @@ export default class RFB extends EventTargetMixin {
this._canvas.removeEventListener("gesturemove", this._eventHandlers.handleGesture);
this._canvas.removeEventListener("gestureend", this._eventHandlers.handleGesture);
this._canvas.removeEventListener("wheel", this._eventHandlers.handleWheel);
this._canvas.removeEventListener('mousedown', this._eventHandlers.handleMouse);
this._canvas.removeEventListener('mouseup', this._eventHandlers.handleMouse);
this._canvas.removeEventListener('mousemove', this._eventHandlers.handleMouse);
this._canvas.removeEventListener('click', this._eventHandlers.handleMouse);
this._canvas.removeEventListener('contextmenu', this._eventHandlers.handleMouse);
this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas);
this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas);
window.removeEventListener('resize', this._eventHandlers.windowResize);
this._keyboard.ungrab();
this._mouse.ungrab();
this._gestures.detach();
this._sock.close();
try {
@@ -859,6 +867,51 @@ export default class RFB extends EventTargetMixin {
this.sendKey(keysym, code, down);
}
_handleMouse(ev) {
/*
* We don't check connection status or viewOnly here as the
* mouse events might be used to control the viewport
*/
if (ev.type === 'click') {
/*
* Note: This is only needed for the 'click' event as it fails
* to fire properly for the target element so we have
* to listen on the document element instead.
*/
if (ev.target !== this._canvas) {
return;
}
}
// FIXME: if we're in view-only and not dragging,
// should we stop events?
ev.stopPropagation();
ev.preventDefault();
if ((ev.type === 'click') || (ev.type === 'contextmenu')) {
return;
}
let pos = clientToElement(ev.clientX, ev.clientY,
this._canvas);
switch (ev.type) {
case 'mousedown':
setCapture(this._canvas);
this._handleMouseButton(pos.x, pos.y,
true, 1 << ev.button);
break;
case 'mouseup':
this._handleMouseButton(pos.x, pos.y,
false, 1 << ev.button);
break;
case 'mousemove':
this._handleMouseMove(pos.x, pos.y);
break;
}
}
_handleMouseButton(x, y, down, bmask) {
if (this.dragViewport) {
if (down && !this._viewportDragging) {
@@ -1678,7 +1731,6 @@ export default class RFB extends EventTargetMixin {
this._resize(width, height);
if (!this._viewOnly) { this._keyboard.grab(); }
if (!this._viewOnly) { this._mouse.grab(); }
this._fbDepth = 24;