From 92d476df054cdfcf1b4f8934c56031301659afa7 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Tue, 11 Sep 2018 14:08:15 -0500 Subject: [PATCH] move visual to xlib, adding framework for interactive select --- imlib2/lib.rs | 6 ++---- imlib2/visual.rs | 15 --------------- src/capture.rs | 29 ----------------------------- src/gui.rs | 11 ++++++++--- src/lib.rs | 22 +++------------------- src/window.rs | 15 +++++++++++++++ xlib/src/display.rs | 7 +++++++ xlib/src/lib.rs | 5 +++++ xlib/src/rect.rs | 24 ++++++++++++++++++++++++ xlib/src/visual.rs | 21 +++++++++++++++++++++ xlib/src/window.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 125 insertions(+), 70 deletions(-) delete mode 100644 imlib2/visual.rs create mode 100644 src/window.rs create mode 100644 xlib/src/rect.rs create mode 100644 xlib/src/visual.rs diff --git a/imlib2/lib.rs b/imlib2/lib.rs index 6c8da1a..12c6bc0 100644 --- a/imlib2/lib.rs +++ b/imlib2/lib.rs @@ -9,12 +9,10 @@ extern crate x11; mod errors; mod image; -mod visual; pub use errors::Error; pub use image::Image; pub use imlib2_sys::{Drawable, Pixmap}; -pub use visual::Visual; /// Set the display for the imlib context. pub fn context_set_display(display: *mut x11::xlib::Display) { @@ -22,6 +20,6 @@ pub fn context_set_display(display: *mut x11::xlib::Display) { } /// Set the visual for the imlib context. -pub fn context_set_visual(visual: Visual) { - unsafe { imlib2_sys::imlib_context_set_visual(visual.inner) }; +pub fn context_set_visual(visual: *mut x11::xlib::Visual) { + unsafe { imlib2_sys::imlib_context_set_visual(visual as *mut imlib2_sys::Visual) }; } diff --git a/imlib2/visual.rs b/imlib2/visual.rs deleted file mode 100644 index 66c6ac6..0000000 --- a/imlib2/visual.rs +++ /dev/null @@ -1,15 +0,0 @@ -use imlib2_sys as im; -use x11; - -/// Visual -pub struct Visual { - pub(crate) inner: *mut im::Visual, -} - -impl Visual { - /// get the default visual for a display - pub fn default(display: *mut x11::xlib::_XDisplay, screen: i32) -> Self { - let inner = unsafe { im::XDefaultVisual(display as *mut im::_XDisplay, screen) }; - Visual { inner } - } -} diff --git a/src/capture.rs b/src/capture.rs index ec7fb43..548117c 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -6,42 +6,13 @@ use options::{Options, Region}; pub fn capture(opt: &Options) -> Result<(), ScreenshotError> { let gui = GUI::new()?; - // let window_to_capture = match opt.region { - // Region::Fullscreen | Region::Selection => gui.display.get_default_root_window()?, - // Region::ActiveWindow => gui.get_active_window()?, - // }; let window_to_capture = match opt.region { Region::ActiveWindow => gui.get_active_window()?, _ => gui.display.get_default_root_window()?, }; - // let _clip = match opt.region { - // Region::ActiveWindow => { - // let win = gui.get_active_window()?; - // let attr = win.get_attributes()?; - // let width = attr.get_width(); - // let height = attr.get_height(); - // let root = gui.display.get_default_root_window()?; - // let (x, y, _) = gui.display.translate_coordinates(win, 0, 0, root)?; - // Some(Rectangle::new(x as u32, y as u32, width, height)) - // } - // _ => None, - // }; - let capture = gui.capture_window(window_to_capture)?; - - // capture.write_png(&opt.outfile, clip)?; capture.save_image(&opt.outfile)?; - // let final_capture = match opt.region { - // Region::Fullscreen | Region::ActiveWindow => window_capture, - // Region::Selection => gui.interactive_select(&window_capture), - // }; - - // if let Region::Selection = opt.region { - // let region = gui.interactive_select(&capture)?; - // capture.apply_region(®ion); - // }; - Ok(()) } diff --git a/src/gui.rs b/src/gui.rs index aa3b166..96b6ef6 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,8 +1,9 @@ -use imlib2::{self, Image as Image2, Visual}; -use xlib::{Display, Image, Window}; +use imlib2::{self, Image as Image2}; +use xlib::{Display, Image, Window, Visual}; use errors::ScreenshotError; use Rectangle; +use SelectWindow; pub struct GUI { pub(crate) display: Display, @@ -21,8 +22,11 @@ impl GUI { let height = attr.get_height() as i32; let root = self.display.get_default_root_window()?; let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?; + imlib2::context_set_display(self.display.as_raw()); - imlib2::context_set_visual(Visual::default(self.display.as_raw(), 0)); + let visual = Visual::default(&self.display, 0); + imlib2::context_set_visual(visual.as_raw()); + Image2::create_from_drawable(window, 0, x, y, width, height, true).map_err(|err| err.into()) } @@ -37,6 +41,7 @@ impl GUI { /// Brings up an interactive selection GUI. #[allow(dead_code)] pub fn interactive_select(&self, _capture: &Image) -> Result { + let window = SelectWindow::new(&self.display); Err(ScreenshotError::Error) } } diff --git a/src/lib.rs b/src/lib.rs index 47c2a85..6a041c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,27 +11,11 @@ mod capture; mod errors; mod gui; mod options; +mod window; use structopt::StructOpt; +use xlib::Rectangle; pub use capture::capture; pub use options::Options; - -#[derive(Debug)] -pub struct Rectangle { - pub x: u32, - pub y: u32, - pub width: u32, - pub height: u32, -} - -impl Rectangle { - pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self { - Rectangle { - x, - y, - width, - height, - } - } -} +pub use window::SelectWindow; diff --git a/src/window.rs b/src/window.rs new file mode 100644 index 0000000..8093a1f --- /dev/null +++ b/src/window.rs @@ -0,0 +1,15 @@ +use xlib::{Display, Window, Rectangle}; + +use errors::ScreenshotError; + +pub struct SelectWindow { + inner: Window, +} + +impl SelectWindow { + pub fn new(display: &Display) -> Result { + // TODO: unhardcode + let window = Window::create(display, None, Rectangle::new(0, 0, 1920, 1080))?; + Ok(SelectWindow { inner: window }) + } +} diff --git a/xlib/src/display.rs b/xlib/src/display.rs index bf087ac..f2790f4 100644 --- a/xlib/src/display.rs +++ b/xlib/src/display.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use x11::xlib as x; +use Visual; use Window; use X11Error; @@ -29,6 +30,12 @@ impl Display { self.inner } + /// Gets the default visual + pub fn default_visual(&self, screen: i32) -> Visual { + let visual = unsafe { x::XDefaultVisual(self.inner, screen) }; + Visual { inner: visual } + } + /// Returns the root window for the given screen. pub fn get_root_window(&self, screen: i32) -> Result { let inner = unsafe { x::XRootWindow(self.inner, screen) }; diff --git a/xlib/src/lib.rs b/xlib/src/lib.rs index 5ac09c9..b6abef4 100644 --- a/xlib/src/lib.rs +++ b/xlib/src/lib.rs @@ -13,9 +13,14 @@ extern crate x11; mod display; mod errors; mod image; +mod visual; +mod rect; mod window; pub use display::Display; pub use errors::X11Error; pub use image::{Image, ImageByteOrder, PixBuffer}; +pub use visual::Visual; +pub use rect::Rectangle; pub use window::{Window, WindowAttributes}; + diff --git a/xlib/src/rect.rs b/xlib/src/rect.rs new file mode 100644 index 0000000..89429be --- /dev/null +++ b/xlib/src/rect.rs @@ -0,0 +1,24 @@ +/// A rectangle. +#[derive(Debug)] +pub struct Rectangle { + /// x + pub x: u32, + /// y + pub y: u32, + /// width + pub width: u32, + /// height + pub height: u32, +} + +impl Rectangle { + /// Create a new Rectangle from u32s + pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self { + Rectangle { + x, + y, + width, + height, + } + } +} \ No newline at end of file diff --git a/xlib/src/visual.rs b/xlib/src/visual.rs new file mode 100644 index 0000000..264d5e8 --- /dev/null +++ b/xlib/src/visual.rs @@ -0,0 +1,21 @@ +use x11::xlib as x; + +use Display; + +/// A wrapper around a Visual +pub struct Visual { + pub(super) inner: *mut x::Visual, +} + +impl Visual { + /// Gets the raw handle to the x11 Visual + pub fn as_raw(&self) -> *mut x::Visual { + self.inner + } + + /// Gets the default visual + pub fn default(display: &Display, screen: i32) -> Self { + let inner = unsafe { x::XDefaultVisual(display.as_raw(), screen) }; + Visual { inner } + } +} diff --git a/xlib/src/window.rs b/xlib/src/window.rs index 342d37f..e71b680 100644 --- a/xlib/src/window.rs +++ b/xlib/src/window.rs @@ -4,7 +4,9 @@ use imlib2::Drawable; use libc; use x11::xlib as x; +use Display; use Image; +use Rectangle; use X11Error; /// A wrapper around a window handle. @@ -20,6 +22,39 @@ pub struct WindowAttributes { } impl Window { + /// Create a new window + pub fn create( + display: &Display, + parent: Option, + location: Rectangle, + ) -> Result { + let parent = match parent { + Some(parent) => parent, + None => display.get_default_root_window()?, + }; + let visual = display.default_visual(0); + let window = unsafe { + x::XCreateWindow( + display.as_raw(), + parent.as_raw(), + location.x as i32, + location.y as i32, + location.width, + location.height, + 0, + 0, + 0, + visual.as_raw(), + 0, + 0 as *mut x::XSetWindowAttributes, + ) + }; + Ok(Window { + display: display.as_raw(), + inner: window, + }) + } + /// Get window attributes. pub fn get_attributes(&self) -> Result { let attr = unsafe { @@ -49,6 +84,11 @@ impl Window { }; Ok(Image { inner: image }) } + + /// Get the raw window handle + pub fn as_raw(&self) -> x::Window { + self.inner + } } impl AsRef for Window {