From 6d174cff7ab6af525319e5e12ef8930e648a4b3c Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 19 Jan 2012 15:17:59 +0200 Subject: [PATCH] window: menu leak fixes When a menu self-destructs, free also the widget and struct menu. As menus are self-destructing, it does not make sense to store the window pointer, since we cannot clear it automatically. Therefore, rename window_create_menu() to window_show_menu() that does not return the window pointer. It also calls window_schedule_redraw() internally. Fixes Valgrind reported memory leaks. The alternative would be to explicitly destroy the menu in application's menu callback. Signed-off-by: Pekka Paalanen --- clients/desktop-shell.c | 9 +++------ clients/resizor.c | 8 ++------ clients/window.c | 39 ++++++++++++++++++++------------------- clients/window.h | 10 +++++----- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index e2e2433c..642e92a8 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -59,7 +59,6 @@ struct panel { struct surface base; struct window *window; struct widget *widget; - struct window *menu; struct wl_list launcher_list; }; @@ -141,11 +140,9 @@ show_menu(struct panel *panel, struct input *input, uint32_t time) }; input_get_position(input, &x, &y); - panel->menu = window_create_menu(window_get_display(panel->window), - input, time, panel->window, - x - 10, y - 10, NULL, entries, 4); - - window_schedule_redraw(panel->menu); + window_show_menu(window_get_display(panel->window), + input, time, panel->window, + x - 10, y - 10, NULL, entries, 4); } static void diff --git a/clients/resizor.c b/clients/resizor.c index 5eeb8ea2..15900fce 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -171,12 +171,8 @@ show_menu(struct resizor *resizor, struct input *input, uint32_t time) }; input_get_position(input, &x, &y); - resizor->menu = window_create_menu(resizor->display, - input, time, resizor->window, - x - 10, y - 10, - menu_func, entries, 4); - - window_schedule_redraw(resizor->menu); + window_show_menu(resizor->display, input, time, resizor->window, + x - 10, y - 10, menu_func, entries, 4); } static void diff --git a/clients/window.c b/clients/window.c index d1833af6..6cd93000 100644 --- a/clients/window.c +++ b/clients/window.c @@ -132,7 +132,6 @@ struct window { struct frame *frame; struct widget *widget; - struct window *menu; void *user_data; struct wl_list link; @@ -1394,13 +1393,8 @@ frame_button_handler(struct widget *widget, } } else if (button == BTN_RIGHT && state == 1) { input_get_position(input, &x, &y); - window->menu = window_create_menu(window->display, - input, time, - window, - x - 10, y - 10, - frame_menu_func, - entries, 4); - window_schedule_redraw(window->menu); + window_show_menu(window->display, input, time, window, + x - 10, y - 10, frame_menu_func, entries, 4); } } @@ -2081,6 +2075,14 @@ handle_configure(void *data, struct wl_shell_surface *shell_surface, window_resize(window, width, height); } +static void +menu_destroy(struct menu *menu) +{ + widget_destroy(menu->widget); + window_destroy(menu->window); + free(menu); +} + static void handle_popup_done(void *data, struct wl_shell_surface *shell_surface) { @@ -2094,7 +2096,7 @@ handle_popup_done(void *data, struct wl_shell_surface *shell_surface) menu->func(window->parent, menu->current, window->parent->user_data); input_ungrab(menu->input, 0); - window_destroy(window); + menu_destroy(menu); } static const struct wl_shell_surface_listener shell_surface_listener = { @@ -2393,7 +2395,7 @@ menu_button_handler(struct widget *widget, menu->func(menu->window->parent, menu->current, menu->window->parent->user_data); input_ungrab(input, time); - window_destroy(menu->widget->window); + menu_destroy(menu); } } @@ -2437,11 +2439,11 @@ menu_redraw_handler(struct widget *widget, void *data) cairo_destroy(cr); } -struct window * -window_create_menu(struct display *display, - struct input *input, uint32_t time, struct window *parent, - int32_t x, int32_t y, - menu_func_t func, const char **entries, int count) +void +window_show_menu(struct display *display, + struct input *input, uint32_t time, struct window *parent, + int32_t x, int32_t y, + menu_func_t func, const char **entries, int count) { struct window *window; struct menu *menu; @@ -2449,12 +2451,12 @@ window_create_menu(struct display *display, menu = malloc(sizeof *menu); if (!menu) - return NULL; + return; window = window_create_internal(parent->display, parent, 200, count * 20 + margin * 2); if (!window) - return NULL; + return; menu->window = window; menu->widget = window_add_widget(menu->window, menu); @@ -2480,8 +2482,7 @@ window_create_menu(struct display *display, widget_set_button_handler(menu->widget, menu_button_handler); input_grab(input, menu->widget, 0); - - return window; + window_schedule_redraw(window); } void diff --git a/clients/window.h b/clients/window.h index 4ff2fc88..e35d6577 100644 --- a/clients/window.h +++ b/clients/window.h @@ -200,11 +200,11 @@ window_create_transient(struct display *display, struct window *parent, typedef void (*menu_func_t)(struct window *window, int index, void *data); -struct window * -window_create_menu(struct display *display, - struct input *input, uint32_t time, struct window *parent, - int32_t x, int32_t y, - menu_func_t func, const char **entries, int count); +void +window_show_menu(struct display *display, + struct input *input, uint32_t time, struct window *parent, + int32_t x, int32_t y, + menu_func_t func, const char **entries, int count); void window_destroy(struct window *window);