]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Separate out cursor handling
authorPierre Ossman <ossman@cendio.se>
Wed, 28 Feb 2018 15:08:25 +0000 (16:08 +0100)
committerPierre Ossman <ossman@cendio.se>
Thu, 15 Mar 2018 16:22:21 +0000 (17:22 +0100)
Make cursor handling more generic in preparation for generic handling
of corner cases.

core/display.js
core/rfb.js
core/util/cursor.js [new file with mode: 0644]
docs/API-internal.md

index 99156157ac77db2d6f3219574d2bd03576a6bd06..44304ae58a38f1d02be5cf32ef80c2862aa63da8 100644 (file)
@@ -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';
-};
index 81e1e6adf974ddb833cfcabe9cbea8e4500ad1d5..741bf18d7bdab879a8adb6ba965c9df79b2fa895 100644 (file)
@@ -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 (file)
index 0000000..b7dcd5f
--- /dev/null
@@ -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;
index 4943c1a107555c0172955ecabb6a0fbd867d6087..0b29afb61fc279f1a4da25cf3ad2658833f2f2be 100644 (file)
@@ -113,9 +113,6 @@ None
 | blitRgbImage       | (x, y, width, height, arr, offset, from_queue)          | Blit RGB encoded image to display
 | blitRgbxImage      | (x, y, width, height, arr, offset, from_queue)          | Blit RGBX encoded image to display
 | drawImage          | (img, x, y)                                             | Draw image and track damage
-| changeCursor       | (pixels, mask, hotx, hoty, w, h)                        | Change cursor appearance
-| defaultCursor      | ()                                                      | Restore default cursor appearance
-| disableLocalCursor | ()                                                      | Disable local (client-side) cursor
 | autoscale          | (containerWidth, containerHeight)                       | Scale the display
 
 ### 2.3.3 Callbacks