EvanZhu0721 / 公开仓库
SBMS
SBMS complete the calculation rules for the default logical desktop topology relationship and the physical dimensions of the displays in the Windows multi-screen collaboration system.
文件
../ diagnostic_view.rs6.1 KBgeometry_view.rs15.9 KBhandlers.rs32.1 KBprojection.rs6.7 KBstate.rs13.2 KBsrc/ui/projection.rs6.7 KB
1
use std::rc::Rc;2
3
use slint::{Model, ModelRc, SharedString, VecModel};4
5
use crate::controller::DisplayOption;6
7
use super::state::{GroupDraft, SunshineState};8
use super::{9
QuickAccess, STREAM_ONLY_ID, geometry_request, group_tab_detail, populate_geometry_fields,10
rebuild_reference_options, selected_display_id, selected_reference_source, set_geometry_result,11
set_geometry_unconfigured, update_reference_action, update_stream_suggestions,12
validate_stream_fields,13
};14
15
pub(super) fn update_tab_projection(ui: &QuickAccess, groups: &[GroupDraft], active: usize) {16
let first = if groups.len() <= 3 {17
018
} else {19
active.saturating_sub(1).min(groups.len() - 3)20
};21
let visible = groups.iter().enumerate().skip(first).take(3);22
let mut labels = Vec::new();23
let mut details = Vec::new();24
let mut indices = Vec::new();25
for (index, group) in visible {26
labels.push(SharedString::from((group.id + 1).to_string()));27
details.push(SharedString::from(group.tab_detail.as_str()));28
indices.push(index as i32);29
}30
ui.set_tab_labels(ModelRc::new(Rc::new(VecModel::from(labels))));31
ui.set_tab_details(ModelRc::new(Rc::new(VecModel::from(details))));32
ui.set_tab_indices(ModelRc::new(Rc::new(VecModel::from(indices))));33
ui.set_active_group_index(active as i32);34
ui.set_group_count(groups.len() as i32);35
}36
37
pub(super) fn project_group_telemetry(ui: &QuickAccess, groups: &[GroupDraft], active: usize) {38
let Some(group) = groups.get(active) else {39
return;40
};41
let telemetry = &group.telemetry;42
ui.set_mapping_fps(telemetry.fps.unwrap_or_default() as i32);43
ui.set_mapping_fps_valid(telemetry.fps.is_some());44
ui.set_mapping_fps_error(telemetry.error);45
ui.set_mapping_fps_nan(ui.get_stream_only() && !telemetry.error);46
ui.set_sunshine_state(telemetry.sunshine_state.as_i32());47
ui.set_sunshine_port(telemetry.sunshine_port.unwrap_or_default().into());48
ui.set_sunshine_panel_enabled(49
telemetry.ready50
&& telemetry.sunshine_state == SunshineState::Ready51
&& telemetry.sunshine_port.is_some()52
&& group.stream_only,53
);54
}55
56
pub(super) fn set_target_options(57
ui: &QuickAccess,58
displays: &[DisplayOption],59
groups: &[GroupDraft],60
active: usize,61
) {62
let used = groups63
.iter()64
.enumerate()65
.filter(|(index, group)| *index != active && !group.stream_only)66
.filter_map(|(_, group)| group.target_id.as_deref())67
.collect::<Vec<_>>();68
let candidates = displays69
.iter()70
.filter(|display| !used.contains(&display.id.as_str()))71
.collect::<Vec<_>>();72
let mut names = candidates73
.iter()74
.map(|display| SharedString::from(display.name.as_str()))75
.collect::<Vec<_>>();76
let mut labels = candidates77
.iter()78
.map(|display| {79
SharedString::from(80
if display.physical_width_mm.is_some() && display.physical_height_mm.is_some() {81
display.label.clone()82
} else {83
format!("{} · Size unavailable", display.label)84
},85
)86
})87
.collect::<Vec<_>>();88
let mut ids = candidates89
.iter()90
.map(|display| SharedString::from(display.id.as_str()))91
.collect::<Vec<_>>();92
names.push("Stream only".into());93
labels.push("Stream only · Create a virtual display".into());94
ids.push(STREAM_ONLY_ID.into());95
ui.set_display_names(ModelRc::new(Rc::new(VecModel::from(names))));96
ui.set_display_labels(ModelRc::new(Rc::new(VecModel::from(labels))));97
ui.set_display_ids(ModelRc::new(Rc::new(VecModel::from(ids))));98
99
let group = &groups[active];100
let desired = if group.stream_only {101
STREAM_ONLY_ID102
} else {103
group.target_id.as_deref().unwrap_or("")104
};105
let selected = (0..ui.get_display_ids().row_count())106
.find(|index| {107
ui.get_display_ids()108
.row_data(*index)109
.is_some_and(|id| id.as_str() == desired)110
})111
.or_else(|| (!candidates.is_empty()).then_some(0))112
.unwrap_or(candidates.len());113
ui.set_selected_display(selected as i32);114
ui.set_stream_only(115
ui.get_display_ids()116
.row_data(selected)117
.is_some_and(|id| id.as_str() == STREAM_ONLY_ID),118
);119
}120
121
pub(super) fn hydrate_group(122
ui: &QuickAccess,123
displays: &[DisplayOption],124
groups: &[GroupDraft],125
active: usize,126
) {127
let Some(group) = groups.get(active) else {128
return;129
};130
set_target_options(ui, displays, groups, active);131
ui.set_stream_width(group.stream_width.as_str().into());132
ui.set_stream_height(group.stream_height.as_str().into());133
ui.set_stream_diagonal(group.stream_diagonal.as_str().into());134
ui.set_stream_refresh(group.stream_refresh.as_str().into());135
ui.set_stream_aspect_ratio_index(group.stream_aspect_ratio_index);136
ui.set_stream_rotation(group.stream_rotation_index);137
if let Some(request) = group.sizing {138
populate_geometry_fields(ui, request);139
match request.calculate() {140
Ok(result) => set_geometry_result(ui, result, true),141
Err(error) => {142
set_geometry_unconfigured(ui);143
ui.set_geometry_error(error.to_string().into());144
}145
}146
} else {147
set_geometry_unconfigured(ui);148
}149
rebuild_reference_options(ui, displays, group.reference_source.clone());150
update_reference_action(ui, displays);151
update_stream_suggestions(ui);152
if group.stream_only {153
validate_stream_fields(ui, displays);154
}155
update_tab_projection(ui, groups, active);156
project_group_telemetry(ui, groups, active);157
}158
159
pub(super) fn snapshot_group(160
ui: &QuickAccess,161
displays: &[DisplayOption],162
groups: &mut [GroupDraft],163
active: usize,164
) {165
let Some(group) = groups.get_mut(active) else {166
return;167
};168
let target_id = selected_display_id(ui, ui.get_selected_display());169
group.stream_only = target_id.as_deref() == Some(STREAM_ONLY_ID);170
group.target_id = (!group.stream_only).then_some(target_id).flatten();171
group.reference_source = selected_reference_source(ui);172
group.sizing = geometry_request(ui, displays)173
.ok()174
.flatten()175
.filter(|request| request.calculate().is_ok());176
group.stream_width = ui.get_stream_width().to_string();177
group.stream_height = ui.get_stream_height().to_string();178
group.stream_diagonal = ui.get_stream_diagonal().to_string();179
group.stream_refresh = ui.get_stream_refresh().to_string();180
group.stream_aspect_ratio_index = ui.get_stream_aspect_ratio_index();181
group.stream_rotation_index = ui.get_stream_rotation();182
group.tab_detail = group_tab_detail(group, displays);183
}184