From 44fc1be913ab2faad0414f50e51d58310302d065 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 24 Jan 2018 23:29:53 +0100 Subject: [PATCH] xwm: Fix icon surface ownership 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 Tested-by: Derek Foreman Signed-off-by: Emmanuel Gil Peyrot --- 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 acac2ca8..e8a5cad6 100644 --- a/shared/frame.c +++ b/shared/frame.c @@ -448,6 +448,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);