win: don't ignore SHADOW_STALE flag on unmapped windows

Previously all image stale flags are ignored when processing an unmapped
window. If a window gains a shadow during its fading out transition, the
shadow flag will be set, but shadow won't actually be generated, causing
a NULL pointer dereference during render.

Fixes #239

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-09-23 19:44:35 +01:00
parent c85c9ef1cc
commit 33a106e254
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
1 changed files with 24 additions and 10 deletions

View File

@ -324,6 +324,11 @@ void win_release_images(struct backend_base *backend, struct managed_win *w) {
} }
void win_process_flags(session_t *ps, struct managed_win *w) { void win_process_flags(session_t *ps, struct managed_win *w) {
// Make sure all pending window updates are processed before this. Making this
// assumption simplifies some checks (e.g. whether window is mapped)
auto iw = (struct managed_win_internal *)w;
assert(iw->pending_updates == 0);
if (!w->flags || (w->flags & WIN_FLAGS_IMAGE_ERROR) != 0) { if (!w->flags || (w->flags & WIN_FLAGS_IMAGE_ERROR) != 0) {
return; return;
} }
@ -331,19 +336,25 @@ void win_process_flags(session_t *ps, struct managed_win *w) {
// Not a loop // Not a loop
while ((w->flags & WIN_FLAGS_IMAGES_STALE) != 0) { while ((w->flags & WIN_FLAGS_IMAGES_STALE) != 0) {
// Image needs to be updated, update it. // Image needs to be updated, update it.
if (w->state == WSTATE_UNMAPPING || w->state == WSTATE_DESTROYING || if (!ps->backend_data) {
!ps->backend_data) { // We are using legacy backend, nothing to do here.
// Window is already gone, or we are using the legacy backend
// we cannot rebind image
break; break;
} }
// Must release images first, otherwise breaks NVIDIA driver
if ((w->flags & WIN_FLAGS_PIXMAP_STALE) != 0) { if ((w->flags & WIN_FLAGS_PIXMAP_STALE) != 0) {
if ((w->flags & WIN_FLAGS_PIXMAP_NONE) == 0) { // Check to make sure the window is still mapped, otherwise we
win_release_pixmap(ps->backend_data, w); // won't be able to rebind pixmap after releasing it, yet we might
// still need the pixmap for rendering.
if (w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING) {
if ((w->flags & WIN_FLAGS_PIXMAP_NONE) == 0) {
// Must release images first, otherwise breaks
// NVIDIA driver
win_release_pixmap(ps->backend_data, w);
}
win_bind_pixmap(ps->backend_data, w);
} else {
assert(w->win_image);
} }
win_bind_pixmap(ps->backend_data, w);
} }
if ((w->flags & WIN_FLAGS_SHADOW_STALE) != 0) { if ((w->flags & WIN_FLAGS_SHADOW_STALE) != 0) {
@ -360,9 +371,12 @@ void win_process_flags(session_t *ps, struct managed_win *w) {
} }
} }
// Flags are cleared here, loop always run only once // break here, loop always run only once
w->flags &= ~WIN_FLAGS_IMAGES_STALE; break;
} }
// Clear stale image flags
w->flags &= ~WIN_FLAGS_IMAGES_STALE;
} }
/** /**