UNPKG

vue-guacamole-client

Version:

A Vue.js based Guacamole client

214 lines (187 loc) 6.7 kB
/** * Contains code relevant to handling mouse, keyboard, * and clipboard input for a Guacamole connection */ import Guacamole from 'guacamole-common-js' export default{ methods: { /** * Initializes the mouse event handlers and ties it to a display */ initMouse () { this.mouse = new Guacamole.Mouse(this.client.getDisplay().getElement()) this.mouse.onmousedown = this.mouse.onmouseup = this.mouse.onmousemove = (mouseState) => { this.updateActivity() this.client.sendMouseState(mouseState) } // let oldEvent = this.mouse.fromClientPosition // this.mouse.fromClientPosition = function(element, clientX, clientY) { // console.log("here") // oldEvent(element, clientX, clientY) // } }, /** * Initializes the keyboard event handlers and ties it to the document * * The document is the preferred method for the event handlers, * but can cause some trouble if not careful. All input for the tab will be * directed to this connection while these event handlers are in place. When * wanting to not redirect the input to the VM (when the options drawer is open for instance) * the event handlers will need to be nullified */ initKeyboard () { this.keyboard = new Guacamole.Keyboard(document); if (!this.options.showOptionsDrawer && this.viewState !== 'thumbnail') { this.keyboard.onkeydown = (keysym) => this.client.sendKeyEvent(1, keysym) this.keyboard.onkeyup = (keysym) => this.client.sendKeyEvent(0, keysym) } else { this.keyboard.onkeydown = null this.keyboard.onkeyup = null } }, /** * Initializes the clipboard event handlers * * These event handlers will watch for changes to the VM clipboard and fire when * those changes are detected. The value of the clipboard is saved in the options object. */ initClipboard () { this.client.onclipboard = (stream, mimetype) => { // Only text/plain is supported for now if (mimetype !== 'text/plain') { stream.sendAck('Only text/plain supported', Guacamole.Status.Code.UNSUPPORTED) return } var reader = new Guacamole.StringReader(stream) var data = '' // Append any received data to buffer reader.ontext = (text) => { data += text stream.sendAck('Received', Guacamole.Status.Code.SUCCESS) } // Update state when done reader.onend = () => { this.options.clipboard = data } } }, /** * Sets the clipboard of the VM to the value found in the clipboard * property of the options object * * Used to inject clipboard data to the VM */ setClipboard () { const stream = this.client.createClipboardStream() const writer = new Guacamole.StringWriter(stream) // Send text chunks for (let i = 0; i < this.options.clipboard.length; i += 4096) { writer.sendText(this.options.clipboard.substring(i, i + 4096)) } // Close stream writer.sendEnd() }, /** * Updates the mouse event listeners to correctly use the current scale of the display * * With out this the remote mouse and the local mouse will be offset based on the scale of the display */ setScaledMouseState (scale) { this.display.scale(scale) this.mouse.onmousedown = this.mouse.onmouseup = this.mouse.onmousemove = (mouseState) => { // Scale event by current scale const scaledState = new Guacamole.Mouse.State( mouseState.x / scale, mouseState.y / scale, mouseState.left, mouseState.middle, mouseState.right, mouseState.up, mouseState.down ) this.updateActivity() this.scrollToMouse(mouseState) this.client.sendMouseState(scaledState) } }, /** * Scrolls the client view such that the mouse cursor is visible. * * @param {Guacamole.Mouse.State} mouseState The current mouse * state. */ scrollToMouse (mouseState) { const displayContainer = this.$refs.displayWrapper const main = this.$refs.display // Determine mouse position within view const mouseViewX = mouseState.x + displayContainer.offsetLeft - main.scrollLeft const mouseViewY = mouseState.y + displayContainer.offsetTop - main.scrollTop // Determine viewport dimensions const viewWidth = main.offsetWidth const viewHeight = main.offsetHeight // Determine scroll amounts based on mouse position relative to document let scrollAmountX if (mouseViewX > viewWidth) { scrollAmountX = mouseViewX - viewWidth } else if (mouseViewX < 0) { scrollAmountX = mouseViewX } else { scrollAmountX = 0 } let scrollAmountY if (mouseViewY > viewHeight) { scrollAmountY = mouseViewY - viewHeight } else if (mouseViewY < 0) { scrollAmountY = mouseViewY } else { scrollAmountY = 0 } // Scroll (if necessary) to keep mouse on screen. main.scrollLeft += scrollAmountX main.scrollTop += scrollAmountY } }, beforeDestroy () { if (this.keyboard){ this.keyboard.onkeydown = null this.keyboard.onkeyup = null } }, watch: { /** * Removes the event handlers for the keyboard when options drawer * is displayed * * Restores keyboard event handlers when options drawer is closed */ 'options.showOptionsDrawer': function (showOptionsDrawer) { if (!this.keyboard) return if (!showOptionsDrawer) { this.keyboard.onkeydown = (keysym) => this.client.sendKeyEvent(1, keysym) this.keyboard.onkeyup = (keysym) => this.client.sendKeyEvent(0, keysym) } else { this.keyboard.onkeydown = null this.keyboard.onkeyup = null } }, /** * Removes the event handlers for the keyboard when options drawer * is displayed * * Restores keyboard event handlers when options drawer is closed */ 'viewState': function (viewState) { if (!this.keyboard) return if (!(viewState === 'thumbnail')) { this.keyboard.onkeydown = (keysym) => { this.updateActivity() this.client.sendKeyEvent(1, keysym) } this.keyboard.onkeyup = (keysym) => this.client.sendKeyEvent(0, keysym) } else { this.keyboard.onkeydown = null this.keyboard.onkeyup = null } } } }