[window] remove frame delay when moving/resizing
This commit is contained in:
parent
bcc786fd95
commit
3de20d033e
4 changed files with 69 additions and 38 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue