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 20, 2024
1 parent a60dd0e commit 56aea0e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 18 deletions.
5 changes: 3 additions & 2 deletions examples/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ fn main() {

for monitor in monitors {
println!(
"Monitor: {:?} {:?} {:?}",
"Monitor: {} {} {:?} {:?}",
monitor.id(),
monitor.name(),
(
monitor.x(),
monitor.y(),
Expand All @@ -27,7 +28,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
57 changes: 43 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,38 @@ 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 = None;
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 = Some(impl_monitor);
}
}

find_result
.ok_or(ScreenCaptureError::new("window monitor is None"))?
.to_owned()
};

let (is_minimized, is_maximized) = {
Expand Down Expand Up @@ -144,10 +171,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 +189,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 +204,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,6 +1,7 @@
mod capture;
mod wayland_capture;
mod xorg_capture;
mod utils;

pub mod impl_monitor;
pub mod impl_window;
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
}
}

0 comments on commit 56aea0e

Please sign in to comment.