Copy purify.fvwm2rc to /tmp - add instructions in README.
[fvwm.git] / bin / fvwm-root.c
blob796dc9a65ee42acef5d37d10af065330a06b3d4e
1 /* -*-c-*- */
2 /*
3 * This is an all new program to set the root window to an Xpm pixmap.
4 * Copyright 1993, Rob Nation
5 * You may use this file for anything you want, as long as the copyright
6 * is kept intact. No guarantees of any sort are made in any way regarding
7 * this program or anything related to it.
8 */
10 #include "config.h"
12 #include <stdio.h>
13 #include <signal.h>
14 #include <X11/Xos.h>
15 #include <X11/Xatom.h>
16 #include "libs/fvwmlib.h"
17 #include "libs/Picture.h"
18 #include "libs/Graphics.h"
19 #include "libs/Fsvg.h"
21 int save_colors = 0;
22 Display *dpy;
23 int screen;
24 Window root;
25 char *display_name = NULL;
26 Pixmap rootImage = None;
27 Bool NoDither = False;
28 Bool Dither = False;
29 Bool NoColorLimit = False;
30 int opt_color_limit = -1;
31 Bool use_our_color_limit = False;
33 void usage(int verbose)
35 FILE *output = verbose ? stdout : stderr;
36 fprintf(
37 output, "fvwm-root version %s with support for: XBM"
38 #ifdef XPM
39 ", XPM"
40 #endif
41 #ifdef HAVE_PNG
42 ", PNG"
43 #endif
44 #ifdef HAVE_RSVG
45 ", SVG"
46 #endif
47 "\n", VERSION);
48 fprintf(output,
49 "\nUsage: fvwm-root [ options ] file\n");
50 if (verbose)
52 fprintf(output,
53 "Options:\n"
54 "\t--dither\n"
55 "\t--no-dither\n"
56 "\t--retain-pixmap\n"
57 "\t--no-retain-pixmap\n"
58 "\t--color-limit l\n"
59 "\t--no-color-limit\n"
60 "\t--dummy\n"
61 "\t--no-dummy\n"
62 "\t--help\n"
63 "\t--version\n");
67 int SetRootWindow(char *tline)
69 Pixmap shapeMask = None, temp_pix = None, alpha = None;
70 int w, h;
71 int depth;
72 int nalloc_pixels = 0;
73 Pixel *alloc_pixels = NULL;
74 char *file_path;
75 FvwmPictureAttributes fpa;
77 if (use_our_color_limit)
79 PictureColorLimitOption colorLimitop = {-1, -1, -1, -1, -1};
80 colorLimitop.color_limit = opt_color_limit;
81 PictureInitCMapRoot(
82 dpy, !NoColorLimit, &colorLimitop, True, True);
84 else
86 /* this use the default visual (not the fvwm one) as
87 * getenv("FVWM_VISUALID") is NULL in any case. But this use
88 * the same color limit than fvwm.
89 * This is "broken" when fvwm use depth <= 8 and a private
90 * color map (i.e., fvwm is started with the -visual{ID}
91 * option), because when fvwm use a private color map the
92 * default color limit is 244. There is no way to know here if
93 * getenv("FVWM_VISUALID") !=NULL.
94 * So, in this unfortunate case the user should use the
95 * --color-limit option */
96 PictureInitCMap(dpy);
98 Frsvg_init();
99 /* try built-in image path first, but not before pwd */
100 PictureSetImagePath(".:+");
101 file_path = PictureFindImageFile(tline, NULL, R_OK);
103 if (file_path == NULL)
105 file_path = tline;
107 fpa.mask = FPAM_NO_ALLOC_PIXELS | FPAM_NO_ALPHA;
108 if (Pdepth <= 8 && !NoDither)
110 fpa.mask |= FPAM_DITHER;
112 else if (Pdepth <= 16 && Dither)
114 fpa.mask |= FPAM_DITHER;
116 if (NoColorLimit)
118 fpa.mask |= FPAM_NO_COLOR_LIMIT;
120 if (!PImageLoadPixmapFromFile(
121 dpy, root, file_path, &temp_pix, &shapeMask, &alpha,
122 &w, &h, &depth, &nalloc_pixels, &alloc_pixels, 0, fpa))
124 fprintf(
125 stderr, "[fvwm-root] failed to load image file '%s'\n",
126 tline);
127 return -1;
129 if (depth == Pdepth)
131 rootImage = temp_pix;
133 else
135 XGCValues gcv;
136 GC gc;
138 gcv.background= WhitePixel(dpy, screen);
139 gcv.foreground= BlackPixel(dpy, screen);
140 gc = fvwmlib_XCreateGC(
141 dpy, root, GCForeground | GCBackground, &gcv);
142 rootImage = XCreatePixmap(dpy, root, w, h, Pdepth);
143 XCopyPlane(dpy, temp_pix, rootImage, gc, 0, 0, w, h, 0, 0, 1);
144 XFreePixmap(dpy, temp_pix);
145 XFreeGC(dpy, gc);
147 XSetWindowBackgroundPixmap(dpy, root, rootImage);
148 save_colors = 1;
149 XClearWindow(dpy, root);
151 return 0;
154 int main(int argc, char **argv)
156 Atom prop = None;
157 Atom e_prop = None;
158 Atom m_prop = None;
159 Atom type;
160 int format;
161 unsigned long length, after;
162 unsigned char *data;
163 int i = 1;
164 Bool e_killed = False;
165 Bool Dummy = False;
166 Bool RetainPixmap = False;
168 if (argc < 2)
170 usage(0);
171 fprintf(stderr, "Nothing to do, try again.\n");
172 exit(1);
174 dpy = XOpenDisplay(display_name);
175 if (!dpy)
177 fprintf(
178 stderr, "fvwm-root: unable to open display '%s'\n",
179 XDisplayName (display_name));
180 exit(2);
182 screen = DefaultScreen(dpy);
183 root = RootWindow(dpy, screen);
185 for (i = 1; i < argc - 1; i++)
187 if (
188 strcasecmp(argv[i], "-r") == 0 ||
189 strcasecmp(argv[i], "--retain-pixmap") == 0)
191 RetainPixmap = True;
193 else if (
194 strcasecmp(argv[i], "--no-retain-pixmap") == 0)
196 RetainPixmap = False;
198 else if (
199 strcasecmp(argv[i], "-d") == 0 ||
200 strcasecmp(argv[i], "--dummy") == 0)
202 Dummy = True;
204 else if (
205 strcasecmp(argv[i], "--no-dummy") == 0)
207 Dummy = False;
209 else if (
210 strcasecmp(argv[i], "--dither") == 0)
212 Dither = True;
214 else if (
215 strcasecmp(argv[i], "--no-dither") == 0)
217 NoDither = True;
219 else if (
220 strcasecmp(argv[i], "--color-limit") == 0)
222 use_our_color_limit = True;
223 if (i+1 < argc)
225 i++;
226 opt_color_limit = atoi(argv[i]);
229 else if (
230 strcasecmp(argv[i], "--no-color-limit") == 0)
232 NoColorLimit = True;
234 else if (
235 strcasecmp(argv[i], "-h") == 0 ||
236 strcasecmp(argv[i], "-?") == 0 ||
237 strcasecmp(argv[i], "--help") == 0)
239 usage(1);
240 exit(0);
242 else if (
243 strcasecmp(argv[i], "-V") == 0 ||
244 strcasecmp(argv[i], "--version") == 0)
246 fprintf(stdout, "%s\n", VERSION);
247 exit(0);
249 else
251 fprintf(
252 stderr, "fvwm-root: unknown option '%s'\n",
253 argv[i]);
254 fprintf(
255 stderr, "Run '%s --help' to get the usage.\n",
256 argv[0]);
257 exit(1);
261 if (
262 Dummy ||
263 strcasecmp(argv[argc-1], "-d") == 0 ||
264 strcasecmp(argv[argc-1], "--dummy") == 0)
266 Dummy = True;
268 else if (
269 strcasecmp(argv[argc-1], "-h") == 0 ||
270 strcasecmp(argv[argc-1], "-?") == 0 ||
271 strcasecmp(argv[argc-1], "--help") == 0)
273 usage(1);
274 exit(0);
276 else if (
277 strcasecmp(argv[argc-1], "-V") == 0 ||
278 strcasecmp(argv[argc-1], "--version") == 0)
280 fprintf(stdout, "%s\n", VERSION);
281 exit(0);
283 else
285 int rc;
287 rc = SetRootWindow(argv[argc-1]);
288 if (rc == -1)
290 exit(1);
294 prop = XInternAtom(dpy, "_XSETROOT_ID", False);
295 (void)XGetWindowProperty(
296 dpy, root, prop, 0L, 1L, True, AnyPropertyType,
297 &type, &format, &length, &after, &data);
298 if (type == XA_PIXMAP && format == 32 && length == 1 && after == 0 &&
299 data != NULL && (Pixmap)(*(long *)data) != None)
301 XKillClient(dpy, *((Pixmap *)data));
304 if (data != NULL)
305 XFree(data);
306 e_prop = XInternAtom(dpy, "ESETROOT_PMAP_ID", False);
307 (void)XGetWindowProperty(
308 dpy, root, e_prop, 0L, 1L, True, AnyPropertyType,
309 &type, &format, &length, &after, &data);
310 if (type == XA_PIXMAP && format == 32 && length == 1 && after == 0 &&
311 data != NULL && (Pixmap)(*(long *)data) != None)
313 e_killed = True;
314 XKillClient(dpy, *((Pixmap *)data));
316 if (e_killed && !Dummy)
318 m_prop = XInternAtom(dpy, "_XROOTPMAP_ID", False);
319 XDeleteProperty(dpy, root, m_prop);
322 if (RetainPixmap && !Dummy)
324 long prop;
326 prop = rootImage;
327 if (data != NULL)
328 XFree(data);
329 XSetCloseDownMode(dpy, RetainPermanent);
330 if (e_prop == None)
331 e_prop = XInternAtom(dpy, "ESETROOT_PMAP_ID", False);
332 if (m_prop == None)
333 m_prop = XInternAtom(dpy, "_XROOTPMAP_ID", False);
334 XChangeProperty(
335 dpy, root, e_prop, XA_PIXMAP, 32, PropModeReplace,
336 (unsigned char *) &prop, 1);
337 XChangeProperty(
338 dpy, root, m_prop, XA_PIXMAP, 32, PropModeReplace,
339 (unsigned char *) &prop, 1);
341 else
343 long dp = (long)None;
345 if (prop == None)
346 prop = XInternAtom(dpy, "_XSETROOT_ID", False);
347 XChangeProperty(
348 dpy, root, prop, XA_PIXMAP, 32, PropModeReplace,
349 (unsigned char *) &dp, 1);
351 XCloseDisplay(dpy);
353 return 0;