iced: Allow rendering at a higher native scale than it's output
This commit is contained in:
parent
f72d2b91f3
commit
24b5742554
1 changed files with 67 additions and 18 deletions
|
|
@ -152,6 +152,7 @@ impl<P: Program> IcedProgram for ProgramWrapper<P> {
|
||||||
|
|
||||||
pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
|
pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
|
||||||
// draw buffer
|
// draw buffer
|
||||||
|
additional_scale: f64,
|
||||||
outputs: HashSet<Output>,
|
outputs: HashSet<Output>,
|
||||||
buffers: HashMap<OrderedFloat<f64>, (MemoryRenderBuffer, Option<(Vec<Layer>, Color)>)>,
|
buffers: HashMap<OrderedFloat<f64>, (MemoryRenderBuffer, Option<(Vec<Layer>, Color)>)>,
|
||||||
pending_update: Option<Instant>,
|
pending_update: Option<Instant>,
|
||||||
|
|
@ -204,6 +205,7 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
|
||||||
);
|
);
|
||||||
|
|
||||||
IcedElementInternal {
|
IcedElementInternal {
|
||||||
|
additional_scale: self.additional_scale,
|
||||||
outputs: self.outputs.clone(),
|
outputs: self.outputs.clone(),
|
||||||
buffers: self.buffers.clone(),
|
buffers: self.buffers.clone(),
|
||||||
pending_update: self.pending_update.clone(),
|
pending_update: self.pending_update.clone(),
|
||||||
|
|
@ -226,10 +228,17 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
|
||||||
impl<P: Program + Send + 'static> fmt::Debug for IcedElementInternal<P> {
|
impl<P: Program + Send + 'static> fmt::Debug for IcedElementInternal<P> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("IcedElementInternal")
|
f.debug_struct("IcedElementInternal")
|
||||||
|
.field("additional_scale", &self.additional_scale)
|
||||||
|
.field(
|
||||||
|
"outputs",
|
||||||
|
&self.outputs.iter().map(|o| o.name()).collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
.field("buffers", &"...")
|
.field("buffers", &"...")
|
||||||
.field("size", &self.size)
|
.field("size", &self.size)
|
||||||
.field("pending_update", &self.pending_update)
|
.field("pending_update", &self.pending_update)
|
||||||
|
.field("last_seat", &self.last_seat)
|
||||||
.field("cursor_pos", &self.cursor_pos)
|
.field("cursor_pos", &self.cursor_pos)
|
||||||
|
.field("touch_map", &self.touch_map)
|
||||||
.field("theme", &"...")
|
.field("theme", &"...")
|
||||||
.field("renderer", &"...")
|
.field("renderer", &"...")
|
||||||
.field("state", &"...")
|
.field("state", &"...")
|
||||||
|
|
@ -281,6 +290,7 @@ impl<P: Program + Send + 'static> IcedElement<P> {
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let mut internal = IcedElementInternal {
|
let mut internal = IcedElementInternal {
|
||||||
|
additional_scale: 1.0,
|
||||||
outputs: HashSet::new(),
|
outputs: HashSet::new(),
|
||||||
buffers: HashMap::new(),
|
buffers: HashMap::new(),
|
||||||
pending_update: None,
|
pending_update: None,
|
||||||
|
|
@ -352,6 +362,19 @@ impl<P: Program + Send + 'static> IcedElement<P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_additional_scale(&self, scale: f64) {
|
||||||
|
{
|
||||||
|
let mut internal = self.0.lock().unwrap();
|
||||||
|
let internal_ref = &mut *internal;
|
||||||
|
if internal_ref.additional_scale == scale {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_ref.additional_scale = scale;
|
||||||
|
}
|
||||||
|
self.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn force_update(&self) {
|
pub fn force_update(&self) {
|
||||||
self.0.lock().unwrap().update(true);
|
self.0.lock().unwrap().update(true);
|
||||||
}
|
}
|
||||||
|
|
@ -370,7 +393,12 @@ impl<P: Program + Send + 'static> IcedElement<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_size(&self) -> Size<i32, Logical> {
|
pub fn current_size(&self) -> Size<i32, Logical> {
|
||||||
self.0.lock().unwrap().size
|
let internal = self.0.lock().unwrap();
|
||||||
|
internal
|
||||||
|
.size
|
||||||
|
.to_f64()
|
||||||
|
.upscale(internal.additional_scale)
|
||||||
|
.to_i32_round()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn queue_message(&self, msg: P::Message) {
|
pub fn queue_message(&self, msg: P::Message) {
|
||||||
|
|
@ -405,6 +433,7 @@ impl<P: Program + Send + 'static> IcedElementInternal<P> {
|
||||||
.map(|p| IcedPoint::new(p.x as f32, p.y as f32))
|
.map(|p| IcedPoint::new(p.x as f32, p.y as f32))
|
||||||
.map(Cursor::Available)
|
.map(Cursor::Available)
|
||||||
.unwrap_or(Cursor::Unavailable);
|
.unwrap_or(Cursor::Unavailable);
|
||||||
|
|
||||||
let actions = self
|
let actions = self
|
||||||
.state
|
.state
|
||||||
.update(
|
.update(
|
||||||
|
|
@ -446,12 +475,13 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
|
||||||
internal
|
internal
|
||||||
.state
|
.state
|
||||||
.queue_event(Event::Mouse(MouseEvent::CursorEntered));
|
.queue_event(Event::Mouse(MouseEvent::CursorEntered));
|
||||||
let position = IcedPoint::new(event.location.x as f32, event.location.y as f32);
|
let event_location = event.location.downscale(internal.additional_scale);
|
||||||
|
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
|
||||||
internal
|
internal
|
||||||
.state
|
.state
|
||||||
.queue_event(Event::Mouse(MouseEvent::CursorMoved { position }));
|
.queue_event(Event::Mouse(MouseEvent::CursorMoved { position }));
|
||||||
// TODO: Update iced widgets to handle touch using event position, not cursor_pos
|
// TODO: Update iced widgets to handle touch using event position, not cursor_pos
|
||||||
internal.cursor_pos = Some(event.location);
|
internal.cursor_pos = Some(event_location);
|
||||||
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
|
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
|
||||||
let _ = internal.update(true);
|
let _ = internal.update(true);
|
||||||
}
|
}
|
||||||
|
|
@ -463,11 +493,12 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
|
||||||
event: &MotionEvent,
|
event: &MotionEvent,
|
||||||
) {
|
) {
|
||||||
let mut internal = self.0.lock().unwrap();
|
let mut internal = self.0.lock().unwrap();
|
||||||
let position = IcedPoint::new(event.location.x as f32, event.location.y as f32);
|
let event_location = event.location.downscale(internal.additional_scale);
|
||||||
|
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
|
||||||
internal
|
internal
|
||||||
.state
|
.state
|
||||||
.queue_event(Event::Mouse(MouseEvent::CursorMoved { position }));
|
.queue_event(Event::Mouse(MouseEvent::CursorMoved { position }));
|
||||||
internal.cursor_pos = Some(event.location);
|
internal.cursor_pos = Some(event_location);
|
||||||
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
|
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
|
||||||
let _ = internal.update(true);
|
let _ = internal.update(true);
|
||||||
}
|
}
|
||||||
|
|
@ -610,12 +641,13 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
|
||||||
) {
|
) {
|
||||||
let mut internal = self.0.lock().unwrap();
|
let mut internal = self.0.lock().unwrap();
|
||||||
let id = Finger(i32::from(event.slot) as u64);
|
let id = Finger(i32::from(event.slot) as u64);
|
||||||
let position = IcedPoint::new(event.location.x as f32, event.location.y as f32);
|
let event_location = event.location.downscale(internal.additional_scale);
|
||||||
|
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
|
||||||
internal
|
internal
|
||||||
.state
|
.state
|
||||||
.queue_event(Event::Touch(TouchEvent::FingerPressed { id, position }));
|
.queue_event(Event::Touch(TouchEvent::FingerPressed { id, position }));
|
||||||
internal.touch_map.insert(id, position);
|
internal.touch_map.insert(id, position);
|
||||||
internal.cursor_pos = Some(event.location);
|
internal.cursor_pos = Some(event_location);
|
||||||
*internal.last_seat.lock().unwrap() = Some((seat.clone(), seq));
|
*internal.last_seat.lock().unwrap() = Some((seat.clone(), seq));
|
||||||
let _ = internal.update(true);
|
let _ = internal.update(true);
|
||||||
}
|
}
|
||||||
|
|
@ -647,13 +679,14 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
|
||||||
) {
|
) {
|
||||||
let mut internal = self.0.lock().unwrap();
|
let mut internal = self.0.lock().unwrap();
|
||||||
let id = Finger(i32::from(event.slot) as u64);
|
let id = Finger(i32::from(event.slot) as u64);
|
||||||
let position = IcedPoint::new(event.location.x as f32, event.location.y as f32);
|
let event_location = event.location.downscale(internal.additional_scale);
|
||||||
|
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
|
||||||
*internal.last_seat.lock().unwrap() = Some((seat.clone(), seq));
|
*internal.last_seat.lock().unwrap() = Some((seat.clone(), seq));
|
||||||
internal
|
internal
|
||||||
.state
|
.state
|
||||||
.queue_event(Event::Touch(TouchEvent::FingerMoved { id, position }));
|
.queue_event(Event::Touch(TouchEvent::FingerMoved { id, position }));
|
||||||
internal.touch_map.insert(id, position);
|
internal.touch_map.insert(id, position);
|
||||||
internal.cursor_pos = Some(event.location);
|
internal.cursor_pos = Some(event_location);
|
||||||
let _ = internal.update(true);
|
let _ = internal.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -767,7 +800,14 @@ impl<P: Program + Send + 'static> IsAlive for IcedElement<P> {
|
||||||
|
|
||||||
impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
|
impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
|
||||||
fn bbox(&self) -> Rectangle<i32, Logical> {
|
fn bbox(&self) -> Rectangle<i32, Logical> {
|
||||||
Rectangle::from_size(self.0.lock().unwrap().size)
|
let internal = self.0.lock().unwrap();
|
||||||
|
Rectangle::from_size(
|
||||||
|
internal
|
||||||
|
.size
|
||||||
|
.to_f64()
|
||||||
|
.upscale(internal.additional_scale)
|
||||||
|
.to_i32_round(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_in_input_region(&self, _point: &Point<f64, Logical>) -> bool {
|
fn is_in_input_region(&self, _point: &Point<f64, Logical>) -> bool {
|
||||||
|
|
@ -786,7 +826,7 @@ impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
|
||||||
|
|
||||||
fn output_enter(&self, output: &Output, _overlap: Rectangle<i32, Logical>) {
|
fn output_enter(&self, output: &Output, _overlap: Rectangle<i32, Logical>) {
|
||||||
let mut internal = self.0.lock().unwrap();
|
let mut internal = self.0.lock().unwrap();
|
||||||
let scale = output.current_scale().fractional_scale();
|
let scale = output.current_scale().fractional_scale() * internal.additional_scale;
|
||||||
|
|
||||||
let internal_size = internal.size;
|
let internal_size = internal.size;
|
||||||
internal.buffers.entry(OrderedFloat(scale)).or_insert({
|
internal.buffers.entry(OrderedFloat(scale)).or_insert({
|
||||||
|
|
@ -820,15 +860,16 @@ impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
|
||||||
// makes partial borrows easier
|
// makes partial borrows easier
|
||||||
let internal_ref = &mut *internal;
|
let internal_ref = &mut *internal;
|
||||||
internal_ref.buffers.retain(|scale, _| {
|
internal_ref.buffers.retain(|scale, _| {
|
||||||
internal_ref
|
internal_ref.outputs.iter().any(|o| {
|
||||||
.outputs
|
o.current_scale().fractional_scale() * internal_ref.additional_scale == **scale
|
||||||
.iter()
|
})
|
||||||
.any(|o| o.current_scale().fractional_scale() == **scale)
|
|
||||||
});
|
});
|
||||||
for scale in internal_ref
|
for scale in internal_ref
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|o| OrderedFloat(o.current_scale().fractional_scale()))
|
.map(|o| {
|
||||||
|
OrderedFloat(o.current_scale().fractional_scale() * internal_ref.additional_scale)
|
||||||
|
})
|
||||||
.filter(|scale| !internal_ref.buffers.contains_key(scale))
|
.filter(|scale| !internal_ref.buffers.contains_key(scale))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -868,7 +909,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
location: Point<i32, Physical>,
|
location: Point<i32, Physical>,
|
||||||
scale: Scale<f64>,
|
mut scale: Scale<f64>,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Vec<C> {
|
) -> Vec<C> {
|
||||||
let mut internal = self.0.lock().unwrap();
|
let mut internal = self.0.lock().unwrap();
|
||||||
|
|
@ -886,6 +927,8 @@ where
|
||||||
internal_ref.pending_update = None;
|
internal_ref.pending_update = None;
|
||||||
}
|
}
|
||||||
let _ = internal_ref.update(force);
|
let _ = internal_ref.update(force);
|
||||||
|
|
||||||
|
scale = scale * internal_ref.additional_scale;
|
||||||
if let Some((buffer, ref mut old_layers)) =
|
if let Some((buffer, ref mut old_layers)) =
|
||||||
internal_ref.buffers.get_mut(&OrderedFloat(scale.x))
|
internal_ref.buffers.get_mut(&OrderedFloat(scale.x))
|
||||||
{
|
{
|
||||||
|
|
@ -988,7 +1031,13 @@ where
|
||||||
.to_logical(1., Transform::Normal)
|
.to_logical(1., Transform::Normal)
|
||||||
.to_i32_round(),
|
.to_i32_round(),
|
||||||
)),
|
)),
|
||||||
Some(internal_ref.size),
|
Some(
|
||||||
|
internal_ref
|
||||||
|
.size
|
||||||
|
.to_f64()
|
||||||
|
.upscale(internal_ref.additional_scale)
|
||||||
|
.to_i32_round(),
|
||||||
|
),
|
||||||
Kind::Unspecified,
|
Kind::Unspecified,
|
||||||
) {
|
) {
|
||||||
return vec![C::from(buffer)];
|
return vec![C::from(buffer)];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue