Browse Source

very basic rust statusbar

Getty Ritter 5 years ago
commit
c14dd913d4
6 changed files with 603 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 208 0
      Cargo.lock
  3. 20 0
      Cargo.toml
  4. 3 0
      build.rs
  5. 154 0
      src/main.rs
  6. 215 0
      src/window.rs

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/target
+**/*.rs.bk*~
+*~

+ 208 - 0
Cargo.lock

@@ -0,0 +1,208 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bitflags"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cairo-rs"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cairo-sys-rs"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "glib"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "glib-sys"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "gobject-sys"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pango"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pango-sys"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pangocairo"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pangocairo-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pangocairo-sys"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "time"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "x11"
+version = "2.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "xsamp"
+version = "0.1.0"
+dependencies = [
+ "cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pangocairo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e09d8a818b2ccc8983f04d95a9350c3cf8d24cc456cedca3b88fa3a81fdc0e2"
+"checksum cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fa13914fdc013387afa771f554f2f71d6ae931f4e5be9246c337d60c3dc484"
+"checksum glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e8fdc159c196a5dfa53a92929ac4c10c8a6637ffb43951f3fff89c2cd2365"
+"checksum glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bda542f3caee39a027638e9644ff89204101ad916fd7370b585ad2c5fc97e61"
+"checksum gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e05a14290d3dc255223cba51db4b0f3da438d5250657996fa99b2a30faf43e"
+"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
+"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
+"checksum pango 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e36b55d7cd522bd183efeb3dfabc547bda1f26eadf8a1241dac09ab3fd3242c"
+"checksum pango-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "747ab9cd4d537e6dc5ef0e4308c10dde8b706673b0237fed4e056b8d2c0b23c8"
+"checksum pangocairo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "706e885b46a16ba96f46f3c8d880ca6082c2c62693b75f3d167bd3aa4e34b0d4"
+"checksum pangocairo-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "868310e83da5269323c28bd47b641557d032426f396cddfa45e247ff44da9a12"
+"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
+"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+"checksum x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39697e3123f715483d311b5826e254b6f3cfebdd83cf7ef3358f579c3d68e235"

+ 20 - 0
Cargo.toml

@@ -0,0 +1,20 @@
+[package]
+name = "xsamp"
+version = "0.1.0"
+authors = ["Getty Ritter <samothes@infinitenegativeutility.com>"]
+edition = "2018"
+
+[dependencies]
+cairo-rs = "*"
+pango = "*"
+pangocairo = "*"
+time = "*"
+libc = "*"
+
+[dependencies.cairo-sys-rs]
+version = "*"
+features = ["xlib"]
+
+[dependencies.x11]
+version = "*"
+features = ["xlib", "xinput"]

+ 3 - 0
build.rs

@@ -0,0 +1,3 @@
+fn main() {
+    println!("cargo:rustc-flags=-l X11");
+}

+ 154 - 0
src/main.rs

@@ -0,0 +1,154 @@
+mod window;
+
+use x11::xlib;
+use x11::xinput2;
+
+use std::ffi::CString;
+use std::os::raw::{c_int,c_uchar};
+use std::ptr;
+
+use pango::LayoutExt;
+
+use window::{Event,Window};
+
+fn main() {
+    unsafe {
+        let mut w = Window::create();
+        w.change_property("_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DOCK");
+
+        {
+            let prop = w.intern("_NET_WM_STRUT_PARTIAL");
+            let val = [
+                0i64, 0, 36, 0,
+                0, 0, 0,  0,
+                0, 3840, 0, 0,
+            ];
+            xlib::XChangeProperty(
+                w.display,
+                w.window,
+                prop,
+                xlib::XA_CARDINAL,
+                32,
+                xlib::PropModeReplace,
+                std::mem::transmute(val.as_ptr()),
+                val.len() as c_int,
+            );
+        }
+
+        {
+            let prop = w.intern("_NET_WM_STRUT");
+            let val = &[
+                0i64, 0, 36, 0,
+            ];
+            xlib::XChangeProperty(
+                w.display,
+                w.window,
+                prop,
+                xlib::XA_CARDINAL,
+                32,
+                xlib::PropModeReplace,
+                std::mem::transmute(val.as_ptr()),
+                val.len() as c_int,
+            );
+        }
+
+        w.set_title("rbar");
+
+        {
+            let mut opcode = 0;
+            let mut event = 0;
+            let mut error = 0;
+            let xinput_str = CString::new("XInputExtension").unwrap();
+            let _xinput_available =
+                xlib::XQueryExtension(w.display, xinput_str.as_ptr(), &mut opcode, &mut event, &mut error);
+
+            let mut mask: [c_uchar;1] = [0];
+            let mut input_event_mask = xinput2::XIEventMask {
+                deviceid: xinput2::XIAllMasterDevices,
+                mask_len: mask.len() as i32,
+                mask: mask.as_mut_ptr(),
+            };
+            let events = &[
+                xinput2::XI_ButtonPress,
+                xinput2::XI_ButtonRelease,
+            ];
+            for &event in events {
+                xinput2::XISetMask(&mut mask, event);
+            }
+
+        
+            match xinput2::XISelectEvents(w.display, w.window, &mut input_event_mask, 1) {
+                status if status as u8 == xlib::Success => (),
+                err => panic!("Failed to select events {:?}", err)
+            }
+        }
+
+        w.set_protocols();        
+        w.map();
+
+        let surf = w.get_cairo_surface();
+        let ctx = cairo::Context::new(&surf);
+
+        let window_fd = w.get_fd();
+
+        let mut fds = std::mem::uninitialized();
+        let mut input = format!("Loading...");
+        let mut stdin = std::io::BufReader::new(std::io::stdin());
+        let mut timer = libc::timeval {
+            tv_sec: 5,
+            tv_usec: 0,
+        };
+        draw(&ctx, "[1]");
+        
+        loop {
+            use std::io::BufRead;
+
+            libc::FD_ZERO(&mut fds);
+            libc::FD_SET(window_fd, &mut fds);
+            libc::FD_SET(1, &mut fds);
+
+            libc::select(window_fd + 1, &mut fds, ptr::null_mut(), ptr::null_mut(), &mut timer);
+
+            if libc::FD_ISSET(1, &mut fds) {
+                input = String::new();
+                stdin.read_line(&mut input).unwrap();
+                if input == "" {
+                    break;
+                }
+                draw(&ctx, &input);
+            }
+
+            while w.has_events() {
+                draw(&ctx, &input);
+                match w.handle() {
+                    Event::QuitEvent => break,
+                    e => (),
+                }
+            }
+
+        }
+    }
+}
+
+
+fn draw(ctx: &cairo::Context, left: &str) {
+    let now = time::now();
+    
+    ctx.set_source_rgb(0.1, 0.1, 0.1);
+    ctx.paint();
+    ctx.set_source_rgb(1.0, 1.0, 1.0);
+
+    let layout = pangocairo::functions::create_layout(&ctx).unwrap();
+    layout.set_alignment(pango::Alignment::Right);
+    layout.set_width((3840 - 20) * pango::SCALE);
+    let mut font = pango::FontDescription::from_string("Fira Mono 18");
+    font.set_weight(pango::Weight::Bold);
+    layout.set_font_description(&font);
+    ctx.move_to(10.0, 4.0);
+    layout.set_text(&time::strftime("%a %b %d %H:%M", &now).unwrap());
+    pangocairo::functions::show_layout(&ctx, &layout);
+
+    layout.set_alignment(pango::Alignment::Left);
+    layout.set_text(left);
+    pangocairo::functions::show_layout(&ctx, &layout);
+}

+ 215 - 0
src/window.rs

@@ -0,0 +1,215 @@
+use x11::{xlib,xinput2};
+
+use std::ffi::CString;
+use std::{mem,ptr};
+use std::os::raw::c_int;
+
+pub struct Window {
+    pub display: *mut xlib::_XDisplay,
+    pub screen: i32,
+    pub window: u64,
+    pub wm_protocols: u64,
+    pub wm_delete_window: u64,
+}
+
+impl Window {
+    pub fn create() -> Window {
+        unsafe {
+            let display = xlib::XOpenDisplay(ptr::null());
+            let screen = xlib::XDefaultScreen(display);
+            let window = xlib::XCreateSimpleWindow(
+                display,
+                xlib::XRootWindow(display, screen),
+                0,
+                0,
+                3840,
+                36,
+                1,
+                xlib::XBlackPixel(display, screen),
+                xlib::XWhitePixel(display, screen),
+            );
+            let wm_protocols = {
+                let cstr = CString::new("WM_PROTOCOLS").unwrap();
+                xlib::XInternAtom(display, cstr.as_ptr(), 0)
+            };
+            let wm_delete_window = {
+                let cstr = CString::new("WM_DELETE_WINDOW").unwrap();
+                xlib::XInternAtom(display, cstr.as_ptr(), 0)
+            };
+            Window {
+                display,
+                screen,
+                window,
+                wm_protocols,
+                wm_delete_window,
+            }
+        }
+    }
+
+    pub fn set_protocols(&mut self) {
+        let mut protocols = [self.intern("WM_DELETE_WINDOW")];
+        unsafe {
+            xlib::XSetWMProtocols(
+                self.display,
+                self.window,
+                protocols.as_mut_ptr(),
+                protocols.len() as c_int,
+            );
+        }
+    }
+
+    pub fn set_title(&mut self, name: &str) {
+        unsafe {
+            xlib::XStoreName(
+                self.display,
+                self.window,
+                CString::new(name).unwrap().as_ptr(),
+            );
+        }
+    }
+
+    pub fn map(&mut self) {
+        unsafe {
+            xlib::XMapWindow(self.display, self.window);
+        }
+    }
+
+    pub fn intern(&mut self, s: &str) -> u64 {
+        unsafe {
+            let cstr = CString::new(s).unwrap();
+            xlib::XInternAtom(self.display, cstr.as_ptr(), 0)
+        }
+    }
+
+    pub fn change_property(&mut self, prop: &str, val: &str) {
+        let prop = self.intern(prop);
+        let val  = self.intern(val);
+        unsafe {
+            xlib::XChangeProperty(
+                self.display,
+                self.window,
+                prop,
+                xlib::XA_ATOM,
+                32,
+                xlib::PropModeReplace,
+                mem::transmute(&val),
+                1,
+            );
+        }
+    }
+
+    pub fn get_cairo_surface(&mut self) -> cairo::Surface {
+        unsafe {
+            let s = cairo_sys::cairo_xlib_surface_create(
+                self.display,
+                self.window,
+                xlib::XDefaultVisual(self.display, self.screen),
+                3840,
+                64,
+            );
+            cairo::Surface::from_raw_none(s)
+        }
+}
+
+    pub fn handle(&mut self) -> Event {
+        // to find out if we're getting a delete window event
+
+        let mut e = unsafe { mem::uninitialized() };
+        unsafe { xlib::XNextEvent(self.display, &mut e) };
+        match e.get_type() {
+            xlib::ClientMessage => {
+                let xclient: xlib::XClientMessageEvent = From::from(e);
+                if xclient.message_type == self.wm_protocols && xclient.format == 32 {
+                    let protocol = xclient.data.get_long(0) as xlib::Atom;
+                    if protocol == self.wm_delete_window {
+                        return Event::QuitEvent;
+                    }
+                }
+            }
+
+            xlib::Expose => return Event::ShowEvent,
+                
+            xlib::GenericEvent => {
+                let mut cookie: xlib::XGenericEventCookie = From::from(e);
+                unsafe { xlib::XGetEventData(self.display, &mut cookie) };
+                    match cookie.evtype {
+                        xinput2::XI_ButtonPress => {
+                            let data: &xinput2::XIDeviceEvent = unsafe { mem::transmute(cookie.data) };
+                            return Event::MouseEvent { x: data.event_x, y: data.event_y };
+                        }
+                        _ => (),
+                    }
+            }
+            _ => (),
+        }
+
+        Event::Other
+    }
+
+    pub fn has_events(&mut self) -> bool {
+        unsafe {
+            xlib::XPending(self.display) != 0
+        }
+    }
+
+    pub fn show(&mut self) {
+        unsafe {
+            xlib::XClearArea(
+                self.display,
+                self.window,
+                0,
+                0,
+                3840,
+                36,
+                1
+            );
+        }
+    }
+
+    pub fn get_fd(&mut self) -> i32 {
+        unsafe {
+            xlib::XConnectionNumber(self.display)
+        }
+    }
+}
+
+
+impl Drop for Window {
+    fn drop(&mut self) {
+        unsafe {
+            xlib::XCloseDisplay(self.display);
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum Event {
+    MouseEvent { x:f64, y: f64 },
+    ShowEvent,
+    QuitEvent,
+    Other,
+}
+
+/*
+cairo_surface_t *cairo_create_x11_surface0(int x, int y)
+{
+    Display *dsp;
+    Drawable da;
+    int screen;
+    cairo_surface_t *sfc;
+
+    if ((dsp = XOpenDisplay(NULL)) == NULL)
+        exit(1);
+    screen = DefaultScreen(dsp);
+    da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp),
+        0, 0, x, y, 0, 0, 0);
+    XSelectInput(dsp, da, ButtonPressMask | KeyPressMask);
+    XMapWindow(dsp, da);
+
+    sfc = cairo_xlib_surface_create(dsp, da,
+        DefaultVisual(dsp, screen), x, y);
+    cairo_xlib_surface_set_size(sfc, x, y);
+
+    return sfc;
+}
+ */