Files
terminal/web/node_modules/.vite/deps/@dushixiang_guacamole-common-js.js
T

5456 lines
175 KiB
JavaScript

import "./chunk-V4OQ3NZ2.js";
// node_modules/@dushixiang/guacamole-common-js/dist/esm/guacamole-common.js
var Guacamole = Guacamole || {};
Guacamole.ArrayBufferReader = function(stream) {
var guac_reader = this;
stream.onblob = function(data) {
var arrayBuffer, bufferView;
if (Uint8Array.fromBase64) {
bufferView = Uint8Array.fromBase64(data);
arrayBuffer = bufferView.buffer;
} else {
var binary = window.atob(data);
arrayBuffer = new ArrayBuffer(binary.length);
bufferView = new Uint8Array(arrayBuffer);
for (var i = 0; i < binary.length; i++)
bufferView[i] = binary.charCodeAt(i);
}
if (guac_reader.ondata)
guac_reader.ondata(arrayBuffer);
};
stream.onend = function() {
if (guac_reader.onend)
guac_reader.onend();
};
this.ondata = null;
this.onend = null;
};
var Guacamole = Guacamole || {};
Guacamole.ArrayBufferWriter = function(stream) {
var guac_writer = this;
stream.onack = function(status) {
if (guac_writer.onack)
guac_writer.onack(status);
};
function __send_blob(bytes) {
var binary = "";
for (var i = 0; i < bytes.byteLength; i++)
binary += String.fromCharCode(bytes[i]);
stream.sendBlob(window.btoa(binary));
}
this.blobLength = Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH;
this.sendData = function(data) {
var bytes = new Uint8Array(data);
if (bytes.length <= guac_writer.blobLength)
__send_blob(bytes);
else {
for (var offset = 0; offset < bytes.length; offset += guac_writer.blobLength)
__send_blob(bytes.subarray(offset, offset + guac_writer.blobLength));
}
};
this.sendEnd = function() {
stream.sendEnd();
};
this.onack = null;
};
Guacamole.ArrayBufferWriter.DEFAULT_BLOB_LENGTH = 6048;
var Guacamole = Guacamole || {};
Guacamole.AudioContextFactory = {
/**
* A singleton instance of a Web Audio API AudioContext object, or null if
* no instance has yes been created. This property may be manually set if
* you wish to supply your own AudioContext instance, but care must be
* taken to do so as early as possible. Assignments to this property will
* not retroactively affect the value returned by previous calls to
* getAudioContext().
*
* @type {AudioContext}
*/
"singleton": null,
/**
* Returns a singleton instance of a Web Audio API AudioContext object.
*
* @return {AudioContext}
* A singleton instance of a Web Audio API AudioContext object, or null
* if the Web Audio API is not supported.
*/
"getAudioContext": function getAudioContext() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
try {
if (!Guacamole.AudioContextFactory.singleton)
Guacamole.AudioContextFactory.singleton = new AudioContext();
return Guacamole.AudioContextFactory.singleton;
} catch (e) {
}
}
return null;
}
};
var Guacamole = Guacamole || {};
Guacamole.AudioPlayer = function AudioPlayer() {
this.sync = function sync() {
};
};
Guacamole.AudioPlayer.isSupportedType = function isSupportedType(mimetype) {
return Guacamole.RawAudioPlayer.isSupportedType(mimetype);
};
Guacamole.AudioPlayer.getSupportedTypes = function getSupportedTypes() {
return Guacamole.RawAudioPlayer.getSupportedTypes();
};
Guacamole.AudioPlayer.getInstance = function getInstance(stream, mimetype) {
if (Guacamole.RawAudioPlayer.isSupportedType(mimetype))
return new Guacamole.RawAudioPlayer(stream, mimetype);
return null;
};
Guacamole.RawAudioPlayer = function RawAudioPlayer(stream, mimetype) {
var format = Guacamole.RawAudioFormat.parse(mimetype);
var context = Guacamole.AudioContextFactory.getAudioContext();
var nextPacketTime = context.currentTime;
var reader = new Guacamole.ArrayBufferReader(stream);
var MIN_SPLIT_SIZE = 0.02;
var maxLatency = 0.3;
var SampleArray = format.bytesPerSample === 1 ? window.Int8Array : window.Int16Array;
var maxSampleValue = format.bytesPerSample === 1 ? 128 : 32768;
var packetQueue = [];
var joinAudioPackets = function joinAudioPackets2(packets) {
if (packets.length <= 1)
return packets[0];
var totalLength = 0;
packets.forEach(function addPacketLengths(packet) {
totalLength += packet.length;
});
var offset = 0;
var joined = new SampleArray(totalLength);
packets.forEach(function appendPacket(packet) {
joined.set(packet, offset);
offset += packet.length;
});
return joined;
};
var splitAudioPacket = function splitAudioPacket2(data) {
var minValue = Number.MAX_VALUE;
var optimalSplitLength = data.length;
var samples = Math.floor(data.length / format.channels);
var minSplitSamples = Math.floor(format.rate * MIN_SPLIT_SIZE);
var start = Math.max(
format.channels * minSplitSamples,
format.channels * (samples - minSplitSamples)
);
for (var offset = start; offset < data.length; offset += format.channels) {
var totalValue = 0;
for (var channel = 0; channel < format.channels; channel++) {
totalValue += Math.abs(data[offset + channel]);
}
if (totalValue <= minValue) {
optimalSplitLength = offset + format.channels;
minValue = totalValue;
}
}
if (optimalSplitLength === data.length)
return [data];
return [
new SampleArray(data.buffer.slice(0, optimalSplitLength * format.bytesPerSample)),
new SampleArray(data.buffer.slice(optimalSplitLength * format.bytesPerSample))
];
};
var pushAudioPacket = function pushAudioPacket2(data) {
packetQueue.push(new SampleArray(data));
};
var shiftAudioPacket = function shiftAudioPacket2() {
var data = joinAudioPackets(packetQueue);
if (!data)
return null;
packetQueue = splitAudioPacket(data);
data = packetQueue.shift();
return data;
};
var toAudioBuffer = function toAudioBuffer2(data) {
var samples = data.length / format.channels;
var packetTime = context.currentTime;
if (nextPacketTime < packetTime)
nextPacketTime = packetTime;
var audioBuffer = context.createBuffer(format.channels, samples, format.rate);
for (var channel = 0; channel < format.channels; channel++) {
var audioData = audioBuffer.getChannelData(channel);
var offset = channel;
for (var i = 0; i < samples; i++) {
audioData[i] = data[offset] / maxSampleValue;
offset += format.channels;
}
}
return audioBuffer;
};
reader.ondata = function playReceivedAudio(data) {
pushAudioPacket(new SampleArray(data));
var packet = shiftAudioPacket();
if (!packet)
return;
var packetTime = context.currentTime;
if (nextPacketTime < packetTime)
nextPacketTime = packetTime;
var source = context.createBufferSource();
source.connect(context.destination);
if (!source.start)
source.start = source.noteOn;
source.buffer = toAudioBuffer(packet);
source.start(nextPacketTime);
nextPacketTime += packet.length / format.channels / format.rate;
};
this.sync = function sync() {
var now = context.currentTime;
nextPacketTime = Math.min(nextPacketTime, now + maxLatency);
};
};
Guacamole.RawAudioPlayer.prototype = new Guacamole.AudioPlayer();
Guacamole.RawAudioPlayer.isSupportedType = function isSupportedType2(mimetype) {
if (!Guacamole.AudioContextFactory.getAudioContext())
return false;
return Guacamole.RawAudioFormat.parse(mimetype) !== null;
};
Guacamole.RawAudioPlayer.getSupportedTypes = function getSupportedTypes2() {
if (!Guacamole.AudioContextFactory.getAudioContext())
return [];
return [
"audio/L8",
"audio/L16"
];
};
var Guacamole = Guacamole || {};
Guacamole.AudioRecorder = function AudioRecorder() {
this.onclose = null;
this.onerror = null;
};
Guacamole.AudioRecorder.isSupportedType = function isSupportedType3(mimetype) {
return Guacamole.RawAudioRecorder.isSupportedType(mimetype);
};
Guacamole.AudioRecorder.getSupportedTypes = function getSupportedTypes3() {
return Guacamole.RawAudioRecorder.getSupportedTypes();
};
Guacamole.AudioRecorder.getInstance = function getInstance2(stream, mimetype) {
if (Guacamole.RawAudioRecorder.isSupportedType(mimetype))
return new Guacamole.RawAudioRecorder(stream, mimetype);
return null;
};
Guacamole.RawAudioRecorder = function RawAudioRecorder(stream, mimetype) {
var recorder = this;
var BUFFER_SIZE = 2048;
var LANCZOS_WINDOW_SIZE = 3;
var format = Guacamole.RawAudioFormat.parse(mimetype);
var context = Guacamole.AudioContextFactory.getAudioContext();
if (!navigator.mediaDevices)
navigator.mediaDevices = {};
if (!navigator.mediaDevices.getUserMedia)
navigator.mediaDevices.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia).bind(navigator);
var writer = new Guacamole.ArrayBufferWriter(stream);
var SampleArray = format.bytesPerSample === 1 ? window.Int8Array : window.Int16Array;
var maxSampleValue = format.bytesPerSample === 1 ? 128 : 32768;
var readSamples = 0;
var writtenSamples = 0;
var mediaStream = null;
var source = null;
var processor = null;
var sinc = function sinc2(x) {
if (x === 0)
return 1;
var piX = Math.PI * x;
return Math.sin(piX) / piX;
};
var lanczos = function lanczos2(x, a) {
if (-a < x && x < a)
return sinc(x) * sinc(x / a);
return 0;
};
var interpolateSample = function getValueAt(audioData, t) {
var index = (audioData.length - 1) * t;
var start = Math.floor(index) - LANCZOS_WINDOW_SIZE + 1;
var end = Math.floor(index) + LANCZOS_WINDOW_SIZE;
var sum = 0;
for (var i = start; i <= end; i++) {
sum += (audioData[i] || 0) * lanczos(index - i, LANCZOS_WINDOW_SIZE);
}
return sum;
};
var toSampleArray = function toSampleArray2(audioBuffer) {
var inSamples = audioBuffer.length;
readSamples += inSamples;
var expectedWrittenSamples = Math.round(readSamples * format.rate / audioBuffer.sampleRate);
var outSamples = expectedWrittenSamples - writtenSamples;
writtenSamples += outSamples;
var data = new SampleArray(outSamples * format.channels);
for (var channel = 0; channel < format.channels; channel++) {
var audioData = audioBuffer.getChannelData(channel);
var offset = channel;
for (var i = 0; i < outSamples; i++) {
data[offset] = interpolateSample(audioData, i / (outSamples - 1)) * maxSampleValue;
offset += format.channels;
}
}
return data;
};
var streamReceived = function streamReceived2(stream2) {
processor = context.createScriptProcessor(BUFFER_SIZE, format.channels, format.channels);
processor.connect(context.destination);
processor.onaudioprocess = function processAudio(e) {
writer.sendData(toSampleArray(e.inputBuffer).buffer);
};
source = context.createMediaStreamSource(stream2);
source.connect(processor);
if (context.state === "suspended")
context.resume();
mediaStream = stream2;
};
var streamDenied = function streamDenied2() {
writer.sendEnd();
if (recorder.onerror)
recorder.onerror();
};
var beginAudioCapture = function beginAudioCapture2() {
var promise = navigator.mediaDevices.getUserMedia({
"audio": true
}, streamReceived, streamDenied);
if (promise && promise.then)
promise.then(streamReceived, streamDenied);
};
var stopAudioCapture = function stopAudioCapture2() {
if (source)
source.disconnect();
if (processor)
processor.disconnect();
if (mediaStream) {
var tracks = mediaStream.getTracks();
for (var i = 0; i < tracks.length; i++)
tracks[i].stop();
}
processor = null;
source = null;
mediaStream = null;
writer.sendEnd();
};
writer.onack = function audioStreamAcknowledged(status) {
if (status.code === Guacamole.Status.Code.SUCCESS && !mediaStream)
beginAudioCapture();
else {
stopAudioCapture();
writer.onack = null;
if (status.code === Guacamole.Status.Code.RESOURCE_CLOSED) {
if (recorder.onclose)
recorder.onclose();
} else {
if (recorder.onerror)
recorder.onerror();
}
}
};
};
Guacamole.RawAudioRecorder.prototype = new Guacamole.AudioRecorder();
Guacamole.RawAudioRecorder.isSupportedType = function isSupportedType4(mimetype) {
if (!Guacamole.AudioContextFactory.getAudioContext())
return false;
return Guacamole.RawAudioFormat.parse(mimetype) !== null;
};
Guacamole.RawAudioRecorder.getSupportedTypes = function getSupportedTypes4() {
if (!Guacamole.AudioContextFactory.getAudioContext())
return [];
return [
"audio/L8",
"audio/L16"
];
};
var Guacamole = Guacamole || {};
Guacamole.BlobReader = function(stream, mimetype) {
var guac_reader = this;
var length = 0;
var blob_builder;
if (window.BlobBuilder) blob_builder = new BlobBuilder();
else if (window.WebKitBlobBuilder) blob_builder = new WebKitBlobBuilder();
else if (window.MozBlobBuilder) blob_builder = new MozBlobBuilder();
else
blob_builder = new (function() {
var blobs = [];
this.append = function(data) {
blobs.push(new Blob([data], { "type": mimetype }));
};
this.getBlob = function() {
return new Blob(blobs, { "type": mimetype });
};
})();
stream.onblob = function(data) {
var binary = window.atob(data);
var arrayBuffer = new ArrayBuffer(binary.length);
var bufferView = new Uint8Array(arrayBuffer);
for (var i = 0; i < binary.length; i++)
bufferView[i] = binary.charCodeAt(i);
blob_builder.append(arrayBuffer);
length += arrayBuffer.byteLength;
if (guac_reader.onprogress)
guac_reader.onprogress(arrayBuffer.byteLength);
stream.sendAck("OK", 0);
};
stream.onend = function() {
if (guac_reader.onend)
guac_reader.onend();
};
this.getLength = function() {
return length;
};
this.getBlob = function() {
return blob_builder.getBlob();
};
this.onprogress = null;
this.onend = null;
};
var Guacamole = Guacamole || {};
Guacamole.BlobWriter = function BlobWriter(stream) {
var guacWriter = this;
var arrayBufferWriter = new Guacamole.ArrayBufferWriter(stream);
arrayBufferWriter.onack = function(status) {
if (guacWriter.onack)
guacWriter.onack(status);
};
var slice = function slice2(blob, start, end) {
var sliceImplementation = (blob.slice || blob.webkitSlice || blob.mozSlice).bind(blob);
var length = end - start;
if (length !== end) {
var sliceResult = sliceImplementation(start, length);
if (sliceResult.size === length)
return sliceResult;
}
return sliceImplementation(start, end);
};
this.sendBlob = function sendBlob(blob) {
var offset = 0;
var reader = new FileReader();
var readNextChunk = function readNextChunk2() {
if (offset >= blob.size) {
if (guacWriter.oncomplete)
guacWriter.oncomplete(blob);
return;
}
var chunk = slice(blob, offset, offset + arrayBufferWriter.blobLength);
offset += arrayBufferWriter.blobLength;
reader.readAsArrayBuffer(chunk);
};
reader.onload = function chunkLoadComplete() {
arrayBufferWriter.sendData(reader.result);
arrayBufferWriter.onack = function sendMoreChunks(status) {
if (guacWriter.onack)
guacWriter.onack(status);
if (status.isError())
return;
if (guacWriter.onprogress)
guacWriter.onprogress(blob, offset - arrayBufferWriter.blobLength);
readNextChunk();
};
};
reader.onerror = function chunkLoadFailed() {
if (guacWriter.onerror)
guacWriter.onerror(blob, offset, reader.error);
};
readNextChunk();
};
this.sendEnd = function sendEnd() {
arrayBufferWriter.sendEnd();
};
this.onack = null;
this.onerror = null;
this.onprogress = null;
this.oncomplete = null;
};
var Guacamole = Guacamole || {};
Guacamole.Client = function(tunnel) {
var guac_client = this;
var currentState = Guacamole.Client.State.IDLE;
var currentTimestamp = 0;
var KEEP_ALIVE_FREQUENCY = 5e3;
var keepAliveTimeout = null;
var lastSentKeepAlive = 0;
var lineCap = {
0: "butt",
1: "round",
2: "square"
};
var lineJoin = {
0: "bevel",
1: "miter",
2: "round"
};
var display = new Guacamole.Display();
var layers = {};
var audioPlayers = {};
var videoPlayers = {};
var parsers = [];
var streams = [];
var objects = [];
var stream_indices = new Guacamole.IntegerPool();
var output_streams = [];
function setState(state) {
if (state != currentState) {
currentState = state;
if (guac_client.onstatechange)
guac_client.onstatechange(currentState);
}
}
function isConnected() {
return currentState == Guacamole.Client.State.CONNECTED || currentState == Guacamole.Client.State.WAITING;
}
this.exportState = function exportState(callback) {
var state = {
"currentState": currentState,
"currentTimestamp": currentTimestamp,
"layers": {}
};
var layersSnapshot = {};
for (var key in layers) {
layersSnapshot[key] = layers[key];
}
display.flush(function populateLayers() {
for (var key2 in layersSnapshot) {
var index = parseInt(key2);
var layer = layersSnapshot[key2];
var exportLayer = {
"width": layer.width,
"height": layer.height
};
if (layer.width && layer.height) {
var canvas = layer.toCanvas();
exportLayer.url = canvas.toDataURL("image/png");
}
if (index > 0) {
exportLayer.x = layer.x;
exportLayer.y = layer.y;
exportLayer.z = layer.z;
exportLayer.alpha = layer.alpha;
exportLayer.matrix = layer.matrix;
exportLayer.parent = getLayerIndex(layer.parent);
}
state.layers[key2] = exportLayer;
}
callback(state);
});
};
this.importState = function importState(state, callback) {
var key;
var index;
currentState = state.currentState;
currentTimestamp = state.currentTimestamp;
display.cancel();
for (key in layers) {
index = parseInt(key);
if (index > 0)
layers[key].dispose();
}
layers = {};
for (key in state.layers) {
index = parseInt(key);
var importLayer = state.layers[key];
var layer = getLayer(index);
display.resize(layer, importLayer.width, importLayer.height);
if (importLayer.url) {
display.setChannelMask(layer, Guacamole.Layer.SRC);
display.draw(layer, 0, 0, importLayer.url);
}
if (index > 0 && importLayer.parent >= 0) {
var parent = getLayer(importLayer.parent);
display.move(layer, parent, importLayer.x, importLayer.y, importLayer.z);
display.shade(layer, importLayer.alpha);
var matrix = importLayer.matrix;
display.distort(
layer,
matrix[0],
matrix[1],
matrix[2],
matrix[3],
matrix[4],
matrix[5]
);
}
}
display.flush(callback);
};
this.getDisplay = function() {
return display;
};
this.sendSize = function(width, height) {
if (!isConnected())
return;
tunnel.sendMessage("size", width, height);
};
this.sendKeyEvent = function(pressed, keysym) {
if (!isConnected())
return;
tunnel.sendMessage("key", keysym, pressed);
};
this.sendMouseState = function sendMouseState(mouseState, applyDisplayScale) {
if (!isConnected())
return;
var x = mouseState.x;
var y = mouseState.y;
if (applyDisplayScale) {
x /= display.getScale();
y /= display.getScale();
}
display.moveCursor(
Math.floor(x),
Math.floor(y)
);
var buttonMask = 0;
if (mouseState.left) buttonMask |= 1;
if (mouseState.middle) buttonMask |= 2;
if (mouseState.right) buttonMask |= 4;
if (mouseState.up) buttonMask |= 8;
if (mouseState.down) buttonMask |= 16;
tunnel.sendMessage("mouse", Math.floor(x), Math.floor(y), buttonMask);
};
this.sendTouchState = function sendTouchState(touchState, applyDisplayScale) {
if (!isConnected())
return;
var x = touchState.x;
var y = touchState.y;
if (applyDisplayScale) {
x /= display.getScale();
y /= display.getScale();
}
tunnel.sendMessage(
"touch",
touchState.id,
Math.floor(x),
Math.floor(y),
Math.floor(touchState.radiusX),
Math.floor(touchState.radiusY),
touchState.angle,
touchState.force
);
};
this.createOutputStream = function createOutputStream() {
var index = stream_indices.next();
var stream = output_streams[index] = new Guacamole.OutputStream(guac_client, index);
return stream;
};
this.createAudioStream = function(mimetype) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("audio", stream.index, mimetype);
return stream;
};
this.createFileStream = function(mimetype, filename) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("file", stream.index, mimetype, filename);
return stream;
};
this.createPipeStream = function(mimetype, name) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("pipe", stream.index, mimetype, name);
return stream;
};
this.createClipboardStream = function(mimetype) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("clipboard", stream.index, mimetype);
return stream;
};
this.createArgumentValueStream = function createArgumentValueStream(mimetype, name) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("argv", stream.index, mimetype, name);
return stream;
};
this.createObjectOutputStream = function createObjectOutputStream(index, mimetype, name) {
var stream = guac_client.createOutputStream();
tunnel.sendMessage("put", index, stream.index, mimetype, name);
return stream;
};
this.requestObjectInputStream = function requestObjectInputStream(index, name) {
if (!isConnected())
return;
tunnel.sendMessage("get", index, name);
};
this.sendAck = function(index, message, code) {
if (!isConnected())
return;
tunnel.sendMessage("ack", index, message, code);
};
this.sendBlob = function(index, data) {
if (!isConnected())
return;
tunnel.sendMessage("blob", index, data);
};
this.endStream = function(index) {
if (!isConnected())
return;
tunnel.sendMessage("end", index);
if (output_streams[index]) {
stream_indices.free(index);
delete output_streams[index];
}
};
this.onstatechange = null;
this.onname = null;
this.onerror = null;
this.onmsg = null;
this.onjoin = null;
this.onleave = null;
this.onaudio = null;
this.onvideo = null;
this.onmultitouch = null;
this.onargv = null;
this.onclipboard = null;
this.onfile = null;
this.onfilesystem = null;
this.onpipe = null;
this.onrequired = null;
this.onsync = null;
var getLayer = function getLayer2(index) {
var layer = layers[index];
if (!layer) {
if (index === 0)
layer = display.getDefaultLayer();
else if (index > 0)
layer = display.createLayer();
else
layer = display.createBuffer();
layers[index] = layer;
}
return layer;
};
var getLayerIndex = function getLayerIndex2(layer) {
if (!layer)
return null;
for (var key in layers) {
if (layer === layers[key])
return parseInt(key);
}
return null;
};
function getParser(index) {
var parser = parsers[index];
if (parser == null) {
parser = parsers[index] = new Guacamole.Parser();
parser.oninstruction = tunnel.oninstruction;
}
return parser;
}
var layerPropertyHandlers = {
"miter-limit": function(layer, value) {
display.setMiterLimit(layer, parseFloat(value));
},
"multi-touch": function layerSupportsMultiTouch(layer, value) {
if (guac_client.onmultitouch && layer instanceof Guacamole.Display.VisibleLayer)
guac_client.onmultitouch(layer, parseInt(value));
}
};
var instructionHandlers = {
"ack": function(parameters) {
var stream_index = parseInt(parameters[0]);
var reason = parameters[1];
var code = parseInt(parameters[2]);
var stream = output_streams[stream_index];
if (stream) {
if (stream.onack)
stream.onack(new Guacamole.Status(code, reason));
if (code >= 256 && output_streams[stream_index] === stream) {
stream_indices.free(stream_index);
delete output_streams[stream_index];
}
}
},
"arc": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var x = parseInt(parameters[1]);
var y = parseInt(parameters[2]);
var radius = parseInt(parameters[3]);
var startAngle = parseFloat(parameters[4]);
var endAngle = parseFloat(parameters[5]);
var negative = parseInt(parameters[6]);
display.arc(layer, x, y, radius, startAngle, endAngle, negative != 0);
},
"argv": function(parameters) {
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
var name = parameters[2];
if (guac_client.onargv) {
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
guac_client.onargv(stream, mimetype, name);
} else
guac_client.sendAck(stream_index, "Receiving argument values unsupported", 256);
},
"audio": function(parameters) {
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
var audioPlayer = null;
if (guac_client.onaudio)
audioPlayer = guac_client.onaudio(stream, mimetype);
if (!audioPlayer)
audioPlayer = Guacamole.AudioPlayer.getInstance(stream, mimetype);
if (audioPlayer) {
audioPlayers[stream_index] = audioPlayer;
guac_client.sendAck(stream_index, "OK", 0);
} else
guac_client.sendAck(stream_index, "BAD TYPE", 783);
},
"blob": function(parameters) {
var stream_index = parseInt(parameters[0]);
var data = parameters[1];
var stream = streams[stream_index];
if (stream && stream.onblob)
stream.onblob(data);
},
"body": function handleBody(parameters) {
var objectIndex = parseInt(parameters[0]);
var object = objects[objectIndex];
var streamIndex = parseInt(parameters[1]);
var mimetype = parameters[2];
var name = parameters[3];
if (object && object.onbody) {
var stream = streams[streamIndex] = new Guacamole.InputStream(guac_client, streamIndex);
object.onbody(stream, mimetype, name);
} else
guac_client.sendAck(streamIndex, "Receipt of body unsupported", 256);
},
"cfill": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var r = parseInt(parameters[2]);
var g = parseInt(parameters[3]);
var b = parseInt(parameters[4]);
var a = parseInt(parameters[5]);
display.setChannelMask(layer, channelMask);
display.fillColor(layer, r, g, b, a);
},
"clip": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.clip(layer);
},
"clipboard": function(parameters) {
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
if (guac_client.onclipboard) {
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
guac_client.onclipboard(stream, mimetype);
} else
guac_client.sendAck(stream_index, "Clipboard unsupported", 256);
},
"close": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.close(layer);
},
"copy": function(parameters) {
var srcL = getLayer(parseInt(parameters[0]));
var srcX = parseInt(parameters[1]);
var srcY = parseInt(parameters[2]);
var srcWidth = parseInt(parameters[3]);
var srcHeight = parseInt(parameters[4]);
var channelMask = parseInt(parameters[5]);
var dstL = getLayer(parseInt(parameters[6]));
var dstX = parseInt(parameters[7]);
var dstY = parseInt(parameters[8]);
display.setChannelMask(dstL, channelMask);
display.copy(
srcL,
srcX,
srcY,
srcWidth,
srcHeight,
dstL,
dstX,
dstY
);
},
"cstroke": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var cap = lineCap[parseInt(parameters[2])];
var join = lineJoin[parseInt(parameters[3])];
var thickness = parseInt(parameters[4]);
var r = parseInt(parameters[5]);
var g = parseInt(parameters[6]);
var b = parseInt(parameters[7]);
var a = parseInt(parameters[8]);
display.setChannelMask(layer, channelMask);
display.strokeColor(layer, cap, join, thickness, r, g, b, a);
},
"cursor": function(parameters) {
var cursorHotspotX = parseInt(parameters[0]);
var cursorHotspotY = parseInt(parameters[1]);
var srcL = getLayer(parseInt(parameters[2]));
var srcX = parseInt(parameters[3]);
var srcY = parseInt(parameters[4]);
var srcWidth = parseInt(parameters[5]);
var srcHeight = parseInt(parameters[6]);
display.setCursor(
cursorHotspotX,
cursorHotspotY,
srcL,
srcX,
srcY,
srcWidth,
srcHeight
);
},
"curve": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var cp1x = parseInt(parameters[1]);
var cp1y = parseInt(parameters[2]);
var cp2x = parseInt(parameters[3]);
var cp2y = parseInt(parameters[4]);
var x = parseInt(parameters[5]);
var y = parseInt(parameters[6]);
display.curveTo(layer, cp1x, cp1y, cp2x, cp2y, x, y);
},
"disconnect": function handleDisconnect(parameters) {
guac_client.disconnect();
},
"dispose": function(parameters) {
var layer_index = parseInt(parameters[0]);
if (layer_index > 0) {
var layer = getLayer(layer_index);
display.dispose(layer);
delete layers[layer_index];
} else if (layer_index < 0)
delete layers[layer_index];
},
"distort": function(parameters) {
var layer_index = parseInt(parameters[0]);
var a = parseFloat(parameters[1]);
var b = parseFloat(parameters[2]);
var c = parseFloat(parameters[3]);
var d = parseFloat(parameters[4]);
var e = parseFloat(parameters[5]);
var f = parseFloat(parameters[6]);
if (layer_index >= 0) {
var layer = getLayer(layer_index);
display.distort(layer, a, b, c, d, e, f);
}
},
"error": function(parameters) {
var reason = parameters[0];
var code = parseInt(parameters[1]);
if (guac_client.onerror)
guac_client.onerror(new Guacamole.Status(code, reason));
guac_client.disconnect();
},
"end": function(parameters) {
var stream_index = parseInt(parameters[0]);
var stream = streams[stream_index];
if (stream) {
if (stream.onend)
stream.onend();
delete streams[stream_index];
}
},
"file": function(parameters) {
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
var filename = parameters[2];
if (guac_client.onfile) {
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
guac_client.onfile(stream, mimetype, filename);
} else
guac_client.sendAck(stream_index, "File transfer unsupported", 256);
},
"filesystem": function handleFilesystem(parameters) {
var objectIndex = parseInt(parameters[0]);
var name = parameters[1];
if (guac_client.onfilesystem) {
var object = objects[objectIndex] = new Guacamole.Object(guac_client, objectIndex);
guac_client.onfilesystem(object, name);
}
},
"identity": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.setTransform(layer, 1, 0, 0, 1, 0, 0);
},
"img": function(parameters) {
var stream_index = parseInt(parameters[0]);
var channelMask = parseInt(parameters[1]);
var layer = getLayer(parseInt(parameters[2]));
var mimetype = parameters[3];
var x = parseInt(parameters[4]);
var y = parseInt(parameters[5]);
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
display.setChannelMask(layer, channelMask);
display.drawStream(layer, x, y, stream, mimetype);
},
"jpeg": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var x = parseInt(parameters[2]);
var y = parseInt(parameters[3]);
var data = parameters[4];
display.setChannelMask(layer, channelMask);
display.draw(layer, x, y, "data:image/jpeg;base64," + data);
},
"lfill": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var srcLayer = getLayer(parseInt(parameters[2]));
display.setChannelMask(layer, channelMask);
display.fillLayer(layer, srcLayer);
},
"line": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var x = parseInt(parameters[1]);
var y = parseInt(parameters[2]);
display.lineTo(layer, x, y);
},
"lstroke": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var srcLayer = getLayer(parseInt(parameters[2]));
display.setChannelMask(layer, channelMask);
display.strokeLayer(layer, srcLayer);
},
"mouse": function handleMouse(parameters) {
var x = parseInt(parameters[0]);
var y = parseInt(parameters[1]);
display.showCursor(true);
display.moveCursor(x, y);
},
"move": function(parameters) {
var layer_index = parseInt(parameters[0]);
var parent_index = parseInt(parameters[1]);
var x = parseInt(parameters[2]);
var y = parseInt(parameters[3]);
var z = parseInt(parameters[4]);
if (layer_index > 0 && parent_index >= 0) {
var layer = getLayer(layer_index);
var parent = getLayer(parent_index);
display.move(layer, parent, x, y, z);
}
},
"msg": function(parameters) {
var userID;
var username;
var allowDefault = true;
var msgid = parseInt(parameters[0]);
if (guac_client.onmsg) {
allowDefault = guac_client.onmsg(msgid, parameters.slice(1));
if (allowDefault === void 0)
allowDefault = true;
}
if (allowDefault) {
switch (msgid) {
case Guacamole.Client.Message.USER_JOINED:
userID = parameters[1];
username = parameters[2];
if (guac_client.onjoin)
guac_client.onjoin(userID, username);
break;
case Guacamole.Client.Message.USER_LEFT:
userID = parameters[1];
username = parameters[2];
if (guac_client.onleave)
guac_client.onleave(userID, username);
break;
}
}
},
"name": function(parameters) {
if (guac_client.onname) guac_client.onname(parameters[0]);
},
"nest": function(parameters) {
var parser = getParser(parseInt(parameters[0]));
parser.receive(parameters[1]);
},
"pipe": function(parameters) {
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
var name = parameters[2];
if (guac_client.onpipe) {
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
guac_client.onpipe(stream, mimetype, name);
} else
guac_client.sendAck(stream_index, "Named pipes unsupported", 256);
},
"png": function(parameters) {
var channelMask = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var x = parseInt(parameters[2]);
var y = parseInt(parameters[3]);
var data = parameters[4];
display.setChannelMask(layer, channelMask);
display.draw(layer, x, y, "data:image/png;base64," + data);
},
"pop": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.pop(layer);
},
"push": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.push(layer);
},
"rect": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var x = parseInt(parameters[1]);
var y = parseInt(parameters[2]);
var w = parseInt(parameters[3]);
var h = parseInt(parameters[4]);
display.rect(layer, x, y, w, h);
},
"required": function required(parameters) {
if (guac_client.onrequired) guac_client.onrequired(parameters);
},
"reset": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
display.reset(layer);
},
"set": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var name = parameters[1];
var value = parameters[2];
var handler = layerPropertyHandlers[name];
if (handler)
handler(layer, value);
},
"shade": function(parameters) {
var layer_index = parseInt(parameters[0]);
var a = parseInt(parameters[1]);
if (layer_index >= 0) {
var layer = getLayer(layer_index);
display.shade(layer, a);
}
},
"size": function(parameters) {
var layer_index = parseInt(parameters[0]);
var layer = getLayer(layer_index);
var width = parseInt(parameters[1]);
var height = parseInt(parameters[2]);
display.resize(layer, width, height);
},
"start": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var x = parseInt(parameters[1]);
var y = parseInt(parameters[2]);
display.moveTo(layer, x, y);
},
"sync": function(parameters) {
var timestamp = parseInt(parameters[0]);
var frames = parameters[1] ? parseInt(parameters[1]) : 0;
display.flush(function displaySyncComplete() {
for (var index in audioPlayers) {
var audioPlayer = audioPlayers[index];
if (audioPlayer)
audioPlayer.sync();
}
if (timestamp !== currentTimestamp) {
tunnel.sendMessage("sync", timestamp);
currentTimestamp = timestamp;
}
}, timestamp, frames);
if (currentState === Guacamole.Client.State.WAITING)
setState(Guacamole.Client.State.CONNECTED);
if (guac_client.onsync)
guac_client.onsync(timestamp, frames);
},
"transfer": function(parameters) {
var srcL = getLayer(parseInt(parameters[0]));
var srcX = parseInt(parameters[1]);
var srcY = parseInt(parameters[2]);
var srcWidth = parseInt(parameters[3]);
var srcHeight = parseInt(parameters[4]);
var function_index = parseInt(parameters[5]);
var dstL = getLayer(parseInt(parameters[6]));
var dstX = parseInt(parameters[7]);
var dstY = parseInt(parameters[8]);
if (function_index === 3)
display.put(
srcL,
srcX,
srcY,
srcWidth,
srcHeight,
dstL,
dstX,
dstY
);
else if (function_index !== 5)
display.transfer(
srcL,
srcX,
srcY,
srcWidth,
srcHeight,
dstL,
dstX,
dstY,
Guacamole.Client.DefaultTransferFunction[function_index]
);
},
"transform": function(parameters) {
var layer = getLayer(parseInt(parameters[0]));
var a = parseFloat(parameters[1]);
var b = parseFloat(parameters[2]);
var c = parseFloat(parameters[3]);
var d = parseFloat(parameters[4]);
var e = parseFloat(parameters[5]);
var f = parseFloat(parameters[6]);
display.transform(layer, a, b, c, d, e, f);
},
"undefine": function handleUndefine(parameters) {
var objectIndex = parseInt(parameters[0]);
var object = objects[objectIndex];
if (object && object.onundefine)
object.onundefine();
},
"video": function(parameters) {
var stream_index = parseInt(parameters[0]);
var layer = getLayer(parseInt(parameters[1]));
var mimetype = parameters[2];
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
var videoPlayer = null;
if (guac_client.onvideo)
videoPlayer = guac_client.onvideo(stream, layer, mimetype);
if (!videoPlayer)
videoPlayer = Guacamole.VideoPlayer.getInstance(stream, layer, mimetype);
if (videoPlayer) {
videoPlayers[stream_index] = videoPlayer;
guac_client.sendAck(stream_index, "OK", 0);
} else
guac_client.sendAck(stream_index, "BAD TYPE", 783);
}
};
var sendKeepAlive = function sendKeepAlive2() {
tunnel.sendMessage("nop");
lastSentKeepAlive = (/* @__PURE__ */ new Date()).getTime();
};
var scheduleKeepAlive = function scheduleKeepAlive2() {
window.clearTimeout(keepAliveTimeout);
var currentTime = (/* @__PURE__ */ new Date()).getTime();
var keepAliveDelay = Math.max(lastSentKeepAlive + KEEP_ALIVE_FREQUENCY - currentTime, 0);
if (keepAliveDelay > 0)
keepAliveTimeout = window.setTimeout(sendKeepAlive, keepAliveDelay);
else
sendKeepAlive();
};
var stopKeepAlive = function stopKeepAlive2() {
window.clearTimeout(keepAliveTimeout);
};
tunnel.oninstruction = function(opcode, parameters) {
var handler = instructionHandlers[opcode];
if (handler)
handler(parameters);
scheduleKeepAlive();
};
this.disconnect = function() {
if (currentState != Guacamole.Client.State.DISCONNECTED && currentState != Guacamole.Client.State.DISCONNECTING) {
setState(Guacamole.Client.State.DISCONNECTING);
stopKeepAlive();
tunnel.sendMessage("disconnect");
tunnel.disconnect();
setState(Guacamole.Client.State.DISCONNECTED);
}
};
this.connect = function(data) {
setState(Guacamole.Client.State.CONNECTING);
try {
tunnel.connect(data);
} catch (status) {
setState(Guacamole.Client.State.IDLE);
throw status;
}
scheduleKeepAlive();
setState(Guacamole.Client.State.WAITING);
};
};
Guacamole.Client.State = {
/**
* The client is idle, with no active connection.
*
* @type number
*/
"IDLE": 0,
/**
* The client is in the process of establishing a connection.
*
* @type {!number}
*/
"CONNECTING": 1,
/**
* The client is waiting on further information or a remote server to
* establish the connection.
*
* @type {!number}
*/
"WAITING": 2,
/**
* The client is actively connected to a remote server.
*
* @type {!number}
*/
"CONNECTED": 3,
/**
* The client is in the process of disconnecting from the remote server.
*
* @type {!number}
*/
"DISCONNECTING": 4,
/**
* The client has completed the connection and is no longer connected.
*
* @type {!number}
*/
"DISCONNECTED": 5
};
Guacamole.Client.DefaultTransferFunction = {
/* BLACK */
0: function(src, dst) {
dst.red = dst.green = dst.blue = 0;
},
/* WHITE */
15: function(src, dst) {
dst.red = dst.green = dst.blue = 255;
},
/* SRC */
3: function(src, dst) {
dst.red = src.red;
dst.green = src.green;
dst.blue = src.blue;
dst.alpha = src.alpha;
},
/* DEST (no-op) */
5: function(src, dst) {
},
/* Invert SRC */
12: function(src, dst) {
dst.red = 255 & ~src.red;
dst.green = 255 & ~src.green;
dst.blue = 255 & ~src.blue;
dst.alpha = src.alpha;
},
/* Invert DEST */
10: function(src, dst) {
dst.red = 255 & ~dst.red;
dst.green = 255 & ~dst.green;
dst.blue = 255 & ~dst.blue;
},
/* AND */
1: function(src, dst) {
dst.red = src.red & dst.red;
dst.green = src.green & dst.green;
dst.blue = src.blue & dst.blue;
},
/* NAND */
14: function(src, dst) {
dst.red = 255 & ~(src.red & dst.red);
dst.green = 255 & ~(src.green & dst.green);
dst.blue = 255 & ~(src.blue & dst.blue);
},
/* OR */
7: function(src, dst) {
dst.red = src.red | dst.red;
dst.green = src.green | dst.green;
dst.blue = src.blue | dst.blue;
},
/* NOR */
8: function(src, dst) {
dst.red = 255 & ~(src.red | dst.red);
dst.green = 255 & ~(src.green | dst.green);
dst.blue = 255 & ~(src.blue | dst.blue);
},
/* XOR */
6: function(src, dst) {
dst.red = src.red ^ dst.red;
dst.green = src.green ^ dst.green;
dst.blue = src.blue ^ dst.blue;
},
/* XNOR */
9: function(src, dst) {
dst.red = 255 & ~(src.red ^ dst.red);
dst.green = 255 & ~(src.green ^ dst.green);
dst.blue = 255 & ~(src.blue ^ dst.blue);
},
/* AND inverted source */
4: function(src, dst) {
dst.red = 255 & (~src.red & dst.red);
dst.green = 255 & (~src.green & dst.green);
dst.blue = 255 & (~src.blue & dst.blue);
},
/* OR inverted source */
13: function(src, dst) {
dst.red = 255 & (~src.red | dst.red);
dst.green = 255 & (~src.green | dst.green);
dst.blue = 255 & (~src.blue | dst.blue);
},
/* AND inverted destination */
2: function(src, dst) {
dst.red = 255 & (src.red & ~dst.red);
dst.green = 255 & (src.green & ~dst.green);
dst.blue = 255 & (src.blue & ~dst.blue);
},
/* OR inverted destination */
11: function(src, dst) {
dst.red = 255 & (src.red | ~dst.red);
dst.green = 255 & (src.green | ~dst.green);
dst.blue = 255 & (src.blue | ~dst.blue);
}
};
Guacamole.Client.Message = {
/**
* A client message that indicates that a user has joined an existing
* connection. This message expects a single additional argument - the
* name of the user who has joined the connection.
*
* @type {!number}
*/
"USER_JOINED": 1,
/**
* A client message that indicates that a user has left an existing
* connection. This message expects a single additional argument - the
* name of the user who has left the connection.
*
* @type {!number}
*/
"USER_LEFT": 2
};
var Guacamole = Guacamole || {};
Guacamole.DataURIReader = function(stream, mimetype) {
var guac_reader = this;
var uri = "data:" + mimetype + ";base64,";
stream.onblob = function dataURIReaderBlob(data) {
uri += data;
};
stream.onend = function dataURIReaderEnd() {
if (guac_reader.onend)
guac_reader.onend();
};
this.getURI = function getURI() {
return uri;
};
this.onend = null;
};
var Guacamole = Guacamole || {};
Guacamole.Display = function() {
var guac_display = this;
var displayWidth = 0;
var displayHeight = 0;
var displayScale = 1;
var display = document.createElement("div");
display.style.position = "relative";
display.style.width = displayWidth + "px";
display.style.height = displayHeight + "px";
display.style.transformOrigin = display.style.webkitTransformOrigin = display.style.MozTransformOrigin = display.style.OTransformOrigin = display.style.msTransformOrigin = "0 0";
var default_layer = new Guacamole.Display.VisibleLayer(displayWidth, displayHeight);
var cursor = new Guacamole.Display.VisibleLayer(0, 0);
cursor.setChannelMask(Guacamole.Layer.SRC);
display.appendChild(default_layer.getElement());
display.appendChild(cursor.getElement());
var bounds = document.createElement("div");
bounds.style.position = "relative";
bounds.style.width = displayWidth * displayScale + "px";
bounds.style.height = displayHeight * displayScale + "px";
bounds.appendChild(display);
this.cursorHotspotX = 0;
this.cursorHotspotY = 0;
this.cursorX = 0;
this.cursorY = 0;
this.statisticWindow = 0;
this.onresize = null;
this.oncursor = null;
this.onstatistics = null;
var tasks = [];
var frames = [];
var syncFlush = function syncFlush2() {
var localTimestamp = 0;
var remoteTimestamp = 0;
var renderedLogicalFrames = 0;
var rendered_frames = 0;
while (rendered_frames < frames.length) {
var frame = frames[rendered_frames];
if (!frame.isReady())
break;
frame.flush();
localTimestamp = frame.localTimestamp;
remoteTimestamp = frame.remoteTimestamp;
renderedLogicalFrames += frame.logicalFrames;
rendered_frames++;
}
frames.splice(0, rendered_frames);
if (rendered_frames)
notifyFlushed(localTimestamp, remoteTimestamp, renderedLogicalFrames);
};
var statistics = [];
var notifyFlushed = function notifyFlushed2(localTimestamp, remoteTimestamp, logicalFrames) {
if (!guac_display.statisticWindow)
return;
var current = (/* @__PURE__ */ new Date()).getTime();
for (var first = 0; first < statistics.length; first++) {
if (current - statistics[first].timestamp <= guac_display.statisticWindow)
break;
}
statistics.splice(0, first - 1);
statistics.push({
localTimestamp,
remoteTimestamp,
timestamp: current,
frames: logicalFrames
});
var statDuration = (statistics[statistics.length - 1].timestamp - statistics[0].timestamp) / 1e3;
var remoteDuration = (statistics[statistics.length - 1].remoteTimestamp - statistics[0].remoteTimestamp) / 1e3;
var localFrames = statistics.length;
var remoteFrames = statistics.reduce(function sumFrames(prev, stat) {
return prev + stat.frames;
}, 0);
var drops = statistics.reduce(function sumDrops(prev, stat) {
return prev + Math.max(0, stat.frames - 1);
}, 0);
var stats = new Guacamole.Display.Statistics({
processingLag: current - localTimestamp,
desktopFps: remoteDuration && remoteFrames ? remoteFrames / remoteDuration : null,
clientFps: statDuration ? localFrames / statDuration : null,
serverFps: remoteDuration ? localFrames / remoteDuration : null,
dropRate: remoteDuration ? drops / remoteDuration : null
});
if (guac_display.onstatistics)
guac_display.onstatistics(stats);
};
function __flush_frames() {
syncFlush();
}
var Frame = function Frame2(callback, tasks2, timestamp, logicalFrames) {
this.localTimestamp = (/* @__PURE__ */ new Date()).getTime();
this.remoteTimestamp = timestamp || this.localTimestamp;
this.logicalFrames = logicalFrames || 0;
this.cancel = function cancel() {
callback = null;
tasks2.forEach(function cancelTask(task) {
task.cancel();
});
tasks2 = [];
};
this.isReady = function() {
for (var i = 0; i < tasks2.length; i++) {
if (tasks2[i].blocked)
return false;
}
return true;
};
this.flush = function() {
for (var i = 0; i < tasks2.length; i++)
tasks2[i].execute();
if (callback) callback();
};
};
function Task(taskHandler, blocked) {
var task = this;
this.blocked = blocked;
this.cancel = function cancel() {
task.blocked = false;
taskHandler = null;
};
this.unblock = function() {
if (task.blocked) {
task.blocked = false;
if (frames.length)
__flush_frames();
}
};
this.execute = function() {
if (taskHandler) taskHandler();
};
}
function scheduleTask(handler, blocked) {
var task = new Task(handler, blocked);
tasks.push(task);
return task;
}
this.getElement = function() {
return bounds;
};
this.getWidth = function() {
return displayWidth;
};
this.getHeight = function() {
return displayHeight;
};
this.getDefaultLayer = function() {
return default_layer;
};
this.getCursorLayer = function() {
return cursor;
};
this.createLayer = function() {
var layer = new Guacamole.Display.VisibleLayer(displayWidth, displayHeight);
layer.move(default_layer, 0, 0, 0);
return layer;
};
this.createBuffer = function() {
var buffer = new Guacamole.Layer(0, 0);
buffer.autosize = 1;
return buffer;
};
this.flush = function(callback, timestamp, logicalFrames) {
frames.push(new Frame(callback, tasks, timestamp, logicalFrames));
tasks = [];
__flush_frames();
};
this.cancel = function cancel() {
frames.forEach(function cancelFrame(frame) {
frame.cancel();
});
frames = [];
tasks.forEach(function cancelTask(task) {
task.cancel();
});
tasks = [];
};
this.setCursor = function(hotspotX, hotspotY, layer, srcx, srcy, srcw, srch) {
scheduleTask(function __display_set_cursor() {
guac_display.cursorHotspotX = hotspotX;
guac_display.cursorHotspotY = hotspotY;
cursor.resize(srcw, srch);
cursor.copy(layer, srcx, srcy, srcw, srch, 0, 0);
guac_display.moveCursor(guac_display.cursorX, guac_display.cursorY);
if (guac_display.oncursor)
guac_display.oncursor(cursor.toCanvas(), hotspotX, hotspotY);
});
};
this.showCursor = function(shown) {
var element = cursor.getElement();
var parent = element.parentNode;
if (shown === false) {
if (parent)
parent.removeChild(element);
} else if (parent !== display)
display.appendChild(element);
};
this.moveCursor = function(x, y) {
cursor.translate(
x - guac_display.cursorHotspotX,
y - guac_display.cursorHotspotY
);
guac_display.cursorX = x;
guac_display.cursorY = y;
};
this.resize = function(layer, width, height) {
scheduleTask(function __display_resize() {
layer.resize(width, height);
if (layer === default_layer) {
displayWidth = width;
displayHeight = height;
display.style.width = displayWidth + "px";
display.style.height = displayHeight + "px";
bounds.style.width = displayWidth * displayScale + "px";
bounds.style.height = displayHeight * displayScale + "px";
if (guac_display.onresize)
guac_display.onresize(width, height);
}
});
};
this.drawImage = function(layer, x, y, image) {
scheduleTask(function __display_drawImage() {
layer.drawImage(x, y, image);
});
};
this.drawBlob = function(layer, x, y, blob) {
var task;
if (window.createImageBitmap) {
var bitmap;
task = scheduleTask(function drawImageBitmap() {
layer.drawImage(x, y, bitmap);
}, true);
window.createImageBitmap(blob).then(function bitmapLoaded(decoded) {
bitmap = decoded;
task.unblock();
});
} else {
var url = URL.createObjectURL(blob);
task = scheduleTask(function __display_drawBlob() {
if (image.width && image.height)
layer.drawImage(x, y, image);
URL.revokeObjectURL(url);
}, true);
var image = new Image();
image.onload = task.unblock;
image.onerror = task.unblock;
image.src = url;
}
};
this.drawStream = function drawStream(layer, x, y, stream, mimetype) {
if (window.ImageDecoder && window.ReadableStream) {
var imageDecoder = new ImageDecoder({
type: mimetype,
data: stream.toReadableStream()
});
var decodedFrame = null;
var task = scheduleTask(function drawImageBitmap() {
layer.drawImage(x, y, decodedFrame);
}, true);
imageDecoder.decode({ completeFramesOnly: true }).then(function bitmapLoaded(result) {
decodedFrame = result.image;
task.unblock();
});
} else {
var reader = new Guacamole.DataURIReader(stream, mimetype);
reader.onend = function drawImageDataURI() {
guac_display.draw(layer, x, y, reader.getURI());
};
}
};
this.draw = function(layer, x, y, url) {
var task = scheduleTask(function __display_draw() {
if (image.width && image.height)
layer.drawImage(x, y, image);
}, true);
var image = new Image();
image.onload = task.unblock;
image.onerror = task.unblock;
image.src = url;
};
this.play = function(layer, mimetype, duration, url) {
var video = document.createElement("video");
video.type = mimetype;
video.src = url;
video.addEventListener("play", function() {
function render_callback() {
layer.drawImage(0, 0, video);
if (!video.ended)
window.setTimeout(render_callback, 20);
}
render_callback();
}, false);
scheduleTask(video.play);
};
this.transfer = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y, transferFunction) {
scheduleTask(function __display_transfer() {
dstLayer.transfer(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction);
});
};
this.put = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y) {
scheduleTask(function __display_put() {
dstLayer.put(srcLayer, srcx, srcy, srcw, srch, x, y);
});
};
this.copy = function(srcLayer, srcx, srcy, srcw, srch, dstLayer, x, y) {
scheduleTask(function __display_copy() {
dstLayer.copy(srcLayer, srcx, srcy, srcw, srch, x, y);
});
};
this.moveTo = function(layer, x, y) {
scheduleTask(function __display_moveTo() {
layer.moveTo(x, y);
});
};
this.lineTo = function(layer, x, y) {
scheduleTask(function __display_lineTo() {
layer.lineTo(x, y);
});
};
this.arc = function(layer, x, y, radius, startAngle, endAngle, negative) {
scheduleTask(function __display_arc() {
layer.arc(x, y, radius, startAngle, endAngle, negative);
});
};
this.curveTo = function(layer, cp1x, cp1y, cp2x, cp2y, x, y) {
scheduleTask(function __display_curveTo() {
layer.curveTo(cp1x, cp1y, cp2x, cp2y, x, y);
});
};
this.close = function(layer) {
scheduleTask(function __display_close() {
layer.close();
});
};
this.rect = function(layer, x, y, w, h) {
scheduleTask(function __display_rect() {
layer.rect(x, y, w, h);
});
};
this.clip = function(layer) {
scheduleTask(function __display_clip() {
layer.clip();
});
};
this.strokeColor = function(layer, cap, join, thickness, r, g, b, a) {
scheduleTask(function __display_strokeColor() {
layer.strokeColor(cap, join, thickness, r, g, b, a);
});
};
this.fillColor = function(layer, r, g, b, a) {
scheduleTask(function __display_fillColor() {
layer.fillColor(r, g, b, a);
});
};
this.strokeLayer = function(layer, cap, join, thickness, srcLayer) {
scheduleTask(function __display_strokeLayer() {
layer.strokeLayer(cap, join, thickness, srcLayer);
});
};
this.fillLayer = function(layer, srcLayer) {
scheduleTask(function __display_fillLayer() {
layer.fillLayer(srcLayer);
});
};
this.push = function(layer) {
scheduleTask(function __display_push() {
layer.push();
});
};
this.pop = function(layer) {
scheduleTask(function __display_pop() {
layer.pop();
});
};
this.reset = function(layer) {
scheduleTask(function __display_reset() {
layer.reset();
});
};
this.setTransform = function(layer, a, b, c, d, e, f) {
scheduleTask(function __display_setTransform() {
layer.setTransform(a, b, c, d, e, f);
});
};
this.transform = function(layer, a, b, c, d, e, f) {
scheduleTask(function __display_transform() {
layer.transform(a, b, c, d, e, f);
});
};
this.setChannelMask = function(layer, mask) {
scheduleTask(function __display_setChannelMask() {
layer.setChannelMask(mask);
});
};
this.setMiterLimit = function(layer, limit) {
scheduleTask(function __display_setMiterLimit() {
layer.setMiterLimit(limit);
});
};
this.dispose = function dispose(layer) {
scheduleTask(function disposeLayer() {
layer.dispose();
});
};
this.distort = function distort(layer, a, b, c, d, e, f) {
scheduleTask(function distortLayer() {
layer.distort(a, b, c, d, e, f);
});
};
this.move = function move(layer, parent, x, y, z) {
scheduleTask(function moveLayer() {
layer.move(parent, x, y, z);
});
};
this.shade = function shade(layer, alpha) {
scheduleTask(function shadeLayer() {
layer.shade(alpha);
});
};
this.scale = function(scale) {
display.style.transform = display.style.WebkitTransform = display.style.MozTransform = display.style.OTransform = display.style.msTransform = "scale(" + scale + "," + scale + ")";
displayScale = scale;
bounds.style.width = displayWidth * displayScale + "px";
bounds.style.height = displayHeight * displayScale + "px";
};
this.getScale = function() {
return displayScale;
};
this.flatten = function() {
var canvas = document.createElement("canvas");
canvas.width = default_layer.width;
canvas.height = default_layer.height;
var context = canvas.getContext("2d");
function get_children(layer) {
var children = [];
for (var index in layer.children)
children.push(layer.children[index]);
children.sort(function children_comparator(a, b) {
var diff = a.z - b.z;
if (diff !== 0)
return diff;
var a_element = a.getElement();
var b_element = b.getElement();
var position = b_element.compareDocumentPosition(a_element);
if (position & Node.DOCUMENT_POSITION_PRECEDING) return -1;
if (position & Node.DOCUMENT_POSITION_FOLLOWING) return 1;
return 0;
});
return children;
}
function draw_layer(layer, x, y) {
if (layer.width > 0 && layer.height > 0) {
var initial_alpha = context.globalAlpha;
context.globalAlpha *= layer.alpha / 255;
context.drawImage(layer.getCanvas(), x, y);
var children = get_children(layer);
for (var i = 0; i < children.length; i++) {
var child = children[i];
draw_layer(child, x + child.x, y + child.y);
}
context.globalAlpha = initial_alpha;
}
}
draw_layer(default_layer, 0, 0);
return canvas;
};
};
Guacamole.Display.VisibleLayer = function(width, height) {
Guacamole.Layer.apply(this, [width, height]);
var layer = this;
this.__unique_id = Guacamole.Display.VisibleLayer.__next_id++;
this.alpha = 255;
this.x = 0;
this.y = 0;
this.z = 0;
this.matrix = [1, 0, 0, 1, 0, 0];
this.parent = null;
this.children = {};
var canvas = layer.getCanvas();
canvas.style.position = "absolute";
canvas.style.left = "0px";
canvas.style.top = "0px";
var div = document.createElement("div");
div.appendChild(canvas);
div.style.width = width + "px";
div.style.height = height + "px";
div.style.position = "absolute";
div.style.left = "0px";
div.style.top = "0px";
div.style.overflow = "hidden";
var __super_resize = this.resize;
this.resize = function(width2, height2) {
div.style.width = width2 + "px";
div.style.height = height2 + "px";
__super_resize(width2, height2);
};
this.getElement = function() {
return div;
};
var translate = "translate(0px, 0px)";
var matrix = "matrix(1, 0, 0, 1, 0, 0)";
this.translate = function(x, y) {
layer.x = x;
layer.y = y;
translate = "translate(" + x + "px," + y + "px)";
div.style.transform = div.style.WebkitTransform = div.style.MozTransform = div.style.OTransform = div.style.msTransform = translate + " " + matrix;
};
this.move = function(parent, x, y, z) {
if (layer.parent !== parent) {
if (layer.parent)
delete layer.parent.children[layer.__unique_id];
layer.parent = parent;
parent.children[layer.__unique_id] = layer;
var parent_element = parent.getElement();
parent_element.appendChild(div);
}
layer.translate(x, y);
layer.z = z;
div.style.zIndex = z;
};
this.shade = function(a) {
layer.alpha = a;
div.style.opacity = a / 255;
};
this.dispose = function() {
if (layer.parent) {
delete layer.parent.children[layer.__unique_id];
layer.parent = null;
}
if (div.parentNode)
div.parentNode.removeChild(div);
};
this.distort = function(a, b, c, d, e, f) {
layer.matrix = [a, b, c, d, e, f];
matrix = /* a c e
* b d f
* 0 0 1
*/
"matrix(" + a + "," + b + "," + c + "," + d + "," + e + "," + f + ")";
div.style.transform = div.style.WebkitTransform = div.style.MozTransform = div.style.OTransform = div.style.msTransform = translate + " " + matrix;
};
};
Guacamole.Display.VisibleLayer.__next_id = 0;
Guacamole.Display.Statistics = function Statistics(template) {
template = template || {};
this.processingLag = template.processingLag;
this.desktopFps = template.desktopFps;
this.serverFps = template.serverFps;
this.clientFps = template.clientFps;
this.dropRate = template.dropRate;
};
var Guacamole = Guacamole || {};
Guacamole.Event = function Event(type) {
this.type = type;
this.timestamp = (/* @__PURE__ */ new Date()).getTime();
this.getAge = function getAge() {
return (/* @__PURE__ */ new Date()).getTime() - this.timestamp;
};
this.invokeLegacyHandler = function invokeLegacyHandler(eventTarget) {
};
};
Guacamole.Event.DOMEvent = function DOMEvent(type, events) {
Guacamole.Event.call(this, type);
events = events || [];
if (!Array.isArray(events))
events = [events];
this.preventDefault = function preventDefault() {
events.forEach(function applyPreventDefault(event) {
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
});
};
this.stopPropagation = function stopPropagation() {
events.forEach(function applyStopPropagation(event) {
event.stopPropagation();
});
};
};
Guacamole.Event.DOMEvent.cancelEvent = function cancelEvent(event) {
event.stopPropagation();
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
};
Guacamole.Event.Target = function Target() {
var listeners = {};
this.on = function on(type, listener) {
var relevantListeners = listeners[type];
if (!relevantListeners)
listeners[type] = relevantListeners = [];
relevantListeners.push(listener);
};
this.onEach = function onEach(types, listener) {
types.forEach(function addListener(type) {
this.on(type, listener);
}, this);
};
this.dispatch = function dispatch(event) {
event.invokeLegacyHandler(this);
var relevantListeners = listeners[event.type];
if (relevantListeners) {
for (var i = 0; i < relevantListeners.length; i++) {
relevantListeners[i](event, this);
}
}
};
this.off = function off(type, listener) {
var relevantListeners = listeners[type];
if (!relevantListeners)
return false;
for (var i = 0; i < relevantListeners.length; i++) {
if (relevantListeners[i] === listener) {
relevantListeners.splice(i, 1);
return true;
}
}
return false;
};
this.offEach = function offEach(types, listener) {
var changed = false;
types.forEach(function removeListener(type) {
changed |= this.off(type, listener);
}, this);
return changed;
};
};
var Guacamole = Guacamole || {};
Guacamole.InputSink = function InputSink() {
var sink = this;
var field = document.createElement("textarea");
field.style.position = "fixed";
field.style.outline = "none";
field.style.border = "none";
field.style.margin = "0";
field.style.padding = "0";
field.style.height = "0";
field.style.width = "0";
field.style.left = "0";
field.style.bottom = "0";
field.style.resize = "none";
field.style.background = "transparent";
field.style.color = "transparent";
field.addEventListener("keypress", function clearKeypress(e) {
field.value = "";
}, false);
field.addEventListener("compositionend", function clearCompletedComposition(e) {
if (e.data)
field.value = "";
}, false);
field.addEventListener("input", function clearCompletedInput(e) {
if (e.data && !e.isComposing)
field.value = "";
}, false);
field.addEventListener("focus", function focusReceived() {
window.setTimeout(function deferRefocus() {
field.click();
field.select();
}, 0);
}, true);
this.focus = function focus() {
window.setTimeout(function deferRefocus() {
field.focus();
}, 0);
};
this.getElement = function getElement() {
return field;
};
document.addEventListener("keydown", function refocusSink(e) {
var focused = document.activeElement;
if (focused && focused !== document.body) {
var rect = focused.getBoundingClientRect();
if (rect.left + rect.width > 0 && rect.top + rect.height > 0)
return;
}
sink.focus();
}, true);
};
var Guacamole = Guacamole || {};
Guacamole.InputStream = function(client, index) {
var guac_stream = this;
this.index = index;
this.onblob = null;
this.onend = null;
this.sendAck = function(message, code) {
client.sendAck(guac_stream.index, message, code);
};
this.toReadableStream = function toReadableStream() {
return new ReadableStream({
type: "bytes",
start: function startStream(controller) {
var reader = new Guacamole.ArrayBufferReader(guac_stream);
reader.ondata = function dataReceived(data) {
if (controller.byobRequest) {
var view = controller.byobRequest.view;
var length = Math.min(view.byteLength, data.byteLength);
var byobBlock = new Uint8Array(data, 0, length);
view.buffer.set(byobBlock);
controller.byobRequest.respond(length);
if (length < data.byteLength) {
controller.enqueue(data.slice(length));
}
} else {
controller.enqueue(new Uint8Array(data));
}
};
reader.onend = function dataComplete() {
controller.close();
};
}
});
};
};
var Guacamole = Guacamole || {};
Guacamole.IntegerPool = function() {
var guac_pool = this;
var pool = [];
this.next_int = 0;
this.next = function() {
if (pool.length > 0)
return pool.shift();
return guac_pool.next_int++;
};
this.free = function(integer) {
pool.push(integer);
};
};
var Guacamole = Guacamole || {};
Guacamole.JSONReader = function guacamoleJSONReader(stream) {
var guacReader = this;
var stringReader = new Guacamole.StringReader(stream);
var json = "";
this.getLength = function getLength() {
return json.length;
};
this.getJSON = function getJSON() {
return JSON.parse(json);
};
stringReader.ontext = function ontext(text) {
json += text;
if (guacReader.onprogress)
guacReader.onprogress(text.length);
};
stringReader.onend = function onend() {
if (guacReader.onend)
guacReader.onend();
};
this.onprogress = null;
this.onend = null;
};
var Guacamole = Guacamole || {};
Guacamole.KeyEventInterpreter = function KeyEventInterpreter(startTimestamp) {
if (startTimestamp === void 0 || startTimestamp === null)
startTimestamp = 0;
var _KNOWN_KEYS = [
{ keysym: 65027, name: "AltGr" },
{ keysym: 65288, name: "Backspace" },
{ keysym: 65289, name: "Tab" },
{ keysym: 65291, name: "Clear" },
{ keysym: 65293, name: "Return", value: "\n" },
{ keysym: 65299, name: "Pause" },
{ keysym: 65300, name: "Scroll" },
{ keysym: 65301, name: "SysReq" },
{ keysym: 65307, name: "Escape" },
{ keysym: 65360, name: "Home" },
{ keysym: 65361, name: "Left" },
{ keysym: 65362, name: "Up" },
{ keysym: 65363, name: "Right" },
{ keysym: 65364, name: "Down" },
{ keysym: 65365, name: "Page Up" },
{ keysym: 65366, name: "Page Down" },
{ keysym: 65367, name: "End" },
{ keysym: 65379, name: "Insert" },
{ keysym: 65381, name: "Undo" },
{ keysym: 65386, name: "Help" },
{ keysym: 65407, name: "Num" },
{ keysym: 65408, name: "Space", value: " " },
{ keysym: 65421, name: "Enter", value: "\n" },
{ keysym: 65429, name: "Home" },
{ keysym: 65430, name: "Left" },
{ keysym: 65431, name: "Up" },
{ keysym: 65432, name: "Right" },
{ keysym: 65433, name: "Down" },
{ keysym: 65434, name: "Page Up" },
{ keysym: 65435, name: "Page Down" },
{ keysym: 65436, name: "End" },
{ keysym: 65438, name: "Insert" },
{ keysym: 65450, name: "*", value: "*" },
{ keysym: 65451, name: "+", value: "+" },
{ keysym: 65453, name: "-", value: "-" },
{ keysym: 65454, name: ".", value: "." },
{ keysym: 65455, name: "/", value: "/" },
{ keysym: 65456, name: "0", value: "0" },
{ keysym: 65457, name: "1", value: "1" },
{ keysym: 65458, name: "2", value: "2" },
{ keysym: 65459, name: "3", value: "3" },
{ keysym: 65460, name: "4", value: "4" },
{ keysym: 65461, name: "5", value: "5" },
{ keysym: 65462, name: "6", value: "6" },
{ keysym: 65463, name: "7", value: "7" },
{ keysym: 65464, name: "8", value: "8" },
{ keysym: 65465, name: "9", value: "9" },
{ keysym: 65470, name: "F1" },
{ keysym: 65471, name: "F2" },
{ keysym: 65472, name: "F3" },
{ keysym: 65473, name: "F4" },
{ keysym: 65474, name: "F5" },
{ keysym: 65475, name: "F6" },
{ keysym: 65476, name: "F7" },
{ keysym: 65477, name: "F8" },
{ keysym: 65478, name: "F9" },
{ keysym: 65479, name: "F10" },
{ keysym: 65480, name: "F11" },
{ keysym: 65481, name: "F12" },
{ keysym: 65482, name: "F13" },
{ keysym: 65483, name: "F14" },
{ keysym: 65484, name: "F15" },
{ keysym: 65485, name: "F16" },
{ keysym: 65486, name: "F17" },
{ keysym: 65487, name: "F18" },
{ keysym: 65488, name: "F19" },
{ keysym: 65489, name: "F20" },
{ keysym: 65490, name: "F21" },
{ keysym: 65491, name: "F22" },
{ keysym: 65492, name: "F23" },
{ keysym: 65493, name: "F24" },
{ keysym: 65505, name: "Shift" },
{ keysym: 65506, name: "Shift" },
{ keysym: 65507, name: "Ctrl" },
{ keysym: 65508, name: "Ctrl" },
{ keysym: 65509, name: "Caps" },
{ keysym: 65511, name: "Meta" },
{ keysym: 65512, name: "Meta" },
{ keysym: 65513, name: "Alt" },
{ keysym: 65514, name: "Alt" },
{ keysym: 65515, name: "Super" },
{ keysym: 65516, name: "Super" },
{ keysym: 65517, name: "Hyper" },
{ keysym: 65518, name: "Hyper" },
{ keysym: 65535, name: "Delete" }
];
var KNOWN_KEYS = {};
_KNOWN_KEYS.forEach(function createKeyDefinitionMap(keyDefinition) {
KNOWN_KEYS[keyDefinition.keysym] = new Guacamole.KeyEventInterpreter.KeyDefinition(keyDefinition);
});
var parsedEvents = [];
function getUnicodeKeyDefinition(keysym) {
if (keysym < 0 || keysym > 255 && (keysym | 65535) != 16842751)
return null;
var codepoint = keysym & 65535;
var name = String.fromCharCode(codepoint);
return new Guacamole.KeyEventInterpreter.KeyDefinition({
keysym,
name,
value: name
});
}
function getKeyDefinitionByKeysym(keysym) {
if (keysym in KNOWN_KEYS)
return KNOWN_KEYS[keysym];
var definition = getUnicodeKeyDefinition(keysym);
if (definition != null)
return definition;
return new Guacamole.KeyEventInterpreter.KeyDefinition({
keysym,
name: "0x" + String(keysym.toString(16))
});
}
this.handleKeyEvent = function handleKeyEvent(args) {
var keysym = parseInt(args[0]);
var pressed = parseInt(args[1]);
var timestamp = parseInt(args[2]);
var relativeTimestap = timestamp - startTimestamp;
var definition = getKeyDefinitionByKeysym(keysym);
parsedEvents.push(new Guacamole.KeyEventInterpreter.KeyEvent({
definition,
pressed,
timestamp: relativeTimestap
}));
};
this.getEvents = function getEvents() {
return parsedEvents;
};
};
Guacamole.KeyEventInterpreter.KeyDefinition = function KeyDefinition(template) {
template = template || {};
this.keysym = parseInt(template.keysym);
this.name = template.name;
this.value = template.value;
};
Guacamole.KeyEventInterpreter.KeyEvent = function KeyEvent(template) {
template = template || {};
this.definition = template.definition;
this.pressed = !!template.pressed;
this.timestamp = template.timestamp;
};
var Guacamole = Guacamole || {};
Guacamole.Keyboard = function Keyboard(element) {
var guac_keyboard = this;
var guacKeyboardID = Guacamole.Keyboard._nextID++;
var EVENT_MARKER = "_GUAC_KEYBOARD_HANDLED_BY_" + guacKeyboardID;
this.onkeydown = null;
this.onkeyup = null;
var quirks = {
/**
* Whether keyup events are universally unreliable.
*
* @type {!boolean}
*/
keyupUnreliable: false,
/**
* Whether the Alt key is actually a modifier for typable keys and is
* thus never used for keyboard shortcuts.
*
* @type {!boolean}
*/
altIsTypableOnly: false,
/**
* Whether we can rely on receiving a keyup or keydown event for the
* Caps Lock key.
*
* @type {!boolean}
*/
capsLockKeyEventUnreliable: false
};
if (navigator && navigator.platform) {
if (navigator.platform.match(/ipad|iphone|ipod/i))
quirks.keyupUnreliable = true;
else if (navigator.platform.match(/^mac/i)) {
quirks.altIsTypableOnly = true;
quirks.capsLockKeyEventUnreliable = true;
}
}
var KeyEvent2 = function KeyEvent3(orig) {
var key_event = this;
this.keyCode = orig ? orig.which || orig.keyCode : 0;
this.keyIdentifier = orig && orig.keyIdentifier;
this.key = orig && orig.key;
this.location = orig ? getEventLocation(orig) : 0;
this.modifiers = orig ? Guacamole.Keyboard.ModifierState.fromKeyboardEvent(orig) : new Guacamole.Keyboard.ModifierState();
this.timestamp = (/* @__PURE__ */ new Date()).getTime();
this.defaultPrevented = false;
this.keysym = null;
this.reliable = false;
this.getAge = function() {
return (/* @__PURE__ */ new Date()).getTime() - key_event.timestamp;
};
};
var KeydownEvent = function KeydownEvent2(orig) {
KeyEvent2.call(this, orig);
this.keysym = keysym_from_key_identifier(this.key, this.location) || keysym_from_keycode(this.keyCode, this.location);
this.keyupReliable = !quirks.keyupUnreliable;
if (this.keysym && !isPrintable(this.keysym))
this.reliable = true;
if (!this.keysym && key_identifier_sane(this.keyCode, this.keyIdentifier))
this.keysym = keysym_from_key_identifier(this.keyIdentifier, this.location, this.modifiers.shift);
if (this.modifiers.meta && this.keysym !== 65511 && this.keysym !== 65512)
this.keyupReliable = false;
else if (this.keysym === 65509 && quirks.capsLockKeyEventUnreliable)
this.keyupReliable = false;
var prevent_alt = !this.modifiers.ctrl && !quirks.altIsTypableOnly;
if (quirks.altIsTypableOnly && (this.keysym === 65513 || this.keysym === 65514))
this.keysym = 65027;
var prevent_ctrl = !this.modifiers.alt;
if (prevent_ctrl && this.modifiers.ctrl || prevent_alt && this.modifiers.alt || this.modifiers.meta || this.modifiers.hyper)
this.reliable = true;
recentKeysym[this.keyCode] = this.keysym;
};
KeydownEvent.prototype = new KeyEvent2();
var KeypressEvent = function KeypressEvent2(orig) {
KeyEvent2.call(this, orig);
this.keysym = keysym_from_charcode(this.keyCode);
this.reliable = true;
};
KeypressEvent.prototype = new KeyEvent2();
var KeyupEvent = function KeyupEvent2(orig) {
KeyEvent2.call(this, orig);
if (this.keyCode == 20 && quirks.capsLockKeyEventUnreliable) {
eventLog.push(new KeydownEvent(this));
return;
}
this.keysym = keysym_from_keycode(this.keyCode, this.location) || keysym_from_key_identifier(this.key, this.location);
if (!guac_keyboard.pressed[this.keysym])
this.keysym = recentKeysym[this.keyCode] || this.keysym;
this.reliable = true;
};
KeyupEvent.prototype = new KeyEvent2();
var eventLog = [];
var keycodeKeysyms = {
8: [65288],
// backspace
9: [65289],
// tab
12: [65291, 65291, 65291, 65461],
// clear / KP 5
13: [65293],
// enter
16: [65505, 65505, 65506],
// shift
17: [65507, 65507, 65508],
// ctrl
18: [65513, 65513, 65514],
// alt
19: [65299],
// pause/break
20: [65509],
// caps lock
27: [65307],
// escape
32: [32],
// space
33: [65365, 65365, 65365, 65465],
// page up / KP 9
34: [65366, 65366, 65366, 65459],
// page down / KP 3
35: [65367, 65367, 65367, 65457],
// end / KP 1
36: [65360, 65360, 65360, 65463],
// home / KP 7
37: [65361, 65361, 65361, 65460],
// left arrow / KP 4
38: [65362, 65362, 65362, 65464],
// up arrow / KP 8
39: [65363, 65363, 65363, 65462],
// right arrow / KP 6
40: [65364, 65364, 65364, 65458],
// down arrow / KP 2
45: [65379, 65379, 65379, 65456],
// insert / KP 0
46: [65535, 65535, 65535, 65454],
// delete / KP decimal
91: [65511],
// left windows/command key (meta_l)
92: [65512],
// right window/command key (meta_r)
93: [65383],
// menu key
96: [65456],
// KP 0
97: [65457],
// KP 1
98: [65458],
// KP 2
99: [65459],
// KP 3
100: [65460],
// KP 4
101: [65461],
// KP 5
102: [65462],
// KP 6
103: [65463],
// KP 7
104: [65464],
// KP 8
105: [65465],
// KP 9
106: [65450],
// KP multiply
107: [65451],
// KP add
109: [65453],
// KP subtract
110: [65454],
// KP decimal
111: [65455],
// KP divide
112: [65470],
// f1
113: [65471],
// f2
114: [65472],
// f3
115: [65473],
// f4
116: [65474],
// f5
117: [65475],
// f6
118: [65476],
// f7
119: [65477],
// f8
120: [65478],
// f9
121: [65479],
// f10
122: [65480],
// f11
123: [65481],
// f12
144: [65407],
// num lock
145: [65300],
// scroll lock
225: [65027]
// altgraph (iso_level3_shift)
};
var keyidentifier_keysym = {
"Again": [65382],
"AllCandidates": [65341],
"Alphanumeric": [65328],
"Alt": [65513, 65513, 65514],
"Attn": [64782],
"AltGraph": [65027],
"ArrowDown": [65364],
"ArrowLeft": [65361],
"ArrowRight": [65363],
"ArrowUp": [65362],
"Backspace": [65288],
"CapsLock": [65509],
"Cancel": [65385],
"Clear": [65291],
"Convert": [65315],
"Copy": [64789],
"Crsel": [64796],
"CrSel": [64796],
"CodeInput": [65335],
"Compose": [65312],
"Control": [65507, 65507, 65508],
"ContextMenu": [65383],
"Delete": [65535],
"Down": [65364],
"End": [65367],
"Enter": [65293],
"EraseEof": [64774],
"Escape": [65307],
"Execute": [65378],
"Exsel": [64797],
"ExSel": [64797],
"F1": [65470],
"F2": [65471],
"F3": [65472],
"F4": [65473],
"F5": [65474],
"F6": [65475],
"F7": [65476],
"F8": [65477],
"F9": [65478],
"F10": [65479],
"F11": [65480],
"F12": [65481],
"F13": [65482],
"F14": [65483],
"F15": [65484],
"F16": [65485],
"F17": [65486],
"F18": [65487],
"F19": [65488],
"F20": [65489],
"F21": [65490],
"F22": [65491],
"F23": [65492],
"F24": [65493],
"Find": [65384],
"GroupFirst": [65036],
"GroupLast": [65038],
"GroupNext": [65032],
"GroupPrevious": [65034],
"FullWidth": null,
"HalfWidth": null,
"HangulMode": [65329],
"Hankaku": [65321],
"HanjaMode": [65332],
"Help": [65386],
"Hiragana": [65317],
"HiraganaKatakana": [65319],
"Home": [65360],
"Hyper": [65517, 65517, 65518],
"Insert": [65379],
"JapaneseHiragana": [65317],
"JapaneseKatakana": [65318],
"JapaneseRomaji": [65316],
"JunjaMode": [65336],
"KanaMode": [65325],
"KanjiMode": [65313],
"Katakana": [65318],
"Left": [65361],
"Meta": [65511, 65511, 65512],
"ModeChange": [65406],
"NonConvert": [65314],
"NumLock": [65407],
"PageDown": [65366],
"PageUp": [65365],
"Pause": [65299],
"Play": [64790],
"PreviousCandidate": [65342],
"PrintScreen": [65377],
"Redo": [65382],
"Right": [65363],
"Romaji": [65316],
"RomanCharacters": null,
"Scroll": [65300],
"Select": [65376],
"Separator": [65452],
"Shift": [65505, 65505, 65506],
"SingleCandidate": [65340],
"Super": [65515, 65515, 65516],
"Tab": [65289],
"UIKeyInputDownArrow": [65364],
"UIKeyInputEscape": [65307],
"UIKeyInputLeftArrow": [65361],
"UIKeyInputRightArrow": [65363],
"UIKeyInputUpArrow": [65362],
"Up": [65362],
"Undo": [65381],
"Win": [65511, 65511, 65512],
"Zenkaku": [65320],
"ZenkakuHankaku": [65322]
};
var no_repeat = {
65027: true,
// ISO Level 3 Shift (AltGr)
65505: true,
// Left shift
65506: true,
// Right shift
65507: true,
// Left ctrl
65508: true,
// Right ctrl
65509: true,
// Caps Lock
65511: true,
// Left meta
65512: true,
// Right meta
65513: true,
// Left alt
65514: true,
// Right alt
65515: true,
// Left super/hyper
65516: true
// Right super/hyper
};
this.modifiers = new Guacamole.Keyboard.ModifierState();
this.pressed = {};
var implicitlyPressed = {};
var last_keydown_result = {};
var recentKeysym = {};
var key_repeat_timeout = null;
var key_repeat_interval = null;
var get_keysym = function get_keysym2(keysyms, location) {
if (!keysyms)
return null;
return keysyms[location] || keysyms[0];
};
var isPrintable = function isPrintable2(keysym) {
return keysym >= 0 && keysym <= 255 || (keysym & 4294901760) === 16777216;
};
function keysym_from_key_identifier(identifier, location, shifted) {
if (!identifier)
return null;
var typedCharacter;
var unicodePrefixLocation = identifier.indexOf("U+");
if (unicodePrefixLocation >= 0) {
var hex = identifier.substring(unicodePrefixLocation + 2);
typedCharacter = String.fromCharCode(parseInt(hex, 16));
} else if (identifier.length === 1 && location !== 3)
typedCharacter = identifier;
else
return get_keysym(keyidentifier_keysym[identifier], location);
if (shifted === true)
typedCharacter = typedCharacter.toUpperCase();
else if (shifted === false)
typedCharacter = typedCharacter.toLowerCase();
var codepoint = typedCharacter.charCodeAt(0);
return keysym_from_charcode(codepoint);
}
function isControlCharacter(codepoint) {
return codepoint <= 31 || codepoint >= 127 && codepoint <= 159;
}
function keysym_from_charcode(codepoint) {
if (isControlCharacter(codepoint)) return 65280 | codepoint;
if (codepoint >= 0 && codepoint <= 255)
return codepoint;
if (codepoint >= 256 && codepoint <= 1114111)
return 16777216 | codepoint;
return null;
}
function keysym_from_keycode(keyCode, location) {
return get_keysym(keycodeKeysyms[keyCode], location);
}
var key_identifier_sane = function key_identifier_sane2(keyCode, keyIdentifier) {
if (!keyIdentifier)
return false;
var unicodePrefixLocation = keyIdentifier.indexOf("U+");
if (unicodePrefixLocation === -1)
return true;
var codepoint = parseInt(keyIdentifier.substring(unicodePrefixLocation + 2), 16);
if (keyCode !== codepoint)
return true;
if (keyCode >= 65 && keyCode <= 90 || keyCode >= 48 && keyCode <= 57)
return true;
return false;
};
this.press = function(keysym) {
if (keysym === null) return;
if (!guac_keyboard.pressed[keysym]) {
guac_keyboard.pressed[keysym] = true;
if (guac_keyboard.onkeydown) {
var result = guac_keyboard.onkeydown(keysym);
last_keydown_result[keysym] = result;
window.clearTimeout(key_repeat_timeout);
window.clearInterval(key_repeat_interval);
if (!no_repeat[keysym])
key_repeat_timeout = window.setTimeout(function() {
key_repeat_interval = window.setInterval(function() {
guac_keyboard.onkeyup(keysym);
guac_keyboard.onkeydown(keysym);
}, 50);
}, 500);
return result;
}
}
return last_keydown_result[keysym] || false;
};
this.release = function(keysym) {
if (guac_keyboard.pressed[keysym]) {
delete guac_keyboard.pressed[keysym];
delete implicitlyPressed[keysym];
window.clearTimeout(key_repeat_timeout);
window.clearInterval(key_repeat_interval);
if (keysym !== null && guac_keyboard.onkeyup)
guac_keyboard.onkeyup(keysym);
}
};
this.type = function type(str) {
for (var i = 0; i < str.length; i++) {
var codepoint = str.codePointAt ? str.codePointAt(i) : str.charCodeAt(i);
var keysym = keysym_from_charcode(codepoint);
guac_keyboard.press(keysym);
guac_keyboard.release(keysym);
}
};
this.reset = function() {
for (var keysym in guac_keyboard.pressed)
guac_keyboard.release(parseInt(keysym));
eventLog = [];
};
var updateModifierState = function updateModifierState2(modifier, keysyms, keyEvent) {
var localState = keyEvent.modifiers[modifier];
var remoteState = guac_keyboard.modifiers[modifier];
var i;
if (keysyms.indexOf(keyEvent.keysym) !== -1)
return;
if (remoteState && localState === false) {
for (i = 0; i < keysyms.length; i++) {
guac_keyboard.release(keysyms[i]);
}
} else if (!remoteState && localState) {
for (i = 0; i < keysyms.length; i++) {
if (guac_keyboard.pressed[keysyms[i]])
return;
}
var keysym = keysyms[0];
if (keyEvent.keysym)
implicitlyPressed[keysym] = true;
guac_keyboard.press(keysym);
}
};
var syncModifierStates = function syncModifierStates2(keyEvent) {
updateModifierState("alt", [
65513,
// Left alt
65514,
// Right alt
65027
// AltGr
], keyEvent);
updateModifierState("shift", [
65505,
// Left shift
65506
// Right shift
], keyEvent);
updateModifierState("ctrl", [
65507,
// Left ctrl
65508
// Right ctrl
], keyEvent);
updateModifierState("meta", [
65511,
// Left meta
65512
// Right meta
], keyEvent);
updateModifierState("hyper", [
65515,
// Left super/hyper
65516
// Right super/hyper
], keyEvent);
guac_keyboard.modifiers = keyEvent.modifiers;
};
var isStateImplicit = function isStateImplicit2() {
for (var keysym in guac_keyboard.pressed) {
if (!implicitlyPressed[keysym])
return false;
}
return true;
};
function interpret_events() {
var handled_event = interpret_event();
if (!handled_event)
return false;
var last_event;
do {
last_event = handled_event;
handled_event = interpret_event();
} while (handled_event !== null);
if (isStateImplicit())
guac_keyboard.reset();
return last_event.defaultPrevented;
}
var release_simulated_altgr = function release_simulated_altgr2(keysym) {
if (!guac_keyboard.modifiers.ctrl || !guac_keyboard.modifiers.alt)
return;
if (keysym >= 65 && keysym <= 90)
return;
if (keysym >= 97 && keysym <= 122)
return;
if (keysym <= 255 || (keysym & 4278190080) === 16777216) {
guac_keyboard.release(65507);
guac_keyboard.release(65508);
guac_keyboard.release(65513);
guac_keyboard.release(65514);
}
};
var interpret_event = function interpret_event2() {
var first = eventLog[0];
if (!first)
return null;
if (first instanceof KeydownEvent) {
var keysym = null;
var accepted_events = [];
if (first.keysym === 65511 || first.keysym === 65512) {
if (eventLog.length === 1)
return null;
if (eventLog[1].keysym !== first.keysym) {
if (!eventLog[1].modifiers.meta)
return eventLog.shift();
} else if (eventLog[1] instanceof KeydownEvent)
return eventLog.shift();
}
if (first.reliable) {
keysym = first.keysym;
accepted_events = eventLog.splice(0, 1);
} else if (eventLog[1] instanceof KeypressEvent) {
keysym = eventLog[1].keysym;
accepted_events = eventLog.splice(0, 2);
} else if (eventLog[1]) {
keysym = first.keysym;
accepted_events = eventLog.splice(0, 1);
}
if (accepted_events.length > 0) {
syncModifierStates(first);
if (keysym) {
release_simulated_altgr(keysym);
var defaultPrevented = !guac_keyboard.press(keysym);
recentKeysym[first.keyCode] = keysym;
if (!first.keyupReliable)
guac_keyboard.release(keysym);
for (var i = 0; i < accepted_events.length; i++)
accepted_events[i].defaultPrevented = defaultPrevented;
}
return first;
}
} else if (first instanceof KeyupEvent && !quirks.keyupUnreliable) {
var keysym = first.keysym;
if (keysym) {
guac_keyboard.release(keysym);
delete recentKeysym[first.keyCode];
first.defaultPrevented = true;
} else {
guac_keyboard.reset();
return first;
}
syncModifierStates(first);
return eventLog.shift();
} else
return eventLog.shift();
return null;
};
var getEventLocation = function getEventLocation2(e) {
if ("location" in e)
return e.location;
if ("keyLocation" in e)
return e.keyLocation;
return 0;
};
var markEvent = function markEvent2(e) {
if (e[EVENT_MARKER])
return false;
e[EVENT_MARKER] = true;
return true;
};
this.listenTo = function listenTo(element2) {
element2.addEventListener("keydown", function(e) {
if (!guac_keyboard.onkeydown) return;
if (!markEvent(e)) return;
var keydownEvent = new KeydownEvent(e);
if (e.isComposing || keydownEvent.keyCode === 229)
return;
eventLog.push(keydownEvent);
if (interpret_events())
e.preventDefault();
}, true);
element2.addEventListener("keypress", function(e) {
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
if (!markEvent(e)) return;
eventLog.push(new KeypressEvent(e));
if (interpret_events())
e.preventDefault();
}, true);
element2.addEventListener("keyup", function(e) {
if (!guac_keyboard.onkeyup) return;
if (!markEvent(e)) return;
e.preventDefault();
eventLog.push(new KeyupEvent(e));
interpret_events();
}, true);
var handleInput = function handleInput2(e) {
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
if (!markEvent(e)) return;
if (e.data && !e.isComposing)
guac_keyboard.type(e.data);
};
var handleCompositionStart = function handleCompositionStart2(e) {
element2.removeEventListener("input", handleInput, false);
};
var handleCompositionEnd = function handleCompositionEnd2(e) {
if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
if (!markEvent(e)) return;
if (e.data)
guac_keyboard.type(e.data);
};
element2.addEventListener("input", handleInput, false);
element2.addEventListener("compositionend", handleCompositionEnd, false);
element2.addEventListener("compositionstart", handleCompositionStart, false);
};
if (element)
guac_keyboard.listenTo(element);
};
Guacamole.Keyboard._nextID = 0;
Guacamole.Keyboard.ModifierState = function() {
this.shift = false;
this.ctrl = false;
this.alt = false;
this.meta = false;
this.hyper = false;
};
Guacamole.Keyboard.ModifierState.fromKeyboardEvent = function(e) {
var state = new Guacamole.Keyboard.ModifierState();
state.shift = e.shiftKey;
state.ctrl = e.ctrlKey;
state.alt = e.altKey;
state.meta = e.metaKey;
if (e.getModifierState) {
state.hyper = e.getModifierState("OS") || e.getModifierState("Super") || e.getModifierState("Hyper") || e.getModifierState("Win");
}
return state;
};
var Guacamole = Guacamole || {};
Guacamole.Layer = function(width, height) {
var layer = this;
var CANVAS_SIZE_FACTOR = 64;
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
context.save();
var empty = true;
var pathClosed = true;
var stackSize = 0;
var compositeOperation = {
/* 0x0 NOT IMPLEMENTED */
1: "destination-in",
2: "destination-out",
/* 0x3 NOT IMPLEMENTED */
4: "source-in",
/* 0x5 NOT IMPLEMENTED */
6: "source-atop",
/* 0x7 NOT IMPLEMENTED */
8: "source-out",
9: "destination-atop",
10: "xor",
11: "destination-over",
12: "copy",
/* 0xD NOT IMPLEMENTED */
14: "source-over",
15: "lighter"
};
var resize = function resize2(newWidth, newHeight) {
newWidth = newWidth || 0;
newHeight = newHeight || 0;
var canvasWidth = Math.ceil(newWidth / CANVAS_SIZE_FACTOR) * CANVAS_SIZE_FACTOR;
var canvasHeight = Math.ceil(newHeight / CANVAS_SIZE_FACTOR) * CANVAS_SIZE_FACTOR;
if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {
var oldData = null;
if (!empty && canvas.width !== 0 && canvas.height !== 0) {
oldData = document.createElement("canvas");
oldData.width = Math.min(layer.width, newWidth);
oldData.height = Math.min(layer.height, newHeight);
var oldDataContext = oldData.getContext("2d");
oldDataContext.drawImage(
canvas,
0,
0,
oldData.width,
oldData.height,
0,
0,
oldData.width,
oldData.height
);
}
var oldCompositeOperation = context.globalCompositeOperation;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
if (oldData)
context.drawImage(
oldData,
0,
0,
oldData.width,
oldData.height,
0,
0,
oldData.width,
oldData.height
);
context.globalCompositeOperation = oldCompositeOperation;
stackSize = 0;
context.save();
} else
layer.reset();
layer.width = newWidth;
layer.height = newHeight;
};
function fitRect(x, y, w, h) {
var opBoundX = w + x;
var opBoundY = h + y;
var resizeWidth;
if (opBoundX > layer.width)
resizeWidth = opBoundX;
else
resizeWidth = layer.width;
var resizeHeight;
if (opBoundY > layer.height)
resizeHeight = opBoundY;
else
resizeHeight = layer.height;
layer.resize(resizeWidth, resizeHeight);
}
this.autosize = false;
this.width = width;
this.height = height;
this.getCanvas = function getCanvas() {
return canvas;
};
this.toCanvas = function toCanvas() {
var canvas2 = document.createElement("canvas");
canvas2.width = layer.width;
canvas2.height = layer.height;
var context2 = canvas2.getContext("2d");
context2.drawImage(layer.getCanvas(), 0, 0);
return canvas2;
};
this.resize = function(newWidth, newHeight) {
if (newWidth !== layer.width || newHeight !== layer.height)
resize(newWidth, newHeight);
};
this.drawImage = function(x, y, image) {
if (layer.autosize) fitRect(x, y, image.width, image.height);
context.drawImage(image, x, y);
empty = false;
};
this.transfer = function(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction) {
var srcCanvas = srcLayer.getCanvas();
if (srcx >= srcCanvas.width || srcy >= srcCanvas.height) return;
if (srcx + srcw > srcCanvas.width)
srcw = srcCanvas.width - srcx;
if (srcy + srch > srcCanvas.height)
srch = srcCanvas.height - srcy;
if (srcw === 0 || srch === 0) return;
if (layer.autosize) fitRect(x, y, srcw, srch);
var src = srcLayer.getCanvas().getContext("2d").getImageData(srcx, srcy, srcw, srch);
var dst = context.getImageData(x, y, srcw, srch);
for (var i = 0; i < srcw * srch * 4; i += 4) {
var src_pixel = new Guacamole.Layer.Pixel(
src.data[i],
src.data[i + 1],
src.data[i + 2],
src.data[i + 3]
);
var dst_pixel = new Guacamole.Layer.Pixel(
dst.data[i],
dst.data[i + 1],
dst.data[i + 2],
dst.data[i + 3]
);
transferFunction(src_pixel, dst_pixel);
dst.data[i] = dst_pixel.red;
dst.data[i + 1] = dst_pixel.green;
dst.data[i + 2] = dst_pixel.blue;
dst.data[i + 3] = dst_pixel.alpha;
}
context.putImageData(dst, x, y);
empty = false;
};
this.put = function(srcLayer, srcx, srcy, srcw, srch, x, y) {
var srcCanvas = srcLayer.getCanvas();
if (srcx >= srcCanvas.width || srcy >= srcCanvas.height) return;
if (srcx + srcw > srcCanvas.width)
srcw = srcCanvas.width - srcx;
if (srcy + srch > srcCanvas.height)
srch = srcCanvas.height - srcy;
if (srcw === 0 || srch === 0) return;
if (layer.autosize) fitRect(x, y, srcw, srch);
var src = srcLayer.getCanvas().getContext("2d").getImageData(srcx, srcy, srcw, srch);
context.putImageData(src, x, y);
empty = false;
};
this.copy = function(srcLayer, srcx, srcy, srcw, srch, x, y) {
var srcCanvas = srcLayer.getCanvas();
if (srcx >= srcCanvas.width || srcy >= srcCanvas.height) return;
if (srcx + srcw > srcCanvas.width)
srcw = srcCanvas.width - srcx;
if (srcy + srch > srcCanvas.height)
srch = srcCanvas.height - srcy;
if (srcw === 0 || srch === 0) return;
if (layer.autosize) fitRect(x, y, srcw, srch);
context.drawImage(srcCanvas, srcx, srcy, srcw, srch, x, y, srcw, srch);
empty = false;
};
this.moveTo = function(x, y) {
if (pathClosed) {
context.beginPath();
pathClosed = false;
}
if (layer.autosize) fitRect(x, y, 0, 0);
context.moveTo(x, y);
};
this.lineTo = function(x, y) {
if (pathClosed) {
context.beginPath();
pathClosed = false;
}
if (layer.autosize) fitRect(x, y, 0, 0);
context.lineTo(x, y);
};
this.arc = function(x, y, radius, startAngle, endAngle, negative) {
if (pathClosed) {
context.beginPath();
pathClosed = false;
}
if (layer.autosize) fitRect(x, y, 0, 0);
context.arc(x, y, radius, startAngle, endAngle, negative);
};
this.curveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
if (pathClosed) {
context.beginPath();
pathClosed = false;
}
if (layer.autosize) fitRect(x, y, 0, 0);
context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
};
this.close = function() {
context.closePath();
pathClosed = true;
};
this.rect = function(x, y, w, h) {
if (pathClosed) {
context.beginPath();
pathClosed = false;
}
if (layer.autosize) fitRect(x, y, w, h);
context.rect(x, y, w, h);
};
this.clip = function() {
context.clip();
pathClosed = true;
};
this.strokeColor = function(cap, join, thickness, r, g, b, a) {
context.lineCap = cap;
context.lineJoin = join;
context.lineWidth = thickness;
context.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
context.stroke();
empty = false;
pathClosed = true;
};
this.fillColor = function(r, g, b, a) {
context.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
context.fill();
empty = false;
pathClosed = true;
};
this.strokeLayer = function(cap, join, thickness, srcLayer) {
context.lineCap = cap;
context.lineJoin = join;
context.lineWidth = thickness;
context.strokeStyle = context.createPattern(
srcLayer.getCanvas(),
"repeat"
);
context.stroke();
empty = false;
pathClosed = true;
};
this.fillLayer = function(srcLayer) {
context.fillStyle = context.createPattern(
srcLayer.getCanvas(),
"repeat"
);
context.fill();
empty = false;
pathClosed = true;
};
this.push = function() {
context.save();
stackSize++;
};
this.pop = function() {
if (stackSize > 0) {
context.restore();
stackSize--;
}
};
this.reset = function() {
while (stackSize > 0) {
context.restore();
stackSize--;
}
context.restore();
context.save();
context.beginPath();
pathClosed = false;
};
this.setTransform = function(a, b, c, d, e, f) {
context.setTransform(
a,
b,
c,
d,
e,
f
/*0, 0, 1*/
);
};
this.transform = function(a, b, c, d, e, f) {
context.transform(
a,
b,
c,
d,
e,
f
/*0, 0, 1*/
);
};
this.setChannelMask = function(mask) {
context.globalCompositeOperation = compositeOperation[mask];
};
this.setMiterLimit = function(limit) {
context.miterLimit = limit;
};
resize(width, height);
canvas.style.zIndex = -1;
};
Guacamole.Layer.ROUT = 2;
Guacamole.Layer.ATOP = 6;
Guacamole.Layer.XOR = 10;
Guacamole.Layer.ROVER = 11;
Guacamole.Layer.OVER = 14;
Guacamole.Layer.PLUS = 15;
Guacamole.Layer.RIN = 1;
Guacamole.Layer.IN = 4;
Guacamole.Layer.OUT = 8;
Guacamole.Layer.RATOP = 9;
Guacamole.Layer.SRC = 12;
Guacamole.Layer.Pixel = function(r, g, b, a) {
this.red = r;
this.green = g;
this.blue = b;
this.alpha = a;
};
var Guacamole = Guacamole || {};
Guacamole.Mouse = function Mouse(element) {
Guacamole.Mouse.Event.Target.call(this);
var guac_mouse = this;
this.touchMouseThreshold = 3;
this.scrollThreshold = 53;
this.PIXELS_PER_LINE = 18;
this.PIXELS_PER_PAGE = this.PIXELS_PER_LINE * 16;
var MOUSE_BUTTONS = [
Guacamole.Mouse.State.Buttons.LEFT,
Guacamole.Mouse.State.Buttons.MIDDLE,
Guacamole.Mouse.State.Buttons.RIGHT
];
var ignore_mouse = 0;
var scroll_delta = 0;
element.addEventListener("contextmenu", function(e) {
Guacamole.Event.DOMEvent.cancelEvent(e);
}, false);
element.addEventListener("mousemove", function(e) {
if (ignore_mouse) {
Guacamole.Event.DOMEvent.cancelEvent(e);
ignore_mouse--;
return;
}
guac_mouse.move(Guacamole.Position.fromClientPosition(element, e.clientX, e.clientY), e);
}, false);
element.addEventListener("mousedown", function(e) {
if (ignore_mouse) {
Guacamole.Event.DOMEvent.cancelEvent(e);
return;
}
var button = MOUSE_BUTTONS[e.button];
if (button)
guac_mouse.press(button, e);
}, false);
element.addEventListener("mouseup", function(e) {
if (ignore_mouse) {
Guacamole.Event.DOMEvent.cancelEvent(e);
return;
}
var button = MOUSE_BUTTONS[e.button];
if (button)
guac_mouse.release(button, e);
}, false);
element.addEventListener("mouseout", function(e) {
if (!e) e = window.event;
var target = e.relatedTarget || e.toElement;
while (target) {
if (target === element)
return;
target = target.parentNode;
}
guac_mouse.reset(e);
guac_mouse.out(e);
}, false);
element.addEventListener("selectstart", function(e) {
Guacamole.Event.DOMEvent.cancelEvent(e);
}, false);
function ignorePendingMouseEvents() {
ignore_mouse = guac_mouse.touchMouseThreshold;
}
element.addEventListener("touchmove", ignorePendingMouseEvents, false);
element.addEventListener("touchstart", ignorePendingMouseEvents, false);
element.addEventListener("touchend", ignorePendingMouseEvents, false);
function mousewheel_handler(e) {
var delta = e.deltaY || -e.wheelDeltaY || -e.wheelDelta;
if (delta) {
if (e.deltaMode === 1)
delta = e.deltaY * guac_mouse.PIXELS_PER_LINE;
else if (e.deltaMode === 2)
delta = e.deltaY * guac_mouse.PIXELS_PER_PAGE;
} else
delta = e.detail * guac_mouse.PIXELS_PER_LINE;
scroll_delta += delta;
if (scroll_delta <= -guac_mouse.scrollThreshold) {
do {
guac_mouse.click(Guacamole.Mouse.State.Buttons.UP);
scroll_delta += guac_mouse.scrollThreshold;
} while (scroll_delta <= -guac_mouse.scrollThreshold);
scroll_delta = 0;
}
if (scroll_delta >= guac_mouse.scrollThreshold) {
do {
guac_mouse.click(Guacamole.Mouse.State.Buttons.DOWN);
scroll_delta -= guac_mouse.scrollThreshold;
} while (scroll_delta >= guac_mouse.scrollThreshold);
scroll_delta = 0;
}
Guacamole.Event.DOMEvent.cancelEvent(e);
}
if (window.WheelEvent) {
element.addEventListener("wheel", mousewheel_handler, false);
} else {
element.addEventListener("DOMMouseScroll", mousewheel_handler, false);
element.addEventListener("mousewheel", mousewheel_handler, false);
}
var CSS3_CURSOR_SUPPORTED = (function() {
var div = document.createElement("div");
if (!("cursor" in div.style))
return false;
try {
div.style.cursor = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX///+nxBvIAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==) 0 0, auto";
} catch (e) {
return false;
}
return /\burl\([^()]*\)\s+0\s+0\b/.test(div.style.cursor || "");
})();
this.setCursor = function(canvas, x, y) {
if (CSS3_CURSOR_SUPPORTED) {
var dataURL = canvas.toDataURL("image/png");
element.style.cursor = "url(" + dataURL + ") " + x + " " + y + ", auto";
return true;
}
return false;
};
};
Guacamole.Mouse.State = function State(template) {
var legacyConstructor = function legacyConstructor2(x, y, left, middle, right, up, down) {
return {
x,
y,
left,
middle,
right,
up,
down
};
};
if (arguments.length > 1)
template = legacyConstructor.apply(this, arguments);
else
template = template || {};
Guacamole.Position.call(this, template);
this.left = template.left || false;
this.middle = template.middle || false;
this.right = template.right || false;
this.up = template.up || false;
this.down = template.down || false;
};
Guacamole.Mouse.State.Buttons = {
/**
* The name of the {@link Guacamole.Mouse.State} property representing the
* left mouse button.
*
* @constant
* @type {!string}
*/
LEFT: "left",
/**
* The name of the {@link Guacamole.Mouse.State} property representing the
* middle mouse button.
*
* @constant
* @type {!string}
*/
MIDDLE: "middle",
/**
* The name of the {@link Guacamole.Mouse.State} property representing the
* right mouse button.
*
* @constant
* @type {!string}
*/
RIGHT: "right",
/**
* The name of the {@link Guacamole.Mouse.State} property representing the
* up mouse button (the fourth mouse button, clicked when the mouse scroll
* wheel is scrolled up).
*
* @constant
* @type {!string}
*/
UP: "up",
/**
* The name of the {@link Guacamole.Mouse.State} property representing the
* down mouse button (the fifth mouse button, clicked when the mouse scroll
* wheel is scrolled up).
*
* @constant
* @type {!string}
*/
DOWN: "down"
};
Guacamole.Mouse.Event = function MouseEvent(type, state, events) {
Guacamole.Event.DOMEvent.call(this, type, events);
var legacyHandlerName = "on" + this.type;
this.state = state;
this.invokeLegacyHandler = function invokeLegacyHandler(target) {
if (target[legacyHandlerName]) {
this.preventDefault();
this.stopPropagation();
target[legacyHandlerName](this.state);
}
};
};
Guacamole.Mouse.Event.Target = function MouseEventTarget() {
Guacamole.Event.Target.call(this);
this.currentState = new Guacamole.Mouse.State();
this.press = function press(button, events) {
if (!this.currentState[button]) {
this.currentState[button] = true;
this.dispatch(new Guacamole.Mouse.Event("mousedown", this.currentState, events));
}
};
this.release = function release(button, events) {
if (this.currentState[button]) {
this.currentState[button] = false;
this.dispatch(new Guacamole.Mouse.Event("mouseup", this.currentState, events));
}
};
this.click = function click(button, events) {
this.press(button, events);
this.release(button, events);
};
this.move = function move(position, events) {
if (this.currentState.x !== position.x || this.currentState.y !== position.y) {
this.currentState.x = position.x;
this.currentState.y = position.y;
this.dispatch(new Guacamole.Mouse.Event("mousemove", this.currentState, events));
}
};
this.out = function out(events) {
this.dispatch(new Guacamole.Mouse.Event("mouseout", this.currentState, events));
};
this.reset = function reset(events) {
for (var button in Guacamole.Mouse.State.Buttons) {
this.release(Guacamole.Mouse.State.Buttons[button], events);
}
};
};
Guacamole.Mouse.Touchpad = function Touchpad(element) {
Guacamole.Mouse.Event.Target.call(this);
var guac_touchpad = this;
this.scrollThreshold = 20 * (window.devicePixelRatio || 1);
this.clickTimingThreshold = 250;
this.clickMoveThreshold = 10 * (window.devicePixelRatio || 1);
this.currentState = new Guacamole.Mouse.State();
var touch_count = 0;
var last_touch_x = 0;
var last_touch_y = 0;
var last_touch_time = 0;
var pixels_moved = 0;
var touch_buttons = {
1: "left",
2: "right",
3: "middle"
};
var gesture_in_progress = false;
var click_release_timeout = null;
element.addEventListener("touchend", function(e) {
e.preventDefault();
if (gesture_in_progress && e.touches.length === 0) {
var time = (/* @__PURE__ */ new Date()).getTime();
var button = touch_buttons[touch_count];
if (guac_touchpad.currentState[button]) {
guac_touchpad.release(button, e);
if (click_release_timeout) {
window.clearTimeout(click_release_timeout);
click_release_timeout = null;
}
}
if (time - last_touch_time <= guac_touchpad.clickTimingThreshold && pixels_moved < guac_touchpad.clickMoveThreshold) {
guac_touchpad.press(button, e);
click_release_timeout = window.setTimeout(function() {
guac_touchpad.release(button, e);
gesture_in_progress = false;
}, guac_touchpad.clickTimingThreshold);
}
if (!click_release_timeout)
gesture_in_progress = false;
}
}, false);
element.addEventListener("touchstart", function(e) {
e.preventDefault();
touch_count = Math.min(e.touches.length, 3);
if (click_release_timeout) {
window.clearTimeout(click_release_timeout);
click_release_timeout = null;
}
if (!gesture_in_progress) {
gesture_in_progress = true;
var starting_touch = e.touches[0];
last_touch_x = starting_touch.clientX;
last_touch_y = starting_touch.clientY;
last_touch_time = (/* @__PURE__ */ new Date()).getTime();
pixels_moved = 0;
}
}, false);
element.addEventListener("touchmove", function(e) {
e.preventDefault();
var touch = e.touches[0];
var delta_x = touch.clientX - last_touch_x;
var delta_y = touch.clientY - last_touch_y;
pixels_moved += Math.abs(delta_x) + Math.abs(delta_y);
if (touch_count === 1) {
var velocity = pixels_moved / ((/* @__PURE__ */ new Date()).getTime() - last_touch_time);
var scale = 1 + velocity;
var position = new Guacamole.Position(guac_touchpad.currentState);
position.x += delta_x * scale;
position.y += delta_y * scale;
position.x = Math.min(Math.max(0, position.x), element.offsetWidth - 1);
position.y = Math.min(Math.max(0, position.y), element.offsetHeight - 1);
guac_touchpad.move(position, e);
last_touch_x = touch.clientX;
last_touch_y = touch.clientY;
} else if (touch_count === 2) {
if (Math.abs(delta_y) >= guac_touchpad.scrollThreshold) {
var button;
if (delta_y > 0) button = "down";
else button = "up";
guac_touchpad.click(button, e);
last_touch_x = touch.clientX;
last_touch_y = touch.clientY;
}
}
}, false);
};
Guacamole.Mouse.Touchscreen = function Touchscreen(element) {
Guacamole.Mouse.Event.Target.call(this);
var guac_touchscreen = this;
var gesture_in_progress = false;
var gesture_start_x = null;
var gesture_start_y = null;
var click_release_timeout = null;
var long_press_timeout = null;
this.scrollThreshold = 20 * (window.devicePixelRatio || 1);
this.clickTimingThreshold = 250;
this.clickMoveThreshold = 16 * (window.devicePixelRatio || 1);
this.longPressThreshold = 500;
function finger_moved(e) {
var touch = e.touches[0] || e.changedTouches[0];
var delta_x = touch.clientX - gesture_start_x;
var delta_y = touch.clientY - gesture_start_y;
return Math.sqrt(delta_x * delta_x + delta_y * delta_y) >= guac_touchscreen.clickMoveThreshold;
}
function begin_gesture(e) {
var touch = e.touches[0];
gesture_in_progress = true;
gesture_start_x = touch.clientX;
gesture_start_y = touch.clientY;
}
function end_gesture() {
window.clearTimeout(click_release_timeout);
window.clearTimeout(long_press_timeout);
gesture_in_progress = false;
}
element.addEventListener("touchend", function(e) {
if (!gesture_in_progress)
return;
if (e.touches.length !== 0 || e.changedTouches.length !== 1) {
end_gesture();
return;
}
window.clearTimeout(long_press_timeout);
guac_touchscreen.release(Guacamole.Mouse.State.Buttons.LEFT, e);
if (!finger_moved(e)) {
e.preventDefault();
if (!guac_touchscreen.currentState.left) {
var touch = e.changedTouches[0];
guac_touchscreen.move(Guacamole.Position.fromClientPosition(element, touch.clientX, touch.clientY));
guac_touchscreen.press(Guacamole.Mouse.State.Buttons.LEFT, e);
click_release_timeout = window.setTimeout(function() {
guac_touchscreen.release(Guacamole.Mouse.State.Buttons.LEFT, e);
end_gesture();
}, guac_touchscreen.clickTimingThreshold);
}
}
}, false);
element.addEventListener("touchstart", function(e) {
if (e.touches.length !== 1) {
end_gesture();
return;
}
e.preventDefault();
begin_gesture(e);
window.clearTimeout(click_release_timeout);
long_press_timeout = window.setTimeout(function() {
var touch = e.touches[0];
guac_touchscreen.move(Guacamole.Position.fromClientPosition(element, touch.clientX, touch.clientY));
guac_touchscreen.click(Guacamole.Mouse.State.Buttons.RIGHT, e);
end_gesture();
}, guac_touchscreen.longPressThreshold);
}, false);
element.addEventListener("touchmove", function(e) {
if (!gesture_in_progress)
return;
if (finger_moved(e))
window.clearTimeout(long_press_timeout);
if (e.touches.length !== 1) {
end_gesture();
return;
}
if (guac_touchscreen.currentState.left) {
e.preventDefault();
var touch = e.touches[0];
guac_touchscreen.move(Guacamole.Position.fromClientPosition(element, touch.clientX, touch.clientY), e);
}
}, false);
};
var Guacamole = Guacamole || {};
var Guacamole = Guacamole || {};
Guacamole.Object = function guacamoleObject(client, index) {
var guacObject = this;
var bodyCallbacks = {};
var dequeueBodyCallback = function dequeueBodyCallback2(name) {
var callbacks = bodyCallbacks[name];
if (!callbacks)
return null;
var callback = callbacks.shift();
if (callbacks.length === 0)
delete bodyCallbacks[name];
return callback;
};
var enqueueBodyCallback = function enqueueBodyCallback2(name, callback) {
var callbacks = bodyCallbacks[name];
if (!callbacks) {
callbacks = [];
bodyCallbacks[name] = callbacks;
}
callbacks.push(callback);
};
this.index = index;
this.onbody = function defaultBodyHandler(inputStream, mimetype, name) {
var callback = dequeueBodyCallback(name);
if (callback)
callback(inputStream, mimetype);
};
this.onundefine = null;
this.requestInputStream = function requestInputStream(name, bodyCallback) {
if (bodyCallback)
enqueueBodyCallback(name, bodyCallback);
client.requestObjectInputStream(guacObject.index, name);
};
this.createOutputStream = function createOutputStream(mimetype, name) {
return client.createObjectOutputStream(guacObject.index, mimetype, name);
};
};
Guacamole.Object.ROOT_STREAM = "/";
Guacamole.Object.STREAM_INDEX_MIMETYPE = "application/vnd.glyptodon.guacamole.stream-index+json";
var Guacamole = Guacamole || {};
Guacamole.OnScreenKeyboard = function(layout) {
var osk = this;
var modifierKeysyms = {};
var pressed = {};
var scaledElements = [];
var addClass = function addClass2(element, classname) {
if (element.classList)
element.classList.add(classname);
else
element.className += " " + classname;
};
var removeClass = function removeClass2(element, classname) {
if (element.classList)
element.classList.remove(classname);
else {
element.className = element.className.replace(
/([^ ]+)[ ]*/g,
function removeMatchingClasses(match, testClassname) {
if (testClassname === classname)
return "";
return match;
}
);
}
};
var ignoreMouse = 0;
var ignorePendingMouseEvents = function ignorePendingMouseEvents2() {
ignoreMouse = osk.touchMouseThreshold;
};
var ScaledElement = function ScaledElement2(element, width, height, scaleFont) {
this.width = width;
this.height = height;
this.scale = function(pixels) {
element.style.width = width * pixels + "px";
element.style.height = height * pixels + "px";
if (scaleFont) {
element.style.lineHeight = height * pixels + "px";
element.style.fontSize = pixels + "px";
}
};
};
var modifiersPressed = function modifiersPressed2(names) {
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (!(name in modifierKeysyms))
return false;
}
return true;
};
var getActiveKey = function getActiveKey2(keyName) {
var keys = osk.keys[keyName];
if (!keys)
return null;
for (var i = keys.length - 1; i >= 0; i--) {
var candidate = keys[i];
if (modifiersPressed(candidate.requires))
return candidate;
}
return null;
};
var press = function press2(keyName, keyElement) {
if (!pressed[keyName]) {
addClass(keyElement, "guac-keyboard-pressed");
var key = getActiveKey(keyName);
if (key.modifier) {
var modifierClass = "guac-keyboard-modifier-" + getCSSName(key.modifier);
var originalKeysym = modifierKeysyms[key.modifier];
if (originalKeysym === void 0) {
addClass(keyboard, modifierClass);
modifierKeysyms[key.modifier] = key.keysym;
if (key.keysym && osk.onkeydown)
osk.onkeydown(key.keysym);
} else {
removeClass(keyboard, modifierClass);
delete modifierKeysyms[key.modifier];
if (originalKeysym && osk.onkeyup)
osk.onkeyup(originalKeysym);
}
} else if (osk.onkeydown)
osk.onkeydown(key.keysym);
pressed[keyName] = true;
}
};
var release = function release2(keyName, keyElement) {
if (pressed[keyName]) {
removeClass(keyElement, "guac-keyboard-pressed");
var key = getActiveKey(keyName);
if (!key.modifier && osk.onkeyup)
osk.onkeyup(key.keysym);
pressed[keyName] = false;
}
};
var keyboard = document.createElement("div");
keyboard.className = "guac-keyboard";
keyboard.onselectstart = keyboard.onmousemove = keyboard.onmouseup = keyboard.onmousedown = function handleMouseEvents(e) {
if (ignoreMouse)
ignoreMouse--;
e.stopPropagation();
return false;
};
this.touchMouseThreshold = 3;
this.onkeydown = null;
this.onkeyup = null;
this.layout = new Guacamole.OnScreenKeyboard.Layout(layout);
this.getElement = function() {
return keyboard;
};
this.resize = function(width) {
var unit = Math.floor(width * 10 / osk.layout.width) / 10;
for (var i = 0; i < scaledElements.length; i++) {
var scaledElement = scaledElements[i];
scaledElement.scale(unit);
}
};
var asKeyArray = function asKeyArray2(name, object) {
if (object instanceof Array) {
var keys = [];
for (var i = 0; i < object.length; i++) {
keys.push(new Guacamole.OnScreenKeyboard.Key(object[i], name));
}
return keys;
}
if (typeof object === "number") {
return [new Guacamole.OnScreenKeyboard.Key({
name,
keysym: object
})];
}
if (typeof object === "string") {
return [new Guacamole.OnScreenKeyboard.Key({
name,
title: object
})];
}
return [new Guacamole.OnScreenKeyboard.Key(object, name)];
};
var getKeys = function getKeys2(keys) {
var keyArrays = {};
for (var name in layout.keys) {
keyArrays[name] = asKeyArray(name, keys[name]);
}
return keyArrays;
};
this.keys = getKeys(layout.keys);
var getCSSName = function getCSSName2(name) {
var cssName = name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[^A-Za-z0-9]+/g, "-").toLowerCase();
return cssName;
};
var appendElements = function appendElements2(element, object, name) {
var i;
var div = document.createElement("div");
if (name)
addClass(div, "guac-keyboard-" + getCSSName(name));
if (object instanceof Array) {
addClass(div, "guac-keyboard-group");
for (i = 0; i < object.length; i++)
appendElements2(div, object[i]);
} else if (object instanceof Object) {
addClass(div, "guac-keyboard-group");
var names = Object.keys(object).sort();
for (i = 0; i < names.length; i++) {
var name = names[i];
appendElements2(div, object[name], name);
}
} else if (typeof object === "number") {
addClass(div, "guac-keyboard-gap");
scaledElements.push(new ScaledElement(div, object, object));
} else if (typeof object === "string") {
var keyName = object;
if (keyName.length === 1)
keyName = "0x" + keyName.charCodeAt(0).toString(16);
addClass(div, "guac-keyboard-key-container");
var keyElement = document.createElement("div");
keyElement.className = "guac-keyboard-key guac-keyboard-key-" + getCSSName(keyName);
var keys = osk.keys[object];
if (keys) {
for (i = 0; i < keys.length; i++) {
var key = keys[i];
var capElement = document.createElement("div");
capElement.className = "guac-keyboard-cap";
capElement.textContent = key.title;
for (var j = 0; j < key.requires.length; j++) {
var requirement = key.requires[j];
addClass(capElement, "guac-keyboard-requires-" + getCSSName(requirement));
addClass(keyElement, "guac-keyboard-uses-" + getCSSName(requirement));
}
keyElement.appendChild(capElement);
}
}
div.appendChild(keyElement);
scaledElements.push(new ScaledElement(div, osk.layout.keyWidths[object] || 1, 1, true));
var touchPress = function touchPress2(e) {
e.preventDefault();
ignoreMouse = osk.touchMouseThreshold;
press(object, keyElement);
};
var touchRelease = function touchRelease2(e) {
e.preventDefault();
ignoreMouse = osk.touchMouseThreshold;
release(object, keyElement);
};
var mousePress = function mousePress2(e) {
e.preventDefault();
if (ignoreMouse === 0)
press(object, keyElement);
};
var mouseRelease = function mouseRelease2(e) {
e.preventDefault();
if (ignoreMouse === 0)
release(object, keyElement);
};
keyElement.addEventListener("touchstart", touchPress, true);
keyElement.addEventListener("touchend", touchRelease, true);
keyElement.addEventListener("mousedown", mousePress, true);
keyElement.addEventListener("mouseup", mouseRelease, true);
keyElement.addEventListener("mouseout", mouseRelease, true);
}
element.appendChild(div);
};
appendElements(keyboard, layout.layout);
};
Guacamole.OnScreenKeyboard.Layout = function(template) {
this.language = template.language;
this.type = template.type;
this.keys = template.keys;
this.layout = template.layout;
this.width = template.width;
this.keyWidths = template.keyWidths || {};
};
Guacamole.OnScreenKeyboard.Key = function(template, name) {
this.name = name || template.name;
this.title = template.title || this.name;
this.keysym = template.keysym || (function deriveKeysym(title) {
if (!title || title.length !== 1)
return null;
var charCode = title.charCodeAt(0);
if (charCode >= 0 && charCode <= 255)
return charCode;
if (charCode >= 256 && charCode <= 1114111)
return 16777216 | charCode;
return null;
})(this.title);
this.modifier = template.modifier;
this.requires = template.requires || [];
};
var Guacamole = Guacamole || {};
Guacamole.OutputStream = function(client, index) {
var guac_stream = this;
this.index = index;
this.onack = null;
this.sendBlob = function(data) {
client.sendBlob(guac_stream.index, data);
};
this.sendEnd = function() {
client.endStream(guac_stream.index);
};
};
var Guacamole = Guacamole || {};
Guacamole.Parser = function Parser() {
var parser = this;
var buffer = "";
var elementBuffer = [];
var elementEnd = -1;
var startIndex = 0;
var elementCodepoints = 0;
var BUFFER_TRUNCATION_THRESHOLD = 4096;
var MIN_CODEPOINT_REQUIRES_SURROGATE = 65536;
this.receive = function receive(packet, isBuffer) {
if (isBuffer)
buffer = packet;
else {
if (startIndex > BUFFER_TRUNCATION_THRESHOLD && elementEnd >= startIndex) {
buffer = buffer.substring(startIndex);
elementEnd -= startIndex;
startIndex = 0;
}
if (buffer.length)
buffer += packet;
else
buffer = packet;
}
while (elementEnd < buffer.length) {
if (elementEnd >= startIndex) {
var codepoints = Guacamole.Parser.codePointCount(buffer, startIndex, elementEnd);
if (codepoints < elementCodepoints) {
elementEnd += elementCodepoints - codepoints;
continue;
} else if (elementCodepoints && buffer.codePointAt(elementEnd - 1) >= MIN_CODEPOINT_REQUIRES_SURROGATE) {
elementEnd++;
continue;
}
var element = buffer.substring(startIndex, elementEnd);
var terminator = buffer.substring(elementEnd, elementEnd + 1);
elementBuffer.push(element);
if (terminator === ";") {
var opcode = elementBuffer.shift();
if (parser.oninstruction !== null)
parser.oninstruction(opcode, elementBuffer);
elementBuffer = [];
if (!isBuffer && elementEnd + 1 === buffer.length) {
elementEnd = -1;
buffer = "";
}
} else if (terminator !== ",")
throw new Error('Element terminator of instruction was not ";" nor ",".');
startIndex = elementEnd + 1;
}
var lengthEnd = buffer.indexOf(".", startIndex);
if (lengthEnd !== -1) {
elementCodepoints = parseInt(buffer.substring(elementEnd + 1, lengthEnd));
if (isNaN(elementCodepoints))
throw new Error("Non-numeric character in element length.");
startIndex = lengthEnd + 1;
elementEnd = startIndex + elementCodepoints;
} else {
startIndex = buffer.length;
break;
}
}
};
this.oninstruction = null;
};
Guacamole.Parser.codePointCount = function codePointCount(str, start, end) {
str = str.substring(start || 0, end);
var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
return str.length - (surrogatePairs ? surrogatePairs.length : 0);
};
Guacamole.Parser.toInstruction = function toInstruction(elements) {
var toElement = function toElement2(value) {
var str = "" + value;
return Guacamole.Parser.codePointCount(str) + "." + str;
};
var instr = toElement(elements[0]);
for (var i = 1; i < elements.length; i++)
instr += "," + toElement(elements[i]);
return instr + ";";
};
var Guacamole = Guacamole || {};
Guacamole.Position = function Position(template) {
template = template || {};
this.x = template.x || 0;
this.y = template.y || 0;
this.fromClientPosition = function fromClientPosition2(element, clientX, clientY) {
this.x = clientX - element.offsetLeft;
this.y = clientY - element.offsetTop;
var parent = element.offsetParent;
while (parent && !(parent === document.body)) {
this.x -= parent.offsetLeft - parent.scrollLeft;
this.y -= parent.offsetTop - parent.scrollTop;
parent = parent.offsetParent;
}
if (parent) {
var documentScrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop;
this.x -= parent.offsetLeft - documentScrollLeft;
this.y -= parent.offsetTop - documentScrollTop;
}
};
};
Guacamole.Position.fromClientPosition = function fromClientPosition(element, clientX, clientY) {
var position = new Guacamole.Position();
position.fromClientPosition(element, clientX, clientY);
return position;
};
var Guacamole = Guacamole || {};
Guacamole.RawAudioFormat = function RawAudioFormat(template) {
this.bytesPerSample = template.bytesPerSample;
this.channels = template.channels;
this.rate = template.rate;
};
Guacamole.RawAudioFormat.parse = function parseFormat(mimetype) {
var bytesPerSample;
var rate = null;
var channels = 1;
if (mimetype.substring(0, 9) === "audio/L8;") {
mimetype = mimetype.substring(9);
bytesPerSample = 1;
} else if (mimetype.substring(0, 10) === "audio/L16;") {
mimetype = mimetype.substring(10);
bytesPerSample = 2;
} else
return null;
var parameters = mimetype.split(",");
for (var i = 0; i < parameters.length; i++) {
var parameter = parameters[i];
var equals = parameter.indexOf("=");
if (equals === -1)
return null;
var name = parameter.substring(0, equals);
var value = parameter.substring(equals + 1);
switch (name) {
// Number of audio channels
case "channels":
channels = parseInt(value);
break;
// Sample rate
case "rate":
rate = parseInt(value);
break;
// All other parameters are unsupported
default:
return null;
}
}
;
if (rate === null)
return null;
return new Guacamole.RawAudioFormat({
bytesPerSample,
channels,
rate
});
};
var Guacamole = Guacamole || {};
Guacamole.SessionRecording = function SessionRecording(source, refreshInterval) {
if (refreshInterval === void 0)
refreshInterval = 1e3;
var recording = this;
var recordingBlob;
var tunnel = null;
var BLOCK_SIZE = 262144;
var KEYFRAME_CHAR_INTERVAL = 16384;
var KEYFRAME_TIME_INTERVAL = 5e3;
var frames = [];
var lastKeyframe = 0;
var playbackTunnel = new Guacamole.SessionRecording._PlaybackTunnel();
var playbackClient = new Guacamole.Client(playbackTunnel);
var currentFrame = -1;
var startVideoPosition = null;
var startRealTimestamp = null;
var currentPosition = 0;
var activeSeek = null;
var frameStart = 0;
var frameEnd = 0;
var aborted = false;
var seekCallback = null;
var updateTimeout = null;
var lastUpdateTimestamp = null;
var parseBlob = function parseBlob2(blob, instructionCallback, completionCallback) {
if (aborted && blob === recordingBlob)
return;
var parser = new Guacamole.Parser();
parser.oninstruction = instructionCallback;
var offset = 0;
var reader = new FileReader();
var readNextBlock = function readNextBlock2() {
if (aborted && blob === recordingBlob)
return;
if (reader.readyState === 2) {
try {
parser.receive(reader.result);
} catch (parseError) {
if (recording.onerror) {
recording.onerror(parseError.message);
}
return;
}
}
if (offset >= blob.size) {
if (completionCallback)
completionCallback();
} else {
var block = blob.slice(offset, offset + BLOCK_SIZE);
offset += block.size;
reader.readAsText(block);
}
};
reader.onload = readNextBlock;
readNextBlock();
};
var getUtf8StringByteSize = function(str) {
var byteSize = str.length;
for (var i = str.length - 1; i >= 0; i--) {
var code = str.charCodeAt(i);
if (code > 127 && code <= 2047)
byteSize++;
else if (code > 2047 && code <= 65535)
byteSize += 2;
if (code >= 56320 && code <= 57343)
i--;
}
return byteSize;
};
var getElementSize = function getElementSize2(value) {
var byteSize = getUtf8StringByteSize(value) + 3;
var valueLength = Guacamole.Parser.codePointCount(value);
while (valueLength >= 10) {
byteSize++;
valueLength = Math.floor(valueLength / 10);
}
return byteSize;
};
playbackClient.connect();
playbackClient.getDisplay().showCursor(false);
var keyEventInterpreter = null;
function initializeKeyInterpreter(startTimestamp) {
keyEventInterpreter = new Guacamole.KeyEventInterpreter(startTimestamp);
}
var loadInstruction = function loadInstruction2(opcode, args) {
frameEnd += getElementSize(opcode);
for (var i = 0; i < args.length; i++)
frameEnd += getElementSize(args[i]);
if (opcode === "sync") {
var timestamp = parseInt(args[0]);
var frame = new Guacamole.SessionRecording._Frame(timestamp, frameStart, frameEnd);
frames.push(frame);
frameStart = frameEnd;
if (frames.length === 1)
initializeKeyInterpreter(timestamp);
if (frames.length === 1 || frameEnd - frames[lastKeyframe].start >= KEYFRAME_CHAR_INTERVAL && timestamp - frames[lastKeyframe].timestamp >= KEYFRAME_TIME_INTERVAL) {
frame.keyframe = true;
lastKeyframe = frames.length - 1;
}
if (recording.onprogress)
recording.onprogress(recording.getDuration(), frameEnd);
} else if (opcode === "key")
keyEventInterpreter.handleKeyEvent(args);
};
var notifyLoaded = function notifyLoaded2() {
if (recording.onload)
recording.onload();
};
if (source instanceof Blob) {
recordingBlob = source;
parseBlob(recordingBlob, loadInstruction, notifyLoaded);
} else {
tunnel = source;
recordingBlob = new Blob();
var errorEncountered = false;
var instructionBuffer = "";
tunnel.oninstruction = function handleInstruction(opcode, args) {
instructionBuffer += opcode.length + "." + opcode;
args.forEach(function appendArg(arg) {
instructionBuffer += "," + arg.length + "." + arg;
});
instructionBuffer += ";";
if (instructionBuffer.length >= BLOCK_SIZE) {
recordingBlob = new Blob([recordingBlob, instructionBuffer]);
instructionBuffer = "";
}
loadInstruction(opcode, args);
};
tunnel.onerror = function tunnelError(status) {
errorEncountered = true;
if (recording.onerror)
recording.onerror(status.message);
};
tunnel.onstatechange = function tunnelStateChanged(state) {
if (state === Guacamole.Tunnel.State.CLOSED) {
if (instructionBuffer.length) {
recordingBlob = new Blob([recordingBlob, instructionBuffer]);
instructionBuffer = "";
}
if (recording.onkeyevents)
recording.onkeyevents(keyEventInterpreter.getEvents());
if (!errorEncountered)
notifyLoaded();
}
};
}
var toRelativeTimestamp = function toRelativeTimestamp2(timestamp) {
if (frames.length === 0)
return 0;
return timestamp - frames[0].timestamp;
};
var findFrame = function findFrame2(minIndex, maxIndex, timestamp) {
if (minIndex === maxIndex) {
if (minIndex === 0)
return minIndex;
if (toRelativeTimestamp(frames[minIndex].timestamp) > timestamp)
return minIndex - 1;
}
var midIndex = Math.floor((minIndex + maxIndex) / 2);
var midTimestamp = toRelativeTimestamp(frames[midIndex].timestamp);
if (timestamp < midTimestamp && midIndex > minIndex)
return findFrame2(minIndex, midIndex - 1, timestamp);
if (timestamp > midTimestamp && midIndex < maxIndex)
return findFrame2(midIndex + 1, maxIndex, timestamp);
return midIndex;
};
var replayFrame = function replayFrame2(index, callback) {
var frame = frames[index];
parseBlob(recordingBlob.slice(frame.start, frame.end), function handleInstruction(opcode, args) {
playbackTunnel.receiveInstruction(opcode, args);
}, function replayCompleted() {
if (frame.keyframe && !frame.clientState) {
playbackClient.exportState(function storeClientState(state) {
frame.clientState = new Blob([JSON.stringify(state)]);
});
}
currentFrame = index;
if (callback)
callback();
});
};
var seekToFrame = function seekToFrame2(index, callback, nextRealTimestamp) {
abortSeek();
var thisSeek = activeSeek = {
aborted: false
};
var startIndex = index;
var continueReplay = function continueReplay2() {
if (recording.onseek && currentFrame > startIndex) {
currentPosition = toRelativeTimestamp(frames[currentFrame].timestamp);
recording.onseek(
currentPosition,
currentFrame - startIndex,
index - startIndex
);
}
if (thisSeek.aborted)
return;
if (currentFrame < index)
replayFrame(currentFrame + 1, continueReplay2);
else
callback();
};
var continueAfterRequiredDelay = function continueAfterRequiredDelay2() {
var delay = nextRealTimestamp ? Math.max(nextRealTimestamp - (/* @__PURE__ */ new Date()).getTime(), 0) : 0;
if (delay) {
updateTimeout && clearTimeout(updateTimeout);
updateTimeout = window.setTimeout(function timeoutComplete() {
updateTimeout = null;
continueReplay();
}, delay);
} else
continueReplay();
};
for (; startIndex >= 0; startIndex--) {
var frame = frames[startIndex];
if (startIndex === currentFrame)
break;
if (frame.clientState) {
frame.clientState.text().then(function textReady(text) {
playbackClient.importState(JSON.parse(text));
currentFrame = startIndex;
continueAfterRequiredDelay();
});
return;
}
}
continueAfterRequiredDelay();
};
var abortSeek = function abortSeek2() {
if (activeSeek) {
activeSeek.aborted = true;
activeSeek = null;
}
};
var continuePlayback = function continuePlayback2() {
if (!recording.isPlaying())
return;
if (currentFrame + 1 < frames.length) {
var next = frames[currentFrame + 1];
var realLifePlayTime = Date.now() - startRealTimestamp;
var timestampOffset = toRelativeTimestamp(next.timestamp) - startVideoPosition;
var nextFrameDelay = timestampOffset - realLifePlayTime;
var nextRefreshDelay = refreshInterval >= 0 ? refreshInterval * Math.floor(
(currentPosition + refreshInterval) / refreshInterval
) - currentPosition : nextFrameDelay;
if (nextFrameDelay <= nextRefreshDelay)
seekToFrame(currentFrame + 1, function frameDelayElapsed() {
lastUpdateTimestamp = Date.now();
continuePlayback2();
}, Date.now() + nextFrameDelay);
else {
updateTimeout && window.clearTimeout(updateTimeout);
updateTimeout = window.setTimeout(function incrementPosition() {
updateTimeout = null;
currentPosition += nextRefreshDelay;
if (recording.onseek)
recording.onseek(currentPosition);
lastUpdateTimestamp = Date.now();
continuePlayback2();
}, nextRefreshDelay);
}
} else
recording.pause();
};
this.onload = null;
this.onerror = null;
this.onabort = null;
this.onprogress = null;
this.onplay = null;
this.onpause = null;
this.onkeyevents = null;
this.onseek = null;
this.connect = function connect(data) {
if (tunnel)
tunnel.connect(data);
};
this.disconnect = function disconnect() {
if (tunnel)
tunnel.disconnect();
};
this.abort = function abort() {
if (!aborted) {
aborted = true;
if (recording.onabort)
recording.onabort();
if (tunnel)
tunnel.disconnect();
}
};
this.getDisplay = function getDisplay() {
return playbackClient.getDisplay();
};
this.isPlaying = function isPlaying() {
return !!startRealTimestamp;
};
this.getPosition = function getPosition() {
return currentPosition;
};
this.getDuration = function getDuration() {
if (frames.length === 0)
return 0;
return toRelativeTimestamp(frames[frames.length - 1].timestamp);
};
this.play = function play() {
if (!recording.isPlaying() && currentFrame + 1 < frames.length) {
if (recording.onplay)
recording.onplay();
startVideoPosition = currentPosition;
startRealTimestamp = Date.now();
lastUpdateTimestamp = Date.now();
continuePlayback();
}
};
this.seek = function seek(position, callback) {
if (frames.length === 0)
return;
recording.cancel();
var originallyPlaying = recording.isPlaying();
recording.pause();
seekCallback = function restorePlaybackState() {
seekCallback = null;
if (originallyPlaying) {
recording.play();
originallyPlaying = null;
}
if (callback)
callback();
};
var closestFrame = findFrame(0, frames.length - 1, position);
seekToFrame(closestFrame, function seekComplete() {
currentPosition = position;
if (recording.onseek)
recording.onseek(position);
seekCallback();
});
};
this.cancel = function cancel() {
if (seekCallback) {
abortSeek();
seekCallback();
}
};
this.pause = function pause() {
abortSeek();
updateTimeout && clearTimeout(updateTimeout);
currentPosition += Date.now() - lastUpdateTimestamp;
if (recording.isPlaying()) {
if (recording.onpause)
recording.onpause();
lastUpdateTimestamp = null;
startVideoPosition = null;
startRealTimestamp = null;
}
};
};
Guacamole.SessionRecording._Frame = function _Frame(timestamp, start, end) {
this.keyframe = false;
this.timestamp = timestamp;
this.start = start;
this.end = end;
this.clientState = null;
};
Guacamole.SessionRecording._PlaybackTunnel = function _PlaybackTunnel() {
var tunnel = this;
this.connect = function connect(data) {
};
this.sendMessage = function sendMessage(elements) {
};
this.disconnect = function disconnect() {
};
this.receiveInstruction = function receiveInstruction(opcode, args) {
if (tunnel.oninstruction)
tunnel.oninstruction(opcode, args);
};
};
var Guacamole = Guacamole || {};
Guacamole.Status = function(code, message) {
var guac_status = this;
this.code = code;
this.message = message;
this.isError = function() {
return guac_status.code < 0 || guac_status.code > 255;
};
};
Guacamole.Status.Code = {
/**
* The operation succeeded.
*
* @type {!number}
*/
"SUCCESS": 0,
/**
* The requested operation is unsupported.
*
* @type {!number}
*/
"UNSUPPORTED": 256,
/**
* The operation could not be performed due to an internal failure.
*
* @type {!number}
*/
"SERVER_ERROR": 512,
/**
* The operation could not be performed as the server is busy.
*
* @type {!number}
*/
"SERVER_BUSY": 513,
/**
* The operation could not be performed because the upstream server is not
* responding.
*
* @type {!number}
*/
"UPSTREAM_TIMEOUT": 514,
/**
* The operation was unsuccessful due to an error or otherwise unexpected
* condition of the upstream server.
*
* @type {!number}
*/
"UPSTREAM_ERROR": 515,
/**
* The operation could not be performed as the requested resource does not
* exist.
*
* @type {!number}
*/
"RESOURCE_NOT_FOUND": 516,
/**
* The operation could not be performed as the requested resource is
* already in use.
*
* @type {!number}
*/
"RESOURCE_CONFLICT": 517,
/**
* The operation could not be performed as the requested resource is now
* closed.
*
* @type {!number}
*/
"RESOURCE_CLOSED": 518,
/**
* The operation could not be performed because the upstream server does
* not appear to exist.
*
* @type {!number}
*/
"UPSTREAM_NOT_FOUND": 519,
/**
* The operation could not be performed because the upstream server is not
* available to service the request.
*
* @type {!number}
*/
"UPSTREAM_UNAVAILABLE": 520,
/**
* The session within the upstream server has ended because it conflicted
* with another session.
*
* @type {!number}
*/
"SESSION_CONFLICT": 521,
/**
* The session within the upstream server has ended because it appeared to
* be inactive.
*
* @type {!number}
*/
"SESSION_TIMEOUT": 522,
/**
* The session within the upstream server has been forcibly terminated.
*
* @type {!number}
*/
"SESSION_CLOSED": 523,
/**
* The operation could not be performed because bad parameters were given.
*
* @type {!number}
*/
"CLIENT_BAD_REQUEST": 768,
/**
* Permission was denied to perform the operation, as the user is not yet
* authorized (not yet logged in, for example).
*
* @type {!number}
*/
"CLIENT_UNAUTHORIZED": 769,
/**
* Permission was denied to perform the operation, and this permission will
* not be granted even if the user is authorized.
*
* @type {!number}
*/
"CLIENT_FORBIDDEN": 771,
/**
* The client took too long to respond.
*
* @type {!number}
*/
"CLIENT_TIMEOUT": 776,
/**
* The client sent too much data.
*
* @type {!number}
*/
"CLIENT_OVERRUN": 781,
/**
* The client sent data of an unsupported or unexpected type.
*
* @type {!number}
*/
"CLIENT_BAD_TYPE": 783,
/**
* The operation failed because the current client is already using too
* many resources.
*
* @type {!number}
*/
"CLIENT_TOO_MANY": 797
};
Guacamole.Status.Code.fromHTTPCode = function fromHTTPCode(status) {
switch (status) {
// HTTP 400 - Bad request
case 400:
return Guacamole.Status.Code.CLIENT_BAD_REQUEST;
// HTTP 403 - Forbidden
case 403:
return Guacamole.Status.Code.CLIENT_FORBIDDEN;
// HTTP 404 - Resource not found
case 404:
return Guacamole.Status.Code.RESOURCE_NOT_FOUND;
// HTTP 429 - Too many requests
case 429:
return Guacamole.Status.Code.CLIENT_TOO_MANY;
// HTTP 503 - Server unavailable
case 503:
return Guacamole.Status.Code.SERVER_BUSY;
}
return Guacamole.Status.Code.SERVER_ERROR;
};
Guacamole.Status.Code.fromWebSocketCode = function fromWebSocketCode(code) {
switch (code) {
// Successful disconnect (no error)
case 1e3:
return Guacamole.Status.Code.SUCCESS;
// Codes which indicate the server is not reachable
case 1006:
// Abnormal Closure (also signalled by JavaScript when the connection cannot be opened in the first place)
case 1015:
return Guacamole.Status.Code.UPSTREAM_NOT_FOUND;
// Codes which indicate the server is reachable but busy/unavailable
case 1001:
// Going Away
case 1012:
// Service Restart
case 1013:
// Try Again Later
case 1014:
return Guacamole.Status.Code.UPSTREAM_UNAVAILABLE;
}
return Guacamole.Status.Code.SERVER_ERROR;
};
var Guacamole = Guacamole || {};
Guacamole.StringReader = function(stream) {
var guac_reader = this;
var utf8Parser = new Guacamole.UTF8Parser();
var array_reader = new Guacamole.ArrayBufferReader(stream);
array_reader.ondata = function(buffer) {
var text = utf8Parser.decode(buffer);
if (guac_reader.ontext)
guac_reader.ontext(text);
};
array_reader.onend = function() {
if (guac_reader.onend)
guac_reader.onend();
};
this.ontext = null;
this.onend = null;
};
var Guacamole = Guacamole || {};
Guacamole.StringWriter = function(stream) {
var guac_writer = this;
var array_writer = new Guacamole.ArrayBufferWriter(stream);
var buffer = new Uint8Array(8192);
var length = 0;
array_writer.onack = function(status) {
if (guac_writer.onack)
guac_writer.onack(status);
};
function __expand(bytes) {
if (length + bytes >= buffer.length) {
var new_buffer = new Uint8Array((length + bytes) * 2);
new_buffer.set(buffer);
buffer = new_buffer;
}
length += bytes;
}
function __append_utf8(codepoint) {
var mask;
var bytes;
if (codepoint <= 127) {
mask = 0;
bytes = 1;
} else if (codepoint <= 2047) {
mask = 192;
bytes = 2;
} else if (codepoint <= 65535) {
mask = 224;
bytes = 3;
} else if (codepoint <= 2097151) {
mask = 240;
bytes = 4;
} else {
__append_utf8(65533);
return;
}
__expand(bytes);
var offset = length - 1;
for (var i = 1; i < bytes; i++) {
buffer[offset--] = 128 | codepoint & 63;
codepoint >>= 6;
}
buffer[offset] = mask | codepoint;
}
function __encode_utf8(text) {
for (var i = 0; i < text.length; i++) {
var codepoint = text.charCodeAt(i);
__append_utf8(codepoint);
}
if (length > 0) {
var out_buffer = buffer.subarray(0, length);
length = 0;
return out_buffer;
}
}
this.sendText = function(text) {
if (text.length)
array_writer.sendData(__encode_utf8(text));
};
this.sendEnd = function() {
array_writer.sendEnd();
};
this.onack = null;
};
var Guacamole = Guacamole || {};
Guacamole.Touch = function Touch(element) {
Guacamole.Event.Target.call(this);
var guacTouch = this;
var identifierPool = new Guacamole.IntegerPool();
var identifierMapping = {};
var DEFAULT_CONTACT_RADIUS = Math.floor(16 * window.devicePixelRatio);
this.touches = {};
this.activeTouches = 0;
var mapIdentifier = function mapIdentifier2(identifier) {
if (identifier in identifierMapping)
return identifierMapping[identifier];
return identifierMapping[identifier] = identifierPool.next();
};
var unmapIdentifier = function unmapIdentifier2(identifier) {
var id = mapIdentifier(identifier);
delete identifierMapping[identifier];
identifierPool.free(id);
return id;
};
element.addEventListener("touchstart", function touchstart(e) {
for (var i = 0; i < e.changedTouches.length; i++) {
var changedTouch = e.changedTouches[i];
var identifier = mapIdentifier(changedTouch.identifier);
if (guacTouch.touches[identifier])
continue;
var touch = guacTouch.touches[identifier] = new Guacamole.Touch.State({
id: identifier,
radiusX: changedTouch.radiusX || DEFAULT_CONTACT_RADIUS,
radiusY: changedTouch.radiusY || DEFAULT_CONTACT_RADIUS,
angle: changedTouch.angle || 0,
force: changedTouch.force || 1
/* Within JavaScript changedTouch events, a force of 0.0 indicates the device does not support reporting changedTouch force */
});
guacTouch.activeTouches++;
touch.fromClientPosition(element, changedTouch.clientX, changedTouch.clientY);
guacTouch.dispatch(new Guacamole.Touch.Event("touchmove", e, touch));
}
}, false);
element.addEventListener("touchmove", function touchstart(e) {
for (var i = 0; i < e.changedTouches.length; i++) {
var changedTouch = e.changedTouches[i];
var identifier = mapIdentifier(changedTouch.identifier);
var touch = guacTouch.touches[identifier];
if (!touch)
continue;
if (changedTouch.force)
touch.force = changedTouch.force;
touch.angle = changedTouch.angle || 0;
touch.radiusX = changedTouch.radiusX || DEFAULT_CONTACT_RADIUS;
touch.radiusY = changedTouch.radiusY || DEFAULT_CONTACT_RADIUS;
touch.fromClientPosition(element, changedTouch.clientX, changedTouch.clientY);
guacTouch.dispatch(new Guacamole.Touch.Event("touchmove", e, touch));
}
}, false);
element.addEventListener("touchend", function touchstart(e) {
for (var i = 0; i < e.changedTouches.length; i++) {
var changedTouch = e.changedTouches[i];
var identifier = unmapIdentifier(changedTouch.identifier);
var touch = guacTouch.touches[identifier];
if (!touch)
continue;
delete guacTouch.touches[identifier];
guacTouch.activeTouches--;
touch.force = 0;
touch.fromClientPosition(element, changedTouch.clientX, changedTouch.clientY);
guacTouch.dispatch(new Guacamole.Touch.Event("touchend", e, touch));
}
}, false);
};
Guacamole.Touch.State = function State2(template) {
template = template || {};
Guacamole.Position.call(this, template);
this.id = template.id || 0;
this.radiusX = template.radiusX || 0;
this.radiusY = template.radiusY || 0;
this.angle = template.angle || 0;
this.force = template.force || 1;
};
Guacamole.Touch.Event = function TouchEvent(type, event, state) {
Guacamole.Event.DOMEvent.call(this, type, [event]);
this.state = state;
};
var Guacamole = Guacamole || {};
Guacamole.Tunnel = function() {
this.connect = function(data) {
};
this.disconnect = function() {
};
this.sendMessage = function(elements) {
};
this.setState = function(state) {
if (state !== this.state) {
this.state = state;
if (this.onstatechange)
this.onstatechange(state);
}
};
this.setUUID = function setUUID(uuid) {
this.uuid = uuid;
if (this.onuuid)
this.onuuid(uuid);
};
this.isConnected = function isConnected() {
return this.state === Guacamole.Tunnel.State.OPEN || this.state === Guacamole.Tunnel.State.UNSTABLE;
};
this.state = Guacamole.Tunnel.State.CLOSED;
this.receiveTimeout = 15e3;
this.unstableThreshold = 1500;
this.uuid = null;
this.onuuid = null;
this.onerror = null;
this.onstatechange = null;
this.oninstruction = null;
};
Guacamole.Tunnel.INTERNAL_DATA_OPCODE = "";
Guacamole.Tunnel.State = {
/**
* A connection is in pending. It is not yet known whether connection was
* successful.
*
* @type {!number}
*/
"CONNECTING": 0,
/**
* Connection was successful, and data is being received.
*
* @type {!number}
*/
"OPEN": 1,
/**
* The connection is closed. Connection may not have been successful, the
* tunnel may have been explicitly closed by either side, or an error may
* have occurred.
*
* @type {!number}
*/
"CLOSED": 2,
/**
* The connection is open, but communication through the tunnel appears to
* be disrupted, and the connection may close as a result.
*
* @type {!number}
*/
"UNSTABLE": 3
};
Guacamole.HTTPTunnel = function(tunnelURL, crossDomain, extraTunnelHeaders) {
var tunnel = this;
var TUNNEL_CONNECT = tunnelURL + "?connect";
var TUNNEL_READ = tunnelURL + "?read:";
var TUNNEL_WRITE = tunnelURL + "?write:";
var POLLING_ENABLED = 1;
var POLLING_DISABLED = 0;
var pollingMode = POLLING_ENABLED;
var sendingMessages = false;
var outputMessageBuffer = "";
var withCredentials = !!crossDomain;
var receive_timeout = null;
var unstableTimeout = null;
var pingInterval = null;
var PING_FREQUENCY = 500;
var extraHeaders = extraTunnelHeaders || {};
var TUNNEL_TOKEN_HEADER = "Guacamole-Tunnel-Token";
var tunnelSessionToken = null;
function addExtraHeaders(request, headers) {
for (var name in headers) {
request.setRequestHeader(name, headers[name]);
}
}
var resetTimers = function resetTimers2() {
window.clearTimeout(receive_timeout);
window.clearTimeout(unstableTimeout);
if (tunnel.state === Guacamole.Tunnel.State.UNSTABLE)
tunnel.setState(Guacamole.Tunnel.State.OPEN);
receive_timeout = window.setTimeout(function() {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.UPSTREAM_TIMEOUT, "Server timeout."));
}, tunnel.receiveTimeout);
unstableTimeout = window.setTimeout(function() {
tunnel.setState(Guacamole.Tunnel.State.UNSTABLE);
}, tunnel.unstableThreshold);
};
function close_tunnel(status) {
window.clearTimeout(receive_timeout);
window.clearTimeout(unstableTimeout);
window.clearInterval(pingInterval);
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
return;
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror) {
if (tunnel.state === Guacamole.Tunnel.State.CONNECTING || status.code !== Guacamole.Status.Code.RESOURCE_NOT_FOUND)
tunnel.onerror(status);
}
sendingMessages = false;
tunnel.setState(Guacamole.Tunnel.State.CLOSED);
}
this.sendMessage = function() {
if (!tunnel.isConnected())
return;
if (!arguments.length)
return;
outputMessageBuffer += Guacamole.Parser.toInstruction(arguments);
if (!sendingMessages)
sendPendingMessages();
};
function sendPendingMessages() {
if (!tunnel.isConnected())
return;
if (outputMessageBuffer.length > 0) {
sendingMessages = true;
var message_xmlhttprequest = new XMLHttpRequest();
message_xmlhttprequest.open("POST", TUNNEL_WRITE + tunnel.uuid);
message_xmlhttprequest.withCredentials = withCredentials;
addExtraHeaders(message_xmlhttprequest, extraHeaders);
message_xmlhttprequest.setRequestHeader("Content-type", "application/octet-stream");
message_xmlhttprequest.setRequestHeader(TUNNEL_TOKEN_HEADER, tunnelSessionToken);
message_xmlhttprequest.onreadystatechange = function() {
if (message_xmlhttprequest.readyState === 4) {
resetTimers();
if (message_xmlhttprequest.status !== 200)
handleHTTPTunnelError(message_xmlhttprequest);
else
sendPendingMessages();
}
};
message_xmlhttprequest.send(outputMessageBuffer);
outputMessageBuffer = "";
} else
sendingMessages = false;
}
function handleHTTPTunnelError(xmlhttprequest) {
var code = parseInt(xmlhttprequest.getResponseHeader("Guacamole-Status-Code"));
if (code) {
var message = xmlhttprequest.getResponseHeader("Guacamole-Error-Message");
close_tunnel(new Guacamole.Status(code, message));
} else if (xmlhttprequest.status)
close_tunnel(new Guacamole.Status(
Guacamole.Status.Code.fromHTTPCode(xmlhttprequest.status),
xmlhttprequest.statusText
));
else
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.UPSTREAM_NOT_FOUND));
}
function handleResponse(xmlhttprequest) {
var interval = null;
var nextRequest = null;
var dataUpdateEvents = 0;
var parser = new Guacamole.Parser();
parser.oninstruction = function instructionReceived(opcode, args) {
if (opcode === Guacamole.Tunnel.INTERNAL_DATA_OPCODE && args.length === 0) {
parser = new Guacamole.Parser();
parser.oninstruction = instructionReceived;
if (interval)
clearInterval(interval);
xmlhttprequest.onreadystatechange = null;
xmlhttprequest.abort();
if (nextRequest)
handleResponse(nextRequest);
} else if (opcode !== Guacamole.Tunnel.INTERNAL_DATA_OPCODE && tunnel.oninstruction)
tunnel.oninstruction(opcode, args);
};
function parseResponse() {
if (!tunnel.isConnected()) {
if (interval !== null)
clearInterval(interval);
return;
}
if (xmlhttprequest.readyState < 2) return;
var status;
try {
status = xmlhttprequest.status;
} catch (e) {
status = 200;
}
if (!nextRequest && status === 200)
nextRequest = makeRequest();
if (xmlhttprequest.readyState === 3 || xmlhttprequest.readyState === 4) {
resetTimers();
if (pollingMode === POLLING_ENABLED) {
if (xmlhttprequest.readyState === 3 && !interval)
interval = setInterval(parseResponse, 30);
else if (xmlhttprequest.readyState === 4 && interval)
clearInterval(interval);
}
if (xmlhttprequest.status === 0) {
tunnel.disconnect();
return;
} else if (xmlhttprequest.status !== 200) {
handleHTTPTunnelError(xmlhttprequest);
return;
}
var current;
try {
current = xmlhttprequest.responseText;
} catch (e) {
return;
}
try {
parser.receive(current, true);
} catch (e) {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.SERVER_ERROR, e.message));
return;
}
}
}
if (pollingMode === POLLING_ENABLED) {
xmlhttprequest.onreadystatechange = function() {
if (xmlhttprequest.readyState === 3) {
dataUpdateEvents++;
if (dataUpdateEvents >= 2) {
pollingMode = POLLING_DISABLED;
xmlhttprequest.onreadystatechange = parseResponse;
}
}
parseResponse();
};
} else
xmlhttprequest.onreadystatechange = parseResponse;
parseResponse();
}
var request_id = 0;
function makeRequest() {
var xmlhttprequest = new XMLHttpRequest();
xmlhttprequest.open("GET", TUNNEL_READ + tunnel.uuid + ":" + request_id++);
xmlhttprequest.setRequestHeader(TUNNEL_TOKEN_HEADER, tunnelSessionToken);
xmlhttprequest.withCredentials = withCredentials;
addExtraHeaders(xmlhttprequest, extraHeaders);
xmlhttprequest.send(null);
return xmlhttprequest;
}
this.connect = function(data) {
resetTimers();
tunnel.setState(Guacamole.Tunnel.State.CONNECTING);
var connect_xmlhttprequest = new XMLHttpRequest();
connect_xmlhttprequest.onreadystatechange = function() {
if (connect_xmlhttprequest.readyState !== 4)
return;
if (connect_xmlhttprequest.status !== 200) {
handleHTTPTunnelError(connect_xmlhttprequest);
return;
}
resetTimers();
tunnel.setUUID(connect_xmlhttprequest.responseText);
tunnelSessionToken = connect_xmlhttprequest.getResponseHeader(TUNNEL_TOKEN_HEADER);
if (!tunnelSessionToken) {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.UPSTREAM_NOT_FOUND));
return;
}
tunnel.setState(Guacamole.Tunnel.State.OPEN);
pingInterval = setInterval(function sendPing() {
tunnel.sendMessage("nop");
}, PING_FREQUENCY);
handleResponse(makeRequest());
};
connect_xmlhttprequest.open("POST", TUNNEL_CONNECT, true);
connect_xmlhttprequest.withCredentials = withCredentials;
addExtraHeaders(connect_xmlhttprequest, extraHeaders);
connect_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
connect_xmlhttprequest.send(data);
};
this.disconnect = function() {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.SUCCESS, "Manually closed."));
};
};
Guacamole.HTTPTunnel.prototype = new Guacamole.Tunnel();
Guacamole.WebSocketTunnel = function(tunnelURL) {
var tunnel = this;
var parser = null;
var socket = null;
var receive_timeout = null;
var unstableTimeout = null;
var pingTimeout = null;
var ws_protocol = {
"http:": "ws:",
"https:": "wss:"
};
var PING_FREQUENCY = 500;
var lastSentPing = 0;
if (tunnelURL.substring(0, 3) !== "ws:" && tunnelURL.substring(0, 4) !== "wss:") {
var protocol = ws_protocol[window.location.protocol];
if (tunnelURL.substring(0, 1) === "/")
tunnelURL = protocol + "//" + window.location.host + tunnelURL;
else {
var slash = window.location.pathname.lastIndexOf("/");
var path = window.location.pathname.substring(0, slash + 1);
tunnelURL = protocol + "//" + window.location.host + path + tunnelURL;
}
}
var sendPing = function sendPing2() {
var currentTime = (/* @__PURE__ */ new Date()).getTime();
tunnel.sendMessage(Guacamole.Tunnel.INTERNAL_DATA_OPCODE, "ping", currentTime);
lastSentPing = currentTime;
};
var resetTimers = function resetTimers2() {
window.clearTimeout(receive_timeout);
window.clearTimeout(unstableTimeout);
window.clearTimeout(pingTimeout);
if (tunnel.state === Guacamole.Tunnel.State.UNSTABLE)
tunnel.setState(Guacamole.Tunnel.State.OPEN);
receive_timeout = window.setTimeout(function() {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.UPSTREAM_TIMEOUT, "Server timeout."));
}, tunnel.receiveTimeout);
unstableTimeout = window.setTimeout(function() {
tunnel.setState(Guacamole.Tunnel.State.UNSTABLE);
}, tunnel.unstableThreshold);
var currentTime = (/* @__PURE__ */ new Date()).getTime();
var pingDelay = Math.max(lastSentPing + PING_FREQUENCY - currentTime, 0);
if (pingDelay > 0)
pingTimeout = window.setTimeout(sendPing, pingDelay);
else
sendPing();
};
function close_tunnel(status) {
window.clearTimeout(receive_timeout);
window.clearTimeout(unstableTimeout);
window.clearTimeout(pingTimeout);
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
return;
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
tunnel.onerror(status);
tunnel.setState(Guacamole.Tunnel.State.CLOSED);
socket.close();
}
this.sendMessage = function(elements) {
if (!tunnel.isConnected())
return;
if (!arguments.length)
return;
socket.send(Guacamole.Parser.toInstruction(arguments));
};
this.connect = function(data) {
resetTimers();
tunnel.setState(Guacamole.Tunnel.State.CONNECTING);
parser = new Guacamole.Parser();
parser.oninstruction = function instructionReceived(opcode, args) {
if (tunnel.uuid === null) {
if (opcode === Guacamole.Tunnel.INTERNAL_DATA_OPCODE && args.length === 1)
tunnel.setUUID(args[0]);
tunnel.setState(Guacamole.Tunnel.State.OPEN);
}
if (opcode !== Guacamole.Tunnel.INTERNAL_DATA_OPCODE && tunnel.oninstruction)
tunnel.oninstruction(opcode, args);
};
socket = new WebSocket(tunnelURL + "?" + data, "guacamole");
socket.onopen = function(event) {
resetTimers();
};
socket.onclose = function(event) {
if (event.reason)
close_tunnel(new Guacamole.Status(parseInt(event.reason), event.reason));
else if (event.code)
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.fromWebSocketCode(event.code)));
else
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.UPSTREAM_NOT_FOUND));
};
socket.onmessage = function(event) {
resetTimers();
try {
parser.receive(event.data);
} catch (e) {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.SERVER_ERROR, e.message));
}
};
};
this.disconnect = function() {
close_tunnel(new Guacamole.Status(Guacamole.Status.Code.SUCCESS, "Manually closed."));
};
};
Guacamole.WebSocketTunnel.prototype = new Guacamole.Tunnel();
Guacamole.ChainedTunnel = function(tunnelChain) {
var chained_tunnel = this;
var connect_data;
var tunnels = [];
var committedTunnel = null;
for (var i = 0; i < arguments.length; i++)
tunnels.push(arguments[i]);
function attach(tunnel) {
chained_tunnel.disconnect = tunnel.disconnect;
chained_tunnel.sendMessage = tunnel.sendMessage;
var failTunnel = function failTunnel2(status) {
if (status && status.code === Guacamole.Status.Code.UPSTREAM_TIMEOUT) {
tunnels = [];
return null;
}
var next_tunnel = tunnels.shift();
if (next_tunnel) {
tunnel.onerror = null;
tunnel.oninstruction = null;
tunnel.onstatechange = null;
attach(next_tunnel);
}
return next_tunnel;
};
function commit_tunnel() {
tunnel.onstatechange = chained_tunnel.onstatechange;
tunnel.oninstruction = chained_tunnel.oninstruction;
tunnel.onerror = chained_tunnel.onerror;
if (tunnel.uuid)
chained_tunnel.setUUID(tunnel.uuid);
tunnel.onuuid = function uuidReceived(uuid) {
chained_tunnel.setUUID(uuid);
};
committedTunnel = tunnel;
}
tunnel.onstatechange = function(state) {
switch (state) {
// If open, use this tunnel from this point forward.
case Guacamole.Tunnel.State.OPEN:
commit_tunnel();
if (chained_tunnel.onstatechange)
chained_tunnel.onstatechange(state);
break;
// If closed, mark failure, attempt next tunnel
case Guacamole.Tunnel.State.CLOSED:
if (!failTunnel() && chained_tunnel.onstatechange)
chained_tunnel.onstatechange(state);
break;
}
};
tunnel.oninstruction = function(opcode, elements) {
commit_tunnel();
if (chained_tunnel.oninstruction)
chained_tunnel.oninstruction(opcode, elements);
};
tunnel.onerror = function(status) {
if (!failTunnel(status) && chained_tunnel.onerror)
chained_tunnel.onerror(status);
};
tunnel.connect(connect_data);
}
this.connect = function(data) {
connect_data = data;
var next_tunnel = committedTunnel ? committedTunnel : tunnels.shift();
if (next_tunnel)
attach(next_tunnel);
else if (chained_tunnel.onerror)
chained_tunnel.onerror(Guacamole.Status.Code.SERVER_ERROR, "No tunnels to try.");
};
};
Guacamole.ChainedTunnel.prototype = new Guacamole.Tunnel();
Guacamole.StaticHTTPTunnel = function StaticHTTPTunnel(url, crossDomain, extraTunnelHeaders) {
var tunnel = this;
var abortController = null;
var extraHeaders = extraTunnelHeaders || {};
this.size = null;
this.sendMessage = function sendMessage(elements) {
};
this.connect = function connect(data) {
tunnel.disconnect();
tunnel.setState(Guacamole.Tunnel.State.CONNECTING);
var parser = new Guacamole.Parser();
var utf8Parser = new Guacamole.UTF8Parser();
parser.oninstruction = function instructionReceived(opcode, args) {
if (tunnel.oninstruction)
tunnel.oninstruction(opcode, args);
};
abortController = new AbortController();
fetch(url, {
headers: extraHeaders,
credentials: crossDomain ? "include" : "same-origin",
signal: abortController.signal
}).then(function gotResponse(response) {
if (!response.ok) {
if (tunnel.onerror)
tunnel.onerror(new Guacamole.Status(
Guacamole.Status.Code.fromHTTPCode(response.status),
response.statusText
));
tunnel.disconnect();
return;
}
tunnel.size = response.headers.get("Content-Length");
tunnel.setState(Guacamole.Tunnel.State.OPEN);
var reader = response.body.getReader();
var processReceivedText = function processReceivedText2(result) {
if (result.done) {
tunnel.disconnect();
return;
}
parser.receive(utf8Parser.decode(result.value));
reader.read().then(processReceivedText2);
};
reader.read().then(processReceivedText);
});
};
this.disconnect = function disconnect() {
if (abortController) {
abortController.abort();
abortController = null;
}
tunnel.setState(Guacamole.Tunnel.State.CLOSED);
};
};
Guacamole.StaticHTTPTunnel.prototype = new Guacamole.Tunnel();
var Guacamole = Guacamole || {};
Guacamole.UTF8Parser = function UTF8Parser() {
var bytesRemaining = 0;
var codepoint = 0;
this.decode = function decode(buffer) {
var text = "";
var bytes = new Uint8Array(buffer);
for (var i = 0; i < bytes.length; i++) {
var value = bytes[i];
if (bytesRemaining === 0) {
if ((value | 127) === 127)
text += String.fromCharCode(value);
else if ((value | 31) === 223) {
codepoint = value & 31;
bytesRemaining = 1;
} else if ((value | 15) === 239) {
codepoint = value & 15;
bytesRemaining = 2;
} else if ((value | 7) === 247) {
codepoint = value & 7;
bytesRemaining = 3;
} else
text += "";
} else if ((value | 63) === 191) {
codepoint = codepoint << 6 | value & 63;
bytesRemaining--;
if (bytesRemaining === 0)
text += String.fromCharCode(codepoint);
} else {
bytesRemaining = 0;
text += "";
}
}
return text;
};
};
var Guacamole = Guacamole || {};
Guacamole.API_VERSION = "1.6.0";
var Guacamole = Guacamole || {};
Guacamole.VideoPlayer = function VideoPlayer() {
this.sync = function sync() {
};
};
Guacamole.VideoPlayer.isSupportedType = function isSupportedType5(mimetype) {
return false;
};
Guacamole.VideoPlayer.getSupportedTypes = function getSupportedTypes5() {
return [];
};
Guacamole.VideoPlayer.getInstance = function getInstance3(stream, layer, mimetype) {
return null;
};
var guacamole_common_default = Guacamole;
export {
guacamole_common_default as default
};
//# sourceMappingURL=@dushixiang_guacamole-common-js.js.map