took bsetroot from Blackbox moving_target.. "bsetroot now sets xrootpmap_id, pseudo...
[mikachu/openbox.git] / util / bsetroot.cc
1 #ifdef    HAVE_CONFIG_H
2 #  include "../config.h"
3 #endif // HAVE_CONFIG_H
4
5 #ifdef    STDC_HEADERS
6 #  include <string.h>
7 #  include <stdlib.h>
8 #endif // STDC_HEADERS
9
10 #ifdef    HAVE_STDIO_H
11 #  include <stdio.h>
12 #endif // HAVE_STDIO_H
13
14 #include "../src/i18n.h"
15 #include "../src/BaseDisplay.h"
16 #include "../src/Image.h"
17 #include "bsetroot.h"
18
19
20 bsetroot::bsetroot(int argc, char **argv, char *dpy_name)
21   : BaseDisplay(argv[0], dpy_name)
22 {
23   grad = fore = back = (char *) 0;
24
25   Bool mod = False, sol = False, grd = False;
26   int mod_x = 0, mod_y = 0;
27
28   for (int i = 1; i < argc; i++) {
29     if (! strcmp("-help", argv[i])) {
30       usage();
31     } else if ((! strcmp("-fg", argv[i])) ||
32                (! strcmp("-foreground", argv[i])) ||
33                (! strcmp("-from", argv[i]))) {
34       if ((++i) >= argc) usage(1);
35
36       fore = argv[i];
37     } else if ((! strcmp("-bg", argv[i])) ||
38                (! strcmp("-background", argv[i])) ||
39                (! strcmp("-to", argv[i]))) {
40       if ((++i) >= argc) usage(1);
41
42       back = argv[i];
43     } else if (! strcmp("-solid", argv[i])) {
44       if ((++i) >= argc) usage(1);
45
46       fore = argv[i];
47       sol = True;
48     } else if (! strcmp("-mod", argv[i])) {
49       if ((++i) >= argc) usage();
50
51       mod_x = atoi(argv[i]);
52
53       if ((++i) >= argc) usage();
54
55       mod_y = atoi(argv[i]);
56
57       if (mod_x < 1) mod_x = 1;
58       if (mod_y < 1) mod_y = 1;
59
60       mod = True;
61     } else if (! strcmp("-gradient", argv[i])) {
62       if ((++i) >= argc) usage();
63
64       grad = argv[i];
65       grd = True;
66     } else if (! strcmp("-display", argv[i])) {
67       // -display passed through tests ealier... we just skip it now
68       i++;
69     } else
70       usage();
71   }
72
73   if ((mod + sol + grd) != True) {
74     fprintf(stderr,
75             i18n->getMessage(bsetrootSet, bsetrootMustSpecify,
76                   "%s: error: must specify one of: -solid, -mod, -gradient\n"),
77             getApplicationName());
78     
79     usage(2);
80   }
81   
82   img_ctrl = new BImageControl*[getNumberOfScreens()];
83   for (int i = 0; i < getNumberOfScreens(); i++)
84     img_ctrl[i] = new BImageControl(*this, *getScreenInfo(i), True);
85
86   if (sol && fore) solid();
87   else if (mod && mod_x && mod_y && fore && back) modula(mod_x, mod_y);
88   else if (grd && grad && fore && back) gradient();
89   else usage();
90 }
91
92
93 bsetroot::~bsetroot(void) {
94   XSetCloseDownMode(getXDisplay(), RetainPermanent);
95
96   XKillClient(getXDisplay(), AllTemporary);
97
98   for (int i = 0; i < getNumberOfScreens(); i++)
99     delete img_ctrl[i];
100
101   delete [] img_ctrl;
102 }
103
104 // adapted from wmsetbg
105 void bsetroot::setPixmapProperty(int screen, Pixmap pixmap) {
106   static Atom rootpmap_id = None;
107   Atom type;
108   int format;
109   unsigned long length, after;
110   unsigned char *data;
111   int mode;
112   
113   if (rootpmap_id == None)
114     rootpmap_id = XInternAtom(getXDisplay(), "_XROOTPMAP_ID", False);
115
116   XGrabServer(getXDisplay());
117   
118   /* Clear out the old pixmap */
119   XGetWindowProperty(getXDisplay(), getScreenInfo(screen)->getRootWindow(),
120                      rootpmap_id, 0L, 1L, False, AnyPropertyType,
121                      &type, &format, &length, &after, &data);
122   
123   if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
124     XKillClient(getXDisplay(), *((Pixmap *)data));
125     XSync(getXDisplay(), False);
126     mode = PropModeReplace;
127   } else {
128     mode = PropModeAppend;
129   }
130   if (pixmap) {
131     XChangeProperty(getXDisplay(), getScreenInfo(screen)->getRootWindow(),
132                     rootpmap_id, XA_PIXMAP, 32, mode,
133                     (unsigned char *) &pixmap, 1);
134   } else {
135     XDeleteProperty(getXDisplay(), getScreenInfo(screen)->getRootWindow(),
136                     rootpmap_id);
137   }
138   
139   XUngrabServer(getXDisplay());
140   XFlush(getXDisplay());
141 }
142
143
144 // adapted from wmsetbg
145 Pixmap bsetroot::duplicatePixmap(int screen, Pixmap pixmap,
146                                  int width, int height) {
147   XSync(getXDisplay(), False);
148
149   Pixmap copyP = XCreatePixmap(getXDisplay(),
150                                getScreenInfo(screen)->getRootWindow(),
151                                width, height,
152                                DefaultDepth(getXDisplay(), screen));
153   XCopyArea(getXDisplay(), pixmap, copyP, DefaultGC(getXDisplay(), screen),
154             0, 0, width, height, 0, 0);
155   XSync(getXDisplay(), False);
156
157   return copyP;
158 }
159
160
161 void bsetroot::solid(void) {
162   for (int screen = 0; screen < getNumberOfScreens(); screen++) {
163     BColor c;
164
165     img_ctrl[screen]->parseColor(&c, fore);
166     if (! c.isAllocated()) c.setPixel(BlackPixel(getXDisplay(), screen));
167
168     XSetWindowBackground(getXDisplay(), getScreenInfo(screen)->getRootWindow(),
169                          c.getPixel());
170     XClearWindow(getXDisplay(), getScreenInfo(screen)->getRootWindow());
171
172     Pixmap pixmap = XCreatePixmap(getXDisplay(),
173                                   getScreenInfo(screen)->getRootWindow(),
174                                   8, 8, DefaultDepth(getXDisplay(), screen));
175     XSetForeground(getXDisplay(), DefaultGC(getXDisplay(), screen),
176                    c.getPixel());
177     XFillRectangle(getXDisplay(), pixmap, DefaultGC(getXDisplay(), screen),
178                    0, 0, 8, 8);
179
180     setPixmapProperty(screen, duplicatePixmap(screen, pixmap, 8, 8));
181
182     XFreePixmap(getXDisplay(), pixmap);
183   }
184 }
185
186
187 void bsetroot::modula(int x, int y) {
188   char data[32];
189   long pattern;
190
191   int screen, i;
192
193   for (pattern = 0, screen = 0; screen < getNumberOfScreens(); screen++) {
194     for (i = 0; i < 16; i++) {
195       pattern <<= 1;
196       if ((i % x) == 0)
197         pattern |= 0x0001;
198     }
199
200     for (i = 0; i < 16; i++) {
201       if ((i %  y) == 0) {
202         data[(i * 2)] = (char) 0xff;
203         data[(i * 2) + 1] = (char) 0xff;
204       } else {
205         data[(i * 2)] = pattern & 0xff;
206         data[(i * 2) + 1] = (pattern >> 8) & 0xff;
207       }
208     }
209
210     BColor f, b;
211     GC gc;
212     Pixmap bitmap;
213     XGCValues gcv;
214
215     bitmap =
216       XCreateBitmapFromData(getXDisplay(),
217                             getScreenInfo(screen)->getRootWindow(), data,
218                             16, 16);
219
220     img_ctrl[screen]->parseColor(&f, fore);
221     img_ctrl[screen]->parseColor(&b, back);
222
223     if (! f.isAllocated()) f.setPixel(WhitePixel(getXDisplay(), screen));
224     if (! b.isAllocated()) b.setPixel(BlackPixel(getXDisplay(), screen));
225
226     gcv.foreground = f.getPixel();
227     gcv.background = b.getPixel();
228
229     gc = XCreateGC(getXDisplay(), getScreenInfo(screen)->getRootWindow(),
230                    GCForeground | GCBackground, &gcv);
231
232     Pixmap pixmap = XCreatePixmap(getXDisplay(),
233                                   getScreenInfo(screen)->getRootWindow(),
234                                   16, 16, getScreenInfo(screen)->getDepth());
235
236     XCopyPlane(getXDisplay(), bitmap, pixmap, gc,
237                0, 0, 16, 16, 0, 0, 1l);
238     XSetWindowBackgroundPixmap(getXDisplay(),
239                                getScreenInfo(screen)->getRootWindow(),
240                                pixmap);
241     XClearWindow(getXDisplay(), getScreenInfo(screen)->getRootWindow());
242
243     setPixmapProperty(screen,
244                       duplicatePixmap(screen, pixmap, 16, 16));
245
246     XFreeGC(getXDisplay(), gc);
247     XFreePixmap(getXDisplay(), bitmap);
248
249     if (! (getScreenInfo(screen)->getVisual()->c_class & 1))
250       XFreePixmap(getXDisplay(), pixmap);
251   }
252 }
253
254
255 void bsetroot::gradient(void) {
256   for (int screen = 0; screen < getNumberOfScreens(); screen++) {
257     BTexture texture;
258     img_ctrl[screen]->parseTexture(&texture, grad);
259     img_ctrl[screen]->parseColor(texture.getColor(), fore);
260     img_ctrl[screen]->parseColor(texture.getColorTo(), back);
261
262     if (! texture.getColor()->isAllocated())
263       texture.getColor()->setPixel(WhitePixel(getXDisplay(), screen));
264     if (! texture.getColorTo()->isAllocated())
265       texture.getColorTo()->setPixel(BlackPixel(getXDisplay(), screen));
266
267     Pixmap pixmap =
268       img_ctrl[screen]->renderImage(getScreenInfo(screen)->size().w(),
269                                     getScreenInfo(screen)->size().h(),
270                                     &texture);
271
272     XSetWindowBackgroundPixmap(getXDisplay(),
273                                getScreenInfo(screen)->getRootWindow(),
274                                pixmap);
275     XClearWindow(getXDisplay(), getScreenInfo(screen)->getRootWindow());
276
277     setPixmapProperty(screen,
278                       duplicatePixmap(screen, pixmap,
279                                       getScreenInfo(screen)->size().w(), 
280                                       getScreenInfo(screen)->size().h()));
281       
282     if (! (getScreenInfo(screen)->getVisual()->c_class & 1)) {
283       img_ctrl[screen]->removeImage(pixmap);
284     }
285   }
286 }
287
288
289 void bsetroot::usage(int exit_code) {
290   fprintf(stderr,
291           i18n->
292           getMessage(bsetrootSet, bsetrootUsage,
293                      "%s 2.0 : (c) 1997-1999 Brad Hughes\n\n"
294                      "  -display <string>        display connection\n"
295                      "  -mod <x> <y>             modula pattern\n"
296                      "  -foreground, -fg <color> modula foreground color\n"
297                      "  -background, -bg <color> modula background color\n\n"
298                      "  -gradient <texture>      gradient texture\n"
299                      "  -from <color>            gradient start color\n"
300                      "  -to <color>              gradient end color\n\n"
301                      "  -solid <color>           solid color\n\n"
302                      "  -help                    print this help text and exit\n"),
303           getApplicationName());
304   
305   exit(exit_code);
306 }
307
308
309 int main(int argc, char **argv) {
310   char *display_name = (char *) 0;
311   
312   NLSInit("openbox.cat");
313   
314   for (int i = 1; i < argc; i++) {
315     if (! strcmp(argv[i], "-display")) {
316       // check for -display option
317       
318       if ((++i) >= argc) {
319         fprintf(stderr,
320                 i18n->getMessage(mainSet, mainDISPLAYRequiresArg,
321                                  "error: '-display' requires an argument\n"));
322         
323         ::exit(1);
324       }
325       
326       display_name = argv[i];
327     }
328   }
329   
330   bsetroot app(argc, argv, display_name);
331   
332   return 0;
333 }