无法在Guacamole iframe中获取键盘事件

4
我们正在使用guacamole(http://guac-dev.org/)在浏览器中通过iframe流式传输我们的vnc服务器。但是,我们无法在vnc画布上获取键盘事件。不过,一旦我们单击guacamole画布外部的div,焦点就会进入所需部分,并且键事件会被正确捕获。

我们已经将应用程序部署在http://test-mate.com:8081/#/

以下是guacamole渲染代码。

<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>

这里的Java链接是什么?为什么你的问题要加上Java标签? - Hovercraft Full Of Eels
@Rahul Chaki - 你最终解决了这个问题吗?raju的“答案”有帮助吗?我也遇到了同样没有键盘事件的问题。 - lcbrevard
有人解决了吗?我正在尝试使用两个DIV来拆分屏幕,左侧DIV显示的是iFrame HTML页面,右侧DIV显示的是ng-view(canvas)。当点击左侧HTML页面并尝试在右侧vm上键入时,会丢失键盘焦点。 - Suheal Pasha
4个回答

1
这个问题可以通过调用以下函数来解决。
function setFocusThickboxIframe() {
    var iframe = $("#TB_iframeContent")[0];
    iframe.contentWindow.focus();
}

每当用户点击iframe时,使用window.focus()使主窗口获得焦点。

0

我们正在使用JOOMLA包装器模块的iframe设置。

文本焦点的修复方法是要求包装器模块:

  1. 定义一个额外的javascript函数setFocus()

  2. 在参数中包含onmouseover="setFocus()"

以下是modules/mod_wrapper/tmpl/default.php中显示此内容的代码:

<?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>

我猜我应该补充说明一下 iframe 中的 URL 是指提供 VNC 服务器桌面服务的鳄梨(Guacamole)URL,通常看起来像: /guacamole/client.xhtml?id=c%2Fade3 - lcbrevard

0

简而言之

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

基于@raju的答案,但没有使用JQuery。简短、现代、纯净。免责声明:这是我唯一能让它工作的方法。详见下文。

<!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>

这里的魔法在于body标签。 技巧是在body元素上使用keydown事件,触发[yourFrameID].contentWindow.focus()将焦点返回到iFrame内部Guac页面。


唯一另外一个对我有效的方法是每次加载页面时从DevTools控制台运行[id].windowContent.onFocus()
我尝试了许多不同的方法--包括iFrame本身、其他事件和许多变种。
如果有人能展示另一种可行(简单明了)的方式,我会很高兴看到它。

无论如何,代码的其余部分形成了一个简单而完整的实现。

这是一个现代化的Guacamole包装器所需的全部内容,它可以完美地调整浏览器窗口大小,为Guac客户端获取键盘输入,如果用户触发选择,则不会执行任何奇怪的操作。此外,您可以使用右键单击而不会被浏览器劫持您的上下文菜单。


0

我正在使用Angular。

我在包含IFrame的组件的ngOnInit中调用了这个函数。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接