forked from michael/leanshot
try build
This commit is contained in:
parent
201b2e480f
commit
de118c6047
21 changed files with 15108 additions and 13 deletions
|
@ -2,8 +2,11 @@ language: rust
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
|
script:
|
||||||
|
- ./ci/check.sh screenshot
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- ./ci/build-release.sh dip ${TRAVIS_TAG}-${TRAVIS_OS_NAME}
|
- ./ci/build-release.sh screenshot ${TRAVIS_TAG}-${TRAVIS_OS_NAME}
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: releases
|
- provider: releases
|
||||||
|
|
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -104,6 +104,19 @@ dependencies = [
|
||||||
"synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imlib2"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"imlib2-sys 0.1.0",
|
||||||
|
"x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imlib2-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inflate"
|
name = "inflate"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -199,6 +212,7 @@ name = "screenshot"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"imlib2 0.1.0",
|
||||||
"png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -347,6 +361,7 @@ name = "xlib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"imlib2 0.1.0",
|
||||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11 2.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,7 @@ version = "0.3.0"
|
||||||
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [".", "xlib"]
|
members = [".", "imlib2", "imlib2/imlib2-sys", "xlib"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["dylib", "rlib"]
|
crate-type = ["dylib", "rlib"]
|
||||||
|
@ -13,6 +13,7 @@ crate-type = ["dylib", "rlib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
png = "0.12"
|
png = "0.12"
|
||||||
|
imlib2 = { path = "imlib2" }
|
||||||
structopt = "0.2"
|
structopt = "0.2"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
xlib = { path = "xlib" }
|
xlib = { path = "xlib" }
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
FROM ekidd/rust-musl-builder
|
FROM ekidd/rust-musl-builder
|
||||||
|
|
||||||
|
RUN sudo apt-get update -y && sudo apt-get install -y libx11-dev libimlib2-dev
|
||||||
|
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN sudo chown -R rust:rust .
|
RUN sudo chown -R rust:rust .
|
||||||
|
|
||||||
|
|
8
Dockerfile.check
Normal file
8
Dockerfile.check
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM ekidd/rust-musl-builder
|
||||||
|
|
||||||
|
RUN sudo apt-get update -y && sudo apt-get install -y libx11-dev libimlib2-dev
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
RUN sudo chown -R rust:rust .
|
||||||
|
|
||||||
|
CMD cargo build
|
33
ci/check.sh
Executable file
33
ci/check.sh
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Usage: ./build-release <PROJECT> ${TRAVIS_TAG}-${TRAVIS_OS_NAME}
|
||||||
|
#
|
||||||
|
# The latest version of this script is available at
|
||||||
|
# https://github.com/emk/rust-musl-builder/blob/master/examples/build-release
|
||||||
|
#
|
||||||
|
# Called by `.travis.yml` to build release binaries. We use
|
||||||
|
# ekidd/rust-musl-builder to make the Linux binaries so that we can run
|
||||||
|
# them unchanged on any distro, including tiny distros like Alpine (which
|
||||||
|
# is heavily used for Docker containers). Other platforms get regular
|
||||||
|
# binaries, which will generally be dynamically linked against libc.
|
||||||
|
#
|
||||||
|
# If you have a platform which supports static linking of libc, and this
|
||||||
|
# would be generally useful, please feel free to submit patches.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
case `uname -s` in
|
||||||
|
Linux)
|
||||||
|
echo "Building static binaries using ekidd/rust-musl-builder"
|
||||||
|
docker build -f Dockerfile.check -t build-"$1"-image .
|
||||||
|
docker run -it --name build-"$1" build-"$1"-image
|
||||||
|
docker cp build-"$1":/home/rust/src/target/x86_64-unknown-linux-musl/release/"$1" "$1"
|
||||||
|
docker rm build-"$1"
|
||||||
|
docker rmi build-"$1"-image
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Building standard release binaries"
|
||||||
|
cargo build --release
|
||||||
|
zip -j "$1"-"$2".zip target/release/"$1"
|
||||||
|
;;
|
||||||
|
esac
|
12
imlib2/Cargo.toml
Normal file
12
imlib2/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "imlib2"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
failure = "0.1"
|
||||||
|
imlib2-sys = { path = "imlib2-sys" }
|
||||||
|
x11 = { version = "2.18", features = ["xlib"] }
|
7
imlib2/errors.rs
Normal file
7
imlib2/errors.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/// Enumerated error type.
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[derive(Debug, Fail)]
|
||||||
|
pub enum Error {
|
||||||
|
#[fail(display = "error")]
|
||||||
|
Error,
|
||||||
|
}
|
45
imlib2/image.rs
Normal file
45
imlib2/image.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use imlib2_sys as im;
|
||||||
|
use x11;
|
||||||
|
|
||||||
|
use Error;
|
||||||
|
|
||||||
|
/// A simple wrapper around Imlib_Image
|
||||||
|
pub struct Image {
|
||||||
|
inner: im::Imlib_Image,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image {
|
||||||
|
/// Set the display for the imlib context.
|
||||||
|
pub fn context_set_display(display: *mut x11::xlib::Display) {
|
||||||
|
unsafe { im::imlib_context_set_display(display as *mut im::_XDisplay) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an Image from a pixmap.
|
||||||
|
pub fn create_from_drawable(
|
||||||
|
drawable: impl AsRef<im::Drawable>,
|
||||||
|
pixmap: im::Pixmap,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
grab_x: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
unsafe { im::imlib_context_set_drawable(*drawable.as_ref()) };
|
||||||
|
let image = unsafe {
|
||||||
|
im::imlib_create_image_from_drawable(pixmap, x, y, width, height, if grab_x{ 1 } else { 0 }) as im::Imlib_Image
|
||||||
|
};
|
||||||
|
Ok(Image { inner: image })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save this image
|
||||||
|
pub fn save_image(&self, file: impl AsRef<Path>) -> Result<(), Error> {
|
||||||
|
unsafe { im::imlib_context_set_image((*self).inner) };
|
||||||
|
let mut error = 0;
|
||||||
|
let path = CString::new(file.as_ref().to_str().unwrap()).unwrap();
|
||||||
|
unsafe { im::imlib_save_image_with_error_return(path.as_ptr(), &mut error) };
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
10
imlib2/imlib2-sys/Cargo.toml
Normal file
10
imlib2/imlib2-sys/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "imlib2-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[build-dependencies]
|
3
imlib2/imlib2-sys/build.rs
Normal file
3
imlib2/imlib2-sys/build.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rustc-link-lib=Imlib2");
|
||||||
|
}
|
14917
imlib2/imlib2-sys/lib.rs
Normal file
14917
imlib2/imlib2-sys/lib.rs
Normal file
File diff suppressed because it is too large
Load diff
15
imlib2/lib.rs
Normal file
15
imlib2/lib.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//! Safe-ish bindings to imlib2 (at least the only parts I need).
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure;
|
||||||
|
extern crate imlib2_sys;
|
||||||
|
extern crate x11;
|
||||||
|
|
||||||
|
mod errors;
|
||||||
|
mod image;
|
||||||
|
|
||||||
|
pub use errors::Error;
|
||||||
|
pub use image::Image;
|
||||||
|
pub use imlib2_sys::{Drawable, Pixmap};
|
|
@ -2,12 +2,10 @@ use errors::ScreenshotError;
|
||||||
|
|
||||||
use gui::GUI;
|
use gui::GUI;
|
||||||
use options::{Options, Region};
|
use options::{Options, Region};
|
||||||
use xlib::Image;
|
|
||||||
|
|
||||||
use ImageExt;
|
|
||||||
use Rectangle;
|
use Rectangle;
|
||||||
|
|
||||||
pub fn capture(opt: &Options) -> Result<Image, ScreenshotError> {
|
pub fn capture(opt: &Options) -> Result<(), ScreenshotError> {
|
||||||
let gui = GUI::new()?;
|
let gui = GUI::new()?;
|
||||||
|
|
||||||
// let window_to_capture = match opt.region {
|
// let window_to_capture = match opt.region {
|
||||||
|
@ -17,7 +15,7 @@ pub fn capture(opt: &Options) -> Result<Image, ScreenshotError> {
|
||||||
let window_to_capture = gui.display.get_default_root_window()?;
|
let window_to_capture = gui.display.get_default_root_window()?;
|
||||||
|
|
||||||
let capture = gui.capture_window(window_to_capture)?;
|
let capture = gui.capture_window(window_to_capture)?;
|
||||||
let clip = match opt.region {
|
let _clip = match opt.region {
|
||||||
Region::ActiveWindow => {
|
Region::ActiveWindow => {
|
||||||
let win = gui.get_active_window()?;
|
let win = gui.get_active_window()?;
|
||||||
let attr = win.get_attributes()?;
|
let attr = win.get_attributes()?;
|
||||||
|
@ -35,7 +33,8 @@ pub fn capture(opt: &Options) -> Result<Image, ScreenshotError> {
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
capture.write_png(&opt.outfile, clip)?;
|
// capture.write_png(&opt.outfile, clip)?;
|
||||||
|
capture.save_image(&opt.outfile)?;
|
||||||
|
|
||||||
// let final_capture = match opt.region {
|
// let final_capture = match opt.region {
|
||||||
// Region::Fullscreen | Region::ActiveWindow => window_capture,
|
// Region::Fullscreen | Region::ActiveWindow => window_capture,
|
||||||
|
@ -47,5 +46,5 @@ pub fn capture(opt: &Options) -> Result<Image, ScreenshotError> {
|
||||||
// capture.apply_region(®ion);
|
// capture.apply_region(®ion);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
Ok(capture)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ pub enum ScreenshotError {
|
||||||
#[fail(display = "x11 error")]
|
#[fail(display = "x11 error")]
|
||||||
X11Error(#[cause] ::xlib::X11Error),
|
X11Error(#[cause] ::xlib::X11Error),
|
||||||
|
|
||||||
|
#[fail(display = "imlib2 error")]
|
||||||
|
ImlibError(#[cause] ::imlib2::Error),
|
||||||
|
|
||||||
#[fail(display = "io error")]
|
#[fail(display = "io error")]
|
||||||
IOError(#[cause] ::std::io::Error),
|
IOError(#[cause] ::std::io::Error),
|
||||||
|
|
||||||
|
@ -25,6 +28,12 @@ impl From<::xlib::X11Error> for ScreenshotError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<::imlib2::Error> for ScreenshotError {
|
||||||
|
fn from(err: ::imlib2::Error) -> Self {
|
||||||
|
ScreenshotError::ImlibError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<::png::EncodingError> for ScreenshotError {
|
impl From<::png::EncodingError> for ScreenshotError {
|
||||||
fn from(err: ::png::EncodingError) -> Self {
|
fn from(err: ::png::EncodingError) -> Self {
|
||||||
ScreenshotError::PngEncodingError(err)
|
ScreenshotError::PngEncodingError(err)
|
||||||
|
|
11
src/gui.rs
11
src/gui.rs
|
@ -1,4 +1,5 @@
|
||||||
use xlib::{Display, Image, Window};
|
use xlib::{Display, Image, Window};
|
||||||
|
use imlib2::{Image as Image2,};
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
use errors::ScreenshotError;
|
||||||
use Rectangle;
|
use Rectangle;
|
||||||
|
@ -14,14 +15,14 @@ impl GUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Captures the window and produces a DynamicImage.
|
/// Captures the window and produces a DynamicImage.
|
||||||
pub fn capture_window(&self, window: Window) -> Result<Image, ScreenshotError> {
|
pub fn capture_window(&self, window: Window) -> Result<Image2, ScreenshotError> {
|
||||||
let attr = window.get_attributes()?;
|
let attr = window.get_attributes()?;
|
||||||
let width = attr.get_width();
|
let width = attr.get_width() as i32;
|
||||||
let height = attr.get_height();
|
let height = attr.get_height() as i32;
|
||||||
let root = self.display.get_default_root_window()?;
|
let root = self.display.get_default_root_window()?;
|
||||||
let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
||||||
println!("x={} y={} width={} height={}", x, y, width, height);
|
Image2::context_set_display(self.display.as_raw());
|
||||||
window.get_image().map_err(|err| err.into())
|
Image2::create_from_drawable(window, 0, x, y, width, height, true).map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the active window.
|
/// Get the active window.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
extern crate imlib2;
|
||||||
extern crate png;
|
extern crate png;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate structopt;
|
extern crate structopt;
|
||||||
|
|
|
@ -6,5 +6,6 @@ authors = ["Michael Zhang <failed.down@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
imlib2 = { path = "../imlib2" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
x11 = { version = "2.18", features = ["xlib"] }
|
x11 = { version = "2.18", features = ["xlib"] }
|
||||||
|
|
|
@ -24,6 +24,11 @@ impl Display {
|
||||||
Ok(Display { inner })
|
Ok(Display { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the raw X Display handle
|
||||||
|
pub fn as_raw(&self) -> *mut x::Display {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the root window for the given screen.
|
/// Returns the root window for the given screen.
|
||||||
pub fn get_root_window(&self, screen: i32) -> Result<Window, X11Error> {
|
pub fn get_root_window(&self, screen: i32) -> Result<Window, X11Error> {
|
||||||
let inner = unsafe { x::XRootWindow(self.inner, screen) };
|
let inner = unsafe { x::XRootWindow(self.inner, screen) };
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
extern crate imlib2;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate x11;
|
extern crate x11;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
use imlib2::Drawable;
|
||||||
use libc;
|
use libc;
|
||||||
use x11::xlib as x;
|
use x11::xlib as x;
|
||||||
|
|
||||||
|
@ -50,6 +51,12 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Drawable> for Window {
|
||||||
|
fn as_ref(&self) -> &Drawable {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WindowAttributes {
|
impl WindowAttributes {
|
||||||
/// Gets the width of the window
|
/// Gets the width of the window
|
||||||
pub fn get_x(&self) -> i32 {
|
pub fn get_x(&self) -> i32 {
|
||||||
|
|
Loading…
Reference in a new issue