fix: Wayland resolution

1. Add filed `scale` in `message SwitchDisplay`(`message.proto`).
2. Add new function to get all display info.
3. Add help link of KDE Plasma Wayland.

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-11-04 10:45:32 +08:00
parent 9b53baeffe
commit 4fe91763b7
4 changed files with 101 additions and 0 deletions

View File

@@ -81,3 +81,8 @@ winapi = { version = "0.3", features = [
[target.'cfg(target_os = "macos")'.dependencies]
osascript = "0.3"
[target.'cfg(target_os = "linux")'.dependencies]
sctk = { package = "smithay-client-toolkit", version = "0.20.0", default-features = false, features = [
"calloop",
] }

View File

@@ -607,6 +607,7 @@ message SwitchDisplay {
SupportedResolutions resolutions = 7;
// Do not care about the origin point for now.
Resolution original_resolution = 8;
double scale = 9;
}
message CaptureDisplays {

View File

@@ -90,11 +90,15 @@ pub const LINK_DOCS_HOME: &str = "https://rustdesk.com/docs/en/";
pub const LINK_DOCS_X11_REQUIRED: &str = "https://rustdesk.com/docs/en/manual/linux/#x11-required";
pub const LINK_HEADLESS_LINUX_SUPPORT: &str =
"https://github.com/rustdesk/rustdesk/wiki/Headless-Linux-Support";
pub const LINK_KDE_PLASMA_WAYLAND_SELECT_ALL_DISPLAYS: &str =
"https://github.com/rustdesk/rustdesk/discussions/13468";
lazy_static::lazy_static! {
pub static ref HELPER_URL: HashMap<&'static str, &'static str> = HashMap::from([
("rustdesk docs home", LINK_DOCS_HOME),
("rustdesk docs x11-required", LINK_DOCS_X11_REQUIRED),
("rustdesk x11 headless", LINK_HEADLESS_LINUX_SUPPORT),
("rustdesk discussion Plasma Wayland all displays", LINK_KDE_PLASMA_WAYLAND_SELECT_ALL_DISPLAYS),
]);
}

View File

@@ -1,6 +1,15 @@
use crate::ResultType;
use std::{collections::HashMap, process::Command};
use sctk::{
output::OutputData,
output::{OutputHandler, OutputState},
reexports::client::protocol::wl_output::WlOutput,
reexports::client::{globals, Proxy},
reexports::client::{Connection, QueueHandle},
registry::{ProvidesRegistryState, RegistryState},
};
lazy_static::lazy_static! {
pub static ref DISTRO: Distro = Distro::new();
}
@@ -337,6 +346,88 @@ pub fn system_message(title: &str, msg: &str, forever: bool) -> ResultType<()> {
crate::bail!("failed to post system message");
}
#[derive(Debug, Clone)]
pub struct WaylandDisplayInfo {
pub name: String,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
pub logical_size: Option<(i32, i32)>,
pub refresh_rate: i32,
}
// Retrieves information about all connected displays via the Wayland protocol.
pub fn get_wayland_displays() -> ResultType<Vec<WaylandDisplayInfo>> {
struct WaylandEnv {
registry_state: RegistryState,
output_state: OutputState,
}
impl OutputHandler for WaylandEnv {
fn output_state(&mut self) -> &mut OutputState {
&mut self.output_state
}
fn new_output(&mut self, _: &Connection, _: &QueueHandle<Self>, _: WlOutput) {}
fn update_output(&mut self, _: &Connection, _: &QueueHandle<Self>, _: WlOutput) {}
fn output_destroyed(&mut self, _: &Connection, _: &QueueHandle<Self>, _: WlOutput) {}
}
impl ProvidesRegistryState for WaylandEnv {
fn registry(&mut self) -> &mut RegistryState {
&mut self.registry_state
}
sctk::registry_handlers!();
}
sctk::delegate_output!(WaylandEnv);
sctk::delegate_registry!(WaylandEnv);
let conn = Connection::connect_to_env()?;
let (globals, mut event_queue) = globals::registry_queue_init(&conn)?;
let queue_handle = event_queue.handle();
let registry_state = RegistryState::new(&globals);
let output_state = OutputState::new(&globals, &queue_handle);
let mut environment = WaylandEnv {
registry_state,
output_state,
};
event_queue.roundtrip(&mut environment)?;
let outputs: Vec<_> = environment.output_state.outputs().collect();
let mut display_infos = Vec::new();
for output in outputs {
if let Some(output_data) = output.data::<OutputData>() {
output_data.with_output_info(|info| {
if let Some(mode) = info.modes.iter().find(|m| m.current) {
let (x, y) = info.location;
let (width, height) = mode.dimensions;
let refresh_rate = mode.refresh_rate;
let name = info.name.clone().unwrap_or_default();
let logical_size = info.logical_size;
display_infos.push(WaylandDisplayInfo {
name,
x,
y,
width,
height,
logical_size,
refresh_rate,
});
}
});
}
}
Ok(display_infos)
}
#[cfg(test)]
mod tests {
use super::*;