Skip to content

Instantly share code, notes, and snippets.

@sbourdeauducq
Last active April 19, 2020 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbourdeauducq/185d9b67b9826cdad522e59e6a5f073d to your computer and use it in GitHub Desktop.
Save sbourdeauducq/185d9b67b9826cdad522e59e6a5f073d to your computer and use it in GitHub Desktop.
Computer graphics like it's MS-DOS
// Small example of drawing on a Linux graphics screen, with relatively sane graphics
// primitives and a minimal amount of wacko libraries.
// See: The Unix-Haters Handbook, chapter 7 "The X-Windows Disaster"
extern crate xcb;
extern crate cairo;
extern crate cairo_sys;
use std::mem::transmute;
fn find_visual(conn: &xcb::Connection, visual: xcb::ffi::xcb_visualid_t) -> Option<xcb::Visualtype> {
let setup: xcb::Setup = conn.get_setup();
for screen in setup.roots() {
let d_iter: xcb::DepthIterator = screen.allowed_depths();
for depth in d_iter {
for vis in depth.visuals() {
if visual == vis.visual_id() {
return Some(vis)
}
}
}
}
None
}
fn main() {
let (conn, screen_num) = xcb::Connection::connect(None).unwrap();
let setup = conn.get_setup();
let screen = setup.roots().nth(screen_num as usize).unwrap();
let win = conn.generate_id();
xcb::create_window(&conn,
xcb::COPY_FROM_PARENT as u8,
win,
screen.root(),
0, 0,
1024, 768,
10,
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
screen.root_visual(), &[
(xcb::CW_BACK_PIXEL, screen.white_pixel()),
(xcb::CW_EVENT_MASK,
xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_KEY_PRESS),
]
);
xcb::map_window(&conn, win);
conn.flush();
let cairo_conn = cairo::XCBConnection(unsafe { transmute(conn.get_raw_conn()) });
let cairo_win = cairo::XCBDrawable(win);
let visual = find_visual(&conn, screen.root_visual());
let cairo_visual = cairo::XCBVisualType(unsafe { transmute(&mut visual.unwrap().base) });
let surface = cairo::XCBSurface::create(
&cairo_conn,
&cairo_win,
&cairo_visual,
1024,
768).unwrap();
loop {
let event = conn.wait_for_event();
match event {
None => { break; }
Some(event) => {
let r = event.response_type() & !0x80;
match r {
xcb::EXPOSE => {
let cr = cairo::Context::new(&surface);
cr.scale(120.0, 120.0);
cr.set_line_width(0.1);
cr.set_source_rgb(0.0, 0.0, 0.0);
cr.rectangle(0.25, 0.25, 0.5, 0.5);
cr.stroke();
conn.flush();
},
xcb::KEY_PRESS => {
let key_press: &xcb::KeyPressEvent = unsafe {
xcb::cast_event(&event)
};
let key_code = key_press.detail();
// q to exit
if key_code == 24 {
break;
}
},
_ => {}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment