frang75 / nappgui_src

SDK for building cross-platform desktop apps in ANSI-C
https://www.nappgui.com
MIT License
506 stars 50 forks source link

Modal Window Close Crash. #24

Closed dgramirez closed 10 months ago

dgramirez commented 2 years ago

Hello,

First thing I would like to mention, I really enjoy this library! Imo, easy to grasp and not really bloated like other libraries I've used prior.

I've came across an issue on Windows. Whenever I would close a second window, using the [X] on the title bar, it would crash the whole program. After looking into the debug, it crashes at the strcmp between "bool_t" and an unknown value with "0x3f3f3f3f3f3f3f3f", and looking even more back the event->return_type inside event_result_imp() is also set to "0x3f3f3f3f3f3f3f3f".

The good news, if I were to not use the [X] on the title bar, It wouldn't crash (eg. a push button, set to destroy the modal window).

I have modified the "HelloWorld" main.c files to show you what I've encountered. I made sure that I did a fresh compilation of nappgui before sending this issue (using vs2022): win32_modal_crash.zip

I also sent two pics (the actual modal window in where it would crash, and the event_result_imp 0x3f3f.) Hopefully this crash is easily replicated on your end. [Or hopefully this is just my machine and everything is truly ok, that works too lol]

frang75 commented 2 years ago

Hi @dgramirez! Thank you very much for the feedback and use NAppGUI.

The crash has occurred because the window has been destroyed within an event that launches the window itself. I leave this issue open to include a patch for this case in NAppGUI 1.3. For now, you can avoid this issue by destroying the window outside of the event handler.

/*
 * NAppGUI Cross-platform C SDK
 * 2015-2022 Francisco Garcia Collado
 * MIT Licence
 * https://nappgui.com/en/legal/license.html
 *
 * File: main.c
 *
 */

/* NAppGUI Hello World */

#include "nappgui.h"

typedef struct _app_t App;

struct _app_t
{
    Window *window;
    Window *modal_window;
    TextView *text;
    uint32_t clicks;
};

/*---------------------------------------------------------------------------*/

static void i_OnCloseModal(App* app, Event* e)
{
    window_stop_modal(app->modal_window, 0);
    unref(e);
}

/*---------------------------------------------------------------------------*/

static Panel* i_modal_panel(App* app)
{
    Panel *panel = panel_create();
    Layout* layout = layout_create(1, 2);
    Label* label = label_create();
    Button* button = button_push();

    label_text(label, "Hello! I'm a Modal Window!");
    button_text(button, "Lets go back!");
    button_OnClick(button, listener(app, i_OnCloseModal, App));

    layout_label(layout, label, 0, 0);
    layout_button(layout, button, 0, 1);
    panel_layout(panel, layout);

    return panel;
}

/*---------------------------------------------------------------------------*/

static void i_modal_create(App* app)
{
    Panel* panel = i_modal_panel(app);
    app->modal_window = window_create(ekWNSTD);
    window_panel(app->modal_window, panel);

    window_title(app->modal_window, "Hello, Modal World!");
    window_origin(app->modal_window, v2df(500, 200));

    // Stop modal window is the default option when we press [X] button
    // This listener is necessary if you want to "abort" the window close with same condition
    // window_OnClose(app->modal_window, listener(app, i_OnCloseModal, App));

    // Here the current runloop will wait until some 'window_stop_modal'
    window_modal(app->modal_window, app->window);

    // Here you can safely destroy the window
    window_destroy(&app->modal_window);

    app->modal_window = NULL;
}

/*---------------------------------------------------------------------------*/

static void i_OnButton(App *app, Event *e)
{
    i_modal_create(app);
    unref(e);
    /*
    String *msg = str_printf("Button click (%d)\n", app->clicks);
    textview_writef(app->text, tc(msg));
    str_destroy(&msg);
    app->clicks += 1;
    unref(e);
    */
}

/*---------------------------------------------------------------------------*/

static Panel *i_panel(App *app)
{
    Panel *panel = panel_create();
    Layout *layout = layout_create(1, 3);
    Label *label = label_create();
    Button *button = button_push();
    TextView *text = textview_create();
    app->text = text;
    label_text(label, "Hello!, I'm a label");
    button_text(button, "Click Me!");
    button_OnClick(button, listener(app, i_OnButton, App));
    layout_label(layout, label, 0, 0);
    layout_button(layout, button, 0, 1);
    layout_textview(layout, text, 0, 2);
    layout_hsize(layout, 0, 250);
    layout_vsize(layout, 2, 100);
    layout_margin(layout, 5);
    layout_vmargin(layout, 0, 5);
    layout_vmargin(layout, 1, 5);
    panel_layout(panel, layout);
    return panel;
}

/*---------------------------------------------------------------------------*/

static void i_OnClose(App *app, Event *e)
{
    osapp_finish();
    unref(app);
    unref(e);
}

/*---------------------------------------------------------------------------*/

static App *i_create(void)
{
    App *app = heap_new0(App);
    Panel *panel = i_panel(app);
    app->window = window_create(ekWNSTD);
    window_panel(app->window, panel);
    window_title(app->window, "Hello, World!");
    window_origin(app->window, v2df(500, 200));
    window_OnClose(app->window, listener(app, i_OnClose, App));
    window_show(app->window);
    return app;
}

/*---------------------------------------------------------------------------*/

static void i_destroy(App **app)
{
    window_destroy(&(*app)->window);
    heap_delete(app, App);
}

/*---------------------------------------------------------------------------*/

#include "osmain.h"
osmain(i_create, i_destroy, "", App)