http://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996...
[xscreensaver] / driver / xscreensaver-command.c
1 /* xscreensaver-command, Copyright (c) 1991-1995 
2  * Jamie Zawinski <jwz@netscape.com>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 #include "version.h"
14 #include <stdio.h>
15 #include <X11/Xlib.h>
16 #include <X11/Xatom.h>
17 #include <X11/Xos.h>
18 #if __STDC__
19 # include <stdlib.h>
20 #endif
21
22 #ifdef _VROOT_H_
23 ERROR! you must not include vroot.h in this file
24 #endif
25
26 static char *screensaver_version;
27 static char *usage = "usage: %s -<switch>\n\
28 \n\
29   This program provides external control of a running xscreensaver process.\n\
30   Version %s, copyright (c) 1991-1994 Jamie Zawinski <jwz@netscape.com>.\n\
31 \n\
32   -demo         Enter interactive demo mode.\n\
33   -deactivate   Turns off the screensaver if it is on, as user input would.\n\
34   -activate     Turns it on as if the user had been idle for long enough.\n\
35   -cycle        Stops the current hack and runs a new one.\n\
36   -next         Like either -activate or -cycle, depending on which is more\n\
37                 appropriate, except that the screenhack that will be run is\n\
38                 the next one in the list of hacks, instead of a randomly-\n\
39                 chosen one.  This option is good for looking at a demo of\n\
40                 each of the hacks in place.\n\
41   -prev         Like -next, but goes in the other direction.\n\
42   -exit         Causes the screensaver process to exit.  It should be ok to\n\
43                 just kill the process (NOT with -9!) but this is a slightly\n\
44                 easier way.\n\
45   -restart      Causes the screensaver process to exit and then restart with\n\
46                 the same command line arguments.  This is a good way of \n\
47                 causing the screensaver to re-read the resource database.\n\
48   -lock         Same as -activate, but with immediate locking.\n\
49 \n\
50   See the man page for more details.\n\n";
51
52 static Window
53 find_screensaver_window (dpy, progname)
54      Display *dpy;
55      char *progname;
56 {
57   int i;
58   Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
59   Window root2, parent, *kids;
60   unsigned int nkids;
61
62   if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
63     abort ();
64   if (root != root2)
65     abort ();
66   if (parent)
67     abort ();
68   if (! (kids && nkids))
69     abort ();
70   for (i = 0; i < nkids; i++)
71     {
72       Atom type;
73       int format;
74       unsigned long nitems, bytesafter;
75       char *version;
76
77       if (XGetWindowProperty (dpy, kids[i],
78                               XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
79                               0, 1, False, XA_STRING,
80                               &type, &format, &nitems, &bytesafter,
81                               (unsigned char **) &version)
82           == Success
83           && type != None)
84         return kids[i];
85     }
86   fprintf (stderr, "%s: no screensaver is running on display %s\n", progname,
87            DisplayString (dpy));
88   exit (1);
89 }
90
91
92 #define USAGE() \
93  { fprintf (stderr, usage, argv[0], screensaver_version); exit (1); }
94
95 void
96 main (argc, argv)
97      int argc;
98      char **argv;
99 {
100   Display *dpy;
101   Window window;
102   XEvent event;
103   int i;
104   char *message = 0, *dpyname = 0;
105   screensaver_version = (char *) malloc (5);
106   memcpy (screensaver_version, screensaver_id + 17, 4);
107   screensaver_version [4] = 0;
108   for (i = 1; i < argc; i++)
109     {
110       char *s = argv [i];
111       int L = strlen (s);
112       if (L < 2) USAGE ();
113       if (!strncmp (s, "-display", L))          dpyname = argv [++i];
114       else if (message) USAGE ()
115       else if (!strncmp (s, "-activate", L))    message = "ACTIVATE";
116       else if (!strncmp (s, "-deactivate", L))  message = "DEACTIVATE";
117       else if (!strncmp (s, "-cycle", L))       message = "CYCLE";
118       else if (!strncmp (s, "-next", L))        message = "NEXT";
119       else if (!strncmp (s, "-prev", L))        message = "PREV";
120       else if (!strncmp (s, "-exit", L))        message = "EXIT";
121       else if (!strncmp (s, "-restart", L))     message = "RESTART";
122       else if (!strncmp (s, "-demo", L))        message = "DEMO";
123       else if (!strncmp (s, "-lock", L))        message = "LOCK";
124       else USAGE ();
125     }
126   if (! message) USAGE ();
127   if (!dpyname) dpyname = (char *) getenv ("DISPLAY");
128   dpy = XOpenDisplay (dpyname);
129   if (!dpy)
130     {
131       fprintf (stderr, "%s: can't open display %s\n", argv[0],
132                (dpyname ? dpyname : "(null)"));
133       exit (1);
134     }
135   window = find_screensaver_window (dpy, argv[0]);
136
137   event.xany.type = ClientMessage;
138   event.xclient.display = dpy;
139   event.xclient.window = window;
140   event.xclient.message_type = XInternAtom (dpy, "SCREENSAVER", False);
141   event.xclient.format = 32;
142   event.xclient.data.l[0] = (long) XInternAtom (dpy, message, False);
143   if (! XSendEvent (dpy, window, False, 0L, &event))
144     {
145       fprintf (stderr, "%s: XSendEvent(dpy, 0x%x ...) failed.\n", argv [0],
146                (unsigned int) window);
147       exit (1);
148     }
149   XSync (dpy, 0);
150   exit (0);
151 }