Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[eframe native-windows] Entire program crashes when eframe viewport is resized fast from a corner #5460

Open
AvinashPrajapati opened this issue Dec 11, 2024 · 0 comments

Comments

@AvinashPrajapati
Copy link

use eframe::{self};
use eframe::egui::{self, CentralPanel, Sense, UiBuilder, ViewportCommand, RichText};

struct MyApp {
    window_size: egui::Vec2,
}

impl Default for MyApp {
    fn default() -> Self {
        MyApp {
            window_size: egui::vec2(400.0, 300.0),
        }
    }
}

impl eframe::App for MyApp {
    fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] {
        egui::Rgba::TRANSPARENT.to_array() // Make sure we don't paint anything behind the rounded corners
    }

    fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
        custom_window_frame(ctx, frame, "Custom Window", &mut self.window_size, |ui| {
            ui.label(RichText::new("This is bold").strong());
        });
    }
}

fn custom_window_frame(
    ctx: &egui::Context,
    frame: &mut eframe::Frame,
    title: &str,
    window_size: &mut egui::Vec2,
    add_contents: impl FnOnce(&mut egui::Ui),
) {
    let panel_frame = egui::Frame {
        fill: ctx.style().visuals.window_fill(),
        rounding: 5.0.into(),
        stroke: ctx.style().visuals.widgets.noninteractive.fg_stroke,
        outer_margin: 0.5.into(), // so the stroke is within the bounds
        ..Default::default()
    };
    // panel_frame.

    CentralPanel::default().frame(panel_frame).show(ctx, |ui| {
        let mut app_rect = ui.max_rect();

        let title_bar_height = 25.0;
        let title_bar_rect = {
            let mut rect = app_rect;
            rect.max.y = rect.min.y + title_bar_height;
            rect
        };

        title_bar_ui(ui, title_bar_rect, title);

        // Add the contents:
        let content_rect = {
            let mut rect = app_rect;
            rect.min.y = title_bar_rect.max.y;
            rect
        }
        .shrink(4.0);
        let mut content_ui = ui.new_child(UiBuilder::new().max_rect(content_rect));
        add_contents(&mut content_ui);

        // Visual indicator for resizing
        // Resize interaction on bottom-right corner
        let resize_area_size = 10.0;
        let resize_rect = egui::Rect {
            min: app_rect.right_bottom() - egui::vec2(resize_area_size, resize_area_size),
            max: app_rect.right_bottom(),
        };

        let resize_response =
            ui.interact(resize_rect, egui::Id::new("resize_handle"), Sense::drag());
        if resize_response.dragged() {
            if let Some(pointer_pos) = resize_response.hover_pos() {
                let delta = pointer_pos - app_rect.right_bottom();

                // Update window size
                window_size.x = (window_size.x + delta.x).max(200.0); // Min width
                window_size.y = (window_size.y + delta.y).max(150.0); // Min height

                // Update the application rectangle

                // Update the app rectangle based on the new window size
                ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(*window_size));
                


                // ui.ctx().request_repaint();
            }
        }

        if resize_response.hovered() {
            ui.painter()
                .rect_filled(resize_rect, 1.0, egui::Color32::from_white_alpha(128));
        }
    });
}

fn title_bar_ui(ui: &mut egui::Ui, title_bar_rect: eframe::epaint::Rect, title: &str) {
    use egui::{vec2, Align2, FontId, Id, PointerButton, Sense, UiBuilder};

    let painter = ui.painter();

    let title_bar_response = ui.interact(
        title_bar_rect,
        Id::new("title_bar"),
        Sense::click_and_drag(),
    );

    // Paint the title:
    painter.text(
        title_bar_rect.center() - egui::vec2(title_bar_rect.width() / 3.0, 0.0),
        Align2::CENTER_CENTER,
        title,
        FontId::proportional(15.0),
        ui.style().visuals.text_color(),
    );

    // Paint the line under the title:
    painter.line_segment(
        [
            title_bar_rect.left_bottom() + vec2(1.0, 0.0),
            title_bar_rect.right_bottom() + vec2(-1.0, 0.0),
        ],
        ui.visuals().widgets.noninteractive.bg_stroke,
    );

    // Interact with the title bar (drag to move window):
    if title_bar_response.double_clicked() {
        let is_maximized = ui.input(|i| i.viewport().maximized.unwrap_or(false));
        ui.ctx()
            .send_viewport_cmd(ViewportCommand::Maximized(!is_maximized));
    }

    if title_bar_response.drag_started_by(PointerButton::Primary) {
        ui.ctx().send_viewport_cmd(ViewportCommand::StartDrag);
    }

    // Close button for the window
    ui.allocate_new_ui(
        UiBuilder::new()
            .max_rect(title_bar_rect)
            .layout(egui::Layout::right_to_left(egui::Align::Center)),
        |ui| {
            ui.spacing_mut().item_spacing.x = 0.0;
            ui.visuals_mut().button_frame = false;
            ui.add_space(8.0);
            close_button(ui);
        },
    );
}

fn close_button(ui: &mut egui::Ui) {
    use egui::{Button, RichText};

    let button_height = 12.0;

    let close_response = ui
        .add(Button::new(RichText::new("❌").size(button_height)))
        .on_hover_text("Close the window");
    if close_response.clicked() {
        ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
    }
}

fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_decorations(false) // Hide the OS-specific "chrome" around the window
            .with_inner_size([400.0, 600.0]) // Set the initial size
            .with_min_inner_size([200.0, 300.0]) // Minimum size for the window
            .with_transparent(true), // To have rounded corners we need transparency
        ..Default::default()
    };

    eframe::run_native(
        "Custom Window with Close Button",
        options,
        Box::new(|_cc| Ok(Box::<MyApp>::default())),
    )
}

** i got the same issue here**

  • My toml file code
[package]
name = "egui-ui"
version = "0.1.0"
edition = "2021"

[dependencies]
eframe = "0.29.1"
egui = "0.29.1"

When i resize it very fast then the application just crashes.

I am guessing sending the command to resize the viewport on fast resize(each change in dimensional unit sends the command to viewport to resize) the application can not process and get crashes.

// Update the app rectangle based on the new window size
                ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(*window_size));

Any solution??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant