shell: Centralize management of sending configure requests

Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:

  => set_fullscreen
  <= configure(800, 600, [STATE_FULLSCREEN])

  => set_maximized
  <= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])

Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.

This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.

In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.

Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 1704b84..293697f 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -162,7 +162,7 @@
 
 	const struct weston_shell_client *client;
 
-	struct {
+	struct surface_state {
 		bool maximized;
 		bool fullscreen;
 		bool relative;
@@ -351,14 +351,64 @@
 	}
 }
 
+static int
+get_output_panel_height(struct desktop_shell *shell,
+			struct weston_output *output)
+{
+	struct weston_view *view;
+	int panel_height = 0;
+
+	if (!output)
+		return 0;
+
+	wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) {
+		if (view->surface->output == output) {
+			panel_height = view->surface->height;
+			break;
+		}
+	}
+
+	return panel_height;
+}
+
+static void
+send_configure_for_surface(struct shell_surface *shsurf)
+{
+	int32_t width, height;
+	struct surface_state *state;
+
+	if (shsurf->state_requested)
+		state = &shsurf->requested_state;
+	else if (shsurf->state_changed)
+		state = &shsurf->next_state;
+	else
+		state = &shsurf->state;
+
+	if (state->fullscreen) {
+		width = shsurf->output->width;
+		height = shsurf->output->height;
+	} else if (state->maximized) {
+		struct desktop_shell *shell;
+		uint32_t panel_height = 0;
+
+		shell = shell_surface_get_shell(shsurf);
+		panel_height = get_output_panel_height(shell, shsurf->output);
+
+		width = shsurf->output->width;
+		height = shsurf->output->height - panel_height;
+	} else {
+		width = 0;
+		height = 0;
+	}
+
+	shsurf->client->send_configure(shsurf->surface, width, height);
+}
+
 static void
 shell_surface_state_changed(struct shell_surface *shsurf)
 {
-	if (shell_surface_is_xdg_surface(shsurf)) {
-		shsurf->client->send_configure(shsurf->surface,
-					       shsurf->surface->width,
-					       shsurf->surface->height);
-	}
+	if (shell_surface_is_xdg_surface(shsurf))
+		send_configure_for_surface(shsurf);
 }
 
 static void
@@ -2122,26 +2172,6 @@
 		restore_output_mode(output);
 }
 
-static int
-get_output_panel_height(struct desktop_shell *shell,
-			struct weston_output *output)
-{
-	struct weston_view *view;
-	int panel_height = 0;
-
-	if (!output)
-		return 0;
-
-	wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) {
-		if (view->surface->output == output) {
-			panel_height = view->surface->height;
-			break;
-		}
-	}
-
-	return panel_height;
-}
-
 /* The surface will be inserted into the list immediately after the link
  * returned by this function (i.e. will be stacked immediately above the
  * returned link). */
@@ -2343,19 +2373,13 @@
 	       struct weston_output *output)
 {
 	shell_surface_set_output(shsurf, output);
+	shsurf->type = SHELL_SURFACE_TOPLEVEL;
 
 	shsurf->fullscreen_output = shsurf->output;
 	shsurf->fullscreen.type = method;
 	shsurf->fullscreen.framerate = framerate;
 
-	shsurf->type = SHELL_SURFACE_TOPLEVEL;
-
-	shsurf->client->send_configure(shsurf->surface,
-				       shsurf->output->width,
-				       shsurf->output->height);
-
-	/* The layer_link is updated in set_surface_type(),
-	 * called from configure. */
+	send_configure_for_surface(shsurf);
 }
 
 static void
@@ -2414,10 +2438,9 @@
 	shell_surface_set_parent(shsurf, NULL);
 
 	surface_clear_next_states(shsurf);
-	set_fullscreen(shsurf, method, framerate, output);
-
 	shsurf->next_state.fullscreen = true;
 	shsurf->state_changed = true;
+	set_fullscreen(shsurf, method, framerate, output);
 }
 
 static void
@@ -2463,19 +2486,10 @@
 set_maximized(struct shell_surface *shsurf,
               struct weston_output *output)
 {
-	struct desktop_shell *shell;
-	uint32_t panel_height = 0;
-
 	shell_surface_set_output(shsurf, output);
-
-	shell = shell_surface_get_shell(shsurf);
-	panel_height = get_output_panel_height(shell, shsurf->output);
-
-	shsurf->client->send_configure(shsurf->surface,
-	                               shsurf->output->width,
-	                               shsurf->output->height - panel_height);
-
 	shsurf->type = SHELL_SURFACE_TOPLEVEL;
+
+	send_configure_for_surface(shsurf);
 }
 
 static void
@@ -3463,7 +3477,7 @@
 
 	shsurf->state_requested = true;
 	shsurf->requested_state.maximized = false;
-	shsurf->client->send_configure(shsurf->surface, 0, 0);
+	send_configure_for_surface(shsurf);
 }
 
 static void
@@ -3497,7 +3511,7 @@
 
 	shsurf->state_requested = true;
 	shsurf->requested_state.fullscreen = false;
-	shsurf->client->send_configure(shsurf->surface, 0, 0);
+	send_configure_for_surface(shsurf);
 }
 
 static void