shutter-rs/src/main.rs

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);
}
}