1 /* testx11.c, Copyright (c) 2015-2017 Dave Odell <dmo2118@gmail.com>
2 *
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
9 * implied warranty.
10 *
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.
13 *
14 * Almost no error checking in here. This is intentional.
15 */
16
17 #include "screenhack.h"
18 #include "glx/rotator.h"
19 #include "colorbars.h"
20 #include "erase.h"
21
22 #include "ximage-loader.h"
23 #include "images/gen/logo-180_png.h"
24
25 #include <assert.h>
26 #include <errno.h>
27
28 #ifndef HAVE_JWXYZ
29 # define jwxyz_XSetAntiAliasing(dpy, gc, p)
30 #endif
31
32 #ifndef jwxyz_assert_display
33 # define jwxyz_assert_display(dpy)
34 #endif
35
36 #define countof(a) (sizeof(a) / sizeof(*(a)))
37
38 static const char *testx11_defaults [] = {
39 ".background: #a020f0", /* purple */
40 ".foreground: white",
41 #ifdef HAVE_MOBILE
42 "*ignoreRotation: True",
43 #endif
44 0
45 };
46
47 static XrmOptionDescRec testx11_options [] = {
48 { 0, 0, 0, 0 }
49 };
50
51 enum
52 {
53 mode_welcome,
54 mode_primitives,
55 mode_images,
56 mode_copy,
57 mode_preserve,
58 mode_erase,
59
60 mode_count
61 };
62
63 struct testx11 {
64 Display *dpy;
65 Window win;
66
67 XWindowAttributes xgwa;
68
69 # ifndef HAVE_JWXYZ
70 Pixmap backbuffer;
71 # endif
72
73 unsigned mode;
74
75 /* Pixels from XAllocPixel. */
76 unsigned long rgb[3], salmon, magenta, gray50, dark_slate_gray1, cyan;
77
78 unsigned frame;
79
80 Bool anti_alias_p;
81
82 /* These X11 objects aren't altered after creation, except for:
83 - copy_gc and thick_line_gc get anti-aliasing toggled.
84 - xor_gc's clip mask (if it's turned on) always covers the entire window.
85 */
86 GC copy_gc, mono_gc, thick_line_gc, xor_gc, graph_gc;
87 Pixmap clip_mask_tile;
88
89 /* Backdrop stuff, naturally. */
90 GC backdrop_black_gc;
91 Pixmap backdrop_tile, backdrop_scratch;
92 XColor backdrop_colors[64];
93 int backdrop_ncolors;
94
95 /* The following items may be modified by various test modes. */
96 Pixmap primitives_mini_pix;
97
98 GC images_point_gc;
99
100 Pixmap copy_pix64;
101
102 Pixmap preserve[2];
103
104 eraser_state *erase;
105
106 rotator *rot;
107 };
108
109
110 static void
abort_no_mem(void)111 abort_no_mem (void)
112 {
113 fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
114 abort();
115 }
116
117 static void
check_no_mem(void * ptr)118 check_no_mem (void *ptr)
119 {
120 if(!ptr)
121 abort_no_mem();
122 }
123
124
125 static unsigned long
alloc_color(struct testx11 * st,unsigned short r,unsigned short g,unsigned short b)126 alloc_color (struct testx11 *st,
127 unsigned short r, unsigned short g, unsigned short b)
128 {
129 XColor color;
130 color.red = r;
131 color.green = g;
132 color.blue = b;
133 color.flags = DoRed | DoGreen | DoBlue;
134 XAllocColor (st->dpy, st->xgwa.colormap, &color);
135 return color.pixel;
136 }
137
138 static void
create_backbuffer(struct testx11 * st)139 create_backbuffer(struct testx11 *st)
140 {
141 # ifndef HAVE_JWXYZ
142 st->backbuffer = XCreatePixmap (st->dpy, st->win,
143 st->xgwa.width, st->xgwa.height,
144 st->xgwa.depth);
145 # endif
146 }
147
148 static Bool
toggle_antialiasing(struct testx11 * st)149 toggle_antialiasing (struct testx11 *st)
150 {
151 st->anti_alias_p ^= True;
152 jwxyz_XSetAntiAliasing (st->dpy, st->copy_gc, st->anti_alias_p);
153 jwxyz_XSetAntiAliasing (st->dpy, st->thick_line_gc, st->anti_alias_p);
154 return True;
155 }
156
157
158 static void
primitives_mini_rect(struct testx11 * st,Drawable t,int x,int y)159 primitives_mini_rect(struct testx11 *st, Drawable t, int x, int y)
160 {
161 XFillRectangle(st->dpy, t, st->copy_gc, x, y, 2, 2);
162 }
163
164 static void
images_copy_test(Display * dpy,Drawable src,Drawable dst,GC gc,int src_y,int dst_x,int dst_y,unsigned long cells)165 images_copy_test (Display *dpy, Drawable src, Drawable dst, GC gc,
166 int src_y, int dst_x, int dst_y, unsigned long cells)
167 {
168 XCopyArea(dpy, src, dst, gc, 0, src_y, 3, 2, dst_x, dst_y);
169
170 {
171 XImage *image = XGetImage(dpy, src, 0, src_y, 3, 2, cells, ZPixmap);
172 XPutImage(dpy, dst, gc, image, 0, 0, dst_x, dst_y + 2, 3, 2);
173 XDestroyImage(image);
174 }
175 }
176
177 static void
images_pattern(struct testx11 * st,Drawable d,unsigned y)178 images_pattern (struct testx11 *st, Drawable d, unsigned y)
179 {
180 unsigned x;
181 for (x = 0; x != 3; ++x) {
182 XSetForeground(st->dpy, st->images_point_gc, st->rgb[x]);
183 XDrawPoint(st->dpy, d, st->images_point_gc, x, y);
184 XSetForeground(st->dpy, st->images_point_gc, st->rgb[2 - x]);
185 XFillRectangle(st->dpy, d, st->images_point_gc, x, y + 1, 1, 1);
186 }
187
188 images_copy_test (st->dpy, d, d, st->images_point_gc, y, 0, y + 2,
189 st->rgb[0] | st->rgb[1] | st->rgb[2]);
190 }
191
192 static const unsigned tile_size = 16;
193 static const unsigned tile_count = 8;
194
195 static const unsigned preserve_size = 128;
196
197 static void
make_clip_mask(struct testx11 * st)198 make_clip_mask (struct testx11 *st)
199 {
200 /* Activate this for extra Fun! */
201 # if 0
202 /* This is kind of slow, but that's OK, because this only happens on int
203 or during a resize.
204 */
205 unsigned w = st->xgwa.width, h = st->xgwa.height;
206 unsigned x, y;
207 Pixmap mask = XCreatePixmap (st->dpy, st->clip_mask_tile, w, h, 1);
208
209 for (y = 0; y < h; y += 8) {
210 for (x = 0; x < w; x += 8) {
211 XCopyArea (st->dpy, st->clip_mask_tile, mask, st->mono_gc,
212 0, 0, 8, 8, x, y);
213 }
214 }
215
216 XSetClipMask (st->dpy, st->xor_gc, mask);
217 XFreePixmap (st->dpy, mask);
218 # endif
219 }
220
221
222 static void
colorbars(struct testx11 * st)223 colorbars (struct testx11 *st)
224 {
225 Pixmap logo_mask = 0;
226 Pixmap logo = image_data_to_pixmap (st->dpy, st->win,
227 logo_180_png, sizeof(logo_180_png),
228 0, 0, &logo_mask);
229 draw_colorbars (st->xgwa.screen, st->xgwa.visual, st->win,
230 st->xgwa.colormap, 0, 0, st->xgwa.width, st->xgwa.height,
231 logo, logo_mask);
232 XFreePixmap (st->dpy, logo);
233 XFreePixmap (st->dpy, logo_mask);
234 }
235
236
237 static void *
testx11_init(Display * dpy,Window win)238 testx11_init (Display *dpy, Window win)
239 {
240 static const char backdrop_pattern[] = {
241 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07', /* Zig */
242 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01', /* Zag */
243 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07', /* etc. */
244 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
245 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07',
246 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
247 '\xff', '\x00', '\xfe', '\x01', '\xfc', '\x03', '\xf8', '\x07',
248 '\xf0', '\x0f', '\xf8', '\x07', '\xfc', '\x03', '\xfe', '\x01',
249 };
250
251 static const char clip_bits[] = {
252 '\x33', '\x33', '\xcc', '\xcc', '\x33', '\x33', '\xcc', '\xcc'
253 };
254
255 struct testx11 *st = (struct testx11 *) malloc (sizeof(*st));
256 XGCValues gcv;
257
258 check_no_mem (st);
259
260 st->dpy = dpy;
261 st->win = win;
262
263 XGetWindowAttributes (dpy, win, &st->xgwa);
264
265 create_backbuffer (st);
266
267 st->rgb[0] = alloc_color (st, 0xffff, 0x0000, 0x0000);
268 st->rgb[1] = alloc_color (st, 0x0000, 0xffff, 0x0000);
269 st->rgb[2] = alloc_color (st, 0x0000, 0x0000, 0xffff);
270 st->salmon = alloc_color (st, 0xffff, 0x7fff, 0x7fff);
271 st->magenta = alloc_color (st, 0xffff, 0x0000, 0xffff);
272 st->gray50 = alloc_color (st, 0x8000, 0x8000, 0x8000);
273 st->dark_slate_gray1 = alloc_color (st, 0x8000, 0xffff, 0xffff);
274 st->cyan = alloc_color (st, 0x0000, 0xffff, 0xffff);
275
276 st->backdrop_tile = XCreatePixmapFromBitmapData (dpy, win,
277 (char *) backdrop_pattern,
278 tile_size, tile_size * 2,
279 1, 0, 1);
280
281 st->clip_mask_tile = XCreatePixmapFromBitmapData (dpy, win,
282 (char *) clip_bits, 8, 8,
283 1, 0, 1);
284
285 {
286 unsigned s = tile_size * tile_count;
287 st->backdrop_scratch = XCreatePixmap (dpy, win, s, s, st->xgwa.depth);
288 }
289
290 st->backdrop_ncolors = countof (st->backdrop_colors);
291 make_color_loop (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
292 180, 1, 0.5, 210, 1, 0.5, 240, 1, 0.5,
293 st->backdrop_colors, &st->backdrop_ncolors, True, NULL);
294
295 st->frame = 0;
296
297 # ifdef HAVE_ANDROID
298 st->mode = mode_primitives;
299 # else
300 st->mode = mode_welcome;
301 # endif
302
303 st->anti_alias_p = False;
304
305 gcv.function = GXcopy;
306 gcv.foreground = st->cyan;
307 gcv.background = st->magenta;
308 gcv.line_width = 0;
309 gcv.cap_style = CapRound;
310 /* TODO: Real X11 uses fixed by default. */
311 gcv.font = XLoadFont (dpy, "fixed");
312 st->copy_gc = XCreateGC (dpy, win,
313 GCFunction | GCForeground | GCBackground
314 | GCLineWidth | GCCapStyle | GCFont, &gcv);
315
316 gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
317 st->backdrop_black_gc = XCreateGC (dpy, win, GCForeground, &gcv);
318
319 gcv.foreground = alloc_color (st, 0x8000, 0x4000, 0xffff);
320 gcv.line_width = 8;
321 gcv.cap_style = CapProjecting;
322 st->thick_line_gc = XCreateGC (dpy, win,
323 GCForeground | GCLineWidth | GCCapStyle,
324 &gcv);
325
326 gcv.function = GXxor;
327 st->xor_gc = XCreateGC (dpy, win, GCFunction, &gcv);
328
329 st->images_point_gc = XCreateGC (dpy, win, 0, NULL);
330
331 st->graph_gc = XCreateGC (dpy, win, 0, &gcv);
332
333 st->mono_gc = XCreateGC (dpy, st->clip_mask_tile, 0, &gcv);
334
335 st->copy_pix64 = XCreatePixmap(dpy, win, 64, 64, st->xgwa.depth);
336
337 st->primitives_mini_pix = XCreatePixmap (dpy, win, 16, 24, st->xgwa.depth);
338
339 {
340 static const char text[] = "Welcome from testx11_init().";
341 colorbars (st);
342 XDrawString (dpy, win, st->copy_gc, 16, 16, text, countof (text) - 1);
343 }
344
345 make_clip_mask (st);
346
347 st->preserve[0] =
348 XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
349 st->preserve[1] =
350 XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
351
352 toggle_antialiasing (st);
353
354 st->erase = NULL;
355
356 jwxyz_assert_display (dpy);
357
358 st->rot = make_rotator (2, 2, 2, 2, 0.01, False);
359 return st;
360 }
361
362
363 static void
backdrop(struct testx11 * st,Drawable t)364 backdrop (struct testx11 *st, Drawable t)
365 {
366 unsigned w = st->xgwa.width, h = st->xgwa.height;
367 unsigned x, y;
368
369 for (y = 0; y != tile_count; ++y) {
370 const float s0 = 2 * M_PI / tile_count;
371 float y_fac = sin ((y + st->frame / 16.0) * s0);
372 for (x = 0; x != tile_count; ++x) {
373 int c = ((sin ((x + st->frame / 8.0) * s0) * y_fac) - 1) / 2 *
374 st->backdrop_ncolors / 2;
375 c = (c + st->frame) % st->backdrop_ncolors;
376 XSetBackground (st->dpy, st->backdrop_black_gc,
377 st->backdrop_colors[c].pixel);
378 XCopyPlane (st->dpy, st->backdrop_tile, st->backdrop_scratch,
379 st->backdrop_black_gc, 0, st->frame % tile_size,
380 tile_size, tile_size, x * tile_size, y * tile_size, 1);
381 }
382 }
383
384 /* XFillRectangle (st->dpy, t, st->backdrop_black_gc, 0, 0, w, h); */
385
386 for (y = 0; y < h; y += tile_count * tile_size) {
387 for (x = 0; x < w; x += tile_count * tile_size) {
388 XCopyArea (st->dpy, st->backdrop_scratch, t, st->copy_gc, 0, 0,
389 tile_count * tile_size, tile_count * tile_size, x, y);
390 }
391 }
392 }
393
394 static const unsigned button_pad = 16;
395 static const unsigned button_size = 64;
396
397
398 static void
testx11_graph_rotator(struct testx11 * st)399 testx11_graph_rotator (struct testx11 *st)
400 {
401 double x, y, z;
402
403 int boxw = st->xgwa.width / 3;
404 int boxh = (st->xgwa.height - (22 * 5)) / 4;
405 int boxx = st->xgwa.width - boxw - 20;
406 int boxy = st->xgwa.height - boxh - 20;
407
408 /* position */
409
410 get_position (st->rot, &x, &y, &z, True);
411 if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
412
413
414 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
415 XDrawRectangle (st->dpy, st->win, st->graph_gc,
416 boxx-1, boxy-1, boxw+2, boxh+2);
417
418 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
419 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
420
421 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
422 XDrawLine (st->dpy, st->win, st->graph_gc,
423 boxx + boxw - 1, boxy,
424 boxx + boxw - 1, boxy + boxh);
425
426 XSetForeground (st->dpy, st->graph_gc, st->salmon);
427 XDrawPoint (st->dpy, st->win, st->graph_gc,
428 boxx + boxw - 1,
429 boxy + boxh - 1 - (int) (x * (boxh - 1)));
430
431 XSetForeground (st->dpy, st->graph_gc, st->magenta);
432 XDrawPoint (st->dpy, st->win, st->graph_gc,
433 boxx + boxw - 1,
434 boxy + boxh - 1 - (int) (y * (boxh - 1)));
435
436 XSetForeground (st->dpy, st->graph_gc, st->gray50);
437 XDrawPoint (st->dpy, st->win, st->graph_gc,
438 boxx + boxw - 1,
439 boxy + boxh - 1 - (int) (z * (boxh - 1)));
440
441 /* spin */
442
443 get_rotation (st->rot, &x, &y, &z, True);
444 if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
445
446 /* put 0 in the middle */
447 x += 0.5; if (x > 1) x--;
448 y += 0.5; if (y > 1) y--;
449 z += 0.5; if (z > 1) z--;
450
451
452 boxy -= boxh + 20;
453
454 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
455 XDrawRectangle (st->dpy, st->win, st->graph_gc,
456 boxx-1, boxy-1, boxw+2, boxh+2);
457
458 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
459 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
460
461 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
462 XDrawLine (st->dpy, st->win, st->graph_gc,
463 boxx + boxw - 1, boxy,
464 boxx + boxw - 1, boxy + boxh);
465
466 XSetForeground (st->dpy, st->graph_gc, st->magenta);
467 XDrawPoint (st->dpy, st->win, st->graph_gc,
468 boxx + boxw - 1,
469 boxy + boxh - 1 - (int) (x * (boxh - 1)));
470
471
472 boxy -= boxh + 20;
473
474 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
475 XDrawRectangle (st->dpy, st->win, st->graph_gc,
476 boxx-1, boxy-1, boxw+2, boxh+2);
477
478 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
479 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
480
481 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
482 XDrawLine (st->dpy, st->win, st->graph_gc,
483 boxx + boxw - 1, boxy,
484 boxx + boxw - 1, boxy + boxh);
485
486 XSetForeground (st->dpy, st->graph_gc, st->magenta);
487 XDrawPoint (st->dpy, st->win, st->graph_gc,
488 boxx + boxw - 1,
489 boxy + boxh - 1 - (int) (y * (boxh - 1)));
490
491
492 boxy -= boxh + 20;
493
494 XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
495 XDrawRectangle (st->dpy, st->win, st->graph_gc,
496 boxx-1, boxy-1, boxw+2, boxh+2);
497
498 XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
499 boxx+1, boxy, boxw-1, boxh, boxx, boxy);
500
501 XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
502 XDrawLine (st->dpy, st->win, st->graph_gc,
503 boxx + boxw - 1, boxy,
504 boxx + boxw - 1, boxy + boxh);
505
506 XSetForeground (st->dpy, st->graph_gc, st->magenta);
507 XDrawPoint (st->dpy, st->win, st->graph_gc,
508 boxx + boxw - 1,
509 boxy + boxh - 1 - (int) (z * (boxh - 1)));
510 }
511
512
513 /* Draws a blinking box in what should be the upper left corner of the
514 device, as physically oriented. The box is taller than it is wide.
515 */
516 static void
testx11_show_orientation(struct testx11 * st)517 testx11_show_orientation (struct testx11 *st)
518 {
519 #ifdef HAVE_MOBILE
520 int x, y;
521 int w = st->xgwa.width;
522 int h = st->xgwa.height;
523 int ww = 15;
524 int hh = ww*2;
525 static int tick = 0;
526 static int oo = -1;
527 int o = (int) current_device_rotation ();
528
529 if (o != oo) {
530 // fprintf (stderr,"ROT %d -> %d\n", oo, o);
531 oo = o;
532 }
533
534 switch (o) {
535 case 0: case 360: x = 0; y = 0; w = ww; h = hh; break;
536 case 90: case -270: x = 0; y = h-ww; w = hh; h = ww; break;
537 case -90: case 270: x = w-hh; y = 0; w = hh; h = ww; break;
538 case 180: case -180: x = w-ww; y = h-hh; w = ww; h = hh; break;
539 default: return;
540 }
541
542 if (++tick > 20) tick = 0;
543
544 XSetForeground (st->dpy, st->graph_gc,
545 (tick > 10
546 ? WhitePixelOfScreen (st->xgwa.screen)
547 : BlackPixelOfScreen (st->xgwa.screen)));
548 XFillRectangle (st->dpy, st->win, st->graph_gc,
549 x, y, w, h);
550 #endif
551 }
552
553
554 static unsigned long
testx11_draw(Display * dpy,Window win,void * st_raw)555 testx11_draw (Display *dpy, Window win, void *st_raw)
556 {
557 struct testx11 *st = (struct testx11 *) st_raw;
558 unsigned w = st->xgwa.width, h = st->xgwa.height;
559 # ifdef HAVE_JWXYZ
560 Drawable t = win;
561 # else
562 Drawable t = st->mode == mode_primitives ? st->backbuffer : win;
563 # endif
564 unsigned i;
565
566 assert (dpy == st->dpy);
567 assert (win == st->win);
568
569 jwxyz_assert_display (dpy);
570
571 XSetWindowBackground (dpy, win, st->gray50);
572
573 switch (st->mode)
574 {
575 case mode_primitives:
576 backdrop (st, t);
577
578 XDrawPoint (dpy, t, st->thick_line_gc, 0, 0);
579 XDrawPoint (dpy, t, st->thick_line_gc, 0, 1);
580 XDrawPoint (dpy, t, st->thick_line_gc, 1, 0);
581 XDrawPoint (dpy, t, st->thick_line_gc, 1, 1);
582
583 primitives_mini_rect (st, t, 2, 0);
584 primitives_mini_rect (st, t, 0, 2);
585 primitives_mini_rect (st, t, 4, 2);
586 primitives_mini_rect (st, t, 2, 4);
587
588 primitives_mini_rect (st, t, 30, -2);
589 primitives_mini_rect (st, t, 32, 0);
590
591 primitives_mini_rect (st, t, 30, h - 2);
592 primitives_mini_rect (st, t, 32, h);
593
594 primitives_mini_rect (st, t, -2, 30);
595 primitives_mini_rect (st, t, 0, 32);
596 primitives_mini_rect (st, t, w - 2, 30);
597 primitives_mini_rect (st, t, w, 32);
598
599 primitives_mini_rect (st, t, w / 2 + 4, h / 2 + 4);
600
601 XFillArc (dpy, t, st->copy_gc, 16, 16, 256, 256, 45 * 64, -135 * 64);
602 /* XCopyArea(dpy, t, t, st->copy_gc, 48, 48, 128, 128, 64, 64); */
603
604 /* Center */
605 XDrawPoint (dpy, t, st->copy_gc, w / 2, h / 2);
606
607 /* Top/bottom */
608 XDrawPoint (dpy, t, st->copy_gc, w / 2, 0);
609 XDrawPoint (dpy, t, st->copy_gc, w / 2, h - 1);
610
611 XDrawPoint (dpy, t, st->copy_gc, 16, -1);
612 XDrawPoint (dpy, t, st->copy_gc, 17, 0);
613
614 XDrawPoint (dpy, t, st->copy_gc, 15, h - 2);
615 XDrawPoint (dpy, t, st->copy_gc, 16, h - 1);
616 XDrawPoint (dpy, t, st->copy_gc, 17, h);
617
618 {
619 XPoint *points = malloc (sizeof(XPoint) * h);
620 XSegment *lines = malloc (sizeof(XSegment) * h);
621 XPoint *points2 = malloc (sizeof(XPoint) * h);
622 for(i = 0; i != h; ++i)
623 {
624 points[i].x = 8 + (i & 1);
625 points[i].y = i;
626
627 lines[i].x1 = 48 + (i & 1) * 4;
628 lines[i].y1 = i;
629 lines[i].x2 = 50;
630 lines[i].y2 = i;
631
632 points2[i].x = 24 + (i & 1);
633 points2[i].y = i;
634 /* XFillRectangle(st->dpy, t, st->copy_gc, 24 + (i & 1), i, 1, 1); */
635 }
636
637 XDrawPoints (dpy, t, st->copy_gc, points, h, CoordModeOrigin);
638 XDrawSegments (dpy, t, st->copy_gc, lines, h);
639 XDrawPoints (dpy, t, st->copy_gc, points2, h, CoordModeOrigin);
640 free (lines);
641 free (points);
642 free (points2);
643 }
644
645 /* Left/right */
646 XDrawPoint (dpy, t, st->copy_gc, -1, 16);
647 XDrawPoint (dpy, t, st->copy_gc, 0, 17);
648 XDrawPoint (dpy, t, st->copy_gc, w - 1, 16);
649 XDrawPoint (dpy, t, st->copy_gc, w, 17);
650
651 {
652 XPoint *points = malloc(sizeof(XPoint) * w);
653 XSegment *lines = malloc(sizeof(XSegment) * w);
654 XPoint *points2 = malloc(sizeof(XPoint) * w);
655 for(i = 0; i != w; ++i)
656 {
657 points[i].x = i;
658 points[i].y = 8 + (i & 1);
659 lines[i].x1 = i;
660 lines[i].y1 = 48 + (i & 1) * 4;
661 lines[i].x2 = i;
662 lines[i].y2 = 50;
663
664 points2[i].x = i;
665 points2[i].y = 24 + (i & 1);
666 /* XFillRectangle(dpy, t, st->copy_gc, i, 24 + (i & 1), 1, 1); */
667 }
668
669 XDrawPoints (dpy, t, st->copy_gc, points, w, CoordModeOrigin);
670 XDrawSegments (dpy, t, st->copy_gc, lines, w);
671 {
672 /* Thick purple lines */
673 XSegment seg[2] =
674 {
675 {31, 31, 31, 31}, /* TODO: This should not be rotated in Cocoa. */
676 {42, 31, 42, 42}
677 };
678 XDrawSegments (dpy, t, st->thick_line_gc, seg, 2);
679
680 XDrawLine (dpy, t, st->thick_line_gc, 58, 43, 64, 43);
681 XDrawLine (dpy, t, st->thick_line_gc, 73, 43, 80, 43);
682 }
683
684 XDrawPoints (dpy, t, st->copy_gc, points2, w, CoordModeOrigin);
685 free (points);
686 free (points2);
687 free (lines);
688 }
689
690 XDrawLine (dpy, t, st->copy_gc, 54, 11, 72, 22);
691
692 {
693 XPoint vertices[] = {{5, 5}, {5, 8}, {8, 8}, {8, 5}};
694 XFillPolygon (dpy, t, st->copy_gc, vertices, 4, Convex, CoordModeOrigin);
695 }
696
697 {
698 XDrawRectangle (dpy, t, st->copy_gc, 11, 11, 11, 11);
699 XFillRectangle (dpy, t, st->copy_gc, 13, 13, 8, 8);
700 }
701
702 /* Several ~16 pixel boxes in a row. */
703
704 /* Box 0 */
705 {
706 XDrawRectangle (dpy, t, st->copy_gc, 54, 54, 16, 16);
707 XDrawRectangle (dpy, t, st->copy_gc, 55, 55, 14, 14);
708
709 XDrawPoint (dpy, t, st->thick_line_gc, 56, 56);
710 XDrawPoint (dpy, t, st->copy_gc, 57, 56);
711 }
712
713 /* Box 1 */
714 XCopyArea (dpy, t, t, st->copy_gc, 55, 55, 15, 15, 72, 55);
715
716 /* Box 2 */
717 {
718 XImage *image = XGetImage(st->dpy, t, 55, 55, 15, 15, 0xffffff, ZPixmap);
719 XPutPixel(image, 2, 0, 0x00000000);
720 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 88, 55, 15, 15);
721 XDestroyImage(image);
722 }
723
724 /* Box 3 */
725
726 {
727 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
728 104, 55, 16, 16, 0, 0);
729 /* XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
730 105, 56, 14, 14, 1, 1);
731 XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
732 1, 1, 14, 14, 1, 1);
733 */
734
735 /* This point gets hidden. */
736 XDrawPoint (dpy, t, st->copy_gc, 104 + 8, 55 + 8);
737
738 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 0, 0);
739 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 1, 0);
740 XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 15, 15);
741 XDrawRectangle (dpy, st->primitives_mini_pix, st->copy_gc,
742 1, 1, 13, 13);
743 XCopyArea (dpy, st->primitives_mini_pix, t, st->copy_gc,
744 0, 0, 16, 16, 104, 55);
745 }
746
747 {
748 XDrawLine (dpy, t, st->copy_gc, 11, 28, 22, 28);
749 XDrawLine (dpy, t, st->copy_gc, 12, 27, 12, 46);
750 XDrawLine (dpy, t, st->copy_gc, 14, 30, 14, 30);
751 }
752
753 XDrawArc (dpy, t, st->copy_gc, 27, 11, 19, 11, 0, 360 * 64);
754
755 XDrawRectangle (dpy, t, st->copy_gc, 54, 73, 64, 64);
756 XFillArc (dpy, t, st->copy_gc, 56, 75, 60, 60, 0, 360 * 64);
757 /* XDrawArc (dpy, t, st->thick_line_gc, 56, 75, 60, 60, 0, 360 * 64); */
758
759 XClearArea (dpy, win, 121, 55, 16, 16, False);
760 break;
761
762 case mode_images:
763 backdrop (st, t);
764
765 /* if(w >= 9 && h >= 10) */
766 {
767 #ifdef HAVE_ANDROID
768 /* Draw below the status bar. */
769 const unsigned y = 64;
770 #else
771 const unsigned y = 0;
772 #endif
773
774 Screen *screen = st->xgwa.screen;
775 Visual *visual = st->xgwa.visual;
776 Pixmap pixmap = XCreatePixmap (dpy, t, 3, 10,
777 visual_depth (screen, visual));
778 unsigned long cells = cells = st->rgb[0] | st->rgb[1] | st->rgb[2];
779
780 {
781 XSetForeground (dpy, st->images_point_gc, st->salmon);
782 XDrawPoint (dpy, t, st->images_point_gc, 0, h - 1);
783 XDrawLine (dpy, t, st->images_point_gc, 0, y - 1, 8, y - 1);
784 }
785
786 images_pattern (st, t, y);
787 images_pattern (st, pixmap, 0);
788 /* Here's a good spot to verify that the pixmap contains the right colors
789 at the top.
790 */
791 images_copy_test (dpy, t, pixmap, st->copy_gc, y, 0, 6, cells);
792
793 XCopyArea (dpy, pixmap, t, st->copy_gc, 0, 0, 3, 10, 3, y);
794
795 {
796 XImage *image = XGetImage (dpy, pixmap, 0, 0, 3, 10, cells, ZPixmap);
797 XPutImage (dpy, t, st->copy_gc, image, 0, 0, 6, y, 3, 10);
798 XDestroyImage (image);
799 }
800
801 XFreePixmap (dpy, pixmap);
802 XSync (dpy, False);
803 }
804 break;
805
806 case mode_copy:
807 backdrop (st, win);
808
809 /* X.org isn't making a whole lot of sense here. */
810
811 Bool use_copy = (st->frame / 20) & 1;
812
813 {
814 GC gc = use_copy ? st->copy_gc : st->xor_gc;
815
816 XSetWindowBackground (dpy, t, st->magenta);
817 XCopyArea (dpy, t, t, gc, -2, -2, 40, 40, 20, 20);
818
819 if (!use_copy)
820 XCopyArea (st->dpy, t, t, gc, -20, h - 20, 40, 40, 20, h - 60);
821 XCopyArea (dpy, t, t, gc, w - 38, h - 38, 40, 40, w - 60, h - 60);
822 XCopyArea (dpy, t, t, gc, w - 20, -20, 40, 40, w - 60, 20);
823
824 XSetWindowBackground (dpy, t, st->gray50);
825 XCopyArea (st->dpy, t, t, gc, -20, 64, 40, 40, 20, 64);
826
827 XSetWindowBackground (dpy, t, st->dark_slate_gray1);
828 XCopyArea (st->dpy, t, t, gc, -20, 112, 40, 40, 20, 112);
829 }
830
831 if (use_copy)
832 {
833 GC gc = st->copy_gc;
834 XCopyArea (st->dpy, t, st->copy_pix64, gc, 0, h - 64, 64, 64, 0, 0);
835
836 XSetForeground (st->dpy, st->xor_gc, st->rgb[1]);
837 XSetBackground (st->dpy, st->xor_gc, st->cyan);
838
839 /* XCopyArea (st->dpy, st->copy_pix64, st->copy_pix64, gc,
840 32, 32, 64, 64, 0, 0);
841 XCopyArea (st->dpy, st->copy_pix64, t, gc, 0, 0, 64, 64, 4, h - 68);
842 */
843 XCopyArea (st->dpy, st->copy_pix64, t, gc, 32, 32, 128, 64, 0, h - 64);
844 }
845
846 break;
847
848 case mode_preserve:
849 backdrop (st, t);
850
851 if(!(st->frame % 10)) {
852 const unsigned r = 16;
853 unsigned n = st->frame / 10;
854 unsigned m = n >> 1;
855 XFillArc (st->dpy, st->preserve[n & 1],
856 m & 1 ? st->copy_gc : st->thick_line_gc,
857 NRAND(preserve_size) - r, NRAND(preserve_size) - r,
858 r * 2, r * 2, 0, 360 * 64);
859 }
860
861 XCopyArea (st->dpy, st->preserve[0], t, st->copy_gc, 0, 0,
862 preserve_size, preserve_size, 0, 0);
863 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
864 preserve_size, preserve_size, preserve_size, 0);
865 XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
866 preserve_size, preserve_size,
867 w - preserve_size / 2, preserve_size);
868 break;
869
870 case mode_erase:
871 if (!st->erase)
872 colorbars (st);
873 st->erase = erase_window(st->dpy, st->win, st->erase);
874 break;
875 }
876
877 /* Mode toggle buttons */
878 for (i = 1; i != mode_count; ++i) {
879 unsigned i0 = i - 1;
880 char str[32];
881 XRectangle button_dims;
882 button_dims.x = i0 * (button_pad + button_size) + button_pad;
883 button_dims.y = h - button_pad - button_size;
884 button_dims.width = button_size;
885 button_dims.height = button_size;
886 if (!st->mode)
887 XFillRectangles (dpy, t, st->backdrop_black_gc, &button_dims, 1);
888 XDrawRectangle (dpy, t, st->copy_gc, button_dims.x, button_dims.y,
889 button_dims.width, button_dims.height);
890
891 XDrawString (dpy, t, st->copy_gc,
892 button_dims.x + button_size / 2 - 3,
893 h - button_pad - button_size / 2 + 13 / 2,
894 str, sprintf(str, "%u", i));
895 }
896
897 if (t != win)
898 XCopyArea (dpy, t, win, st->copy_gc, 0, 0, w, h, 0, 0);
899
900 testx11_graph_rotator (st);
901 testx11_show_orientation (st);
902
903 ++st->frame;
904 return 1000000 / 20;
905 }
906
907 static void
testx11_reshape(Display * dpy,Window window,void * st_raw,unsigned int w,unsigned int h)908 testx11_reshape (Display *dpy, Window window, void *st_raw,
909 unsigned int w, unsigned int h)
910 {
911 struct testx11 *st = (struct testx11 *)st_raw;
912 st->xgwa.width = w;
913 st->xgwa.height = h;
914 # ifndef HAVE_JWXYZ
915 XFreePixmap (st->dpy, st->backbuffer);
916 # endif
917 create_backbuffer (st);
918 make_clip_mask (st);
919 }
920
921 static Bool
testx11_event(Display * dpy,Window window,void * st_raw,XEvent * event)922 testx11_event (Display *dpy, Window window, void *st_raw, XEvent *event)
923 {
924 struct testx11 *st = (struct testx11 *) st_raw;
925
926 Bool handled = False;
927
928 switch (event->xany.type)
929 {
930 case KeyPress:
931 {
932 KeySym keysym;
933 char c = 0;
934 XLookupString (&event->xkey, &c, 1, &keysym, 0);
935 if (c == ' ')
936 handled = toggle_antialiasing (st);
937
938 if (c >= '0' && c <= '9' && c < '0' + mode_count) {
939 st->mode = c - '0';
940 handled = True;
941 }
942 }
943 break;
944
945 case ButtonPress:
946 if (event->xbutton.y >= st->xgwa.height - button_pad * 2 - button_size) {
947 int i = (event->xbutton.x - button_pad / 2) / (button_pad + button_size) + 1;
948 if (i && i < mode_count) {
949 st->mode = i;
950 handled = True;
951 }
952 }
953
954 if (!handled)
955 handled = toggle_antialiasing (st);
956 break;
957 }
958
959 return handled;
960 }
961
962 static void
testx11_free(Display * dpy,Window window,void * st_raw)963 testx11_free (Display *dpy, Window window, void *st_raw)
964 {
965 /* Omitted for the sake of brevity. */
966 }
967
968 XSCREENSAVER_MODULE_2 ("TestX11", testx11, testx11)
969