[PATCH] [RFC]Shell: Hide panels when compositor has a top fullscreen surface.

zhiwen.wu at intel.com zhiwen.wu at intel.com
Tue Feb 14 00:18:19 PST 2012


From: Alex Wu <zhiwen.wu at intel.com>

 Hi krh
 This patch is the implementation of the method 3 of the proposal(http://lists.freedesktop.org/archives/wayland-devel/2012-February/002085.html) 
 for handling panels when compositor has a top fullscreen regular surface, and rebases on commit 
 8fb8d3b1b5b4ef7836a61f111aeb4aaa87ae89e4. Need your suggestion and ideas.
 The main logic and modifications are as follows:

 1.Add a struct wl_list wl_shell::hidden_panels to store the hidden panels.
 2.Add a hook weston_shell:prepare_repaint to do the stacking adjustment before output repainting.
 3.In the hook, check if we had a top and fullscreen surface.
   If yes, remove the panel surface from weston_compositor::surface_list and store them to wl_shell:hidden_panels.
   If no, and we have hidden panels, unhide them.
 4.For now, popup surface is treated as regular surface, when popup surface got on top of fullscreen surface, 
   panels will be unhidden.

 PS: Just a RFC, coding style is not aligned.
---
 src/compositor.c |    2 +
 src/compositor.h |    1 +
 src/shell.c      |  125 ++++++++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 115 insertions(+), 13 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index ab90ded..5ef830e 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -966,6 +966,8 @@ weston_output_repaint(struct weston_output *output, int msecs)
 		overlap, surface_overlap;
 	int32_t width, height;
 
+  ec->shell->prepare_repaint (ec->shell, output);
+
 	width = output->current->width +
 		output->border.left + output->border.right;
 	height = output->current->height +
diff --git a/src/compositor.h b/src/compositor.h
index 966d3f4..bc1f72b 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -135,6 +135,7 @@ struct weston_shell {
 			  struct weston_surface *surface,
 			  GLfloat x, GLfloat y, int32_t width, int32_t height);
 	void (*destroy)(struct weston_shell *shell);
+	void (*prepare_repaint)(struct weston_shell *shell, struct weston_output *output);
 };
 
 enum {
diff --git a/src/shell.c b/src/shell.c
index 66c4f01..85a487f 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -57,6 +57,7 @@ struct wl_shell {
 	struct shell_surface *lock_surface;
 	struct wl_listener lock_surface_listener;
 	struct wl_list hidden_surface_list;
+	struct wl_list hidden_panels;
 
 	struct wl_list backgrounds;
 	struct wl_list panels;
@@ -70,6 +71,7 @@ struct wl_shell {
 	} screensaver;
 };
 
+/*FIXME:Using bit flag for the type due to some surface may be both toplevel and fullscreen*/
 enum shell_surface_type {
 	SHELL_SURFACE_NONE,
 
@@ -600,7 +602,7 @@ get_shell_surface(struct weston_surface *surface)
 	struct wl_list *lst = &surface->surface.resource.destroy_listener_list;
 	struct wl_listener *listener;
 
-	/* search the destroy listener list for our callback */
+  /* search the destroy listener list for our callback */
 	wl_list_for_each(listener, lst, link) {
 		if (listener->func == shell_handle_surface_destroy) {
 			return container_of(listener, struct shell_surface,
@@ -1266,6 +1268,101 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
 	weston_surface_set_position(surface, output->x + x, output->y + y);
 }
 
+static struct weston_surface *
+top_regular_surface (struct weston_shell *base)
+{
+	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+	struct weston_compositor *compositor = shell->compositor;
+	struct wl_list *list;
+  struct weston_surface *surf;
+	struct weston_surface *tmp;
+  bool   done = false;
+
+  list = &compositor->surface_list;
+
+  wl_list_for_each_safe(surf, tmp, list, link) {
+    /*skip non-client surface*/
+		if (surf->surface.resource.client == NULL)
+			continue;
+    if (get_shell_surface_type(surf) == SHELL_SURFACE_LOCK)
+      continue;
+    if (get_shell_surface_type(surf) == SHELL_SURFACE_SCREENSAVER)
+      continue;
+    if (get_shell_surface_type(surf) == SHELL_SURFACE_PANEL)
+      continue;
+    if (get_shell_surface_type(surf) == SHELL_SURFACE_BACKGROUND) {
+      break;
+    }
+    /*got the top regular surface*/
+    done = true;
+    break;
+  }
+
+  if (!done) {
+    printf ("no regular surface\n");
+    surf = NULL;
+  }
+
+  return surf;
+}
+
+static bool 
+is_fullscreen_surface (struct weston_surface *base)
+{
+  struct shell_surface *shsurf;
+  enum shell_surface_type surf_type;
+
+  if (!base) {
+    return false;
+  }
+
+  shsurf = get_shell_surface (base);
+  surf_type = get_shell_surface_type (base);
+
+  if (surf_type == SHELL_SURFACE_FULLSCREEN)
+    return true;
+  else
+    return false;
+}
+
+static void
+prepare_repaint (struct weston_shell *base, struct weston_output *output)
+{
+  struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+	struct weston_compositor *compositor = shell->compositor;
+  struct weston_surface *top_regular_surf;
+	struct weston_surface *tmp;
+  struct shell_surface *panel;
+  bool   do_damage = false;
+
+  top_regular_surf = top_regular_surface (base);
+
+  if (is_fullscreen_surface (top_regular_surf)){ 
+    if (wl_list_empty (&shell->hidden_panels) && !wl_list_empty (&shell->panels)) {
+      /*hide panels*/
+      wl_list_for_each(panel, &shell->panels, link) {
+        panel->surface->output = NULL;
+        wl_list_remove(&panel->surface->link);
+        wl_list_insert(shell->hidden_panels.prev, &panel->surface->link);
+      }
+      do_damage = true;
+    }
+  } else {
+    if (!wl_list_empty (&shell->hidden_panels)) {
+      /*unhide panels*/
+      struct wl_list *list = weston_compositor_top(compositor);
+      wl_list_insert_list(list, &shell->hidden_panels);
+      wl_list_init(&shell->hidden_panels);
+      do_damage = true;
+    }
+  }
+
+  if (do_damage) {
+    weston_output_damage (output);
+  }
+  return;
+}
+
 static void
 map(struct weston_shell *base,
     struct weston_surface *surface, int32_t width, int32_t height)
@@ -1344,14 +1441,14 @@ map(struct weston_shell *base,
 		break;
 	default:
 		/* everything else just below the panel */
-		if (!wl_list_empty(&shell->panels)) {
-			struct shell_surface *panel =
-				container_of(shell->panels.prev,
-					     struct shell_surface, link);
-			wl_list_insert(&panel->surface->link, &surface->link);
-		} else {
-			wl_list_insert(list, &surface->link);
-		}
+    if (!wl_list_empty(&shell->panels) && wl_list_empty (&shell->hidden_panels)) {
+      struct shell_surface *panel =
+        container_of(shell->panels.prev,
+            struct shell_surface, link);
+      wl_list_insert(&panel->surface->link, &surface->link);
+    } else {
+      wl_list_insert(list, &surface->link);
+    }
 	}
 
 	if (do_configure) {
@@ -1399,10 +1496,10 @@ configure(struct weston_shell *base, struct weston_surface *surface,
 		do_configure = !do_configure;
 		/* fall through */
 	case SHELL_SURFACE_FULLSCREEN:
-		center_on_output(surface, surface->fullscreen_output);
-		break;
-	default:
-		break;
+    center_on_output(surface, surface->fullscreen_output);
+    break;
+  default:
+    break;
 	}
 
 	/*  XXX: would a fullscreen surface need the same handling? */
@@ -1589,8 +1686,10 @@ shell_init(struct weston_compositor *ec)
 	shell->shell.map = map;
 	shell->shell.configure = configure;
 	shell->shell.destroy = shell_destroy;
+	shell->shell.prepare_repaint = prepare_repaint;
 
 	wl_list_init(&shell->hidden_surface_list);
+	wl_list_init(&shell->hidden_panels);
 	wl_list_init(&shell->backgrounds);
 	wl_list_init(&shell->panels);
 	wl_list_init(&shell->screensaver.surfaces);
-- 
1.7.5.4



More information about the wayland-devel mailing list