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>
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index e2e2433..642e92a 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -59,7 +59,6 @@
 	struct surface base;
 	struct window *window;
 	struct widget *widget;
-	struct window *menu;
 	struct wl_list launcher_list;
 };
 
@@ -141,11 +140,9 @@
 	};
 
 	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 5eeb8ea..15900fc 100644
--- a/clients/resizor.c
+++ b/clients/resizor.c
@@ -171,12 +171,8 @@
 	};
 
 	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 d1833af..6cd9300 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -132,7 +132,6 @@
 
 	struct frame *frame;
 	struct widget *widget;
-	struct window *menu;
 
 	void *user_data;
 	struct wl_list link;
@@ -1394,13 +1393,8 @@
 		}
 	} 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);
 	}
 }
 
@@ -2082,6 +2076,14 @@
 }
 
 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)
 {
 	struct window *window = data;
@@ -2094,7 +2096,7 @@
 
 	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->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 @@
 	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 @@
 
 	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 @@
 	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 4ff2fc8..e35d657 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -200,11 +200,11 @@
 
 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);