Remote i3-wm WS : ma télécommande pour bureau Debian GNU/Linux
Article recommandé : Remote i3-wm WS : ma télécommande pour bureau GNU/Linux (v2)
Il m'arrive d'avoir besoin de prendre le contrôle de ma machine via mon Android (bouger la souris, scroller et taper du texte).
J'ai quasiment toujours utilisé l'application Pointer Host. elle s'appuie sur un serveur Java lancé sur ma machine. Pour bouger la souris et générer des cliques, elle est très efficace. Cependant, l'écriture de caractères a toujours posé problème (chiffres et lettres accentuées erronés).
Depuis quelques semaines, j'ai envie de jouer avec les websockets et réécrire une appli du genre m'a semblé être un bon exercice.
Ce que je vais vous présenter est une POC. Cette application n'est pas sécurisée et est orientée pour mes besoins. Il est cependant très simple de la faire évoluer.
Voici mon cahier des charges :
- aucune application ne doit être installée sur mon téléphone
- utilisation du navigateur web pour le pilotage
- pouvoir bouger la souris
- pouvoir générer des cliques
- pouvoir scroller
- pouvoir taper des mots
- pouvoir lancer des raccouris claviers
- pouvoir gérer le volume du son
- pour Spotify : lancer et mettre en pause la musique, avancer et reculer dans la playlist en cours de lecture
- pouvoir changer de workspace dans mon gestionnaire de fenêtres i3-wm
Les outils pour scripter tout ça sont connus :
xdotool
pour simuler un clavier et une souris (3, 4, 5, 6, 7) :xdotool type "ceci va être tapé"
xdotool key Enter
(toucheEntrée
)xdotool click 1
(clique gauche)
amixer
pour gérer le volume (8) :amixer set Master 50%
(volume à 50%)
playerctl
pour piloter Spotify (9) :playerctl -p spotify next
(titre suivant)
i3-msg
pour piloter i3-wm (10) :i3-msg 'workspace "Foo"'
(affichage du workspaceFoo
)
Websocket est un protocole réseau issu du web qui permet de créer un canal full-duplex entre un client et un serveur. Ils peuvent donc communiquer en temps réel dans une connexion TCP.
Comme à mon habitude et par esprit de contradiction (pas de NodeJS), j'ai décidé d'écrire la partie serveur en PHP 7. La partie cliente est en HTML 5 avec un peu de javascript.
Entre le serveur et le client, ce sont des messages textes qui sont échangés. J'ai décidé de les formater en JSON et seul le client va en envoyer. Ils sont toujours sous cette forme : {"type":"un type de message", [données complémentaires]}
. Voici quelques exemples :
{"type":"workspace","value":"1. IRC"}
{"type":"pointer","click":"left"}
{"type":"media","value":"next"}
{"type":"volume","value":"down"}
{"type":"scroll","value":"up"}
{"type":"pointer","x":"-2","y":"3"}
{"type":"text","value":"Un texte"}
On peut aussi envoyer plusieurs messages dans un seul. Voici un exemple qui va permettre d'ouvrir urxvt
via dmenu
que je lance avec win+d
:
{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"urxvt"},{"type":"key","value":"enter"}]}
Ces messages sont générés par le client et sont interprétés par des messageHandler
une fois transmis au serveur. En voici un exemple :
Le code source de l'application est disponible sur deblan/remote-i3wm-ws et la procédure d'installation est simple :
Pour lancer le serveur websocket, il faut exécuter server/server start
(@see restart
et stop
). Le serveur va écouter sur le port 14598
.
Concernant la partie cliente, vous pouvez créer un vhost Apache/Nginx qui pointera sur client/
ou lancer le serveur web built-in de PHP via php -S 0.0.0.0:15000 -t client/
. Il faudra à présent vous connecter au serveur web depuis un navigateur.
Quelques captures de la partie cliente :
Je vais essayer de faire une vidéo de démonstration. Depuis mon Samsung S8, ça fonctionne du feu de dieu et sur un petit Iphone 4S, c'est tout aussi fonctionnel (à part l'interface web un peu étriquée).
Edit 1
dbus-send
a été remplacé parplayerctl
(merci Thomas L)- le type
messages
a été ajouté et permet d'envoyer plusieurs messages (cf l'exemple avecurxvt
) et les mises à jour du code
Edit 2
- Le code PHP du serveur a été déplacé dans
server/src/resource/server.php
server/server
est à présent un script shell et permet de lancer, relancer et stopper le serveur websocket (server/server start|restart|stop
)

Remote i3-wm WS : ma télécommande pour bureau GNU/Linux (v2)
En février 2018, je publiais l'article Remote i3-wm WS : ma télécommande pour bureau Debian …

Blocs pour i3wm
Je suis un fervent utilisateur de i3wm et ça dure depuis des années ! Grâce à i3blocks, j'ai…

Mes scripts i3blocks pour générer les éléments de ma barre i3-wm
i3-wm est le gestionnaire de fenêtres que j'utilise depuis quelques d'années maintenant. Au…
- Génial.
Je vais étudier ça.
Pour arrêter le serveur, un ctrl+c suffit ?
Pour changer le port utilisé, il faut le faire dans les fichiers server/server et client/assets/js/main.js.
Y a-t-il un autre endroit ou est-ce que ce sont les seuls fichiers ?
Est-ce que le fait de changer le port utilisé par php dans la commande qui lance le client (15000) aura une conséquence quant au fonctionnement de l'appli ?
Merci pour le partage.
- Tu as tout juste et aucune incidence :)
- Cool et merci pour la réponse ultra-rapide ^_^
- Tu devrais essayer playerctl pour la musique, c'est un player assez universel qui est bien pratique.
- Merci pour le tips ! Je l'utilise déjà pour afficher le titre en cours de lecture mais je n'avais pas du tout penser à lui pour gérer la lecture.
- Pour arrêter le serveur, un ctrl+c ne suffit pas. Si on actualise la page, le serveur se relance.
Pour vraiment l'arrêter, il faut tuer le processus (kill) en ajoutant les deux index donnés lors du lancement des commandes pour le client et le serveur.
- J'ai également détecté ce problème…je vais essayer de trouver un fix !
- Ça fonctionne pour le serveur mais pas pour le client qui continue de fonctionner si on rafraichit la page.
On devrait pouvoir rafraichir uniquement si le client n'a pas été tué via le terminal.
Par contre, je ne parviens pas à afficher la page sur mon tel ou sur ma tablette, uniquement sur l'ordi qui lance les processus...
- Effectivement, le correctif mis en ligne ne permet que de piloter le serveur websocket et pas le serveur web. En effet, il pourrait être tout à fait possible de passer par apache ou nginx pour délivrer cette partie du service.
Quand tu lances le serveur web, quelles commandes utilises-tu ?
- php -S 0.0.0.0:15000 -t client/