Skip to content

Commit

Permalink
feat: windows支持app_name
Browse files Browse the repository at this point in the history
  • Loading branch information
nashaofu committed Jan 29, 2024
1 parent afc7b46 commit b65f70e
Show file tree
Hide file tree
Showing 12 changed files with 220 additions and 125 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ keywords = ["screen", "monitor", "window", "capture", "image"]

[dependencies]
image = "0.24"
log = "0.4"
thiserror = "1.0"

[target.'cfg(target_os = "macos")'.dependencies]
Expand All @@ -26,6 +27,9 @@ windows = { version = "0.52", features = [
"Win32_Graphics_Dwm",
"Win32_UI_WindowsAndMessaging",
"Win32_Storage_Xps",
"Win32_System_Threading",
"Win32_System_ProcessStatus",
"Win32_Storage_FileSystem",
] }

[target.'cfg(target_os="linux")'.dependencies]
Expand Down
5 changes: 3 additions & 2 deletions examples/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ fn main() {

for monitor in monitors {
println!(
"Monitor: {} {} {:?} {:?}",
"Monitor:\n id: {}\n name: {}\n position: {:?}\n size: {:?}\n state:{:?}\n",
monitor.id(),
monitor.name(),
(monitor.x(), monitor.y(), monitor.width(), monitor.height()),
(monitor.x(), monitor.y()),
(monitor.width(), monitor.height()),
(
monitor.rotation(),
monitor.scale_factor(),
Expand Down
5 changes: 3 additions & 2 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ fn main() {

for window in windows {
println!(
"Window: {} {} {} {:?} {:?} {:?}",
"Window:\n id: {}\n title: {}\n app_name: {}\n monitor: {:?}\n position: {:?}\n size {:?}\n state {:?}\n",
window.id(),
window.title(),
window.app_name(),
window.current_monitor().name(),
(window.x(), window.y(), window.width(), window.height()),
(window.x(), window.y()),
(window.width(), window.height()),
(window.is_minimized(), window.is_maximized())
);
}
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod error;
mod monitor;
mod utils;
mod window;

#[cfg(target_os = "macos")]
Expand Down
10 changes: 4 additions & 6 deletions src/linux/xorg_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use xcb::{
Connection,
};

use crate::{
error::{XCapError, XCapResult},
utils::image::vec_to_rgba_image,
};
use crate::error::{XCapError, XCapResult};

fn get_pixel8_rgba(
bytes: &[u8],
Expand Down Expand Up @@ -97,7 +94,6 @@ pub fn xorg_capture(
let bytes = get_image_reply.data();
let depth = get_image_reply.depth();

let mut rgba = vec![0u8; (width * height * 4) as usize];
let pixmap_format = setup
.pixmap_formats()
.iter()
Expand All @@ -115,6 +111,7 @@ pub fn xorg_capture(
_ => return Err(XCapError::new(format!("Unsupported {} depth", depth))),
};

let mut rgba = vec![0u8; (width * height * 4) as usize];
for y in 0..height {
for x in 0..width {
let index = ((y * width + x) * 4) as usize;
Expand All @@ -127,5 +124,6 @@ pub fn xorg_capture(
}
}

vec_to_rgba_image(width, height, rgba)
RgbaImage::from_raw(width, height, rgba)
.ok_or_else(|| XCapError::new("RgbaImage::from_raw failed"))
}
28 changes: 17 additions & 11 deletions src/macos/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use core_graphics::{
};
use image::RgbaImage;

use crate::{
error::{XCapError, XCapResult},
utils::image::{bgra_to_rgba_image, remove_extra_data},
};
use crate::error::{XCapError, XCapResult};

pub fn capture(
cg_rect: CGRect,
Expand All @@ -20,12 +17,21 @@ pub fn capture(

let width = cg_image.width();
let height = cg_image.height();
let clean_buf = remove_extra_data(
width,
height,
cg_image.bytes_per_row(),
Vec::from(cg_image.data().bytes()),
);
let bytes = Vec::from(cg_image.data().bytes());

// Some platforms e.g. MacOS can have extra bytes at the end of each row.
// See
// https://github.com/nashaofu/xcap/issues/29
// https://github.com/nashaofu/xcap/issues/38
let mut buffer = Vec::with_capacity(width * height * 4);
for row in bytes.chunks_exact(cg_image.bytes_per_row()) {
buffer.extend_from_slice(&row[..width * 4]);
}

for bgra in buffer.chunks_exact_mut(4) {
bgra.swap(0, 2);
}

bgra_to_rgba_image(width as u32, height as u32, clean_buf)
RgbaImage::from_raw(width as u32, height as u32, buffer)
.ok_or_else(|| XCapError::new("RgbaImage::from_raw failed"))
}
71 changes: 0 additions & 71 deletions src/utils/image.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/utils/mod.rs

This file was deleted.

50 changes: 46 additions & 4 deletions src/windows/boxed.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use log::error;
use std::{ops::Deref, ptr};
use windows::{
core::PCWSTR,
Win32::{
Foundation::HWND,
Foundation::{CloseHandle, HANDLE, HWND},
Graphics::Gdi::{CreateDCW, DeleteDC, DeleteObject, GetWindowDC, ReleaseDC, HBITMAP, HDC},
System::Threading::{OpenProcess, PROCESS_ACCESS_RIGHTS},
},
};

use crate::XCapResult;

#[derive(Debug)]
pub(super) struct BoxHDC {
hdc: HDC,
hwnd: Option<HWND>,
Expand All @@ -25,9 +30,13 @@ impl Drop for BoxHDC {
// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-releasedc
unsafe {
if let Some(hwnd) = self.hwnd {
ReleaseDC(hwnd, self.hdc);
if ReleaseDC(hwnd, self.hdc) != 1 {
error!("ReleaseDC {:?} failed", self)
}
} else {
DeleteDC(self.hdc);
if !DeleteDC(self.hdc).as_bool() {
error!("DeleteDC {:?} failed", self)
}
}
};
}
Expand Down Expand Up @@ -66,6 +75,7 @@ impl From<HWND> for BoxHDC {
}
}

#[derive(Debug)]
pub(super) struct BoxHBITMAP(HBITMAP);

impl Deref for BoxHBITMAP {
Expand All @@ -79,7 +89,9 @@ impl Drop for BoxHBITMAP {
fn drop(&mut self) {
// https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap
unsafe {
DeleteObject(self.0);
if !DeleteObject(self.0).as_bool() {
error!("DeleteObject {:?} failed", self)
}
};
}
}
Expand All @@ -89,3 +101,33 @@ impl BoxHBITMAP {
BoxHBITMAP(h_bitmap)
}
}

#[derive(Debug)]
pub(super) struct BoxProcessHandle(HANDLE);

impl Deref for BoxProcessHandle {
type Target = HANDLE;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl Drop for BoxProcessHandle {
fn drop(&mut self) {
unsafe {
CloseHandle(self.0).unwrap_or_else(|_| error!("CloseHandle {:?} failed", self));
};
}
}

impl BoxProcessHandle {
pub fn open(
dw_desired_access: PROCESS_ACCESS_RIGHTS,
b_inherit_handle: bool,
dw_process_id: u32,
) -> XCapResult<Self> {
let h_process = unsafe { OpenProcess(dw_desired_access, b_inherit_handle, dw_process_id)? };

Ok(BoxProcessHandle(h_process))
}
}
21 changes: 13 additions & 8 deletions src/windows/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ use windows::Win32::{
UI::WindowsAndMessaging::{GetDesktopWindow, PW_RENDERFULLCONTENT},
};

use crate::{
error::{XCapError, XCapResult},
utils::image::bgra_to_rgba_image,
};
use crate::error::{XCapError, XCapResult};

use super::boxed::{BoxHBITMAP, BoxHDC};

Expand All @@ -40,8 +37,7 @@ fn to_rgba_image(
bmiColors: [RGBQUAD::default(); 1],
};

let data = vec![0u8; (width * height) as usize * 4];
let buf_prt = data.as_ptr() as *mut _;
let mut buffer = vec![0u8; (width * height) as usize * 4];

unsafe {
// 读取数据到 buffer 中
Expand All @@ -50,7 +46,7 @@ fn to_rgba_image(
*box_h_bitmap,
0,
height as u32,
Some(buf_prt),
Some(buffer.as_mut_ptr().cast()),
&mut bitmap_info,
DIB_RGB_COLORS,
) == 0;
Expand All @@ -60,7 +56,16 @@ fn to_rgba_image(
}
};

bgra_to_rgba_image(width as u32, height as u32, data)
for src in buffer.chunks_exact_mut(4) {
src.swap(0, 2);
// fix https://github.com/nashaofu/xcap/issues/92#issuecomment-1910014951
if src[3] == 0 {
src[3] = 255;
}
}

RgbaImage::from_raw(width as u32, height as u32, buffer)
.ok_or_else(|| XCapError::new("RgbaImage::from_raw failed"))
}

#[allow(unused)]
Expand Down
Loading

0 comments on commit b65f70e

Please sign in to comment.