[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