mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 09:01:54 +08:00
focus-based window manager
This commit is contained in:
@@ -71,10 +71,11 @@ ul#menu li a.menu-item-selected {
|
||||
|
||||
ul#menu li div.menu-item-content {
|
||||
visibility: hidden;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
border: var(--border-intensive-2px);
|
||||
border-top: var(--border-control-thin);
|
||||
border: var(--border-menu-item-content-default-2px);
|
||||
border-top: var(--border-menu-item-content-top-thin);
|
||||
border-radius: 0 0 8px 8px;
|
||||
position: absolute;
|
||||
background-color: var(--cs-menu-default-bg);
|
||||
@@ -82,6 +83,10 @@ ul#menu li div.menu-item-content {
|
||||
box-shadow: var(--shadow-big);
|
||||
z-index: 2147483645;
|
||||
}
|
||||
ul#menu li div.menu-item-content-active {
|
||||
border: var(--border-menu-item-content-active-2px) !important;
|
||||
border-top: var(--border-menu-item-content-top-thin) !important;
|
||||
}
|
||||
|
||||
ul#menu li div.menu-item-content-buttons {
|
||||
background-color: var(--cs-control-default-bg);
|
||||
|
||||
@@ -56,4 +56,8 @@
|
||||
--border-key-thin: thin solid #202225;
|
||||
--border-intensive-2px: 2px solid #5b90bb;
|
||||
--border-intensive-thin: thin solid #5b90bb;
|
||||
|
||||
--border-menu-item-content-default-2px: 2px solid black;
|
||||
--border-menu-item-content-active-2px: 2px solid #5b90bb;
|
||||
--border-menu-item-content-top-thin: thin solid #17191d;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ function Atx() {
|
||||
$("atx-power-led").className = (state.leds.power ? "led-green" : "led-gray");
|
||||
$("atx-hdd-led").className = (state.leds.hdd ? "led-red" : "led-gray");
|
||||
|
||||
$("atx-power-button").disabled = state.busy;
|
||||
$("atx-power-button-long").disabled = state.busy;
|
||||
$("atx-reset-button").disabled = state.busy;
|
||||
ui.switchDisabled($("atx-power-button"), state.busy);
|
||||
ui.switchDisabled($("atx-power-button-long"), state.busy);
|
||||
ui.switchDisabled($("atx-reset-button"), state.busy);
|
||||
};
|
||||
|
||||
self.clearState = function() {
|
||||
|
||||
@@ -54,9 +54,9 @@ function Hid() {
|
||||
/********************************************************************************/
|
||||
|
||||
self.setSocket = function(ws) {
|
||||
$("hid-pak-text").disabled = !ws;
|
||||
$("hid-pak-button").disabled = !ws;
|
||||
$("hid-reset-button").disabled = !ws;
|
||||
ui.switchDisabled($("hid-pak-text"), !ws);
|
||||
ui.switchDisabled($("hid-pak-button"), !ws);
|
||||
ui.switchDisabled($("hid-reset-button"), !ws);
|
||||
__ws = ws;
|
||||
__keyboard.setSocket(ws);
|
||||
__mouse.setSocket(ws);
|
||||
@@ -154,8 +154,8 @@ function Hid() {
|
||||
|
||||
ui.confirm(confirm_msg).then(function(ok) {
|
||||
if (ok) {
|
||||
$("hid-pak-text").disabled = true;
|
||||
$("hid-pak-button").disabled = true;
|
||||
ui.switchDisabled($("hid-pak-text"), true);
|
||||
ui.switchDisabled($("hid-pak-button"), true);
|
||||
$("hid-pak-led").className = "led-yellow-rotating-fast";
|
||||
$("hid-pak-led").title = "Autotyping...";
|
||||
|
||||
@@ -169,8 +169,8 @@ function Hid() {
|
||||
iterate();
|
||||
} else {
|
||||
$("hid-pak-text").value = "";
|
||||
$("hid-pak-text").disabled = false;
|
||||
$("hid-pak-button").disabled = false;
|
||||
ui.switchDisabled($("hid-pak-text"), false);
|
||||
ui.switchDisabled($("hid-pak-button"), false);
|
||||
$("hid-pak-led").className = "led-gray";
|
||||
$("hid-pak-led").title = "";
|
||||
}
|
||||
|
||||
@@ -21,9 +21,8 @@ function Keyboard() {
|
||||
$("stream-window").onfocus = __updateLeds;
|
||||
$("stream-window").onblur = __updateLeds;
|
||||
|
||||
window.addEventListener("focus", __updateLeds);
|
||||
window.addEventListener("pagehide", __updateLeds);
|
||||
window.addEventListener("blur", __updateLeds);
|
||||
window.addEventListener("focusin", __updateLeds);
|
||||
window.addEventListener("focusout", __updateLeds);
|
||||
|
||||
Array.prototype.forEach.call($$("key"), function(el_key) {
|
||||
tools.setOnDown(el_key, () => __clickHandler(el_key, true));
|
||||
@@ -67,14 +66,9 @@ function Keyboard() {
|
||||
};
|
||||
|
||||
var __updateLeds = function() {
|
||||
tools.info("Update leds");
|
||||
tools.debug("Keyboard: update leds");
|
||||
if (
|
||||
__ws
|
||||
&& (
|
||||
document.activeElement === $("stream-window")
|
||||
|| document.activeElement === $("keyboard-window")
|
||||
)
|
||||
&& (
|
||||
__ws && (
|
||||
$("stream-window").classList.contains("window-active")
|
||||
|| $("keyboard-window").classList.contains("window-active")
|
||||
)
|
||||
|
||||
@@ -61,7 +61,7 @@ function Msd() {
|
||||
__applyState();
|
||||
});
|
||||
__applyState();
|
||||
$(`msd-switch-to-${to}-button`).disabled = true;
|
||||
ui.switchDisabled($(`msd-switch-to-${to}-button`), true);
|
||||
};
|
||||
|
||||
var __selectNewImageFile = function() {
|
||||
@@ -120,12 +120,12 @@ function Msd() {
|
||||
$("msd-current-image-size").innerHTML = (__state.in_operate && __state.info.image ? __formatSize(__state.info.image.size) : "None");
|
||||
$("msd-storage-size").innerHTML = (__state.in_operate ? __formatSize(__state.info.size) : "Unavailable");
|
||||
|
||||
$("msd-switch-to-kvm-button").disabled = (!__state.in_operate || __state.connected_to === "kvm" || __state.busy);
|
||||
$("msd-switch-to-server-button").disabled = (!__state.in_operate || __state.connected_to === "server" || __state.busy);
|
||||
$("msd-select-new-image-button").disabled = (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || __upload_http);
|
||||
$("msd-upload-new-image-button").disabled = (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || !__image_file);
|
||||
$("msd-abort-uploading-button").disabled = (!__state.in_operate || !__upload_http);
|
||||
$("msd-reset-button").disabled = (!__state.in_operate || __upload_http);
|
||||
ui.switchDisabled($("msd-switch-to-kvm-button"), (!__state.in_operate || __state.connected_to === "kvm" || __state.busy));
|
||||
ui.switchDisabled($("msd-switch-to-server-button"), (!__state.in_operate || __state.connected_to === "server" || __state.busy));
|
||||
ui.switchDisabled($("msd-select-new-image-button"), (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || __upload_http));
|
||||
ui.switchDisabled($("msd-upload-new-image-button"), (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || !__image_file));
|
||||
ui.switchDisabled($("msd-abort-uploading-button"), (!__state.in_operate || !__upload_http));
|
||||
ui.switchDisabled($("msd-reset-button"), (!__state.in_operate || __upload_http));
|
||||
|
||||
$("msd-new-image").style.display = (__image_file ? "block" : "none");
|
||||
$("msd-progress").setAttribute("data-label", "Waiting for upload ...");
|
||||
|
||||
@@ -49,7 +49,7 @@ function Streamer() {
|
||||
}
|
||||
|
||||
if (!$("stream-quality-slider").activated) {
|
||||
$("stream-quality-slider").disabled = false;
|
||||
ui.switchDisabled($("stream-quality-slider"), false);
|
||||
if ($("stream-quality-slider").value !== source.quality) {
|
||||
$("stream-quality-slider").value = source.quality;
|
||||
__updateQualityValue(source.quality);
|
||||
@@ -57,7 +57,7 @@ function Streamer() {
|
||||
}
|
||||
|
||||
if (!$("stream-desired-fps-slider").activated) {
|
||||
$("stream-desired-fps-slider").disabled = false;
|
||||
ui.switchDisabled($("stream-desired-fps-slider"), false);
|
||||
if ($("stream-desired-fps-slider").value !== source.desired_fps) {
|
||||
$("stream-desired-fps-slider").value = source.desired_fps;
|
||||
__updateDesiredFpsValue(source.desired_fps);
|
||||
@@ -101,8 +101,8 @@ function Streamer() {
|
||||
$("stream-box").classList.remove("stream-box-inactive");
|
||||
$("stream-led").className = "led-green";
|
||||
$("stream-led").title = "Stream is active";
|
||||
$("stream-screenshot-button").disabled = false;
|
||||
$("stream-reset-button").disabled = false;
|
||||
ui.switchDisabled($("stream-screenshot-button"), false);
|
||||
ui.switchDisabled($("stream-reset-button"), false);
|
||||
tools.info("Stream: acquired");
|
||||
__prev = true;
|
||||
}
|
||||
@@ -121,10 +121,10 @@ function Streamer() {
|
||||
$("stream-box").classList.add("stream-box-inactive");
|
||||
$("stream-led").className = "led-gray";
|
||||
$("stream-led").title = "Stream inactive";
|
||||
$("stream-screenshot-button").disabled = true;
|
||||
$("stream-reset-button").disabled = true;
|
||||
$("stream-quality-slider").disabled = true;
|
||||
$("stream-desired-fps-slider").disabled = true;
|
||||
ui.switchDisabled($("stream-screenshot-button"), true);
|
||||
ui.switchDisabled($("stream-reset-button"), true);
|
||||
ui.switchDisabled($("stream-quality-slider"), true);
|
||||
ui.switchDisabled($("stream-desired-fps-slider"), true);
|
||||
|
||||
__client_key = tools.makeId();
|
||||
__client_id = "";
|
||||
|
||||
166
web/js/ui.js
166
web/js/ui.js
@@ -15,11 +15,13 @@ function Ui() {
|
||||
});
|
||||
|
||||
Array.prototype.forEach.call($$("menu-item"), function(el_item) {
|
||||
el_item.parentElement.querySelector(".menu-item-content").setAttribute("tabindex", "-1");
|
||||
tools.setOnClick(el_item, () => __toggleMenu(el_item));
|
||||
__menu_items.push(el_item);
|
||||
});
|
||||
|
||||
Array.prototype.forEach.call($$("window"), function(el_window) {
|
||||
el_window.setAttribute("tabindex", "-1");
|
||||
__makeWindowMovable(el_window);
|
||||
__windows.push(el_window);
|
||||
|
||||
@@ -39,11 +41,9 @@ function Ui() {
|
||||
window.onmouseup = __globalMouseButtonHandler;
|
||||
window.ontouchend = __globalMouseButtonHandler;
|
||||
|
||||
window.addEventListener("focus", () => __activateLastWindow());
|
||||
window.addEventListener("pagehide", () => __deactivateAllWindows());
|
||||
window.addEventListener("pagehide", __closeAllMenues);
|
||||
window.addEventListener("blur", () => __deactivateAllWindows());
|
||||
window.addEventListener("blur", __closeAllMenues);
|
||||
window.addEventListener("focusin", __focusIn);
|
||||
window.addEventListener("focusout", __focusOut);
|
||||
|
||||
window.addEventListener("resize", () => __organizeWindowsOnResize(false));
|
||||
window.addEventListener("orientationchange", () => __organizeWindowsOnResize(true));
|
||||
};
|
||||
@@ -126,6 +126,20 @@ function Ui() {
|
||||
return promise;
|
||||
};
|
||||
|
||||
self.switchDisabled = function(el, disabled) {
|
||||
if (disabled && document.activeElement === el) {
|
||||
var el_to_focus = (
|
||||
el.closest(".modal-window")
|
||||
|| el.closest(".window")
|
||||
|| el.closest(".menu-item-content")
|
||||
);
|
||||
if (el_to_focus) {
|
||||
el_to_focus.focus();
|
||||
}
|
||||
}
|
||||
el.disabled = disabled;
|
||||
};
|
||||
|
||||
self.showWindow = function(el_window, activate=true, center=false) {
|
||||
if (!__isWindowOnPage(el_window) || el_window.hasAttribute("data-centered") || center) {
|
||||
var view = self.getViewGeometry();
|
||||
@@ -169,10 +183,9 @@ function Ui() {
|
||||
__menu_items.forEach(function(el_item) {
|
||||
var el_menu = el_item.parentElement.querySelector(".menu-item-content");
|
||||
if (el_item === el_a && window.getComputedStyle(el_menu, null).visibility === "hidden") {
|
||||
__deactivateAllWindows();
|
||||
el_item.focus();
|
||||
el_item.classList.add("menu-item-selected");
|
||||
el_menu.style.visibility = "visible";
|
||||
el_menu.focus();
|
||||
all_hidden &= false;
|
||||
} else {
|
||||
el_item.classList.remove("menu-item-selected");
|
||||
@@ -203,6 +216,30 @@ function Ui() {
|
||||
});
|
||||
};
|
||||
|
||||
var __focusIn = function(event) {
|
||||
var el_parent;
|
||||
if ((el_parent = event.target.closest(".modal-window")) !== null) {
|
||||
el_parent.classList.add("window-active");
|
||||
} else if ((el_parent = event.target.closest(".window")) !== null) {
|
||||
el_parent.classList.add("window-active");
|
||||
} else if ((el_parent = event.target.closest(".menu-item-content")) !== null) {
|
||||
el_parent.classList.add("menu-item-content-active");
|
||||
}
|
||||
tools.debug("Focus in:", el_parent);
|
||||
};
|
||||
|
||||
var __focusOut = function(event) {
|
||||
var el_parent;
|
||||
if ((el_parent = event.target.closest(".modal-window")) !== null) {
|
||||
el_parent.classList.remove("window-active");
|
||||
} else if ((el_parent = event.target.closest(".window")) !== null) {
|
||||
el_parent.classList.remove("window-active");
|
||||
} else if ((el_parent = event.target.closest(".menu-item-content")) !== null) {
|
||||
el_parent.classList.remove("menu-item-content-active");
|
||||
}
|
||||
tools.debug("Focus out:", el_parent);
|
||||
};
|
||||
|
||||
var __globalMouseButtonHandler = function(event) {
|
||||
if (!event.target.matches(".menu-item")) {
|
||||
for (var el_item = event.target; el_item && el_item !== document; el_item = el_item.parentNode) {
|
||||
@@ -231,6 +268,59 @@ function Ui() {
|
||||
});
|
||||
};
|
||||
|
||||
var __activateLastWindow = function(el_except_window=null) {
|
||||
var el_last_window = null;
|
||||
|
||||
if (document.activeElement) {
|
||||
el_last_window = (document.activeElement.closest(".modal-window") || document.activeElement.closest(".window"));
|
||||
}
|
||||
|
||||
if (!el_last_window || el_last_window === el_except_window) {
|
||||
var max_z_index = 0;
|
||||
|
||||
__windows.forEach(function(el_window) {
|
||||
var z_index = parseInt(window.getComputedStyle(el_window, null).zIndex) || 0;
|
||||
var visibility = window.getComputedStyle(el_window, null).visibility;
|
||||
|
||||
if (max_z_index < z_index && visibility !== "hidden" && el_window !== el_except_window) {
|
||||
el_last_window = el_window;
|
||||
max_z_index = z_index;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (el_last_window) {
|
||||
tools.debug("Activating last window:", el_last_window);
|
||||
__activateWindow(el_last_window);
|
||||
}
|
||||
};
|
||||
|
||||
var __activateWindow = function(el_window) {
|
||||
if (window.getComputedStyle(el_window, null).visibility !== "hidden") {
|
||||
var el_to_focus;
|
||||
var el_window_contains_focus;
|
||||
|
||||
if (el_window.className === "modal") {
|
||||
el_to_focus = el_window.querySelector(".modal-window");
|
||||
el_window_contains_focus = (document.activeElement && document.activeElement.closest(".modal-window"));
|
||||
} else { // .window
|
||||
el_to_focus = el_window;
|
||||
el_window_contains_focus = (document.activeElement && document.activeElement.closest(".window"));
|
||||
}
|
||||
|
||||
if (el_window.className !== "modal" && parseInt(el_window.style.zIndex) !== __top_z_index) {
|
||||
__top_z_index += 1;
|
||||
el_window.style.zIndex = __top_z_index;
|
||||
tools.debug("UI: activated window:", el_window);
|
||||
}
|
||||
|
||||
if (el_window !== el_window_contains_focus) {
|
||||
el_to_focus.focus();
|
||||
tools.debug("UI: focused window:", el_window);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var __makeWindowMovable = function(el_window) {
|
||||
var el_header = el_window.querySelector(".window-header");
|
||||
var el_grab = el_window.querySelector(".window-header .window-grab");
|
||||
@@ -297,67 +387,5 @@ function Ui() {
|
||||
el_grab.ontouchstart = startMoving;
|
||||
};
|
||||
|
||||
var __activateLastWindow = function(el_except=null) {
|
||||
var el_last_window = null;
|
||||
|
||||
if (document.activeElement) {
|
||||
el_last_window = (document.activeElement.closest(".modal-window") || document.activeElement.closest(".window"));
|
||||
}
|
||||
|
||||
if (!el_last_window || el_last_window === el_except) {
|
||||
var max_z_index = 0;
|
||||
__windows.forEach(function(el_window) {
|
||||
var z_index = parseInt(window.getComputedStyle(el_window, null).zIndex) || 0;
|
||||
var visibility = window.getComputedStyle(el_window, null).visibility;
|
||||
if (max_z_index < z_index && visibility !== "hidden" && el_window !== el_except) {
|
||||
el_last_window = el_window;
|
||||
max_z_index = z_index;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (el_last_window) {
|
||||
tools.info("Activating last window:", el_last_window);
|
||||
__activateWindow(el_last_window);
|
||||
}
|
||||
};
|
||||
|
||||
var __activateWindow = function(el_window) {
|
||||
if (window.getComputedStyle(el_window, null).visibility !== "hidden") {
|
||||
var el_to_focus;
|
||||
var el_window_contains_focus;
|
||||
|
||||
if (el_window.className === "modal") {
|
||||
el_to_focus = el_window.querySelector(".modal-window");
|
||||
el_window_contains_focus = (document.activeElement && document.activeElement.closest(".modal-window"));
|
||||
} else { // .window
|
||||
el_to_focus = el_window;
|
||||
el_window_contains_focus = (document.activeElement && document.activeElement.closest(".window"));
|
||||
}
|
||||
|
||||
__deactivateAllWindows(el_to_focus);
|
||||
el_to_focus.classList.add("window-active");
|
||||
|
||||
if (el_window.className !== "modal" && parseInt(el_window.style.zIndex) !== __top_z_index) {
|
||||
__top_z_index += 1;
|
||||
el_window.style.zIndex = __top_z_index;
|
||||
tools.debug("UI: activated window:", el_window);
|
||||
}
|
||||
|
||||
if (el_window !== el_window_contains_focus) {
|
||||
el_to_focus.focus();
|
||||
tools.debug("UI: focused window:", el_window);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var __deactivateAllWindows = function(el_except=null) {
|
||||
__windows.forEach(function(el_window) {
|
||||
if (el_window !== el_except) {
|
||||
el_window.classList.remove("window-active");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
__init__();
|
||||
}
|
||||
|
||||
@@ -276,8 +276,10 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="stream-window" class="window" style="z-index: 1" tabindex="0">
|
||||
<div id="stream-window-header" class="window-header"><div class="window-grab">Stream</div></div>
|
||||
<div id="stream-window" class="window" style="z-index: 1">
|
||||
<div id="stream-window-header" class="window-header">
|
||||
<div class="window-grab">Stream</div>
|
||||
</div>
|
||||
<div id="stream-info"></div>
|
||||
<div id="stream-box" class="stream-box-inactive">
|
||||
<img id="stream-image" class="stream-image-inactive" src="../png/blank-stream.png" />
|
||||
@@ -288,7 +290,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="keyboard-window" class="window" tabindex="0">
|
||||
<div id="keyboard-window" class="window">
|
||||
<div id="keyboard-window-header" class="window-header">
|
||||
<div class="window-grab">Virtual Keyboard</div>
|
||||
<button class="window-button-close">×</button>
|
||||
@@ -523,7 +525,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="about-window" class="window" tabindex="0">
|
||||
<div id="about-window" class="window">
|
||||
<div class="window-header">
|
||||
<div class="window-grab">About</div>
|
||||
<button class="window-button-close">×</button>
|
||||
|
||||
Reference in New Issue
Block a user