<NME> libinput.rs
<BEF> ADDFILE
<MSG> First draft of a libinput backend

- Only does DeviceEvent parsing for now
- No way to initialize it

<DFF> @@ -0,0 +1,147 @@
+//! Implementation of input backend trait for types provided by `libinput`
+
+use backend::SeatInternal;
+use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities};
+use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability};
+use input::event::*;
+
+use std::io::Error as IoError;
+use std::collections::hash_map::{DefaultHasher, HashMap};
+use std::hash::{Hash, Hasher};
+
+pub struct LibinputInputBackend {
+    context: Libinput,
+    devices: Vec<Device>,
+    seats: HashMap<LibinputSeat, Seat>,
+    handler: Option<Box<InputHandler<LibinputInputBackend> + 'static>>,
+}
+
+impl InputBackend for LibinputInputBackend {
+    type InputConfig = [Device];
+    type EventError = IoError;
+
+    fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
+        if self.handler.is_some() {
+            self.clear_handler();
+        }
+        for seat in self.seats.values() {
+            handler.on_seat_created(&seat);
+        }
+        self.handler = Some(Box::new(handler));
+    }
+
+    fn get_handler(&mut self) -> Option<&mut InputHandler<Self>> {
+        self.handler
+            .as_mut()
+            .map(|handler| handler as &mut InputHandler<Self>)
+    }
+
+    fn clear_handler(&mut self) {
+        if let Some(mut handler) = self.handler.take() {
+            for seat in self.seats.values() {
+                handler.on_seat_destroyed(&seat);
+            }
+        }
+    }
+
+    fn input_config(&mut self) -> &mut Self::InputConfig {
+        &mut self.devices
+    }
+
+    fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> {
+        // FIXME later.
+        // This will be doable with the hardware cursor api and probably some more cases
+        Err(())
+    }
+
+    fn dispatch_new_events(&mut self) -> Result<(), IoError> {
+        self.context.dispatch()?;
+        for event in &mut self.context {
+            match event {
+                Event::Device(device_event) => {
+                    use input::event::device::*;
+                    match device_event {
+                        DeviceEvent::Added(device_added_event) => {
+                            let added = device_added_event.into_event().device();
+
+                            let new_caps = SeatCapabilities {
+                                pointer: added.has_capability(DeviceCapability::Pointer),
+                                keyboard: added.has_capability(DeviceCapability::Keyboard),
+                                touch: added.has_capability(DeviceCapability::Touch),
+                            };
+
+                            let device_seat = added.seat();
+                            self.devices.push(added);
+
+                            let contains = self.seats.contains_key(&device_seat);
+                            if contains {
+                                let old_seat = self.seats.get_mut(&device_seat).unwrap();
+                                {
+                                    let caps = old_seat.capabilities_mut();
+                                    caps.pointer = new_caps.pointer || caps.pointer;
+                                    caps.keyboard = new_caps.keyboard || caps.keyboard;
+                                    caps.touch = new_caps.touch || caps.touch;
+                                }
+                                if let Some(ref mut handler) = self.handler {
+                                    handler.on_seat_changed(old_seat);
+                                }
+                            } else {
+                                let mut hasher = DefaultHasher::default();
+                                device_seat.hash(&mut hasher);
+                                self.seats.insert(device_seat.clone(), Seat::new(hasher.finish(), new_caps));
+                                if let Some(ref mut handler) = self.handler {
+                                    handler.on_seat_created(self.seats.get(&device_seat).unwrap());
+                                }
+                            }
+                        },
+                        DeviceEvent::Removed(device_removed_event) => {
+                            let removed = device_removed_event.into_event().device();
+
+                            // remove device
+                            self.devices.retain(|dev| *dev == removed);
+
+                            let device_seat = removed.seat();
+
+                            // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
+                            if let Some(seat) = self.seats.get_mut(&device_seat) {
+                                let caps = seat.capabilities_mut();
+                                caps.pointer = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Pointer));
+                                caps.keyboard = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Keyboard));
+                                caps.touch = self.devices.iter().any(|x| x.has_capability(DeviceCapability::Touch));
+                            } else {
+                                //TODO is this the best we can do?
+                                panic!("Seat changed that was never created")
+                            }
+
+                            // check if the seat has any other devices
+                            if !self.devices.iter().any(|x| x.seat() == device_seat) {
+                                // it has not, lets destroy it
+                                if let Some(seat) = self.seats.remove(&device_seat) {
+                                    if let Some(ref mut handler) = self.handler {
+                                        handler.on_seat_destroyed(&seat);
+                                    }
+                                } else {
+                                    //TODO is this the best we can do?
+                                    panic!("Seat destroyed that was never created");
+                                }
+                            } else {
+                                // it has, notify about updates
+                                if let Some(ref mut handler) = self.handler {
+                                    handler.on_seat_changed(self.seats.get(&device_seat).unwrap());
+                                }
+                            }
+                        },
+                    }
+                    if let Some(ref mut handler) = self.handler {
+                       handler.on_input_config_changed(&mut self.devices);
+                    }
+                },
+                Event::Touch(touch_event) => {},
+                Event::Keyboard(keyboard_event) => {},
+                Event::Pointer(pointer_event) => {},
+                _ => {}, //FIXME: What to do with the rest.
+            }
+        };
+        Ok(())
+    }
+}

First draft of a libinput backend