1 /* xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
14 But it's a bunch of function definitions that bear some resemblance to
15 Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
16 to the things that Xlib might have done.
18 This is the version of jwxyz for Android. The version used by MacOS
19 and iOS is in jwxyz.m.
24 #ifdef HAVE_JWXYZ /* whole file */
28 /* There's only one Window for a given jwxyz_Display. */
29 #define assert_window(dpy, w) \
30 Assert (w == RootWindow (dpy, 0), "not a window")
34 Log (const char *fmt, ...)
44 XDisplayWidth (Display *dpy, int screen)
46 return jwxyz_frame (XRootWindow (dpy, 0))->width;
50 XDisplayHeight (Display *dpy, int screen)
52 return jwxyz_frame (XRootWindow (dpy, 0))->height;
56 /* XLFDs use dots per inch, but Xlib uses millimeters. Go figure. */
57 static const unsigned dpi = 75;
60 XDisplayWidthMM (Display *dpy, int screen)
62 const unsigned denom = dpi * 10 / 2;
63 return (254 * XDisplayWidth (dpy, screen) + denom) / (2 * denom);
67 XDisplayHeightMM (Display *dpy, int screen)
69 const unsigned denom = dpi * 10 / 2;
70 return (254 * XDisplayHeight (dpy, screen) + denom) / (2 * denom);
75 jwxyz_validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
78 Assert (depth == 1 || depth == visual_depth(NULL, NULL),
79 "invalid depth: %d", depth);
82 Assert ((pixel == 0 || pixel == 1), "bogus mono pixel: 0x%08X", pixel);
83 else if (!alpha_allowed_p)
84 Assert (((pixel & BlackPixel(dpy,0)) == BlackPixel(dpy,0)),
85 "bogus color pixel: 0x%08X", pixel);
90 XDrawPoint (Display *dpy, Drawable d, GC gc, int x, int y)
95 return XDrawPoints (dpy, d, gc, &p, 1, CoordModeOrigin);
100 jwxyz_dumb_drawing_mode(Display *dpy, Drawable d, GC gc,
101 int x, int y, unsigned width, unsigned height)
103 XGCValues *gcv = jwxyz_gc_gcv (gc);
105 if (gcv->function == GXset || gcv->function == GXclear) {
106 // "set" and "clear" are dumb drawing modes that ignore the source
107 // bits and just draw solid rectangles.
108 unsigned depth = jwxyz_gc_depth (gc);
109 jwxyz_fill_rect (dpy, d, 0, x, y, width, height,
110 (gcv->function == GXset
111 ? (depth == 1 ? 1 : WhitePixel(dpy,0))
112 : (depth == 1 ? 0 : BlackPixel(dpy,0))));
121 XCopyArea (Display *dpy, Drawable src, Drawable dst, GC gc,
122 int src_x, int src_y,
123 unsigned int width, unsigned int height,
124 int dst_x, int dst_y)
126 Assert (gc, "no GC");
127 Assert ((width < 65535), "improbably large width");
128 Assert ((height < 65535), "improbably large height");
129 Assert ((src_x < 65535 && src_x > -65535), "improbably large src_x");
130 Assert ((src_y < 65535 && src_y > -65535), "improbably large src_y");
131 Assert ((dst_x < 65535 && dst_x > -65535), "improbably large dst_x");
132 Assert ((dst_y < 65535 && dst_y > -65535), "improbably large dst_y");
134 if (width == 0 || height == 0)
137 if (jwxyz_dumb_drawing_mode (dpy, dst, gc, dst_x, dst_y, width, height))
140 XRectangle src_frame, dst_frame; // Sizes and origins of the two drawables
141 Bool clipped = False; // Whether we did any clipping of the rects.
143 src_frame = *jwxyz_frame (src);
144 dst_frame = *jwxyz_frame (dst);
146 // Initialize src_rect...
148 src_x += src_frame.x;
149 src_y += src_frame.y;
150 if (src_y < -65535) Assert(0, "src.origin.y went nuts");
152 // Initialize dst_rect...
154 dst_x += dst_frame.x;
155 dst_y += dst_frame.y;
156 if (dst_y < -65535) Assert(0, "dst.origin.y went nuts");
158 // Use signed width and height for this...
159 int width0 = width, height0 = height;
161 // Clip rects to frames...
164 # define CLIP(THIS,THAT,VAL,SIZE) do { \
165 int off = THIS##_##VAL; \
169 THIS##_##VAL -= off; \
170 THAT##_##VAL -= off; \
172 off = (( THIS##_##VAL + SIZE##0) - \
173 (THIS##_frame.VAL + THIS##_frame.SIZE)); \
179 CLIP (dst, src, x, width);
180 CLIP (dst, src, y, height);
182 // Not actually the original dst_rect, just the one before it's clipped to
184 int orig_dst_x = dst_x;
185 int orig_dst_y = dst_y;
186 int orig_width = width0;
187 int orig_height = height0;
189 if (width0 <= 0 || height0 <= 0)
192 CLIP (src, dst, x, width);
193 CLIP (src, dst, y, height);
196 // Sort-of-special case where no pixels can be grabbed from the source,
197 // and the whole destination is filled with the background color.
198 if (width0 <= 0 || height0 <= 0) {
202 jwxyz_copy_area (dpy, src, dst, gc,
203 src_x, src_y, width0, height0, dst_x, dst_y);
206 // If either the src or dst rects did not lie within their drawables, then
207 // we have adjusted both the src and dst rects to account for the clipping;
208 // that means we need to clear to the background, so that clipped bits end
209 // up in the bg color instead of simply not being copied.
211 // This has to happen after the copy, because if it happens before, the
212 // cleared area will get grabbed if it overlaps with the source rectangle.
214 if (clipped && dst == XRootWindow (dpy,0)) {
218 Assert (orig_dst_x >= 0 &&
219 orig_dst_x + orig_width <= dst_frame.width &&
221 orig_dst_y + orig_height <= dst_frame.height,
225 XRectangle *rects_end = rects;
227 if (orig_dst_y < dst_y0) {
228 rects_end->x = orig_dst_x;
229 rects_end->y = orig_dst_y;
230 rects_end->width = orig_width;
231 rects_end->height = dst_y0 - orig_dst_y;
235 if (orig_dst_y + orig_height > dst_y0 + height0) {
236 rects_end->x = orig_dst_x;
237 rects_end->y = dst_y0 + height0;
238 rects_end->width = orig_width;
239 rects_end->height = orig_dst_y + orig_height - dst_y0 - height0;
243 if (orig_dst_x < dst_x0) {
244 rects_end->x = orig_dst_x;
245 rects_end->y = dst_y0;
246 rects_end->width = dst_x0 - orig_dst_x;
247 rects_end->height = height0;
251 if (dst_x0 + width0 < orig_dst_x + orig_width) {
252 rects_end->x = dst_x0 + width0;
253 rects_end->y = dst_y0;
254 rects_end->width = orig_dst_x + orig_width - dst_x0 - width0;
255 rects_end->height = height0;
259 XGCValues *gcv = jwxyz_gc_gcv (gc);
260 int old_function = gcv->function;
261 gcv->function = GXcopy;
262 jwxyz_fill_rects (dpy, dst, gc, rects, rects_end - rects,
263 jwxyz_window_background (dpy));
264 gcv->function = old_function;
272 XCopyPlane (Display *dpy, Drawable src, Drawable dest, GC gc,
273 int src_x, int src_y,
274 unsigned width, int height,
275 int dest_x, int dest_y, unsigned long plane)
277 Assert ((jwxyz_gc_depth (gc) == 1 || plane == 1), "hairy plane mask!");
279 // This isn't right: XCopyPlane() is supposed to map 1/0 to fg/bg,
280 // not to white/black.
281 return XCopyArea (dpy, src, dest, gc,
282 src_x, src_y, width, height, dest_x, dest_y);
287 jwxyz_fill_rect (Display *dpy, Drawable d, GC gc,
288 int x, int y, unsigned int width, unsigned int height,
291 XRectangle r = {x, y, width, height};
292 jwxyz_fill_rects (dpy, d, gc, &r, 1, pixel);
296 XFillRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
297 unsigned int width, unsigned int height)
299 jwxyz_fill_rect (dpy, d, gc, x, y, width, height,
300 jwxyz_gc_gcv (gc)->foreground);
305 XDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
306 unsigned int width, unsigned int height)
311 {x + width, y + height},
316 XDrawLines(dpy, d, gc, points, 5, CoordModeOrigin);
321 XFillRectangles (Display *dpy, Drawable d, GC gc, XRectangle *rects, int n)
323 jwxyz_fill_rects (dpy, d, gc, rects, n, jwxyz_gc_gcv (gc)->foreground);
329 XDrawArc (Display *dpy, Drawable d, GC gc, int x, int y,
330 unsigned int width, unsigned int height, int angle1, int angle2)
332 return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
337 XFillArc (Display *dpy, Drawable d, GC gc, int x, int y,
338 unsigned int width, unsigned int height, int angle1, int angle2)
340 return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
345 XDrawArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
348 for (i = 0; i < narcs; i++)
349 jwxyz_draw_arc (dpy, d, gc,
350 arcs[i].x, arcs[i].y,
351 arcs[i].width, arcs[i].height,
352 arcs[i].angle1, arcs[i].angle2,
358 XFillArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
361 for (i = 0; i < narcs; i++)
362 jwxyz_draw_arc (dpy, d, gc,
363 arcs[i].x, arcs[i].y,
364 arcs[i].width, arcs[i].height,
365 arcs[i].angle1, arcs[i].angle2,
371 jwxyz_gcv_defaults (Display *dpy, XGCValues *gcv, int depth)
373 memset (gcv, 0, sizeof(*gcv));
374 gcv->function = GXcopy;
375 gcv->foreground = (depth == 1 ? 1 : WhitePixel(dpy,0));
376 gcv->background = (depth == 1 ? 0 : BlackPixel(dpy,0));
378 gcv->cap_style = CapButt;
379 gcv->join_style = JoinMiter;
380 gcv->fill_rule = EvenOddRule;
382 gcv->alpha_allowed_p = False;
383 gcv->antialias_p = True;
388 XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *from)
390 if (! mask) return 0;
391 Assert (gc && from, "no gc");
392 if (!gc || !from) return 0;
394 XGCValues *to = jwxyz_gc_gcv (gc);
395 unsigned depth = jwxyz_gc_depth (gc);
397 if (mask & GCFunction) to->function = from->function;
398 if (mask & GCForeground) to->foreground = from->foreground;
399 if (mask & GCBackground) to->background = from->background;
400 if (mask & GCLineWidth) to->line_width = from->line_width;
401 if (mask & GCCapStyle) to->cap_style = from->cap_style;
402 if (mask & GCJoinStyle) to->join_style = from->join_style;
403 if (mask & GCFillRule) to->fill_rule = from->fill_rule;
404 if (mask & GCClipXOrigin) to->clip_x_origin = from->clip_x_origin;
405 if (mask & GCClipYOrigin) to->clip_y_origin = from->clip_y_origin;
406 if (mask & GCSubwindowMode) to->subwindow_mode = from->subwindow_mode;
408 if (mask & GCClipMask) XSetClipMask (0, gc, from->clip_mask);
409 if (mask & GCFont) XSetFont (0, gc, from->font);
411 if (mask & GCForeground)
412 jwxyz_validate_pixel (dpy, from->foreground, depth, to->alpha_allowed_p);
413 if (mask & GCBackground)
414 jwxyz_validate_pixel (dpy, from->background, depth, to->alpha_allowed_p);
416 Assert ((! (mask & (GCLineStyle |
423 GCGraphicsExposures |
427 "unimplemented gcvalues mask");
434 XGetWindowAttributes (Display *dpy, Window w, XWindowAttributes *xgwa)
436 assert_window(dpy, w);
437 memset (xgwa, 0, sizeof(*xgwa));
438 const XRectangle *frame = jwxyz_frame (w);
441 xgwa->width = frame->width;
442 xgwa->height = frame->height;
443 xgwa->depth = visual_depth (NULL, NULL);
444 xgwa->screen = DefaultScreenOfDisplay (dpy);
445 xgwa->visual = XDefaultVisualOfScreen (xgwa->screen);
450 XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
451 int *x_ret, int *y_ret,
452 unsigned int *w_ret, unsigned int *h_ret,
453 unsigned int *bw_ret, unsigned int *d_ret)
455 const XRectangle *frame = jwxyz_frame (d);
458 *w_ret = frame->width;
459 *h_ret = frame->height;
460 *d_ret = jwxyz_drawable_depth (d);
461 *root_ret = RootWindow (dpy, 0);
468 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
470 color->pixel = jwxyz_alloc_color (dpy,
479 XAllocColorCells (Display *dpy, Colormap cmap, Bool contig,
480 unsigned long *pmret, unsigned int npl,
481 unsigned long *pxret, unsigned int npx)
487 XStoreColors (Display *dpy, Colormap cmap, XColor *colors, int n)
489 Assert(0, "XStoreColors called");
494 XStoreColor (Display *dpy, Colormap cmap, XColor *c)
496 Assert(0, "XStoreColor called");
501 XFreeColors (Display *dpy, Colormap cmap, unsigned long *px, int npixels,
502 unsigned long planes)
508 XParseColor (Display *dpy, Colormap cmap, const char *spec, XColor *ret)
510 unsigned char r=0, g=0, b=0;
511 if (*spec == '#' && strlen(spec) == 7) {
512 static unsigned const char hex[] = { // yeah yeah, shoot me.
513 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
514 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
515 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
516 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
517 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
518 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
519 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
520 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
521 const unsigned char *uspec = (const unsigned char *)spec;
522 r = (hex[uspec[1]] << 4) | hex[uspec[2]];
523 g = (hex[uspec[3]] << 4) | hex[uspec[4]];
524 b = (hex[uspec[5]] << 4) | hex[uspec[6]];
525 } else if (!strcasecmp(spec,"black")) {
527 } else if (!strcasecmp(spec,"white")) {
529 } else if (!strcasecmp(spec,"red")) {
531 } else if (!strcasecmp(spec,"green")) {
533 } else if (!strcasecmp(spec,"blue")) {
535 } else if (!strcasecmp(spec,"cyan")) {
537 } else if (!strcasecmp(spec,"magenta")) {
539 } else if (!strcasecmp(spec,"yellow")) {
545 ret->red = (r << 8) | r;
546 ret->green = (g << 8) | g;
547 ret->blue = (b << 8) | b;
548 ret->flags = DoRed|DoGreen|DoBlue;
553 XAllocNamedColor (Display *dpy, Colormap cmap, char *name,
554 XColor *screen_ret, XColor *exact_ret)
556 if (! XParseColor (dpy, cmap, name, screen_ret))
558 *exact_ret = *screen_ret;
559 return XAllocColor (dpy, cmap, screen_ret);
563 XQueryColor (Display *dpy, Colormap cmap, XColor *color)
565 jwxyz_validate_pixel (dpy, color->pixel, visual_depth (NULL, NULL), False);
567 jwxyz_query_color (dpy, color->pixel, rgba);
568 color->red = (rgba[0] << 8) | rgba[0];
569 color->green = (rgba[1] << 8) | rgba[1];
570 color->blue = (rgba[2] << 8) | rgba[2];
571 color->flags = DoRed|DoGreen|DoBlue;
576 XQueryColors (Display *dpy, Colormap cmap, XColor *c, int n)
579 for (i = 0; i < n; i++)
580 XQueryColor (dpy, cmap, &c[i]);
586 ximage_getpixel_1 (XImage *ximage, int x, int y)
588 return ((ximage->data [y * ximage->bytes_per_line + (x>>3)] >> (x & 7)) & 1);
592 ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
595 ximage->data [y * ximage->bytes_per_line + (x>>3)] |= (1 << (x & 7));
597 ximage->data [y * ximage->bytes_per_line + (x>>3)] &= ~(1 << (x & 7));
603 ximage_getpixel_32 (XImage *ximage, int x, int y)
605 return ((unsigned long)
606 *((uint32_t *) ximage->data +
607 (y * (ximage->bytes_per_line >> 2)) +
612 ximage_putpixel_32 (XImage *ximage, int x, int y, unsigned long pixel)
614 *((uint32_t *) ximage->data +
615 (y * (ximage->bytes_per_line >> 2)) +
616 x) = (uint32_t) pixel;
622 XInitImage (XImage *ximage)
624 if (!ximage->bytes_per_line)
625 ximage->bytes_per_line = (ximage->depth == 1
626 ? (ximage->width + 7) / 8
627 : ximage->width * 4);
629 if (ximage->depth == 1) {
630 ximage->f.put_pixel = ximage_putpixel_1;
631 ximage->f.get_pixel = ximage_getpixel_1;
632 } else if (ximage->depth == 32 || ximage->depth == 24) {
633 ximage->f.put_pixel = ximage_putpixel_32;
634 ximage->f.get_pixel = ximage_getpixel_32;
636 Assert (0, "unknown depth");
643 XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
644 int format, int offset, char *data,
645 unsigned int width, unsigned int height,
646 int bitmap_pad, int bytes_per_line)
648 XImage *ximage = (XImage *) calloc (1, sizeof(*ximage));
649 ximage->width = width;
650 ximage->height = height;
651 ximage->format = format;
653 ximage->bitmap_unit = 8;
654 ximage->byte_order = LSBFirst;
655 ximage->bitmap_bit_order = ximage->byte_order;
656 ximage->bitmap_pad = bitmap_pad;
657 ximage->depth = depth;
658 Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
659 ximage->red_mask = (depth == 1 ? 0 : v->red_mask);
660 ximage->green_mask = (depth == 1 ? 0 : v->green_mask);
661 ximage->blue_mask = (depth == 1 ? 0 : v->blue_mask);
662 ximage->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
663 ximage->bytes_per_line = bytes_per_line;
670 XSubImage (XImage *from, int x, int y, unsigned int w, unsigned int h)
672 XImage *to = (XImage *) malloc (sizeof(*to));
673 memcpy (to, from, sizeof(*from));
676 to->bytes_per_line = 0;
679 to->data = (char *) malloc (h * to->bytes_per_line);
681 if (x >= from->width)
683 else if (x+w > from->width)
686 if (y >= from->height)
688 else if (y+h > from->height)
689 h = from->height - y;
692 for (ty = 0; ty < h; ty++)
693 for (tx = 0; tx < w; tx++)
694 XPutPixel (to, tx, ty, XGetPixel (from, x+tx, y+ty));
699 XPixmapFormatValues *
700 XListPixmapFormats (Display *dpy, int *n_ret)
702 XPixmapFormatValues *ret = calloc (2, sizeof(*ret));
703 ret[0].depth = visual_depth (NULL, NULL);
704 ret[0].bits_per_pixel = 32;
705 ret[0].scanline_pad = 8;
707 ret[1].bits_per_pixel = 1;
708 ret[1].scanline_pad = 8;
715 XGetPixel (XImage *ximage, int x, int y)
717 return ximage->f.get_pixel (ximage, x, y);
722 XPutPixel (XImage *ximage, int x, int y, unsigned long pixel)
724 return ximage->f.put_pixel (ximage, x, y, pixel);
728 XDestroyImage (XImage *ximage)
730 if (ximage->data) free (ximage->data);
737 XCreatePixmapFromBitmapData (Display *dpy, Drawable drawable,
739 unsigned int w, unsigned int h,
740 unsigned long fg, unsigned int bg,
743 Pixmap p = XCreatePixmap (dpy, drawable, w, h, depth);
744 XImage *image = XCreateImage (dpy, 0, 1, XYPixmap, 0,
745 (char *) data, w, h, 0, 0);
749 GC gc = XCreateGC (dpy, p, GCForeground|GCBackground, &gcv);
750 XPutImage (dpy, p, gc, image, 0, 0, 0, 0, w, h);
753 XDestroyImage (image);
759 XGetAtomName (Display *dpy, Atom atom)
762 return strdup ("FONT");
764 // Note that atoms (that aren't predefined) are just char *.
765 return strdup ((char *) atom);
770 XSetForeground (Display *dpy, GC gc, unsigned long fg)
772 XGCValues *gcv = jwxyz_gc_gcv (gc);
773 jwxyz_validate_pixel (dpy, fg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
774 gcv->foreground = fg;
780 XSetBackground (Display *dpy, GC gc, unsigned long bg)
782 XGCValues *gcv = jwxyz_gc_gcv (gc);
783 jwxyz_validate_pixel (dpy, bg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
784 gcv->background = bg;
789 jwxyz_XSetAlphaAllowed (Display *dpy, GC gc, Bool allowed)
791 jwxyz_gc_gcv (gc)->alpha_allowed_p = allowed;
796 jwxyz_XSetAntiAliasing (Display *dpy, GC gc, Bool antialias_p)
798 jwxyz_gc_gcv (gc)->antialias_p = antialias_p;
804 XSetLineAttributes (Display *dpy, GC gc, unsigned int line_width,
805 int line_style, int cap_style, int join_style)
807 XGCValues *gcv = jwxyz_gc_gcv (gc);
808 gcv->line_width = line_width;
809 Assert (line_style == LineSolid, "only LineSolid implemented");
810 // gc->gcv.line_style = line_style;
811 gcv->cap_style = cap_style;
812 gcv->join_style = join_style;
817 XSetGraphicsExposures (Display *dpy, GC gc, Bool which)
823 XSetFunction (Display *dpy, GC gc, int which)
825 jwxyz_gc_gcv (gc)->function = which;
830 XSetSubwindowMode (Display *dpy, GC gc, int which)
832 jwxyz_gc_gcv (gc)->subwindow_mode = which;
838 XQueryPointer (Display *dpy, Window w, Window *root_ret, Window *child_ret,
839 int *root_x_ret, int *root_y_ret,
840 int *win_x_ret, int *win_y_ret, unsigned int *mask_ret)
842 assert_window (dpy, w);
845 jwxyz_get_pos (w, &vpos, &p);
847 if (root_x_ret) *root_x_ret = p.x;
848 if (root_y_ret) *root_y_ret = p.y;
849 if (win_x_ret) *win_x_ret = p.x - vpos.x;
850 if (win_y_ret) *win_y_ret = p.y - vpos.y;
851 if (mask_ret) *mask_ret = 0; // #### poll the keyboard modifiers?
852 if (root_ret) *root_ret = 0;
853 if (child_ret) *child_ret = 0;
858 XTranslateCoordinates (Display *dpy, Window w, Window dest_w,
859 int src_x, int src_y,
860 int *dest_x_ret, int *dest_y_ret,
863 assert_window (dpy, w);
866 jwxyz_get_pos (w, &vpos, NULL);
868 // point starts out relative to top left of view
872 // get point relative to top left of screen
885 XKeycodeToKeysym (Display *dpy, KeyCode code, int index)
891 XLookupString (XKeyEvent *e, char *buf, int size, KeySym *k_ret,
894 KeySym ks = XKeycodeToKeysym (0, e->keycode, 0);
896 // Do not put non-ASCII KeySyms like XK_Shift_L and XK_Page_Up in the string.
897 if ((unsigned int) ks <= 255)
900 // Put control characters in the string. Not meta.
901 if (e->state & ControlMask) {
902 if (c >= 'a' && c <= 'z') // Upcase control.
904 if (c >= '@' && c <= '_') // Shift to control page.
906 if (c == ' ') // C-SPC is NULL.
910 if (k_ret) *k_ret = ks;
911 if (size > 0) buf[0] = c;
912 if (size > 1) buf[1] = 0;
913 return (size > 0 ? 1 : 0);
918 XFlush (Display *dpy)
920 // Just let the event loop take care of this on its own schedule.
925 XSync (Display *dpy, Bool flush)
931 // declared in utils/visual.h
933 has_writable_cells (Screen *s, Visual *v)
939 visual_depth (Screen *s, Visual *v)
945 visual_cells (Screen *s, Visual *v)
947 return (int)(v->red_mask | v->green_mask | v->blue_mask);
951 visual_class (Screen *s, Visual *v)
957 get_bits_per_pixel (Display *dpy, int depth)
959 Assert (depth == 32 || depth == 1, "unexpected depth");
964 screen_number (Screen *screen)
966 Display *dpy = DisplayOfScreen (screen);
968 for (i = 0; i < ScreenCount (dpy); i++)
969 if (ScreenOfDisplay (dpy, i) == screen)
975 // declared in utils/grabclient.h
977 use_subwindow_mode_p (Screen *screen, Window window)
982 #endif /* HAVE_JWXYZ */