diff options
author | Pierre Ossman <ossman@cendio.se> | 2018-02-28 16:08:25 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2018-03-15 17:22:21 +0100 |
commit | b475eed5fae5e7e1cdc80ae78604680b914d2a6e (patch) | |
tree | 234305c338e6583b87f6ff7bd803d08da6037424 /core | |
parent | e62b4ccb5ea4dccc51b7712981e4442dc54171c6 (diff) | |
download | novnc-b475eed5fae5e7e1cdc80ae78604680b914d2a6e.tar.gz |
Separate out cursor handling
Make cursor handling more generic in preparation for generic handling
of corner cases.
Diffstat (limited to 'core')
-rw-r--r-- | core/display.js | 53 | ||||
-rw-r--r-- | core/rfb.js | 16 | ||||
-rw-r--r-- | core/util/cursor.js | 71 |
3 files changed, 80 insertions, 60 deletions
diff --git a/core/display.js b/core/display.js index 9915615..44304ae 100644 --- a/core/display.js +++ b/core/display.js @@ -498,18 +498,6 @@ Display.prototype = { this._damage(x, y, img.width, img.height); }, - changeCursor: function (pixels, mask, hotx, hoty, w, h) { - Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h); - }, - - defaultCursor: function () { - this._target.style.cursor = "default"; - }, - - disableLocalCursor: function () { - this._target.style.cursor = "none"; - }, - autoscale: function (containerWidth, containerHeight) { var vp = this._viewportLoc; var targetAspectRatio = containerWidth / containerHeight; @@ -655,44 +643,3 @@ Display.prototype = { } }, }; - -// Class Methods -Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) { - if ((w === 0) || (h === 0)) { - target.style.cursor = 'none'; - return; - } - - var cur = [] - var y, x; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - var idx = y * Math.ceil(w / 8) + Math.floor(x / 8); - var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; - idx = ((w * y) + x) * 4; - cur.push(pixels[idx + 2]); // red - cur.push(pixels[idx + 1]); // green - cur.push(pixels[idx]); // blue - cur.push(alpha); // alpha - } - } - - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - - canvas.width = w; - canvas.height = h; - - var img; - if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) { - img = new ImageData(new Uint8ClampedArray(cur), w, h); - } else { - img = ctx.createImageData(w, h); - img.data.set(new Uint8ClampedArray(cur)); - } - ctx.clearRect(0, 0, w, h); - ctx.putImageData(img, 0, 0); - - var url = canvas.toDataURL(); - target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default'; -}; diff --git a/core/rfb.js b/core/rfb.js index 81e1e6a..741bf18 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -17,6 +17,7 @@ import EventTargetMixin from './util/eventtarget.js'; import Display from "./display.js"; import Keyboard from "./input/keyboard.js"; import Mouse from "./input/mouse.js"; +import Cursor from "./util/cursor.js"; import Websock from "./websock.js"; import DES from "./des.js"; import KeyTable from "./input/keysym.js"; @@ -164,6 +165,8 @@ export default function RFB(target, url, options) { this._canvas.tabIndex = -1; this._screen.appendChild(this._canvas); + this._cursor = new Cursor(); + // populate encHandlers with bound versions this._encHandlers[encodings.encodingRaw] = RFB.encodingHandlers.RAW.bind(this); this._encHandlers[encodings.encodingCopyRect] = RFB.encodingHandlers.COPYRECT.bind(this); @@ -413,6 +416,8 @@ RFB.prototype = { // Make our elements part of the page this._target.appendChild(this._screen); + this._cursor.attach(this._canvas); + // Monitor size changes of the screen // FIXME: Use ResizeObserver, or hidden overflow window.addEventListener('resize', this._eventHandlers.windowResize); @@ -426,6 +431,7 @@ RFB.prototype = { _disconnect: function () { Log.Debug(">> RFB.disconnect"); + this._cursor.detach(); this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas); this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas); window.removeEventListener('resize', this._eventHandlers.windowResize); @@ -1241,10 +1247,6 @@ RFB.prototype = { this._timing.fbu_rt_start = (new Date()).getTime(); this._timing.pixels = 0; - // Cursor will be server side until the server decides to honor - // our request and send over the cursor image - this._display.disableLocalCursor(); - this._updateConnectionState('connected'); return true; }, @@ -2522,9 +2524,9 @@ RFB.encodingHandlers = { this._FBU.bytes = pixelslength + masklength; if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; } - this._display.changeCursor(this._sock.rQshiftBytes(pixelslength), - this._sock.rQshiftBytes(masklength), - x, y, w, h); + this._cursor.change(this._sock.rQshiftBytes(pixelslength), + this._sock.rQshiftBytes(masklength), + x, y, w, h); this._FBU.bytes = 0; this._FBU.rects--; diff --git a/core/util/cursor.js b/core/util/cursor.js new file mode 100644 index 0000000..b7dcd5f --- /dev/null +++ b/core/util/cursor.js @@ -0,0 +1,71 @@ +/* + * noVNC: HTML5 VNC client + * Copyright 2018 Pierre Ossman for noVNC + * Licensed under MPL 2.0 or any later version (see LICENSE.txt) + */ + +function Cursor(container) { + this._target = null; +} + +Cursor.prototype = { + attach: function (target) { + if (this._target) { + this.detach(); + } + + this._target = target; + + this.clear(); + }, + + detach: function () { + this._target = null; + }, + + change: function (pixels, mask, hotx, hoty, w, h) { + if ((w === 0) || (h === 0)) { + this.clear(); + return; + } + + let cur = [] + for (let y = 0; y < h; y++) { + for (let x = 0; x < w; x++) { + let idx = y * Math.ceil(w / 8) + Math.floor(x / 8); + let alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; + idx = ((w * y) + x) * 4; + cur.push(pixels[idx + 2]); // red + cur.push(pixels[idx + 1]); // green + cur.push(pixels[idx]); // blue + cur.push(alpha); // alpha + } + } + + let canvas = document.createElement('canvas'); + let ctx = canvas.getContext('2d'); + + canvas.width = w; + canvas.height = h; + + let img; + try { + // IE doesn't support this + img = new ImageData(new Uint8ClampedArray(cur), w, h); + } catch (ex) { + img = ctx.createImageData(w, h); + img.data.set(new Uint8ClampedArray(cur)); + } + ctx.clearRect(0, 0, w, h); + ctx.putImageData(img, 0, 0); + + let url = this._canvas.toDataURL(); + this._target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default'; + }, + + clear: function () { + this._target.style.cursor = 'none'; + }, +}; + +export default Cursor; |