On 12/03/2013 05:25 AM, Xiong Zhang wrote:
if the unplugged output is the first default output, the second
output will move to the first working as default output. Mark
the surface on unplaugged output as dirty, so on the next output
repaint, these views will reassign output and get the right
output.
when we move output, the views on moved output should be moved also.
Because of the page flip intervention, the weston_output_destroy()
maybe asynchronous with update_outputs(). So we should change
moving following outputs to output_destroy handler.

Building up on the idea on my previous email - were we would have an output_destroyed() callback for the view which receives the new output the view should be in - I think we could avoid having different logic for the case where the first output is removed. Instead, we could move the outputs position before calling the callback, so when it calculates the new position for the view that would be final.

It sounds like we still need to delay weston_output_move() in the drm backend, so that would be split into a separate patch.


Ander


Signed-off-by: Xiong Zhang <[email protected]>
---
  src/compositor-drm.c |  8 -----
  src/compositor.c     | 18 +++++++++++
  src/shell.c          | 88 ++++++++++++++++++++++++++++++++++++----------------
  3 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index c34fc1c..158a05f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -2223,7 +2223,6 @@ update_outputs(struct drm_compositor *ec, struct 
udev_device *drm_device)
        drmModeRes *resources;
        struct drm_output *output, *next;
        int x = 0, y = 0;
-       int x_offset = 0, y_offset = 0;
        uint32_t connected = 0, disconnects = 0;
        int i;

@@ -2273,17 +2272,10 @@ update_outputs(struct drm_compositor *ec, struct 
udev_device *drm_device)
        if (disconnects) {
                wl_list_for_each_safe(output, next, &ec->base.output_list,
                                      base.link) {
-                       if (x_offset != 0 || y_offset != 0) {
-                               weston_output_move(&output->base,
-                                                output->base.x - x_offset,
-                                                output->base.y - y_offset);
-                       }
-
                        if (disconnects & (1 << output->connector_id)) {
                                disconnects &= ~(1 << output->connector_id);
                                weston_log("connector %d disconnected\n",
                                       output->connector_id);
-                               x_offset += output->base.width;
                                drm_output_destroy(&output->base);
                        }
                }
diff --git a/src/compositor.c b/src/compositor.c
index 32e72b1..246b02b 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3128,6 +3128,13 @@ weston_output_transform_scale_init(struct weston_output 
*output, uint32_t transf
  WL_EXPORT void
  weston_output_move(struct weston_output *output, int x, int y)
  {
+       struct weston_view *view;
+       struct weston_layer *layer;
+       int offset_x, offset_y;
+
+       offset_x = x - output->x;
+       offset_y = y - output->y;
+
        output->x = x;
        output->y = y;

@@ -3135,6 +3142,17 @@ weston_output_move(struct weston_output *output, int x, 
int y)
        pixman_region32_init_rect(&output->region, x, y,
                                  output->width,
                                  output->height);
+       output->dirty = 1;
+
+       wl_list_for_each(layer, &output->compositor->layer_list, link) {
+               wl_list_for_each(view, &layer->view_list, layer_link) {
+                       if (view->output == output &&
+                               view->geometry.parent == NULL)
+                               weston_view_set_position(view,
+                                               view->geometry.x + offset_x,
+                                               view->geometry.y + offset_y);
+               }
+       }
  }

  WL_EXPORT void
diff --git a/src/shell.c b/src/shell.c
index 16d22f1..3cf87fd 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -6084,11 +6084,17 @@ clamp_coordinate(struct weston_output *target_output,
        return result;
  }

+/* if destroyed output is default output, marking views on this output */
+/* are dirty, so the next repaint will assign a new output to these views */
+/* if destroyed output isn't default output, move views on this output */
+/* to default output */
  static void
  handle_view_on_destroyed_output(struct weston_view *view,
-                                       struct weston_output *target_output)
+                                       struct weston_output *target_output,
+                                       unsigned int move)
  {
        float new_x, new_y, original_x, original_y;
+       int result;

        /* the child window's view->geometry is a relative coordinate to */
        /* parent view, no need to move child_view */
@@ -6098,17 +6104,23 @@ handle_view_on_destroyed_output(struct weston_view 
*view,
        original_x = view->geometry.x;
        original_y = view->geometry.y;

-       clamp_coordinate(target_output, view->output,
-                       &original_x, &original_y);
+       result = clamp_coordinate(target_output, view->output,
+                               &original_x, &original_y);

-       new_x = target_output->x + original_x - view->output->x;
-       new_y = target_output->y + original_y - view->output->y;
-       weston_view_set_position(view, new_x, new_y);
+       if (move) {
+               new_x = target_output->x + original_x - view->output->x;
+               new_y = target_output->y + original_y - view->output->y;
+               weston_view_set_position(view, new_x, new_y);
+       } else if (result)
+               weston_view_set_position(view, original_x, original_y);
+       else
+               weston_view_geometry_dirty(view);
  }

  static void
  normal_view_on_destroyed_output(struct shell_output *shell_output,
-                                               struct weston_output 
*target_output)
+                                               struct weston_output 
*target_output,
+                                               unsigned int move)
  {
        struct weston_output *del_output = shell_output->output;
        struct desktop_shell *shell = shell_output->shell;
@@ -6142,7 +6154,8 @@ normal_view_on_destroyed_output(struct shell_output 
*shell_output,

  static void
  full_screen_view_on_destroyed_output(struct shell_output *shell_output,
-                                               struct weston_output 
*target_output)
+                                               struct weston_output 
*target_output,
+                                               unsigned int move)
  {
        struct weston_output *del_output = shell_output->output;
        struct desktop_shell *shell = shell_output->shell;
@@ -6155,7 +6168,7 @@ full_screen_view_on_destroyed_output(struct shell_output 
*shell_output,
        wl_list_for_each(view, &shell->fullscreen_layer.view_list, layer_link) {
                /* fullscreen.black_view followed fullscreen.view */
                if (shsurf && shsurf->fullscreen.black_view == view) {
-                       handle_view_on_destroyed_output(view, target_output);
+                       handle_view_on_destroyed_output(view, target_output, 
move);
                        weston_view_configure(view, target_output->x, 
target_output->y,
                                                                
target_output->width, target_output->height);
                        pixman_region32_fini(&view->surface->opaque);
@@ -6168,7 +6181,7 @@ full_screen_view_on_destroyed_output(struct shell_output 
*shell_output,
                }
                shsurf = get_shell_surface(view->surface);
                if (shsurf->fullscreen_output == del_output) {
-                       handle_view_on_destroyed_output(view, target_output);
+                       handle_view_on_destroyed_output(view, target_output, 
move);
                        shsurf->type = SHELL_SURFACE_NONE;
                        set_fullscreen(shsurf,
                                                   shsurf->fullscreen.type,
@@ -6180,7 +6193,8 @@ full_screen_view_on_destroyed_output(struct shell_output 
*shell_output,

  static void
  pointer_on_destroyed_output(struct shell_output *shell_output,
-                                       struct weston_output *target_output)
+                                       struct weston_output *target_output,
+                                       unsigned int move)
  {
        struct weston_output *del_output = shell_output->output;
        struct weston_compositor *wc = del_output->compositor;
@@ -6205,12 +6219,15 @@ pointer_on_destroyed_output(struct shell_output 
*shell_output,
                        pointer->x = wl_fixed_from_double(pointer_x);
                        pointer->y = wl_fixed_from_double(pointer_y);
                }
-               dx = wl_fixed_from_int(target_output->x - del_output->x);
-               dy = wl_fixed_from_int(target_output->y - del_output->y);
-               pointer->x += dx;
-               pointer->y += dy;
+               if (move) {
+                       dx = wl_fixed_from_int(target_output->x - 
del_output->x);
+                       dy = wl_fixed_from_int(target_output->y - 
del_output->y);
+                       pointer->x += dx;
+                       pointer->y += dy;
+               }
                if (pointer->sprite)
-                       handle_view_on_destroyed_output(pointer->sprite, 
target_output);
+                       handle_view_on_destroyed_output(pointer->sprite,
+                                                       target_output, move);
                pointer->grab->interface->focus(pointer->grab);
                resource_list = &pointer->focus_resource_list;
                wl_resource_for_each(resource, resource_list) {
@@ -6231,22 +6248,41 @@ handle_output_destroy(struct wl_listener *listener, 
void *data)
                container_of(listener, struct shell_output, destroy_listener);
        struct weston_output *output = (struct weston_output *)data;
        struct weston_compositor *wc = output->compositor;
-       struct weston_output *default_output, *target_output = NULL;
+       struct weston_output *default_output, *target_output = NULL, *tmp;
+       unsigned int move;
+       int x_offset = 0, y_offset = 0;

        default_output = get_default_output(wc);
-       /* if default output is the only output in output_list, or destroyed
-          output is default output, return*/
-       if ((default_output->link.prev == default_output->link.next) ||
-               (default_output == output))
+       /* if default output is the only output in output_list, return*/
+       if (default_output->link.prev == default_output->link.next)
                goto exit_handler;

-       target_output = default_output;
+       if (default_output != output) {
+               target_output = default_output;
+               move = 1;
+       } else {
+               target_output = container_of(output->link.next,
+                                       struct weston_output, link);
+               move = 0;
+       }
+
+       normal_view_on_destroyed_output(shell_output, target_output, move);
+       full_screen_view_on_destroyed_output(shell_output, target_output, move);
+       pointer_on_destroyed_output(shell_output, target_output, move);

-       normal_view_on_destroyed_output(shell_output, target_output);
-       full_screen_view_on_destroyed_output(shell_output, target_output);
-       pointer_on_destroyed_output(shell_output, target_output);
+       if (move)
+               weston_output_schedule_repaint(target_output);

-       weston_output_schedule_repaint(target_output);
+       /* move the following output */
+       wl_list_for_each(tmp, &wc->output_list, link) {
+               if (x_offset != 0 || y_offset != 0) {
+                       weston_output_move(tmp,
+                               tmp->x - x_offset, tmp->y - y_offset);
+                       weston_output_damage(tmp);
+               }
+               if (tmp == output)
+                       x_offset = output->width;
+       }

  exit_handler:
        wl_list_remove(&shell_output->destroy_listener.link);


_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to