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")
33 XDisplayWidth (Display *dpy, int screen)
35 return jwxyz_frame (XRootWindow (dpy, 0))->width;
39 XDisplayHeight (Display *dpy, int screen)
41 return jwxyz_frame (XRootWindow (dpy, 0))->height;
45 /* XLFDs use dots per inch, but Xlib uses millimeters. Go figure. */
46 static const unsigned dpi = 75;
49 XDisplayWidthMM (Display *dpy, int screen)
51 const unsigned denom = dpi * 10 / 2;
52 return (254 * XDisplayWidth (dpy, screen) + denom) / (2 * denom);
56 XDisplayHeightMM (Display *dpy, int screen)
58 const unsigned denom = dpi * 10 / 2;
59 return (254 * XDisplayHeight (dpy, screen) + denom) / (2 * denom);
64 jwxyz_validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
67 Assert (depth == 1 || depth == visual_depth(NULL, NULL),
68 "invalid depth: %d", depth);
71 Assert ((pixel == 0 || pixel == 1), "bogus mono pixel: 0x%08X", pixel);
72 else if (!alpha_allowed_p)
73 Assert (((pixel & BlackPixel(dpy,0)) == BlackPixel(dpy,0)),
74 "bogus color pixel: 0x%08X", pixel);
79 XDrawPoint (Display *dpy, Drawable d, GC gc, int x, int y)
84 return XDrawPoints (dpy, d, gc, &p, 1, CoordModeOrigin);
89 jwxyz_dumb_drawing_mode(Display *dpy, Drawable d, GC gc,
90 int x, int y, unsigned width, unsigned height)
92 XGCValues *gcv = jwxyz_gc_gcv (gc);
94 if (gcv->function == GXset || gcv->function == GXclear) {
95 // "set" and "clear" are dumb drawing modes that ignore the source
96 // bits and just draw solid rectangles.
97 unsigned depth = jwxyz_gc_depth (gc);
98 jwxyz_fill_rect (dpy, d, 0, x, y, width, height,
99 (gcv->function == GXset
100 ? (depth == 1 ? 1 : WhitePixel(dpy,0))
101 : (depth == 1 ? 0 : BlackPixel(dpy,0))));
110 XCopyArea (Display *dpy, Drawable src, Drawable dst, GC gc,
111 int src_x, int src_y,
112 unsigned int width, unsigned int height,
113 int dst_x, int dst_y)
115 Assert (gc, "no GC");
116 Assert ((width < 65535), "improbably large width");
117 Assert ((height < 65535), "improbably large height");
118 Assert ((src_x < 65535 && src_x > -65535), "improbably large src_x");
119 Assert ((src_y < 65535 && src_y > -65535), "improbably large src_y");
120 Assert ((dst_x < 65535 && dst_x > -65535), "improbably large dst_x");
121 Assert ((dst_y < 65535 && dst_y > -65535), "improbably large dst_y");
123 if (width == 0 || height == 0)
126 if (jwxyz_dumb_drawing_mode (dpy, dst, gc, dst_x, dst_y, width, height))
129 XRectangle src_frame, dst_frame; // Sizes and origins of the two drawables
130 Bool clipped = False; // Whether we did any clipping of the rects.
132 src_frame = *jwxyz_frame (src);
133 dst_frame = *jwxyz_frame (dst);
135 // Initialize src_rect...
137 src_x += src_frame.x;
138 src_y += src_frame.y;
139 if (src_y < -65535) Assert(0, "src.origin.y went nuts");
141 // Initialize dst_rect...
143 dst_x += dst_frame.x;
144 dst_y += dst_frame.y;
145 if (dst_y < -65535) Assert(0, "dst.origin.y went nuts");
147 // Use signed width and height for this...
148 int width0 = width, height0 = height;
150 // Clip rects to frames...
153 # define CLIP(THIS,THAT,VAL,SIZE) do { \
154 int off = THIS##_##VAL; \
158 THIS##_##VAL -= off; \
159 THAT##_##VAL -= off; \
161 off = (( THIS##_##VAL + SIZE##0) - \
162 (THIS##_frame.VAL + THIS##_frame.SIZE)); \
168 CLIP (dst, src, x, width);
169 CLIP (dst, src, y, height);
171 // Not actually the original dst_rect, just the one before it's clipped to
173 int orig_dst_x = dst_x;
174 int orig_dst_y = dst_y;
175 int orig_width = width0;
176 int orig_height = height0;
178 if (width0 <= 0 || height0 <= 0)
181 CLIP (src, dst, x, width);
182 CLIP (src, dst, y, height);
185 // Sort-of-special case where no pixels can be grabbed from the source,
186 // and the whole destination is filled with the background color.
187 if (width0 <= 0 || height0 <= 0) {
191 jwxyz_copy_area (dpy, src, dst, gc,
192 src_x, src_y, width0, height0, dst_x, dst_y);
195 // If either the src or dst rects did not lie within their drawables, then
196 // we have adjusted both the src and dst rects to account for the clipping;
197 // that means we need to clear to the background, so that clipped bits end
198 // up in the bg color instead of simply not being copied.
200 // This has to happen after the copy, because if it happens before, the
201 // cleared area will get grabbed if it overlaps with the source rectangle.
203 if (clipped && dst == XRootWindow (dpy,0)) {
207 Assert (orig_dst_x >= 0 &&
208 orig_dst_x + orig_width <= dst_frame.width &&
210 orig_dst_y + orig_height <= dst_frame.height,
214 XRectangle *rects_end = rects;
216 if (orig_dst_y < dst_y0) {
217 rects_end->x = orig_dst_x;
218 rects_end->y = orig_dst_y;
219 rects_end->width = orig_width;
220 rects_end->height = dst_y0 - orig_dst_y;
224 if (orig_dst_y + orig_height > dst_y0 + height0) {
225 rects_end->x = orig_dst_x;
226 rects_end->y = dst_y0 + height0;
227 rects_end->width = orig_width;
228 rects_end->height = orig_dst_y + orig_height - dst_y0 - height0;
232 if (orig_dst_x < dst_x0) {
233 rects_end->x = orig_dst_x;
234 rects_end->y = dst_y0;
235 rects_end->width = dst_x0 - orig_dst_x;
236 rects_end->height = height0;
240 if (dst_x0 + width0 < orig_dst_x + orig_width) {
241 rects_end->x = dst_x0 + width0;
242 rects_end->y = dst_y0;
243 rects_end->width = orig_dst_x + orig_width - dst_x0 - width0;
244 rects_end->height = height0;
248 XGCValues *gcv = jwxyz_gc_gcv (gc);
249 int old_function = gcv->function;
250 gcv->function = GXcopy;
251 jwxyz_fill_rects (dpy, dst, gc, rects, rects_end - rects,
252 jwxyz_window_background (dpy));
253 gcv->function = old_function;
261 XCopyPlane (Display *dpy, Drawable src, Drawable dest, GC gc,
262 int src_x, int src_y,
263 unsigned width, int height,
264 int dest_x, int dest_y, unsigned long plane)
266 Assert ((jwxyz_gc_depth (gc) == 1 || plane == 1), "hairy plane mask!");
268 // This isn't right: XCopyPlane() is supposed to map 1/0 to fg/bg,
269 // not to white/black.
270 return XCopyArea (dpy, src, dest, gc,
271 src_x, src_y, width, height, dest_x, dest_y);
276 jwxyz_fill_rect (Display *dpy, Drawable d, GC gc,
277 int x, int y, unsigned int width, unsigned int height,
280 XRectangle r = {x, y, width, height};
281 jwxyz_fill_rects (dpy, d, gc, &r, 1, pixel);
285 XFillRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
286 unsigned int width, unsigned int height)
288 jwxyz_fill_rect (dpy, d, gc, x, y, width, height,
289 jwxyz_gc_gcv (gc)->foreground);
294 XDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
295 unsigned int width, unsigned int height)
300 {x + width, y + height},
305 XDrawLines(dpy, d, gc, points, 5, CoordModeOrigin);
310 XFillRectangles (Display *dpy, Drawable d, GC gc, XRectangle *rects, int n)
312 jwxyz_fill_rects (dpy, d, gc, rects, n, jwxyz_gc_gcv (gc)->foreground);
318 XDrawArc (Display *dpy, Drawable d, GC gc, int x, int y,
319 unsigned int width, unsigned int height, int angle1, int angle2)
321 return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
326 XFillArc (Display *dpy, Drawable d, GC gc, int x, int y,
327 unsigned int width, unsigned int height, int angle1, int angle2)
329 return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
334 XDrawArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
337 for (i = 0; i < narcs; i++)
338 jwxyz_draw_arc (dpy, d, gc,
339 arcs[i].x, arcs[i].y,
340 arcs[i].width, arcs[i].height,
341 arcs[i].angle1, arcs[i].angle2,
347 XFillArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
350 for (i = 0; i < narcs; i++)
351 jwxyz_draw_arc (dpy, d, gc,
352 arcs[i].x, arcs[i].y,
353 arcs[i].width, arcs[i].height,
354 arcs[i].angle1, arcs[i].angle2,
360 jwxyz_gcv_defaults (Display *dpy, XGCValues *gcv, int depth)
362 memset (gcv, 0, sizeof(*gcv));
363 gcv->function = GXcopy;
364 gcv->foreground = (depth == 1 ? 1 : WhitePixel(dpy,0));
365 gcv->background = (depth == 1 ? 0 : BlackPixel(dpy,0));
367 gcv->cap_style = CapButt;
368 gcv->join_style = JoinMiter;
369 gcv->fill_rule = EvenOddRule;
371 gcv->alpha_allowed_p = False;
372 gcv->antialias_p = True;
377 XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *from)
379 if (! mask) return 0;
380 Assert (gc && from, "no gc");
381 if (!gc || !from) return 0;
383 XGCValues *to = jwxyz_gc_gcv (gc);
384 unsigned depth = jwxyz_gc_depth (gc);
386 if (mask & GCFunction) to->function = from->function;
387 if (mask & GCForeground) to->foreground = from->foreground;
388 if (mask & GCBackground) to->background = from->background;
389 if (mask & GCLineWidth) to->line_width = from->line_width;
390 if (mask & GCCapStyle) to->cap_style = from->cap_style;
391 if (mask & GCJoinStyle) to->join_style = from->join_style;
392 if (mask & GCFillRule) to->fill_rule = from->fill_rule;
393 if (mask & GCClipXOrigin) to->clip_x_origin = from->clip_x_origin;
394 if (mask & GCClipYOrigin) to->clip_y_origin = from->clip_y_origin;
395 if (mask & GCSubwindowMode) to->subwindow_mode = from->subwindow_mode;
397 if (mask & GCClipMask) XSetClipMask (0, gc, from->clip_mask);
398 if (mask & GCFont) XSetFont (0, gc, from->font);
400 if (mask & GCForeground)
401 jwxyz_validate_pixel (dpy, from->foreground, depth, to->alpha_allowed_p);
402 if (mask & GCBackground)
403 jwxyz_validate_pixel (dpy, from->background, depth, to->alpha_allowed_p);
405 Assert ((! (mask & (GCLineStyle |
412 GCGraphicsExposures |
416 "unimplemented gcvalues mask");
423 XGetWindowAttributes (Display *dpy, Window w, XWindowAttributes *xgwa)
425 assert_window(dpy, w);
426 memset (xgwa, 0, sizeof(*xgwa));
427 const XRectangle *frame = jwxyz_frame (w);
430 xgwa->width = frame->width;
431 xgwa->height = frame->height;
432 xgwa->depth = visual_depth (NULL, NULL);
433 xgwa->screen = DefaultScreenOfDisplay (dpy);
434 xgwa->visual = XDefaultVisualOfScreen (xgwa->screen);
439 XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
440 int *x_ret, int *y_ret,
441 unsigned int *w_ret, unsigned int *h_ret,
442 unsigned int *bw_ret, unsigned int *d_ret)
444 const XRectangle *frame = jwxyz_frame (d);
447 *w_ret = frame->width;
448 *h_ret = frame->height;
449 *d_ret = jwxyz_drawable_depth (d);
450 *root_ret = RootWindow (dpy, 0);
457 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
459 color->pixel = jwxyz_alloc_color (dpy,
468 XAllocColorCells (Display *dpy, Colormap cmap, Bool contig,
469 unsigned long *pmret, unsigned int npl,
470 unsigned long *pxret, unsigned int npx)
476 XStoreColors (Display *dpy, Colormap cmap, XColor *colors, int n)
478 Assert(0, "XStoreColors called");
483 XStoreColor (Display *dpy, Colormap cmap, XColor *c)
485 Assert(0, "XStoreColor called");
490 XFreeColors (Display *dpy, Colormap cmap, unsigned long *px, int npixels,
491 unsigned long planes)
497 XParseColor (Display *dpy, Colormap cmap, const char *spec, XColor *ret)
499 unsigned char r=0, g=0, b=0;
500 if (*spec == '#' && strlen(spec) == 7) {
501 static unsigned const char hex[] = { // yeah yeah, shoot me.
502 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,
503 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,
504 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,
505 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,
506 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,
507 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,
508 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,
509 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};
510 const unsigned char *uspec = (const unsigned char *)spec;
511 r = (hex[uspec[1]] << 4) | hex[uspec[2]];
512 g = (hex[uspec[3]] << 4) | hex[uspec[4]];
513 b = (hex[uspec[5]] << 4) | hex[uspec[6]];
514 } else if (!strcasecmp(spec,"black")) {
516 } else if (!strcasecmp(spec,"white")) {
518 } else if (!strcasecmp(spec,"red")) {
520 } else if (!strcasecmp(spec,"green")) {
522 } else if (!strcasecmp(spec,"blue")) {
524 } else if (!strcasecmp(spec,"cyan")) {
526 } else if (!strcasecmp(spec,"magenta")) {
528 } else if (!strcasecmp(spec,"yellow")) {
534 ret->red = (r << 8) | r;
535 ret->green = (g << 8) | g;
536 ret->blue = (b << 8) | b;
537 ret->flags = DoRed|DoGreen|DoBlue;
542 XAllocNamedColor (Display *dpy, Colormap cmap, char *name,
543 XColor *screen_ret, XColor *exact_ret)
545 if (! XParseColor (dpy, cmap, name, screen_ret))
547 *exact_ret = *screen_ret;
548 return XAllocColor (dpy, cmap, screen_ret);
552 XQueryColor (Display *dpy, Colormap cmap, XColor *color)
554 jwxyz_validate_pixel (dpy, color->pixel, visual_depth (NULL, NULL), False);
556 jwxyz_query_color (dpy, color->pixel, rgba);
557 color->red = (rgba[0] << 8) | rgba[0];
558 color->green = (rgba[1] << 8) | rgba[1];
559 color->blue = (rgba[2] << 8) | rgba[2];
560 color->flags = DoRed|DoGreen|DoBlue;
565 XQueryColors (Display *dpy, Colormap cmap, XColor *c, int n)
568 for (i = 0; i < n; i++)
569 XQueryColor (dpy, cmap, &c[i]);
575 ximage_getpixel_1 (XImage *ximage, int x, int y)
577 return ((ximage->data [y * ximage->bytes_per_line + (x>>3)] >> (x & 7)) & 1);
581 ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
584 ximage->data [y * ximage->bytes_per_line + (x>>3)] |= (1 << (x & 7));
586 ximage->data [y * ximage->bytes_per_line + (x>>3)] &= ~(1 << (x & 7));
592 ximage_getpixel_32 (XImage *ximage, int x, int y)
594 return ((unsigned long)
595 *((uint32_t *) ximage->data +
596 (y * (ximage->bytes_per_line >> 2)) +
601 ximage_putpixel_32 (XImage *ximage, int x, int y, unsigned long pixel)
603 *((uint32_t *) ximage->data +
604 (y * (ximage->bytes_per_line >> 2)) +
605 x) = (uint32_t) pixel;
611 XInitImage (XImage *ximage)
613 if (!ximage->bytes_per_line)
614 ximage->bytes_per_line = (ximage->depth == 1
615 ? (ximage->width + 7) / 8
616 : ximage->width * 4);
618 if (ximage->depth == 1) {
619 ximage->f.put_pixel = ximage_putpixel_1;
620 ximage->f.get_pixel = ximage_getpixel_1;
621 } else if (ximage->depth == 32 || ximage->depth == 24) {
622 ximage->f.put_pixel = ximage_putpixel_32;
623 ximage->f.get_pixel = ximage_getpixel_32;
625 Assert (0, "unknown depth");
632 XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
633 int format, int offset, char *data,
634 unsigned int width, unsigned int height,
635 int bitmap_pad, int bytes_per_line)
637 XImage *ximage = (XImage *) calloc (1, sizeof(*ximage));
638 ximage->width = width;
639 ximage->height = height;
640 ximage->format = format;
642 ximage->bitmap_unit = 8;
643 ximage->byte_order = LSBFirst;
644 ximage->bitmap_bit_order = ximage->byte_order;
645 ximage->bitmap_pad = bitmap_pad;
646 ximage->depth = depth;
647 Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
648 ximage->red_mask = (depth == 1 ? 0 : v->red_mask);
649 ximage->green_mask = (depth == 1 ? 0 : v->green_mask);
650 ximage->blue_mask = (depth == 1 ? 0 : v->blue_mask);
651 ximage->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
652 ximage->bytes_per_line = bytes_per_line;
659 XSubImage (XImage *from, int x, int y, unsigned int w, unsigned int h)
661 XImage *to = (XImage *) malloc (sizeof(*to));
662 memcpy (to, from, sizeof(*from));
665 to->bytes_per_line = 0;
668 to->data = (char *) malloc (h * to->bytes_per_line);
670 if (x >= from->width)
672 else if (x+w > from->width)
675 if (y >= from->height)
677 else if (y+h > from->height)
678 h = from->height - y;
681 for (ty = 0; ty < h; ty++)
682 for (tx = 0; tx < w; tx++)
683 XPutPixel (to, tx, ty, XGetPixel (from, x+tx, y+ty));
688 XPixmapFormatValues *
689 XListPixmapFormats (Display *dpy, int *n_ret)
691 XPixmapFormatValues *ret = calloc (2, sizeof(*ret));
692 ret[0].depth = visual_depth (NULL, NULL);
693 ret[0].bits_per_pixel = 32;
694 ret[0].scanline_pad = 8;
696 ret[1].bits_per_pixel = 1;
697 ret[1].scanline_pad = 8;
704 XGetPixel (XImage *ximage, int x, int y)
706 return ximage->f.get_pixel (ximage, x, y);
711 XPutPixel (XImage *ximage, int x, int y, unsigned long pixel)
713 return ximage->f.put_pixel (ximage, x, y, pixel);
717 XDestroyImage (XImage *ximage)
719 if (ximage->data) free (ximage->data);
726 XCreatePixmapFromBitmapData (Display *dpy, Drawable drawable,
728 unsigned int w, unsigned int h,
729 unsigned long fg, unsigned int bg,
732 Pixmap p = XCreatePixmap (dpy, drawable, w, h, depth);
733 XImage *image = XCreateImage (dpy, 0, 1, XYPixmap, 0,
734 (char *) data, w, h, 0, 0);
738 GC gc = XCreateGC (dpy, p, GCForeground|GCBackground, &gcv);
739 XPutImage (dpy, p, gc, image, 0, 0, 0, 0, w, h);
742 XDestroyImage (image);
748 XGetAtomName (Display *dpy, Atom atom)
751 return strdup ("FONT");
753 // Note that atoms (that aren't predefined) are just char *.
754 return strdup ((char *) atom);
759 XSetForeground (Display *dpy, GC gc, unsigned long fg)
761 XGCValues *gcv = jwxyz_gc_gcv (gc);
762 jwxyz_validate_pixel (dpy, fg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
763 gcv->foreground = fg;
769 XSetBackground (Display *dpy, GC gc, unsigned long bg)
771 XGCValues *gcv = jwxyz_gc_gcv (gc);
772 jwxyz_validate_pixel (dpy, bg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
773 gcv->background = bg;
778 jwxyz_XSetAlphaAllowed (Display *dpy, GC gc, Bool allowed)
780 jwxyz_gc_gcv (gc)->alpha_allowed_p = allowed;
785 jwxyz_XSetAntiAliasing (Display *dpy, GC gc, Bool antialias_p)
787 jwxyz_gc_gcv (gc)->antialias_p = antialias_p;
793 XSetLineAttributes (Display *dpy, GC gc, unsigned int line_width,
794 int line_style, int cap_style, int join_style)
796 XGCValues *gcv = jwxyz_gc_gcv (gc);
797 gcv->line_width = line_width;
798 Assert (line_style == LineSolid, "only LineSolid implemented");
799 // gc->gcv.line_style = line_style;
800 gcv->cap_style = cap_style;
801 gcv->join_style = join_style;
806 XSetGraphicsExposures (Display *dpy, GC gc, Bool which)
812 XSetFunction (Display *dpy, GC gc, int which)
814 jwxyz_gc_gcv (gc)->function = which;
819 XSetSubwindowMode (Display *dpy, GC gc, int which)
821 jwxyz_gc_gcv (gc)->subwindow_mode = which;
827 XQueryPointer (Display *dpy, Window w, Window *root_ret, Window *child_ret,
828 int *root_x_ret, int *root_y_ret,
829 int *win_x_ret, int *win_y_ret, unsigned int *mask_ret)
831 assert_window (dpy, w);
834 jwxyz_get_pos (w, &vpos, &p);
836 if (root_x_ret) *root_x_ret = p.x;
837 if (root_y_ret) *root_y_ret = p.y;
838 if (win_x_ret) *win_x_ret = p.x - vpos.x;
839 if (win_y_ret) *win_y_ret = p.y - vpos.y;
840 if (mask_ret) *mask_ret = 0; // #### poll the keyboard modifiers?
841 if (root_ret) *root_ret = 0;
842 if (child_ret) *child_ret = 0;
847 XTranslateCoordinates (Display *dpy, Window w, Window dest_w,
848 int src_x, int src_y,
849 int *dest_x_ret, int *dest_y_ret,
852 assert_window (dpy, w);
855 jwxyz_get_pos (w, &vpos, NULL);
857 // point starts out relative to top left of view
861 // get point relative to top left of screen
874 XKeycodeToKeysym (Display *dpy, KeyCode code, int index)
880 XLookupString (XKeyEvent *e, char *buf, int size, KeySym *k_ret,
883 KeySym ks = XKeycodeToKeysym (0, e->keycode, 0);
885 // Do not put non-ASCII KeySyms like XK_Shift_L and XK_Page_Up in the string.
886 if ((unsigned int) ks <= 255)
889 // Put control characters in the string. Not meta.
890 if (e->state & ControlMask) {
891 if (c >= 'a' && c <= 'z') // Upcase control.
893 if (c >= '@' && c <= '_') // Shift to control page.
895 if (c == ' ') // C-SPC is NULL.
899 if (k_ret) *k_ret = ks;
900 if (size > 0) buf[0] = c;
901 if (size > 1) buf[1] = 0;
902 return (size > 0 ? 1 : 0);
907 XFlush (Display *dpy)
909 // Just let the event loop take care of this on its own schedule.
914 XSync (Display *dpy, Bool flush)
920 // declared in utils/visual.h
922 has_writable_cells (Screen *s, Visual *v)
928 visual_depth (Screen *s, Visual *v)
934 visual_cells (Screen *s, Visual *v)
936 return (int)(v->red_mask | v->green_mask | v->blue_mask);
940 visual_class (Screen *s, Visual *v)
946 get_bits_per_pixel (Display *dpy, int depth)
948 Assert (depth == 32 || depth == 1, "unexpected depth");
953 screen_number (Screen *screen)
955 Display *dpy = DisplayOfScreen (screen);
957 for (i = 0; i < ScreenCount (dpy); i++)
958 if (ScreenOfDisplay (dpy, i) == screen)
964 // declared in utils/grabclient.h
966 use_subwindow_mode_p (Screen *screen, Window window)
971 #endif /* HAVE_JWXYZ */