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 => {
let mut image = gui.capture_full_screen()?;
if let Region::Fullscreen = opt.region {
// calculate the full size of the image
let mut min_x = 0;
let mut min_y = 0;
let mut max_x = 0;
let mut max_y = 0;
for (i, (_, screen)) in screen_layout.iter().enumerate() {
let left = screen.x;
let right = screen.x + screen.width as i16;
let top = screen.y;
let bottom = screen.y + screen.height as i16;
if i == 0 {
min_x = left;
min_y = top;
max_x = right;
max_y = bottom;
} else {
min_x = min_x.min(left);
min_y = min_y.min(top);
max_x = max_x.max(right);
max_y = max_y.max(bottom);
}
// calculate the full size of the image
let mut min_x = 0;
let mut min_y = 0;
let mut max_x = 0;
let mut max_y = 0;
for (i, (_, screen)) in screen_layout.iter().enumerate() {
let left = screen.x;
let right = screen.x + screen.width as i16;
let top = screen.y;
let bottom = screen.y + screen.height as i16;
if i == 0 {
min_x = left;
min_y = top;
max_x = right;
max_y = bottom;
} else {
min_x = min_x.min(left);
min_y = min_y.min(top);
max_x = max_x.max(right);
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>>;
/// 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
pub trait Image {
/// 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())
}
fn show_interactive_selection(&self, image: Self::Image) -> Result<Rectangle> {
let window = Window::create(&self.inner, None, Rectangle::new(0, 0, 500, 500))?;
fn show_interactive_selection(
&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();
let mut running = false;
while true {
let event = self.inner.next_event()?;
debug!("event: {:?}", event);
// quit
}
while running {}
unimplemented!()
}
}
@ -83,7 +95,7 @@ impl Platform for X11 {
pub struct Image(x11::xlib::Image);
impl ImageT for Image {
fn into_rgb_image(self) -> RgbImage {
fn to_rgb_image(&self) -> RgbImage {
let width = self.0.get_width();
let height = self.0.get_height();
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)]
#[derive(Debug, Error)]
pub enum Error {
#[error("invalid image byte order")]
#[error("invalid image byte order: {0}")]
InvalidByteOrder(i32),
#[error("invalid event type: {0}")]
InvalidEventType(i32),
#[error("failed to get attributes")]
GetAttributesError,

View file

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

View file

@ -1,23 +1,19 @@
use x11::xlib;
use crate::errors::Result;
use crate::errors::{Error, Result};
/// An x11 Event
#[derive(Debug)]
pub struct Event {
inner: *mut xlib::XAnyEvent,
inner: *mut xlib::XEvent,
kind: EventKind,
}
/// Type of event
#[derive(Debug)]
pub enum EventKind {
/// A mouse button was pressed
ButtonPress,
/// A mouse button was released
ButtonRelease,
/// None event
None,
KeyPress(KeyEvent),
KeyRelease(KeyEvent),
}
impl Event {
@ -26,11 +22,16 @@ impl Event {
&self.kind
}
pub(super) fn from_raw(event: *mut xlib::XAnyEvent) -> Result<Self> {
Ok(Event {
inner: event,
kind: EventKind::None,
})
pub(super) unsafe fn from_raw(event: *mut xlib::XEvent) -> Result<Self> {
let inner = event;
let event = unsafe { *event };
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) };
}
}
#[derive(Debug)]
pub struct KeyEvent(xlib::XKeyEvent);