No description
Find a file
2026-04-30 04:42:12 +01:00
android inital 2026-04-30 04:39:20 +01:00
backend inital 2026-04-30 04:39:20 +01:00
ios inital 2026-04-30 04:39:20 +01:00
lib inital 2026-04-30 04:39:20 +01:00
linux inital 2026-04-30 04:39:20 +01:00
macos inital 2026-04-30 04:39:20 +01:00
nginx inital 2026-04-30 04:39:20 +01:00
test inital 2026-04-30 04:39:20 +01:00
web inital 2026-04-30 04:39:20 +01:00
windows inital 2026-04-30 04:39:20 +01:00
.gitignore inital 2026-04-30 04:39:20 +01:00
.metadata inital 2026-04-30 04:39:20 +01:00
analysis_options.yaml inital 2026-04-30 04:39:20 +01:00
docker-compose.yml inital 2026-04-30 04:42:12 +01:00
pubspec.lock inital 2026-04-30 04:39:20 +01:00
pubspec.yaml inital 2026-04-30 04:39:20 +01:00
README.md first commit 2026-04-30 04:36:56 +01:00

Pulsar

A LAN remote desktop app built with Flutter + WebRTC.
The host shares their screen; the viewer streams it and forwards mouse/keyboard input back.


Architecture

Host (desktop)  <──WebRTC──>  Viewer (any platform)
        │                            │
        └────── WebSocket ───────────┘
                    │
             Signalling Server
             (Node.js / ws)
  • Signalling server — relays WebRTC offer/answer/ICE between peers. In-memory, no auth.
  • Host — captures screen with getDisplayMedia, streams it via WebRTC. Desktop/Web only.
  • Viewer — receives the video stream, renders it full-screen, and sends input events back over a WebRTC data channel.
  • Input injection — host injects received events into the OS via platform channels (CGEvent on macOS, SendInput on Windows, XTest on Linux/X11).

Running the backend

cd backend
npm install
npm start

The server listens on ws://localhost:3000 by default.


Running the Flutter app

flutter pub get
flutter run -d macos   # or windows, linux

macOS notes

Screen capture requires granting Screen Recording permission in
System Settings → Privacy & Security → Screen Recording.

Input injection requires granting Accessibility permission in
System Settings → Privacy & Security → Accessibility.

The sandbox is disabled in debug/release entitlements so that CGEvent can post
events to other processes. Do not ship this as-is to the Mac App Store.

Windows notes

No extra permissions needed. SendInput works out of the box.

Linux notes

Only X11 is supported for input injection. Wayland sessions will not receive
injected events. Make sure libxtst-dev is installed before building:

sudo apt install libxtst-dev   # Debian / Ubuntu
sudo dnf install libXtst-devel # Fedora

Usage

  1. Start the signalling server.
  2. On the host machine: open Pulsar → Host. A 6-character room code appears.
  3. On the viewer machine: open Pulsar → Connect, enter the room code.
  4. The viewer will display the host's screen. Move the mouse and type to control the host.

Both machines must be able to reach the signalling server. For LAN testing, use the
host's local IP in the server URL field (e.g. ws://192.168.1.10:3000).


Key input mapping caveat

Flutter's logical key IDs are not the same as OS virtual key codes. The current
implementation uses the low byte of the logical key ID as a rough approximation.
This works for standard ASCII keys but may misbehave for function keys, modifiers,
and non-Latin layouts. A proper mapping table would be needed for production use.