forked from michael/leanshot
fullscreen for x11
This commit is contained in:
parent
69e226dcf3
commit
c519114a9f
10 changed files with 111 additions and 33 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -185,7 +185,6 @@ name = "leanshot"
|
|||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"image",
|
||||
"leanshot-x11",
|
||||
"libc",
|
||||
|
|
25
Cargo.toml
25
Cargo.toml
|
@ -12,19 +12,28 @@ members = ["x11"]
|
|||
|
||||
[features]
|
||||
default = ["backend-x11", "backend-x11-glx"]
|
||||
backend-x11 = []
|
||||
backend-x11-glx = ["backend-x11"]
|
||||
backend-x11 = ["leanshot-x11"]
|
||||
backend-x11-glx = ["backend-x11", "leanshot-x11/glx"]
|
||||
backend-xcb = ["xcb-util", "xcb"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.38"
|
||||
image = { version = "0.23.13", default-features = false, features = ["jpeg", "png"] }
|
||||
leanshot-x11 = { path = "x11" }
|
||||
anyhow = "1.0.42"
|
||||
image = { version = "0.23.14", default-features = false, features = ["jpeg", "png"] }
|
||||
log = "0.4.14"
|
||||
stderrlog = "0.5.1"
|
||||
structopt = "0.3.21"
|
||||
libc = "0.2.86"
|
||||
structopt = "0.3.22"
|
||||
libc = "0.2.98"
|
||||
|
||||
# x11
|
||||
leanshot-x11 = { path = "x11", optional = true }
|
||||
|
||||
# xcb
|
||||
xcb-util = { version = "0.3.0", features = ["image", "cursor"], optional = true }
|
||||
xcb = { version = "0.9.0", optional = true }
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
skip_feature_sets = [
|
||||
["backend-x11", "backend-xcb"],
|
||||
[],
|
||||
]
|
||||
skip_optional_dependencies = true
|
||||
|
|
|
@ -11,6 +11,9 @@ pub trait Gui {
|
|||
}
|
||||
|
||||
pub trait Capture {
|
||||
fn save_to(&self, path: impl AsRef<Path>) -> Result<()>;
|
||||
fn save_to(&self, to: impl AsRef<Path>) -> Result<()> {
|
||||
self.save_cropped_to(to, None)
|
||||
}
|
||||
|
||||
fn save_cropped_to(&self, path: impl AsRef<Path>, section: Option<Rectangle>) -> Result<()>;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use x11::xlib::Display;
|
||||
use x11::xlib::{Display, Image as XImage, Screen};
|
||||
use image::{Bgra, DynamicImage, ImageBuffer};
|
||||
|
||||
use crate::gui_trait::{Capture, Gui};
|
||||
use crate::rect::Rectangle;
|
||||
|
@ -15,33 +16,71 @@ impl X11Gui {
|
|||
let disp = Display::connect(None)?;
|
||||
Ok(X11Gui { conn: disp })
|
||||
}
|
||||
|
||||
fn get_default_screen(&self) -> Screen {
|
||||
self.conn.default_screen()
|
||||
}
|
||||
}
|
||||
|
||||
impl Gui for X11Gui {
|
||||
type Capture = ScreenCapture;
|
||||
fn capture_entire_screen(&self) -> Result<<Self as Gui>::Capture, anyhow::Error> {
|
||||
todo!()
|
||||
|
||||
fn capture_entire_screen(&self) -> Result<Self::Capture> {
|
||||
// get the dimensions of the screen
|
||||
let screen = self.get_default_screen();
|
||||
let (width, height) = (screen.width_in_pixels(), screen.height_in_pixels());
|
||||
|
||||
let root_window = self.conn.get_root_window(screen)?;
|
||||
let image = root_window.get_image()?;
|
||||
|
||||
Ok(ScreenCapture { image })
|
||||
}
|
||||
|
||||
fn interactive_select(
|
||||
&self,
|
||||
_: &<Self as Gui>::Capture,
|
||||
) -> Result<Option<Rectangle>, anyhow::Error> {
|
||||
_: &Self::Capture,
|
||||
) -> Result<Option<Rectangle>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScreenCapture {}
|
||||
pub struct ScreenCapture {
|
||||
image: XImage,
|
||||
}
|
||||
|
||||
impl Capture for ScreenCapture {
|
||||
fn save_to(&self, _: impl AsRef<Path>) -> Result<(), anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn save_cropped_to(
|
||||
&self,
|
||||
_: impl AsRef<Path>,
|
||||
_: Option<Rectangle>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
todo!()
|
||||
to: impl AsRef<Path>,
|
||||
section: Option<Rectangle>,
|
||||
) -> Result<()> {
|
||||
let to = to.as_ref();
|
||||
|
||||
let buffer = self.image.buffer();
|
||||
|
||||
let image = ImageBuffer::<Bgra<u8>, _>::from_raw(
|
||||
self.image.get_width(),
|
||||
self.image.get_height(),
|
||||
buffer.get_buffer().to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let image = DynamicImage::ImageBgra8(image);
|
||||
let mut image = DynamicImage::ImageRgb8(image.into_rgb8());
|
||||
|
||||
let image = if let Some(section) = section {
|
||||
// crop the image
|
||||
image.crop(
|
||||
section.x as u32,
|
||||
section.y as u32,
|
||||
section.width as u32,
|
||||
section.height as u32,
|
||||
)
|
||||
} else {
|
||||
image
|
||||
};
|
||||
|
||||
image.save(to)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -296,10 +296,6 @@ pub struct ScreenCapture {
|
|||
}
|
||||
|
||||
impl Capture for ScreenCapture {
|
||||
fn save_to(&self, to: impl AsRef<Path>) -> Result<()> {
|
||||
self.save_cropped_to(to, None)
|
||||
}
|
||||
|
||||
fn save_cropped_to(&self, to: impl AsRef<Path>, section: Option<Rectangle>) -> Result<()> {
|
||||
let to = to.as_ref();
|
||||
let image = ImageBuffer::<Bgra<u8>, _>::from_raw(
|
||||
|
|
|
@ -3,6 +3,7 @@ extern crate log;
|
|||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
|
||||
#[cfg(feature = "backend-x11")]
|
||||
extern crate leanshot_x11 as x11;
|
||||
|
||||
#[cfg(all(feature = "backend-x11", feature = "backend-xcb"))]
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::ffi;
|
|||
|
||||
use super::cursor::Cursor;
|
||||
use super::event::Event;
|
||||
use super::screen::Screen;
|
||||
use super::visual::Visual;
|
||||
use super::window::Window;
|
||||
|
||||
|
@ -99,15 +100,24 @@ impl Display {
|
|||
self.inner
|
||||
}
|
||||
|
||||
/// Gets the default screen
|
||||
pub fn default_screen(&self) -> Screen {
|
||||
let screen = unsafe { xlib::XDefaultScreen(self.inner) };
|
||||
Screen {
|
||||
display: self,
|
||||
num: screen,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the default visual
|
||||
pub fn default_visual(&self, screen: i32) -> Visual {
|
||||
let visual = unsafe { xlib::XDefaultVisual(self.inner, screen) };
|
||||
pub fn default_visual(&self, screen: Screen) -> Visual {
|
||||
let visual = unsafe { xlib::XDefaultVisual(self.inner, screen.num) };
|
||||
Visual { inner: visual }
|
||||
}
|
||||
|
||||
/// Returns the root window for the given screen.
|
||||
pub fn get_root_window(&self, screen: i32) -> Result<Window> {
|
||||
let inner = unsafe { xlib::XRootWindow(self.inner, screen) };
|
||||
pub fn get_root_window(&self, screen: Screen) -> Result<Window> {
|
||||
let inner = unsafe { xlib::XRootWindow(self.inner, screen.num) };
|
||||
if inner == 0 {
|
||||
return Err(Error::GetWindowError);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ mod drawable;
|
|||
mod event;
|
||||
mod image;
|
||||
mod pixmap;
|
||||
mod screen;
|
||||
mod visual;
|
||||
mod window;
|
||||
|
||||
|
@ -24,5 +25,6 @@ pub use self::drawable::Drawable;
|
|||
pub use self::event::{Event, EventKind};
|
||||
pub use self::image::{Image, ImageByteOrder, PixBuffer};
|
||||
pub use self::pixmap::PixMap;
|
||||
pub use self::screen::Screen;
|
||||
pub use self::visual::{Visual, VisualInfo};
|
||||
pub use self::window::{EventMask, SetWindowAttributes, Window, WindowAttributes};
|
||||
|
|
18
x11/src/xlib/screen.rs
Normal file
18
x11/src/xlib/screen.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use x11::xlib;
|
||||
|
||||
use super::display::Display;
|
||||
|
||||
pub struct Screen<'a> {
|
||||
pub(crate) display: &'a Display,
|
||||
pub(crate) num: i32,
|
||||
}
|
||||
|
||||
impl<'a> Screen<'a> {
|
||||
pub fn width_in_pixels(&self) -> i32 {
|
||||
unsafe { xlib::XDisplayWidth(self.display.inner, self.num) }
|
||||
}
|
||||
|
||||
pub fn height_in_pixels(&self) -> i32 {
|
||||
unsafe { xlib::XDisplayHeight(self.display.inner, self.num) }
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ use crate::rect::Rectangle;
|
|||
|
||||
use super::atom::Atom;
|
||||
use super::display::{Display, GetDisplay};
|
||||
use super::screen::Screen;
|
||||
use super::drawable::Drawable;
|
||||
use super::image::Image;
|
||||
|
||||
|
@ -33,7 +34,7 @@ impl<'a> Window<'a> {
|
|||
Some(parent) => parent,
|
||||
None => display.get_default_root_window()?,
|
||||
};
|
||||
let visual = display.default_visual(0);
|
||||
let visual = display.default_visual(Screen { display, num: 0 });
|
||||
let window = unsafe {
|
||||
xlib::XCreateWindow(
|
||||
display.as_raw(),
|
||||
|
|
Loading…
Reference in a new issue