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) where
H: 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 address
let 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 address
let 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_screen
if screen_addr == other_addr {
// TODO: Merge screen properties
// *screen = *other_screen;
continue 'outer;
}
}
// If new address, add new screen
let 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 machine
size: 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> where
H: 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> where
H: 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 events
io::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 events
io::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,
// Screen
focused: bool,
x: i32, y: i32,
width: i32, height: i32,
// Debug
out_packets: Cell<usize>,
in_packets: Cell<usize>,
event_loop.run(&mut manager).unwrap();
// Setup UDP socket
let 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 interface
let net = IpInterface::open(config);
// Query information for local screen
let (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 functions
fn 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 functions
fn 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();
// Debug
println!("=> {}", 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();
// Debug
println!("<= {}", 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 left
self.unfocus();
} else if self.x >= self.width - 1 {
// TODO: Check right
self.unfocus();
} else if self.y <= 0 {
// TODO: Check top
self.unfocus();
} else if self.y >= self.height - 1 {
// TODO: Check bottom
self.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),