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 <ppaalanen@gmail.com>
dev
Pekka Paalanen 13 years ago
parent 84d62dc999
commit 6d174cff7a
  1. 9
      clients/desktop-shell.c
  2. 8
      clients/resizor.c
  3. 39
      clients/window.c
  4. 10
      clients/window.h

@ -59,7 +59,6 @@ struct panel {
struct surface base; struct surface base;
struct window *window; struct window *window;
struct widget *widget; struct widget *widget;
struct window *menu;
struct wl_list launcher_list; 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); input_get_position(input, &x, &y);
panel->menu = window_create_menu(window_get_display(panel->window), window_show_menu(window_get_display(panel->window),
input, time, panel->window, input, time, panel->window,
x - 10, y - 10, NULL, entries, 4); x - 10, y - 10, NULL, entries, 4);
window_schedule_redraw(panel->menu);
} }
static void static void

@ -171,12 +171,8 @@ show_menu(struct resizor *resizor, struct input *input, uint32_t time)
}; };
input_get_position(input, &x, &y); input_get_position(input, &x, &y);
resizor->menu = window_create_menu(resizor->display, window_show_menu(resizor->display, input, time, resizor->window,
input, time, resizor->window, x - 10, y - 10, menu_func, entries, 4);
x - 10, y - 10,
menu_func, entries, 4);
window_schedule_redraw(resizor->menu);
} }
static void static void

@ -132,7 +132,6 @@ struct window {
struct frame *frame; struct frame *frame;
struct widget *widget; struct widget *widget;
struct window *menu;
void *user_data; void *user_data;
struct wl_list link; struct wl_list link;
@ -1394,13 +1393,8 @@ frame_button_handler(struct widget *widget,
} }
} else if (button == BTN_RIGHT && state == 1) { } else if (button == BTN_RIGHT && state == 1) {
input_get_position(input, &x, &y); input_get_position(input, &x, &y);
window->menu = window_create_menu(window->display, window_show_menu(window->display, input, time, window,
input, time, x - 10, y - 10, frame_menu_func, entries, 4);
window,
x - 10, y - 10,
frame_menu_func,
entries, 4);
window_schedule_redraw(window->menu);
} }
} }
@ -2081,6 +2075,14 @@ handle_configure(void *data, struct wl_shell_surface *shell_surface,
window_resize(window, width, height); window_resize(window, width, height);
} }
static void
menu_destroy(struct menu *menu)
{
widget_destroy(menu->widget);
window_destroy(menu->window);
free(menu);
}
static void static void
handle_popup_done(void *data, struct wl_shell_surface *shell_surface) 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); menu->func(window->parent, menu->current, window->parent->user_data);
input_ungrab(menu->input, 0); input_ungrab(menu->input, 0);
window_destroy(window); menu_destroy(menu);
} }
static const struct wl_shell_surface_listener shell_surface_listener = { 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->func(menu->window->parent,
menu->current, menu->window->parent->user_data); menu->current, menu->window->parent->user_data);
input_ungrab(input, time); 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); cairo_destroy(cr);
} }
struct window * void
window_create_menu(struct display *display, window_show_menu(struct display *display,
struct input *input, uint32_t time, struct window *parent, struct input *input, uint32_t time, struct window *parent,
int32_t x, int32_t y, int32_t x, int32_t y,
menu_func_t func, const char **entries, int count) menu_func_t func, const char **entries, int count)
{ {
struct window *window; struct window *window;
struct menu *menu; struct menu *menu;
@ -2449,12 +2451,12 @@ window_create_menu(struct display *display,
menu = malloc(sizeof *menu); menu = malloc(sizeof *menu);
if (!menu) if (!menu)
return NULL; return;
window = window_create_internal(parent->display, parent, window = window_create_internal(parent->display, parent,
200, count * 20 + margin * 2); 200, count * 20 + margin * 2);
if (!window) if (!window)
return NULL; return;
menu->window = window; menu->window = window;
menu->widget = window_add_widget(menu->window, menu); 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); widget_set_button_handler(menu->widget, menu_button_handler);
input_grab(input, menu->widget, 0); input_grab(input, menu->widget, 0);
window_schedule_redraw(window);
return window;
} }
void void

@ -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); typedef void (*menu_func_t)(struct window *window, int index, void *data);
struct window * void
window_create_menu(struct display *display, window_show_menu(struct display *display,
struct input *input, uint32_t time, struct window *parent, struct input *input, uint32_t time, struct window *parent,
int32_t x, int32_t y, int32_t x, int32_t y,
menu_func_t func, const char **entries, int count); menu_func_t func, const char **entries, int count);
void void
window_destroy(struct window *window); window_destroy(struct window *window);

Loading…
Cancel
Save