From f96529bcc7d979b667651cdb403b7171e0486650 Mon Sep 17 00:00:00 2001 From: darkgallium Date: Wed, 20 Jan 2021 23:27:39 +0100 Subject: [PATCH] update --- Cargo.lock | 94 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 ++- src/main.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 207 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 000cefe..e2fa913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index ef01889..88d1e92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/main.rs b/src/main.rs index 4b3c019..d69a919 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 = MaybeUninit::uninit(); + let mut window: MaybeUninit = MaybeUninit::uninit(); + let mut text: MaybeUninit = 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 { + + unsafe { + let display: *mut xlib::Display = xlib::XOpenDisplay(std::ptr::null()); + + let mut revert_to_ret: MaybeUninit = MaybeUninit::uninit(); + let mut window: MaybeUninit = MaybeUninit::uninit(); + let mut text: MaybeUninit = 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 = MaybeUninit::uninit(); + let mut format: MaybeUninit = MaybeUninit::uninit(); + let mut n_items: MaybeUninit = MaybeUninit::uninit(); + let mut bytes_after: MaybeUninit = 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 { + 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 { + let now: DateTime = 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 = 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::::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 { 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 { loop { while xlib::XPending(display) > 0 { let mut e: MaybeUninit = 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 { 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 { } -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(); +}