[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,
}
impl State {
pub fn rect(&self) -> Rect {
Rect::from_min_size(self.pos, self.size)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Area {
id: Id,
@ -93,9 +99,8 @@ impl Area {
pub(crate) struct Prepared {
layer: Layer,
pub(crate) state: State,
state: State,
movable: bool,
pub(crate) content_ui: Ui,
}
impl Area {
@ -122,35 +127,44 @@ impl Area {
state.pos = fixed_pos.unwrap_or(state.pos);
state.pos = state.pos.round();
let content_ui = Ui::new(
ctx.clone(),
layer,
id,
Rect::from_min_size(state.pos, Vec2::infinity()),
);
Prepared {
layer,
state,
movable,
content_ui,
}
}
pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo {
let mut prepared = self.begin(ctx);
add_contents(&mut prepared.content_ui);
prepared.end(ctx)
let prepared = self.begin(ctx);
let mut content_ui = prepared.content_ui(ctx);
add_contents(&mut content_ui);
prepared.end(ctx, content_ui)
}
}
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 {
layer,
mut state,
movable,
content_ui,
} = self;
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 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 --------------------------------
let mut frame = frame.begin(&mut area.content_ui);
let mut frame = frame.begin(&mut area_content_ui);
let default_expanded = true;
let mut collapsing = collapsing_header::State::from_memory_with_default_open(
@ -201,40 +221,25 @@ impl<'open> Window<'open> {
})
.map(|ri| ri.1);
let outer_rect = frame.end(&mut area.content_ui);
let outer_rect = frame.end(&mut area_content_ui);
// 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(
&mut area.content_ui,
&mut area_content_ui,
outer_rect,
content_rect,
open,
&mut collapsing,
);
area.content_ui
area_content_ui
.memory()
.collapsing_headers
.insert(collapsing_id, collapsing);
if let Some(interaction) = interaction {
paint_frame_interaction(
&mut area.content_ui,
&mut area_content_ui,
outer_rect,
interaction,
ctx.style().interact.active,
@ -242,7 +247,7 @@ impl<'open> Window<'open> {
} else {
if let Some(hover_interaction) = hover_interaction {
paint_frame_interaction(
&mut area.content_ui,
&mut area_content_ui,
outer_rect,
hover_interaction,
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)
}
@ -377,6 +382,7 @@ fn window_interaction(
hover_window_interaction.set_cursor(ctx);
if ctx.input().mouse.pressed {
ctx.memory().interaction.drag_id = Some(id);
ctx.memory().interaction.drag_is_window = true;
window_interaction = Some(hover_window_interaction);
ctx.memory().window_interaction = window_interaction;
}

View file

@ -309,9 +309,13 @@ impl Context {
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
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;
}

View file

@ -44,6 +44,13 @@ pub struct Interaction {
/// A widget interested in drags that has a mouse press on it.
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?
/// Cleared to false at start of each frame.
pub click_interest: bool,