Keyboard support + data requests via tcp server

This commit is contained in:
Ferdinand Schober
2022-09-19 17:20:50 +02:00
parent d4b4e7c269
commit 35414059a8
10 changed files with 451 additions and 174 deletions

View File

@@ -1,5 +1,5 @@
use std::net::UdpSocket;
use lan_mouse::protocol;
use std::{os::unix::prelude::AsRawFd, io::{Write, BufWriter}};
use lan_mouse::{protocol::{self, DataRequest}, config::Config};
use wayland_protocols_wlr::virtual_pointer::v1::client::{
zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1 as VpManager,
@@ -12,10 +12,12 @@ use wayland_protocols_misc::zwp_virtual_keyboard_v1::client::{
};
use wayland_client::{
protocol::{wl_registry, wl_seat, wl_keyboard::KeyState},
protocol::{wl_registry, wl_seat, wl_keyboard},
Connection, Dispatch, EventQueue, QueueHandle,
};
use tempfile;
// App State, implements Dispatch event handlers
struct App {
vpm: Option<VpManager>,
@@ -41,6 +43,9 @@ impl Dispatch<wl_registry::WlRegistry, ()> for App {
{
// println!("[{}] {} (v{})", name, interface, version);
match &interface[..] {
"wl_keyboard" => {
registry.bind::<wl_keyboard::WlKeyboard, _, _>(name, 1, qh, ());
}
"wl_seat" => {
app.seat = Some(registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ()));
}
@@ -58,6 +63,7 @@ impl Dispatch<wl_registry::WlRegistry, ()> for App {
// The main function of our program
fn main() {
let config = Config::new("config.toml").unwrap();
// establish connection via environment-provided configuration.
let conn = Connection::connect_to_env().unwrap();
@@ -80,47 +86,43 @@ fn main() {
// use roundtrip to process this event synchronously
event_queue.roundtrip(&mut app).unwrap();
let vpm = app.vpm.unwrap();
let vkm = app.vkm.unwrap();
let seat = app.seat.unwrap();
let vpm = app.vpm.as_ref().unwrap();
let vkm = app.vkm.as_ref().unwrap();
let seat = app.seat.as_ref().unwrap();
let pointer: Vp = vpm.create_virtual_pointer(None, &qh, ());
let keyboard: Vk = vkm.create_virtual_keyboard(&seat, &qh, ());
udp_loop(&pointer, &keyboard, event_queue).unwrap();
println!();
let connection = protocol::Connection::new(config);
let data = loop {
match connection.receive_data(DataRequest::KeyMap) {
Some(data) => { break data }
None => {}
}
};
// TODO use shm_open
let f = tempfile::tempfile().unwrap();
let mut buf = BufWriter::new(&f);
buf.write_all(&data[..]).unwrap();
buf.flush().unwrap();
keyboard.keymap(1, f.as_raw_fd(), data.len() as u32);
event_queue.roundtrip(&mut app).unwrap();
udp_loop(&connection, &pointer, &keyboard, event_queue).unwrap();
}
/// main loop handling udp packets
fn udp_loop(pointer: &Vp, keyboard: &Vk, q: EventQueue<App>) -> std::io::Result<()> {
let socket = UdpSocket::bind("0.0.0.0:42069")?;
// we don't care about possible dropped packets for now
let mut buf = [0u8; 21];
fn udp_loop(connection: &protocol::Connection, pointer: &Vp, keyboard: &Vk, q: EventQueue<App>) -> std::io::Result<()> {
loop {
let (_amt, _src) = socket.recv_from(&mut buf)?;
match protocol::Event::decode(buf) {
protocol::Event::Mouse { t, x, y } => {
pointer.motion(t, x, y);
if let Some(event) = connection.receive_event() {
match event {
protocol::Event::Mouse { t, x, y } => { 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 } => { keyboard.key(t, k, u32::from(s)); },
protocol::Event::KeyModifier { mods_depressed, mods_latched, mods_locked, group } => {
keyboard.modifiers(mods_depressed, mods_latched, mods_locked, group);
},
}
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);
},
}
q.flush().unwrap();
}
}
@@ -151,6 +153,19 @@ impl Dispatch<Vp, ()> for App {
}
}
impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
fn event(
_: &mut Self,
_: &wl_keyboard::WlKeyboard,
_: <wl_keyboard::WlKeyboard as wayland_client::Proxy>::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
//
}
}
impl Dispatch<VkManager, ()> for App {
fn event(
_: &mut Self,

View File

@@ -1,11 +1,10 @@
use lan_mouse::protocol;
use memmap::Mmap;
use std::{
env,
fs::File,
io::{BufWriter, Write},
net::{IpAddr, SocketAddr, UdpSocket},
str::FromStr,
os::unix::prelude::AsRawFd,
os::unix::prelude::{AsRawFd, FromRawFd},
};
use wayland_protocols::{
@@ -25,7 +24,6 @@ use wayland_client::{
};
use tempfile;
use trust_dns_resolver::Resolver;
struct App {
running: bool,
@@ -35,15 +33,16 @@ struct App {
surface: Option<wl_surface::WlSurface>,
top_level: Option<xdg_toplevel::XdgToplevel>,
xdg_surface: Option<xdg_surface::XdgSurface>,
socket: UdpSocket,
pointer_constraints: Option<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1>,
rel_pointer_manager: Option<zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1>,
pointer_lock: Option<zwp_locked_pointer_v1::ZwpLockedPointerV1>,
rel_pointer: Option<zwp_relative_pointer_v1::ZwpRelativePointerV1>,
ip: Option<IpAddr>,
connection: protocol::Connection,
}
fn main() {
let config = lan_mouse::config::Config::new("config.toml").unwrap();
let connection = protocol::Connection::new(config);
// establish connection via environment-provided configuration.
let conn = Connection::connect_to_env().unwrap();
@@ -65,26 +64,13 @@ fn main() {
surface: None,
top_level: None,
xdg_surface: None,
socket: UdpSocket::bind("0.0.0.0:42070").expect("couldn't bind to address"),
pointer_constraints: None,
rel_pointer_manager: None,
pointer_lock: None,
rel_pointer: None,
ip: None,
connection,
};
let args: Vec<String> = env::args().collect();
let arg = match args.get(1) {
Some(s) => s.as_str(),
None => "localhost",
};
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
event_queue.roundtrip(&mut app).unwrap();
@@ -97,7 +83,7 @@ fn main() {
app.top_level
.as_ref()
.unwrap()
.set_title("LAN Mouse".into());
.set_title("LAN Mouse Share".into());
app.surface.as_ref().unwrap().commit();
while app.running {
@@ -120,37 +106,20 @@ fn draw(f: &mut File, (width, height): (u32, u32)) {
}
impl App {
fn resolve_host(&mut self, host: &str) {
let resolver = Resolver::from_system_conf().unwrap();
let response = resolver
.lookup_ip(host)
.expect(format!("couldn't resolve {}", host).as_str());
self.ip = response.iter().next();
if let None = self.ip {
panic!("couldn't resolve host: {}!", host)
}
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) {
let e = protocol::Event::Mouse { t: (time), x: (x), y: (y) };
self.send_event(&e);
self.connection.send_event(&e);
}
fn send_button_event(&self, t: u32, b: u32, s: ButtonState) {
let e = protocol::Event::Button { t, b, s };
self.send_event(&e);
self.connection.send_event(&e);
}
fn send_axis_event(&self, t: u32, a: Axis, v: f64) {
let e = protocol::Event::Axis { t, a, v };
self.send_event(&e);
self.connection.send_event(&e);
}
}
@@ -425,20 +394,30 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
_: &Connection,
_: &QueueHandle<Self>,
) {
if let wl_keyboard::Event::Key { serial: _, time, key, state } = event {
if key == 1 {
// ESC key
if let Some(pointer_lock) = app.pointer_lock.as_ref() {
pointer_lock.destroy();
app.pointer_lock = None;
match event {
wl_keyboard::Event::Key { serial: _, time, key, state } => {
if key == 1 {
// ESC key
if let Some(pointer_lock) = app.pointer_lock.as_ref() {
pointer_lock.destroy();
app.pointer_lock = None;
}
if let Some(rel_pointer) = app.rel_pointer.as_ref() {
rel_pointer.destroy();
app.rel_pointer = None;
}
} else {
app.connection.send_event(&protocol::Event::Key{ t: (time), k: (key), s: (state.into_result().unwrap()) });
}
if let Some(rel_pointer) = app.rel_pointer.as_ref() {
rel_pointer.destroy();
app.rel_pointer = None;
}
} else {
app.send_event(&protocol::Event::Key{ t: (time), k: (key), s: (state.into_result().unwrap()) });
}
wl_keyboard::Event::Modifiers { serial: _, mods_depressed, mods_latched, mods_locked, group } => {
app.connection.send_event(&protocol::Event::KeyModifier{ mods_depressed, mods_latched, mods_locked, group });
}
wl_keyboard::Event::Keymap { format:_ , fd, size:_ } => {
let mmap = unsafe { Mmap::map(&File::from_raw_fd(fd.as_raw_fd())).unwrap() };
app.connection.offer_data(protocol::DataRequest::KeyMap, mmap);
}
_ => (),
}
}
}