for some reason still can't get it to do full screen
This commit is contained in:
parent
c7fc13ed64
commit
a8e0349d2a
31 changed files with 1172 additions and 15051 deletions
804
Cargo.lock
generated
804
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
10
Cargo.toml
10
Cargo.toml
|
@ -5,16 +5,18 @@ version = "0.3.0"
|
||||||
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [".", "imlib2-sys"]
|
members = [".", "imlib2", "imlib2/imlib2-sys", "xlib"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["dylib", "rlib"]
|
crate-type = ["dylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
gl = "0.10"
|
||||||
|
glutin = "0.18"
|
||||||
|
imlib2 = { path = "imlib2" }
|
||||||
|
nanovg = { version = "1.0.2", features = ["gl3"] }
|
||||||
png = "0.12"
|
png = "0.12"
|
||||||
imlib2-sys = { path = "imlib2-sys" }
|
|
||||||
libc = "0.2"
|
|
||||||
structopt = "0.2"
|
structopt = "0.2"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
x11 = { version = "2.18", features = ["xlib"] }
|
xlib = { path = "xlib" }
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("cargo:rustc-link-lib=Imlib2");
|
|
||||||
}
|
|
14917
imlib2-sys/lib.rs
14917
imlib2-sys/lib.rs
File diff suppressed because it is too large
Load diff
9
imlib2/Cargo.toml
Normal file
9
imlib2/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "imlib2"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
failure = "0.1"
|
||||||
|
imlib2-sys = { path = "imlib2-sys" }
|
||||||
|
xlib = { path = "../xlib" }
|
|
@ -8,3 +8,4 @@ build = "build.rs"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
bindgen = "0.40"
|
20
imlib2/imlib2-sys/build.rs
Normal file
20
imlib2/imlib2-sys/build.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// bindgen build script by remexre
|
||||||
|
|
||||||
|
extern crate bindgen;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use bindgen::Builder;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rustc-link-lib=Imlib2");
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
Builder::default()
|
||||||
|
.header("wrapper.h")
|
||||||
|
.blacklist_type("max_align_t")
|
||||||
|
.generate()
|
||||||
|
.expect("Unable to generate bindings")
|
||||||
|
.write_to_file(out_path.join("bindings.rs"))
|
||||||
|
.expect("Unable to write bindings");
|
||||||
|
}
|
5
imlib2/imlib2-sys/lib.rs
Normal file
5
imlib2/imlib2-sys/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
1
imlib2/imlib2-sys/wrapper.h
Normal file
1
imlib2/imlib2-sys/wrapper.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "Imlib2.h"
|
|
@ -3,7 +3,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use imlib2_sys as im;
|
use imlib2_sys as im;
|
||||||
|
|
||||||
use imlib2::Error;
|
use Error;
|
||||||
use xlib::Drawable;
|
use xlib::Drawable;
|
||||||
|
|
||||||
/// A simple wrapper around Imlib_Image
|
/// A simple wrapper around Imlib_Image
|
||||||
|
@ -44,10 +44,18 @@ impl Image {
|
||||||
unsafe { im::imlib_save_image_with_error_return(path.as_ptr(), &mut error) };
|
unsafe { im::imlib_save_image_with_error_return(path.as_ptr(), &mut error) };
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get raw image
|
||||||
|
pub fn as_raw(&self) -> im::Imlib_Image {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Image {
|
impl Drop for Image {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { im::imlib_free_image() };
|
unsafe {
|
||||||
|
im::imlib_context_set_image(self.inner);
|
||||||
|
im::imlib_free_image();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,15 @@
|
||||||
//! Safe-ish bindings to imlib2 (at least the only parts I need).
|
//! Safe-ish bindings to imlib2 (at least the only parts I need).
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure;
|
||||||
|
extern crate imlib2_sys;
|
||||||
|
extern crate xlib;
|
||||||
|
|
||||||
mod errors;
|
mod errors;
|
||||||
mod image;
|
mod image;
|
||||||
|
|
||||||
use imlib2_sys;
|
pub use errors::Error;
|
||||||
|
pub use image::Image;
|
||||||
pub use self::errors::Error;
|
|
||||||
pub use self::image::Image;
|
|
||||||
pub use imlib2_sys::{Drawable, Pixmap};
|
pub use imlib2_sys::{Drawable, Pixmap};
|
||||||
|
|
||||||
use xlib::{Display, Visual};
|
use xlib::{Display, Visual};
|
||||||
|
@ -22,3 +25,13 @@ pub fn context_set_display(display: &Display) {
|
||||||
pub fn context_set_visual(visual: &Visual) {
|
pub fn context_set_visual(visual: &Visual) {
|
||||||
unsafe { imlib2_sys::imlib_context_set_visual(visual.as_raw() as *mut imlib2_sys::Visual) };
|
unsafe { imlib2_sys::imlib_context_set_visual(visual.as_raw() as *mut imlib2_sys::Visual) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the visual for the imlib context.
|
||||||
|
pub fn context_set_image(image: &Image) {
|
||||||
|
unsafe { imlib2_sys::imlib_context_set_image(image.as_raw() as imlib2_sys::Imlib_Image) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pointer to the raw image data for the current image.
|
||||||
|
pub fn image_get_data() -> *mut u32 {
|
||||||
|
unsafe { imlib2_sys::imlib_image_get_data_for_reading_only() }
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ pub fn capture(opt: &Options) -> Result<(), ScreenshotError> {
|
||||||
_ => gui.display.get_default_root_window()?,
|
_ => gui.display.get_default_root_window()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
println!("{}", window_to_capture.as_raw());
|
||||||
let capture = gui.capture_window(&opt, window_to_capture)?;
|
let capture = gui.capture_window(&opt, window_to_capture)?;
|
||||||
capture.save_image(&opt.outfile)?;
|
capture.save_image(&opt.outfile)?;
|
||||||
|
|
||||||
|
|
263
src/gui.rs
263
src/gui.rs
|
@ -1,11 +1,10 @@
|
||||||
use imlib2::{self, Image as Image2};
|
use imlib2::{self, Image as Image2};
|
||||||
use xlib::{Display, EventKind, Visual, Window};
|
use xlib::{Display, Visual, Window};
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
use errors::ScreenshotError;
|
||||||
use Options;
|
use Options;
|
||||||
use Rectangle;
|
use Rectangle;
|
||||||
use Region;
|
use Region;
|
||||||
use SelectWindow;
|
|
||||||
|
|
||||||
pub struct GUI {
|
pub struct GUI {
|
||||||
pub(crate) display: Display,
|
pub(crate) display: Display,
|
||||||
|
@ -22,7 +21,7 @@ impl GUI {
|
||||||
let attr = window.get_attributes()?;
|
let attr = window.get_attributes()?;
|
||||||
let mut width = attr.get_width();
|
let mut width = attr.get_width();
|
||||||
let mut height = attr.get_height();
|
let mut height = attr.get_height();
|
||||||
let root = self.display.get_default_root_window()?;
|
let root = attr.get_root();
|
||||||
let (mut x, mut y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
let (mut x, mut y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
||||||
|
|
||||||
imlib2::context_set_display(&self.display);
|
imlib2::context_set_display(&self.display);
|
||||||
|
@ -31,7 +30,7 @@ impl GUI {
|
||||||
|
|
||||||
match opt.region {
|
match opt.region {
|
||||||
Region::Selection => {
|
Region::Selection => {
|
||||||
let region = self.interactive_select()?;
|
let region = self.interactive_select(window)?;
|
||||||
x = region.x;
|
x = region.x;
|
||||||
y = region.y;
|
y = region.y;
|
||||||
width = region.width;
|
width = region.width;
|
||||||
|
@ -53,29 +52,243 @@ impl GUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Brings up an interactive selection GUI.
|
/// Brings up an interactive selection GUI.
|
||||||
pub fn interactive_select(&self) -> Result<Rectangle, ScreenshotError> {
|
pub fn interactive_select(&self, window: Window) -> Result<Rectangle, ScreenshotError> {
|
||||||
let window = SelectWindow::new(&self.display);
|
// let window = SelectWindow::new(&self.display);
|
||||||
let root = self.display.get_default_root_window()?;
|
// let root = self.display.get_default_root_window()?;
|
||||||
|
|
||||||
let root_im = root.get_image();
|
// let root_im = root.get_image();
|
||||||
|
|
||||||
let mut done = 0;
|
// let mut done = 0;
|
||||||
let mut button_press = false;
|
// let mut button_press = false;
|
||||||
while done == 0 && self.display.pending()? > 0 {
|
// while done == 0 && self.display.pending()? > 0 {
|
||||||
let ev = self.display.next_event()?;
|
// let ev = self.display.next_event()?;
|
||||||
match ev.kind() {
|
// match ev.kind() {
|
||||||
EventKind::ButtonPress => {
|
// EventKind::ButtonPress => {
|
||||||
button_press = true;
|
// button_press = true;
|
||||||
}
|
// }
|
||||||
EventKind::ButtonRelease => {
|
// EventKind::ButtonRelease => {
|
||||||
if button_press {
|
// if button_press {
|
||||||
done = 1;
|
// done = 1;
|
||||||
}
|
// }
|
||||||
button_press = false;
|
// button_press = false;
|
||||||
}
|
// }
|
||||||
_ => (),
|
// _ => (),
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
use gl;
|
||||||
|
use glutin::{
|
||||||
|
dpi::LogicalSize, ElementState, Event, EventsLoop, GlContext, GlWindow, KeyboardInput,
|
||||||
|
MouseButton, VirtualKeyCode, WindowBuilder, WindowEvent,
|
||||||
|
};
|
||||||
|
use nanovg::{Color, Image, ImagePattern, PathOptions, StrokeOptions};
|
||||||
|
use std::{f32::consts, slice};
|
||||||
|
|
||||||
|
let attr = window.get_attributes()?;
|
||||||
|
let width = attr.get_width();
|
||||||
|
let height = attr.get_height();
|
||||||
|
let root = attr.get_root();
|
||||||
|
println!("{} {}", width, height);
|
||||||
|
let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
||||||
|
|
||||||
|
let mut evl = EventsLoop::new();
|
||||||
|
let mon = evl.get_primary_monitor();
|
||||||
|
|
||||||
|
// TODO: handle error
|
||||||
|
let wb = WindowBuilder::new()
|
||||||
|
.with_decorations(false)
|
||||||
|
.with_always_on_top(true)
|
||||||
|
.with_dimensions(LogicalSize::new(width.into(), height.into()))
|
||||||
|
.with_fullscreen(Some(mon));
|
||||||
|
let ctx = glutin::ContextBuilder::new()
|
||||||
|
.with_vsync(false)
|
||||||
|
.with_multisampling(4)
|
||||||
|
.with_srgb(true);
|
||||||
|
let win = GlWindow::new(wb, ctx, &evl).expect("couldn't make window");
|
||||||
|
let f = win.get_hidpi_factor() as f64;
|
||||||
|
unsafe {
|
||||||
|
win.make_current().expect("couldn't make window");
|
||||||
|
gl::load_with(|sym| win.get_proc_address(sym) as *const _);
|
||||||
|
}
|
||||||
|
// win.set_inner_size((width, height).into());
|
||||||
|
// println!("size={:?} pos={:?} outer={:?}", win.get_inner_size(), win.get_inner_position(), win.get_outer_size());
|
||||||
|
// println!("{:?}", win.get_hidpi_factor());
|
||||||
|
|
||||||
|
imlib2::context_set_display(&self.display);
|
||||||
|
let visual = Visual::default(&self.display, 0);
|
||||||
|
imlib2::context_set_visual(&visual);
|
||||||
|
|
||||||
|
let img = Image2::create_from_drawable(window, 0, x, y, width as i32, height as i32, true)?;
|
||||||
|
imlib2::context_set_image(&img);
|
||||||
|
let len = (width * height) as usize;
|
||||||
|
let raw_data = unsafe { slice::from_raw_parts(imlib2::image_get_data(), len) };
|
||||||
|
|
||||||
|
// convert ARGB to RGBA
|
||||||
|
let mut data = vec![0u32; raw_data.len()];
|
||||||
|
data.copy_from_slice(raw_data);
|
||||||
|
for i in &mut data {
|
||||||
|
// fix the colors
|
||||||
|
*i = (*i & 0xff00ff00) | ((*i & 0xff) << 16) | ((*i >> 16) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctx = nanovg::ContextBuilder::new()
|
||||||
|
.build()
|
||||||
|
.expect("couldn't init nanovg");
|
||||||
|
|
||||||
|
let image = Image::new(&ctx)
|
||||||
|
.build_from_rgba(width as usize, height as usize, data.as_slice())
|
||||||
|
.expect("couldn't create image");
|
||||||
|
|
||||||
|
let mut running = true;
|
||||||
|
let mut down = false;
|
||||||
|
// drag start
|
||||||
|
let mut dx = -1.0f64;
|
||||||
|
let mut dy = -1.0f64;
|
||||||
|
// curr mouse
|
||||||
|
let mut mx = -1.0f64;
|
||||||
|
let mut my = -1.0f64;
|
||||||
|
// rect
|
||||||
|
let mut rectw = 0.0f64;
|
||||||
|
let mut recth = 0.0f64;
|
||||||
|
let mut delayed_down = false;
|
||||||
|
while running {
|
||||||
|
let mut redraw = true;
|
||||||
|
evl.poll_events(|event| match event {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
|
WindowEvent::CloseRequested | WindowEvent::Destroyed => running = false,
|
||||||
|
WindowEvent::KeyboardInput {
|
||||||
|
input:
|
||||||
|
KeyboardInput {
|
||||||
|
virtual_keycode,
|
||||||
|
state,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} => match (virtual_keycode, state) {
|
||||||
|
(Some(VirtualKeyCode::Escape), ElementState::Released) => {
|
||||||
|
if down {
|
||||||
|
down = false;
|
||||||
|
} else {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
WindowEvent::CursorMoved { position, .. } => {
|
||||||
|
mx = position.x;
|
||||||
|
my = position.y;
|
||||||
|
if down {
|
||||||
|
if delayed_down {
|
||||||
|
dx = mx;
|
||||||
|
dy = my;
|
||||||
|
delayed_down = false;
|
||||||
|
} else {
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
rectw = mx - dx;
|
||||||
|
recth = my - dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WindowEvent::MouseInput { button, state, .. } => match button {
|
||||||
|
MouseButton::Left => {
|
||||||
|
down = match state {
|
||||||
|
ElementState::Pressed => {
|
||||||
|
delayed_down = true;
|
||||||
|
if mx < 0.0 || my < 0.0 {
|
||||||
|
} else {
|
||||||
|
dx = mx;
|
||||||
|
dy = my;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ElementState::Released => {
|
||||||
|
if down && rectw.abs() > 0.0 && recth.abs() > 0.0 {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
});
|
||||||
|
|
||||||
|
if !redraw {
|
||||||
|
// don't do anything if it's not moved
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let size = win.get_inner_size().unwrap();
|
||||||
|
// let (width, height) = (size.width as i32, size.height as i32);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::Viewport(0, 0, width as i32, height as i32);
|
||||||
|
gl::ClearColor(0.3, 0.3, 0.32, 1.0);
|
||||||
|
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (width, height) = (width as f64, height as f64);
|
||||||
|
ctx.frame((width as f32, height as f32), f as f32, |frame| {
|
||||||
|
let path_opts = PathOptions::default();
|
||||||
|
frame.path(
|
||||||
|
|path| {
|
||||||
|
path.rect((0.0, 0.0), ((width * f) as f32, (height * f) as f32));
|
||||||
|
// path.fill(Color::from_rgba(200, 200, 200, 255), Default::default());
|
||||||
|
path.fill(
|
||||||
|
ImagePattern {
|
||||||
|
image: &image,
|
||||||
|
origin: (0.0, 0.0),
|
||||||
|
size: (width as f32, height as f32),
|
||||||
|
angle: 0.0 / 180.0 * consts::PI,
|
||||||
|
alpha: 1.0,
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
path_opts,
|
||||||
|
);
|
||||||
|
if down && rectw.abs() > 0.0 && recth.abs() > 0.0 {
|
||||||
|
frame.path(
|
||||||
|
|path| {
|
||||||
|
path.rect(
|
||||||
|
((dx * f) as f32, (dy * f) as f32),
|
||||||
|
((rectw * f) as f32, (recth * f) as f32),
|
||||||
|
);
|
||||||
|
path.stroke(
|
||||||
|
Color::from_rgba(0, 0, 0, 255),
|
||||||
|
StrokeOptions {
|
||||||
|
width: 2.0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
path_opts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
win.swap_buffers().expect("couldn't swap buffers");
|
||||||
|
}
|
||||||
|
if rectw.abs() > 0.0 && recth.abs() > 0.0 {
|
||||||
|
let mut x = dx;
|
||||||
|
let mut y = dy;
|
||||||
|
if rectw < 0.0 {
|
||||||
|
x += rectw;
|
||||||
|
}
|
||||||
|
if recth < 0.0 {
|
||||||
|
y += recth;
|
||||||
|
}
|
||||||
|
Ok(Rectangle::new(
|
||||||
|
(x * f) as i32,
|
||||||
|
(y * f) as i32,
|
||||||
|
(rectw.abs() * f) as u32,
|
||||||
|
(recth.abs() * f) as u32,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(ScreenshotError::Error)
|
||||||
}
|
}
|
||||||
Err(ScreenshotError::Error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -4,22 +4,20 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
extern crate imlib2_sys;
|
extern crate gl;
|
||||||
extern crate libc;
|
extern crate glutin;
|
||||||
|
extern crate imlib2;
|
||||||
|
extern crate nanovg;
|
||||||
extern crate png;
|
extern crate png;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate structopt;
|
extern crate structopt;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate x11;
|
extern crate xlib;
|
||||||
|
|
||||||
mod capture;
|
mod capture;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod gui;
|
mod gui;
|
||||||
mod options;
|
mod options;
|
||||||
mod window;
|
|
||||||
|
|
||||||
pub mod imlib2;
|
|
||||||
pub mod xlib;
|
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
use errors::ScreenshotError;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
@ -27,4 +25,11 @@ use xlib::Rectangle;
|
||||||
|
|
||||||
pub use capture::capture;
|
pub use capture::capture;
|
||||||
pub use options::{Options, Region};
|
pub use options::{Options, Region};
|
||||||
pub use window::SelectWindow;
|
|
||||||
|
use failure::Error;
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn main() -> Result<(), Error> {
|
||||||
|
let opt = Options::from_args();
|
||||||
|
capture(&opt).map(|_| ()).map_err(|err| err.into())
|
||||||
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -1,12 +0,0 @@
|
||||||
extern crate failure;
|
|
||||||
extern crate screenshot;
|
|
||||||
extern crate structopt;
|
|
||||||
|
|
||||||
use failure::Error;
|
|
||||||
use screenshot::{capture, Options};
|
|
||||||
use structopt::StructOpt;
|
|
||||||
|
|
||||||
pub fn main() -> Result<(), Error> {
|
|
||||||
let opt = Options::from_args();
|
|
||||||
capture(&opt).map(|_| ()).map_err(|err| err.into())
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
use xlib::{Display, Rectangle, Window};
|
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
|
||||||
|
|
||||||
/// A window that's opened for the user to select a region
|
|
||||||
pub struct SelectWindow {
|
|
||||||
inner: Window,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectWindow {
|
|
||||||
/// Creates a new SelectWindow
|
|
||||||
pub fn new(display: &Display) -> Result<Self, ScreenshotError> {
|
|
||||||
// TODO: unhardcode
|
|
||||||
let window = Window::create(display, None, Rectangle::new(0, 0, 1920, 1080))?;
|
|
||||||
Ok(SelectWindow { inner: window })
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Graphics context
|
|
||||||
pub struct GC {}
|
|
|
@ -1,30 +0,0 @@
|
||||||
//! Safe-ish bindings to parts of x11's xlib module.
|
|
||||||
//!
|
|
||||||
//! I need this for my project.
|
|
||||||
|
|
||||||
mod cursor;
|
|
||||||
mod display;
|
|
||||||
mod drawable;
|
|
||||||
mod errors;
|
|
||||||
mod event;
|
|
||||||
mod gc;
|
|
||||||
mod image;
|
|
||||||
mod rect;
|
|
||||||
mod visual;
|
|
||||||
mod window;
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
mod cursorfont;
|
|
||||||
|
|
||||||
pub use self::cursor::Cursor;
|
|
||||||
pub use self::cursorfont::*;
|
|
||||||
pub use self::display::{Display, GetDisplay};
|
|
||||||
pub use self::drawable::Drawable;
|
|
||||||
pub use self::errors::X11Error;
|
|
||||||
pub use self::event::{Event, EventKind};
|
|
||||||
pub use self::gc::GC;
|
|
||||||
pub use self::image::{Image, ImageByteOrder, PixBuffer};
|
|
||||||
pub use self::rect::Rectangle;
|
|
||||||
pub use self::visual::Visual;
|
|
||||||
pub use self::window::{Window, WindowAttributes};
|
|
9
xlib/Cargo.toml
Normal file
9
xlib/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "xlib"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
failure = "0.1"
|
||||||
|
libc = "0.2"
|
||||||
|
x11 = { version = "2.18", features = ["xlib"] }
|
|
@ -3,7 +3,7 @@ use std::ffi::CString;
|
||||||
use libc;
|
use libc;
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::{Cursor, Event, Visual, Window, X11Error};
|
use {Cursor, Event, Visual, Window, X11Error};
|
||||||
|
|
||||||
/// A connection to an X server.
|
/// A connection to an X server.
|
||||||
pub struct Display {
|
pub struct Display {
|
|
@ -1,6 +1,6 @@
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::{GetDisplay, Image, Rectangle, X11Error};
|
use {GetDisplay, Image, Rectangle, X11Error};
|
||||||
|
|
||||||
/// Anything that's drawable
|
/// Anything that's drawable
|
||||||
pub trait Drawable: GetDisplay {
|
pub trait Drawable: GetDisplay {
|
|
@ -1,7 +1,7 @@
|
||||||
use libc;
|
use libc;
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::X11Error;
|
use X11Error;
|
||||||
|
|
||||||
/// An x11 Event
|
/// An x11 Event
|
||||||
pub struct Event {
|
pub struct Event {
|
|
@ -1,6 +1,6 @@
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::X11Error;
|
use X11Error;
|
||||||
|
|
||||||
/// A handle to an XImage.
|
/// A handle to an XImage.
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
|
@ -17,8 +17,10 @@ pub enum ImageByteOrder {
|
||||||
|
|
||||||
/// The buffer pointed to by an XImage.
|
/// The buffer pointed to by an XImage.
|
||||||
pub struct PixBuffer {
|
pub struct PixBuffer {
|
||||||
pub(self) buf: *mut u8,
|
/// The raw pointer to the buffer
|
||||||
pub(self) size: usize,
|
pub buf: *mut u8,
|
||||||
|
/// The size of the buffer
|
||||||
|
pub size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
33
xlib/src/lib.rs
Normal file
33
xlib/src/lib.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//! Safe-ish bindings to parts of x11's xlib module.
|
||||||
|
//!
|
||||||
|
//! I need this for my project.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure;
|
||||||
|
extern crate libc;
|
||||||
|
extern crate x11;
|
||||||
|
|
||||||
|
mod cursor;
|
||||||
|
mod display;
|
||||||
|
mod drawable;
|
||||||
|
mod errors;
|
||||||
|
mod event;
|
||||||
|
mod image;
|
||||||
|
mod rect;
|
||||||
|
mod visual;
|
||||||
|
mod window;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
mod cursorfont;
|
||||||
|
|
||||||
|
pub use cursor::Cursor;
|
||||||
|
pub use cursorfont::*;
|
||||||
|
pub use display::{Display, GetDisplay};
|
||||||
|
pub use drawable::Drawable;
|
||||||
|
pub use errors::X11Error;
|
||||||
|
pub use event::{Event, EventKind};
|
||||||
|
pub use image::{Image, ImageByteOrder, PixBuffer};
|
||||||
|
pub use rect::Rectangle;
|
||||||
|
pub use visual::Visual;
|
||||||
|
pub use window::{Window, WindowAttributes};
|
|
@ -1,6 +1,6 @@
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::Display;
|
use Display;
|
||||||
|
|
||||||
/// A wrapper around a Visual
|
/// A wrapper around a Visual
|
||||||
pub struct Visual {
|
pub struct Visual {
|
|
@ -4,7 +4,7 @@ use std::mem;
|
||||||
use libc;
|
use libc;
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
use xlib::{Display, Drawable, GetDisplay, Image, Rectangle, X11Error};
|
use {Display, Drawable, GetDisplay, Image, Rectangle, X11Error};
|
||||||
|
|
||||||
/// A wrapper around a window handle.
|
/// A wrapper around a window handle.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -15,6 +15,7 @@ pub struct Window {
|
||||||
|
|
||||||
/// Window Attributes
|
/// Window Attributes
|
||||||
pub struct WindowAttributes {
|
pub struct WindowAttributes {
|
||||||
|
pub(super) display: *mut x::Display,
|
||||||
pub(self) inner: *mut x::XWindowAttributes,
|
pub(self) inner: *mut x::XWindowAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +61,10 @@ impl Window {
|
||||||
let result = unsafe { x::XGetWindowAttributes(self.display, self.inner, attr) };
|
let result = unsafe { x::XGetWindowAttributes(self.display, self.inner, attr) };
|
||||||
match result {
|
match result {
|
||||||
0 => Err(X11Error::GetAttributesError),
|
0 => Err(X11Error::GetAttributesError),
|
||||||
_ => Ok(WindowAttributes { inner: attr }),
|
_ => Ok(WindowAttributes {
|
||||||
|
display: self.display,
|
||||||
|
inner: attr,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +126,14 @@ impl WindowAttributes {
|
||||||
pub fn get_height(&self) -> u32 {
|
pub fn get_height(&self) -> u32 {
|
||||||
unsafe { (*self.inner).height as u32 }
|
unsafe { (*self.inner).height as u32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the root window of this window
|
||||||
|
pub fn get_root(&self) -> Window {
|
||||||
|
Window {
|
||||||
|
display: self.display,
|
||||||
|
inner: unsafe { (*self.inner).root },
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WindowAttributes {
|
impl Drop for WindowAttributes {
|
Loading…
Reference in a new issue