1 /* xscreensaver, Copyright (c) 2008-2013 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
11 * Draws repetitive patterns that should undo burned in LCD screens.
12 * Concept shamelessly cloned from
13 * http://toastycode.com/blog/2008/02/05/lcd-scrub/
16 #include "screenhack.h"
19 #define countof(x) (sizeof((x))/sizeof((*x)))
24 XWindowAttributes xgwa;
25 enum { HORIZ_W, HORIZ_B,
31 unsigned int enabled_mask;
42 pick_mode (struct state *st)
47 if (++st->mode == END)
49 if (st->enabled_mask & (1 << st->mode))
55 lcdscrub_init (Display *dpy, Window window)
57 struct state *st = (struct state *) calloc (1, sizeof(*st));
61 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
62 st->spread = get_integer_resource (st->dpy, "spread", "Integer");
63 st->cycles = get_integer_resource (st->dpy, "cycles", "Integer");
65 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
66 gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
67 gcv.background = WhitePixelOfScreen (st->xgwa.screen);
68 st->bg = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
69 st->bg2 = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
70 gcv.foreground = WhitePixelOfScreen (st->xgwa.screen);
71 gcv.background = BlackPixelOfScreen (st->xgwa.screen);
72 st->fg = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
75 jwxyz_XSetAntiAliasing (st->dpy, st->fg, False);
76 jwxyz_XSetAntiAliasing (st->dpy, st->bg, False);
77 jwxyz_XSetAntiAliasing (st->dpy, st->bg2, False);
82 if (get_boolean_resource (st->dpy, R, "Mode")) st->enabled_mask |= (1 << F)
83 PREF("modeHW", HORIZ_W);
84 PREF("modeHB", HORIZ_B);
85 PREF("modeVW", VERT_W);
86 PREF("modeVB", VERT_B);
87 PREF("modeDW", DIAG_W);
88 PREF("modeDB", DIAG_B);
93 if (! st->enabled_mask)
95 fprintf (stderr, "%s: no modes enabled\n", progname);
105 lcdscrub_draw (Display *dpy, Window window, void *closure)
107 struct state *st = (struct state *) closure;
108 int count = st->count % st->spread;
110 GC fg = (st->mode & 1 ? st->fg : st->bg);
111 GC bg = (st->mode & 1 ? st->bg : st->fg);
116 XFillRectangle (st->dpy, st->window, bg, 0, 0,
117 st->xgwa.width, st->xgwa.height);
118 for (i = count; i < st->xgwa.height; i += st->spread)
119 XDrawLine (st->dpy, st->window, fg, 0, i, st->xgwa.width, i);
123 XFillRectangle (st->dpy, st->window, bg, 0, 0,
124 st->xgwa.width, st->xgwa.height);
125 for (i = count; i < st->xgwa.width; i += st->spread)
126 XDrawLine (st->dpy, st->window, fg, i, 0, i, st->xgwa.height);
130 XFillRectangle (st->dpy, st->window, bg, 0, 0,
131 st->xgwa.width, st->xgwa.height);
132 for (i = count; i < st->xgwa.width; i += st->spread)
133 XDrawLine (st->dpy, st->window, fg, i, 0,
134 i + st->xgwa.width, st->xgwa.width);
135 for (i = -count; i < st->xgwa.height; i += st->spread)
136 XDrawLine (st->dpy, st->window, fg, 0, i,
137 st->xgwa.height, i + st->xgwa.height);
141 int scale = 10 * 8; /* 8 sec */
142 static const unsigned short colors[][3] = {
143 { 0xFFFF, 0x0000, 0x0000 },
144 { 0x0000, 0xFFFF, 0x0000 },
145 { 0x0000, 0x0000, 0xFFFF },
146 { 0xFFFF, 0xFFFF, 0x0000 },
147 { 0xFFFF, 0x0000, 0xFFFF },
148 { 0x0000, 0xFFFF, 0xFFFF },
149 { 0xFFFF, 0xFFFF, 0xFFFF },
150 { 0x0000, 0x0000, 0x0000 },
152 static unsigned long last = 0;
155 xc.red = colors[st->color_tick / scale][0];
156 xc.green = colors[st->color_tick / scale][1];
157 xc.blue = colors[st->color_tick / scale][2];
158 if (last) XFreeColors (st->dpy, st->xgwa.colormap, &last, 1, 0);
159 XAllocColor (st->dpy, st->xgwa.colormap, &xc);
161 XSetForeground (st->dpy, bg, xc.pixel);
162 st->color_tick = (st->color_tick + 1) % (countof(colors) * scale);
167 XFillRectangle (st->dpy, st->window, bg, 0, 0,
168 st->xgwa.width, st->xgwa.height);
177 if (st->count > st->spread * st->cycles)
184 lcdscrub_reshape (Display *dpy, Window window, void *closure,
185 unsigned int w, unsigned int h)
190 lcdscrub_event (Display *dpy, Window window, void *closure, XEvent *event)
196 lcdscrub_free (Display *dpy, Window window, void *closure)
198 struct state *st = (struct state *) closure;
199 XFreeGC (dpy, st->fg);
200 XFreeGC (dpy, st->bg);
201 XFreeGC (dpy, st->bg2);
206 static const char *lcdscrub_defaults [] = {
207 ".background: black",
208 ".foreground: white",
224 static XrmOptionDescRec lcdscrub_options [] = {
225 { "-delay", ".delay", XrmoptionSepArg, 0 },
226 { "-spread", ".spread", XrmoptionSepArg, 0 },
227 { "-cycles", ".cycles", XrmoptionSepArg, 0 },
228 { "-no-hw", ".modeHW", XrmoptionNoArg, "False" },
229 { "-no-hb", ".modeHB", XrmoptionNoArg, "False" },
230 { "-no-vw", ".modeVW", XrmoptionNoArg, "False" },
231 { "-no-vb", ".modeVB", XrmoptionNoArg, "False" },
232 { "-no-dw", ".modeDW", XrmoptionNoArg, "False" },
233 { "-no-db", ".modeDB", XrmoptionNoArg, "False" },
234 { "-no-w", ".modeW", XrmoptionNoArg, "False" },
235 { "-no-b", ".modeB", XrmoptionNoArg, "False" },
236 { "-no-rgb", ".modeRGB", XrmoptionNoArg, "False" },
241 XSCREENSAVER_MODULE ("LCDscrub", lcdscrub)