web: better handling of windows with iframes

This commit is contained in:
Maxim Devaev 2025-05-12 03:57:07 +03:00
parent cfdf225d10
commit eb0fb04b72
3 changed files with 41 additions and 10 deletions

View File

@ -2961,7 +2961,7 @@
<p class="text credits"><a target="_blank" href="https://pikvm.org">PiKVM Project</a>&nbsp; | &nbsp;<a target="_blank" href="https://docs.pikvm.org">Documentation</a>&nbsp; | &nbsp;<a target="_blank" href="https://pikvm.org/support">Support</a></p> <p class="text credits"><a target="_blank" href="https://pikvm.org">PiKVM Project</a>&nbsp; | &nbsp;<a target="_blank" href="https://docs.pikvm.org">Documentation</a>&nbsp; | &nbsp;<a target="_blank" href="https://pikvm.org/support">Support</a></p>
</div> </div>
</div> </div>
<div class="window window-resizable" id="webterm-window" style="width: 640px; height: 480px"> <div class="window window-resizable" id="webterm-window" style="width: 720px; height: 480px">
<div class="window-header"> <div class="window-header">
<div class="window-grab">Terminal</div> <div class="window-grab">Terminal</div>
<button class="window-button-close"><b>&times;</b></button> <button class="window-button-close"><b>&times;</b></button>

View File

@ -1,4 +1,4 @@
.window.window-resizable#webterm-window(style="width: 640px; height: 480px") .window.window-resizable#webterm-window(style="width: 720px; height: 480px")
.window-header .window-header
.window-grab Terminal .window-grab Terminal
button.window-button-close #[b &times;] button.window-button-close #[b &times;]

View File

@ -145,8 +145,38 @@ function __WindowManager() {
window.addEventListener("mouseup", __globalMouseButtonHandler); window.addEventListener("mouseup", __globalMouseButtonHandler);
window.addEventListener("touchend", __globalMouseButtonHandler); window.addEventListener("touchend", __globalMouseButtonHandler);
window.addEventListener("focusin", (event) => __focusInOut(event, true)); window.addEventListener("focusin", (event) => __focusInOut(event.target, true));
window.addEventListener("focusout", (event) => __focusInOut(event, false)); window.addEventListener("focusout", (event) => __focusInOut(event.target, false));
// Окна с iframe нуждаются в особенной логике для подсветки,
// потому что из iframe не приходят события фокуса.
// Мы можешь лишь следить за focus/blur на окне и проверять
// активный элемент, и если это iframe - назодить его окно,
// и подсвечивать его. Или наоборот, тушить все окна,
// в которых есть другие iframe.
window.addEventListener("focus", function() {
let el_active = document.activeElement;
for (let el of document.getElementsByTagName("iframe")) {
if (el !== el_active) {
__focusInOut(el, false);
}
}
});
window.addEventListener("blur", function() {
// При переходе в iframe, в хромиуме прилетает два блура:
// с первым активный элемент становится body, со вторым - iframe.
// В фоксе оба раза это будет body, но если проверить чуть позже -
// то станет iframe. Таймаут решает проблему.
setTimeout(function() {
let el = document.activeElement;
if (el && el.tagName.toLowerCase() === "iframe") {
let el_parent = __focusInOut(el, true);
if (el_parent !== null) {
__activateWindow(el_parent);
}
}
}, 100);
});
window.addEventListener("resize", __organizeWindowsOnBrowserResize); window.addEventListener("resize", __organizeWindowsOnBrowserResize);
window.addEventListener("orientationchange", __organizeWindowsOnBrowserResize); window.addEventListener("orientationchange", __organizeWindowsOnBrowserResize);
@ -421,16 +451,17 @@ function __WindowManager() {
} }
}; };
var __focusInOut = function(event, focus_in) { var __focusInOut = function(el, focus_in) {
let el_parent; let el_parent = null;
if ((el_parent = event.target.closest(".modal-window")) !== null) { if ((el_parent = el.closest(".modal-window")) !== null) {
el_parent.classList.toggle("window-active", focus_in); el_parent.classList.toggle("window-active", focus_in);
} else if ((el_parent = event.target.closest(".window")) !== null) { } else if ((el_parent = el.closest(".window")) !== null) {
el_parent.classList.toggle("window-active", focus_in); el_parent.classList.toggle("window-active", focus_in);
} else if ((el_parent = event.target.closest(".menu")) !== null) { } else if ((el_parent = el.closest(".menu")) !== null) {
el_parent.classList.toggle("menu-active", focus_in); el_parent.classList.toggle("menu-active", focus_in);
} }
tools.debug(`UI: Focus ${focus_in ? "IN" : "OUT"}:`, el_parent); tools.info(`UI: Focus ${focus_in ? "IN" : "OUT"}:`, el_parent);
return el_parent;
}; };
var __globalMouseButtonHandler = function(event) { var __globalMouseButtonHandler = function(event) {