Separate out cursor handling
Make cursor handling more generic in preparation for generic handling of corner cases.
This commit is contained in:
parent
e62b4ccb5e
commit
b475eed5fa
|
@ -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';
|
||||
};
|
||||
|
|
16
core/rfb.js
16
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--;
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue