From 9f170ee2c1c78b657b1c71a1e4b2db3ed7afd56e Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 8 Feb 2018 11:22:26 +0100 Subject: [PATCH] Refactoring: move events handlers to specifics functions, add an output interface to write texts on the server side --- client/assets/js/main.js | 362 +++++++++++++++++++++------------------ client/index.html | 2 +- server/server | 38 +++- server/src/Server.php | 16 +- 4 files changed, 245 insertions(+), 173 deletions(-) diff --git a/client/assets/js/main.js b/client/assets/js/main.js index 1455f0f..a7e3307 100644 --- a/client/assets/js/main.js +++ b/client/assets/js/main.js @@ -1,14 +1,175 @@ -$(function() { - var ws = new WebSocket('ws://' + window.location.hostname + ':14598'); - var $pointer = $('#pointer'); - var $scroller = $('#scrollbar'); - var mouseInitPosX = null; - var mouseInitPosY = null; - var mousePosX = null; - var mousePosY = null; - var scrollLastTimestamp = null; - var scrollLastValue = null; +var ws; +var $pointer, $scroller; +var scrollLastTimestamp, scrollLastValue; +var mousePosX, mousePosY, mouseInitPosX, mouseInitPosY; +var createWebSocketConnection = function() { + ws = new WebSocket('ws://' + window.location.hostname + ':14598'); + + ws.onopen = function(event) { + $('#disconneced').fadeOut(); + } + + ws.onclose = function(event) { + $('#disconneced').fadeIn(); + + window.setTimeout(createWebSocketConnection, 5000); + } + + ws.onmessage = function(event) {} +} + +var navigationClickHandler = function(e) { + $('.pane').hide(); + + var target = $(this).attr('href'); + $(target).show(); + + $('#nav a').removeClass('active'); + $(this).addClass('active'); +} + +var buttonClickHandler = function(e) { + var msg = $(this).attr('data-msg'); + ws.send(msg); +} + +var shortcutClearClickHandler = function(e) { + $('#shortcut-key').val(''); + $('#shortcuts_special_keys input:checked').each(function() { + $(this).prop('checked', false).trigger('change'); + }); +} + +var shortcutSendClickHandler = function(e) { + var keys = []; + + $('#shortcuts_special_keys input:checked').each(function() { + keys.push($(this).val()); + }); + + var key = $('#shortcut-key').val(); + + if (keys.length) { + if (key) { + keys.push(key); + } + + var msg = '{"type":"keys","value": "' + (keys.join(',').replace('"', '\\"')) + '"}'; + ws.send(msg); + } +} + +var textClearClickHandler = function(e) { + $('#text').val(''); +} + +var textSendClickHandler = function(e) { + var keys = $('#text').val(); + + if (keys.length) { + var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}'; + ws.send(msg); + } +} + +var textKeyUpHandler = function(e) { + var keys = $('#text').val(); + + if (e.keyCode === 13) { + var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}'; + ws.send(msg); + } +} + +var liveTextKeyUpHandler = function(e) { + var value = $(this).val(); + var live = false; + + if (e.keyCode === 8) { + var msg = '{"type":"key","value": "backspace"}'; + ws.send(msg); + } else if (e.keyCode === 13) { + var msg = '{"type":"key","value": "enter"}'; + ws.send(msg); + } else if (value.length) { + if (value === ' ') { + var msg = '{"type":"key","value": "space"}'; + ws.send(msg); + } else { + var msg = '{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}'; + ws.send(msg); + } + + $(this).val(''); + } +} + +var shortcutsSpecialKeysOnChangeHandler = function(e) { + $('#shortcuts_special_keys input:checked').each(function() { + $(this).parent().addClass('btn-primary').removeClass('btn-secondary'); + }) + + $('#shortcuts_special_keys input:not(:checked)').each(function() { + $(this).parent().addClass('btn-secondary').removeClass('btn-primary'); + }) +} + +var pointerClickHandler = function(e) { + var msg = '{"type":"pointer","click":"left"}'; + ws.send(msg); +} + +var scrollerTouchStartHandler = function(e) { + var touch = e.targetTouches[0]; + mouseInitPosY = touch.pageY; +} + +var scrollerTouchMoveHandler = function(e) { + var touch = e.changedTouches[0]; + var value = ((touch.pageY - mouseInitPosY > 0) ? 'down' : 'up'); + var now = new Date().getTime(); + + if (value === scrollLastValue && scrollLastTimestamp !== null && now - scrollLastTimestamp < 200) { + return; + } + + scrollLastTimestamp = now; + scrollLastValue = value; + + var msg = '{"type":"scroll","value": "' + value + '"}'; + + mouseInitPosY = touch.pageY; + ws.send(msg); +} + +var pointerTouchStartHandler = function(e) { + var touch = e.targetTouches[0]; + mouseInitPosX = touch.pageX; + mouseInitPosY = touch.pageY; +} + +var pointerTouchMoveHandler = function(e) { + if (e.changedTouches.length === 2) { + return scrollerTouchMoveHandler(e); + } + + var touch = e.changedTouches[0]; + mousePosX = touch.pageX; + mousePosY = touch.pageY; + + var newX = mousePosX - mouseInitPosX; + var newY = mousePosY - mouseInitPosY; + + mouseInitPosX = mousePosX; + mouseInitPosY = mousePosY; + + var msg = '{"type":"pointer","x": "' + newX + '","y": "' + newY + '"}'; + + ws.send(msg); +} + +var documentHashHandler = function() { var hash = window.location.hash; if (hash) { @@ -18,164 +179,41 @@ $(function() { $('#pane-keyboard').show(); $('#nav a').first().addClass('active'); } +} - $('#nav a').click(function(e) { - $('.pane').hide(); +var addListeners = function() { + $('#nav a').click(navigationClickHandler); + $('button[data-msg]').click(buttonClickHandler); - var target = $(this).attr('href'); - $(target).show(); + $('#shortcut-clear').click(shortcutClearClickHandler); + $('#shortcuts_special_keys input').change(shortcutsSpecialKeysOnChangeHandler); + $('#shortcut-send').click(shortcutSendClickHandler); - $('#nav a').removeClass('active'); - $(this).addClass('active'); - }); + $('#text-clear').click(textClearClickHandler); + $('#text-send').click(textSendClickHandler); + $('#text').on('keyup', textKeyUpHandler); + $('#live-text').on('keyup', liveTextKeyUpHandler); - ws.onopen = function(event) { - $('#disconneced').hide(); - } + $scroller + .on('touchstart', scrollerTouchStartHandler) + .on('touchmove', scrollerTouchMoveHandler); - ws.onclose = function(event) { - $('#disconneced').show(); - } + $pointer + .on('click', pointerClickHandler) + .on('touchstart', pointerTouchStartHandler) + .on('touchmove', pointerTouchMoveHandler); +} - ws.onmessage = function(event) {} +var bootstrap = function() { + documentHashHandler(); + shortcutsSpecialKeysOnChangeHandler(); + createWebSocketConnection(); + addListeners(); +} - $('button[data-msg]').click(function() { - var msg = $(this).attr('data-msg'); - ws.send(msg); - }); +$(function() { + $pointer = $('#pointer'); + $scroller = $('#scrollbar'); - $('#shortcut-clear').click(function() { - $('#shortcut-key').val(''); - $('#shortcuts_special_keys input:checked').each(function() { - $(this).prop('checked', false).trigger('change'); - }); - }); - - var shortcutsSpecialKeysOnChange = function() { - $('#shortcuts_special_keys input:checked').each(function() { - $(this).parent().addClass('btn-primary').removeClass('btn-secondary'); - }) - - $('#shortcuts_special_keys input:not(:checked)').each(function() { - $(this).parent().addClass('btn-secondary').removeClass('btn-primary'); - }) - } - - $('#shortcuts_special_keys input').change(shortcutsSpecialKeysOnChange); - shortcutsSpecialKeysOnChange(); - - $('#shortcut-send').click(function() { - var keys = []; - - $('#shortcuts_special_keys input:checked').each(function() { - keys.push($(this).val()); - }); - - var key = $('#shortcut-key').val(); - - if (keys.length) { - if (key) { - keys.push(key); - } - - var msg = '{"type":"keys","value": "' + (keys.join(',').replace('"', '\\"')) + '"}'; - ws.send(msg); - } - }); - - $('#text-clear').click(function() { - $('#text').val(''); - }); - - $pointer.on('click', function(e) { - var msg = '{"type":"pointer","click":"left"}'; - ws.send(msg); - }); - - $('#text-send').click(function() { - var keys = $('#text').val(); - - if (keys.length) { - var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}'; - ws.send(msg); - } - }); - - $('#text').on('keyup', function(e) { - var keys = $('#text').val(); - - if (e.keyCode === 13) { - var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}'; - ws.send(msg); - } - }); - - - $('#live-text').on('keyup', function(e) { - var value = $(this).val(); - var live = false; - - if (e.keyCode === 8) { - var msg = '{"type":"key","value": "backspace"}'; - ws.send(msg); - } else if (e.keyCode === 13) { - var msg = '{"type":"key","value": "enter"}'; - ws.send(msg); - } else if (value.length) { - if (value === ' ') { - var msg = '{"type":"key","value": "space"}'; - ws.send(msg); - } else { - var msg = '{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}'; - ws.send(msg); - } - - $(this).val(''); - } - }); - - $scroller.on('touchstart', function(e) { - var touch = e.targetTouches[0]; - mouseInitPosY = touch.pageY; - }); - - $scroller.on('touchmove', function(e) { - var touch = e.changedTouches[0]; - var value = ((touch.pageY - mouseInitPosY > 0) ? 'down' : 'up'); - var now = new Date().getTime(); - - if (value === scrollLastValue && scrollLastTimestamp !== null && now - scrollLastTimestamp < 200) { - return; - } - - scrollLastTimestamp = now; - scrollLastValue = value; - - var msg = '{"type":"scroll","value": "' + value + '"}'; - - mouseInitPosY = touch.pageY; - ws.send(msg); - }); - - $pointer.on('touchstart', function(e) { - var touch = e.targetTouches[0]; - mouseInitPosX = touch.pageX; - mouseInitPosY = touch.pageY; - }); - - $pointer.on('touchmove', function(e) { - var touch = e.changedTouches[0]; - mousePosX = touch.pageX; - mousePosY = touch.pageY; - - var newX = mousePosX - mouseInitPosX; - var newY = mousePosY - mouseInitPosY; - - mouseInitPosX = mousePosX; - mouseInitPosY = mousePosY; - - var msg = '{"type":"pointer","x": "' + newX + '","y": "' + newY + '"}'; - - ws.send(msg); - }); + bootstrap(); }); diff --git a/client/index.html b/client/index.html index 32fc57d..714a478 100644 --- a/client/index.html +++ b/client/index.html @@ -2,7 +2,7 @@ - + Remote i3-wm diff --git a/server/server b/server/server index 11153ff..7087ccc 100755 --- a/server/server +++ b/server/server @@ -8,10 +8,17 @@ use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; use Ratchet\ConnectionInterface; -$server = new Server(); +$options = getopt( + 'v', + ['verbose', 'vv'] +); + +$serverOutput = new Output(isset($options['v']) || isset($options['verbose'])); +$messageOutput = new Output(isset($options['vv'])); +$server = new Server($serverOutput); $shell = new Shell(); -$server->addMessageHandler('pointer', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('pointer', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $x = $data['x'] ?? null; $y = $data['y'] ?? null; $click = $data['click'] ?? null; @@ -23,36 +30,43 @@ $server->addMessageHandler('pointer', function (ConnectionInterface $from, array $mouseY = (int) ($matches[2] + $y * 2.5); $shell->exec('xdotool mousemove %s %s', $mouseX, $mouseY); + $messageOutput->writeln('Pointer moved'); } elseif ($click !== null) { if ($click === 'left') { $shell->exec('xdotool click 1'); + $messageOutput->writeln('Left click'); } elseif ($click === 'middle') { $shell->exec('xdotool click 2'); + $messageOutput->writeln('Middle click'); } elseif ($click === 'right') { $shell->exec('xdotool click 3'); + $messageOutput->writeln('Right click'); } } }); -$server->addMessageHandler('scroll', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('scroll', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if ($value === 'down') { $shell->exec('xdotool click 5 && xdotool click 5'); + $messageOutput->writeln('Scrolling down'); } elseif ($value === 'up') { $shell->exec('xdotool click 4 && xdotool click 4'); + $messageOutput->writeln('Scrolling up'); } }); -$server->addMessageHandler('workspace', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('workspace', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if (!empty($value)) { $shell->exec("i3-msg 'workspace \"%s\"'", $value); + $messageOutput->writeln('Workspace changed'); } }); -$server->addMessageHandler('volume', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('volume', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if ($value === null) { @@ -66,9 +80,11 @@ $server->addMessageHandler('volume', function (ConnectionInterface $from, array } else { $shell->exec('amixer set Master %d%%', (int) $value); } + + $messageOutput->writeln('Volume modified'); }); -$server->addMessageHandler('media', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('media', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if ($value === 'playpause') { @@ -81,10 +97,11 @@ $server->addMessageHandler('media', function (ConnectionInterface $from, array $ if (!empty($cmd)) { $shell->exec('playerctl -p spotify %s', $cmd); + $messageOutput->writeln('Spotify managed'); } }); -$server->addMessageHandler('keys', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('keys', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if (!empty($value)) { @@ -103,10 +120,11 @@ $server->addMessageHandler('keys', function (ConnectionInterface $from, array $d $value = implode('+', $keys); $shell->exec('xdotool key %s', escapeshellarg($value)); + $messageOutput->writeln('Key pressed'); } }); -$server->addMessageHandler('key', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('key', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; $map = [ 'up' => 'Up', @@ -122,14 +140,16 @@ $server->addMessageHandler('key', function (ConnectionInterface $from, array $da if (!empty($value) && isset($map[$value])) { $shell->exec('xdotool key %s', $map[$value]); + $messageOutput->writeln('Key pressed'); } }); -$server->addMessageHandler('text', function (ConnectionInterface $from, array $data) use ($shell) { +$server->addMessageHandler('text', function (ConnectionInterface $from, array $data) use ($shell, $messageOutput) { $value = $data['value'] ?? null; if (trim($value) !== '') { $shell->exec('xdotool type %s', escapeshellarg($value)); + $messageOutput->writeln('Text wrote'); } }); diff --git a/server/src/Server.php b/server/src/Server.php index daa5df3..444c8f8 100644 --- a/server/src/Server.php +++ b/server/src/Server.php @@ -20,12 +20,18 @@ class Server implements MessageComponentInterface */ protected $messageHandlers = []; + /** + * @var Output + */ + protected $output; + /** * Constructor. */ - public function __construct() + public function __construct(Output $output) { $this->clients = new \SplObjectStorage(); + $this->output = $output; } /** @@ -53,6 +59,7 @@ class Server implements MessageComponentInterface public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); + $this->output->writeln('New client'); } /** @@ -63,15 +70,22 @@ class Server implements MessageComponentInterface $data = json_decode($msg, true); if ($data === null) { + $this->output->writeln('Invalid message received (bad json)'); + return; } $type = $data['type'] ?? null; if ($type === null) { + $this->output->writeln('Invalid message received (type not defined)'); + return; } + $this->output->write('Message received: '); + $this->output->writeln($msg); + $handlers = $this->messageHandlers[$type] ?? []; foreach ($handlers as $handler) {