use x11::xlib::{XGrabPointer, XCreateFontCursor, XOpenDisplay, Display, XDefaultRootWindow, XAllPlanes, ZPixmap, XGetImage, ButtonMotionMask, ButtonPressMask, ButtonReleaseMask, CurrentTime, GrabModeAsync, GrabSuccess, XNextEvent, XEvent, XPending, ButtonPress, ButtonRelease, XButtonEvent, XGrabKeyboard, KeyPress, XKeyEvent}; use std::mem::MaybeUninit; use image::RgbaImage; use std::convert::TryInto; #[derive(Debug)] struct Position { origin_x: u32, origin_y: u32, height: u32, width: u32, } fn screenshot(pos: &Position) { unsafe { let display: *mut Display = XOpenDisplay(std::ptr::null()); let root_window = XDefaultRootWindow(display); let ximg = XGetImage(display, root_window, pos.origin_x.try_into().unwrap(), pos.origin_y.try_into().unwrap(), pos.width.try_into().unwrap(), pos.height.try_into().unwrap(), XAllPlanes(), ZPixmap); let len = pos.height*pos.width*4; let v = Vec::::from_raw_parts((*ximg).data as *mut _, len.try_into().unwrap(), len.try_into().unwrap()); //println!("{:?}", v); let img = RgbaImage::from_raw(pos.width, pos.height, v).unwrap(); img.save("empty.jpg").unwrap(); } } // https://bbs.archlinux.org/viewtopic.php?id=85378 fn trigger_selection() -> Option { unsafe { let display: *mut Display = XOpenDisplay(std::ptr::null()); let root_window = XDefaultRootWindow(display); let c = XCreateFontCursor(display, 130); // XC_tcross = 130 let button_mask = ButtonMotionMask as u32 | ButtonPressMask as u32 | ButtonReleaseMask as u32; if XGrabPointer(display, root_window, 0, button_mask, GrabModeAsync, GrabModeAsync, root_window, c, CurrentTime) != GrabSuccess { panic!("could not grab"); } if XGrabKeyboard(display, root_window, 0, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess { panic!("could not grab"); } let mut pos = Position { origin_x: 0, origin_y: 0, width: 0, height: 0}; 'main: loop { while XPending(display) > 0 { let mut e: MaybeUninit = MaybeUninit::uninit(); XNextEvent(display, e.as_mut_ptr()); let event = unsafe { e.assume_init() }; match event.type_ { KeyPress => { let event = XKeyEvent::from(event); if event.keycode == 9 { // escape keycode (xev) return None; } }, ButtonPress => { let event = XButtonEvent::from(event); println!("origin = ({},{})", event.x, event.y); pos.origin_x = event.x_root.try_into().unwrap(); pos.origin_y = event.y_root.try_into().unwrap(); }, ButtonRelease => { // assuming that the upper left corner is the origin let event = XButtonEvent::from(event); let x: u32 = event.x_root.try_into().unwrap(); let y: u32 = event.y_root.try_into().unwrap(); pos.width = x - pos.origin_x; pos.height = y - pos.origin_y; if pos.height == 0 || pos.width == 0 { return None } return Some(pos); } _ => { println!("type unknown: {}", event.type_); } } } } } } fn main() { let s = trigger_selection(); println!("{:?}", s); if let Some(select) = s { screenshot(&select); } }