summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Chalupa <mchqwerty@gmail.com>2015-05-21 15:43:43 +0200
committerMarek Chalupa <mchqwerty@gmail.com>2015-09-25 15:24:22 +0200
commit21f384b7b8b571151805674c9d384e2ad7f8b7ea (patch)
tree158bb3e312577f536f5b7bc06e85b017c5fb9056
parent95014ad2a7815282efdecc895bf14742b4b3ccb3 (diff)
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>
-rw-r--r--hw/xwayland/xwayland-output.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 28aec8e15..1546eaa01 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -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