Neale Pickett
·
2008-04-21
xss.c
1/* xss -- xautolock replacement using MIT-SCREEN-SAVER (it doesn't poll)
2 * Copyright (C) 2008 Neale Pickett <neale@woozle.org>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <sys/wait.h>
19#include <unistd.h>
20#include <signal.h>
21#include <stdio.h>
22
23#include <X11/Xlib.h>
24#include <X11/Xatom.h>
25#include <X11/extensions/scrnsaver.h>
26
27#include "obj.h"
28
29int child = 0;
30
31void
32sigchld(int signum)
33{
34 (void)waitpid(-1, NULL, WNOHANG);
35 child = 0;
36}
37
38int
39main(int argc, char *argv[])
40{
41 Display *display = NULL;
42 int screen;
43 int bigwindow = 0;
44
45 if ((argc > 1) && (0 == (strcmp(argv[1], "-w")))) {
46 bigwindow = 1;
47 }
48 if (argc - bigwindow < 2) {
49 (void)fprintf(stderr, "Usage: %s [-w] PROGRAM [ARGUMENT ...]\n", argv[0]);
50 (void)fprintf(stderr, "\n");
51 (void)fprintf(stderr, "-w Map X server window, export $XSS_WINDOW. This window\n");
52 (void)fprintf(stderr, " will be unmapped by any keypress or mouse movement.\n");
53 return 64; /* EX_USAGE */
54 }
55 signal(SIGCHLD, sigchld);
56
57 try {
58 int ss_event, ss_error;
59 XEvent event;
60 Window root;
61 char *nargv[argc+1];
62 char id[50];
63 int i;
64
65 if (! (display = XOpenDisplay(NULL))) raise("cannot open display");
66 screen = DefaultScreen(display);
67 if (! XScreenSaverQueryExtension(display, &ss_event, &ss_error)) {
68 raise("X server does not support MIT-SCREEN-SAVER extension.");
69 }
70 if (! XScreenSaverRegister(display, screen, (XID)getpid(), XA_INTEGER)) {
71 raise("cannot register screen saver, is another one already running?");
72 }
73 root = RootWindow(display, screen);
74 XScreenSaverSelectInput(display, root, ScreenSaverNotifyMask);
75
76 {
77 XSetWindowAttributes wa;
78 XScreenSaverInfo info;
79 Pixmap pmap;
80 XColor black;
81
82 pmap = XCreateBitmapFromData(display, root, "\0", 1, 1);
83 black.pixel = BlackPixel(display, screen);
84 wa.cursor = XCreatePixmapCursor(display, pmap, pmap, &black, &black, 0, 0);
85 wa.background_pixel = BlackPixel(display, screen);
86 if (! (XFreePixmap(display, pmap))) break;
87 XScreenSaverSetAttributes(display, root,
88 bigwindow?0:-1, bigwindow?0:-1,
89 bigwindow?DisplayWidth(display, screen):1,
90 bigwindow?DisplayHeight(display, screen):1,
91 0,
92 CopyFromParent, CopyFromParent,
93 CopyFromParent,
94 CWBackPixel | CWCursor,
95 &wa);
96 XScreenSaverQueryInfo(display, (Drawable)root, &info);
97 (void)snprintf(id, sizeof(id), "0x%lx", (unsigned long)info.window);
98 (void)setenv("XSS_WINDOW", id, 1);
99 }
100
101 for (i = 0; i < argc; i += 1) {
102 if (bigwindow && (0 == strcmp(argv[i], "XSS_WINDOW"))) {
103 nargv[i] = id;
104 } else {
105 nargv[i] = argv[i];
106 }
107 }
108 nargv[argc] = NULL;
109
110 while (! XNextEvent(display, &event)) {
111 if (ss_event == event.type) {
112 XScreenSaverNotifyEvent *sevent = (XScreenSaverNotifyEvent *)&event;
113
114 if (ScreenSaverOn == sevent->state) {
115 if (! child) {
116 child = fork();
117 if (0 == child) {
118 (void)execvp(nargv[1+bigwindow], nargv+1+bigwindow);
119 perror("exec");
120 exit(1);
121 }
122 } else {
123 }
124 }
125 }
126 }
127 } while (0);
128
129 if (display) {
130 (void)XScreenSaverUnregister(display, screen);
131 (void)XCloseDisplay(display);
132 }
133
134 except {
135 (void)fprintf(stderr, "Error: %s\n", exception);
136 return 69; /* EX_UNAVAILABLE */
137 }
138
139 return 0;
140}