This commit is contained in:
darkgallium 2021-01-20 23:27:39 +01:00
parent 0e34bffc86
commit f96529bcc7
3 changed files with 207 additions and 9 deletions

94
Cargo.lock generated
View File

@ -42,6 +42,19 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@ -119,12 +132,30 @@ dependencies = [
"byteorder",
]
[[package]]
name = "dmenu_facade"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372af688af899981cb3d9d0b23de762c906d6367325d3a7304f7ad90c4b74d0f"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "flate2"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide 0.4.3",
]
[[package]]
name = "gif"
version = "0.11.1"
@ -144,6 +175,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
[[package]]
name = "image"
version = "0.23.12"
@ -282,6 +319,21 @@ dependencies = [
"miniz_oxide 0.3.7",
]
[[package]]
name = "procfs"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab8809e0c18450a2db0f236d2a44ec0b4c1412d0eb936233579f0990faa5d5cd"
dependencies = [
"bitflags",
"byteorder",
"chrono",
"flate2",
"hex",
"lazy_static",
"libc",
]
[[package]]
name = "rayon"
version = "1.5.0"
@ -323,7 +375,10 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
name = "shutter-rs"
version = "0.1.0"
dependencies = [
"chrono",
"dmenu_facade",
"image",
"procfs",
"x11",
]
@ -338,12 +393,51 @@ dependencies = [
"weezl",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "weezl"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2bb9fc8309084dd7cd651336673844c1d47f8ef6d2091ec160b27f5c4aa277"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "x11"
version = "2.18.2"

View File

@ -8,4 +8,7 @@ edition = "2018"
[dependencies]
image = "0.23.12"
x11 = { version = "2.18", features = [ "xlib", "xss" ] }
x11 = { version = "2.18", features = [ "xlib" ] }
dmenu_facade = "0.3.0"
chrono = "0.4.19"
procfs = "0.9.1"

View File

@ -1,7 +1,12 @@
use dmenu_facade::*;
use x11::xlib;
use std::mem::MaybeUninit;
use std::os::raw::{c_int,c_ulong,c_uchar};
use image::{RgbaImage};
use std::convert::TryInto;
use std::process::{Stdio,Command};
use std::ffi::{CStr,CString};
use chrono::{DateTime, Local, SecondsFormat};
#[derive(Debug)]
struct Position {
@ -11,8 +16,85 @@ struct Position {
width: u32,
}
fn get_focus_win_name() -> String {
unsafe {
let display: *mut xlib::Display = xlib::XOpenDisplay(std::ptr::null());
let mut revert_to_ret: MaybeUninit<c_int> = MaybeUninit::uninit();
let mut window: MaybeUninit<c_ulong> = MaybeUninit::uninit();
let mut text: MaybeUninit<xlib::XTextProperty> = MaybeUninit::uninit();
xlib::XGetInputFocus(display, window.as_mut_ptr(), revert_to_ret.as_mut_ptr());
let mut window = window.assume_init();
xlib::XGetWMName(display, window, text.as_mut_ptr());
let mut text = text.assume_init();
let c_str = CStr::from_ptr(text.value as *mut i8);
let str_slice = c_str.to_str().unwrap();
xlib::XCloseDisplay(display);
str_slice.to_owned()
}
}
fn get_wm_win_pid() -> Option<u64> {
unsafe {
let display: *mut xlib::Display = xlib::XOpenDisplay(std::ptr::null());
let mut revert_to_ret: MaybeUninit<c_int> = MaybeUninit::uninit();
let mut window: MaybeUninit<c_ulong> = MaybeUninit::uninit();
let mut text: MaybeUninit<xlib::XTextProperty> = MaybeUninit::uninit();
xlib::XGetInputFocus(display, window.as_mut_ptr(), revert_to_ret.as_mut_ptr());
let mut window = window.assume_init();
let pid_str = CString::new("_NET_WM_PID").unwrap();
let atom = xlib::XInternAtom(display, pid_str.as_ptr() as *const i8, 0);
let mut retrieved_atom: MaybeUninit<c_ulong> = MaybeUninit::uninit();
let mut format: MaybeUninit<c_int> = MaybeUninit::uninit();
let mut n_items: MaybeUninit<c_ulong> = MaybeUninit::uninit();
let mut bytes_after: MaybeUninit<c_ulong> = MaybeUninit::uninit();
let mut ptr: *mut c_uchar = 0 as *mut c_uchar;
if xlib::XGetWindowProperty(display, window, atom, 0, 1, 0, xlib::XA_CARDINAL,
retrieved_atom.as_mut_ptr(),
format.as_mut_ptr(),
n_items.as_mut_ptr(),
bytes_after.as_mut_ptr(),
&mut ptr) == 0 {
let t = ptr as *mut c_ulong;
Some(*t)
} else {
None
}
}
}
fn get_process_name() -> Option<String> {
let pid = get_wm_win_pid()?;
let p = procfs::process::Process::new(pid as i32).unwrap();
Some(String::from(p.exe().unwrap().file_name()?.to_str()?))
}
fn get_name_proposals() -> Vec<String> {
let now: DateTime<Local> = Local::now();
let formatted_now = now.format("%F %T");
let mut window_name = get_focus_win_name();
let process_name = get_process_name().unwrap();
window_name.truncate(10);
vec!(format!("{}.png", formatted_now),
format!("{} ({}).png", formatted_now, window_name),
format!("{} ({}).png", formatted_now, process_name))
}
fn screenshot(pos: &Position) {
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);
@ -25,18 +107,20 @@ fn screenshot(pos: &Position) {
pos.height,
xlib::XAllPlanes(),
xlib::ZPixmap);
Vec::<u8>::from_raw_parts((*ximg).data as *mut _, len, len)
};
let mut c = 0;
while c < len {
// for some reason, instead of storing RGBA data, x11 store BGRA data,
// we need to fix that before passing that to image lib
data.swap(c,c+2);
c+=4;
}
let img = RgbaImage::from_raw(pos.width, pos.height, data).unwrap();
let img = RgbaImage::from_raw(pos.width, pos.height, data).unwrap();
img.save("empty.png").unwrap();
}
@ -86,6 +170,7 @@ fn select_zone() -> Option<Position> {
dash_offset: 0,
dashes: 0,
};
let gcv_mask = xlib::GCSubwindowMode | xlib::GCLineWidth | xlib::GCForeground | xlib::GCFunction;
let mut old_coord = (0,0);
@ -96,8 +181,8 @@ fn select_zone() -> Option<Position> {
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_ {
@ -146,6 +231,7 @@ fn select_zone() -> Option<Position> {
xlib::XDrawRectangle(display, root_window, gc, pos.origin_x, pos.origin_y, pos.width, pos.height);
xlib::XFlush(display);
xlib::XCloseDisplay(display);
return Some(pos);
}
_ => { println!("type unknown: {}", event.type_); }
@ -158,10 +244,25 @@ fn select_zone() -> Option<Position> {
}
fn main() {
let s = select_zone();
println!("{:?}", s);
if let Some(select) = s {
screenshot(&select);
fn show_interactive_menu() {
let items = vec!["test", "test2"];
let chosen = DMenu::default()
.execute(&items);
//Prints selected item to stdout
if let Ok(item) = chosen {
println!("{}", item);
}
}
fn main() {
/*let a = get_focus_win_name();
println!("{:?}", get_name_proposals());
println!("{:?}", get_wm_win_pid());
println!("{:?}", get_process_name());*/
//let s = select_zone();
//println!("{:?}", s);
//if let Some(select) = s {
// screenshot(&select);
//}
show_interactive_menu();
}