[window] remove frame delay when moving/resizing

This commit is contained in:
Emil Ernerfeldt 2020-05-27 08:38:21 +02:00
parent bcc786fd95
commit 3de20d033e
4 changed files with 69 additions and 38 deletions

View file

@ -24,6 +24,12 @@ pub(crate) struct State {
pub vel: Vec2, pub vel: Vec2,
} }
impl State {
pub fn rect(&self) -> Rect {
Rect::from_min_size(self.pos, self.size)
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct Area { pub struct Area {
id: Id, id: Id,
@ -93,9 +99,8 @@ impl Area {
pub(crate) struct Prepared { pub(crate) struct Prepared {
layer: Layer, layer: Layer,
pub(crate) state: State, state: State,
movable: bool, movable: bool,
pub(crate) content_ui: Ui,
} }
impl Area { impl Area {
@ -122,35 +127,44 @@ impl Area {
state.pos = fixed_pos.unwrap_or(state.pos); state.pos = fixed_pos.unwrap_or(state.pos);
state.pos = state.pos.round(); state.pos = state.pos.round();
let content_ui = Ui::new(
ctx.clone(),
layer,
id,
Rect::from_min_size(state.pos, Vec2::infinity()),
);
Prepared { Prepared {
layer, layer,
state, state,
movable, movable,
content_ui,
} }
} }
pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo {
let mut prepared = self.begin(ctx); let prepared = self.begin(ctx);
add_contents(&mut prepared.content_ui); let mut content_ui = prepared.content_ui(ctx);
prepared.end(ctx) add_contents(&mut content_ui);
prepared.end(ctx, content_ui)
} }
} }
impl Prepared { impl Prepared {
pub(crate) fn end(self, ctx: &Arc<Context>) -> InteractInfo { pub(crate) fn state(&self) -> &State {
&self.state
}
pub(crate) fn state_mut(&mut self) -> &mut State {
&mut self.state
}
pub(crate) fn content_ui(&self, ctx: &Arc<Context>) -> Ui {
Ui::new(
ctx.clone(),
self.layer,
self.layer.id,
Rect::from_min_size(self.state.pos, Vec2::infinity()),
)
}
pub(crate) fn end(self, ctx: &Arc<Context>, content_ui: Ui) -> InteractInfo {
let Prepared { let Prepared {
layer, layer,
mut state, mut state,
movable, movable,
content_ui,
} = self; } = self;
state.size = (content_ui.child_bounds().max - state.pos).ceil(); state.size = (content_ui.child_bounds().max - state.pos).ceil();

View file

@ -167,9 +167,29 @@ impl<'open> Window<'open> {
let frame = frame.unwrap_or_else(|| Frame::window(&ctx.style())); let frame = frame.unwrap_or_else(|| Frame::window(&ctx.style()));
let mut area = area.begin(ctx); let mut area = area.begin(ctx);
// First interact (move etc) to avoid frame delay:
let last_frame_outer_rect = area.state().rect();
let interaction = if possible.movable || possible.resizable {
interact(
ctx,
possible,
area_layer,
area.state_mut(),
window_id,
resize_id,
last_frame_outer_rect,
)
} else {
None
};
let hover_interaction = resize_hover(ctx, possible, area_layer, last_frame_outer_rect);
let mut area_content_ui = area.content_ui(ctx);
{ {
// BEGIN FRAME -------------------------------- // BEGIN FRAME --------------------------------
let mut frame = frame.begin(&mut area.content_ui); let mut frame = frame.begin(&mut area_content_ui);
let default_expanded = true; let default_expanded = true;
let mut collapsing = collapsing_header::State::from_memory_with_default_open( let mut collapsing = collapsing_header::State::from_memory_with_default_open(
@ -201,40 +221,25 @@ impl<'open> Window<'open> {
}) })
.map(|ri| ri.1); .map(|ri| ri.1);
let outer_rect = frame.end(&mut area.content_ui); let outer_rect = frame.end(&mut area_content_ui);
// END FRAME -------------------------------- // END FRAME --------------------------------
let interaction = if possible.movable || possible.resizable {
interact(
ctx,
possible,
area_layer,
&mut area.state,
window_id,
resize_id,
outer_rect,
)
} else {
None
};
let hover_interaction = resize_hover(ctx, possible, area_layer, outer_rect);
title_bar.ui( title_bar.ui(
&mut area.content_ui, &mut area_content_ui,
outer_rect, outer_rect,
content_rect, content_rect,
open, open,
&mut collapsing, &mut collapsing,
); );
area.content_ui area_content_ui
.memory() .memory()
.collapsing_headers .collapsing_headers
.insert(collapsing_id, collapsing); .insert(collapsing_id, collapsing);
if let Some(interaction) = interaction { if let Some(interaction) = interaction {
paint_frame_interaction( paint_frame_interaction(
&mut area.content_ui, &mut area_content_ui,
outer_rect, outer_rect,
interaction, interaction,
ctx.style().interact.active, ctx.style().interact.active,
@ -242,7 +247,7 @@ impl<'open> Window<'open> {
} else { } else {
if let Some(hover_interaction) = hover_interaction { if let Some(hover_interaction) = hover_interaction {
paint_frame_interaction( paint_frame_interaction(
&mut area.content_ui, &mut area_content_ui,
outer_rect, outer_rect,
hover_interaction, hover_interaction,
ctx.style().interact.hovered, ctx.style().interact.hovered,
@ -250,7 +255,7 @@ impl<'open> Window<'open> {
} }
} }
} }
let full_interact = area.end(ctx); let full_interact = area.end(ctx, area_content_ui);
Some(full_interact) Some(full_interact)
} }
@ -377,6 +382,7 @@ fn window_interaction(
hover_window_interaction.set_cursor(ctx); hover_window_interaction.set_cursor(ctx);
if ctx.input().mouse.pressed { if ctx.input().mouse.pressed {
ctx.memory().interaction.drag_id = Some(id); ctx.memory().interaction.drag_id = Some(id);
ctx.memory().interaction.drag_is_window = true;
window_interaction = Some(hover_window_interaction); window_interaction = Some(hover_window_interaction);
ctx.memory().window_interaction = window_interaction; ctx.memory().window_interaction = window_interaction;
} }

View file

@ -309,9 +309,13 @@ impl Context {
info.active = true; info.active = true;
} }
if sense.drag && !memory.interaction.drag_id.is_some() { if sense.drag
&& (!memory.interaction.drag_id.is_some() || memory.interaction.drag_is_window)
{
// start of a drag // start of a drag
memory.interaction.drag_id = Some(interaction_id); memory.interaction.drag_id = Some(interaction_id);
memory.interaction.drag_is_window = false;
memory.window_interaction = None; // HACK: stop moving windows (if any)
info.active = true; info.active = true;
} }

View file

@ -44,6 +44,13 @@ pub struct Interaction {
/// A widget interested in drags that has a mouse press on it. /// A widget interested in drags that has a mouse press on it.
pub drag_id: Option<Id>, pub drag_id: Option<Id>,
/// HACK: windows have low priority on dragging.
/// This is so that if you drag a slider in a window,
/// the slider will steal the drag away from the window.
/// This is needed because we do window interaction first (to prevent frame delay),
/// and then do content layout.
pub drag_is_window: bool,
/// Any interest in catching clicks this frame? /// Any interest in catching clicks this frame?
/// Cleared to false at start of each frame. /// Cleared to false at start of each frame.
pub click_interest: bool, pub click_interest: bool,