This commit is contained in:
Michael Zhang 2020-06-28 00:34:50 -05:00
parent 505f56766a
commit 6be5db5e57
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 93 additions and 71 deletions

View file

@ -31,52 +31,51 @@ pub fn main() -> Result<()> {
Region::Fullscreen | Region::Selection => { Region::Fullscreen | Region::Selection => {
let mut image = gui.capture_full_screen()?; let mut image = gui.capture_full_screen()?;
if let Region::Fullscreen = opt.region { // calculate the full size of the image
// calculate the full size of the image let mut min_x = 0;
let mut min_x = 0; let mut min_y = 0;
let mut min_y = 0; let mut max_x = 0;
let mut max_x = 0; let mut max_y = 0;
let mut max_y = 0; for (i, (_, screen)) in screen_layout.iter().enumerate() {
for (i, (_, screen)) in screen_layout.iter().enumerate() { let left = screen.x;
let left = screen.x; let right = screen.x + screen.width as i16;
let right = screen.x + screen.width as i16; let top = screen.y;
let top = screen.y; let bottom = screen.y + screen.height as i16;
let bottom = screen.y + screen.height as i16; if i == 0 {
if i == 0 { min_x = left;
min_x = left; min_y = top;
min_y = top; max_x = right;
max_x = right; max_y = bottom;
max_y = bottom; } else {
} else { min_x = min_x.min(left);
min_x = min_x.min(left); min_y = min_y.min(top);
min_y = min_y.min(top); max_x = max_x.max(right);
max_x = max_x.max(right); max_y = max_y.max(bottom);
max_y = max_y.max(bottom);
}
} }
debug!(
"full virtual screen rect : ({}, {}) to ({}, {})",
min_x, min_y, max_x, max_y
);
// make a new image
let width = (max_x - min_x) as u32;
let height = (max_y - min_y) as u32;
let mut base_image = RgbImage::new(width, height);
// copy all of the images into it
for (id, image) in gui.capture_full_screen()? {
let screen = screen_layout.get(&id).expect("shouldn't fail");
let x = (screen.x + min_x) as u32;
let y = (screen.y + min_y) as u32;
let image = image.into_rgb_image();
imageops::overlay(&mut base_image, &image, x, y);
}
// save the image
base_image.save(&opt.outfile);
} }
// make a new image
let width = (max_x - min_x) as u32;
let height = (max_y - min_y) as u32;
let mut base_image = RgbImage::new(width, height);
// copy all of the images into it
let images = gui.capture_full_screen()?;
for (id, image) in images.iter() {
let screen = screen_layout.get(&id).expect("shouldn't fail");
let x = (screen.x + min_x) as u32;
let y = (screen.y + min_y) as u32;
let image = image.to_rgb_image();
imageops::overlay(&mut base_image, &image, x, y);
}
if let Region::Selection = opt.region {
// bring up the interactive selection
let rect = gui.show_interactive_selection(&images)?;
}
// save the image
base_image.save(&opt.outfile);
} }
}; };

View file

@ -41,11 +41,14 @@ pub trait Platform {
fn capture_full_screen(&self) -> Result<HashMap<Self::ScreenId, Self::Image>>; fn capture_full_screen(&self) -> Result<HashMap<Self::ScreenId, Self::Image>>;
/// Open the interactive selection interface /// Open the interactive selection interface
fn show_interactive_selection(&self, image: Self::Image) -> Result<Rectangle>; fn show_interactive_selection(
&self,
image: &HashMap<Self::ScreenId, Self::Image>,
) -> Result<Rectangle>;
} }
/// Set of functions platform-specific images must implement /// Set of functions platform-specific images must implement
pub trait Image { pub trait Image {
/// Convert the image into an image::RgbImage /// Convert the image into an image::RgbImage
fn into_rgb_image(self) -> RgbImage; fn to_rgb_image(&self) -> RgbImage;
} }

View file

@ -69,13 +69,25 @@ impl Platform for X11 {
.collect()) .collect())
} }
fn show_interactive_selection(&self, image: Self::Image) -> Result<Rectangle> { fn show_interactive_selection(
let window = Window::create(&self.inner, None, Rectangle::new(0, 0, 500, 500))?; &self,
image: &HashMap<Self::ScreenId, Self::Image>,
) -> Result<Rectangle> {
let root_window = self.inner.get_default_root_window()?;
let window = Window::create(
&self.inner,
Some(root_window),
Rectangle::new(0, 0, 500, 500),
)?;
window.map(); window.map();
let mut running = false; while true {
let event = self.inner.next_event()?;
debug!("event: {:?}", event);
// quit
}
while running {}
unimplemented!() unimplemented!()
} }
} }
@ -83,7 +95,7 @@ impl Platform for X11 {
pub struct Image(x11::xlib::Image); pub struct Image(x11::xlib::Image);
impl ImageT for Image { impl ImageT for Image {
fn into_rgb_image(self) -> RgbImage { fn to_rgb_image(&self) -> RgbImage {
let width = self.0.get_width(); let width = self.0.get_width();
let height = self.0.get_height(); let height = self.0.get_height();
let pixbuf = self.0.buffer(); let pixbuf = self.0.buffer();

View file

@ -4,9 +4,12 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
#[error("invalid image byte order")] #[error("invalid image byte order: {0}")]
InvalidByteOrder(i32), InvalidByteOrder(i32),
#[error("invalid event type: {0}")]
InvalidEventType(i32),
#[error("failed to get attributes")] #[error("failed to get attributes")]
GetAttributesError, GetAttributesError,

View file

@ -1,4 +1,5 @@
use std::ffi::CString; use std::ffi::CString;
use std::ptr;
use x11::xlib; use x11::xlib;
@ -63,10 +64,10 @@ impl Display {
/// Get the next event, blocks until an event is reached. /// Get the next event, blocks until an event is reached.
pub fn next_event(&self) -> Result<Event> { pub fn next_event(&self) -> Result<Event> {
let event = unsafe { let event = ptr::null_mut();
libc::malloc(::std::mem::size_of::<xlib::XAnyEvent>()) as *mut xlib::XAnyEvent unsafe { xlib::XNextEvent(self.inner, event) };
}; // TODO: check to make sure this isn't null
Event::from_raw(event) unsafe { Event::from_raw(event) }
} }
/// Returns the number of events that are still pending /// Returns the number of events that are still pending

View file

@ -1,23 +1,19 @@
use x11::xlib; use x11::xlib;
use crate::errors::Result; use crate::errors::{Error, Result};
/// An x11 Event /// An x11 Event
#[derive(Debug)]
pub struct Event { pub struct Event {
inner: *mut xlib::XAnyEvent, inner: *mut xlib::XEvent,
kind: EventKind, kind: EventKind,
} }
/// Type of event /// Type of event
#[derive(Debug)]
pub enum EventKind { pub enum EventKind {
/// A mouse button was pressed KeyPress(KeyEvent),
ButtonPress, KeyRelease(KeyEvent),
/// A mouse button was released
ButtonRelease,
/// None event
None,
} }
impl Event { impl Event {
@ -26,11 +22,16 @@ impl Event {
&self.kind &self.kind
} }
pub(super) fn from_raw(event: *mut xlib::XAnyEvent) -> Result<Self> { pub(super) unsafe fn from_raw(event: *mut xlib::XEvent) -> Result<Self> {
Ok(Event { let inner = event;
inner: event, let event = unsafe { *event };
kind: EventKind::None, debug!("event type: {:?}", event.type_);
}) let kind = match event.type_ {
xlib::KeyPress => EventKind::KeyPress(KeyEvent(event.key)),
xlib::KeyRelease => EventKind::KeyRelease(KeyEvent(event.key)),
other => return Err(Error::InvalidEventType(other)),
};
Ok(Event { inner, kind })
} }
} }
@ -39,3 +40,6 @@ impl Drop for Event {
unsafe { libc::free(self.inner as *mut libc::c_void) }; unsafe { libc::free(self.inner as *mut libc::c_void) };
} }
} }
#[derive(Debug)]
pub struct KeyEvent(xlib::XKeyEvent);