- /* create XImage */
- pdp->ximage = XCreateImage(dpy,
- pdp->visinfo->visual,
- pdp->visinfo->depth,
- ZPixmap, 0, /* format, offset */
- NULL, /* data */
- 0, 0, /* width, height */
- 32, /* bitmap_pad */
- 0); /* bytes_per_line */
+ return True;
+}
+
+static int xshm_error = 0;
+static int xshm_opcode = -1;
+
+/**
+ * Catches potential Xlib errors.
+ */
+static int
+handle_xerror(Display *dpy, XErrorEvent *event)
+{
+ (void) dpy;
+
+ assert(xshm_opcode != -1);
+ if (event->request_code != xshm_opcode ||
+ event->minor_code != X_ShmAttach)
+ return 0;
+
+ xshm_error = 1;
+ return 0;
+}
+
+static Bool
+XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
+{
+ if (pdp->ximage) {
+ XDestroyImage(pdp->ximage);
+ pdp->ximage = NULL;
+ }
+
+ if (!xshm_error && shmid >= 0) {
+ pdp->shminfo.shmid = shmid;
+ pdp->ximage = XShmCreateImage(dpy,
+ pdp->visinfo->visual,
+ pdp->visinfo->depth,
+ ZPixmap, /* format */
+ NULL, /* data */
+ &pdp->shminfo, /* shminfo */
+ 0, 0); /* width, height */
+ if (pdp->ximage != NULL) {
+ int (*old_handler)(Display *, XErrorEvent *);
+
+ /* dispatch pending errors */
+ XSync(dpy, False);
+
+ old_handler = XSetErrorHandler(handle_xerror);
+ /* This may trigger the X protocol error we're ready to catch: */
+ XShmAttach(dpy, &pdp->shminfo);
+ XSync(dpy, False);
+
+ if (xshm_error) {
+ /* we are on a remote display, this error is normal, don't print it */
+ XDestroyImage(pdp->ximage);
+ pdp->ximage = NULL;
+ }
+
+ (void) XSetErrorHandler(old_handler);
+ }
+ }
+
+ if (pdp->ximage == NULL) {
+ pdp->shminfo.shmid = -1;
+ pdp->ximage = XCreateImage(dpy,
+ pdp->visinfo->visual,
+ pdp->visinfo->depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* width, height */
+ 32, /* bitmap_pad */
+ 0); /* bytes_per_line */
+ }