extern crate byteorder;
extern crate tempfile;
#[macro_use(event_enum)]
extern crate wayland_client;
use std::cmp::min;
use std::io::Write;
use std::os::unix::io::AsRawFd;
use byteorder::{NativeEndian, WriteBytesExt};
use wayland_client::protocol::{wl_compositor, wl_keyboard, wl_pointer, wl_seat, wl_shell, wl_shm};
use wayland_client::{Display, Filter, GlobalManager};
event_enum!(
Events |
Pointer => wl_pointer::WlPointer,
Keyboard => wl_keyboard::WlKeyboard
);
fn main() {
let display = Display::connect_to_env().unwrap();
let mut event_queue = display.create_event_queue();
let attached_display = (*display).clone().attach(event_queue.get_token());
let globals = GlobalManager::new(&attached_display);
event_queue.sync_roundtrip(|_, _| unreachable!()).unwrap();
let buf_x: u32 = 320;
let buf_y: u32 = 240;
let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");
for i in 0..(buf_x * buf_y) {
let x = (i % buf_x) as u32;
let y = (i / buf_x) as u32;
let r: u32 = min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
let _ = tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
}
let _ = tmp.flush();
let compositor = globals
.instantiate_exact::<wl_compositor::WlCompositor>(1)
.unwrap();
let surface = compositor.create_surface();
let shm = globals.instantiate_exact::<wl_shm::WlShm>(1).unwrap();
let pool = shm.create_pool(
tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32, );
let buffer = pool.create_buffer(
0, buf_x as i32, buf_y as i32, (buf_x * 4) as i32, wl_shm::Format::Argb8888, );
let shell = globals
.instantiate_exact::<wl_shell::WlShell>(1)
.expect("Compositor does not support wl_shell");
let shell_surface = shell.get_shell_surface(&surface);
shell_surface.assign_mono(|shell_surface, event| {
use wayland_client::protocol::wl_shell_surface::Event;
if let Event::Ping { serial } = event {
shell_surface.pong(serial);
}
});
shell_surface.set_toplevel();
surface.attach(Some(&buffer), 0, 0);
surface.commit();
let common_filter = Filter::new(move |event, _| match event {
Events::Pointer { event, .. } => match event {
wl_pointer::Event::Enter {
surface_x, surface_y, ..
} => {
println!("Pointer entered at ({}, {}).", surface_x, surface_y);
}
wl_pointer::Event::Leave { .. } => {
println!("Pointer left.");
}
wl_pointer::Event::Motion {
surface_x, surface_y, ..
} => {
println!("Pointer moved to ({}, {}).", surface_x, surface_y);
}
wl_pointer::Event::Button { button, state, .. } => {
println!("Button {} was {:?}.", button, state);
}
_ => {}
},
Events::Keyboard { event, .. } => match event {
wl_keyboard::Event::Enter { .. } => {
println!("Gained keyboard focus.");
}
wl_keyboard::Event::Leave { .. } => {
println!("Lost keyboard focus.");
}
wl_keyboard::Event::Key { key, state, .. } => {
println!("Key with id {} was {:?}.", key, state);
}
_ => (),
},
});
let mut pointer_created = false;
let mut keyboard_created = false;
globals
.instantiate_exact::<wl_seat::WlSeat>(1)
.unwrap()
.assign_mono(move |seat, event| {
use wayland_client::protocol::wl_seat::{Capability, Event as SeatEvent};
if let SeatEvent::Capabilities { capabilities } = event {
if !pointer_created && capabilities.contains(Capability::Pointer) {
pointer_created = true;
seat.get_pointer().assign(common_filter.clone());
}
if !keyboard_created && capabilities.contains(Capability::Keyboard) {
keyboard_created = false;
seat.get_keyboard().assign(common_filter.clone());
}
}
});
event_queue
.sync_roundtrip(|_, _| { })
.unwrap();
loop {
event_queue
.dispatch(|_, _| { })
.unwrap();
}
}