101 lines
3.4 KiB
Rust
101 lines
3.4 KiB
Rust
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::<u8>::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<Position> {
|
|
|
|
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<XEvent> = 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);
|
|
}
|
|
}
|