4

We are streaming our vnc server using guacamole(http://guac-dev.org/) in the browser using an iframe. We are unable to get the keyboard events on the vnc canvas. Though once we click on the div outside the guacamole canvas, focus gets into the required part and key events are captured properly.

We have deployed the application on http://test-mate.com:8081/#/

Below is the guacamole rendering code.

<body>

    <!-- Display -->
    <div class="displayOuter">
        <div class="displayMiddle">
            <div id="display">
            </div>
        </div>
    </div>

    <!-- Dimensional clone of viewport -->
    <div id="viewportClone"/>

    <!-- Notification area -->
    <div id="notificationArea"/>

    <!-- Images which should be preloaded -->
    <div id="preload">
        <img src="images/action-icons/guac-close.png"/>
        <img src="images/progress.png"/>
    </div>

    <script type="text/javascript" src="scripts/lib/blob/blob.js"></script>
    <script type="text/javascript" src="scripts/lib/filesaver/filesaver.js"></script>

    <!-- guacamole-common-js scripts -->
    <script type="text/javascript" src="guacamole-common-js/keyboard.js"></script>
    <script type="text/javascript" src="guacamole-common-js/mouse.js"></script>
    <script type="text/javascript" src="guacamole-common-js/layer.js"></script>
    <script type="text/javascript" src="guacamole-common-js/tunnel.js"></script>
    <script type="text/javascript" src="guacamole-common-js/audio.js"></script>
    <script type="text/javascript" src="guacamole-common-js/guacamole.js"></script>
    <script type="text/javascript" src="guacamole-common-js/oskeyboard.js"></script>

    <!-- guacamole-default-webapp scripts -->
    <script type="text/javascript" src="scripts/session.js"></script>
    <script type="text/javascript" src="scripts/history.js"></script>
    <script type="text/javascript" src="scripts/guac-ui.js"></script>
    <script type="text/javascript" src="scripts/client-ui.js"></script>

    <!-- Init -->
    <script type="text/javascript"> /* <![CDATA[ */

        // Start connect after control returns from onload (allow browser
        // to consider the page loaded).
        window.onload = function() {
            window.setTimeout(function() {

                var tunnel;

                // If WebSocket available, try to use it.
                //if (window.WebSocket)
                    //tunnel = new Guacamole.ChainedTunnel(
                        //new Guacamole.WebSocketTunnel("websocket-tunnel"),
                        //new Guacamole.HTTPTunnel("tunnel")
                    //);

                // If no WebSocket, then use HTTP.
               // else
                    tunnel = new Guacamole.HTTPTunnel("tunnel")

                // Instantiate client
                var guac = new Guacamole.Client(tunnel);

                // Add client to UI
                guac.getDisplay().className = "software-cursor";
                GuacUI.Client.display.appendChild(guac.getDisplay());

                // Tie UI to client
                GuacUI.Client.attach(guac);

                try {

                    // Calculate optimal width/height for display
                    var optimal_width = window.innerWidth;
                    var optimal_height = window.innerHeight;

                    // Scale width/height to be at least 600x600
                    if (optimal_width < 600 || optimal_height < 600) {
                        var scale = Math.max(600 / optimal_width, 600 / optimal_height);
                        optimal_width = Math.floor(optimal_width * scale);
                        optimal_height = Math.floor(optimal_height * scale);
                    }

                    // Get entire query string, and pass to connect().
                    // Normally, only the "id" parameter is required, but
                    // all parameters should be preserved and passed on for
                    // the sake of authentication.

                    var connect_string =
                        window.location.search.substring(1)
                        + "&width="  + optimal_width
                        + "&height=" + optimal_height;

                    // Add audio mimetypes to connect_string
                    GuacUI.Audio.supported.forEach(function(mimetype) {
                        connect_string += "&audio=" + encodeURIComponent(mimetype);
                    });

                    // Add video mimetypes to connect_string
                    GuacUI.Video.supported.forEach(function(mimetype) {
                        connect_string += "&video=" + encodeURIComponent(mimetype);
                    });

                    guac.connect(connect_string);

                }
                catch (e) {
                    GuacUI.Client.showError(e.message);
                }

            }, 0);
        };

    /* ]]> */ </script>

</body>
Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
Rahul Chaki
  • 61
  • 1
  • 4

4 Answers4

1

This problem is sloved by calling following function.

function setFocusThickboxIframe() {
    var iframe = $("#TB_iframeContent")[0];
    iframe.contentWindow.focus();
}

everytime user clicks on iframe. And window.focus() when he clicks on main window to shoft focus to it.

raju
  • 4,788
  • 15
  • 64
  • 119
0

We are using an iframe setup from the JOOMLA wrapper module.

The fix for the text focus was to have the the wrapper module:

  1. Define an additional javascript function setFocus()

  2. Include onmouseover="setFocus()" within the parameters

Here is code in modules/mod_wrapper/tmpl/default.php showing this:

<?php
...
defined('_JEXEC') or die;
?>
<script type="text/javascript">
        function iFrameHeight()
        {
...
        }
        function setFocus() {
          document.getElementById('blockrandom').contentWindow.focus();
        }
</script>
<iframe <?php echo $load; ?>
        id="blockrandom"
        name="<?php echo $target; ?>"
        src="<?php echo $url; ?>"
        width="<?php echo $width; ?>"
        height="<?php echo $height; ?>"
        scrolling="<?php echo $scroll; ?>"
        frameborder="<?php echo $frameborder; ?>"
        sandbox="allow-same-origin allow-scripts allow-forms allow-top-navigation"
        onmouseover="setFocus();"
        class="wrapper<?php echo $moduleclass_sfx; ?>" >
        <?php echo JText::_('MOD_WRAPPER_NO_IFRAMES'); ?>
</iframe>
lcbrevard
  • 263
  • 1
  • 12
  • I guess I should have added that the URL in the iframe is to the guacamole served vncserver desktop. Typically looking like: /guacamole/client.xhtml?id=c%2Fade3 – lcbrevard Feb 20 '14 at 22:07
0

TL;DR

<body onkeydown="myframe.contentWindow.focus()">

Based on answer by @raju but without JQuery. Short, modern vanilla. Disclaimer: This was the ONLY way I could get it to work. Elaboration below.

<!DOCTYPE html>

<body onkeydown="myframe.contentWindow.focus()">

<iframe id=myframe src="/guac" contextmenu="return false" style="
  position: absolute;  top: 0px;  left: 0px;
  border: none;  outline: none;
  height: 100%;  width: 100%;
  user-select: none;
"></iframe>

The magic here is the body tag. Trick is using a keydown event on the body element tripping [yourFrameID].contentWindow.focus() to return focus to Guac's page inside the iFrame.


The only other way it worked for me was to run the [id].windowContent.onFocus() from the DevTools console each time I loaded the page.

I tried a number of different ways-- the iFrame itself, other events, many variations.

If someone can show another (plain and simple) way that works, would love to see it.


Anyway, the rest of the code forms a simple, yet complete, implementation.

--all you need for a modern wrapper for Guacamole, which will size perfectly to the browser window, get keyboard input to the Guac client, and not do anything wierd if somehow the user triggers a selection. And you can use a right-click without the browser hijacking your context menu.

jdmayfield
  • 1,400
  • 1
  • 14
  • 26
0

I was using angular.

I called this function in the ngOnInit of the component containing the IFrame.

private setFocusIframe() {
    const frame = document.querySelector<HTMLIFrameElement>("#myframe")
    window.addEventListener("keydown", function(event: KeyboardEvent){
      frame.contentWindow.focus();
    })
}
Ankit Raibole
  • 35
  • 2
  • 7