Fix Window::pivot
causing windows to move around (#2694)
* Fix Window::pivot causing windows to move around * Add line to changelog
This commit is contained in:
parent
a8d5a82a7f
commit
e8b9e706ca
4 changed files with 50 additions and 27 deletions
|
@ -43,6 +43,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
|
||||||
* The `button_padding` style option works closer as expected with image+text buttons now ([#2510](https://github.com/emilk/egui/pull/2510)).
|
* The `button_padding` style option works closer as expected with image+text buttons now ([#2510](https://github.com/emilk/egui/pull/2510)).
|
||||||
* Fixed rendering of `…` (ellipsis).
|
* Fixed rendering of `…` (ellipsis).
|
||||||
* Menus are now moved to fit on the screen.
|
* Menus are now moved to fit on the screen.
|
||||||
|
* Fix `Window::pivot` causing windows to move around ([#2694](https://github.com/emilk/egui/pull/2694)).
|
||||||
|
|
||||||
|
|
||||||
## 0.20.1 - 2022-12-11 - Fix key-repeat
|
## 0.20.1 - 2022-12-11 - Fix key-repeat
|
||||||
|
|
|
@ -9,8 +9,10 @@ use crate::*;
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
/// Last known pos
|
/// Last known pos of the pivot
|
||||||
pub pos: Pos2,
|
pub pivot_pos: Pos2,
|
||||||
|
|
||||||
|
pub pivot: Align2,
|
||||||
|
|
||||||
/// Last know size. Used for catching clicks.
|
/// Last know size. Used for catching clicks.
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
|
@ -21,8 +23,22 @@ pub(crate) struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
pub fn left_top_pos(&self) -> Pos2 {
|
||||||
|
pos2(
|
||||||
|
self.pivot_pos.x - self.pivot.x().to_factor() * self.size.x,
|
||||||
|
self.pivot_pos.y - self.pivot.y().to_factor() * self.size.y,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_left_top_pos(&mut self, pos: Pos2) {
|
||||||
|
self.pivot_pos = pos2(
|
||||||
|
pos.x + self.pivot.x().to_factor() * self.size.x,
|
||||||
|
pos.y + self.pivot.y().to_factor() * self.size.y,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rect(&self) -> Rect {
|
pub fn rect(&self) -> Rect {
|
||||||
Rect::from_min_size(self.pos, self.size)
|
Rect::from_min_size(self.left_top_pos(), self.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,21 +253,19 @@ impl Area {
|
||||||
ctx.request_repaint(); // if we don't know the previous size we are likely drawing the area in the wrong place
|
ctx.request_repaint(); // if we don't know the previous size we are likely drawing the area in the wrong place
|
||||||
}
|
}
|
||||||
let mut state = state.unwrap_or_else(|| State {
|
let mut state = state.unwrap_or_else(|| State {
|
||||||
pos: default_pos.unwrap_or_else(|| automatic_area_position(ctx)),
|
pivot_pos: default_pos.unwrap_or_else(|| automatic_area_position(ctx)),
|
||||||
|
pivot,
|
||||||
size: Vec2::ZERO,
|
size: Vec2::ZERO,
|
||||||
interactable,
|
interactable,
|
||||||
});
|
});
|
||||||
state.pos = new_pos.unwrap_or(state.pos);
|
state.pivot_pos = new_pos.unwrap_or(state.pivot_pos);
|
||||||
state.interactable = interactable;
|
state.interactable = interactable;
|
||||||
|
|
||||||
if pivot != Align2::LEFT_TOP {
|
|
||||||
state.pos.x -= pivot.x().to_factor() * state.size.x;
|
|
||||||
state.pos.y -= pivot.y().to_factor() * state.size.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((anchor, offset)) = anchor {
|
if let Some((anchor, offset)) = anchor {
|
||||||
let screen = ctx.available_rect();
|
let screen = ctx.available_rect();
|
||||||
state.pos = anchor.align_size_within_rect(state.size, screen).min + offset;
|
state.set_left_top_pos(
|
||||||
|
anchor.align_size_within_rect(state.size, screen).left_top() + offset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interact right away to prevent frame-delay
|
// interact right away to prevent frame-delay
|
||||||
|
@ -278,12 +292,13 @@ impl Area {
|
||||||
// Important check - don't try to move e.g. a combobox popup!
|
// Important check - don't try to move e.g. a combobox popup!
|
||||||
if movable {
|
if movable {
|
||||||
if move_response.dragged() {
|
if move_response.dragged() {
|
||||||
state.pos += ctx.input(|i| i.pointer.delta());
|
state.pivot_pos += ctx.input(|i| i.pointer.delta());
|
||||||
}
|
}
|
||||||
|
|
||||||
state.pos = ctx
|
state.set_left_top_pos(
|
||||||
.constrain_window_rect_to_area(state.rect(), drag_bounds)
|
ctx.constrain_window_rect_to_area(state.rect(), drag_bounds)
|
||||||
.min;
|
.min,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_response.dragged() || move_response.clicked())
|
if (move_response.dragged() || move_response.clicked())
|
||||||
|
@ -297,12 +312,13 @@ impl Area {
|
||||||
move_response
|
move_response
|
||||||
};
|
};
|
||||||
|
|
||||||
state.pos = ctx.round_pos_to_pixels(state.pos);
|
state.set_left_top_pos(ctx.round_pos_to_pixels(state.left_top_pos()));
|
||||||
|
|
||||||
if constrain {
|
if constrain {
|
||||||
state.pos = ctx
|
state.set_left_top_pos(
|
||||||
.constrain_window_rect_to_area(state.rect(), drag_bounds)
|
ctx.constrain_window_rect_to_area(state.rect(), drag_bounds)
|
||||||
.min;
|
.left_top(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Prepared {
|
Prepared {
|
||||||
|
@ -374,14 +390,16 @@ impl Prepared {
|
||||||
};
|
};
|
||||||
|
|
||||||
let max_rect = Rect::from_min_max(
|
let max_rect = Rect::from_min_max(
|
||||||
self.state.pos,
|
self.state.left_top_pos(),
|
||||||
bounds.max.at_least(self.state.pos + Vec2::splat(32.0)),
|
bounds
|
||||||
|
.max
|
||||||
|
.at_least(self.state.left_top_pos() + Vec2::splat(32.0)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let shadow_radius = ctx.style().visuals.window_shadow.extrusion; // hacky
|
let shadow_radius = ctx.style().visuals.window_shadow.extrusion; // hacky
|
||||||
let clip_rect_margin = ctx.style().visuals.clip_rect_margin.max(shadow_radius);
|
let clip_rect_margin = ctx.style().visuals.clip_rect_margin.max(shadow_radius);
|
||||||
|
|
||||||
let clip_rect = Rect::from_min_max(self.state.pos, bounds.max)
|
let clip_rect = Rect::from_min_max(self.state.left_top_pos(), bounds.max)
|
||||||
.expand(clip_rect_margin)
|
.expand(clip_rect_margin)
|
||||||
.intersect(bounds);
|
.intersect(bounds);
|
||||||
|
|
||||||
|
|
|
@ -438,9 +438,12 @@ impl<'open> Window<'open> {
|
||||||
content_inner
|
content_inner
|
||||||
};
|
};
|
||||||
|
|
||||||
area.state_mut().pos = ctx
|
{
|
||||||
|
let pos = ctx
|
||||||
.constrain_window_rect_to_area(area.state().rect(), area.drag_bounds())
|
.constrain_window_rect_to_area(area.state().rect(), area.drag_bounds())
|
||||||
.min;
|
.left_top();
|
||||||
|
area.state_mut().set_left_top_pos(pos);
|
||||||
|
}
|
||||||
|
|
||||||
let full_response = area.end(ctx, area_content_ui);
|
let full_response = area.end(ctx, area_content_ui);
|
||||||
|
|
||||||
|
@ -550,7 +553,7 @@ fn interact(
|
||||||
let new_rect = ctx.constrain_window_rect_to_area(new_rect, area.drag_bounds());
|
let new_rect = ctx.constrain_window_rect_to_area(new_rect, area.drag_bounds());
|
||||||
|
|
||||||
// TODO(emilk): add this to a Window state instead as a command "move here next frame"
|
// TODO(emilk): add this to a Window state instead as a command "move here next frame"
|
||||||
area.state_mut().pos = new_rect.min;
|
area.state_mut().set_left_top_pos(new_rect.left_top());
|
||||||
|
|
||||||
if window_interaction.is_resize() {
|
if window_interaction.is_resize() {
|
||||||
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
||||||
|
|
|
@ -105,7 +105,8 @@ impl ContextImpl {
|
||||||
self.memory.areas.set_state(
|
self.memory.areas.set_state(
|
||||||
LayerId::background(),
|
LayerId::background(),
|
||||||
containers::area::State {
|
containers::area::State {
|
||||||
pos: screen_rect.min,
|
pivot_pos: screen_rect.left_top(),
|
||||||
|
pivot: Align2::LEFT_TOP,
|
||||||
size: screen_rect.size(),
|
size: screen_rect.size(),
|
||||||
interactable: true,
|
interactable: true,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue