LSQ7OPL7Z5WJDO7ZZS3D4UPMEEWUUF2LNQ3FZUWWFUVZEXA7CIOAC T6CZHRR6VHQWOPHF6QNK46X3KWAUHOJ422LOYMQP4YJ3FEVK4O2QC LBG7DYYI7WCROF4GRYVXDXIV2465E5KPGQVZTFUPTZQBNZZ3LNYAC KWR2TS2D7YN4LCGMQZ35V4WBLQDHAVSZJV3SZAIR5HQRSJAWLWCQC K3I54HXNNCTEA7L6UGWIVBFB5TPZVZZXDBRSR2YZDIKREXQVWRIQC 7RMAZDLQ6FEEQGUUAIVEM4X2VME7IUUZMEJMMV3H46U3UKO4BODQC LKAUS67VU5SLG5O5MTSO6N4VVT5OB2X4VNR6HYLIJ3ZOAXRQ4Q2QC WX2TUKTGV5XK5F5GMEUDU2IHT3LRW2IQRE2BRAH76CTJIVUFMQCAC R5ZNUPT57LKKPGEWOAHLSRE4VA47SDZD33OXCFFGVIXJLWXI5Y7AC JVO3ABY7VTFBUPUEPNXVSGWLCBJLPDHLSLZJEW2LSEOFUR5Z4RIAC JUNCSETUHRAPHZYVBESYW4LTKL6EW3X4G73ILT736PWDXB45Z6GQC CPONUGXG2EFQI5VTBCP74GUGHWNORQ7FCKIOVXOIKGIYWZE66UEAC use io;use elemeld::Elemeld;use serde;use std::net;pub type Index = u8;#[derive(Clone, Serialize, Deserialize, Debug)]pub struct Cluster {screens: Vec<Screen>,focus: Index,pos: Dimensions,}impl Cluster {pub fn new(width: i32, height: i32, x: i32, y: i32) -> Self {Cluster {screens: vec![Screen::new(width, height)],focus: 0,pos: Dimensions { x: x , y: y },}}pub fn filter_host_event<H>(&mut self, host: &H) -> Option<io::NetEvent>where H: io::HostInterface{match host.recv_event() {Some(io::HostEvent::Motion(event)) => {if event.dx != 0 || event.dy != 0 {let (focus, x, y) = (self.focus, self.pos.x + event.dx, self.pos.y + event.dy);self.refocus(host, focus, x, y);Some(io::NetEvent::Focus(self.focus, io::PositionEvent {x: self.pos.x, y: self.pos.y,}))} else {None}},Some(event) => {if !self.locally_focused() {match event {io::HostEvent::Button(event) => Some(io::NetEvent::Button(event)),io::HostEvent::Key(event) => Some(io::NetEvent::Key(event)),_ => None,}} else {None}}None => None,}}pub fn filter_net_event(&mut self, event: io::NetEvent) -> Option<io::HostEvent> {if self.locally_focused() {match event {io::NetEvent::Button(event) => Some(io::HostEvent::Button(event)),io::NetEvent::Key(event) => Some(io::HostEvent::Key(event)),_ => None,}} else {return None}}fn locally_focused(&self) -> bool {self.screens[self.focus as usize].is_local()}pub fn refocus<H>(&mut self, host: &H, focus: Index, x: i32, y: i32) whereH: io::HostInterface{let (focus, x, y) = self.normalize_focus(focus, x, y);let was_focused = self.locally_focused();self.focus = focus;self.pos.x = x;self.pos.y = y;if self.locally_focused() {if !was_focused {host.send_event(io::HostEvent::Position(io::PositionEvent {x: self.pos.x, y: self.pos.y,}));host.ungrab_cursor();host.ungrab_keyboard();}} else {if was_focused {host.grab_cursor();host.grab_keyboard();}}}/** Walk through the screens untill the x and y are contained within a screen*/fn normalize_focus(&self, focus: Index, x: i32, y: i32) -> (Index, i32, i32) {let (focus, x) = self.normalize_x(focus, x);let (focus, y) = self.normalize_y(focus, y);(focus, x, y)}fn normalize_x(&self, focus: Index, x: i32) -> (Index, i32) {let screen = self.screens[focus as usize];if self.pos.x < 20 {match screen.edges.left {Some(focus) => return self.normalize_x(focus, x + screen.size.x - 40),None => (),}} else if self.pos.x >= screen.size.x - 20 {match screen.edges.right {Some(focus) => return self.normalize_x(focus, x - screen.size.x + 40),None => (),}}(focus, x)}fn normalize_y(&self, focus: Index, y: i32) -> (Index, i32) {let screen = self.screens[focus as usize];if self.pos.y < 20 {match screen.edges.left {Some(focus) => return self.normalize_y(focus, y + screen.size.y - 40),None => (),}} else if self.pos.y >= screen.size.y - 20 {match screen.edges.right {Some(focus) => return self.normalize_y(focus, y - screen.size.y + 40),None => (),}}(focus, y)}/*** Add a new screen to the far right of the cluster*/fn add(&mut self, mut new_screen: Screen) {let new_index = self.screens.len() as Index;let mut index = 0 as Index;loop {let screen = &mut self.screens[index as usize];index = match screen.edges.right {Some(index) => index,None => {screen.edges.right = Some(new_index);new_screen.edges.left = Some(index);break;}}}self.screens.push(new_screen);}/*** Attempt to merge two clusters together*/pub fn merge(&mut self, other: &Self, src: net::SocketAddr) {'outer: for other_screen in &other.screens {// Interpret other's None addresses as the src addresslet other_addr = match other_screen.addr {Some(addr) => addr.0,None => src,};for screen in &mut self.screens {// Interpret self's None addresses as a null address// TODO: Use getifaddrs to lookup matching interface addresslet screen_addr = match screen.addr {Some(addr) => addr.0,None => net::SocketAddr::V4(net::SocketAddrV4::new(net::Ipv4Addr::new(0, 0, 0, 0), 0)),};// If same address, replace screen with other_screenif screen_addr == other_addr {// TODO: Merge screen properties// *screen = *other_screen;continue 'outer;}}// If new address, add new screenlet mut new_screen = *other_screen;new_screen.addr = Some(SocketAddr(src));self.add(new_screen);}}/*** Replace an existing cluster with a new cluster*/pub fn replace(&mut self, other: &Self) {*self = other.clone();}}#[derive(Copy, Clone, Serialize, Deserialize, Debug)]struct Screen {size: Dimensions,edges: Edges,addr: Option<SocketAddr>,}impl Screen {pub fn new(width: i32, height: i32) -> Self {Screen {addr: None, // None implies local machinesize: Dimensions { x: width, y: height },edges: Edges {top: None,right: None,bottom: None,left: None}}}pub fn is_local(&self) -> bool {self.addr.is_none()}}#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]struct SocketAddr(net::SocketAddr);impl serde::Serialize for SocketAddr {fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>where S: serde::Serializer{serializer.visit_str(&format!("{}", self.0))}}impl serde::Deserialize for SocketAddr {fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>where D: serde::Deserializer{struct SocketAddrVisitor;impl serde::de::Visitor for SocketAddrVisitor {type Value = SocketAddr;fn visit_str<E>(&mut self, val: &str) -> Result<Self::Value, E>where E: serde::de::Error,{match val.parse::<net::SocketAddr>() {Ok(addr) => Ok(SocketAddr(addr)),Err(_) => Err(serde::de::Error::syntax("expected socket address")),}}}deserializer.visit(SocketAddrVisitor)}}#[derive(Copy, Clone, Serialize, Deserialize, Debug)]struct Dimensions {x: i32,y: i32,}#[derive(Copy, Clone, Serialize, Deserialize, Debug)]struct Edges {top: Option<Index>,right: Option<Index>,bottom: Option<Index>,left: Option<Index>,}
use io;use cluster::Cluster;pub struct Elemeld<H, N> whereH: io::HostInterface,N: io::NetInterface,{host: H,net: N,state: State,cluster: Cluster,}#[derive(Debug, Copy, Clone)]enum State {Connecting,Ready,Connected,}impl<H, N> Elemeld<H, N> whereH: io::HostInterface,N: io::NetInterface,{pub fn new(host: H, net: N) -> Self {let (width, height) = host.screen_size();let (x, y) = host.cursor_pos();Elemeld {host: host,net: net,state: State::Connecting,cluster: Cluster::new(width, height, x, y),}}pub fn host_event(&mut self) {match self.state {State::Connected => match self.cluster.filter_host_event(&self.host) {Some(event) => { self.net.send_to_all(&[event]); },None => (),},_ => (),}}pub fn net_event(&mut self) {match self.net.recv_from() {Some((events, addr)) => for event in events {match event {// Initialization eventsio::NetEvent::Connect(cluster) => {self.cluster.merge(&cluster, addr);self.net.send_to_all(&[io::NetEvent::Cluster(self.cluster.clone())]);self.state = State::Connected;},io::NetEvent::Cluster(cluster) => {self.cluster.replace(&cluster);self.state = State::Connected;},// Global eventsio::NetEvent::Focus(focus, pos) => {self.cluster.refocus(&self.host, focus, pos.x, pos.y);self.host.send_event(io::HostEvent::Position(io::PositionEvent {x: pos.x,y: pos.y,}));},// event => match self.cluster.filter_net_event(event) {// Some(event) => { self.host.send_event(event); },// None => (),// },_ => (),}},None => (),}match self.state {State::Connecting => {self.net.send_to_all(&[io::NetEvent::Connect(self.cluster.clone())]);self.state = State::Ready;},_ => ()}}}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]pub enum Button { Left, Right, Middle }#[allow(dead_code)]#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]pub enum Key {ControlL, ControlR,AltL, AltR,ShiftL, ShiftR,SuperL, SuperR,CapsLock,
Space, Enter, Tab,Backspace, Delete,Num0, Num1, Num2, Num3, Num4,Num5, Num6, Num7, Num8, Num9,A, B, C, D, E, F, G, H,I, J, K, L, M, N, O, P,Q, R, S, T, U, V, W, X,Y, Z,F1, F2, F3, F4,F5, F6, F7, F8,F9, F10, F11, F12,
pub trait NetInterface {fn send_to(&self, events: &[NetEvent], addr: &SocketAddr) -> Option<usize>;fn send_to_all(&self, events: &[NetEvent]) -> Option<usize>;fn recv_from(&self) -> Option<(Vec<NetEvent>, SocketAddr)>;
pub enum NetEvent {Connect(cluster::Cluster),Cluster(cluster::Cluster),Focus(cluster::Index, PositionEvent),Button(ButtonEvent),Key(KeyEvent),}#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]pub enum Button { Left, Right, Middle }#[derive(Serialize, Deserialize, Debug)]
use io::{self, NetInterface};use mio;use serde_json;use std::str;use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};use std::cell::Cell;pub struct IpInterface {config: Config,socket: mio::udp::UdpSocket,out_packets: Cell<usize>,in_packets: Cell<usize>,}pub struct Config {pub server_addr: Ipv4Addr,pub multicast_addr: Ipv4Addr,pub port: u16}impl IpInterface {pub fn open(config: Config) -> Self {let socket = mio::udp::UdpSocket::v4().unwrap();socket.set_multicast_loop(false).unwrap();socket.join_multicast(&mio::IpAddr::V4(config.multicast_addr)).unwrap();socket.bind(&SocketAddr::V4(SocketAddrV4::new(config.server_addr, config.port))).unwrap();IpInterface {config: config,socket: socket,out_packets: Cell::new(0),in_packets: Cell::new(0),}}}impl NetInterface for IpInterface {fn send_to(&self, events: &[io::NetEvent], addr: &SocketAddr) -> Option<usize> {let id = self.out_packets.get();let msg = serde_json::to_string(&(id, events)).unwrap();println!("=> {}", msg);match self.socket.send_to(msg.as_bytes(), &addr).unwrap() {Some(size) => {self.out_packets.set(id + 1);Some(size)},None => {println!("Failed to send: {}", msg);None},}}fn send_to_all(&self, events: &[io::NetEvent]) -> Option<usize> {let multicast_addr = SocketAddr::V4(SocketAddrV4::new(self.config.multicast_addr, self.config.port));self.send_to(events, &multicast_addr)}fn recv_from(&self) -> Option<(Vec<io::NetEvent>, SocketAddr)> {let mut buf = [0; 1024];match self.socket.recv_from(&mut buf).unwrap() {Some((len, addr)) => {let msg = str::from_utf8(&buf[..len]).unwrap();println!("<= {}", msg);let (id, events): (usize, Vec<io::NetEvent>) = serde_json::from_str(msg).unwrap();let expected_id = self.in_packets.get();if id < expected_id {println!("^ out of sync packet");} else {if id > expected_id {println!("^ lost {} packets", id - expected_id)}self.in_packets.set(id + 1);}Some((events, addr))},None => None,}}}/** FIXME(Future):* Method delegation: https://github.com/rust-lang/rfcs/pull/1406*/impl mio::Evented for IpInterface {fn register(&self, selector: &mut mio::Selector, token: mio::Token, interest: mio::EventSet, opts: mio::PollOpt) -> ::std::io::Result<()> {self.socket.register(selector, token, interest, opts)}fn reregister(&self, selector: &mut mio::Selector, token: mio::Token, interest: mio::EventSet, opts: mio::PollOpt) -> ::std::io::Result<()> {self.socket.reregister(selector, token, interest, opts)}fn deregister(&self, selector: &mut mio::Selector) -> ::std::io::Result<()> {self.socket.deregister(selector)}}
struct Server {config: Config,host: X11Host,net: UdpSocket,// Screenfocused: bool,x: i32, y: i32,width: i32, height: i32,// Debugout_packets: Cell<usize>,in_packets: Cell<usize>,
event_loop.run(&mut manager).unwrap();
// Setup UDP socketlet net = UdpSocket::v4().unwrap();net.set_multicast_loop(false).unwrap();net.join_multicast(&IpAddr::V4(config.addr)).unwrap();net.bind(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), config.port))).unwrap();// Listen for UDP connections
// Setup net interfacelet net = IpInterface::open(config);
// Query information for local screenlet (x, y) = host.cursor_pos();let (width, height) = host.screen_size();Server {config: config,host: host,net: net,focused: true,x: x, y: y,width: width, height: height,out_packets: Cell::new(0),in_packets: Cell::new(0),}}// Host functionsfn unfocus(&mut self) {if self.focused {self.host.grab_cursor();self.host.grab_keyboard();self.focused = false;}}fn focus(&mut self) {if !self.focused {self.host.send_position_event(io::PositionEvent {x: self.x,y: self.y,});self.host.ungrab_cursor();self.host.ungrab_keyboard();self.focused = true;}}// Net functionsfn send_to(&self, events: &[io::Event], addr: &SocketAddr) -> Option<usize> {let id = self.out_packets.get();let msg = serde_json::to_string(&(id, events)).unwrap();// Debugprintln!("=> {}", msg);self.out_packets.set(self.out_packets.get() + 1);self.net.send_to(msg.as_bytes(), &addr).unwrap()}fn send_to_all(&self, events: &[io::Event]) -> Option<usize> {let multicast_addr = SocketAddr::V4(SocketAddrV4::new(self.config.addr, self.config.port));self.send_to(events, &multicast_addr)}fn recv_from(&self) -> Option<(Vec<io::Event>, SocketAddr)> {let mut buf = [0; 256];match self.net.recv_from(&mut buf).unwrap() {Some((len, addr)) => {let msg = str::from_utf8(&buf[..len]).unwrap();let (id, events): (usize, Vec<io::Event>) = serde_json::from_str(msg).unwrap();
// Debugprintln!("<= {}", msg);let expected_id = self.in_packets.get();if id < expected_id {println!("^ old packet");None} else {if id > expected_id {println!("^ lost {} packets", id - expected_id)}self.in_packets.set(id + 1);Some((events, addr))}},None => None,}
EventManager { elemeld: Elemeld::new(host, net) }
X11_EVENT => match self.host.recv_event() {Some(event) => match event {io::Event::Motion(event) => {self.x += event.dx;self.y += event.dy;if self.x <= 0 {// TODO: Check leftself.unfocus();} else if self.x >= self.width - 1 {// TODO: Check rightself.unfocus();} else if self.y <= 0 {// TODO: Check topself.unfocus();} else if self.y >= self.height - 1 {// TODO: Check bottomself.unfocus();} else {self.focus();}self.send_to_all(&[io::Event::Position(io::PositionEvent {x: self.x,y: self.y,})]);},event => if !self.focused {self.send_to_all(&[event]);},},None => (),},NET_EVENT => match self.recv_from() {Some((events, addr)) => for event in events {match event {io::Event::Position(event) => {self.x = event.x;self.y = event.y;self.host.send_position_event(event);},event => if self.focused {self.host.send_event(event);},}},None => (),},
HOST_EVENT => self.elemeld.host_event(),NET_EVENT => self.elemeld.net_event(),
io::Event::Position(event) => self.send_position_event(event),io::Event::Motion(event) => self.send_motion_event(event),io::Event::Button(event) => self.send_button_event(event),io::Event::Key(event) => self.send_key_event(event),
io::HostEvent::Position(event) => self.send_position_event(event),io::HostEvent::Motion(event) => self.send_motion_event(event),io::HostEvent::Button(event) => self.send_button_event(event),io::HostEvent::Key(event) => self.send_key_event(event),