use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::time::Instant;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub w: u32,
pub h: u32,
}
impl Rect {
pub const fn new(x: i32, y: i32, w: u32, h: u32) -> Self {
Self { x, y, w, h }
}
pub fn to_array(self) -> [i32; 4] {
[self.x, self.y, self.w as i32, self.h as i32]
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WindowInfo {
pub hwnd: isize,
pub title: String,
pub exe: String,
pub class: String,
pub rect: Rect,
pub client_rect: Rect,
pub dpi: u32,
pub foreground: bool,
}
impl WindowInfo {
pub fn synthetic(title: impl Into<String>, w: u32, h: u32) -> Self {
Self {
hwnd: 0,
title: title.into(),
exe: "mock.exe".to_string(),
class: "Mock".to_string(),
rect: Rect::new(0, 0, w, h),
client_rect: Rect::new(0, 0, w, h),
dpi: 96,
foreground: true,
}
}
}
#[derive(Debug, Clone)]
pub struct RawFrame {
pub buffer: Arc<[u8]>,
pub width: u32,
pub height: u32,
pub stride: u32,
pub captured_at: Instant,
pub wall_time: DateTime<Utc>,
pub window: WindowInfo,
}
impl RawFrame {
pub fn from_bgra(
buffer: impl Into<Arc<[u8]>>,
width: u32,
height: u32,
captured_at: Instant,
wall_time: DateTime<Utc>,
window: WindowInfo,
) -> Self {
Self {
buffer: buffer.into(),
width,
height,
stride: width * 4,
captured_at,
wall_time,
window,
}
}
#[inline]
pub fn pixel(&self, x: u32, y: u32) -> (u8, u8, u8, u8) {
let off = (y * self.stride + x * 4) as usize;
let b = self.buffer.get(off).copied().unwrap_or(0);
let g = self.buffer.get(off + 1).copied().unwrap_or(0);
let r = self.buffer.get(off + 2).copied().unwrap_or(0);
let a = self.buffer.get(off + 3).copied().unwrap_or(255);
(b, g, r, a)
}
}