Skip to main content

webp_screenshot_rust/capture/linux/
mod.rs

1//! Linux screen capture implementation
2
3#[cfg(target_os = "linux")]
4mod x11_capture;
5
6#[cfg(all(target_os = "linux", feature = "wayland"))]
7mod wayland_capture;
8
9#[cfg(target_os = "linux")]
10use crate::{
11    capture::traits::{CaptureCapabilities, ScreenCapture},
12    error::{CaptureError, CaptureResult},
13    types::{CaptureRegion, DisplayInfo, RawImage},
14};
15
16/// Linux screen capture implementation
17#[cfg(target_os = "linux")]
18pub struct LinuxCapture {
19    backend: LinuxBackend,
20}
21
22#[cfg(target_os = "linux")]
23enum LinuxBackend {
24    X11(x11_capture::X11Capture),
25    #[cfg(feature = "wayland")]
26    Wayland(wayland_capture::WaylandCapture),
27}
28
29#[cfg(target_os = "linux")]
30impl LinuxCapture {
31    /// Create a new Linux capturer
32    pub fn new() -> CaptureResult<Box<dyn ScreenCapture>> {
33        // Detect which backend to use
34        let backend = Self::detect_backend()?;
35
36        Ok(Box::new(Self { backend }))
37    }
38
39    /// Detect whether to use X11 or Wayland
40    fn detect_backend() -> CaptureResult<LinuxBackend> {
41        // Check for Wayland session
42        #[cfg(feature = "wayland")]
43        {
44            if std::env::var("WAYLAND_DISPLAY").is_ok() {
45                if let Ok(wayland) = wayland_capture::WaylandCapture::new() {
46                    return Ok(LinuxBackend::Wayland(wayland));
47                }
48            }
49        }
50
51        // Check for X11 session
52        if std::env::var("DISPLAY").is_ok() {
53            let x11 = x11_capture::X11Capture::new()?;
54            return Ok(LinuxBackend::X11(x11));
55        }
56
57        Err(CaptureError::PlatformError(
58            "No X11 or Wayland display found".to_string(),
59        ))
60    }
61}
62
63#[cfg(target_os = "linux")]
64impl ScreenCapture for LinuxCapture {
65    fn get_displays(&self) -> CaptureResult<Vec<DisplayInfo>> {
66        match &self.backend {
67            LinuxBackend::X11(x11) => x11.get_displays(),
68            #[cfg(feature = "wayland")]
69            LinuxBackend::Wayland(wayland) => wayland.get_displays(),
70        }
71    }
72
73    fn capture_display(&self, display_index: usize) -> CaptureResult<RawImage> {
74        match &self.backend {
75            LinuxBackend::X11(x11) => x11.capture_display(display_index),
76            #[cfg(feature = "wayland")]
77            LinuxBackend::Wayland(wayland) => wayland.capture_display(display_index),
78        }
79    }
80
81    fn capture_region(&self, region: CaptureRegion) -> CaptureResult<RawImage> {
82        match &self.backend {
83            LinuxBackend::X11(x11) => x11.capture_region(region),
84            #[cfg(feature = "wayland")]
85            LinuxBackend::Wayland(wayland) => wayland.capture_region(region),
86        }
87    }
88
89    fn implementation_name(&self) -> String {
90        match &self.backend {
91            LinuxBackend::X11(_) => "Linux X11".to_string(),
92            #[cfg(feature = "wayland")]
93            LinuxBackend::Wayland(_) => "Linux Wayland".to_string(),
94        }
95    }
96
97    fn capabilities(&self) -> CaptureCapabilities {
98        CaptureCapabilities {
99            supports_cursor: true,
100            supports_window_capture: true,
101            supports_hdr: false,
102            max_resolution: (0, 0), // No limit
103            supports_multi_display: true,
104            supports_gpu_acceleration: false,
105            estimated_latency_ms: 20,
106        }
107    }
108}
109
110// Stub for non-Linux platforms
111#[cfg(not(target_os = "linux"))]
112pub struct LinuxCapture;
113
114#[cfg(not(target_os = "linux"))]
115impl LinuxCapture {
116    pub fn new() -> CaptureResult<Box<dyn ScreenCapture>> {
117        Err(CaptureError::PlatformError(
118            "Linux capture is only available on Linux".to_string(),
119        ))
120    }
121}