summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2018-02-28 16:08:25 +0100
committerPierre Ossman <ossman@cendio.se>2018-03-15 17:22:21 +0100
commitb475eed5fae5e7e1cdc80ae78604680b914d2a6e (patch)
tree234305c338e6583b87f6ff7bd803d08da6037424 /core
parente62b4ccb5ea4dccc51b7712981e4442dc54171c6 (diff)
downloadnovnc-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.js53
-rw-r--r--core/rfb.js16
-rw-r--r--core/util/cursor.js71
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;