mirror of
https://github.com/emilk/egui.git
synced 2026-06-27 15:13:12 -04:00
Some work making the native window to look like the egui one, and to work the same
This commit is contained in:
@@ -513,7 +513,7 @@ impl Default for NativeOptions {
|
||||
min_window_size: None,
|
||||
max_window_size: None,
|
||||
resizable: true,
|
||||
transparent: false,
|
||||
transparent: true,
|
||||
mouse_passthrough: false,
|
||||
|
||||
active: true,
|
||||
|
||||
@@ -424,7 +424,10 @@ mod glow_integration {
|
||||
prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext},
|
||||
surface::GlSurface,
|
||||
};
|
||||
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use winit::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
window::ResizeDirection,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1252,6 +1255,45 @@ mod glow_integration {
|
||||
}
|
||||
}
|
||||
}
|
||||
egui::window::ViewportCommand::InnerSize(width, height) => {
|
||||
win.set_inner_size(PhysicalSize::new(width, height));
|
||||
}
|
||||
egui::window::ViewportCommand::Resize(
|
||||
top,
|
||||
bottom,
|
||||
right,
|
||||
left,
|
||||
) => {
|
||||
win.drag_resize_window(
|
||||
match (top, bottom, right, left) {
|
||||
(true, false, false, false) => {
|
||||
ResizeDirection::North
|
||||
}
|
||||
(false, true, false, false) => {
|
||||
ResizeDirection::South
|
||||
}
|
||||
(false, false, true, false) => {
|
||||
ResizeDirection::East
|
||||
}
|
||||
(false, false, false, true) => {
|
||||
ResizeDirection::West
|
||||
}
|
||||
(true, false, true, false) => {
|
||||
ResizeDirection::NorthEast
|
||||
}
|
||||
(false, true, true, false) => {
|
||||
ResizeDirection::SouthEast
|
||||
}
|
||||
(true, false, false, true) => {
|
||||
ResizeDirection::NorthWest
|
||||
}
|
||||
(false, true, false, true) => {
|
||||
ResizeDirection::SouthWest
|
||||
}
|
||||
_ => ResizeDirection::East,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -147,6 +147,9 @@ impl ViewportBuilder {
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub enum ViewportCommand {
|
||||
Drag,
|
||||
InnerSize(u32, u32),
|
||||
/// Top, Bottom, Right, Left
|
||||
Resize(bool, bool, bool, bool),
|
||||
}
|
||||
|
||||
/// Builder for a floating window which can be dragged, closed, collapsed, resized and scrolled (off by default).
|
||||
@@ -195,7 +198,9 @@ impl<'open> Window<'open> {
|
||||
.with_stroke(false)
|
||||
.min_size([96.0, 32.0])
|
||||
.default_size([340.0, 420.0]), // Default inner size of a window
|
||||
scroll: ScrollArea::neither(),
|
||||
scroll: ScrollArea::both()
|
||||
.auto_shrink([false, false])
|
||||
.enable_scrolling(true),
|
||||
collapsible: true,
|
||||
default_open: true,
|
||||
with_title_bar: true,
|
||||
@@ -461,15 +466,19 @@ impl<'open> Window<'open> {
|
||||
true
|
||||
};
|
||||
|
||||
// let is_explicitly_closed = matches!(open, Some(false));
|
||||
let is_open = is_open || ctx.memory(|mem| mem.everything_is_visible());
|
||||
|
||||
if !is_open {
|
||||
return;
|
||||
}
|
||||
|
||||
let show_close_button = open.is_some();
|
||||
|
||||
'create_viewport: {
|
||||
if !embedded && ctx.is_desktop() {
|
||||
if !is_open {
|
||||
return;
|
||||
}
|
||||
if let Some(size) = ctx.data(|data| data.get_temp::<Vec2>(area.id.with("size"))) {
|
||||
let size = size.round() + ctx.style().spacing.window_margin.sum();
|
||||
let size = size.round()
|
||||
+ ctx.style().spacing.window_margin.sum() * ctx.pixels_per_point();
|
||||
window_builder =
|
||||
window_builder.with_inner_size((size.x as u32 + 1, size.y as u32 + 1));
|
||||
} else {
|
||||
@@ -478,36 +487,262 @@ impl<'open> Window<'open> {
|
||||
}
|
||||
window_builder.close_button = open.is_some();
|
||||
window_builder.resizable = resize.is_resizable();
|
||||
|
||||
let area_id = area.id;
|
||||
window_builder.decorations = !with_title_bar;
|
||||
let pix = ctx.pixels_per_point();
|
||||
let min_size = resize.min_size * pix;
|
||||
let max_size = resize.max_size * pix;
|
||||
let max_size = if !max_size.is_finite() {
|
||||
None
|
||||
} else {
|
||||
Some(max_size)
|
||||
};
|
||||
window_builder.min_inner_size = Some((min_size.x as u32, min_size.y as u32));
|
||||
if let Some(max_size) = max_size {
|
||||
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
||||
}
|
||||
|
||||
ctx.create_viewport(
|
||||
window_builder,
|
||||
move |ctx, viewport_id, parent_viewport_id| {
|
||||
let mut frame = frame.unwrap_or(Frame::window(&ctx.style())).rounding(0.0);
|
||||
let count = ctx.input(|input| {
|
||||
input
|
||||
.events
|
||||
.iter()
|
||||
.filter(|event| {
|
||||
if let Event::WindowEvent(WindowEvent::CloseRequested) = **event
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
let mut op = is_open;
|
||||
let open = if show_close_button {
|
||||
Some(&mut op)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = scroll.clone();
|
||||
let title = title.clone();
|
||||
let frame = frame
|
||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||
.outer_margin(0.0)
|
||||
.shadow(Shadow::NONE)
|
||||
.stroke(Stroke::new(
|
||||
1.0,
|
||||
if ctx.input(|i| i.focused) {
|
||||
Color32::BLUE
|
||||
} else {
|
||||
Color32::BROWN
|
||||
},
|
||||
));
|
||||
|
||||
area.show_open_close_animation(ctx, &frame, is_open);
|
||||
|
||||
let area_id = area.id;
|
||||
let area_layer_id = area.layer();
|
||||
let resize_id = area_id.with("resize");
|
||||
let mut collapsing = CollapsingState::load_with_default_open(
|
||||
ctx,
|
||||
area_id.with("collapsing"),
|
||||
default_open,
|
||||
);
|
||||
|
||||
let is_collapsed = with_title_bar && !collapsing.is_open();
|
||||
let possible = PossibleInteractions::new(&area, &resize, is_collapsed);
|
||||
|
||||
let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it
|
||||
let resize = resize.resizable(false); // We move it manually
|
||||
let mut resize = resize.id(resize_id);
|
||||
|
||||
let mut area = area.begin(ctx);
|
||||
let win_size = ctx.input(|i| i.screen_rect.size());
|
||||
area.state_mut().set_left_top_pos(Pos2::ZERO);
|
||||
area.state_mut().size = win_size;
|
||||
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
||||
|
||||
let title_bar_height = if with_title_bar {
|
||||
let style = ctx.style();
|
||||
ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let margins = frame.outer_margin.sum()
|
||||
+ frame.inner_margin.sum()
|
||||
+ vec2(0.0, title_bar_height);
|
||||
|
||||
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
||||
state.requested_size = Some(win_size - margins);
|
||||
state.store(ctx, resize_id);
|
||||
}
|
||||
|
||||
// First interact (move etc) to avoid frame delay:
|
||||
let last_frame_outer_rect = area.state().rect();
|
||||
|
||||
let interaction = if possible.movable || possible.resizable() {
|
||||
window_interaction(
|
||||
ctx,
|
||||
possible,
|
||||
area_layer_id,
|
||||
area_id.with("frame_resize"),
|
||||
last_frame_outer_rect,
|
||||
)
|
||||
.and_then(|window_interaction| {
|
||||
// Calculate roughly how much larger the window size is compared to the inner rect
|
||||
|
||||
let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?;
|
||||
let mut rect = window_interaction.start_rect; // prevent drift
|
||||
|
||||
window_interaction.set_cursor(ctx);
|
||||
if window_interaction.is_resize() {
|
||||
ctx.viewport_command(
|
||||
viewport_id,
|
||||
ViewportCommand::Resize(
|
||||
window_interaction.top,
|
||||
window_interaction.bottom,
|
||||
window_interaction.right,
|
||||
window_interaction.left,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if ctx.input(|i| i.pointer.primary_pressed()) {}
|
||||
}
|
||||
ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id));
|
||||
|
||||
Some(window_interaction)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let hover_interaction =
|
||||
resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect);
|
||||
|
||||
let mut area_content_ui = area.content_ui(ctx);
|
||||
|
||||
let mut size = Vec2::new(1.0, 1.0);
|
||||
|
||||
let content_inner = {
|
||||
// BEGIN FRAME --------------------------------
|
||||
let frame_stroke = frame.stroke;
|
||||
let mut frame = frame.begin(&mut area_content_ui);
|
||||
|
||||
let title_bar = if with_title_bar {
|
||||
let title_bar = show_title_bar(
|
||||
&mut frame.content_ui,
|
||||
title,
|
||||
show_close_button,
|
||||
&mut collapsing,
|
||||
collapsible,
|
||||
);
|
||||
resize.min_size.x =
|
||||
resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
|
||||
Some(title_bar)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (content_inner, content_response) = collapsing
|
||||
.show_body_unindented(&mut frame.content_ui, |ui| {
|
||||
resize.show(ui, |ui| {
|
||||
if title_bar.is_some() {
|
||||
ui.add_space(title_content_spacing);
|
||||
}
|
||||
|
||||
if scroll.has_any_bar() {
|
||||
scroll
|
||||
.show(ui, |ui| {
|
||||
add_contents(
|
||||
ui,
|
||||
viewport_id,
|
||||
parent_viewport_id,
|
||||
)
|
||||
})
|
||||
.inner
|
||||
} else {
|
||||
add_contents(ui, viewport_id, parent_viewport_id)
|
||||
}
|
||||
})
|
||||
})
|
||||
.count()
|
||||
});
|
||||
if count > 0 {
|
||||
ctx.data_mut(|data| {
|
||||
data.insert_persisted(area_id.with("_open"), false)
|
||||
});
|
||||
.map_or((None, None), |ir| (Some(ir.inner), Some(ir.response)));
|
||||
if let Some(content_response) = &content_response {
|
||||
size = content_response.rect.size()
|
||||
}
|
||||
|
||||
let outer_rect = frame.end(&mut area_content_ui).rect;
|
||||
paint_resize_corner(
|
||||
&mut area_content_ui,
|
||||
&possible,
|
||||
outer_rect,
|
||||
frame_stroke,
|
||||
);
|
||||
|
||||
// END FRAME --------------------------------
|
||||
|
||||
if let Some(title_bar) = title_bar {
|
||||
title_bar.ui(
|
||||
&mut area_content_ui,
|
||||
outer_rect,
|
||||
&content_response,
|
||||
open,
|
||||
&mut collapsing,
|
||||
collapsible,
|
||||
);
|
||||
}
|
||||
|
||||
collapsing.store(ctx);
|
||||
|
||||
if let Some(interaction) = interaction {
|
||||
paint_frame_interaction(
|
||||
&mut area_content_ui,
|
||||
outer_rect,
|
||||
interaction,
|
||||
ctx.style().visuals.widgets.active,
|
||||
);
|
||||
} else if let Some(hover_interaction) = hover_interaction {
|
||||
if ctx.input(|i| i.pointer.has_pointer()) {
|
||||
paint_frame_interaction(
|
||||
&mut area_content_ui,
|
||||
outer_rect,
|
||||
hover_interaction,
|
||||
ctx.style().visuals.widgets.hovered,
|
||||
);
|
||||
}
|
||||
}
|
||||
content_inner
|
||||
};
|
||||
|
||||
let size = ctx.round_vec_to_pixels(area_content_ui.min_size());
|
||||
|
||||
let full_response = area.end(ctx, area_content_ui);
|
||||
|
||||
if !collapsing.is_open() {
|
||||
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||
ctx.viewport_command(
|
||||
viewport_id,
|
||||
ViewportCommand::InnerSize(size.x as u32, size.y as u32),
|
||||
);
|
||||
}
|
||||
|
||||
if ctx.input(|i| i.pointer.any_pressed()) {
|
||||
if let Some(interaction) = interaction {
|
||||
if !interaction.is_resize() {
|
||||
ctx.viewport_command(viewport_id, ViewportCommand::Drag);
|
||||
println!("Drag");
|
||||
} else {
|
||||
println!("Is resize")
|
||||
}
|
||||
} else {
|
||||
println!("No interaction")
|
||||
}
|
||||
}
|
||||
// let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||
if win_size.x < size.x {
|
||||
println!("Set size!");
|
||||
ctx.viewport_command(
|
||||
viewport_id,
|
||||
ViewportCommand::InnerSize(size.x as u32, win_size.y as u32),
|
||||
);
|
||||
}
|
||||
if win_size.y < size.y {
|
||||
println!("Set size!");
|
||||
ctx.viewport_command(
|
||||
viewport_id,
|
||||
ViewportCommand::InnerSize(win_size.x as u32, size.y as u32),
|
||||
);
|
||||
}
|
||||
if show_close_button && op != is_open {
|
||||
ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op));
|
||||
ctx.request_repaint_viewport(parent_viewport_id);
|
||||
}
|
||||
CentralPanel::default().frame(frame).show(ctx, |ui| {
|
||||
Some(add_contents(ui, viewport_id, parent_viewport_id))
|
||||
});
|
||||
},
|
||||
);
|
||||
return;
|
||||
@@ -517,10 +752,6 @@ impl<'open> Window<'open> {
|
||||
|
||||
area.show_open_close_animation(ctx, &frame, is_open);
|
||||
|
||||
if !is_open {
|
||||
return;
|
||||
}
|
||||
|
||||
let area_id = area.id;
|
||||
let area_layer_id = area.layer();
|
||||
let resize_id = area_id.with("resize");
|
||||
@@ -583,7 +814,6 @@ impl<'open> Window<'open> {
|
||||
let frame_stroke = frame.stroke;
|
||||
let mut frame = frame.begin(&mut area_content_ui);
|
||||
|
||||
let show_close_button = open.is_some();
|
||||
let title_bar = if with_title_bar {
|
||||
let title_bar = show_title_bar(
|
||||
&mut frame.content_ui,
|
||||
|
||||
Reference in New Issue
Block a user