1 /* testx11.c, Copyright (c) 2015-2016 Dave Odell <dmo2118@gmail.com>
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
11 * This is a test for X11 drawing primitives for the non-X11 ports of
12 * XScreenSaver. It shouldn't normally be installed with the other screenhacks.
14 * Almost no error checking in here. This is intentional.
17 #include "screenhack.h"
18 #include "glx/rotator.h"
24 # define jwxyz_XSetAntiAliasing(dpy, gc, p)
27 #ifndef jwxyz_assert_display
28 # define jwxyz_assert_display(dpy)
31 #define countof(a) (sizeof(a) / sizeof(*(a)))
33 static const char *testx11_defaults [] = {
34 ".background: #a020f0", /* purple */
37 "*ignoreRotation: True",
42 static XrmOptionDescRec testx11_options [] = {
61 XWindowAttributes xgwa;
69 /* Pixels from XAllocPixel. */
70 unsigned long rgb[3], salmon, magenta, gray50, dark_slate_gray1, cyan;
76 /* These X11 objects aren't altered after creation, except for:
77 - copy_gc and thick_line_gc get anti-aliasing toggled.
78 - xor_gc's clip mask (if it's turned on) always covers the entire window.
80 GC copy_gc, mono_gc, thick_line_gc, xor_gc, graph_gc;
81 Pixmap clip_mask_tile;
83 /* Backdrop stuff, naturally. */
85 Pixmap backdrop_tile, backdrop_scratch;
86 XColor backdrop_colors[64];
89 /* The following items may be modified by various test modes. */
90 Pixmap primitives_mini_pix;
105 fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
110 check_no_mem (void *ptr)
118 alloc_color (struct testx11 *st,
119 unsigned short r, unsigned short g, unsigned short b)
125 color.flags = DoRed | DoGreen | DoBlue;
126 XAllocColor (st->dpy, st->xgwa.colormap, &color);
131 create_backbuffer(struct testx11 *st)
134 st->backbuffer = XCreatePixmap (st->dpy, st->win,
135 st->xgwa.width, st->xgwa.height,
141 toggle_antialiasing (struct testx11 *st)
143 st->anti_alias_p ^= True;
144 jwxyz_XSetAntiAliasing (st->dpy, st->copy_gc, st->anti_alias_p);
145 jwxyz_XSetAntiAliasing (st->dpy, st->thick_line_gc, st->anti_alias_p);
151 primitives_mini_rect(struct testx11 *st, Drawable t, int x, int y)
153 XFillRectangle(st->dpy, t, st->copy_gc, x, y, 2, 2);
157 images_copy_test (Display *dpy, Drawable src, Drawable dst, GC gc,
158 int src_y, int dst_x, int dst_y, unsigned long cells)
160 XCopyArea(dpy, src, dst, gc, 0, src_y, 3, 2, dst_x, dst_y);
163 XImage *image = XGetImage(dpy, src, 0, src_y, 3, 2, cells, ZPixmap);
164 XPutImage(dpy, dst, gc, image, 0, 0, dst_x, dst_y + 2, 3, 2);
165 XDestroyImage(image);
170 images_pattern (struct testx11 *st, Drawable d, unsigned y)
173 for (x = 0; x != 3; ++x) {
174 XSetForeground(st->dpy, st->images_point_gc, st->rgb[x]);
175 XDrawPoint(st->dpy, d, st->images_point_gc, x, y);
176 XSetForeground(st->dpy, st->images_point_gc, st->rgb[2 - x]);
177 XFillRectangle(st->dpy, d, st->images_point_gc, x, y + 1, 1, 1);
180 images_copy_test (st->dpy, d, d, st->images_point_gc, y, 0, y + 2,
181 st->rgb[0] | st->rgb[1] | st->rgb[2]);
184 static const unsigned tile_size = 16;
185 static const unsigned tile_count = 8;
187 static const unsigned preserve_size = 128;
190 make_clip_mask (struct testx11 *st)
192 /* Activate this for extra Fun! */
194 /* This is kind of slow, but that's OK, because this only happens on int
197 unsigned w = st->xgwa.width, h = st->xgwa.height;
199 Pixmap mask = XCreatePixmap (st->dpy, st->clip_mask_tile, w, h, 1);
201 for (y = 0; y < h; y += 8) {
202 for (x = 0; x < w; x += 8) {
203 XCopyArea (st->dpy, st->clip_mask_tile, mask, st->mono_gc,
208 XSetClipMask (st->dpy, st->xor_gc, mask);
209 XFreePixmap (st->dpy, mask);
215 testx11_init (Display *dpy, Window win)
217 static const char backdrop_pattern[] = {
218 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07', /* Zig */
219 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01', /* Zag */
220 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07', /* etc. */
221 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
222 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07',
223 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
224 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07',
225 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
228 static const char clip_bits[] = {
229 '\x33', '\x33', '\xcc', '\xcc', '\x33', '\x33', '\xcc', '\xcc'
232 struct testx11 *st = (struct testx11 *) malloc (sizeof(*st));
240 XGetWindowAttributes (dpy, win, &st->xgwa);
242 create_backbuffer (st);
244 st->rgb[0] = alloc_color (st, 0xffff, 0x0000, 0x0000);
245 st->rgb[1] = alloc_color (st, 0x0000, 0xffff, 0x0000);
246 st->rgb[2] = alloc_color (st, 0x0000, 0x0000, 0xffff);
247 st->salmon = alloc_color (st, 0xffff, 0x7fff, 0x7fff);
248 st->magenta = alloc_color (st, 0xffff, 0x0000, 0xffff);
249 st->gray50 = alloc_color (st, 0x8000, 0x8000, 0x8000);
250 st->dark_slate_gray1 = alloc_color (st, 0x8000, 0xffff, 0xffff);
251 st->cyan = alloc_color (st, 0x0000, 0xffff, 0xffff);
253 st->backdrop_tile = XCreatePixmapFromBitmapData (dpy, win,
254 (char *) backdrop_pattern,
255 tile_size, tile_size * 2,
258 st->clip_mask_tile = XCreatePixmapFromBitmapData (dpy, win,
259 (char *) clip_bits, 8, 8,
263 unsigned s = tile_size * tile_count;
264 st->backdrop_scratch = XCreatePixmap (dpy, win, s, s, st->xgwa.depth);
267 st->backdrop_ncolors = countof (st->backdrop_colors);
268 make_color_loop (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
269 180, 1, 0.5, 210, 1, 0.5, 240, 1, 0.5,
270 st->backdrop_colors, &st->backdrop_ncolors, True, NULL);
275 st->mode = mode_primitives;
277 st->mode = mode_welcome;
280 st->anti_alias_p = False;
282 gcv.function = GXcopy;
283 gcv.foreground = st->cyan;
284 gcv.background = st->magenta;
286 gcv.cap_style = CapRound;
287 /* TODO: Real X11 uses fixed by default. */
288 gcv.font = XLoadFont (dpy, "fixed");
289 st->copy_gc = XCreateGC (dpy, win,
290 GCFunction | GCForeground | GCBackground
291 | GCLineWidth | GCCapStyle | GCFont, &gcv);
293 gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
294 st->backdrop_black_gc = XCreateGC (dpy, win, GCForeground, &gcv);
296 gcv.foreground = alloc_color (st, 0x8000, 0x4000, 0xffff);
298 gcv.cap_style = CapProjecting;
299 st->thick_line_gc = XCreateGC (dpy, win,
300 GCForeground | GCLineWidth | GCCapStyle,
303 gcv.function = GXxor;
304 st->xor_gc = XCreateGC (dpy, win, GCFunction, &gcv);
306 st->images_point_gc = XCreateGC (dpy, win, 0, NULL);
308 st->graph_gc = XCreateGC (dpy, win, 0, &gcv);
310 st->mono_gc = XCreateGC (dpy, st->clip_mask_tile, 0, &gcv);
312 st->copy_pix64 = XCreatePixmap(dpy, win, 64, 64, st->xgwa.depth);
314 st->primitives_mini_pix = XCreatePixmap (dpy, win, 16, 16, st->xgwa.depth);
317 static const char text[] = "Welcome from testx11_init().";
318 XClearWindow (dpy, win);
319 XDrawString (dpy, win, st->copy_gc, 16, 16, text, countof (text) - 1);
325 XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
327 XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
329 toggle_antialiasing (st);
331 jwxyz_assert_display (dpy);
333 st->rot = make_rotator (2, 2, 2, 2, 0.01, False);
339 backdrop (struct testx11 *st, Drawable t)
341 unsigned w = st->xgwa.width, h = st->xgwa.height;
344 for (y = 0; y != tile_count; ++y) {
345 const float s0 = 2 * M_PI / tile_count;
346 float y_fac = sin ((y + st->frame / 16.0) * s0);
347 for (x = 0; x != tile_count; ++x) {
348 unsigned c = ((sin ((x + st->frame / 8.0) * s0) * y_fac) - 1) / 2 * st->backdrop_ncolors / 2;
349 c = (c + st->frame) % st->backdrop_ncolors;
350 XSetBackground (st->dpy, st->backdrop_black_gc,
351 st->backdrop_colors[c].pixel);
352 XCopyPlane (st->dpy, st->backdrop_tile, st->backdrop_scratch,
353 st->backdrop_black_gc, 0, st->frame % tile_size,
354 tile_size, tile_size, x * tile_size, y * tile_size, 1);
358 /* XFillRectangle (st->dpy, t, st->backdrop_black_gc, 0, 0, w, h); */
360 for (y = 0; y < h; y += tile_count * tile_size) {
361 for (x = 0; x < w; x += tile_count * tile_size) {
362 XCopyArea (st->dpy, st->backdrop_scratch, t, st->copy_gc, 0, 0,
363 tile_count * tile_size, tile_count * tile_size, x, y);
368 static const unsigned button_pad = 16;
369 static const unsigned button_size = 64;
373 testx11_graph_rotator (struct testx11 *st)
377 int boxw = st->xgwa.width / 3;
378 int boxh = (st->xgwa.height - (22 * 5)) / 4;
379 int boxx = st->xgwa.width - boxw - 20;
380 int boxy = st->xgwa.height - boxh - 20;
384 get_position (st->rot, &x, &y, &z, True);
385 if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
388 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
389 XDrawRectangle (st->dpy, st->win, st->graph_gc,
390 boxx-1, boxy-1, boxw+2, boxh+2);
392 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
393 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
395 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
396 XDrawLine (st->dpy, st->win, st->graph_gc,
397 boxx + boxw - 1, boxy,
398 boxx + boxw - 1, boxy + boxh);
400 XSetForeground (st->dpy, st->graph_gc, st->salmon);
401 XDrawPoint (st->dpy, st->win, st->graph_gc,
403 boxy + boxh - 1 - (int) (x * (boxh - 1)));
405 XSetForeground (st->dpy, st->graph_gc, st->magenta);
406 XDrawPoint (st->dpy, st->win, st->graph_gc,
408 boxy + boxh - 1 - (int) (y * (boxh - 1)));
410 XSetForeground (st->dpy, st->graph_gc, st->gray50);
411 XDrawPoint (st->dpy, st->win, st->graph_gc,
413 boxy + boxh - 1 - (int) (z * (boxh - 1)));
417 get_rotation (st->rot, &x, &y, &z, True);
418 if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
420 /* put 0 in the middle */
421 x += 0.5; if (x > 1) x--;
422 y += 0.5; if (y > 1) y--;
423 z += 0.5; if (z > 1) z--;
428 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
429 XDrawRectangle (st->dpy, st->win, st->graph_gc,
430 boxx-1, boxy-1, boxw+2, boxh+2);
432 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
433 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
435 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
436 XDrawLine (st->dpy, st->win, st->graph_gc,
437 boxx + boxw - 1, boxy,
438 boxx + boxw - 1, boxy + boxh);
440 XSetForeground (st->dpy, st->graph_gc, st->magenta);
441 XDrawPoint (st->dpy, st->win, st->graph_gc,
443 boxy + boxh - 1 - (int) (x * (boxh - 1)));
448 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
449 XDrawRectangle (st->dpy, st->win, st->graph_gc,
450 boxx-1, boxy-1, boxw+2, boxh+2);
452 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
453 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
455 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
456 XDrawLine (st->dpy, st->win, st->graph_gc,
457 boxx + boxw - 1, boxy,
458 boxx + boxw - 1, boxy + boxh);
460 XSetForeground (st->dpy, st->graph_gc, st->magenta);
461 XDrawPoint (st->dpy, st->win, st->graph_gc,
463 boxy + boxh - 1 - (int) (y * (boxh - 1)));
468 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
469 XDrawRectangle (st->dpy, st->win, st->graph_gc,
470 boxx-1, boxy-1, boxw+2, boxh+2);
472 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
473 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
475 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
476 XDrawLine (st->dpy, st->win, st->graph_gc,
477 boxx + boxw - 1, boxy,
478 boxx + boxw - 1, boxy + boxh);
480 XSetForeground (st->dpy, st->graph_gc, st->magenta);
481 XDrawPoint (st->dpy, st->win, st->graph_gc,
483 boxy + boxh - 1 - (int) (z * (boxh - 1)));
487 /* Draws a blinking box in what should be the upper left corner of the
488 device, as physically oriented. The box is taller than it is wide.
491 testx11_show_orientation (struct testx11 *st)
495 int w = st->xgwa.width;
496 int h = st->xgwa.height;
501 int o = (int) current_device_rotation ();
504 // fprintf (stderr,"ROT %d -> %d\n", oo, o);
509 case 0: case 360: x = 0; y = 0; w = ww; h = hh; break;
510 case 90: case -270: x = 0; y = h-ww; w = hh; h = ww; break;
511 case -90: case 270: x = w-hh; y = 0; w = hh; h = ww; break;
512 case 180: case -180: x = w-ww; y = h-hh; w = ww; h = hh; break;
516 if (++tick > 20) tick = 0;
518 XSetForeground (st->dpy, st->graph_gc,
520 ? WhitePixelOfScreen (st->xgwa.screen)
521 : BlackPixelOfScreen (st->xgwa.screen)));
522 XFillRectangle (st->dpy, st->win, st->graph_gc,
529 testx11_draw (Display *dpy, Window win, void *st_raw)
531 struct testx11 *st = (struct testx11 *) st_raw;
532 unsigned w = st->xgwa.width, h = st->xgwa.height;
536 Drawable t = st->mode == mode_primitives ? st->backbuffer : win;
540 assert (dpy == st->dpy);
541 assert (win == st->win);
543 jwxyz_assert_display (dpy);
545 XSetWindowBackground (dpy, win, st->gray50);
549 case mode_primitives:
552 XDrawPoint (dpy, t, st->thick_line_gc, 0, 0);
553 XDrawPoint (dpy, t, st->thick_line_gc, 0, 1);
554 XDrawPoint (dpy, t, st->thick_line_gc, 1, 0);
555 XDrawPoint (dpy, t, st->thick_line_gc, 1, 1);
557 primitives_mini_rect (st, t, 2, 0);
558 primitives_mini_rect (st, t, 0, 2);
559 primitives_mini_rect (st, t, 4, 2);
560 primitives_mini_rect (st, t, 2, 4);
562 primitives_mini_rect (st, t, 30, -2);
563 primitives_mini_rect (st, t, 32, 0);
565 primitives_mini_rect (st, t, 30, h - 2);
566 primitives_mini_rect (st, t, 32, h);
568 primitives_mini_rect (st, t, -2, 30);
569 primitives_mini_rect (st, t, 0, 32);
570 primitives_mini_rect (st, t, w - 2, 30);
571 primitives_mini_rect (st, t, w, 32);
573 primitives_mini_rect (st, t, w / 2 + 4, h / 2 + 4);
575 XFillArc (dpy, t, st->copy_gc, 16, 16, 256, 256, 45 * 64, -135 * 64);
576 /* XCopyArea(dpy, t, t, st->copy_gc, 48, 48, 128, 128, 64, 64); */
579 XDrawPoint (dpy, t, st->copy_gc, w / 2, h / 2);
582 XDrawPoint (dpy, t, st->copy_gc, w / 2, 0);
583 XDrawPoint (dpy, t, st->copy_gc, w / 2, h - 1);
585 XDrawPoint (dpy, t, st->copy_gc, 16, -1);
586 XDrawPoint (dpy, t, st->copy_gc, 17, 0);
588 XDrawPoint (dpy, t, st->copy_gc, 15, h - 2);
589 XDrawPoint (dpy, t, st->copy_gc, 16, h - 1);
590 XDrawPoint (dpy, t, st->copy_gc, 17, h);
593 XPoint *points = malloc (sizeof(XPoint) * h);
594 XSegment *lines = malloc (sizeof(XSegment) * h);
595 XPoint *points2 = malloc (sizeof(XPoint) * h);
596 for(i = 0; i != h; ++i)
598 points[i].x = 8 + (i & 1);
601 lines[i].x1 = 48 + (i & 1) * 4;
606 points2[i].x = 24 + (i & 1);
608 /* XFillRectangle(st->dpy, t, st->copy_gc, 24 + (i & 1), i, 1, 1); */
611 XDrawPoints (dpy, t, st->copy_gc, points, h, CoordModeOrigin);
612 XDrawSegments (dpy, t, st->copy_gc, lines, h);
613 XDrawPoints (dpy, t, st->copy_gc, points2, h, CoordModeOrigin);
620 XDrawPoint (dpy, t, st->copy_gc, -1, 16);
621 XDrawPoint (dpy, t, st->copy_gc, 0, 17);
622 XDrawPoint (dpy, t, st->copy_gc, w - 1, 16);
623 XDrawPoint (dpy, t, st->copy_gc, w, 17);
626 XPoint *points = malloc(sizeof(XPoint) * w);
627 XSegment *lines = malloc(sizeof(XSegment) * w);
628 XPoint *points2 = malloc(sizeof(XPoint) * w);
629 for(i = 0; i != w; ++i)
632 points[i].y = 8 + (i & 1);
634 lines[i].y1 = 48 + (i & 1) * 4;
639 points2[i].y = 24 + (i & 1);
640 /* XFillRectangle(dpy, t, st->copy_gc, i, 24 + (i & 1), 1, 1); */
643 XDrawPoints (dpy, t, st->copy_gc, points, w, CoordModeOrigin);
644 XDrawSegments (dpy, t, st->copy_gc, lines, w);
646 /* Thick purple lines */
649 {31, 31, 31, 31}, /* TODO: This should not be rotated in Cocoa. */
652 XDrawSegments (dpy, t, st->thick_line_gc, seg, 2);
654 XDrawLine (dpy, t, st->thick_line_gc, 58, 43, 64, 43);
655 XDrawLine (dpy, t, st->thick_line_gc, 73, 43, 80, 43);
658 XDrawPoints (dpy, t, st->copy_gc, points2, w, CoordModeOrigin);
664 XDrawLine (dpy, t, st->copy_gc, 54, 11, 72, 22);
667 XPoint vertices[] = {{5, 5}, {5, 8}, {8, 8}, {8, 5}};
668 XFillPolygon (dpy, t, st->copy_gc, vertices, 4, Convex, CoordModeOrigin);
672 XDrawRectangle (dpy, t, st->copy_gc, 11, 11, 11, 11);
673 XFillRectangle (dpy, t, st->copy_gc, 13, 13, 8, 8);
676 /* Several ~16 pixel boxes in a row. */
680 XDrawRectangle (dpy, t, st->copy_gc, 54, 54, 16, 16);
681 XDrawRectangle (dpy, t, st->copy_gc, 55, 55, 14, 14);
683 XDrawPoint (dpy, t, st->thick_line_gc, 56, 56);
684 XDrawPoint (dpy, t, st->copy_gc, 57, 56);
688 XCopyArea (dpy, t, t, st->copy_gc, 55, 55, 15, 15, 72, 55);
692 XImage *image = XGetImage(st->dpy, t, 55, 55, 15, 15, 0xffffff, ZPixmap);
693 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 88, 55, 15, 15);
694 XDestroyImage(image);
700 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
701 104, 55, 16, 16, 0, 0);
702 /* XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
703 105, 56, 14, 14, 1, 1);
704 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
708 /* This point gets hidden. */
709 XDrawPoint (dpy, t, st->copy_gc, 104 + 8, 55 + 8);
711 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 0, 0);
712 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 15, 15);
713 XDrawRectangle (dpy, st->primitives_mini_pix, st->copy_gc,
715 XCopyArea (dpy, st->primitives_mini_pix, t, st->copy_gc,
716 0, 0, 16, 16, 104, 55);
720 XDrawLine (dpy, t, st->copy_gc, 11, 28, 22, 28);
721 XDrawLine (dpy, t, st->copy_gc, 12, 27, 12, 46);
722 XDrawLine (dpy, t, st->copy_gc, 14, 30, 14, 30);
725 XDrawArc (dpy, t, st->copy_gc, 27, 11, 19, 11, 0, 360 * 64);
727 XDrawRectangle (dpy, t, st->copy_gc, 54, 73, 64, 64);
728 XFillArc (dpy, t, st->copy_gc, 56, 75, 60, 60, 0, 360 * 64);
729 /* XDrawArc (dpy, t, st->thick_line_gc, 56, 75, 60, 60, 0, 360 * 64); */
731 XClearArea (dpy, win, 121, 55, 16, 16, False);
737 /* if(w >= 9 && h >= 10) */
740 /* Draw below the status bar. */
741 const unsigned y = 64;
743 const unsigned y = 0;
746 Screen *screen = st->xgwa.screen;
747 Visual *visual = st->xgwa.visual;
748 Pixmap pixmap = XCreatePixmap (dpy, t, 3, 10,
749 visual_depth (screen, visual));
750 unsigned long cells = cells = st->rgb[0] | st->rgb[1] | st->rgb[2];
753 XSetForeground (dpy, st->images_point_gc, st->salmon);
754 XDrawPoint (dpy, t, st->images_point_gc, 0, h - 1);
755 XDrawLine (dpy, t, st->images_point_gc, 0, y - 1, 8, y - 1);
758 images_pattern (st, t, y);
759 images_pattern (st, pixmap, 0);
760 /* Here's a good spot to verify that the pixmap contains the right colors
763 images_copy_test (dpy, t, pixmap, st->copy_gc, y, 0, 6, cells);
765 XCopyArea (dpy, pixmap, t, st->copy_gc, 0, 0, 3, 10, 3, y);
768 XImage *image = XGetImage (dpy, pixmap, 0, 0, 3, 10, cells, ZPixmap);
769 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 6, y, 3, 10);
770 XDestroyImage (image);
773 XFreePixmap (dpy, pixmap);
781 /* X.org isn't making a whole lot of sense here. */
783 Bool use_copy = (st->frame / 20) & 1;
786 GC gc = use_copy ? st->copy_gc : st->xor_gc;
788 XSetWindowBackground (dpy, t, st->magenta);
789 XCopyArea (dpy, t, t, gc, -2, -2, 40, 40, 20, 20);
792 XCopyArea (st->dpy, t, t, gc, -20, h - 20, 40, 40, 20, h - 60);
793 XCopyArea (dpy, t, t, gc, w - 38, h - 38, 40, 40, w - 60, h - 60);
794 XCopyArea (dpy, t, t, gc, w - 20, -20, 40, 40, w - 60, 20);
796 XSetWindowBackground (dpy, t, st->gray50);
797 XCopyArea (st->dpy, t, t, gc, -20, 64, 40, 40, 20, 64);
799 XSetWindowBackground (dpy, t, st->dark_slate_gray1);
800 XCopyArea (st->dpy, t, t, gc, -20, 112, 40, 40, 20, 112);
806 XCopyArea (st->dpy, t, st->copy_pix64, gc, 0, h - 64, 64, 64, 0, 0);
808 XSetForeground (st->dpy, st->xor_gc, st->rgb[1]);
809 XSetBackground (st->dpy, st->xor_gc, st->cyan);
811 /* XCopyArea (st->dpy, st->copy_pix64, st->copy_pix64, gc,
812 32, 32, 64, 64, 0, 0);
813 XCopyArea (st->dpy, st->copy_pix64, t, gc, 0, 0, 64, 64, 4, h - 68);
815 XCopyArea (st->dpy, st->copy_pix64, t, gc, 32, 32, 128, 64, 0, h - 64);
823 if(!(st->frame % 10)) {
824 const unsigned r = 16;
825 unsigned n = st->frame / 10;
827 XFillArc (st->dpy, st->preserve[n & 1],
828 m & 1 ? st->copy_gc : st->thick_line_gc,
829 NRAND(preserve_size) - r, NRAND(preserve_size) - r,
830 r * 2, r * 2, 0, 360 * 64);
833 XCopyArea (st->dpy, st->preserve[0], t, st->copy_gc, 0, 0,
834 preserve_size, preserve_size, 0, 0);
835 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
836 preserve_size, preserve_size, preserve_size, 0);
837 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
838 preserve_size, preserve_size,
839 w - preserve_size / 2, preserve_size);
843 /* Mode toggle buttons */
844 for (i = 1; i != mode_count; ++i) {
847 XRectangle button_dims;
848 button_dims.x = i0 * (button_pad + button_size) + button_pad;
849 button_dims.y = h - button_pad - button_size;
850 button_dims.width = button_size;
851 button_dims.height = button_size;
853 XFillRectangles (dpy, t, st->backdrop_black_gc, &button_dims, 1);
854 XDrawRectangle (dpy, t, st->copy_gc, button_dims.x, button_dims.y,
855 button_dims.width, button_dims.height);
857 XDrawString (dpy, t, st->copy_gc,
858 button_dims.x + button_size / 2 - 3,
859 h - button_pad - button_size / 2 + 13 / 2,
860 str, sprintf(str, "%u", i));
864 XCopyArea (dpy, t, win, st->copy_gc, 0, 0, w, h, 0, 0);
866 testx11_graph_rotator (st);
867 testx11_show_orientation (st);
874 testx11_reshape (Display *dpy, Window window, void *st_raw,
875 unsigned int w, unsigned int h)
877 struct testx11 *st = (struct testx11 *)st_raw;
881 XFreePixmap (st->dpy, st->backbuffer);
883 create_backbuffer (st);
888 testx11_event (Display *dpy, Window window, void *st_raw, XEvent *event)
890 struct testx11 *st = (struct testx11 *) st_raw;
892 Bool handled = False;
894 switch (event->xany.type)
900 XLookupString (&event->xkey, &c, 1, &keysym, 0);
902 handled = toggle_antialiasing (st);
904 if (c >= '0' && c <= '9' && c < '0' + mode_count) {
912 if (event->xbutton.y >= st->xgwa.height - button_pad * 2 - button_size) {
913 int i = (event->xbutton.x - button_pad / 2) / (button_pad + button_size) + 1;
914 if (i && i < mode_count) {
921 handled = toggle_antialiasing (st);
929 testx11_free (Display *dpy, Window window, void *st_raw)
931 /* Omitted for the sake of brevity. */
934 XSCREENSAVER_MODULE_2 ("TestX11", testx11, testx11)