#[cfg(feature = "wayland")]
use crate::{
error::{CaptureError, CaptureResult},
types::{CaptureRegion, DisplayInfo, PixelFormat, RawImage},
};
#[cfg(feature = "wayland")]
use wayland_client::{
protocol::{wl_output, wl_registry},
Connection, Dispatch, QueueHandle,
};
#[cfg(feature = "wayland")]
pub struct WaylandCapture {
connection: Connection,
outputs: Vec<WaylandOutput>,
}
#[cfg(feature = "wayland")]
struct WaylandOutput {
output: wl_output::WlOutput,
name: String,
width: u32,
height: u32,
x: i32,
y: i32,
scale: i32,
refresh_rate: u32,
}
#[cfg(feature = "wayland")]
impl WaylandCapture {
pub fn new() -> CaptureResult<Self> {
let connection = Connection::connect_to_env().map_err(|e| {
CaptureError::PlatformError(format!("Failed to connect to Wayland: {}", e))
})?;
let outputs = Self::enumerate_outputs(&connection)?;
Ok(Self {
connection,
outputs,
})
}
fn enumerate_outputs(connection: &Connection) -> CaptureResult<Vec<WaylandOutput>> {
Ok(Vec::new())
}
pub fn get_displays(&self) -> CaptureResult<Vec<DisplayInfo>> {
if self.outputs.is_empty() {
return self.get_displays_via_portal();
}
Ok(self
.outputs
.iter()
.enumerate()
.map(|(index, output)| DisplayInfo {
index,
name: output.name.clone(),
width: output.width,
height: output.height,
x: output.x,
y: output.y,
scale_factor: output.scale as f32,
is_primary: index == 0,
refresh_rate: output.refresh_rate,
color_depth: 32,
})
.collect())
}
fn get_displays_via_portal(&self) -> CaptureResult<Vec<DisplayInfo>> {
#[cfg(feature = "dbus")]
{
use dbus::blocking::Connection;
use std::time::Duration;
let conn = Connection::new_session().map_err(|e| {
CaptureError::PlatformError(format!("Failed to connect to D-Bus: {}", e))
})?;
Ok(vec![DisplayInfo {
index: 0,
name: "Wayland Display".to_string(),
width: 1920,
height: 1080,
x: 0,
y: 0,
scale_factor: 1.0,
is_primary: true,
refresh_rate: 60,
color_depth: 32,
}])
}
#[cfg(not(feature = "dbus"))]
{
Err(CaptureError::PlatformError(
"Wayland capture requires D-Bus support (enable 'dbus' feature)".to_string(),
))
}
}
pub fn capture_display(&self, display_index: usize) -> CaptureResult<RawImage> {
self.capture_via_portal(display_index)
}
pub fn capture_region(&self, region: CaptureRegion) -> CaptureResult<RawImage> {
Err(CaptureError::CaptureFailed(
"Wayland region capture requires portal implementation".to_string(),
))
}
fn capture_via_portal(&self, _display_index: usize) -> CaptureResult<RawImage> {
#[cfg(feature = "dbus")]
{
Err(CaptureError::CaptureFailed(
"Portal-based capture not yet fully implemented".to_string(),
))
}
#[cfg(not(feature = "dbus"))]
{
Err(CaptureError::PlatformError(
"Wayland capture requires D-Bus support".to_string(),
))
}
}
pub fn is_screencast_available(&self) -> bool {
#[cfg(feature = "dbus")]
{
if let Ok(conn) = dbus::blocking::Connection::new_session() {
let proxy = conn.with_proxy(
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
std::time::Duration::from_millis(100),
);
use dbus::blocking::stdintf::org_freedesktop_dbus::Introspectable;
proxy.introspect().is_ok()
} else {
false
}
}
#[cfg(not(feature = "dbus"))]
false
}
}
#[cfg(not(feature = "wayland"))]
pub struct WaylandCapture;
#[cfg(not(feature = "wayland"))]
impl WaylandCapture {
pub fn new() -> CaptureResult<Self> {
Err(CaptureError::PlatformError(
"Wayland support not enabled (compile with 'wayland' feature)".to_string(),
))
}
pub fn get_displays(&self) -> CaptureResult<Vec<crate::types::DisplayInfo>> {
unreachable!()
}
pub fn capture_display(&self, _display_index: usize) -> CaptureResult<crate::types::RawImage> {
unreachable!()
}
pub fn capture_region(&self, _region: crate::types::CaptureRegion) -> CaptureResult<crate::types::RawImage> {
unreachable!()
}
}