diff options
author | Devaev Maxim <[email protected]> | 2018-07-13 20:43:45 +0000 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2018-07-13 21:18:21 +0000 |
commit | 73ec9d853efed8b0cccf177308f825db6d202308 (patch) | |
tree | 00e8830469bb26d114977fff2509647e754b0b85 /kvmd | |
parent | e118d270dfb310498d2135f5af7c6b86bdc161c7 (diff) |
better ui
Diffstat (limited to 'kvmd')
-rw-r--r-- | kvmd/kvmd/hid.py | 8 | ||||
-rw-r--r-- | kvmd/kvmd/server.py | 5 | ||||
-rw-r--r-- | kvmd/web/css/main.css | 42 | ||||
-rw-r--r-- | kvmd/web/index.html | 28 | ||||
-rw-r--r-- | kvmd/web/js/kvmd.js | 99 |
5 files changed, 117 insertions, 65 deletions
diff --git a/kvmd/kvmd/hid.py b/kvmd/kvmd/hid.py index 33676999..0a3511b7 100644 --- a/kvmd/kvmd/hid.py +++ b/kvmd/kvmd/hid.py @@ -56,6 +56,14 @@ class Hid(multiprocessing.Process): # TODO: add reset or power switching + def get_state(self) -> Dict: + return { + "features": { + "keyboard": True, # Always + "mouse": False, # TODO + }, + } + async def send_key_event(self, key: str, state: bool) -> None: if not self.__stop_event.is_set(): async with self.__lock: diff --git a/kvmd/kvmd/server.py b/kvmd/kvmd/server.py index 7f7e3a6d..8a32c8c1 100644 --- a/kvmd/kvmd/server.py +++ b/kvmd/kvmd/server.py @@ -121,6 +121,8 @@ class Server: # pylint: disable=too-many-instance-attributes app.router.add_get("/ws", self.__ws_handler) + app.router.add_get("/hid", self.__hid_state_handler) + app.router.add_get("/atx", self.__atx_state_handler) app.router.add_post("/atx/click", self.__atx_click_handler) @@ -170,6 +172,9 @@ class Server: # pylint: disable=too-many-instance-attributes break return ws + async def __hid_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: + return _json(self.__hid.get_state()) + async def __atx_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: return _json(self.__atx.get_state()) diff --git a/kvmd/web/css/main.css b/kvmd/web/css/main.css index bd74ec10..20d7c714 100644 --- a/kvmd/web/css/main.css +++ b/kvmd/web/css/main.css @@ -1,40 +1,48 @@ -.stream-box { +div#stream-box { box-sizing: border-box; display: inline-block; background-color: #e5e5f5; padding: 10px; } -.stream-image { +img#stream-image { width: 640px; height: 480px; + display: inline-block; border: 1px solid grey; +} +img.stream-image-on { + cursor: cell; + -webkit-filter: none; + filter: none; +} +img.stream-image-off { cursor: wait; + -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */ + filter: grayscale(100%); } -.session-opened { +div.session-active { color: grey; } -.session-closed { +div.session-closed { color: #ff3d40; } -div#power-led, div#hdd-led { - border-radius: 50%; - border: 1px solid grey; - width: 16px; - height: 16px; +div#atx-power-led, div#hid-mouse-led, div#msd-led { + font-weight: bold; + font-size: 150%; } -div.power-led-on { - background: #00ce00; +div#atx-hdd-led, div#screen-led, div#hid-keyboard-led { + font-size: 150%; } -div.power-led-off { - background: #adceab; +div.led-on { + color: #00ce00; } -div.hdd-led-on { - background: #ff373a; +div.led-off { + color: grey; } -div.hdd-led-off { - background: #ffcdce; +div.led-busy { + color: #ff373a; } button#power-button, button#reset-button { diff --git a/kvmd/web/index.html b/kvmd/web/index.html index e8ca859a..3fec1ae3 100644 --- a/kvmd/web/index.html +++ b/kvmd/web/index.html @@ -7,19 +7,21 @@ </head> <script src="js/kvmd.js"></script> -<script> - window.onload = function() { - runKvmdSession(); - pollStreamer(); - } -</script> +<script>window.onload = runKvmdUi;</script> <body> - <div id="stream-box" class="stream-box"> - <img src="/streamer/?action=stream" id="stream-image" class="stream-image" alt="" /> + <div id="stream-box"> + <img src="/streamer/?action=stream" id="stream-image" class="stream-image-off" alt="Loading..."/> + <hr> <table cellpadding="0" cellspacing="0" style="border: none;"> <tr> - <td><button id="reset-streamer-button" type="button" title="Click here if your video looks like crap" onclick="clickResetStreamerButton(this);">Reset stream</button></td> + <td><div id="screen-led" class="led-off">🖵</div></td> + <td> </td> + <td><div id="hid-keyboard-led" class="led-off">⌨</div></td> + <td> </td> + <td><div id="hid-mouse-led" class="led-off">🖰</div></td> + <td> </td> + <td><button id="reset-stream-button" type="button" title="Click here if your video looks like crap" onclick="clickResetStreamButton(this);">Reset stream</button></td> <td> </td> <td><div id="session-status">Not connected yet...</div></td> </tr> @@ -28,9 +30,11 @@ <table cellpadding="0" cellspacing="5" style="border: none;"> <tr> - <td><div id="power-led" class="power-led-off"></div></td> - <td><div id="hdd-led" class="hdd-led-off"></div></td> - <td> </td> + <td><div id="atx-power-led" class="led-off">⏻</div></td> + <td><div id="atx-hdd-led" class="led-off">🖴</div></td> + <td> </td> + <!--<td><div id="msd-led" class="led-off">✇</div></td> + <td> </td>--> <td><button id="atx-power-button" type="button" title="Click hardware power button" onclick="clickAtxButton(this);">Power</button></td> <td><button id="atx-power-button-long" type="button" title="Click hardware power button (long press)" onclick="clickAtxButton(this);">Power (long)</button></td> <td><button id="atx-reset-button" type="button" title="Click to force reset" onclick="clickAtxButton(this);">Reset</button></td> diff --git a/kvmd/web/js/kvmd.js b/kvmd/web/js/kvmd.js index a4d75387..6f254a29 100644 --- a/kvmd/web/js/kvmd.js +++ b/kvmd/web/js/kvmd.js @@ -1,9 +1,16 @@ -function runKvmdSession() { +function runKvmdUi() { + __startSessionPoller(); + __startStreamPoller(); +} + + +// ----------------------------------------------------------------------------- +function __startSessionPoller() { var ws = new WebSocket("ws://" + location.host + "/kvmd/ws"); ws.onopen = function(event) { __installHidHandlers(ws); - __setSessionStatus("session-opened", "Session opened (keyboard captured)"); + __setSessionStatus(true); }; ws.onmessage = function(event) { @@ -12,18 +19,18 @@ function runKvmdSession() { if (event.msg_type == "event") { if (event.msg.event == "atx_state") { leds = event.msg.event_attrs.leds; - document.getElementById("power-led").className = "power-led-" + (leds.power ? "on" : "off"); - document.getElementById("hdd-led").className = "hdd-led-" + (leds.hdd ? "on" : "off"); + document.getElementById("atx-power-led").className = (leds.power ? "led-on" : "led-off"); + document.getElementById("atx-hdd-led").className = (leds.hdd ? "led-busy" : "led-off"); } } }; ws.onclose = function(event) { __clearHidHandlers(); - __setSessionStatus("session-closed", "Session closed (keyboard free), trying to reconnect..."); - document.getElementById("power-led").className = "power-led-off"; - document.getElementById("hdd-led").className = "hdd-led-off"; - setTimeout(runKvmdSession, 5000); + __setSessionStatus(false); + document.getElementById("atx-power-led").className = "led-off"; + document.getElementById("atx-hdd-led").className = "led-off"; + setTimeout(__startSessionPoller, 2000); }; ws.onerror = function(error) { @@ -31,29 +38,47 @@ function runKvmdSession() { }; } -function __setSessionStatus(cls, msg) { +function __setSessionStatus(status) { var el_session_status = document.getElementById("session-status"); - el_session_status.innerHTML = msg; - el_session_status.className = cls; + el_session_status.innerHTML = (status ? "Session active" : "Session closed, trying to reconnect..."); + el_session_status.className = (status ? "session-active" : "session-closed"); } function __installHidHandlers(ws) { - // https://www.codeday.top/2017/05/03/24906.html - document.onkeydown = (event) => __onKeyEvent(ws, event, true); - document.onkeyup = (event) => __onKeyEvent(ws, event, false); + var http = __request("GET", "/kvmd/hid", function() { + if (http.readyState == 4) { + if (http.status == 200) { + features = JSON.parse(http.responseText).result.features; + if (features.keyboard) { + // https://www.codeday.top/2017/05/03/24906.html + document.onkeydown = (event) => __onKeyEvent(ws, event, true); + document.onkeyup = (event) => __onKeyEvent(ws, event, false); + document.getElementById("hid-keyboard-led").className = "led-on"; + } + if (features.mouse) { + el_stream_image = document.getElementById("stream-image"); + el_stream_image.onmousedown = (event) => __onMouseButton(ws, event, true); + el_stream_image.onmouseup = (event) => __onMouseButton(ws, event, false); + el_stream_image.oncontextmenu = (event) => event.preventDefault(); + el_stream_image.onmousemove = __onMouseMove; + el_stream_image.onwheel = (event) => __onMouseWheel(ws, event); + document.getElementById("hid-mouse-led").className = "led-on"; - el_stream_image = document.getElementById("stream-image"); - el_stream_image.onmousedown = (event) => __onMouseButton(ws, event, true); - el_stream_image.onmouseup = (event) => __onMouseButton(ws, event, false); - el_stream_image.oncontextmenu = (event) => event.preventDefault(); - el_stream_image.onmousemove = __onMouseMove; - el_stream_image.onwheel = (event) => __onMouseWheel(ws, event); - runKvmdSession.mouse_move_timer = setInterval(() => __handleMouseMove(ws), 100); + __installHidHandlers.mouse_move_timer = setInterval(() => __handleMouseMove(ws), 100); + } + } else { + alert("Can't fetch HID features:", http.responseText); + } + } + }); } function __clearHidHandlers() { + clearInterval(__installHidHandlers.mouse_move_timer); + document.onkeydown = null; document.onkeyup = null; + document.getElementById("hid-keyboard-led").className = "led-off"; el_stream_image = document.getElementById("stream-image"); el_stream_image.onmousedown = null; @@ -61,7 +86,7 @@ function __clearHidHandlers() { el_stream_image.oncontextmenu = null; el_stream_image.onmousemove = null; el_stream_image.onwheel = null; - clearInterval(runKvmdSession.mouse_move_timer); + document.getElementById("hid-mouse-led").className = "led-off"; } function __onKeyEvent(ws, event, state) { @@ -159,7 +184,7 @@ function clickAtxButton(el_button) { if (http.status == 409) { alert("Performing another ATX operation for other client, please try again later"); } else if (http.status != 200) { - alert("Click error: " + http.responseText); + alert("Click error:", http.responseText); } __setAtxButtonsBusy(false); } @@ -179,28 +204,30 @@ function __setAtxButtonsBusy(busy) { // ----------------------------------------------------------------------------- -function pollStreamer() { +function __startStreamPoller() { var http = __request("GET", "/streamer/?action=snapshot", function() { if (http.readyState == 2 || http.readyState == 4) { var status = http.status; http.onreadystatechange = null; http.abort(); if (status != 200) { - console.log("Refreshing streamer ..."); - pollStreamer.last = false; - document.getElementById("stream-image").style.cursor = "wait"; - } else if (!pollStreamer.last) { - __refreshStreamer(); - document.getElementById("stream-image").style.cursor = "cell"; - pollStreamer.last = true; + console.log("Refreshing stream ..."); + __startStreamPoller.last = false; + document.getElementById("stream-image").className = "stream-image-off"; + document.getElementById("screen-led").className = "led-off"; + } else if (!__startStreamPoller.last) { + __refreshStream(); + __startStreamPoller.last = true; + document.getElementById("stream-image").className = "stream-image-on"; + document.getElementById("screen-led").className = "led-on"; } } }); - setTimeout(pollStreamer, 2000); + setTimeout(__startStreamPoller, 2000); } -pollStreamer.last = false; +__startStreamPoller.last = false; -function __refreshStreamer() { +function __refreshStream() { var http = __request("GET", "/kvmd/streamer", function() { if (http.readyState == 4 && http.status == 200) { size = JSON.parse(http.responseText).result.size; @@ -212,12 +239,12 @@ function __refreshStreamer() { }); } -function clickResetStreamerButton(el_button) { +function clickResetStreamButton(el_button) { __setButtonBusy(el_button, true); var http = __request("POST", "/kvmd/streamer/reset", function() { if (http.readyState == 4) { if (http.status != 200) { - alert("Can't reset streamer: " + http.responseText); + alert("Can't reset stream:", http.responseText); } __setButtonBusy(el_button, false); } |