You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
7.4 KiB
202 lines
7.4 KiB
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;
|
|
}
|
|
},
|
|
|
|
_ => {},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|