2018-09-11 19:08:15 +00:00
|
|
|
use imlib2::{self, Image as Image2};
|
2018-09-11 21:58:16 +00:00
|
|
|
use xlib::{Display, EventKind, Visual, Window};
|
2018-09-10 06:52:54 +00:00
|
|
|
|
|
|
|
use errors::ScreenshotError;
|
2018-09-11 21:58:16 +00:00
|
|
|
use Options;
|
2018-09-10 06:52:54 +00:00
|
|
|
use Rectangle;
|
2018-09-11 21:58:16 +00:00
|
|
|
use Region;
|
2018-09-11 22:25:50 +00:00
|
|
|
use SelectWindow;
|
2018-09-10 06:52:54 +00:00
|
|
|
|
|
|
|
pub struct GUI {
|
2018-09-11 01:31:25 +00:00
|
|
|
pub(crate) display: Display,
|
2018-09-10 06:52:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GUI {
|
2018-09-10 08:15:42 +00:00
|
|
|
pub fn new() -> Result<Self, ScreenshotError> {
|
2018-09-11 01:31:25 +00:00
|
|
|
let display = Display::connect(":0")?;
|
2018-09-10 08:15:42 +00:00
|
|
|
Ok(GUI { display })
|
2018-09-10 06:52:54 +00:00
|
|
|
}
|
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
/// Captures the window and produces an Image.
|
|
|
|
pub fn capture_window(&self, opt: &Options, window: Window) -> Result<Image2, ScreenshotError> {
|
2018-09-11 02:23:11 +00:00
|
|
|
let attr = window.get_attributes()?;
|
2018-09-11 21:58:16 +00:00
|
|
|
let mut width = attr.get_width();
|
|
|
|
let mut height = attr.get_height();
|
2018-09-11 02:23:11 +00:00
|
|
|
let root = self.display.get_default_root_window()?;
|
2018-09-11 21:58:16 +00:00
|
|
|
let (mut x, mut y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
2018-09-11 19:08:15 +00:00
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
imlib2::context_set_display(&self.display);
|
2018-09-11 19:08:15 +00:00
|
|
|
let visual = Visual::default(&self.display, 0);
|
2018-09-11 21:58:16 +00:00
|
|
|
imlib2::context_set_visual(&visual);
|
2018-09-11 19:08:15 +00:00
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
match opt.region {
|
|
|
|
Region::Selection => {
|
|
|
|
let region = self.interactive_select()?;
|
|
|
|
x = region.x;
|
|
|
|
y = region.y;
|
|
|
|
width = region.width;
|
|
|
|
height = region.height;
|
2018-09-11 22:25:50 +00:00
|
|
|
}
|
|
|
|
_ => (),
|
2018-09-11 21:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Image2::create_from_drawable(window, 0, x, y, width as i32, height as i32, true)
|
|
|
|
.map_err(|err| err.into())
|
2018-09-10 06:52:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the active window.
|
2018-09-11 01:31:25 +00:00
|
|
|
pub fn get_active_window(&self) -> Result<Window, ScreenshotError> {
|
2018-09-11 01:44:07 +00:00
|
|
|
self.display
|
|
|
|
.get_input_focus()
|
|
|
|
.map(|(window, _)| window)
|
|
|
|
.map_err(|err| err.into())
|
2018-09-10 06:52:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Brings up an interactive selection GUI.
|
2018-09-11 21:58:16 +00:00
|
|
|
pub fn interactive_select(&self) -> Result<Rectangle, ScreenshotError> {
|
2018-09-11 19:08:15 +00:00
|
|
|
let window = SelectWindow::new(&self.display);
|
2018-09-11 21:58:16 +00:00
|
|
|
let root = self.display.get_default_root_window()?;
|
|
|
|
|
|
|
|
let root_im = root.get_image();
|
|
|
|
|
|
|
|
let mut done = 0;
|
2018-09-11 22:25:50 +00:00
|
|
|
let mut button_press = false;
|
2018-09-11 21:58:16 +00:00
|
|
|
while done == 0 && self.display.pending()? > 0 {
|
|
|
|
let ev = self.display.next_event()?;
|
|
|
|
match ev.kind() {
|
2018-09-11 22:25:50 +00:00
|
|
|
EventKind::ButtonPress => {
|
|
|
|
button_press = true;
|
|
|
|
}
|
|
|
|
EventKind::ButtonRelease => {
|
|
|
|
if button_press {
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
button_press = false;
|
|
|
|
}
|
2018-09-11 22:05:25 +00:00
|
|
|
_ => (),
|
2018-09-11 21:58:16 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-10 06:52:54 +00:00
|
|
|
Err(ScreenshotError::Error)
|
|
|
|
}
|
|
|
|
}
|