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);