--- cursor.js | 18 +++++++-- png.js | 2 +- spice.html | 1 + spice_auto.html | 1 + thirdparty/monocursor.js | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 thirdparty/monocursor.js diff --git a/cursor.js b/cursor.js index d3f4d55..1fb1ede 100644 --- a/cursor.js +++ b/cursor.js @@ -62,7 +62,8 @@ SpiceCursorConn.prototype.process_channel_message = function(msg) if (cursor_set.flags > 0) this.log_warn("FIXME: No support for cursor flags " + cursor_set.flags); - if (cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_ALPHA) + if (cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_ALPHA && + cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_MONO) { this.log_warn("FIXME: No support for cursor type " + cursor_set.cursor.header.type); return false; @@ -117,9 +118,18 @@ SpiceCursorConn.prototype.process_channel_message = function(msg) SpiceCursorConn.prototype.set_cursor = function(cursor) { - var pngstr = create_rgba_png(cursor.header.height, cursor.header.width, cursor.data); - var curstr = 'url(data:image/png,' + pngstr + ') ' + - cursor.header.hot_spot_x + ' ' + cursor.header.hot_spot_y + ", default"; + var pngstr = null; + if (cursor.header.type == SPICE_CURSOR_TYPE_ALPHA) + { + pngstr = create_rgba_png(cursor.header.height, cursor.header.width, cursor.data); + } + if (cursor.header.type == SPICE_CURSOR_TYPE_MONO) + { + pngstr = mono_cursor(cursor.header.height, cursor.header.width, cursor.data); + } + + var curstr = 'url(' + pngstr + ') ' + + cursor.header.hot_spot_x + ' ' + cursor.header.hot_spot_y + ", default"; var screen = document.getElementById(this.parent.screen_id); screen.style.cursor = 'auto'; screen.style.cursor = curstr; diff --git a/png.js b/png.js index 6a26151..5b52ed5 100644 --- a/png.js +++ b/png.js @@ -252,5 +252,5 @@ function create_rgba_png(width, height, bytes) } - return "%89PNG%0D%0A%1A%0A" + str; + return "data:image/png,%89PNG%0D%0A%1A%0A" + str; } diff --git a/spice.html b/spice.html index 7abfcff..3a74e21 100644 --- a/spice.html +++ b/spice.html @@ -54,6 +54,7 @@ <script src="thirdparty/prng4.js"></script> <script src="thirdparty/rng.js"></script> <script src="thirdparty/sha1.js"></script> + <script src="thirdparty/monocursor.js"></script> <script src="ticket.js"></script> <script src="resize.js"></script> <script src="filexfer.js"></script> diff --git a/spice_auto.html b/spice_auto.html index 2f04fc9..10f5508 100644 --- a/spice_auto.html +++ b/spice_auto.html @@ -54,6 +54,7 @@ <script src="thirdparty/prng4.js"></script> <script src="thirdparty/rng.js"></script> <script src="thirdparty/sha1.js"></script> + <script src="thirdparty/monocursor.js"></script> <script src="ticket.js"></script> <script src="resize.js"></script> <script src="filexfer.js"></script> diff --git a/thirdparty/monocursor.js b/thirdparty/monocursor.js new file mode 100644 index 0000000..36ebd88 --- /dev/null +++ b/thirdparty/monocursor.js @@ -0,0 +1,100 @@ +/* Downloaded 1/6/2017 from https://github.com/eyeos/spice-web-client/blob/master/lib/graphic.js by Tomáš Bohdálek. + +License reproduce here for completeness: + + eyeOS Spice Web Client +Copyright (c) 2015 eyeOS S.L. + +Contact Jose Carlos Norte (jose@xxxxxxxxx) for more information about this software. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License version 3 as published by the +Free Software Foundation. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License +version 3 along with this program in the file "LICENSE". If not, see +<http://www.gnu.org/licenses/agpl-3.0.txt>. + +See www.eyeos.org for more details. All requests should be sent to licensing@xxxxxxxxx + +The interactive user interfaces in modified source and object code versions +of this program must display Appropriate Legal Notices, as required under +Section 5 of the GNU Affero General Public License version 3. + +In accordance with Section 7(b) of the GNU Affero General Public License version 3, +these Appropriate Legal Notices must retain the display of the "Powered by +eyeos" logo and retain the original copyright notice. If the display of the +logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices +must display the words "Powered by eyeos" and retain the original copyright notice. +*/ + +function mono_cursor(height, width, data) +{ + var monoMask = [1, 2, 4, 8, 16, 32, 64, 128]; + var bytes = new Uint8Array(data); + var length = bytes.length; + var half = length / 2; + + var canvas = document.createElement("canvas"); + canvas.setAttribute('width', width); + canvas.setAttribute('height', height); + var context = canvas.getContext("2d"); + var result = context.createImageData(width, height); + + var andMask = []; + var xorMask = []; + + for (var i = 0; i < length; i++) { + var currentByte = bytes[i]; + var bitsLeft = 8; + + if (i >= half) { + while (bitsLeft--) { + var bit = (currentByte & monoMask[bitsLeft]) && true; + andMask.push(bit); + } + } else if (i < half) { + while (bitsLeft--) { + var bit = (currentByte & monoMask[bitsLeft]) && true; + xorMask.push(bit); + } + } + } + + var pos = 0; + half = xorMask.length; + + for (i = 0; i < half; i++) { + pos = i * 4; + if (!andMask[i] && !xorMask[i]) { + result.data[pos] = 0; + result.data[pos + 1] = 0; + result.data[pos + 2] = 0; + result.data[pos + 3] = 255; + } else if (!andMask[i] && xorMask[i]) { + result.data[pos] = 255; + result.data[pos + 1] = 255; + result.data[pos + 2] = 255; + result.data[pos + 3] = 0; + } else if (andMask[i] && !xorMask[i]) { + result.data[pos] = 255; + result.data[pos + 1] = 255; + result.data[pos + 2] = 255; + result.data[pos + 3] = 255; + } else if (andMask[i] && xorMask[i]) { + result.data[pos] = 0; + result.data[pos + 1] = 0; + result.data[pos + 2] = 0; + result.data[pos + 3] = 255; + } + } + + context.putImageData(result, 0, 0); + + return canvas.toDataURL("image/png"); +} -- 2.9.5 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel