You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/01/16 18:41:53 UTC

[07/23] guacamole-client git commit: GUACAMOLE-352: Add Guacamole.Keyboard.InputSink object to serve as a reliable default destination for input events.

GUACAMOLE-352: Add Guacamole.Keyboard.InputSink object to serve as a reliable default destination for input events.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/f9a639d2
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/f9a639d2
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/f9a639d2

Branch: refs/heads/master
Commit: f9a639d2014815c8e68bdebb17dd78283d31ee68
Parents: 3d6a3aa
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Dec 17 22:38:10 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 16 09:50:54 2018 -0800

----------------------------------------------------------------------
 .../src/main/webapp/modules/Keyboard.js         | 88 ++++++++++++++++++++
 1 file changed, 88 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/f9a639d2/guacamole-common-js/src/main/webapp/modules/Keyboard.js
----------------------------------------------------------------------
diff --git a/guacamole-common-js/src/main/webapp/modules/Keyboard.js b/guacamole-common-js/src/main/webapp/modules/Keyboard.js
index a11050f..ea7128b 100644
--- a/guacamole-common-js/src/main/webapp/modules/Keyboard.js
+++ b/guacamole-common-js/src/main/webapp/modules/Keyboard.js
@@ -1324,3 +1324,91 @@ Guacamole.Keyboard.ModifierState.fromKeyboardEvent = function(e) {
     return state;
     
 };
+
+/**
+ * A hidden input field which attempts to keep itself focused at all times,
+ * except when another input field has been intentionally focused, whether
+ * programatically or by the user. The actual underlying input field, returned
+ * by getElement(), may be used as a reliable source of keyboard-related events,
+ * particularly composition and input events which may require a focused input
+ * field to be dispatched at all.
+ *
+ * @constructor
+ */
+Guacamole.Keyboard.InputSink = function InputSink() {
+
+    /**
+     * Reference to this instance of Guacamole.Keyboard.InputSink.
+     *
+     * @private
+     * @type {Guacamole.Keyboard.InputSink}
+     */
+    var sink = this;
+
+    /**
+     * The underlying input field, styled to be invisible.
+     *
+     * @private
+     * @type {Element}
+     */
+    var field = document.createElement('textarea');
+    field.setAttribute('autofocus', 'autofocus');
+    field.style.position = 'fixed';
+    field.style.border   = 'none';
+    field.style.width    = '10px';
+    field.style.height   = '10px';
+    field.style.left     = '-10px';
+    field.style.top      = '-10px';
+
+    /**
+     * Clears the contents of the underlying field. The actual clearing of the
+     * field is deferred, occurring asynchronously after the call completes.
+     *
+     * @private
+     */
+    var clear = function clear() {
+        window.setTimeout(function deferClear() {
+            field.value = '';
+        }, 0);
+    };
+
+    // Keep internal field contents clear
+    field.addEventListener("change", clear, false);
+    field.addEventListener("input", clear, false);
+
+    /**
+     * Attempts to focus the underlying input field. The focus attempt occurs
+     * asynchronously, and may silently fail depending on browser restrictions.
+     */
+    this.focus = function focus() {
+        window.setTimeout(function deferRefocus() {
+            field.focus(); // Focus must be deferred to work reliably across browsers
+        }, 0);
+    };
+
+    /**
+     * Returns the underlying input field. This input field MUST be manually
+     * added to the DOM for the Guacamole.Keyboard.InputSink to have any
+     * effect.
+     *
+     * @returns {Element}
+     */
+    this.getElement = function getElement() {
+        return field;
+    };
+
+    // Automatically refocus input sink if part of DOM
+    document.addEventListener("click", function refocusSink(e) {
+
+        // Do not refocus if focus is on an input field
+        var focused = document.activeElement;
+        if (focused && focused !== document.body)
+            return;
+
+        // Refocus input sink instead of handling click
+        sink.focus();
+        e.preventDefault();
+
+    }, true);
+
+};