xdg-shell: Add show_window_menu request
diff --git a/clients/window.c b/clients/window.c
index d5fbd54..b82a93e 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2228,61 +2228,19 @@
 	}
 }
 
-static void
-frame_menu_func(void *data, struct input *input, int index)
-{
-	struct window *window = data;
-	struct display *display;
-
-	switch (index) {
-	case 0: /* close */
-		window_close(window);
-		break;
-	case 1: /* move to workspace above */
-		display = window->display;
-		if (display->workspace > 0)
-			workspace_manager_move_surface(
-				display->workspace_manager,
-				window->main_surface->surface,
-				display->workspace - 1);
-		break;
-	case 2: /* move to workspace below */
-		display = window->display;
-		if (display->workspace < display->workspace_count - 1)
-			workspace_manager_move_surface(
-				display->workspace_manager,
-				window->main_surface->surface,
-				display->workspace + 1);
-		break;
-	case 3: /* fullscreen */
-		/* we don't have a way to get out of fullscreen for now */
-		if (window->fullscreen_handler)
-			window->fullscreen_handler(window, window->user_data);
-		break;
-	}
-}
-
 void
 window_show_frame_menu(struct window *window,
 		       struct input *input, uint32_t time)
 {
 	int32_t x, y;
-	int count;
 
-	static const char *entries[] = {
-		"Close",
-		"Move to workspace above", "Move to workspace below",
-		"Fullscreen"
-	};
-
-	if (window->fullscreen_handler)
-		count = ARRAY_LENGTH(entries);
-	else
-		count = ARRAY_LENGTH(entries) - 1;
-
-	input_get_position(input, &x, &y);
-	window_show_menu(window->display, input, time, window,
-			 x - 10, y - 10, frame_menu_func, entries, count);
+	if (window->xdg_surface) {
+		input_get_position(input, &x, &y);
+		xdg_surface_show_window_menu(window->xdg_surface,
+					     input_get_seat(input),
+					     window->display->serial,
+					     x - 10, y - 10);
+	}
 }
 
 static int
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index dd0b2f9..46c6e18 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -3417,6 +3417,17 @@
 }
 
 static void
+xdg_surface_show_window_menu(struct wl_client *client,
+			     struct wl_resource *surface_resource,
+			     struct wl_resource *seat_resource,
+			     uint32_t serial,
+			     int32_t x,
+			     int32_t y)
+{
+	/* TODO */
+}
+
+static void
 xdg_surface_set_title(struct wl_client *client,
 			struct wl_resource *resource, const char *title)
 {
@@ -3528,6 +3539,7 @@
 	xdg_surface_set_margin,
 	xdg_surface_set_title,
 	xdg_surface_set_app_id,
+	xdg_surface_show_window_menu,
 	xdg_surface_move,
 	xdg_surface_resize,
 	xdg_surface_ack_configure,
diff --git a/protocol/xdg-shell.xml b/protocol/xdg-shell.xml
index 3c18610..28add40 100644
--- a/protocol/xdg-shell.xml
+++ b/protocol/xdg-shell.xml
@@ -198,6 +198,26 @@
       <arg name="app_id" type="string"/>
     </request>
 
+    <request name="show_window_menu">
+      <description summary="show the window menu">
+        Clients implementing client-side decorations might want to show
+        a context menu when right-clicking on the decorations, giving the
+        user a menu that they can use to maximize or minimize the window.
+
+        This request asks the compositor to pop up such a window menu at
+        the given position, relative to the parent surface. There are
+        no guarantees as to what the window menu contains.
+
+        Your surface must have focus on the seat passed in to pop up the
+        window menu.
+      </description>
+
+      <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
+      <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
+      <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
+      <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
+    </request>
+
     <request name="move">
       <description summary="start an interactive move">
 	Start a pointer-driven move of the surface.