The background and panel view of slave output can't exist on
layer_list and view_list, otherwise panel is mess.

When unplugging a master, one slave may become master, the slave's
background and panel view should be moved to view_list.

When plugging a master, one old master may become slave, the old
master's background and panel view should be removed from view_list

Signed-off-by: Xiong Zhang <xiong.y.zh...@intel.com>
---
 desktop-shell/shell.c | 70 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 096d618..2bc1856 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -60,6 +60,8 @@ struct shell_output {
        struct desktop_shell  *shell;
        struct weston_output  *output;
        uint32_t mark_dirty;
+       struct weston_view    *panel_view;
+       struct weston_view    *background_view;
        struct wl_listener    role_change_listener;
        struct wl_listener    destroy_listener;
        struct wl_list        link;
@@ -2066,15 +2068,16 @@ static int
 get_output_panel_height(struct desktop_shell *shell,
                        struct weston_output *output)
 {
-       struct weston_view *view;
+       struct shell_output *shell_output;
        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;
+       wl_list_for_each(shell_output, &shell->output_list, link) {
+               if (shell_output->output == output) {
+                       panel_height =
+                               shell_output->panel_view->surface->height;
                        break;
                }
        }
@@ -3654,7 +3657,8 @@ configure_static_view(struct weston_view *ev, struct 
weston_layer *layer)
 
        weston_view_set_position(ev, ev->output->x, ev->output->y);
 
-       if (wl_list_empty(&ev->layer_link)) {
+       if (wl_list_empty(&ev->layer_link) &&
+           !ev->output->is_slave) {
                wl_list_insert(&layer->view_list, &ev->layer_link);
                weston_compositor_schedule_repaint(ev->surface->compositor);
        }
@@ -3681,6 +3685,7 @@ desktop_shell_set_background(struct wl_client *client,
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
        struct weston_view *view, *next;
+       struct shell_output *shell_output;
 
        if (surface->configure) {
                wl_resource_post_error(surface_resource,
@@ -3697,6 +3702,12 @@ desktop_shell_set_background(struct wl_client *client,
        surface->configure_private = shell;
        surface->output = wl_resource_get_user_data(output_resource);
        view->output = surface->output;
+
+       wl_list_for_each(shell_output, &shell->output_list, link) {
+               if (shell_output->output == view->output)
+                       shell_output->background_view = view;
+       }
+
        desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     surface->output->width,
@@ -3724,6 +3735,7 @@ desktop_shell_set_panel(struct wl_client *client,
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
        struct weston_view *view, *next;
+       struct shell_output *shell_output;
 
        if (surface->configure) {
                wl_resource_post_error(surface_resource,
@@ -3740,6 +3752,12 @@ desktop_shell_set_panel(struct wl_client *client,
        surface->configure_private = shell;
        surface->output = wl_resource_get_user_data(output_resource);
        view->output = surface->output;
+
+       wl_list_for_each(shell_output, &shell->output_list, link) {
+               if (shell_output->output == view->output)
+                       shell_output->panel_view = view;
+       }
+
        desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     surface->output->width,
@@ -5625,15 +5643,30 @@ handle_output_role_change(struct wl_listener *listener, 
void *data)
                container_of(listener, struct shell_output,
                             role_change_listener);
        struct weston_output *output = (struct weston_output *)data;
+       struct desktop_shell *shell = shell_output->shell;
 
        /* Output change from master to slave. */
-       if (output->is_slave)
+       if (output->is_slave) {
+               wl_list_remove(&shell_output->background_view->layer_link);
+               wl_list_init(&shell_output->background_view->layer_link);
+               wl_list_remove(&shell_output->panel_view->layer_link);
+               wl_list_init(&shell_output->panel_view->layer_link);
+
                /* Mark views on this old master as dirty.
                 * But we will use new master as target output,
                 * At this point, new master doesn't have panel view
                 * and background view. So the desktop shell doesn't ready.
                 * So we delay the mark dirty work until desktop shell ready. */
                shell_output->mark_dirty = 1;
+       } else {
+               /* Output change from slave to master. */
+               wl_list_insert(&shell->background_layer.view_list,
+                              &shell_output->background_view->layer_link);
+               wl_list_insert(&shell->panel_layer.view_list,
+                              &shell_output->panel_view->layer_link);
+
+               output->repaint_scheduled = 0;
+       }
 }
 
 static void
@@ -5734,6 +5767,24 @@ shell_destroy(struct wl_listener *listener, void *data)
        struct workspace **ws;
        struct shell_output *shell_output, *tmp;
 
+       wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
+               /* Restore slave output's panel view and background view to
+                * correct layer, otherwise when client destroy slave output's
+                * panel surface and background surface, segment failure will
+                * happen in weston_view_destroy(). */
+               if (wl_list_empty(&shell_output->background_view->layer_link))
+                       wl_list_insert(&shell->background_layer.view_list,
+                               &shell_output->background_view->layer_link);
+               if (wl_list_empty(&shell_output->panel_view->layer_link))
+                       wl_list_insert(&shell->panel_layer.view_list,
+                                      &shell_output->panel_view->layer_link);
+
+               wl_list_remove(&shell_output->destroy_listener.link);
+               wl_list_remove(&shell_output->role_change_listener.link);
+               wl_list_remove(&shell_output->link);
+               free(shell_output);
+       }
+
        /* Force state to unlocked so we don't try to fade */
        shell->locked = false;
        if (shell->child.client)
@@ -5744,13 +5795,6 @@ shell_destroy(struct wl_listener *listener, void *data)
 
        input_panel_destroy(shell);
 
-       wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
-               wl_list_remove(&shell_output->destroy_listener.link);
-               wl_list_remove(&shell_output->role_change_listener.link);
-               wl_list_remove(&shell_output->link);
-               free(shell_output);
-       }
-
        wl_list_remove(&shell->output_create_listener.link);
 
        wl_array_for_each(ws, &shell->workspaces.array)
-- 
1.8.3.2

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to