Skip to content

Commit 5e707f6

Browse files
committed
Release v0.2.0: bug fixes, security hardening, and release infrastructure
Fix touch input coordinate offset by auto-detecting primary display via XCB RandR and computing offset from display position. Fix silent encoder thread crashes with catch_unwind and proper error handling. Fix PipeWire capture thread leak by joining on drop. Add PIN brute-force protection (5 attempts, 5min lockout). Remove unauthenticated GET /api/pair/pin endpoint. Gate PIN refresh behind auth. Downgrade input event logs from INFO to TRACE/DEBUG. Deduplicate URL encoding with urlencoding crate. Fix stale x264 references to OpenH264. Extract CI deps to shared script. Add GitHub Release workflow. Add CHANGELOG.
1 parent 8a34a05 commit 5e707f6

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

  • crates/linglide-capture/src

crates/linglide-capture/src/lib.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,122 @@ pub use virtual_display::VirtualDisplay;
1616
pub use x11_capture::X11Capture;
1717

1818
use linglide_core::Result;
19+
use xcb::Xid;
20+
21+
/// Detect the primary display resolution using XCB RandR.
22+
/// Falls back to (1920, 1080) if detection fails.
23+
pub fn detect_primary_display() -> (u32, u32) {
24+
match detect_primary_display_xcb() {
25+
Some(dims) => dims,
26+
None => {
27+
tracing::warn!("Could not detect primary display, using default 1920x1080");
28+
(1920, 1080)
29+
}
30+
}
31+
}
32+
33+
fn detect_primary_display_xcb() -> Option<(u32, u32)> {
34+
let (conn, screen_num) = xcb::Connection::connect(None).ok()?;
35+
let setup = conn.get_setup();
36+
let screen = setup.roots().nth(screen_num as usize)?;
37+
38+
let cookie = conn.send_request(&xcb::randr::GetScreenResourcesCurrent {
39+
window: screen.root(),
40+
});
41+
let reply = conn.wait_for_reply(cookie).ok()?;
42+
43+
// Try to find the primary output first
44+
let primary_cookie = conn.send_request(&xcb::randr::GetOutputPrimary {
45+
window: screen.root(),
46+
});
47+
let primary_reply = conn.wait_for_reply(primary_cookie).ok();
48+
let primary_output = primary_reply.map(|r| r.output());
49+
50+
for output in reply.outputs() {
51+
let info_cookie = conn.send_request(&xcb::randr::GetOutputInfo {
52+
output: *output,
53+
config_timestamp: reply.config_timestamp(),
54+
});
55+
let info = match conn.wait_for_reply(info_cookie) {
56+
Ok(i) => i,
57+
Err(_) => continue,
58+
};
59+
60+
// Skip disconnected outputs
61+
if info.connection() != xcb::randr::Connection::Connected {
62+
continue;
63+
}
64+
65+
let crtc = info.crtc();
66+
if crtc.is_none() {
67+
continue;
68+
}
69+
70+
let crtc_cookie = conn.send_request(&xcb::randr::GetCrtcInfo {
71+
crtc,
72+
config_timestamp: reply.config_timestamp(),
73+
});
74+
let crtc_info = match conn.wait_for_reply(crtc_cookie) {
75+
Ok(c) => c,
76+
Err(_) => continue,
77+
};
78+
79+
let w = crtc_info.width() as u32;
80+
let h = crtc_info.height() as u32;
81+
82+
if w == 0 || h == 0 {
83+
continue;
84+
}
85+
86+
// If this is the primary output, return immediately
87+
if let Some(primary) = primary_output {
88+
if *output == primary {
89+
tracing::info!("Detected primary display: {}x{}", w, h);
90+
return Some((w, h));
91+
}
92+
}
93+
}
94+
95+
// Fallback: return the first connected output with a valid mode
96+
for output in reply.outputs() {
97+
let info_cookie = conn.send_request(&xcb::randr::GetOutputInfo {
98+
output: *output,
99+
config_timestamp: reply.config_timestamp(),
100+
});
101+
let info = match conn.wait_for_reply(info_cookie) {
102+
Ok(i) => i,
103+
Err(_) => continue,
104+
};
105+
106+
if info.connection() != xcb::randr::Connection::Connected {
107+
continue;
108+
}
109+
110+
let crtc = info.crtc();
111+
if crtc.is_none() {
112+
continue;
113+
}
114+
115+
let crtc_cookie = conn.send_request(&xcb::randr::GetCrtcInfo {
116+
crtc,
117+
config_timestamp: reply.config_timestamp(),
118+
});
119+
let crtc_info = match conn.wait_for_reply(crtc_cookie) {
120+
Ok(c) => c,
121+
Err(_) => continue,
122+
};
123+
124+
let w = crtc_info.width() as u32;
125+
let h = crtc_info.height() as u32;
126+
127+
if w > 0 && h > 0 {
128+
tracing::info!("Detected first connected display: {}x{}", w, h);
129+
return Some((w, h));
130+
}
131+
}
132+
133+
None
134+
}
19135

20136
/// Detect the primary display resolution using XCB RandR.
21137
/// Falls back to (1920, 1080) if detection fails.

0 commit comments

Comments
 (0)