Skip to content

Commit

Permalink
feat: linux x11相关代码实现
Browse files Browse the repository at this point in the history
  • Loading branch information
nashaofu committed Jan 21, 2024
1 parent 308d5d9 commit bedd290
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 25 deletions.
12 changes: 4 additions & 8 deletions examples/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ fn main() {

for monitor in monitors {
println!(
"Monitor: {:?} {:?} {:?}",
"Monitor: {} {} {:?} {:?}",
monitor.id(),
(
monitor.x(),
monitor.y(),
monitor.width(),
monitor.height()
),
monitor.name(),
(monitor.x(), monitor.y(), monitor.width(), monitor.height()),
(
monitor.rotation(),
monitor.scale_factor(),
Expand All @@ -27,7 +23,7 @@ fn main() {

let monitor = Monitor::from_point(100, 100).unwrap();

println!("Monitor::from_point(): {:?}", monitor);
println!("Monitor::from_point(): {}", monitor.name());
println!(
"Monitor::from_point(100, 100) 运行耗时: {:?}",
start.elapsed()
Expand Down
4 changes: 2 additions & 2 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ fn main() {

for window in windows {
println!(
"Window: {} {} {:?} {:?} {:?} {:?}",
"Window: {} {} {} {:?} {:?} {:?}",
window.id(),
window.title(),
window.app_name(),
window.current_monitor(),
window.current_monitor().name(),
(window.x(), window.y(), window.width(), window.height()),
(window.is_minimized(), window.is_maximized())
);
Expand Down
58 changes: 44 additions & 14 deletions src/linux/impl_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use xcb::{

use crate::error::{ScreenCaptureError, ScreenCaptureResult};

use super::{capture::capture_window, impl_monitor::ImplMonitor};
use super::{capture::capture_window, impl_monitor::ImplMonitor, utils::Rect};

#[derive(Debug, Clone)]
pub(crate) struct ImplWindow {
pub window: Window,
pub id: u32,
pub title: String,
pub app_name: String,
pub impl_monitor: ImplMonitor,
pub current_monitor: ImplMonitor,
pub x: i32,
pub y: i32,
pub width: u32,
Expand Down Expand Up @@ -66,7 +66,11 @@ fn get_window_property(
}

impl ImplWindow {
fn new(conn: &Connection, window: &Window) -> ScreenCaptureResult<ImplWindow> {
fn new(
conn: &Connection,
window: &Window,
impl_monitors: &Vec<ImplMonitor>,
) -> ScreenCaptureResult<ImplWindow> {
let title = {
let get_title_reply =
get_window_property(conn, *window, ATOM_WM_NAME, ATOM_STRING, 0, 1024)?;
Expand Down Expand Up @@ -101,15 +105,39 @@ impl ImplWindow {
let translate_coordinates_reply = conn.wait_for_reply(translate_coordinates_cookie)?;

(
translate_coordinates_reply.dst_x() - get_geometry_reply.x(),
translate_coordinates_reply.dst_y() - get_geometry_reply.y(),
get_geometry_reply.width(),
get_geometry_reply.height(),
(translate_coordinates_reply.dst_x() - get_geometry_reply.x()) as i32,
(translate_coordinates_reply.dst_y() - get_geometry_reply.y()) as i32,
get_geometry_reply.width() as u32,
get_geometry_reply.height() as u32,
)
};

let s = {
ImplMonitor::all().iter()
let current_monitor = {
let mut max_area = 0;
let mut find_result = impl_monitors
.get(0)
.ok_or(ScreenCaptureError::new("Get screen info failed"))?;

let window_rect = Rect::new(x, y, width, height);

// window与哪一个monitor交集最大就属于那个monitor
for impl_monitor in impl_monitors {
let monitor_rect = Rect::new(
impl_monitor.x,
impl_monitor.y,
impl_monitor.width,
impl_monitor.height,
);

// 获取最大的面积
let area = window_rect.overlap_area(monitor_rect);
if area > max_area {
max_area = area;
find_result = impl_monitor;
}
}

find_result.to_owned()
};

let (is_minimized, is_maximized) = {
Expand Down Expand Up @@ -144,10 +172,11 @@ impl ImplWindow {
id: window.resource_id(),
title,
app_name,
x: x as i32,
y: y as i32,
width: width as u32,
height: height as u32,
current_monitor,
x,
y,
width,
height,
is_minimized,
is_maximized,
})
Expand All @@ -161,6 +190,7 @@ impl ImplWindow {
let client_list_atom = get_atom(&conn, "_NET_CLIENT_LIST")?;

let mut impl_windows = Vec::new();
let impl_monitors = ImplMonitor::all()?;

for screen in setup.roots() {
let root_window = screen.root();
Expand All @@ -175,7 +205,7 @@ impl ImplWindow {
get_window_property(&conn, root_window, client_list_atom, ATOM_NONE, 0, 100)?;

for client in list_window_reply.value::<Window>() {
impl_windows.push(ImplWindow::new(&conn, client)?);
impl_windows.push(ImplWindow::new(&conn, client, &impl_monitors)?);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod capture;
mod utils;
mod wayland_capture;
mod xorg_capture;

Expand Down
32 changes: 32 additions & 0 deletions src/linux/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
pub(super) struct Rect {
x: i32,
y: i32,
width: u32,
height: u32,
}

impl Rect {
// 计算两个矩形的交集面积
pub(super) fn new(x: i32, y: i32, width: u32, height: u32) -> Rect {
Rect {
x,
y,
width,
height,
}
}

// 计算两个矩形的交集面积
pub(super) fn overlap_area(&self, other_rect: Rect) -> i32 {
let left = self.x.max(other_rect.x);
let top = self.y.max(other_rect.y);
let right = (self.x + self.width as i32).min(other_rect.x + other_rect.width as i32);
let bottom = (self.y + self.height as i32).min(other_rect.y + other_rect.height as i32);

// 与0比较,如果小于0则表示两个矩形无交集
let width = (right - left).max(0);
let height = (bottom - top).max(0);

width * height
}
}
2 changes: 1 addition & 1 deletion src/windows/impl_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl ImplWindow {
window_info,
id: hwnd.0 as u32,
title,
app_name: String::from(""),
app_name: String::from("Unsupported"),
current_monitor: ImplMonitor::new(hmonitor)?,
x: rc_client.left,
y: rc_client.top,
Expand Down

0 comments on commit bedd290

Please sign in to comment.