1 /* $Id: wmpal.c 35 2007-07-05 14:05:18Z danadocus $ */
2 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- */
3 /*  wmpal - a useless DockApp
4  *  Copyright (C) 2000      Hadess <hadess@writeme.com>
5  *  Copyright (C) 2001-2004 A.Sleep <a.sleep@asleep.net>
6  *  Copyright (C) 2007      Dana Jansens <danakj@orodu.net>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include "xpms.h"
23 
24 #include <X11/Xlib.h>
25 #include <X11/xpm.h>
26 #include <unistd.h> /* for sleep() */
27 #include <stdlib.h> /* for rand() */
28 #include <time.h>   /* for time() */
29 #include <string.h>
30 #include <stdio.h>
31 
32 #define MAX_SLEEP_TIME 5
33 
34 char *displayName = NULL;
35 char *palName = "daemon";
36 int windowed = 0;
37 int nodecor = 0;
38 int below = 0;
39 int all = 0;
40 
41 static void print_version();
42 static void print_help();
43 static void parse_args(int argc, char **argv);
44 static Window create_window(Display *d, const char *name, int w, int h,
45                             int windowed, int nodecor, int below, int all);
46 static int load_pixmap(Display *d, char **data, Pixmap *xpm);
47 
main(int argc,char ** argv)48 int main(int argc, char **argv)
49 {
50     Display *d;
51     Window win;
52     Pixmap bg;
53     Pixmap pixanim[3];
54 
55     parse_args(argc, argv);
56     srand(time(NULL));
57 
58     if (!(d = XOpenDisplay(displayName))) {
59         fprintf(stderr, "Unable to open the X display\n");
60         exit(EXIT_FAILURE);
61     }
62 
63     win = create_window(d, "wmpal", 50, 50, windowed, nodecor, below, all);
64 
65     switch (palName[0]) {
66     case 'd':
67         if (palName[1] == 'i') {
68             load_pixmap(d, dino1_xpm, &pixanim[0]);
69             load_pixmap(d, dino2_xpm, &pixanim[1]);
70             load_pixmap(d, dino3_xpm, &pixanim[2]);
71         }
72         else {
73             load_pixmap(d, demon1_xpm, &pixanim[0]);
74             load_pixmap(d, demon2_xpm, &pixanim[1]);
75             load_pixmap(d, demon3_xpm, &pixanim[2]);
76         }
77         break;
78     case 'g':
79         load_pixmap(d, grape1_xpm, &pixanim[0]);
80         load_pixmap(d, grape2_xpm, &pixanim[1]);
81         load_pixmap(d, grape3_xpm, &pixanim[2]);
82         break;
83     case 'p':
84         load_pixmap(d, pear1_xpm, &pixanim[0]);
85         load_pixmap(d, pear2_xpm, &pixanim[1]);
86         load_pixmap(d, pear3_xpm, &pixanim[2]);
87         break;
88     case 's':
89         if (palName[1] == 'u') {
90             load_pixmap(d, sun1_xpm, &pixanim[0]);
91             load_pixmap(d, sun2_xpm, &pixanim[1]);
92             load_pixmap(d, sun3_xpm, &pixanim[2]);
93         } else {
94             load_pixmap(d, snail1_xpm, &pixanim[0]);
95             load_pixmap(d, snail2_xpm, &pixanim[1]);
96             load_pixmap(d, snail1_xpm, &pixanim[2]);
97         }
98         break;
99     case 't':
100         load_pixmap(d, turtle1_xpm, &pixanim[0]);
101         load_pixmap(d, turtle2_xpm, &pixanim[1]);
102         load_pixmap(d, turtle3_xpm, &pixanim[2]);
103         break;
104     }
105 
106     load_pixmap(d, bg_xpm, &bg);
107     XSetWindowBackgroundPixmap(d, win, bg);
108     XMapWindow(d, win);
109 
110     while (1) {
111         static int anim_pos = -1;
112 
113         if (anim_pos < 2) ++anim_pos;
114         else              anim_pos = 0;
115 
116         XCopyArea(d, pixanim[anim_pos], bg, DefaultGC(d, DefaultScreen(d)),
117                   0, 0, 48, 48, 1, 1);
118         XClearWindow(d, win);
119         XFlush(d);
120 
121         /* sleep for a random time */
122         sleep(rand() % (MAX_SLEEP_TIME-1) + 1);
123     }
124 
125     return 0;
126 }
127 
print_version()128 static void print_version()
129 {
130     const char *version =
131 "wmpal " VERSION "\n"
132 "\n"
133 "Copyright (C) 2007      Dana Jansens <danakj@orodu.net>\n"
134 "Copyright (C) 2001-2004 A.Sleep <a.sleep@asleep.net>\n"
135 "Copyright (C) 2000      Hadess <hadess@writeme.com>\n"
136 "\n";
137 
138     printf("%s", version);
139 }
140 
print_help()141 static void print_help()
142 {
143     const char *help =
144 "Usage: wmpal [OPTIONS]\n"
145 "\n"
146 "  -d, --display <string>       Display to use\n"
147 "  -p, --pal <string>           Which pal to use\n"
148 "  -w, --windowed               runs the application in windowed mode\n"
149 "  -n, --nodecor                removes any decorations in windowed mode\n"
150 "  -b, --below                  keeps the window below others in windowed mode\n"
151 "  -a, --all                    show wmpal on all desktops\n"
152 "  -h, --help                   shows this help text and exit\n"
153 "  -v, --version                shows program version and exit\n"
154 "\n"
155 "Available pals are: demon, dino, grape, pear, snail, sun or turtle\n"
156 "\n";
157 
158     printf("%s", help);
159 }
160 
parse_args(int argc,char ** argv)161 static void parse_args(int argc, char **argv)
162 {
163     int i;
164     for (i = 1; i < argc; ++i) {
165         if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--display")) {
166             if (i == argc - 1) /* no args left */
167                 /* not translated cuz it's sekret */
168                 printf("--display requires an argument\n");
169             else
170                 displayName = argv[++i];
171         }
172         else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--pal")) {
173             if (i == argc - 1) /* no args left */
174                 /* not translated cuz it's sekret */
175                 printf("--pal requires an argument\n");
176             else
177                 palName = argv[++i];
178         }
179         else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--windowed")) {
180             windowed = 1;
181         }
182         else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--nodecor")) {
183             nodecor = 1;
184         }
185         else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--below")) {
186             below = 1;
187         }
188         else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--all")) {
189             all = 1;
190         }
191         else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
192             print_help();
193             exit(EXIT_SUCCESS);
194         }
195         else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
196             print_version();
197             exit(EXIT_SUCCESS);
198         }
199     }
200 }
201 
202 #define MWM_FLAG_FUNCTIONS   (1 << 0)
203 #define MWM_FLAG_DECORATIONS (1 << 1)
204 
create_window(Display * d,const char * name,int w,int h,int windowed,int nodecor,int below,int all)205 static Window create_window(Display *d, const char *name, int w, int h,
206                             int windowed, int nodecor, int below, int all)
207 {
208     Window win;
209     int s = DefaultScreen(d);
210 
211     win = XCreateWindow(d, RootWindow(d, s), 0, 0, w, h, 0,
212                         DefaultDepth(d, s), InputOutput, DefaultVisual(d, s),
213                         0, NULL);
214 
215     if (!windowed) {
216         XWMHints *hint = XAllocWMHints();
217         hint->flags = StateHint;
218         hint->initial_state = WithdrawnState;
219         XSetWMHints(d, win, hint);
220         XFree(hint);
221     }
222     else {
223         long state[3];
224         int n = 0;
225 
226         if (nodecor) {
227             long mwm[3];
228             mwm[0] = MWM_FLAG_DECORATIONS;
229             mwm[2] = 0; /* no decorations */
230             XChangeProperty(d, win,
231                             XInternAtom(d, "_MOTIF_WM_HINTS", False),
232                             XInternAtom(d, "_MOTIF_WM_HINTS", False),
233                             32, PropModeReplace, (unsigned char*) mwm, 3);
234 
235             /* set these when no decor is on */
236             state[n++] = XInternAtom(d, "_NET_WM_STATE_SKIP_TASKBAR", False);
237             state[n++] = XInternAtom(d, "_NET_WM_STATE_SKIP_PAGER", False);
238         }
239 
240         if (below)
241             state[n++] = XInternAtom(d, "_NET_WM_STATE_BELOW", False);
242         if (n)
243             XChangeProperty(d, win,
244                             XInternAtom(d, "_NET_WM_STATE", False),
245                             XInternAtom(d, "ATOM", False),
246                             32, PropModeReplace, (unsigned char*) state, n);
247 
248         if (all) {
249             long a[1] = { 0xffffffff };
250             XChangeProperty(d, win,
251                             XInternAtom(d, "_NET_WM_DESKTOP", False),
252                             XInternAtom(d, "CARDINAL", False),
253                             32, PropModeReplace, (unsigned char*) a, 1);
254         }
255     }
256 
257     {
258         XClassHint c;
259         c.res_name = "wmpal";
260         c.res_class = "WMPal";
261         XSetClassHint(d, win, &c);
262     }
263 
264     return win;
265 }
266 
load_pixmap(Display * d,char ** data,Pixmap * xpm)267 static int load_pixmap(Display *d, char **data, Pixmap *xpm)
268 {
269     Pixmap mask;
270     unsigned short w, h;
271     XpmAttributes at;
272 
273     at.valuemask = XpmCloseness;
274     at.closeness = 40000;
275 
276     return XpmCreatePixmapFromData(d, RootWindow(d, DefaultScreen(d)),
277                                    data, xpm, &mask, &at) == 0;
278 }
279 
280