Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Monitor:all or Window::all panic #119

Merged
merged 3 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ jobs:
override: true
components: rustfmt, clippy

- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2

- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xcap"
version = "0.0.7"
version = "0.0.8"
edition = "2021"
description = "XCap is a cross-platform screen capture library written in Rust. It supports Linux (X11, Wayland), MacOS, and Windows. XCap supports screenshot and video recording (to be implemented)."
license = "Apache-2.0"
Expand Down
8 changes: 4 additions & 4 deletions examples/monitor_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use xcap::Monitor;

fn normalized(filename: &str) -> String {
filename
.replace("|", "")
.replace("\\", "")
.replace(":", "")
.replace("/", "")
.replace('|', "")
.replace('\\', "")
.replace(':', "")
.replace('/', "")
}

fn main() {
Expand Down
8 changes: 4 additions & 4 deletions examples/window_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use xcap::Window;

fn normalized(filename: &str) -> String {
filename
.replace("|", "")
.replace("\\", "")
.replace(":", "")
.replace("/", "")
.replace('|', "")
.replace('\\', "")
.replace(':', "")
.replace('/', "")
}

fn main() {
Expand Down
30 changes: 21 additions & 9 deletions src/linux/impl_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn get_scale_factor(conn: &Connection, screen: &Screen) -> XCapResult<f32> {
.strip_prefix(xft_dpi_prefix)
.ok_or_else(|| XCapError::new("Xft.dpi parse failed"))?;

let dpi = xft_dpi.parse::<f32>().map_err(|err| XCapError::new(err))?;
let dpi = xft_dpi.parse::<f32>().map_err(XCapError::new)?;

Ok(dpi / 96.0)
}
Expand Down Expand Up @@ -178,29 +178,41 @@ impl ImplMonitor {

let mode_infos = get_screen_resources_reply.modes();

let mut impl_monitor = Vec::new();
let mut impl_monitors = Vec::new();

for monitor_info in monitor_info_iterator {
let output = monitor_info
.outputs()
.get(0)
.ok_or_else(|| XCapError::new("Not found output"))?;
let output = match monitor_info.outputs().first() {
Some(output) => output,
_ => continue,
};

let (rotation, frequency) =
get_rotation_frequency(&conn, mode_infos, output).unwrap_or((0.0, 0.0));

impl_monitor.push(ImplMonitor::new(
if let Ok(impl_monitor) = ImplMonitor::new(
&conn,
screen,
monitor_info,
output,
rotation,
scale_factor,
frequency,
)?);
) {
impl_monitors.push(impl_monitor);
} else {
log::error!(
"ImplMonitor::new(&conn, {:?}, {:?}, {:?}, {}, {}, {}) failed",
screen,
monitor_info,
output,
rotation,
scale_factor,
frequency
);
}
}

Ok(impl_monitor)
Ok(impl_monitors)
}

pub fn from_point(x: i32, y: i32) -> XCapResult<ImplMonitor> {
Expand Down
32 changes: 26 additions & 6 deletions src/linux/impl_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl ImplWindow {
let current_monitor = {
let mut max_area = 0;
let mut find_result = impl_monitors
.get(0)
.first()
.ok_or(XCapError::new("Get screen info failed"))?;

let window_rect = Rect::new(x, y, width, height);
Expand Down Expand Up @@ -198,14 +198,34 @@ impl ImplWindow {
let query_pointer_cookie = conn.send_request(&QueryPointer {
window: root_window,
});
let query_pointer_reply = conn.wait_for_reply(query_pointer_cookie)?;
let query_pointer_reply = match conn.wait_for_reply(query_pointer_cookie) {
Ok(query_pointer_reply) => query_pointer_reply,
_ => continue,
};

if query_pointer_reply.same_screen() {
let list_window_reply =
get_window_property(&conn, root_window, client_list_atom, ATOM_NONE, 0, 100)?;
let list_window_reply = match get_window_property(
&conn,
root_window,
client_list_atom,
ATOM_NONE,
0,
100,
) {
Ok(list_window_reply) => list_window_reply,
_ => continue,
};

for client in list_window_reply.value::<Window>() {
impl_windows.push(ImplWindow::new(&conn, client, &impl_monitors)?);
if let Ok(impl_window) = ImplWindow::new(&conn, client, &impl_monitors) {
impl_windows.push(impl_window);
} else {
log::error!(
"ImplWindow::new(&conn, {:?}, {:?}) failed",
client,
&impl_monitors
);
}
}
}
}
Expand All @@ -216,6 +236,6 @@ impl ImplWindow {

impl ImplWindow {
pub fn capture_image(&self) -> XCapResult<RgbaImage> {
capture_window(&self)
capture_window(self)
}
}
11 changes: 9 additions & 2 deletions src/macos/impl_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern "C" {
}

impl ImplMonitor {
fn new(id: CGDirectDisplayID) -> XCapResult<ImplMonitor> {
pub(super) fn new(id: CGDirectDisplayID) -> XCapResult<ImplMonitor> {
let cg_display = CGDisplay::new(id);
let screen_num = cg_display.model_number();
let cg_rect = cg_display.bounds();
Expand Down Expand Up @@ -63,7 +63,14 @@ impl ImplMonitor {
let mut impl_monitors: Vec<ImplMonitor> = Vec::with_capacity(display_ids.len());

for display_id in display_ids {
impl_monitors.push(ImplMonitor::new(display_id)?);
// 运行过程中,如果遇到显示器插拔,可能会导致调用报错
// 对于报错的情况,就把报错的情况给排除掉
// https://github.com/nashaofu/xcap/issues/118
if let Ok(impl_monitor) = ImplMonitor::new(display_id) {
impl_monitors.push(impl_monitor);
} else {
log::error!("ImplMonitor::new({}) failed", display_id);
}
}

Ok(impl_monitors)
Expand Down
Loading
Loading