summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2015-03-21 18:33:59 +0100
committerAlfred E. Heggestad <aeh@db.org>2015-03-21 18:33:59 +0100
commitfd7ed20a9c7dd6b47afb61eb19d88bc10165297f (patch)
tree43006668c1003a1ff18b4f66d3cfce2b83904acd
parenta0a35ec8f22e612f9aec133b23ececaf8b056a16 (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.c72
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];