From 48249418df37d7d4b174277d6c8df8415ccf80fd Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Mon, 14 Apr 2008 22:57:19 -0600 Subject: [PATCH] Added "magic" screensaver hack (B/W for now) --- Makefile | 2 +- README | 9 ++- magic.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 magic.c diff --git a/Makefile b/Makefile index 9322d03..683f461 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS = -Wall LDLIBS = -lX11 -all: xss xsswin xcursorpos +all: xss xsswin xcursorpos magic xss: LDLIBS += -lXss diff --git a/README b/README index 0268a2a..d8f3848 100644 --- a/README +++ b/README @@ -12,6 +12,9 @@ keyboard and mouse events. `xcursorpos` prints out the x and y coordinates of the cursor. +`magic` is a reimplementation of the "magic" screen saver from After +Dark. + Examples -------- @@ -25,13 +28,13 @@ Run like `xautolock`: xss xlock -mode qix & -Shell script to run an `xscreensaver` hack and `xtrlock` at the same -time, but prevent locking if the cursor is in the upper-left corner: +Shell script to run `magic` and `xtrlock` at the same time, but prevent +locking if the cursor is in the upper-left corner: #! /bin/sh xcursorpos | (read x y; [ $x -lt 20 -a $y -lt 20 ]) && exit 0 - xsswin /usr/lib/xscreensaver/qix -window-id XSS_WINDOW & + xsswin magic XSS_WINDOW & pid=$! xtrlock kill $pid diff --git a/magic.c b/magic.c new file mode 100644 index 0000000..b0073a9 --- /dev/null +++ b/magic.c @@ -0,0 +1,195 @@ +/* magic -- "Magic" (qix) screen saver hack + * Copyright (C) 2008 Neale Pickett + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include "obj.h" + +#define FPS 17 +#define TRAILPCT 50 +#define MAXDELTAPML 14 +#define MINDELTAPML 2 + +#define nsec (1000000000 / FPS) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + + +void +sum(short *a, short b, short *v, int m) +{ + *a = b + *v; + if (*a < 0) { + *a *= -1; + *v *= -1; + } else if (*a > m) { + *a = (m*2) - *a; + *v *= -1; + } +} + +int +main(int argc, char * const argv[]) +{ + Display *display; + Window w = (Window)0; + GC gc = (GC)0; + GC egc = (GC)0; + int i; + + for (i = 1; i < argc; i += 1) { + if (0 == strcmp(argv[i], "-window-id")) { + /* For compatibility reasons, just ignore */ + } else if (w) { + w = (Window)-1; + break; + } else { + char *end; + + if (argv[i][0] == '0' && argv[i][1] == 'x') { + w = (Window)strtol(argv[i] + 2, &end, 16); + } else { + w = (Window)strtol(argv[i], &end, 10); + } + if ('\0' != *end) { + w = (Window)-1; + break; + } + } + } + if ((Window)-1 == w) { + fprintf(stderr, "Usage: %s [WINDOW_ID]\n", argv[0]); + return 64; /* EX_USAGE */ + } + + try { + int screen; + Window root; + XSegment velocity, *lines; + int width, height, nlines; + + if (! (display = XOpenDisplay(NULL))) raise("cannot open display"); + screen = DefaultScreen(display); + root = RootWindow(display, screen); + + if (w) { + XWindowAttributes wa; + + XGetWindowAttributes(display, w, &wa); + width = wa.width; + height = wa.height; + } else { + XSetWindowAttributes wa; + XColor black; + + + zero(wa); + zero(black); + + wa.override_redirect = 1; + wa.background_pixel = BlackPixel(display, screen); + width = DisplayWidth(display, screen) / 3; + height = DisplayHeight(display, screen) / 3; + w = XCreateWindow(display, root, + 0, 0, + width, height, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWBackPixel, + &wa); + XMapWindow(display, w); + } + + { + XGCValues values; + + gc = XCreateGC(display, w, 0, &values); + if (! XSetForeground(display, gc, WhitePixel(display, screen))) break; + if (! XSetBackground(display, gc, BlackPixel(display, screen))) break; + + egc = XCreateGC(display, w, 0, &values); + if (! XSetForeground(display, egc, BlackPixel(display, screen))) break; + if (! XSetBackground(display, egc, WhitePixel(display, screen))) break; + } + + srandom((unsigned int)time(NULL)); + + { + int u, l; + + u = width * MAXDELTAPML / 1000; + l = width * MINDELTAPML / 1000; + velocity.x1 = (short)(random() % (u - l)) + l; + velocity.y1 = (short)(random() % (u - l)) + l; + velocity.x2 = (short)(random() % (u - l)) + l; + velocity.y2 = (short)(random() % (u - l)) + l; + } + + nlines = (width * TRAILPCT) / (max(velocity.y1, velocity.y2) * 100); + lines = (XSegment *)calloc(nlines, sizeof(XSegment)); + + lines[0].x1 = (short)(random() % width); + lines[0].y1 = (short)(random() % height); + lines[0].x2 = (short)(random() % width); + lines[0].y2 = (short)(random() % height); + + i = 0; + while (1) { + XSegment segments[2]; + struct timespec req = {0, nsec}; + int j = (i + 1) % nlines; + + (void)memcpy(segments + 0, lines + j, sizeof(XSegment)); + (void)memcpy(segments + 1, lines + j, sizeof(XSegment)); + segments[1].x1 = width - segments[0].x1; + segments[1].x2 = width - segments[0].x2; + XDrawSegments(display, (Drawable)w, egc, segments, 2); + + sum(&(lines[j].x1), lines[i].x1, &(velocity.x1), width); + sum(&(lines[j].y1), lines[i].y1, &(velocity.y1), height); + sum(&(lines[j].x2), lines[i].x2, &(velocity.x2), width); + sum(&(lines[j].y2), lines[i].y2, &(velocity.y2), height); + + (void)memcpy(segments + 0, lines + j, sizeof(XSegment)); + (void)memcpy(segments + 1, lines + j, sizeof(XSegment)); + segments[1].x1 = width - segments[0].x1; + segments[1].x2 = width - segments[0].x2; + XDrawSegments(display, (Drawable)w, gc, segments, 2); + + XSync(display, True); + + (void)nanosleep(&req, NULL); + + i = j; + } + } + + if (display) { + if (gc) { + (void)XFreeGC(display, gc); + (void)XFreeGC(display, egc); + } + (void)XCloseDisplay(display); + } + + except { + fprintf(stderr, "Error: %s\n", exception); + return 69; /* EX_UNAVAILABLE */ + } + return 0; +}