fix RGBA/BGRA bug, working selection screenshot, code cleanup
This commit is contained in:
parent
6cb6610436
commit
0e34bffc86
1 changed files with 119 additions and 52 deletions
171
src/main.rs
171
src/main.rs
|
@ -1,85 +1,152 @@
|
|||
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 x11::xlib;
|
||||
use std::mem::MaybeUninit;
|
||||
use image::RgbaImage;
|
||||
use image::{RgbaImage};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Position {
|
||||
origin_x: u32,
|
||||
origin_y: u32,
|
||||
origin_x: i32,
|
||||
origin_y: i32,
|
||||
height: u32,
|
||||
width: u32,
|
||||
}
|
||||
|
||||
fn screenshot(pos: &Position) {
|
||||
unsafe {
|
||||
let display: *mut Display = XOpenDisplay(std::ptr::null());
|
||||
let root_window = XDefaultRootWindow(display);
|
||||
let len: usize = (pos.height as usize)*(pos.width as usize)*4;
|
||||
let mut data: Vec<u8> = unsafe {
|
||||
let display: *mut xlib::Display = xlib::XOpenDisplay(std::ptr::null());
|
||||
let root_window = xlib::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();
|
||||
}
|
||||
let ximg = xlib::XGetImage(display,
|
||||
root_window,
|
||||
pos.origin_x,
|
||||
pos.origin_y,
|
||||
pos.width,
|
||||
pos.height,
|
||||
xlib::XAllPlanes(),
|
||||
xlib::ZPixmap);
|
||||
Vec::<u8>::from_raw_parts((*ximg).data as *mut _, len, len)
|
||||
};
|
||||
|
||||
let mut c = 0;
|
||||
|
||||
while c < len {
|
||||
data.swap(c,c+2);
|
||||
c+=4;
|
||||
}
|
||||
|
||||
let img = RgbaImage::from_raw(pos.width, pos.height, data).unwrap();
|
||||
|
||||
img.save("empty.png").unwrap();
|
||||
}
|
||||
|
||||
// https://bbs.archlinux.org/viewtopic.php?id=85378
|
||||
fn trigger_selection() -> Option<Position> {
|
||||
fn select_zone() -> Option<Position> {
|
||||
|
||||
unsafe {
|
||||
let display: *mut Display = XOpenDisplay(std::ptr::null());
|
||||
let root_window = XDefaultRootWindow(display);
|
||||
let display: *mut xlib::Display = xlib::XOpenDisplay(std::ptr::null());
|
||||
let root_window = xlib::XDefaultRootWindow(display);
|
||||
|
||||
let c = XCreateFontCursor(display, 130); // XC_tcross = 130
|
||||
let button_mask = ButtonMotionMask as u32 | ButtonPressMask as u32 | ButtonReleaseMask as u32;
|
||||
let c = xlib::XCreateFontCursor(display, 130); // xlib::XC_tcross = 130
|
||||
|
||||
let button_mask = xlib::ButtonMotionMask as u32 | xlib::ButtonPressMask as u32 | xlib::ButtonReleaseMask as u32;
|
||||
|
||||
if XGrabPointer(display, root_window, 0, button_mask, GrabModeAsync, GrabModeAsync, root_window, c, CurrentTime) != GrabSuccess {
|
||||
if xlib::XGrabPointer(display, root_window, 0, button_mask, xlib::GrabModeAsync, xlib::GrabModeAsync, root_window, c, xlib::CurrentTime) != xlib::GrabSuccess {
|
||||
panic!("could not grab");
|
||||
}
|
||||
|
||||
if XGrabKeyboard(display, root_window, 0, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess {
|
||||
if xlib::XGrabKeyboard(display, root_window, 0, xlib::GrabModeAsync, xlib::GrabModeAsync, xlib::CurrentTime) != xlib::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 mut gcv = xlib::XGCValues {
|
||||
foreground: (255<<16),
|
||||
subwindow_mode: xlib::IncludeInferiors,
|
||||
plane_mask: 0,
|
||||
function: xlib::GXxor,
|
||||
background: 0,
|
||||
line_width: 2,
|
||||
line_style: 0,
|
||||
cap_style: 0,
|
||||
join_style: 0,
|
||||
fill_style: 0,
|
||||
fill_rule: 0,
|
||||
arc_mode: 0,
|
||||
tile: 0,
|
||||
stipple: 0,
|
||||
ts_x_origin: 0,
|
||||
ts_y_origin: 0,
|
||||
font: 0,
|
||||
graphics_exposures: 0,
|
||||
clip_x_origin: 0,
|
||||
clip_y_origin: 0,
|
||||
clip_mask: 0,
|
||||
dash_offset: 0,
|
||||
dashes: 0,
|
||||
};
|
||||
let gcv_mask = xlib::GCSubwindowMode | xlib::GCLineWidth | xlib::GCForeground | xlib::GCFunction;
|
||||
|
||||
let event = unsafe { e.assume_init() };
|
||||
let mut old_coord = (0,0);
|
||||
let gc = xlib::XCreateGC(display, root_window, gcv_mask.into(), &mut gcv);
|
||||
|
||||
// https://stackoverflow.com/questions/38996916/x11-draw-overlay-remove-drawings-from-overlay
|
||||
|
||||
loop {
|
||||
while xlib::XPending(display) > 0 {
|
||||
let mut e: MaybeUninit<xlib::XEvent> = MaybeUninit::uninit();
|
||||
xlib::XNextEvent(display, e.as_mut_ptr());
|
||||
|
||||
let event = 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();
|
||||
xlib::MotionNotify => {
|
||||
let event = xlib::XMotionEvent::from(event);
|
||||
|
||||
pos.width = x - pos.origin_x;
|
||||
pos.height = y - pos.origin_y;
|
||||
|
||||
if pos.height == 0 || pos.width == 0 {
|
||||
return None
|
||||
}
|
||||
let width = event.x_root - pos.origin_x;
|
||||
let height = event.y_root - pos.origin_y;
|
||||
|
||||
return Some(pos);
|
||||
if height < 0 || width < 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
xlib::XDrawRectangle(display, root_window, gc, pos.origin_x, pos.origin_y, old_coord.0, old_coord.1);
|
||||
xlib::XDrawRectangle(display, root_window, gc, pos.origin_x, pos.origin_y, width.try_into().unwrap(), height.try_into().unwrap());
|
||||
|
||||
old_coord = (width.try_into().unwrap(), height.try_into().unwrap());
|
||||
},
|
||||
xlib::KeyPress => {
|
||||
let event = xlib::XKeyEvent::from(event);
|
||||
|
||||
if event.keycode == 9 { // escape keycode (xev)
|
||||
return None;
|
||||
}
|
||||
},
|
||||
xlib::ButtonPress => {
|
||||
let event = xlib::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();
|
||||
},
|
||||
xlib::ButtonRelease => {
|
||||
// assuming that the upper left corner is the origin
|
||||
let event = xlib::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 as u32;
|
||||
pos.height = y - pos.origin_y as u32;
|
||||
|
||||
if pos.height == 0 || pos.width == 0 {
|
||||
return None
|
||||
}
|
||||
|
||||
xlib::XDrawRectangle(display, root_window, gc, pos.origin_x, pos.origin_y, pos.width, pos.height);
|
||||
xlib::XFlush(display);
|
||||
return Some(pos);
|
||||
}
|
||||
_ => { println!("type unknown: {}", event.type_); }
|
||||
}
|
||||
|
@ -92,7 +159,7 @@ fn trigger_selection() -> Option<Position> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let s = trigger_selection();
|
||||
let s = select_zone();
|
||||
println!("{:?}", s);
|
||||
if let Some(select) = s {
|
||||
screenshot(&select);
|
||||
|
|
Loading…
Reference in a new issue