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"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
|
||||||
"image",
|
"image",
|
||||||
"leanshot-x11",
|
"leanshot-x11",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
25
Cargo.toml
25
Cargo.toml
|
@ -12,19 +12,28 @@ members = ["x11"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["backend-x11", "backend-x11-glx"]
|
default = ["backend-x11", "backend-x11-glx"]
|
||||||
backend-x11 = []
|
backend-x11 = ["leanshot-x11"]
|
||||||
backend-x11-glx = ["backend-x11"]
|
backend-x11-glx = ["backend-x11", "leanshot-x11/glx"]
|
||||||
backend-xcb = ["xcb-util", "xcb"]
|
backend-xcb = ["xcb-util", "xcb"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.38"
|
anyhow = "1.0.42"
|
||||||
image = { version = "0.23.13", default-features = false, features = ["jpeg", "png"] }
|
image = { version = "0.23.14", default-features = false, features = ["jpeg", "png"] }
|
||||||
leanshot-x11 = { path = "x11" }
|
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
stderrlog = "0.5.1"
|
stderrlog = "0.5.1"
|
||||||
structopt = "0.3.21"
|
structopt = "0.3.22"
|
||||||
libc = "0.2.86"
|
libc = "0.2.98"
|
||||||
|
|
||||||
|
# x11
|
||||||
|
leanshot-x11 = { path = "x11", optional = true }
|
||||||
|
|
||||||
|
# xcb
|
||||||
xcb-util = { version = "0.3.0", features = ["image", "cursor"], optional = true }
|
xcb-util = { version = "0.3.0", features = ["image", "cursor"], optional = true }
|
||||||
xcb = { version = "0.9.0", 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 {
|
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<()>;
|
fn save_cropped_to(&self, path: impl AsRef<Path>, section: Option<Rectangle>) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Result;
|
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::gui_trait::{Capture, Gui};
|
||||||
use crate::rect::Rectangle;
|
use crate::rect::Rectangle;
|
||||||
|
@ -15,33 +16,71 @@ impl X11Gui {
|
||||||
let disp = Display::connect(None)?;
|
let disp = Display::connect(None)?;
|
||||||
Ok(X11Gui { conn: disp })
|
Ok(X11Gui { conn: disp })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_default_screen(&self) -> Screen {
|
||||||
|
self.conn.default_screen()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gui for X11Gui {
|
impl Gui for X11Gui {
|
||||||
type Capture = ScreenCapture;
|
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(
|
fn interactive_select(
|
||||||
&self,
|
&self,
|
||||||
_: &<Self as Gui>::Capture,
|
_: &Self::Capture,
|
||||||
) -> Result<Option<Rectangle>, anyhow::Error> {
|
) -> Result<Option<Rectangle>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScreenCapture {}
|
pub struct ScreenCapture {
|
||||||
|
image: XImage,
|
||||||
|
}
|
||||||
|
|
||||||
impl Capture for ScreenCapture {
|
impl Capture for ScreenCapture {
|
||||||
fn save_to(&self, _: impl AsRef<Path>) -> Result<(), anyhow::Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_cropped_to(
|
fn save_cropped_to(
|
||||||
&self,
|
&self,
|
||||||
_: impl AsRef<Path>,
|
to: impl AsRef<Path>,
|
||||||
_: Option<Rectangle>,
|
section: Option<Rectangle>,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<()> {
|
||||||
todo!()
|
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 {
|
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<()> {
|
fn save_cropped_to(&self, to: impl AsRef<Path>, section: Option<Rectangle>) -> Result<()> {
|
||||||
let to = to.as_ref();
|
let to = to.as_ref();
|
||||||
let image = ImageBuffer::<Bgra<u8>, _>::from_raw(
|
let image = ImageBuffer::<Bgra<u8>, _>::from_raw(
|
||||||
|
|
|
@ -3,6 +3,7 @@ extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate anyhow;
|
extern crate anyhow;
|
||||||
|
|
||||||
|
#[cfg(feature = "backend-x11")]
|
||||||
extern crate leanshot_x11 as x11;
|
extern crate leanshot_x11 as x11;
|
||||||
|
|
||||||
#[cfg(all(feature = "backend-x11", feature = "backend-xcb"))]
|
#[cfg(all(feature = "backend-x11", feature = "backend-xcb"))]
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::ffi;
|
||||||
|
|
||||||
use super::cursor::Cursor;
|
use super::cursor::Cursor;
|
||||||
use super::event::Event;
|
use super::event::Event;
|
||||||
|
use super::screen::Screen;
|
||||||
use super::visual::Visual;
|
use super::visual::Visual;
|
||||||
use super::window::Window;
|
use super::window::Window;
|
||||||
|
|
||||||
|
@ -99,15 +100,24 @@ impl Display {
|
||||||
self.inner
|
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
|
/// Gets the default visual
|
||||||
pub fn default_visual(&self, screen: i32) -> Visual {
|
pub fn default_visual(&self, screen: Screen) -> Visual {
|
||||||
let visual = unsafe { xlib::XDefaultVisual(self.inner, screen) };
|
let visual = unsafe { xlib::XDefaultVisual(self.inner, screen.num) };
|
||||||
Visual { inner: visual }
|
Visual { inner: visual }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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> {
|
pub fn get_root_window(&self, screen: Screen) -> Result<Window> {
|
||||||
let inner = unsafe { xlib::XRootWindow(self.inner, screen) };
|
let inner = unsafe { xlib::XRootWindow(self.inner, screen.num) };
|
||||||
if inner == 0 {
|
if inner == 0 {
|
||||||
return Err(Error::GetWindowError);
|
return Err(Error::GetWindowError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod drawable;
|
||||||
mod event;
|
mod event;
|
||||||
mod image;
|
mod image;
|
||||||
mod pixmap;
|
mod pixmap;
|
||||||
|
mod screen;
|
||||||
mod visual;
|
mod visual;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
|
@ -24,5 +25,6 @@ pub use self::drawable::Drawable;
|
||||||
pub use self::event::{Event, EventKind};
|
pub use self::event::{Event, EventKind};
|
||||||
pub use self::image::{Image, ImageByteOrder, PixBuffer};
|
pub use self::image::{Image, ImageByteOrder, PixBuffer};
|
||||||
pub use self::pixmap::PixMap;
|
pub use self::pixmap::PixMap;
|
||||||
|
pub use self::screen::Screen;
|
||||||
pub use self::visual::{Visual, VisualInfo};
|
pub use self::visual::{Visual, VisualInfo};
|
||||||
pub use self::window::{EventMask, SetWindowAttributes, Window, WindowAttributes};
|
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::atom::Atom;
|
||||||
use super::display::{Display, GetDisplay};
|
use super::display::{Display, GetDisplay};
|
||||||
|
use super::screen::Screen;
|
||||||
use super::drawable::Drawable;
|
use super::drawable::Drawable;
|
||||||
use super::image::Image;
|
use super::image::Image;
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ impl<'a> Window<'a> {
|
||||||
Some(parent) => parent,
|
Some(parent) => parent,
|
||||||
None => display.get_default_root_window()?,
|
None => display.get_default_root_window()?,
|
||||||
};
|
};
|
||||||
let visual = display.default_visual(0);
|
let visual = display.default_visual(Screen { display, num: 0 });
|
||||||
let window = unsafe {
|
let window = unsafe {
|
||||||
xlib::XCreateWindow(
|
xlib::XCreateWindow(
|
||||||
display.as_raw(),
|
display.as_raw(),
|
||||||
|
|
Loading…
Reference in a new issue