[PATCH weston] xwm: Fix icon surface ownership

Emmanuel Gil Peyrot linkmauve at linkmauve.fr
Wed Jan 24 22:29:53 UTC 2018


The cairo surface used for the icon must be completely given to the
frame as soon as said frame has been created.  To prevent both the
window and the frame from sharing ownership of the icon, we set
window->icon_surface back to NULL right after creating or changing the
frame, only keeping it there when no frame has been created yet.

Fixes https://lists.freedesktop.org/archives/wayland-devel/2018-January/036655.html
Reported-by: Derek Foreman <derekf at osg.samsung.com>
Tested-by: Derek Foreman <derekf at osg.samsung.com>
Signed-off-by: Emmanuel Gil Peyrot <linkmauve at linkmauve.fr>
---
 shared/cairo-util.h       |  4 ++++
 shared/frame.c            | 14 ++++++++++++++
 xwayland/window-manager.c | 16 ++++++++++------
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/shared/cairo-util.h b/shared/cairo-util.h
index bab48083..6fd11f6b 100644
--- a/shared/cairo-util.h
+++ b/shared/cairo-util.h
@@ -135,6 +135,10 @@ frame_destroy(struct frame *frame);
 int
 frame_set_title(struct frame *frame, const char *title);
 
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_set_icon(struct frame *frame, cairo_surface_t *icon);
+
 /* May set FRAME_STATUS_REPAINT */
 void
 frame_set_flag(struct frame *frame, enum frame_flag flag);
diff --git a/shared/frame.c b/shared/frame.c
index dc7ff85c..3a7d9199 100644
--- a/shared/frame.c
+++ b/shared/frame.c
@@ -423,6 +423,20 @@ frame_set_title(struct frame *frame, const char *title)
 	return 0;
 }
 
+void
+frame_set_icon(struct frame *frame, cairo_surface_t *icon)
+{
+	struct frame_button *button;
+	wl_list_for_each(button, &frame->buttons, link) {
+		if (button->status_effect != FRAME_STATUS_MENU)
+			continue;
+		if (button->icon)
+			cairo_surface_destroy(button->icon);
+		button->icon = icon;
+		frame->status |= FRAME_STATUS_REPAINT;
+	}
+}
+
 void
 frame_set_flag(struct frame *frame, enum frame_flag flag)
 {
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index ac44a29a..c307e199 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -139,7 +139,7 @@ struct weston_wm_window {
 	struct frame *frame;
 	cairo_surface_t *cairo_surface;
 	int icon;
-	cairo_surface_t *icon_surface;
+	cairo_surface_t *icon_surface; /* A temporary slot, to be passed to frame on creation */
 	uint32_t surface_id;
 	struct weston_surface *surface;
 	struct weston_desktop_xwayland_surface *shsurf;
@@ -994,6 +994,7 @@ weston_wm_window_create_frame(struct weston_wm_window *window)
 	                             window->width, window->height,
 	                             buttons, window->name,
 	                             window->icon_surface);
+	window->icon_surface = NULL;
 	frame_resize_inside(window->frame, window->width, window->height);
 
 	weston_wm_window_get_frame_size(window, &width, &height);
@@ -1392,10 +1393,10 @@ weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
 		return;
 	}
 
-	if (window->icon_surface)
-		cairo_surface_destroy(window->icon_surface);
-
-	window->icon_surface = new_surface;
+	if (window->frame)
+		frame_set_icon(window->frame, new_surface);
+	else /* We don’t have a frame yet */
+		window->icon_surface = new_surface;
 }
 
 static void
@@ -1422,7 +1423,10 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even
 		if (property_notify->state != XCB_PROPERTY_DELETE) {
 			weston_wm_handle_icon(wm, window);
 		} else {
-			cairo_surface_destroy(window->icon_surface);
+			if (window->frame)
+				frame_set_icon(window->frame, NULL);
+			if (window->icon_surface)
+				cairo_surface_destroy(window->icon_surface);
 			window->icon_surface = NULL;
 		}
 		weston_wm_window_schedule_repaint(window);
-- 
2.16.1



More information about the wayland-devel mailing list