1 /* testx11.c, Copyright (c) 2015-2017 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, 24, 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 XPutPixel(image, 2, 0, 0x00000000);
694 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 88, 55, 15, 15);
695 XDestroyImage(image);
701 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
702 104, 55, 16, 16, 0, 0);
703 /* XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
704 105, 56, 14, 14, 1, 1);
705 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
709 /* This point gets hidden. */
710 XDrawPoint (dpy, t, st->copy_gc, 104 + 8, 55 + 8);
712 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 0, 0);
713 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 1, 0);
714 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 15, 15);
715 XDrawRectangle (dpy, st->primitives_mini_pix, st->copy_gc,
717 XCopyArea (dpy, st->primitives_mini_pix, t, st->copy_gc,
718 0, 0, 16, 16, 104, 55);
722 XDrawLine (dpy, t, st->copy_gc, 11, 28, 22, 28);
723 XDrawLine (dpy, t, st->copy_gc, 12, 27, 12, 46);
724 XDrawLine (dpy, t, st->copy_gc, 14, 30, 14, 30);
727 XDrawArc (dpy, t, st->copy_gc, 27, 11, 19, 11, 0, 360 * 64);
729 XDrawRectangle (dpy, t, st->copy_gc, 54, 73, 64, 64);
730 XFillArc (dpy, t, st->copy_gc, 56, 75, 60, 60, 0, 360 * 64);
731 /* XDrawArc (dpy, t, st->thick_line_gc, 56, 75, 60, 60, 0, 360 * 64); */
733 XClearArea (dpy, win, 121, 55, 16, 16, False);
739 /* if(w >= 9 && h >= 10) */
742 /* Draw below the status bar. */
743 const unsigned y = 64;
745 const unsigned y = 0;
748 Screen *screen = st->xgwa.screen;
749 Visual *visual = st->xgwa.visual;
750 Pixmap pixmap = XCreatePixmap (dpy, t, 3, 10,
751 visual_depth (screen, visual));
752 unsigned long cells = cells = st->rgb[0] | st->rgb[1] | st->rgb[2];
755 XSetForeground (dpy, st->images_point_gc, st->salmon);
756 XDrawPoint (dpy, t, st->images_point_gc, 0, h - 1);
757 XDrawLine (dpy, t, st->images_point_gc, 0, y - 1, 8, y - 1);
760 images_pattern (st, t, y);
761 images_pattern (st, pixmap, 0);
762 /* Here's a good spot to verify that the pixmap contains the right colors
765 images_copy_test (dpy, t, pixmap, st->copy_gc, y, 0, 6, cells);
767 XCopyArea (dpy, pixmap, t, st->copy_gc, 0, 0, 3, 10, 3, y);
770 XImage *image = XGetImage (dpy, pixmap, 0, 0, 3, 10, cells, ZPixmap);
771 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 6, y, 3, 10);
772 XDestroyImage (image);
775 XFreePixmap (dpy, pixmap);
783 /* X.org isn't making a whole lot of sense here. */
785 Bool use_copy = (st->frame / 20) & 1;
788 GC gc = use_copy ? st->copy_gc : st->xor_gc;
790 XSetWindowBackground (dpy, t, st->magenta);
791 XCopyArea (dpy, t, t, gc, -2, -2, 40, 40, 20, 20);
794 XCopyArea (st->dpy, t, t, gc, -20, h - 20, 40, 40, 20, h - 60);
795 XCopyArea (dpy, t, t, gc, w - 38, h - 38, 40, 40, w - 60, h - 60);
796 XCopyArea (dpy, t, t, gc, w - 20, -20, 40, 40, w - 60, 20);
798 XSetWindowBackground (dpy, t, st->gray50);
799 XCopyArea (st->dpy, t, t, gc, -20, 64, 40, 40, 20, 64);
801 XSetWindowBackground (dpy, t, st->dark_slate_gray1);
802 XCopyArea (st->dpy, t, t, gc, -20, 112, 40, 40, 20, 112);
808 XCopyArea (st->dpy, t, st->copy_pix64, gc, 0, h - 64, 64, 64, 0, 0);
810 XSetForeground (st->dpy, st->xor_gc, st->rgb[1]);
811 XSetBackground (st->dpy, st->xor_gc, st->cyan);
813 /* XCopyArea (st->dpy, st->copy_pix64, st->copy_pix64, gc,
814 32, 32, 64, 64, 0, 0);
815 XCopyArea (st->dpy, st->copy_pix64, t, gc, 0, 0, 64, 64, 4, h - 68);
817 XCopyArea (st->dpy, st->copy_pix64, t, gc, 32, 32, 128, 64, 0, h - 64);
825 if(!(st->frame % 10)) {
826 const unsigned r = 16;
827 unsigned n = st->frame / 10;
829 XFillArc (st->dpy, st->preserve[n & 1],
830 m & 1 ? st->copy_gc : st->thick_line_gc,
831 NRAND(preserve_size) - r, NRAND(preserve_size) - r,
832 r * 2, r * 2, 0, 360 * 64);
835 XCopyArea (st->dpy, st->preserve[0], t, st->copy_gc, 0, 0,
836 preserve_size, preserve_size, 0, 0);
837 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
838 preserve_size, preserve_size, preserve_size, 0);
839 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
840 preserve_size, preserve_size,
841 w - preserve_size / 2, preserve_size);
845 /* Mode toggle buttons */
846 for (i = 1; i != mode_count; ++i) {
849 XRectangle button_dims;
850 button_dims.x = i0 * (button_pad + button_size) + button_pad;
851 button_dims.y = h - button_pad - button_size;
852 button_dims.width = button_size;
853 button_dims.height = button_size;
855 XFillRectangles (dpy, t, st->backdrop_black_gc, &button_dims, 1);
856 XDrawRectangle (dpy, t, st->copy_gc, button_dims.x, button_dims.y,
857 button_dims.width, button_dims.height);
859 XDrawString (dpy, t, st->copy_gc,
860 button_dims.x + button_size / 2 - 3,
861 h - button_pad - button_size / 2 + 13 / 2,
862 str, sprintf(str, "%u", i));
866 XCopyArea (dpy, t, win, st->copy_gc, 0, 0, w, h, 0, 0);
868 testx11_graph_rotator (st);
869 testx11_show_orientation (st);
876 testx11_reshape (Display *dpy, Window window, void *st_raw,
877 unsigned int w, unsigned int h)
879 struct testx11 *st = (struct testx11 *)st_raw;
883 XFreePixmap (st->dpy, st->backbuffer);
885 create_backbuffer (st);
890 testx11_event (Display *dpy, Window window, void *st_raw, XEvent *event)
892 struct testx11 *st = (struct testx11 *) st_raw;
894 Bool handled = False;
896 switch (event->xany.type)
902 XLookupString (&event->xkey, &c, 1, &keysym, 0);
904 handled = toggle_antialiasing (st);
906 if (c >= '0' && c <= '9' && c < '0' + mode_count) {
914 if (event->xbutton.y >= st->xgwa.height - button_pad * 2 - button_size) {
915 int i = (event->xbutton.x - button_pad / 2) / (button_pad + button_size) + 1;
916 if (i && i < mode_count) {
923 handled = toggle_antialiasing (st);
931 testx11_free (Display *dpy, Window window, void *st_raw)
933 /* Omitted for the sake of brevity. */
936 XSCREENSAVER_MODULE_2 ("TestX11", testx11, testx11)