mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-17 03:31:29 +03:00
transmit button events + stub for keyboard
This commit is contained in:
53
Cargo.lock
generated
53
Cargo.lock
generated
@@ -201,6 +201,16 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-lifetimes"
|
||||||
|
version = "1.0.0-rc1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f65dae1d3aa98e6877917ab4e6fdbfdfb00e95885ea7c4f4f29e3a5dfc08fdf"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipconfig"
|
name = "ipconfig"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -227,6 +237,7 @@ dependencies = [
|
|||||||
"trust-dns-resolver",
|
"trust-dns-resolver",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-protocols",
|
"wayland-protocols",
|
||||||
|
"wayland-protocols-misc",
|
||||||
"wayland-protocols-wlr",
|
"wayland-protocols-wlr",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -729,11 +740,12 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.1.0-beta.9"
|
version = "0.1.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
|
"io-lifetimes",
|
||||||
"nix",
|
"nix",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
@@ -742,8 +754,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-client"
|
name = "wayland-client"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@@ -756,8 +768,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols"
|
name = "wayland-protocols"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -766,10 +778,23 @@ dependencies = [
|
|||||||
"wayland-server",
|
"wayland-server",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-protocols-misc"
|
||||||
|
version = "0.1.0-beta.10"
|
||||||
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-scanner",
|
||||||
|
"wayland-server",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols-wlr"
|
name = "wayland-protocols-wlr"
|
||||||
version = "0.1.0-beta.9"
|
version = "0.1.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -781,8 +806,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-scanner"
|
name = "wayland-scanner"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
@@ -792,8 +817,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-server"
|
name = "wayland-server"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
@@ -805,8 +830,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.10"
|
||||||
source = "git+https://github.com/Smithay/wayland-rs.git#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/Smithay/wayland-rs.git#2cd2b5857b476238eb7d2e7e3bb2b1c308bcd16c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
|
|||||||
@@ -9,11 +9,7 @@ edition = "2021"
|
|||||||
wayland-client = { git="https://github.com/Smithay/wayland-rs.git" }
|
wayland-client = { git="https://github.com/Smithay/wayland-rs.git" }
|
||||||
wayland-protocols = { git="https://github.com/Smithay/wayland-rs.git", features=["client", "staging", "unstable"] }
|
wayland-protocols = { git="https://github.com/Smithay/wayland-rs.git", features=["client", "staging", "unstable"] }
|
||||||
wayland-protocols-wlr = { git="https://github.com/Smithay/wayland-rs.git", features=["client", "server"] }
|
wayland-protocols-wlr = { git="https://github.com/Smithay/wayland-rs.git", features=["client", "server"] }
|
||||||
|
wayland-protocols-misc = { git="https://github.com/Smithay/wayland-rs.git", features=["client", "server"] }
|
||||||
tempfile = "3.2"
|
tempfile = "3.2"
|
||||||
trust-dns-resolver = "0.22"
|
trust-dns-resolver = "0.22"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "client"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "server"
|
|
||||||
|
|||||||
@@ -10,14 +10,15 @@ Currently the mouse moves in a circle when receiving a(ny) udp packet on port 42
|
|||||||
## TODO
|
## TODO
|
||||||
- [x] Capture the actual mouse events on the server side via a wayland client and send them to the client
|
- [x] Capture the actual mouse events on the server side via a wayland client and send them to the client
|
||||||
- [x] Mouse grabbing
|
- [x] Mouse grabbing
|
||||||
- [x] Window with absolute position (wlr\_layer\_shell?)
|
- [ ] Window with absolute position (wlr\_layer\_shell?)
|
||||||
- [ ] DNS resolving
|
- [x] DNS resolving
|
||||||
- [ ] Keyboard support
|
- [ ] Keyboard support
|
||||||
- [ ] Scrollwheel support
|
- [ ] Scrollwheel support
|
||||||
- [ ] Button support
|
- [x] Button support
|
||||||
- [ ] Merge server and client
|
- [ ] Merge server and client
|
||||||
- [ ] Clipboard support
|
- [ ] Clipboard support
|
||||||
- [ ] Graphical frontend (gtk?)
|
- [ ] Graphical frontend (gtk?)
|
||||||
|
- [ ] *Encrytion*
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
Sending key and mouse event data over the local network might not be the biggest security concern but in any public network it's QUITE a problem to basically broadcast your keystrokes.
|
Sending key and mouse event data over the local network might not be the biggest security concern but in any public network it's QUITE a problem to basically broadcast your keystrokes.
|
||||||
|
|||||||
@@ -1,27 +1,38 @@
|
|||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
use lan_mouse::protocol;
|
||||||
|
|
||||||
use wayland_protocols_wlr::virtual_pointer::v1::client::{
|
use wayland_protocols_wlr::virtual_pointer::v1::client::{
|
||||||
zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1 as VpManager,
|
zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1 as VpManager,
|
||||||
zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1 as Vp,
|
zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1 as Vp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use wayland_client::{protocol::wl_registry, Connection, Dispatch, EventQueue, QueueHandle};
|
use wayland_protocols_misc::zwp_virtual_keyboard_v1::client::{
|
||||||
|
zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1 as VkManager,
|
||||||
|
zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1 as Vk,
|
||||||
|
};
|
||||||
|
|
||||||
|
use wayland_client::{
|
||||||
|
protocol::{wl_registry, wl_seat, wl_keyboard::KeyState},
|
||||||
|
Connection, Dispatch, EventQueue, QueueHandle,
|
||||||
|
};
|
||||||
|
|
||||||
// App State, implements Dispatch event handlers
|
// App State, implements Dispatch event handlers
|
||||||
struct AppData {
|
struct App {
|
||||||
vpm: Option<VpManager>,
|
vpm: Option<VpManager>,
|
||||||
|
vkm: Option<VkManager>,
|
||||||
|
seat: Option<wl_seat::WlSeat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement `Dispatch<WlRegistry, ()> event handler
|
// Implement `Dispatch<WlRegistry, ()> event handler
|
||||||
// user-data = ()
|
// user-data = ()
|
||||||
impl Dispatch<wl_registry::WlRegistry, ()> for AppData {
|
impl Dispatch<wl_registry::WlRegistry, ()> for App {
|
||||||
fn event(
|
fn event(
|
||||||
app: &mut Self,
|
app: &mut Self,
|
||||||
registry: &wl_registry::WlRegistry,
|
registry: &wl_registry::WlRegistry,
|
||||||
event: wl_registry::Event,
|
event: wl_registry::Event,
|
||||||
_: &(),
|
_: &(),
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
qh: &QueueHandle<AppData>,
|
qh: &QueueHandle<App>,
|
||||||
) {
|
) {
|
||||||
// Match global event to get globals after requesting them in main
|
// Match global event to get globals after requesting them in main
|
||||||
if let wl_registry::Event::Global {
|
if let wl_registry::Event::Global {
|
||||||
@@ -30,10 +41,14 @@ impl Dispatch<wl_registry::WlRegistry, ()> for AppData {
|
|||||||
{
|
{
|
||||||
// println!("[{}] {} (v{})", name, interface, version);
|
// println!("[{}] {} (v{})", name, interface, version);
|
||||||
match &interface[..] {
|
match &interface[..] {
|
||||||
|
"wl_seat" => {
|
||||||
|
app.seat = Some(registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ()));
|
||||||
|
}
|
||||||
"zwlr_virtual_pointer_manager_v1" => {
|
"zwlr_virtual_pointer_manager_v1" => {
|
||||||
// virtual pointer protocol
|
app.vpm = Some(registry.bind::<VpManager, _, _>(name, 1, qh, ()));
|
||||||
let vpm = registry.bind::<VpManager, _, _>(name, 1, qh, ()); // get the vp manager
|
}
|
||||||
app.vpm = Some(vpm); // save it to app state
|
"zwp_virtual_keyboard_manager_v1" => {
|
||||||
|
app.vkm = Some(registry.bind::<VkManager, _, _>(name, 1, qh, ()));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -56,39 +71,61 @@ fn main() {
|
|||||||
// Create a wl_registry object by sending the wl_display.get_registry request
|
// Create a wl_registry object by sending the wl_display.get_registry request
|
||||||
let _registry = display.get_registry(&qh, ());
|
let _registry = display.get_registry(&qh, ());
|
||||||
|
|
||||||
let mut app_data = AppData { vpm: None };
|
let mut app = App {
|
||||||
|
vpm: None,
|
||||||
|
vkm: None,
|
||||||
|
seat: None,
|
||||||
|
};
|
||||||
|
|
||||||
// use roundtrip to process this event synchronously
|
// use roundtrip to process this event synchronously
|
||||||
event_queue.roundtrip(&mut app_data).unwrap();
|
event_queue.roundtrip(&mut app).unwrap();
|
||||||
if let Some(vpm) = app_data.vpm {
|
|
||||||
let pointer: Vp = vpm.create_virtual_pointer(None, &qh, ());
|
let vpm = app.vpm.unwrap();
|
||||||
udp_loop(pointer, event_queue).unwrap();
|
let vkm = app.vkm.unwrap();
|
||||||
println!();
|
let seat = app.seat.unwrap();
|
||||||
} else {
|
let pointer: Vp = vpm.create_virtual_pointer(None, &qh, ());
|
||||||
panic!("zwlr_virtual_pointer_manager_v1 protocol required")
|
let keyboard: Vk = vkm.create_virtual_keyboard(&seat, &qh, ());
|
||||||
};
|
udp_loop(&pointer, &keyboard, event_queue).unwrap();
|
||||||
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// main loop handling udp packets
|
/// main loop handling udp packets
|
||||||
fn udp_loop(pointer: Vp, q: EventQueue<AppData>) -> std::io::Result<()> {
|
fn udp_loop(pointer: &Vp, keyboard: &Vk, q: EventQueue<App>) -> std::io::Result<()> {
|
||||||
let socket = UdpSocket::bind("0.0.0.0:42069")?;
|
let socket = UdpSocket::bind("0.0.0.0:42069")?;
|
||||||
// we don't care about possible dropped packets for now
|
// we don't care about possible dropped packets for now
|
||||||
|
|
||||||
let mut buf = [0u8; 20];
|
let mut buf = [0u8; 21];
|
||||||
loop {
|
loop {
|
||||||
let (amt, _src) = socket.recv_from(&mut buf)?;
|
let (_amt, _src) = socket.recv_from(&mut buf)?;
|
||||||
assert!(amt == 20);
|
|
||||||
|
|
||||||
let time: u32 = u32::from_ne_bytes(buf[0..4].try_into().unwrap());
|
match protocol::Event::decode(buf) {
|
||||||
let x: f64 = f64::from_ne_bytes(buf[4..12].try_into().unwrap());
|
protocol::Event::Mouse { t, x, y } => {
|
||||||
let y: f64 = f64::from_ne_bytes(buf[12..20].try_into().unwrap());
|
pointer.motion(t, x, y);
|
||||||
|
}
|
||||||
|
protocol::Event::Button { t, b, s } => {
|
||||||
|
pointer.button(t, b, s);
|
||||||
|
}
|
||||||
|
protocol::Event::Axis { t, a, v } => {
|
||||||
|
pointer.axis(t, a, v);
|
||||||
|
}
|
||||||
|
protocol::Event::Key { t, k, s } => {
|
||||||
|
// TODO send keymap fist
|
||||||
|
// keyboard.key(t, k, match s {
|
||||||
|
// KeyState::Released => 0,
|
||||||
|
// KeyState::Pressed => 1,
|
||||||
|
// _ => 1,
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
protocol::Event::KeyModifier { mods_depressed, mods_latched, mods_locked, group } => {
|
||||||
|
// keyboard.modifiers(mods_depressed, mods_latched, mods_locked, group);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
pointer.motion(time, x, y);
|
|
||||||
q.flush().unwrap();
|
q.flush().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<VpManager, ()> for AppData {
|
impl Dispatch<VpManager, ()> for App {
|
||||||
fn event(
|
fn event(
|
||||||
_: &mut Self,
|
_: &mut Self,
|
||||||
_: &VpManager,
|
_: &VpManager,
|
||||||
@@ -101,7 +138,7 @@ impl Dispatch<VpManager, ()> for AppData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<Vp, ()> for AppData {
|
impl Dispatch<Vp, ()> for App {
|
||||||
fn event(
|
fn event(
|
||||||
_: &mut Self,
|
_: &mut Self,
|
||||||
_: &Vp,
|
_: &Vp,
|
||||||
@@ -113,3 +150,42 @@ impl Dispatch<Vp, ()> for AppData {
|
|||||||
// no events defined for vp either
|
// no events defined for vp either
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Dispatch<VkManager, ()> for App {
|
||||||
|
fn event(
|
||||||
|
_: &mut Self,
|
||||||
|
_: &VkManager,
|
||||||
|
_: <VkManager as wayland_client::Proxy>::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<Vk, ()> for App {
|
||||||
|
fn event(
|
||||||
|
_: &mut Self,
|
||||||
|
_: &Vk,
|
||||||
|
_: <Vk as wayland_client::Proxy>::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<wl_seat::WlSeat, ()> for App {
|
||||||
|
fn event(
|
||||||
|
_: &mut Self,
|
||||||
|
_: &wl_seat::WlSeat,
|
||||||
|
_: <wl_seat::WlSeat as wayland_client::Proxy>::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
use lan_mouse::protocol;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
net::{UdpSocket, IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr, UdpSocket},
|
||||||
|
str::FromStr,
|
||||||
os::unix::prelude::AsRawFd,
|
os::unix::prelude::AsRawFd,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -16,14 +18,14 @@ use wayland_protocols::{
|
|||||||
|
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
protocol::{
|
protocol::{
|
||||||
wl_buffer, wl_compositor, wl_keyboard, wl_pointer, wl_registry, wl_seat, wl_shm,
|
wl_buffer, wl_compositor, wl_keyboard, wl_pointer::{self, Axis, ButtonState}, wl_registry, wl_seat, wl_shm,
|
||||||
wl_shm_pool, wl_surface,
|
wl_shm_pool, wl_surface,
|
||||||
},
|
},
|
||||||
Connection, Dispatch, QueueHandle, WEnum,
|
Connection, Dispatch, QueueHandle, WEnum,
|
||||||
};
|
};
|
||||||
|
|
||||||
use trust_dns_resolver::Resolver;
|
|
||||||
use tempfile;
|
use tempfile;
|
||||||
|
use trust_dns_resolver::Resolver;
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
running: bool,
|
running: bool,
|
||||||
@@ -72,11 +74,16 @@ fn main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let host = match args.get(1) {
|
let arg = match args.get(1) {
|
||||||
Some(s) => s.as_str(),
|
Some(s) => s.as_str(),
|
||||||
None => "localhost",
|
None => "localhost",
|
||||||
};
|
};
|
||||||
app.resolve_host(host);
|
if let Ok(ip) = IpAddr::from_str(arg) {
|
||||||
|
app.ip = Some(ip);
|
||||||
|
println!("{} ", ip);
|
||||||
|
} else {
|
||||||
|
app.resolve_host(arg);
|
||||||
|
}
|
||||||
|
|
||||||
// use roundtrip to process this event synchronously
|
// use roundtrip to process this event synchronously
|
||||||
event_queue.roundtrip(&mut app).unwrap();
|
event_queue.roundtrip(&mut app).unwrap();
|
||||||
@@ -115,7 +122,9 @@ fn draw(f: &mut File, (width, height): (u32, u32)) {
|
|||||||
impl App {
|
impl App {
|
||||||
fn resolve_host(&mut self, host: &str) {
|
fn resolve_host(&mut self, host: &str) {
|
||||||
let resolver = Resolver::from_system_conf().unwrap();
|
let resolver = Resolver::from_system_conf().unwrap();
|
||||||
let response = resolver.lookup_ip(host).expect(format!("couldn't resolve {}", host).as_str());
|
let response = resolver
|
||||||
|
.lookup_ip(host)
|
||||||
|
.expect(format!("couldn't resolve {}", host).as_str());
|
||||||
self.ip = response.iter().next();
|
self.ip = response.iter().next();
|
||||||
if let None = self.ip {
|
if let None = self.ip {
|
||||||
panic!("couldn't resolve host: {}!", host)
|
panic!("couldn't resolve host: {}!", host)
|
||||||
@@ -123,15 +132,25 @@ impl App {
|
|||||||
println!("Client: {} {}", host, self.ip.unwrap());
|
println!("Client: {} {}", host, self.ip.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_event(&self, e: &protocol::Event) {
|
||||||
|
let buf = e.encode();
|
||||||
|
self.socket
|
||||||
|
.send_to(&buf, SocketAddr::new(self.ip.unwrap(), 42069))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn send_motion_event(&self, time: u32, x: f64, y: f64) {
|
fn send_motion_event(&self, time: u32, x: f64, y: f64) {
|
||||||
let time_bytes = time.to_ne_bytes();
|
let e = protocol::Event::Mouse { t: (time), x: (x), y: (y) };
|
||||||
let x_bytes = x.to_ne_bytes();
|
self.send_event(&e);
|
||||||
let y_bytes = y.to_ne_bytes();
|
}
|
||||||
let mut buf: [u8; 20] = [0u8; 20];
|
|
||||||
buf[0..4].copy_from_slice(&time_bytes);
|
fn send_button_event(&self, t: u32, b: u32, s: ButtonState) {
|
||||||
buf[4..12].copy_from_slice(&x_bytes);
|
let e = protocol::Event::Button { t, b, s };
|
||||||
buf[12..20].copy_from_slice(&y_bytes);
|
self.send_event(&e);
|
||||||
self.socket.send_to(&buf, SocketAddr::new(self.ip.unwrap(), 42069)).unwrap();
|
}
|
||||||
|
fn send_axis_event(&self, t: u32, a: Axis, v: f64) {
|
||||||
|
let e = protocol::Event::Axis { t, a, v };
|
||||||
|
self.send_event(&e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,22 +386,31 @@ impl Dispatch<wl_pointer::WlPointer, ()> for App {
|
|||||||
surface_y: _,
|
surface_y: _,
|
||||||
} => {
|
} => {
|
||||||
if app.pointer_lock.is_none() {
|
if app.pointer_lock.is_none() {
|
||||||
app.pointer_lock = Some(app.pointer_constraints.as_ref().unwrap().lock_pointer(
|
app.pointer_lock =
|
||||||
&app.surface.as_ref().unwrap(),
|
Some(app.pointer_constraints.as_ref().unwrap().lock_pointer(
|
||||||
pointer,
|
&app.surface.as_ref().unwrap(),
|
||||||
None,
|
pointer,
|
||||||
zwp_pointer_constraints_v1::Lifetime::Persistent,
|
None,
|
||||||
qh,
|
zwp_pointer_constraints_v1::Lifetime::Persistent,
|
||||||
(),
|
qh,
|
||||||
));
|
(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if app.rel_pointer.is_none() {
|
if app.rel_pointer.is_none() {
|
||||||
app.rel_pointer = Some(app.rel_pointer_manager
|
app.rel_pointer = Some(
|
||||||
.as_ref()
|
app.rel_pointer_manager
|
||||||
.unwrap()
|
.as_ref()
|
||||||
.get_relative_pointer(pointer, qh, ()));
|
.unwrap()
|
||||||
|
.get_relative_pointer(pointer, qh, ()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wl_pointer::Event::Button { serial:_, time, button, state } => {
|
||||||
|
app.send_button_event(time, button, state.into_result().unwrap());
|
||||||
|
}
|
||||||
|
wl_pointer::Event::Axis { time, axis, value } => {
|
||||||
|
app.send_axis_event(time, axis.into_result().unwrap(), value);
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,24 +418,26 @@ impl Dispatch<wl_pointer::WlPointer, ()> for App {
|
|||||||
|
|
||||||
impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
|
impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
|
||||||
fn event(
|
fn event(
|
||||||
state: &mut Self,
|
app: &mut Self,
|
||||||
_: &wl_keyboard::WlKeyboard,
|
_: &wl_keyboard::WlKeyboard,
|
||||||
event: wl_keyboard::Event,
|
event: wl_keyboard::Event,
|
||||||
_: &(),
|
_: &(),
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
_: &QueueHandle<Self>,
|
_: &QueueHandle<Self>,
|
||||||
) {
|
) {
|
||||||
if let wl_keyboard::Event::Key { key, .. } = event {
|
if let wl_keyboard::Event::Key { serial: _, time, key, state } = event {
|
||||||
if key == 1 {
|
if key == 1 {
|
||||||
// ESC key
|
// ESC key
|
||||||
if let Some(pointer_lock) = state.pointer_lock.as_ref() {
|
if let Some(pointer_lock) = app.pointer_lock.as_ref() {
|
||||||
pointer_lock.destroy();
|
pointer_lock.destroy();
|
||||||
state.pointer_lock = None;
|
app.pointer_lock = None;
|
||||||
}
|
}
|
||||||
if let Some(rel_pointer) = state.rel_pointer.as_ref() {
|
if let Some(rel_pointer) = app.rel_pointer.as_ref() {
|
||||||
rel_pointer.destroy();
|
rel_pointer.destroy();
|
||||||
state.rel_pointer = None;
|
app.rel_pointer = None;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
app.send_event(&protocol::Event::Key{ t: (time), k: (key), s: (state.into_result().unwrap()) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -465,13 +495,13 @@ impl Dispatch<zwp_relative_pointer_v1::ZwpRelativePointerV1, ()> for App {
|
|||||||
_: &QueueHandle<Self>,
|
_: &QueueHandle<Self>,
|
||||||
) {
|
) {
|
||||||
if let zwp_relative_pointer_v1::Event::RelativeMotion {
|
if let zwp_relative_pointer_v1::Event::RelativeMotion {
|
||||||
utime_hi,
|
utime_hi,
|
||||||
utime_lo,
|
utime_lo,
|
||||||
dx: _,
|
dx: _,
|
||||||
dy: _,
|
dy: _,
|
||||||
dx_unaccel,
|
dx_unaccel,
|
||||||
dy_unaccel,
|
dy_unaccel,
|
||||||
} = event {
|
} = event {
|
||||||
let time = ((utime_hi as u64) << 32 | utime_lo as u64) / 1000;
|
let time = ((utime_hi as u64) << 32 | utime_lo as u64) / 1000;
|
||||||
app.send_motion_event(time as u32, dx_unaccel, dy_unaccel);
|
app.send_motion_event(time as u32, dx_unaccel, dy_unaccel);
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod protocol;
|
||||||
116
src/protocol.rs
Normal file
116
src/protocol.rs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
use wayland_client::protocol::{
|
||||||
|
wl_pointer::{Axis, ButtonState},
|
||||||
|
wl_keyboard::KeyState,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
Mouse{t: u32, x: f64, y: f64},
|
||||||
|
Button{t: u32, b: u32, s: ButtonState},
|
||||||
|
Axis{t: u32, a: Axis, v: f64},
|
||||||
|
Key{t: u32, k: u32, s: KeyState},
|
||||||
|
KeyModifier{mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub fn encode(&self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
Event::Mouse { t, x, y } => {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
buf.push(0u8);
|
||||||
|
buf.extend_from_slice(t.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(x.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(y.to_ne_bytes().as_ref());
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
Event::Button { t, b, s } => {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
buf.push(1u8);
|
||||||
|
buf.extend_from_slice(t.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(b.to_ne_bytes().as_ref());
|
||||||
|
buf.push(match s {
|
||||||
|
ButtonState::Released => 0u8,
|
||||||
|
ButtonState::Pressed => 1u8,
|
||||||
|
_ => todo!()
|
||||||
|
});
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
Event::Axis{t, a, v} => {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
buf.push(2u8);
|
||||||
|
buf.extend_from_slice(t.to_ne_bytes().as_ref());
|
||||||
|
buf.push(match a {
|
||||||
|
Axis::VerticalScroll => 0,
|
||||||
|
Axis::HorizontalScroll => 1,
|
||||||
|
_ => todo!()
|
||||||
|
});
|
||||||
|
buf.extend_from_slice(v.to_ne_bytes().as_ref());
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
Event::Key{t, k, s } => {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
buf.push(3u8);
|
||||||
|
buf.extend_from_slice(t.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(k.to_ne_bytes().as_ref());
|
||||||
|
buf.push(match s {
|
||||||
|
KeyState::Released => 0,
|
||||||
|
KeyState::Pressed => 1,
|
||||||
|
_ => todo!(),
|
||||||
|
});
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
Event::KeyModifier{ mods_depressed, mods_latched, mods_locked, group } => {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
buf.push(4u8);
|
||||||
|
buf.extend_from_slice(mods_depressed.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(mods_latched.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(mods_locked.to_ne_bytes().as_ref());
|
||||||
|
buf.extend_from_slice(group.to_ne_bytes().as_ref());
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode(buf: [u8; 21]) -> Event {
|
||||||
|
match buf[0] {
|
||||||
|
0 => Self::Mouse {
|
||||||
|
t: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
|
||||||
|
x: f64::from_ne_bytes(buf[5..13].try_into().unwrap()),
|
||||||
|
y: f64::from_ne_bytes(buf[13..21].try_into().unwrap()),
|
||||||
|
},
|
||||||
|
1 => Self::Button {
|
||||||
|
t: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
|
||||||
|
b: (u32::from_ne_bytes(buf[5..9].try_into().unwrap())),
|
||||||
|
s: (match buf[9] {
|
||||||
|
0 => ButtonState::Released,
|
||||||
|
1 => ButtonState::Pressed,
|
||||||
|
_ => panic!("protocol violation")
|
||||||
|
})
|
||||||
|
},
|
||||||
|
2 => Self::Axis {
|
||||||
|
t: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
|
||||||
|
a: (match buf[5] {
|
||||||
|
0 => Axis::VerticalScroll,
|
||||||
|
1 => Axis::HorizontalScroll,
|
||||||
|
_ => todo!()
|
||||||
|
}),
|
||||||
|
v: (f64::from_ne_bytes(buf[6..14].try_into().unwrap())),
|
||||||
|
},
|
||||||
|
3 => Self::Key {
|
||||||
|
t: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
|
||||||
|
k: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
|
||||||
|
s: match buf[9] {
|
||||||
|
0 => KeyState::Released,
|
||||||
|
1 => KeyState::Pressed,
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
4 => Self::KeyModifier {
|
||||||
|
mods_depressed: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
|
||||||
|
mods_latched: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
|
||||||
|
mods_locked: u32::from_ne_bytes(buf[9..13].try_into().unwrap()),
|
||||||
|
group: u32::from_ne_bytes(buf[13..17].try_into().unwrap()),
|
||||||
|
},
|
||||||
|
_ => panic!("protocol violation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user