Невозможно получить события клавиатуры в гуакамоле ифраме
Мы транслируем наш vnc-сервер с помощью гуакамоле ( http://guac-dev.org/) в браузере, используя iframe. Мы не можем получить события клавиатуры на холсте vnc. Хотя, как только мы нажимаем на div вне холста гуакамоле, фокус попадает в необходимую часть, и ключевые события фиксируются правильно.
Мы развернули приложение на http://test-mate.com:8081/
Ниже приведен код рендеринга гуакамоле.
<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>
4 ответа
Эта проблема решена путем вызова следующей функции.
function setFocusThickboxIframe() {
var iframe = $("#TB_iframeContent")[0];
iframe.contentWindow.focus();
}
каждый раз, когда пользователь нажимает на iframe. И window.focus(), когда он нажимает на главное окно, чтобы сфокусироваться на нем.
Мы используем установку iframe из модуля-оболочки JOOMLA.
Исправление для текстового фокуса должно было иметь модуль обертки:
Определите дополнительную функцию JavaScript setFocus()
Включить 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>
Я использовал угловой.
Я вызвал эту функцию в ngOnInit компонента, содержащего IFrame.
private setFocusIframe() {
const frame = document.querySelector<HTMLIFrameElement>("#myframe")
window.addEventListener("keydown", function(event: KeyboardEvent){
frame.contentWindow.focus();
})
}
ТЛ;ДР
<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. Хитрость заключается в использовании события нажатия клавиши на элементе тела , отключающем [yourFrameID] .contentWindow.focus() , чтобы вернуть фокус на страницу Guac внутри iFrame.
Единственный другой способ, которым это сработало для меня, — запускать [id] .windowContent.onFocus() из консоли DevTools каждый раз, когда я загружал страницу.
Я пробовал разные способы: сам iFrame, другие события, множество вариантов.
Если кто-то может показать другой (простой и понятный) работающий способ, буду рад его увидеть.
В любом случае остальная часть кода образует простую, но полную реализацию.
- все, что вам нужно для современной оболочки для гуакамоле, которая будет идеально соответствовать размеру окна браузера, передавать ввод с клавиатуры клиенту Guac и не делать ничего странного, если пользователь каким-то образом инициирует выбор. И вы можете использовать щелчок правой кнопкой мыши, чтобы браузер не перехватил ваше контекстное меню.