Render remote participant's screen preserving aspect ratio

This commit is contained in:
Antonio Scandurra 2022-10-18 14:16:19 +02:00
parent 46635956f4
commit bf98300547
3 changed files with 56 additions and 34 deletions

View file

@ -495,7 +495,7 @@ pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {} impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}
fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F { pub fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F {
if max_size.x().is_infinite() && max_size.y().is_infinite() { if max_size.x().is_infinite() && max_size.y().is_infinite() {
size size
} else if max_size.x().is_infinite() || max_size.x() / max_size.y() > size.x() / size.y() { } else if max_size.x().is_infinite() || max_size.x() / max_size.y() > size.x() / size.y() {

View file

@ -1,8 +1,10 @@
use crate::{FollowerStatesByLeader, JoinProject, Pane, Workspace}; use crate::{FollowerStatesByLeader, JoinProject, Pane, Workspace};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use call::ActiveCall; use call::{ActiveCall, ParticipantLocation};
use gpui::{ use gpui::{
elements::*, Axis, Border, CursorStyle, ModelHandle, MouseButton, RenderContext, ViewHandle, elements::*,
geometry::{rect::RectF, vector::vec2f},
Axis, Border, CursorStyle, ModelHandle, MouseButton, RenderContext, ViewHandle,
}; };
use project::Project; use project::Project;
use serde::Deserialize; use serde::Deserialize;
@ -130,18 +132,45 @@ impl Member {
Some((collaborator.replica_id, participant)) Some((collaborator.replica_id, participant))
}); });
let mut border = Border::default(); let border = if let Some((replica_id, _)) = leader.as_ref() {
let leader_color = theme.editor.replica_selection_style(*replica_id).cursor;
let prompt = if let Some((replica_id, leader)) = leader { let mut border = Border::all(theme.workspace.leader_border_width, leader_color);
let leader_color = theme.editor.replica_selection_style(replica_id).cursor;
border = Border::all(theme.workspace.leader_border_width, leader_color);
border border
.color .color
.fade_out(1. - theme.workspace.leader_border_opacity); .fade_out(1. - theme.workspace.leader_border_opacity);
border.overlay = true; border.overlay = true;
border
} else {
Border::default()
};
let content = if leader.as_ref().map_or(false, |(_, leader)| {
leader.location == ParticipantLocation::External && !leader.tracks.is_empty()
}) {
let (_, leader) = leader.unwrap();
let track = leader.tracks.values().next().unwrap();
let frame = track.frame().cloned();
Canvas::new(move |bounds, _, cx| {
if let Some(frame) = frame.clone() {
let size = constrain_size_preserving_aspect_ratio(
bounds.size(),
vec2f(frame.width() as f32, frame.height() as f32),
);
let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.;
cx.scene.push_surface(gpui::mac::Surface {
bounds: RectF::new(origin, size),
image_buffer: frame,
});
}
})
.boxed()
} else {
ChildView::new(pane, cx).boxed()
};
let prompt = if let Some((_, leader)) = leader {
match leader.location { match leader.location {
call::ParticipantLocation::SharedProject { ParticipantLocation::SharedProject {
project_id: leader_project_id, project_id: leader_project_id,
} => { } => {
if Some(leader_project_id) == project.read(cx).remote_id() { if Some(leader_project_id) == project.read(cx).remote_id() {
@ -186,7 +215,7 @@ impl Member {
) )
} }
} }
call::ParticipantLocation::UnsharedProject => Some( ParticipantLocation::UnsharedProject => Some(
Label::new( Label::new(
format!( format!(
"{} is viewing an unshared Zed project", "{} is viewing an unshared Zed project",
@ -201,35 +230,28 @@ impl Member {
.right() .right()
.boxed(), .boxed(),
), ),
call::ParticipantLocation::External => { ParticipantLocation::External => Some(
let frame = leader Label::new(
.tracks format!(
.values() "{} is viewing a window outside of Zed",
.next() leader.user.github_login
.and_then(|track| track.frame()) ),
.cloned(); theme.workspace.external_location_message.text.clone(),
return Canvas::new(move |bounds, _, cx| { )
if let Some(frame) = frame.clone() { .contained()
cx.scene.push_surface(gpui::mac::Surface { .with_style(theme.workspace.external_location_message.container)
bounds, .aligned()
image_buffer: frame, .bottom()
}); .right()
} .boxed(),
}) ),
.boxed();
}
} }
} else { } else {
None None
}; };
Stack::new() Stack::new()
.with_child( .with_child(Container::new(content).with_border(border).boxed())
ChildView::new(pane, cx)
.contained()
.with_border(border)
.boxed(),
)
.with_children(prompt) .with_children(prompt)
.boxed() .boxed()
} }

View file

@ -49,7 +49,7 @@ export default function workspace(theme: Theme) {
...text(theme, "sans", "primary", { size: "lg" }), ...text(theme, "sans", "primary", { size: "lg" }),
}, },
externalLocationMessage: { externalLocationMessage: {
background: backgroundColor(theme, "info"), background: backgroundColor(theme, "on500Info"),
border: border(theme, "secondary"), border: border(theme, "secondary"),
cornerRadius: 6, cornerRadius: 6,
padding: 12, padding: 12,