Use ES6 classes

Always use the shorthand notation if the function is a method of an object or class `{ foo() { ... } }` or `class bar { foo() { ... } }`
unless it's a callback in which case you a fat arrow function should be used `{ cb: () => { ... } }`
This commit is contained in:
Juanjo Diaz
2018-07-05 21:31:56 +02:00
parent 67fefcf184
commit 0e4808bf6f
20 changed files with 977 additions and 972 deletions
+2 -3
View File
@@ -11,7 +11,7 @@ export default {
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
base64Pad : '=',
encode: function (data) {
encode(data) {
"use strict";
let result = '';
const length = data.length;
@@ -54,8 +54,7 @@ export default {
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
],
decode: function (data, offset) {
"use strict";
decode(data, offset) {
offset = typeof(offset) !== 'undefined' ? offset : 0;
let data_length = data.indexOf('=') - offset;
+137 -134
View File
@@ -10,66 +10,6 @@
import * as Log from './util/logging.js';
import Base64 from "./base64.js";
export default function Display(target) {
this._drawCtx = null;
this._c_forceCanvas = false;
this._renderQ = []; // queue drawing actions for in-oder rendering
this._flushing = false;
// the full frame buffer (logical canvas) size
this._fb_width = 0;
this._fb_height = 0;
this._prevDrawStyle = "";
this._tile = null;
this._tile16x16 = null;
this._tile_x = 0;
this._tile_y = 0;
Log.Debug(">> Display.constructor");
// The visible canvas
this._target = target;
if (!this._target) {
throw new Error("Target must be set");
}
if (typeof this._target === 'string') {
throw new Error('target must be a DOM element');
}
if (!this._target.getContext) {
throw new Error("no getContext method");
}
this._targetCtx = this._target.getContext('2d');
// the visible canvas viewport (i.e. what actually gets seen)
this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
// The hidden canvas, where we do the actual rendering
this._backbuffer = document.createElement('canvas');
this._drawCtx = this._backbuffer.getContext('2d');
this._damageBounds = { left:0, top:0,
right: this._backbuffer.width,
bottom: this._backbuffer.height };
Log.Debug("User Agent: " + navigator.userAgent);
this.clear();
// Check canvas features
if (!('createImageData' in this._drawCtx)) {
throw new Error("Canvas does not support createImageData");
}
this._tile16x16 = this._drawCtx.createImageData(16, 16);
Log.Debug("<< Display.constructor");
}
let SUPPORTS_IMAGEDATA_CONSTRUCTOR = false;
try {
new ImageData(new Uint8ClampedArray(4), 1, 1);
@@ -78,41 +18,104 @@ try {
// ignore failure
}
Display.prototype = {
export default class Display {
constructor(target) {
this._drawCtx = null;
this._c_forceCanvas = false;
this._renderQ = []; // queue drawing actions for in-oder rendering
this._flushing = false;
// the full frame buffer (logical canvas) size
this._fb_width = 0;
this._fb_height = 0;
this._prevDrawStyle = "";
this._tile = null;
this._tile16x16 = null;
this._tile_x = 0;
this._tile_y = 0;
Log.Debug(">> Display.constructor");
// The visible canvas
this._target = target;
if (!this._target) {
throw new Error("Target must be set");
}
if (typeof this._target === 'string') {
throw new Error('target must be a DOM element');
}
if (!this._target.getContext) {
throw new Error("no getContext method");
}
this._targetCtx = this._target.getContext('2d');
// the visible canvas viewport (i.e. what actually gets seen)
this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
// The hidden canvas, where we do the actual rendering
this._backbuffer = document.createElement('canvas');
this._drawCtx = this._backbuffer.getContext('2d');
this._damageBounds = { left:0, top:0,
right: this._backbuffer.width,
bottom: this._backbuffer.height };
Log.Debug("User Agent: " + navigator.userAgent);
this.clear();
// Check canvas features
if (!('createImageData' in this._drawCtx)) {
throw new Error("Canvas does not support createImageData");
}
this._tile16x16 = this._drawCtx.createImageData(16, 16);
Log.Debug("<< Display.constructor");
// ===== PROPERTIES =====
this._scale = 1.0;
this._clipViewport = false;
this.logo = null;
// ===== EVENT HANDLERS =====
this.onflush = () => {}; // A flush request has finished
}
// ===== PROPERTIES =====
_scale: 1.0,
get scale() { return this._scale; },
get scale() { return this._scale; }
set scale(scale) {
this._rescale(scale);
},
}
_clipViewport: false,
get clipViewport() { return this._clipViewport; },
get clipViewport() { return this._clipViewport; }
set clipViewport(viewport) {
this._clipViewport = viewport;
// May need to readjust the viewport dimensions
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
},
}
get width() {
return this._fb_width;
},
}
get height() {
return this._fb_height;
},
logo: null,
// ===== EVENT HANDLERS =====
onflush: function () {}, // A flush request has finished
}
// ===== PUBLIC METHODS =====
viewportChangePos: function (deltaX, deltaY) {
viewportChangePos(deltaX, deltaY) {
const vp = this._viewportLoc;
deltaX = Math.floor(deltaX);
deltaY = Math.floor(deltaY);
@@ -152,9 +155,9 @@ Display.prototype = {
this._damage(vp.x, vp.y, vp.w, vp.h);
this.flip();
},
}
viewportChangeSize: function(width, height) {
viewportChangeSize(width, height) {
if (!this._clipViewport ||
typeof(width) === "undefined" ||
@@ -190,17 +193,17 @@ Display.prototype = {
// Update the visible size of the target canvas
this._rescale(this._scale);
}
},
}
absX: function (x) {
absX(x) {
return x / this._scale + this._viewportLoc.x;
},
}
absY: function (y) {
absY(y) {
return y / this._scale + this._viewportLoc.y;
},
}
resize: function (width, height) {
resize(width, height) {
this._prevDrawStyle = "";
this._fb_width = width;
@@ -232,10 +235,10 @@ Display.prototype = {
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
},
}
// Track what parts of the visible canvas that need updating
_damage: function(x, y, w, h) {
_damage(x, y, w, h) {
if (x < this._damageBounds.left) {
this._damageBounds.left = x;
}
@@ -248,11 +251,11 @@ Display.prototype = {
if ((y + h) > this._damageBounds.bottom) {
this._damageBounds.bottom = y + h;
}
},
}
// Update the visible canvas with the contents of the
// rendering canvas
flip: function(from_queue) {
flip(from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'flip'
@@ -296,9 +299,9 @@ Display.prototype = {
this._damageBounds.left = this._damageBounds.top = 65535;
this._damageBounds.right = this._damageBounds.bottom = 0;
}
},
}
clear: function () {
clear() {
if (this._logo) {
this.resize(this._logo.width, this._logo.height);
this.imageRect(0, 0, this._logo.type, this._logo.data);
@@ -307,21 +310,21 @@ Display.prototype = {
this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height);
}
this.flip();
},
}
pending: function() {
pending() {
return this._renderQ.length > 0;
},
}
flush: function() {
flush() {
if (this._renderQ.length === 0) {
this.onflush();
} else {
this._flushing = true;
}
},
}
fillRect: function (x, y, width, height, color, from_queue) {
fillRect(x, y, width, height, color, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'fill',
@@ -336,9 +339,9 @@ Display.prototype = {
this._drawCtx.fillRect(x, y, width, height);
this._damage(x, y, width, height);
}
},
}
copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) {
copyImage(old_x, old_y, new_x, new_y, w, h, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'copy',
@@ -367,9 +370,9 @@ Display.prototype = {
new_x, new_y, w, h);
this._damage(new_x, new_y, w, h);
}
},
}
imageRect: function(x, y, mime, arr) {
imageRect(x, y, mime, arr) {
const img = new Image();
img.src = "data: " + mime + ";base64," + Base64.encode(arr);
this._renderQ_push({
@@ -378,10 +381,10 @@ Display.prototype = {
'x': x,
'y': y
});
},
}
// start updating a tile
startTile: function (x, y, width, height, color) {
startTile(x, y, width, height, color) {
this._tile_x = x;
this._tile_y = y;
if (width === 16 && height === 16) {
@@ -401,10 +404,10 @@ Display.prototype = {
data[i + 2] = blue;
data[i + 3] = 255;
}
},
}
// update sub-rectangle of the current tile
subTile: function (x, y, w, h, color) {
subTile(x, y, w, h, color) {
const red = color[2];
const green = color[1];
const blue = color[0];
@@ -422,16 +425,16 @@ Display.prototype = {
data[p + 3] = 255;
}
}
},
}
// draw the current tile to the screen
finishTile: function () {
finishTile() {
this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
this._damage(this._tile_x, this._tile_y,
this._tile.width, this._tile.height);
},
}
blitImage: function (x, y, width, height, arr, offset, from_queue) {
blitImage(x, y, width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@@ -449,9 +452,9 @@ Display.prototype = {
} else {
this._bgrxImageData(x, y, width, height, arr, offset);
}
},
}
blitRgbImage: function (x, y , width, height, arr, offset, from_queue) {
blitRgbImage(x, y , width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@@ -469,9 +472,9 @@ Display.prototype = {
} else {
this._rgbImageData(x, y, width, height, arr, offset);
}
},
}
blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) {
blitRgbxImage(x, y, width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@@ -489,14 +492,14 @@ Display.prototype = {
} else {
this._rgbxImageData(x, y, width, height, arr, offset);
}
},
}
drawImage: function (img, x, y) {
drawImage(img, x, y) {
this._drawCtx.drawImage(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
autoscale: function (containerWidth, containerHeight) {
autoscale(containerWidth, containerHeight) {
const vp = this._viewportLoc;
const targetAspectRatio = containerWidth / containerHeight;
const fbAspectRatio = vp.w / vp.h;
@@ -509,11 +512,11 @@ Display.prototype = {
}
this._rescale(scaleRatio);
},
}
// ===== PRIVATE METHODS =====
_rescale: function (factor) {
_rescale(factor) {
this._scale = factor;
const vp = this._viewportLoc;
@@ -529,17 +532,17 @@ Display.prototype = {
this._target.style.width = width;
this._target.style.height = height;
}
},
}
_setFillColor: function (color) {
_setFillColor(color) {
const newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
if (newStyle !== this._prevDrawStyle) {
this._drawCtx.fillStyle = newStyle;
this._prevDrawStyle = newStyle;
}
},
}
_rgbImageData: function (x, y, width, height, arr, offset) {
_rgbImageData(x, y, width, height, arr, offset) {
const img = this._drawCtx.createImageData(width, height);
const data = img.data;
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 3) {
@@ -550,9 +553,9 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_bgrxImageData: function (x, y, width, height, arr, offset) {
_bgrxImageData(x, y, width, height, arr, offset) {
const img = this._drawCtx.createImageData(width, height);
const data = img.data;
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 4) {
@@ -563,9 +566,9 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_rgbxImageData: function (x, y, width, height, arr, offset) {
_rgbxImageData(x, y, width, height, arr, offset) {
// NB(directxman12): arr must be an Type Array view
let img;
if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
@@ -576,25 +579,25 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_renderQ_push: function (action) {
_renderQ_push(action) {
this._renderQ.push(action);
if (this._renderQ.length === 1) {
// If this can be rendered immediately it will be, otherwise
// the scanner will wait for the relevant event
this._scan_renderQ();
}
},
}
_resume_renderQ: function() {
_resume_renderQ() {
// "this" is the object that is ready, not the
// display object
this.removeEventListener('load', this._noVNC_display._resume_renderQ);
this._noVNC_display._scan_renderQ();
},
}
_scan_renderQ: function () {
_scan_renderQ() {
let ready = true;
while (ready && this._renderQ.length > 0) {
const a = this._renderQ[0];
@@ -639,5 +642,5 @@ Display.prototype = {
this._flushing = false;
this.onflush();
}
},
};
}
}
+13 -13
View File
@@ -1,8 +1,17 @@
import { inflateInit, inflate, inflateReset } from "../vendor/pako/lib/zlib/inflate.js";
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
Inflate.prototype = {
inflate: function (data, flush, expected) {
export default class Inflate {
constructor() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.strm.output = new Uint8Array(this.chunkSize);
this.windowBits = 5;
inflateInit(this.strm, this.windowBits);
}
inflate(data, flush, expected) {
this.strm.input = data;
this.strm.avail_in = this.strm.input.length;
this.strm.next_in = 0;
@@ -21,18 +30,9 @@ Inflate.prototype = {
inflate(this.strm, flush);
return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
},
}
reset: function () {
reset() {
inflateReset(this.strm);
}
};
export default function Inflate() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.strm.output = new Uint8Array(this.chunkSize);
this.windowBits = 5;
inflateInit(this.strm, this.windowBits);
}
+43 -42
View File
@@ -15,32 +15,32 @@ import * as browser from "../util/browser.js";
// Keyboard event handler
//
export default function Keyboard(target) {
this._target = target || null;
export default class Keyboard {
constructor(target) {
this._target = target || null;
this._keyDownList = {}; // List of depressed keys
// (even if they are happy)
this._pendingKey = null; // Key waiting for keypress
this._altGrArmed = false; // Windows AltGr detection
this._keyDownList = {}; // List of depressed keys
// (even if they are happy)
this._pendingKey = null; // Key waiting for keypress
this._altGrArmed = false; // Windows AltGr detection
// keep these here so we can refer to them later
this._eventHandlers = {
'keyup': this._handleKeyUp.bind(this),
'keydown': this._handleKeyDown.bind(this),
'keypress': this._handleKeyPress.bind(this),
'blur': this._allKeysUp.bind(this),
'checkalt': this._checkAlt.bind(this),
};
}
// keep these here so we can refer to them later
this._eventHandlers = {
'keyup': this._handleKeyUp.bind(this),
'keydown': this._handleKeyDown.bind(this),
'keypress': this._handleKeyPress.bind(this),
'blur': this._allKeysUp.bind(this),
'checkalt': this._checkAlt.bind(this),
};
Keyboard.prototype = {
// ===== EVENT HANDLERS =====
// ===== EVENT HANDLERS =====
onkeyevent: function () {}, // Handler for key press/release
this.onkeyevent = () => {}; // Handler for key press/release
}
// ===== PRIVATE METHODS =====
_sendKeyEvent: function (keysym, code, down) {
_sendKeyEvent(keysym, code, down) {
if (down) {
this._keyDownList[code] = keysym;
} else {
@@ -54,9 +54,9 @@ Keyboard.prototype = {
Log.Debug("onkeyevent " + (down ? "down" : "up") +
", keysym: " + keysym, ", code: " + code);
this.onkeyevent(keysym, code, down);
},
}
_getKeyCode: function (e) {
_getKeyCode(e) {
const code = KeyboardUtil.getKeycode(e);
if (code !== 'Unidentified') {
return code;
@@ -87,9 +87,9 @@ Keyboard.prototype = {
}
return 'Unidentified';
},
}
_handleKeyDown: function (e) {
_handleKeyDown(e) {
const code = this._getKeyCode(e);
let keysym = KeyboardUtil.getKeysym(e);
@@ -198,10 +198,10 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
}
// Legacy event for browsers without code/key
_handleKeyPress: function (e) {
_handleKeyPress(e) {
stopEvent(e);
// Are we expecting a keypress?
@@ -226,8 +226,9 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
_handleKeyPressTimeout: function (e) {
}
_handleKeyPressTimeout(e) {
// Did someone manage to sort out the key already?
if (this._pendingKey === null) {
return;
@@ -259,9 +260,9 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
}
_handleKeyUp: function (e) {
_handleKeyUp(e) {
stopEvent(e);
const code = this._getKeyCode(e);
@@ -282,24 +283,24 @@ Keyboard.prototype = {
}
this._sendKeyEvent(this._keyDownList[code], code, false);
},
}
_handleAltGrTimeout: function () {
_handleAltGrTimeout() {
this._altGrArmed = false;
clearTimeout(this._altGrTimeout);
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
},
}
_allKeysUp: function () {
_allKeysUp() {
Log.Debug(">> Keyboard.allKeysUp");
for (let code in this._keyDownList) {
this._sendKeyEvent(this._keyDownList[code], code, false);
}
Log.Debug("<< Keyboard.allKeysUp");
},
}
// Firefox Alt workaround, see below
_checkAlt: function (e) {
_checkAlt(e) {
if (e.altKey) {
return;
}
@@ -316,11 +317,11 @@ Keyboard.prototype = {
code: code });
target.dispatchEvent(event);
});
},
}
// ===== PUBLIC METHODS =====
grab: function () {
grab() {
//Log.Debug(">> Keyboard.grab");
this._target.addEventListener('keydown', this._eventHandlers.keydown);
@@ -341,13 +342,13 @@ Keyboard.prototype = {
document.addEventListener(type, handler,
{ capture: true,
passive: true });
});
});
}
//Log.Debug("<< Keyboard.grab");
},
}
ungrab: function () {
ungrab() {
//Log.Debug(">> Keyboard.ungrab");
if (browser.isWindows() && browser.isFirefox()) {
@@ -368,5 +369,5 @@ Keyboard.prototype = {
this._allKeysUp();
//Log.Debug(">> Keyboard.ungrab");
},
};
}
}
+1 -1
View File
@@ -670,7 +670,7 @@ const codepoints = {
};
export default {
lookup : function(u) {
lookup(u) {
// Latin-1 is one-to-one mapping
if ((u >= 0x20) && (u <= 0xff)) {
return u;
+49 -49
View File
@@ -13,44 +13,44 @@ const WHEEL_STEP = 10; // Delta threshold for a mouse wheel step
const WHEEL_STEP_TIMEOUT = 50; // ms
const WHEEL_LINE_HEIGHT = 19;
export default function Mouse(target) {
this._target = target || document;
export default class Mouse {
constructor(target) {
this._target = target || document;
this._doubleClickTimer = null;
this._lastTouchPos = null;
this._doubleClickTimer = null;
this._lastTouchPos = null;
this._pos = null;
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
this._accumulatedWheelDeltaX = 0;
this._accumulatedWheelDeltaY = 0;
this._pos = null;
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
this._accumulatedWheelDeltaX = 0;
this._accumulatedWheelDeltaY = 0;
this._eventHandlers = {
'mousedown': this._handleMouseDown.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mousewheel': this._handleMouseWheel.bind(this),
'mousedisable': this._handleMouseDisable.bind(this)
};
}
this._eventHandlers = {
'mousedown': this._handleMouseDown.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mousewheel': this._handleMouseWheel.bind(this),
'mousedisable': this._handleMouseDisable.bind(this)
};
Mouse.prototype = {
// ===== PROPERTIES =====
// ===== PROPERTIES =====
touchButton: 1, // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
this.touchButton = 1; // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
// ===== EVENT HANDLERS =====
// ===== EVENT HANDLERS =====
onmousebutton: function () {}, // Handler for mouse button click/release
onmousemove: function () {}, // Handler for mouse movement
this.onmousebutton = () => {}; // Handler for mouse button click/release
this.onmousemove = () => {}; // Handler for mouse movement
}
// ===== PRIVATE METHODS =====
_resetDoubleClickTimer: function () {
_resetDoubleClickTimer() {
this._doubleClickTimer = null;
},
}
_handleMouseButton: function (e, down) {
_handleMouseButton(e, down) {
this._updateMousePosition(e);
let pos = this._pos;
@@ -100,25 +100,25 @@ Mouse.prototype = {
this.onmousebutton(pos.x, pos.y, down, bmask);
stopEvent(e);
},
}
_handleMouseDown: function (e) {
_handleMouseDown(e) {
// Touch events have implicit capture
if (e.type === "mousedown") {
setCapture(this._target);
}
this._handleMouseButton(e, 1);
},
}
_handleMouseUp: function (e) {
_handleMouseUp(e) {
this._handleMouseButton(e, 0);
},
}
// Mouse wheel events are sent in steps over VNC. This means that the VNC
// protocol can't handle a wheel event with specific distance or speed.
// Therefor, if we get a lot of small mouse wheel events we combine them.
_generateWheelStepX: function () {
_generateWheelStepX() {
if (this._accumulatedWheelDeltaX < 0) {
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 5);
@@ -129,9 +129,9 @@ Mouse.prototype = {
}
this._accumulatedWheelDeltaX = 0;
},
}
_generateWheelStepY: function () {
_generateWheelStepY() {
if (this._accumulatedWheelDeltaY < 0) {
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 3);
@@ -142,16 +142,16 @@ Mouse.prototype = {
}
this._accumulatedWheelDeltaY = 0;
},
}
_resetWheelStepTimers: function () {
_resetWheelStepTimers() {
window.clearTimeout(this._wheelStepXTimer);
window.clearTimeout(this._wheelStepYTimer);
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
},
}
_handleMouseWheel: function (e) {
_handleMouseWheel(e) {
this._resetWheelStepTimers();
this._updateMousePosition(e);
@@ -192,15 +192,15 @@ Mouse.prototype = {
}
stopEvent(e);
},
}
_handleMouseMove: function (e) {
_handleMouseMove(e) {
this._updateMousePosition(e);
this.onmousemove(this._pos.x, this._pos.y);
stopEvent(e);
},
}
_handleMouseDisable: function (e) {
_handleMouseDisable(e) {
/*
* Stop propagation if inside canvas area
* Note: This is only needed for the 'click' event as it fails
@@ -210,10 +210,10 @@ Mouse.prototype = {
if (e.target == this._target) {
stopEvent(e);
}
},
}
// Update coordinates relative to target
_updateMousePosition: function(e) {
_updateMousePosition(e) {
e = getPointerEvent(e);
const bounds = this._target.getBoundingClientRect();
let x;
@@ -234,11 +234,11 @@ Mouse.prototype = {
y = e.clientY - bounds.top;
}
this._pos = {x:x, y:y};
},
}
// ===== PUBLIC METHODS =====
grab: function () {
grab() {
const c = this._target;
if (isTouchDevice) {
@@ -257,9 +257,9 @@ Mouse.prototype = {
/* preventDefault() on mousedown doesn't stop this event for some
reason so we have to explicitly block it */
c.addEventListener('contextmenu', this._eventHandlers.mousedisable);
},
}
ungrab: function () {
ungrab() {
const c = this._target;
this._resetWheelStepTimers();
@@ -278,4 +278,4 @@ Mouse.prototype = {
c.removeEventListener('contextmenu', this._eventHandlers.mousedisable);
}
};
}
+349 -344
View File
File diff suppressed because it is too large Load Diff
+58 -60
View File
@@ -8,36 +8,36 @@ import { supportsCursorURIs, isTouchDevice } from './browser.js';
const useFallback = !supportsCursorURIs() || isTouchDevice;
function Cursor(container) {
this._target = null;
export default class Cursor {
constructor(container) {
this._target = null;
this._canvas = document.createElement('canvas');
this._canvas = document.createElement('canvas');
if (useFallback) {
this._canvas.style.position = 'fixed';
this._canvas.style.zIndex = '65535';
this._canvas.style.pointerEvents = 'none';
// Can't use "display" because of Firefox bug #1445997
this._canvas.style.visibility = 'hidden';
document.body.appendChild(this._canvas);
if (useFallback) {
this._canvas.style.position = 'fixed';
this._canvas.style.zIndex = '65535';
this._canvas.style.pointerEvents = 'none';
// Can't use "display" because of Firefox bug #1445997
this._canvas.style.visibility = 'hidden';
document.body.appendChild(this._canvas);
}
this._position = { x: 0, y: 0 };
this._hotSpot = { x: 0, y: 0 };
this._eventHandlers = {
'mouseover': this._handleMouseOver.bind(this),
'mouseleave': this._handleMouseLeave.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'touchstart': this._handleTouchStart.bind(this),
'touchmove': this._handleTouchMove.bind(this),
'touchend': this._handleTouchEnd.bind(this),
};
}
this._position = { x: 0, y: 0 };
this._hotSpot = { x: 0, y: 0 };
this._eventHandlers = {
'mouseover': this._handleMouseOver.bind(this),
'mouseleave': this._handleMouseLeave.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'touchstart': this._handleTouchStart.bind(this),
'touchmove': this._handleTouchMove.bind(this),
'touchend': this._handleTouchEnd.bind(this),
};
}
Cursor.prototype = {
attach: function (target) {
attach(target) {
if (this._target) {
this.detach();
}
@@ -61,9 +61,9 @@ Cursor.prototype = {
}
this.clear();
},
}
detach: function () {
detach() {
if (useFallback) {
const options = { capture: true, passive: true };
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
@@ -77,9 +77,9 @@ Cursor.prototype = {
}
this._target = null;
},
}
change: function (pixels, mask, hotx, hoty, w, h) {
change(pixels, mask, hotx, hoty, w, h) {
if ((w === 0) || (h === 0)) {
this.clear();
return;
@@ -125,9 +125,9 @@ Cursor.prototype = {
let url = this._canvas.toDataURL();
this._target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default';
}
},
}
clear: function () {
clear() {
this._target.style.cursor = 'none';
this._canvas.width = 0;
this._canvas.height = 0;
@@ -135,71 +135,71 @@ Cursor.prototype = {
this._position.y = this._position.y + this._hotSpot.y;
this._hotSpot.x = 0;
this._hotSpot.y = 0;
},
}
_handleMouseOver: function (event) {
_handleMouseOver(event) {
// This event could be because we're entering the target, or
// moving around amongst its sub elements. Let the move handler
// sort things out.
this._handleMouseMove(event);
},
}
_handleMouseLeave: function (event) {
_handleMouseLeave(event) {
this._hideCursor();
},
}
_handleMouseMove: function (event) {
_handleMouseMove(event) {
this._updateVisibility(event.target);
this._position.x = event.clientX - this._hotSpot.x;
this._position.y = event.clientY - this._hotSpot.y;
this._updatePosition();
},
}
_handleMouseUp: function (event) {
_handleMouseUp(event) {
// We might get this event because of a drag operation that
// moved outside of the target. Check what's under the cursor
// now and adjust visibility based on that.
let target = document.elementFromPoint(event.clientX, event.clientY);
this._updateVisibility(target);
},
}
_handleTouchStart: function (event) {
_handleTouchStart(event) {
// Just as for mouseover, we let the move handler deal with it
this._handleTouchMove(event);
},
}
_handleTouchMove: function (event) {
_handleTouchMove(event) {
this._updateVisibility(event.target);
this._position.x = event.changedTouches[0].clientX - this._hotSpot.x;
this._position.y = event.changedTouches[0].clientY - this._hotSpot.y;
this._updatePosition();
},
}
_handleTouchEnd: function (event) {
_handleTouchEnd(event) {
// Same principle as for mouseup
let target = document.elementFromPoint(event.changedTouches[0].clientX,
event.changedTouches[0].clientY);
this._updateVisibility(target);
},
}
_showCursor: function () {
_showCursor() {
if (this._canvas.style.visibility === 'hidden')
this._canvas.style.visibility = '';
},
}
_hideCursor: function () {
_hideCursor() {
if (this._canvas.style.visibility !== 'hidden')
this._canvas.style.visibility = 'hidden';
},
}
// Should we currently display the cursor?
// (i.e. are we over the target, or a child of the target without a
// different cursor set)
_shouldShowCursor: function (target) {
_shouldShowCursor(target) {
// Easy case
if (target === this._target)
return true;
@@ -212,19 +212,17 @@ Cursor.prototype = {
if (window.getComputedStyle(target).cursor !== 'none')
return false;
return true;
},
}
_updateVisibility: function (target) {
_updateVisibility(target) {
if (this._shouldShowCursor(target))
this._showCursor();
else
this._hideCursor();
},
}
_updatePosition: function () {
_updatePosition() {
this._canvas.style.left = this._position.x + "px";
this._canvas.style.top = this._position.y + "px";
},
};
export default Cursor;
}
}
+11 -11
View File
@@ -6,10 +6,12 @@
* See README.md for usage and integration instructions.
*/
const EventTargetMixin = {
_listeners: null,
export default class EventTargetMixin {
constructor() {
this._listeners = null;
}
addEventListener: function(type, callback) {
addEventListener(type, callback) {
if (!this._listeners) {
this._listeners = new Map();
}
@@ -17,16 +19,16 @@ const EventTargetMixin = {
this._listeners.set(type, new Set());
}
this._listeners.get(type).add(callback);
},
}
removeEventListener: function(type, callback) {
removeEventListener(type, callback) {
if (!this._listeners || !this._listeners.has(type)) {
return;
}
this._listeners.get(type).delete(callback);
},
}
dispatchEvent: function(event) {
dispatchEvent(event) {
if (!this._listeners || !this._listeners.has(event.type)) {
return true;
}
@@ -34,7 +36,5 @@ const EventTargetMixin = {
callback.call(this, event);
}, this);
return !event.defaultPrevented;
},
};
export default EventTargetMixin;
}
}
-1
View File
@@ -10,6 +10,5 @@
* Decode from UTF-8
*/
export function decodeUTF8 (utf8string) {
"use strict";
return decodeURIComponent(escape(utf8string));
}
+84 -87
View File
@@ -14,91 +14,88 @@
import * as Log from './util/logging.js';
export default function Websock() {
"use strict";
this._websocket = null; // WebSocket object
this._rQi = 0; // Receive queue index
this._rQlen = 0; // Next write position in the receive queue
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
this._rQmax = this._rQbufferSize / 8;
// called in init: this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ = null; // Receive queue
this._sQbufferSize = 1024 * 10; // 10 KiB
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
this._sQlen = 0;
this._sQ = null; // Send queue
this._eventHandlers = {
'message': function () {},
'open': function () {},
'close': function () {},
'error': function () {}
};
}
// this has performance issues in some versions Chromium, and
// doesn't gain a tremendous amount of performance increase in Firefox
// at the moment. It may be valuable to turn it on in the future.
const ENABLE_COPYWITHIN = false;
const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
Websock.prototype = {
export default class Websock {
constructor() {
this._websocket = null; // WebSocket object
this._rQi = 0; // Receive queue index
this._rQlen = 0; // Next write position in the receive queue
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
this._rQmax = this._rQbufferSize / 8;
// called in init: this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ = null; // Receive queue
this._sQbufferSize = 1024 * 10; // 10 KiB
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
this._sQlen = 0;
this._sQ = null; // Send queue
this._eventHandlers = {
message: () => {},
open: () => {},
close: () => {},
error: () => {}
};
}
// Getters and Setters
get_sQ: function () {
get_sQ() {
return this._sQ;
},
}
get_rQ: function () {
get_rQ() {
return this._rQ;
},
}
get_rQi: function () {
get_rQi() {
return this._rQi;
},
}
set_rQi: function (val) {
set_rQi(val) {
this._rQi = val;
},
}
// Receive Queue
rQlen: function () {
rQlen() {
return this._rQlen - this._rQi;
},
}
rQpeek8: function () {
rQpeek8() {
return this._rQ[this._rQi];
},
}
rQshift8: function () {
rQshift8() {
return this._rQ[this._rQi++];
},
}
rQskip8: function () {
rQskip8() {
this._rQi++;
},
}
rQskipBytes: function (num) {
rQskipBytes(num) {
this._rQi += num;
},
}
// TODO(directxman12): test performance with these vs a DataView
rQshift16: function () {
rQshift16() {
return (this._rQ[this._rQi++] << 8) +
this._rQ[this._rQi++];
},
}
rQshift32: function () {
rQshift32() {
return (this._rQ[this._rQi++] << 24) +
(this._rQ[this._rQi++] << 16) +
(this._rQ[this._rQi++] << 8) +
this._rQ[this._rQi++];
},
}
rQshiftStr: function (len) {
rQshiftStr(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); }
let str = "";
// Handle large arrays in steps to avoid long strings on the stack
@@ -107,37 +104,37 @@ Websock.prototype = {
str += String.fromCharCode.apply(null, part);
}
return str;
},
}
rQshiftBytes: function (len) {
rQshiftBytes(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); }
this._rQi += len;
return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
},
}
rQshiftTo: function (target, len) {
rQshiftTo(target, len) {
if (len === undefined) { len = this.rQlen(); }
// TODO: make this just use set with views when using a ArrayBuffer to store the rQ
target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
this._rQi += len;
},
}
rQwhole: function () {
rQwhole() {
return new Uint8Array(this._rQ.buffer, 0, this._rQlen);
},
}
rQslice: function (start, end) {
rQslice(start, end) {
if (end) {
return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
} else {
return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start);
}
},
}
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
// to be available in the receive queue. Return true if we need to
// wait (and possibly print a debug message), otherwise false.
rQwait: function (msg, num, goback) {
rQwait(msg, num, goback) {
const rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
if (rQlen < num) {
if (goback) {
@@ -149,50 +146,50 @@ Websock.prototype = {
return true; // true means need more data
}
return false;
},
}
// Send Queue
flush: function () {
flush() {
if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
this._websocket.send(this._encode_message());
this._sQlen = 0;
}
},
}
send: function (arr) {
send(arr) {
this._sQ.set(arr, this._sQlen);
this._sQlen += arr.length;
this.flush();
},
}
send_string: function (str) {
send_string(str) {
this.send(str.split('').map(function (chr) {
return chr.charCodeAt(0);
}));
},
}
// Event Handlers
off: function (evt) {
off(evt) {
this._eventHandlers[evt] = function () {};
},
}
on: function (evt, handler) {
on(evt, handler) {
this._eventHandlers[evt] = handler;
},
}
_allocate_buffers: function () {
_allocate_buffers() {
this._rQ = new Uint8Array(this._rQbufferSize);
this._sQ = new Uint8Array(this._sQbufferSize);
},
}
init: function () {
init() {
this._allocate_buffers();
this._rQi = 0;
this._websocket = null;
},
}
open: function (uri, protocols) {
open(uri, protocols) {
this.init();
this._websocket = new WebSocket(uri, protocols);
@@ -218,9 +215,9 @@ Websock.prototype = {
this._eventHandlers.error(e);
Log.Debug("<< WebSock.onerror: " + e);
}).bind(this);
},
}
close: function () {
close() {
if (this._websocket) {
if ((this._websocket.readyState === WebSocket.OPEN) ||
(this._websocket.readyState === WebSocket.CONNECTING)) {
@@ -230,16 +227,16 @@ Websock.prototype = {
this._websocket.onmessage = function (e) { return; };
}
},
}
// private methods
_encode_message: function () {
_encode_message() {
// Put in a binary arraybuffer
// according to the spec, you can send ArrayBufferViews with the send method
return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
},
}
_expand_compact_rQ: function (min_fit) {
_expand_compact_rQ(min_fit) {
const resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
if (resizeNeeded) {
if (!min_fit) {
@@ -274,9 +271,9 @@ Websock.prototype = {
this._rQlen = this._rQlen - this._rQi;
this._rQi = 0;
},
}
_decode_message: function (data) {
_decode_message(data) {
// push arraybuffer values onto the end
const u8 = new Uint8Array(data);
if (u8.length > this._rQbufferSize - this._rQlen) {
@@ -284,9 +281,9 @@ Websock.prototype = {
}
this._rQ.set(u8, this._rQlen);
this._rQlen += u8.length;
},
}
_recv_message: function (e) {
_recv_message(e) {
this._decode_message(e.data);
if (this.rQlen() > 0) {
this._eventHandlers.message();
@@ -301,4 +298,4 @@ Websock.prototype = {
Log.Debug("Ignoring empty message");
}
}
};
}