diff options
author | Alfred E. Heggestad <aeh@db.org> | 2015-03-21 18:33:59 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2015-03-21 18:33:59 +0100 |
commit | fd7ed20a9c7dd6b47afb61eb19d88bc10165297f (patch) | |
tree | 43006668c1003a1ff18b4f66d3cfce2b83904acd | |
parent | a0a35ec8f22e612f9aec133b23ececaf8b056a16 (diff) |
x11: catching window delete
based on a patch from Doug Blewett
if the X11 window is deleted, close all resources and return ENODEV
-rw-r--r-- | modules/x11/x11.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/modules/x11/x11.c b/modules/x11/x11.c index c75b6bd..5710dca 100644 --- a/modules/x11/x11.c +++ b/modules/x11/x11.c @@ -29,6 +29,7 @@ struct vidisp_st { bool xshmat; bool internal; enum vidfmt pixfmt; + Atom XwinDeleted; }; @@ -52,34 +53,48 @@ static int error_handler(Display *d, XErrorEvent *e) } -static void destructor(void *arg) +static void close_window(struct vidisp_st *st) { - struct vidisp_st *st = arg; - - if (st->image) { - st->image->data = NULL; - XDestroyImage(st->image); - } - - if (st->gc) + if (st->gc && st->disp) { XFreeGC(st->disp, st->gc); + st->gc = NULL; + } - if (st->xshmat) + if (st->xshmat && st->disp) { XShmDetach(st->disp, &st->shm); + } - if (st->shm.shmaddr != (char *)-1) + if (st->shm.shmaddr != (char *)-1) { shmdt(st->shm.shmaddr); + st->shm.shmaddr = (char *)-1; + } if (st->shm.shmid >= 0) shmctl(st->shm.shmid, IPC_RMID, NULL); if (st->disp) { - if (st->internal && st->win) + if (st->internal && st->win) { XDestroyWindow(st->disp, st->win); + st->win = 0; + } XCloseDisplay(st->disp); + st->disp = NULL; + } +} + + +static void destructor(void *arg) +{ + struct vidisp_st *st = arg; + + if (st->image) { + st->image->data = NULL; + XDestroyImage(st->image); } + close_window(st); + mem_deref(st->vd); } @@ -96,6 +111,12 @@ static int create_window(struct vidisp_st *st, const struct vidsz *sz) XClearWindow(st->disp, st->win); XMapRaised(st->disp, st->win); + /* + * setup to catch window deletion + */ + st->XwinDeleted = XInternAtom(st->disp, "WM_DELETE_WINDOW", True); + XSetWMProtocols(st->disp, st->win, &st->XwinDeleted, 1); + return 0; } @@ -261,6 +282,33 @@ static int display(struct vidisp_st *st, const char *title, struct vidframe frame_rgb; int err = 0; + if (!st->disp) + return ENODEV; + + /* + * check for window delete - without blocking + */ + while (XPending(st->disp)) { + + XEvent e; + + XNextEvent(st->disp, &e); + + if (e.type == ClientMessage) { + if ((Atom) e.xclient.data.l[0] == st->XwinDeleted) { + + info("x11: window deleted\n"); + + /* + * we have to bail as all of the display + * pointers are bad. + */ + close_window(st); + return ENODEV; + } + } + } + if (!vidsz_cmp(&st->size, &frame->size)) { char capt[256]; |