extern crate xcb; use std::iter::{Iterator}; use std::{thread, time}; use std::sync::Arc; use std::ptr::{null, null_mut}; use std::slice::from_raw_parts_mut; pub fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) { unsafe { let id = libc::shmget( libc::IPC_PRIVATE , size * 4 , libc::IPC_CREAT | 0o744 ); let ptr = libc::shmat(id, null(), 0); (id as i32, from_raw_parts_mut(ptr as *mut u32, size)) } } fn main() { let points: &[xcb::Point] = &[ xcb::Point::new(10, 10) , xcb::Point::new(10, 20) , xcb::Point::new(20, 10) , xcb::Point::new(20, 20) ]; let polyline: &[xcb::Point] = &[ xcb::Point::new(50, 10 ) // rest of points are relative , xcb::Point::new( 5, 20 ) , xcb::Point::new(25, -20) , xcb::Point::new(10, 10 ) ]; let segments: &[xcb::Segment] = &[ xcb::Segment::new(100, 10, 140, 30) , xcb::Segment::new(110, 25, 130, 60) ]; let rectangles: &[xcb::Rectangle] = &[ xcb::Rectangle::new(10, 50, 40, 20) , xcb::Rectangle::new(80, 50, 10, 40) ]; let arcs: &[xcb::Arc] = &[ xcb::Arc::new(10, 100, 60, 40, 0, 90 << 6) , xcb::Arc::new(90, 100, 55, 40, 0, 270 << 6) ]; let (conn, screen_num) = { let (conn, screen_num) = xcb::Connection::connect(None).unwrap(); (Arc::new(conn), screen_num) }; let setup = conn.get_setup(); let screen = setup.roots().nth(screen_num as usize).unwrap(); let (shmid, shm) = getshm(150 * 150); let shmseg = conn.generate_id(); xcb::shm::attach(&conn, shmseg, shmid as u32, false); unsafe { libc::shmctl(shmid, libc::IPC_RMID, null_mut()); } let foreground = conn.generate_id(); let pix = conn.generate_id(); xcb::create_gc( &conn , foreground , screen.root() , &[ (xcb::GC_FOREGROUND, screen.black_pixel()) , (xcb::GC_GRAPHICS_EXPOSURES, 0) ] ); let window = conn.generate_id(); let values = [ ( xcb::CW_BACK_PIXEL, screen.white_pixel() ) , ( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_KEY_PRESS | xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_PROPERTY_CHANGE ) ]; xcb::create_window( &conn , xcb::COPY_FROM_PARENT as u8 , window , screen.root() , 0, 0, 150, 150, 0 , xcb::WINDOW_CLASS_INPUT_OUTPUT as u16 , screen.root_visual() , &values); xcb::shm::create_pixmap( &conn , pix , window , 150, 150 , screen.root_depth() , shmseg , 0 ); xcb::map_window(&conn, window); { let conn = conn.clone(); thread::spawn(move || { let mut blink = false; let mut i = 0; loop { let title = if blink { "Basic Threaded Window ;-)" } else { "Basic Threaded Window :-)" }; shm[i] = 0xFFFFFF; i = (i + 1) % (150 * 150); let c = xcb::change_property_checked( &conn , xcb::PROP_MODE_REPLACE as u8 , window , xcb::ATOM_WM_NAME , xcb::ATOM_STRING , 8 , title.as_bytes() ); xcb::copy_area( &conn , pix , window , foreground , 0, 0, 0, 0 , 150, 150); if conn.has_error().is_err() || c.request_check().is_err() { break; } blink = !blink; thread::sleep(time::Duration::from_millis(500)); } }); } conn.flush(); loop { let event = conn.wait_for_event(); match event { None => break, Some(event) => { match event.response_type() & !0x80 { xcb::PROPERTY_NOTIFY => { let prop_notify: &xcb::PropertyNotifyEvent = unsafe { xcb::cast_event(&event) }; if prop_notify.atom() == xcb::ATOM_WM_NAME { // retrieving title let cookie = xcb::get_property( &conn , false , window , xcb::ATOM_WM_NAME , xcb::ATOM_STRING , 0, 1024); if let Ok(reply) = cookie.get_reply() { let r = reply.value(); let r = std::str::from_utf8(r).unwrap(); println!( "title changed to \"{}\"", r); } } }, xcb::EXPOSE => { xcb::poly_point( &conn , xcb::COORD_MODE_ORIGIN as u8 , window , foreground , &points ); xcb::poly_line( &conn , xcb::COORD_MODE_PREVIOUS as u8 , window , foreground , &polyline ); xcb::poly_segment( &conn , window , foreground , &segments ); xcb::poly_rectangle( &conn , window , foreground , &rectangles ); xcb::poly_arc( &conn , window , foreground , &arcs ); conn.flush(); }, xcb::KEY_PRESS => { let key_press: &xcb::KeyPressEvent = unsafe { xcb::cast_event(&event) }; println!("Key '{}' pressed", key_press.detail()); if key_press.detail() == 0x18 { // Q (on qwerty) break; } }, _ => {}, } } } } }