PageRenderTime 130ms CodeModel.GetById 42ms RepoModel.GetById 1ms app.codeStats 0ms

/hacks/lcdscrub.c

https://github.com/mmehnert/xscreensaver
C | 241 lines | 202 code | 24 blank | 15 comment | 13 complexity | 20eccae3f89641d2da734dc6fe064d6c MD5 | raw file
  1. /* xscreensaver, Copyright (c) 2008-2013 Jamie Zawinski <jwz@jwz.org>
  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. * 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/
  14. */
  15. #include "screenhack.h"
  16. #undef countof
  17. #define countof(x) (sizeof((x))/sizeof((*x)))
  18. struct state {
  19. Display *dpy;
  20. Window window;
  21. XWindowAttributes xgwa;
  22. enum { HORIZ_W, HORIZ_B,
  23. VERT_W, VERT_B,
  24. DIAG_W, DIAG_B,
  25. WHITE, BLACK,
  26. RGB,
  27. END } mode;
  28. unsigned int enabled_mask;
  29. int count;
  30. GC fg, bg, bg2;
  31. int color_tick;
  32. int delay;
  33. int spread;
  34. int cycles;
  35. };
  36. static void
  37. pick_mode (struct state *st)
  38. {
  39. st->count = 0;
  40. while (1)
  41. {
  42. if (++st->mode == END)
  43. st->mode = 0;
  44. if (st->enabled_mask & (1 << st->mode))
  45. break;
  46. }
  47. }
  48. static void *
  49. lcdscrub_init (Display *dpy, Window window)
  50. {
  51. struct state *st = (struct state *) calloc (1, sizeof(*st));
  52. XGCValues gcv;
  53. st->dpy = dpy;
  54. st->window = window;
  55. st->delay = get_integer_resource (st->dpy, "delay", "Integer");
  56. st->spread = get_integer_resource (st->dpy, "spread", "Integer");
  57. st->cycles = get_integer_resource (st->dpy, "cycles", "Integer");
  58. XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
  59. gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
  60. gcv.background = WhitePixelOfScreen (st->xgwa.screen);
  61. st->bg = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
  62. st->bg2 = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
  63. gcv.foreground = WhitePixelOfScreen (st->xgwa.screen);
  64. gcv.background = BlackPixelOfScreen (st->xgwa.screen);
  65. st->fg = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
  66. #ifdef HAVE_COCOA
  67. jwxyz_XSetAntiAliasing (st->dpy, st->fg, False);
  68. jwxyz_XSetAntiAliasing (st->dpy, st->bg, False);
  69. jwxyz_XSetAntiAliasing (st->dpy, st->bg2, False);
  70. #endif
  71. st->enabled_mask = 0;
  72. # define PREF(R,F) \
  73. if (get_boolean_resource (st->dpy, R, "Mode")) st->enabled_mask |= (1 << F)
  74. PREF("modeHW", HORIZ_W);
  75. PREF("modeHB", HORIZ_B);
  76. PREF("modeVW", VERT_W);
  77. PREF("modeVB", VERT_B);
  78. PREF("modeDW", DIAG_W);
  79. PREF("modeDB", DIAG_B);
  80. PREF("modeW", WHITE);
  81. PREF("modeB", BLACK);
  82. PREF("modeRGB", RGB);
  83. # undef PREF
  84. if (! st->enabled_mask)
  85. {
  86. fprintf (stderr, "%s: no modes enabled\n", progname);
  87. exit (1);
  88. }
  89. pick_mode (st);
  90. return st;
  91. }
  92. static unsigned long
  93. lcdscrub_draw (Display *dpy, Window window, void *closure)
  94. {
  95. struct state *st = (struct state *) closure;
  96. int count = st->count % st->spread;
  97. int i;
  98. GC fg = (st->mode & 1 ? st->fg : st->bg);
  99. GC bg = (st->mode & 1 ? st->bg : st->fg);
  100. switch (st->mode) {
  101. case HORIZ_W:
  102. case HORIZ_B:
  103. XFillRectangle (st->dpy, st->window, bg, 0, 0,
  104. st->xgwa.width, st->xgwa.height);
  105. for (i = count; i < st->xgwa.height; i += st->spread)
  106. XDrawLine (st->dpy, st->window, fg, 0, i, st->xgwa.width, i);
  107. break;
  108. case VERT_W:
  109. case VERT_B:
  110. XFillRectangle (st->dpy, st->window, bg, 0, 0,
  111. st->xgwa.width, st->xgwa.height);
  112. for (i = count; i < st->xgwa.width; i += st->spread)
  113. XDrawLine (st->dpy, st->window, fg, i, 0, i, st->xgwa.height);
  114. break;
  115. case DIAG_W:
  116. case DIAG_B:
  117. XFillRectangle (st->dpy, st->window, bg, 0, 0,
  118. st->xgwa.width, st->xgwa.height);
  119. for (i = count; i < st->xgwa.width; i += st->spread)
  120. XDrawLine (st->dpy, st->window, fg, i, 0,
  121. i + st->xgwa.width, st->xgwa.width);
  122. for (i = -count; i < st->xgwa.height; i += st->spread)
  123. XDrawLine (st->dpy, st->window, fg, 0, i,
  124. st->xgwa.height, i + st->xgwa.height);
  125. break;
  126. case RGB:
  127. {
  128. int scale = 10 * 8; /* 8 sec */
  129. static const unsigned short colors[][3] = {
  130. { 0xFFFF, 0x0000, 0x0000 },
  131. { 0x0000, 0xFFFF, 0x0000 },
  132. { 0x0000, 0x0000, 0xFFFF },
  133. { 0xFFFF, 0xFFFF, 0x0000 },
  134. { 0xFFFF, 0x0000, 0xFFFF },
  135. { 0x0000, 0xFFFF, 0xFFFF },
  136. { 0xFFFF, 0xFFFF, 0xFFFF },
  137. { 0x0000, 0x0000, 0x0000 },
  138. };
  139. static unsigned long last = 0;
  140. XColor xc;
  141. bg = st->bg2;
  142. xc.red = colors[st->color_tick / scale][0];
  143. xc.green = colors[st->color_tick / scale][1];
  144. xc.blue = colors[st->color_tick / scale][2];
  145. if (last) XFreeColors (st->dpy, st->xgwa.colormap, &last, 1, 0);
  146. XAllocColor (st->dpy, st->xgwa.colormap, &xc);
  147. last = xc.pixel;
  148. XSetForeground (st->dpy, bg, xc.pixel);
  149. st->color_tick = (st->color_tick + 1) % (countof(colors) * scale);
  150. /* fall through */
  151. }
  152. case WHITE:
  153. case BLACK:
  154. XFillRectangle (st->dpy, st->window, bg, 0, 0,
  155. st->xgwa.width, st->xgwa.height);
  156. break;
  157. default:
  158. abort();
  159. break;
  160. }
  161. st->count++;
  162. if (st->count > st->spread * st->cycles)
  163. pick_mode (st);
  164. return st->delay;
  165. }
  166. static void
  167. lcdscrub_reshape (Display *dpy, Window window, void *closure,
  168. unsigned int w, unsigned int h)
  169. {
  170. }
  171. static Bool
  172. lcdscrub_event (Display *dpy, Window window, void *closure, XEvent *event)
  173. {
  174. return False;
  175. }
  176. static void
  177. lcdscrub_free (Display *dpy, Window window, void *closure)
  178. {
  179. struct state *st = (struct state *) closure;
  180. XFreeGC (dpy, st->fg);
  181. XFreeGC (dpy, st->bg);
  182. XFreeGC (dpy, st->bg2);
  183. free (st);
  184. }
  185. static const char *lcdscrub_defaults [] = {
  186. ".background: black",
  187. ".foreground: white",
  188. "*delay: 100000",
  189. "*spread: 8",
  190. "*cycles: 60",
  191. "*modeHW: True",
  192. "*modeHB: True",
  193. "*modeVW: True",
  194. "*modeVB: True",
  195. "*modeDW: True",
  196. "*modeDB: True",
  197. "*modeW: True",
  198. "*modeB: True",
  199. "*modeRGB: True",
  200. 0
  201. };
  202. static XrmOptionDescRec lcdscrub_options [] = {
  203. { "-delay", ".delay", XrmoptionSepArg, 0 },
  204. { "-spread", ".spread", XrmoptionSepArg, 0 },
  205. { "-cycles", ".cycles", XrmoptionSepArg, 0 },
  206. { "-no-hw", ".modeHW", XrmoptionNoArg, "False" },
  207. { "-no-hb", ".modeHB", XrmoptionNoArg, "False" },
  208. { "-no-vw", ".modeVW", XrmoptionNoArg, "False" },
  209. { "-no-vb", ".modeVB", XrmoptionNoArg, "False" },
  210. { "-no-dw", ".modeDW", XrmoptionNoArg, "False" },
  211. { "-no-db", ".modeDB", XrmoptionNoArg, "False" },
  212. { "-no-w", ".modeW", XrmoptionNoArg, "False" },
  213. { "-no-b", ".modeB", XrmoptionNoArg, "False" },
  214. { "-no-rgb", ".modeRGB", XrmoptionNoArg, "False" },
  215. { 0, 0, 0, 0 }
  216. };
  217. XSCREENSAVER_MODULE ("LCDscrub", lcdscrub)