xwayland: do not add output into output_list multiple times

output.done event can be sent even on some property change, not only
when announcing the output. Therefore we must check if we already have it
otherwise we may corrupt the list by adding it multiple times.

This fixes bug when xwayland looped indefinitely in output.done handler
and that can be reproduced following these steps (under X without
multi-monitor setup):
 1) run weston --output-count=2
 2) run xterm, move it so that half is on one output
    and half on the other
 3) close second output, try run weston-terminal

weston sends updated outputs which trigger this bug.

v2. factor out common code into function
    move expecting_events into right branch

Signed-off-by: Marek Chalupa <mchqwerty@gmail.com>
This commit is contained in:
Marek Chalupa 2015-05-21 15:43:43 +02:00
parent 95014ad2a7
commit 21f384b7b8

View File

@ -113,29 +113,47 @@ output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
}
static inline void
output_get_new_size(struct xwl_output *xwl_output,
int *height, int *width)
{
if (*width < xwl_output->x + xwl_output->width)
*width = xwl_output->x + xwl_output->width;
if (*height < xwl_output->y + xwl_output->height)
*height = xwl_output->y + xwl_output->height;
}
static void
output_handle_done(void *data, struct wl_output *wl_output)
{
struct xwl_output *xwl_output = data;
struct xwl_output *it, *xwl_output = data;
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
int width, height;
int width = 0, height = 0, has_this_output = 0;
xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
/* output done event is sent even when some property
* of output is changed. That means that we may already
* have this output. If it is true, we must not add it
* into the output_list otherwise we'll corrupt it */
if (it == xwl_output)
has_this_output = 1;
width = 0;
height = 0;
xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
if (width < xwl_output->x + xwl_output->width)
width = xwl_output->x + xwl_output->width;
if (height < xwl_output->y + xwl_output->height)
height = xwl_output->y + xwl_output->height;
output_get_new_size(it, &height, &width);
}
if (!has_this_output) {
xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
/* we did not check this output for new screen size, do it now */
output_get_new_size(xwl_output, &height, &width);
--xwl_screen->expecting_event;
}
xwl_screen->width = width;
xwl_screen->height = height;
RRScreenSizeNotify(xwl_screen->screen);
xwl_screen->expecting_event--;
}
static void