diff options
Diffstat (limited to 'util/fbsetroot.cc')
-rw-r--r-- | util/fbsetroot.cc | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/util/fbsetroot.cc b/util/fbsetroot.cc new file mode 100644 index 0000000..434f150 --- /dev/null +++ b/util/fbsetroot.cc | |||
@@ -0,0 +1,427 @@ | |||
1 | // Copyright (c) 2002 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org) | ||
2 | // Copyright (c) 1997 - 2000 Brad Hughes <bhughes at trolltech.com> | ||
3 | // | ||
4 | // Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | // copy of this software and associated documentation files (the "Software"), | ||
6 | // to deal in the Software without restriction, including without limitation | ||
7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | // and/or sell copies of the Software, and to permit persons to whom the | ||
9 | // Software is furnished to do so, subject to the following conditions: | ||
10 | // | ||
11 | // The above copyright notice and this permission notice shall be included in | ||
12 | // all copies or substantial portions of the Software. | ||
13 | // | ||
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | |||
21 | // $Id$ | ||
22 | |||
23 | #include "fbsetroot.hh" | ||
24 | |||
25 | #include "../src/FbTk/I18n.hh" | ||
26 | #include "../src/FbTk/ImageControl.hh" | ||
27 | #include "../src/FbTk/GContext.hh" | ||
28 | #include "../src/FbRootWindow.hh" | ||
29 | |||
30 | #ifdef HAVE_CONFIG_H | ||
31 | #include "config.h" | ||
32 | #endif // HAVE_CONFIG_H | ||
33 | |||
34 | #include <X11/Xatom.h> | ||
35 | |||
36 | #ifdef HAVE_CSTRING | ||
37 | #include <cstring> | ||
38 | #else | ||
39 | #include <string.h> | ||
40 | #endif | ||
41 | #ifdef HAVE_CSTDLIB | ||
42 | #include <cstdlib> | ||
43 | #else | ||
44 | #include <stdlib.h> | ||
45 | #endif | ||
46 | #ifdef HAVE_CSTDIO | ||
47 | #include <cstdio> | ||
48 | #else | ||
49 | #include <stdio.h> | ||
50 | #endif | ||
51 | #include <iostream> | ||
52 | |||
53 | using namespace std; | ||
54 | |||
55 | fbsetroot::fbsetroot(int argc, char **argv, char *dpy_name) | ||
56 | : FbTk::App(dpy_name), m_app_name(argv[0]) { | ||
57 | |||
58 | pixmaps = (Pixmap *) 0; | ||
59 | grad = fore = back = (char *) 0; | ||
60 | |||
61 | bool mod = false, sol = false, grd = false; | ||
62 | int mod_x = 0, mod_y = 0, i = 0; | ||
63 | |||
64 | img_ctrl = new FbTk::ImageControl*[ScreenCount(display())]; | ||
65 | for (; i < ScreenCount(display()); i++) { | ||
66 | img_ctrl[i] = new FbTk::ImageControl(i, true); | ||
67 | } | ||
68 | |||
69 | for (i = 1; i < argc; i++) { | ||
70 | if (! strcmp("-help", argv[i])) { | ||
71 | usage(); | ||
72 | |||
73 | } else if ((! strcmp("-fg", argv[i])) || | ||
74 | (! strcmp("-foreground", argv[i])) || | ||
75 | (! strcmp("-from", argv[i]))) { | ||
76 | if ((++i) >= argc) | ||
77 | usage(1); | ||
78 | fore = argv[i]; | ||
79 | |||
80 | } else if ((! strcmp("-bg", argv[i])) || | ||
81 | (! strcmp("-background", argv[i])) || | ||
82 | (! strcmp("-to", argv[i]))) { | ||
83 | if ((++i) >= argc) | ||
84 | usage(1); | ||
85 | back = argv[i]; | ||
86 | |||
87 | } else if (! strcmp("-solid", argv[i])) { | ||
88 | if ((++i) >= argc) | ||
89 | usage(1); | ||
90 | fore = argv[i]; | ||
91 | sol = true; | ||
92 | |||
93 | } else if (! strcmp("-mod", argv[i])) { | ||
94 | if ((++i) >= argc) | ||
95 | usage(); | ||
96 | mod_x = atoi(argv[i]); | ||
97 | if ((++i) >= argc) | ||
98 | usage(); | ||
99 | mod_y = atoi(argv[i]); | ||
100 | if (mod_x < 1) | ||
101 | mod_x = 1; | ||
102 | if (mod_y < 1) | ||
103 | mod_y = 1; | ||
104 | mod = true; | ||
105 | |||
106 | } else if (! strcmp("-gradient", argv[i])) { | ||
107 | if ((++i) >= argc) | ||
108 | usage(); | ||
109 | |||
110 | grad = argv[i]; | ||
111 | grd = true; | ||
112 | |||
113 | } else if (! strcmp("-display", argv[i])) { | ||
114 | // -display passed through tests earlier... we just skip it now | ||
115 | i++; | ||
116 | |||
117 | } else | ||
118 | usage(); | ||
119 | } | ||
120 | |||
121 | if ((mod + sol + grd) != true) { | ||
122 | _FB_USES_NLS; | ||
123 | cerr<<m_app_name<< | ||
124 | _FBTEXT(fbsetroot, MustSpecify, | ||
125 | "Error: must specify one of: -solid, -mod, -gradient\n", | ||
126 | "user didn't give one of the required options")<<endl; | ||
127 | |||
128 | usage(2); | ||
129 | } | ||
130 | |||
131 | num_screens = ScreenCount(display()); | ||
132 | |||
133 | if (sol && fore) | ||
134 | solid(); | ||
135 | else if (mod && mod_x && mod_y && fore && back) | ||
136 | modula(mod_x, mod_y); | ||
137 | else if (grd && grad && fore && back) | ||
138 | gradient(); | ||
139 | else | ||
140 | usage(); | ||
141 | |||
142 | } | ||
143 | |||
144 | |||
145 | fbsetroot::~fbsetroot() { | ||
146 | XKillClient(display(), AllTemporary); | ||
147 | |||
148 | if (pixmaps) { // should always be true | ||
149 | XSetCloseDownMode(display(), RetainTemporary); | ||
150 | |||
151 | delete [] pixmaps; | ||
152 | } | ||
153 | |||
154 | if (img_ctrl != 0) { | ||
155 | for (int i=0; i < num_screens; i++) | ||
156 | delete img_ctrl[i]; | ||
157 | |||
158 | delete [] img_ctrl; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | set root pixmap atoms so that apps like | ||
164 | Eterm and xchat will be able to use | ||
165 | transparent background | ||
166 | */ | ||
167 | void fbsetroot::setRootAtoms(Pixmap pixmap, int screen) { | ||
168 | Atom atom_root, atom_eroot, type; | ||
169 | unsigned char *data_root, *data_eroot; | ||
170 | int format; | ||
171 | unsigned long length, after; | ||
172 | |||
173 | atom_root = XInternAtom(display(), "_XROOTMAP_ID", true); | ||
174 | atom_eroot = XInternAtom(display(), "ESETROOT_PMAP_ID", true); | ||
175 | FbRootWindow root(screen); | ||
176 | |||
177 | // doing this to clean up after old background | ||
178 | if (atom_root != None && atom_eroot != None) { | ||
179 | root.property(atom_root, 0L, 1L, false, AnyPropertyType, | ||
180 | &type, &format, &length, &after, &data_root); | ||
181 | |||
182 | if (type == XA_PIXMAP) { | ||
183 | root.property(atom_eroot, 0L, 1L, False, AnyPropertyType, | ||
184 | &type, &format, &length, &after, &data_eroot); | ||
185 | |||
186 | if (data_root && data_eroot && type == XA_PIXMAP && | ||
187 | *((Pixmap *) data_root) == *((Pixmap *) data_eroot)) { | ||
188 | |||
189 | XKillClient(display(), *((Pixmap *) data_root)); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | atom_root = XInternAtom(display(), "_XROOTPMAP_ID", false); | ||
195 | atom_eroot = XInternAtom(display(), "ESETROOT_PMAP_ID", false); | ||
196 | |||
197 | if (atom_root == None || atom_eroot == None) { | ||
198 | _FB_USES_NLS; | ||
199 | cerr<<_FBTEXT(fbsetroot, NoPixmapAtoms, "Couldn't create pixmap atoms, giving up!", "Couldn't create atoms to point at root pixmap")<<endl; | ||
200 | exit(1); | ||
201 | } | ||
202 | |||
203 | // setting new background atoms | ||
204 | root.changeProperty(atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1); | ||
205 | root.changeProperty(atom_eroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1); | ||
206 | |||
207 | } | ||
208 | |||
209 | /** | ||
210 | Draws pixmaps with a single color | ||
211 | */ | ||
212 | void fbsetroot::solid() { | ||
213 | register int screen = 0; | ||
214 | |||
215 | pixmaps = new Pixmap[ScreenCount(display())]; | ||
216 | |||
217 | for (; screen < ScreenCount(display()); screen++) { | ||
218 | |||
219 | FbTk::Color c(fore, screen); | ||
220 | if (! c.isAllocated()) | ||
221 | c.setPixel(BlackPixel(display(), screen)); | ||
222 | |||
223 | FbRootWindow root(screen); | ||
224 | |||
225 | FbTk::GContext gc(root); | ||
226 | gc.setForeground(c); | ||
227 | |||
228 | pixmaps[screen] = XCreatePixmap(display(), | ||
229 | root.window(), | ||
230 | root.width(), root.height(), | ||
231 | root.depth()); | ||
232 | |||
233 | XFillRectangle(display(), pixmaps[screen], gc.gc(), 0, 0, | ||
234 | root.width(), root.height()); | ||
235 | |||
236 | setRootAtoms(pixmaps[screen], screen); | ||
237 | |||
238 | root.setBackgroundPixmap(pixmaps[screen]); | ||
239 | root.clear(); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | Draws pixmaps with an 16x16 pattern with | ||
245 | fg and bg colors. | ||
246 | */ | ||
247 | void fbsetroot::modula(int x, int y) { | ||
248 | char data[32]; | ||
249 | long pattern; | ||
250 | |||
251 | register int screen, i; | ||
252 | |||
253 | pixmaps = new Pixmap[ScreenCount(display())]; | ||
254 | |||
255 | for (pattern = 0, screen = 0; screen < ScreenCount(display()); screen++) { | ||
256 | FbRootWindow root(screen); | ||
257 | |||
258 | for (i = 0; i < 16; i++) { | ||
259 | pattern <<= 1; | ||
260 | if ((i % x) == 0) | ||
261 | pattern |= 0x0001; | ||
262 | } | ||
263 | |||
264 | for (i = 0; i < 16; i++) { | ||
265 | if ((i % y) == 0) { | ||
266 | data[(i * 2)] = (char) 0xff; | ||
267 | data[(i * 2) + 1] = (char) 0xff; | ||
268 | } else { | ||
269 | data[(i * 2)] = pattern & 0xff; | ||
270 | data[(i * 2) + 1] = (pattern >> 8) & 0xff; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | |||
275 | Pixmap bitmap, r_bitmap; | ||
276 | |||
277 | |||
278 | bitmap = XCreateBitmapFromData(display(), | ||
279 | root.window(), data, 16, 16); | ||
280 | |||
281 | // bitmap used as tile, needs to have the same depth as background pixmap | ||
282 | r_bitmap = XCreatePixmap(display(), | ||
283 | root.window(), 16, 16, | ||
284 | root.depth()); | ||
285 | |||
286 | FbTk::Color f(fore, screen), b(back, screen); | ||
287 | |||
288 | if (! f.isAllocated()) | ||
289 | f.setPixel(WhitePixel(display(), screen)); | ||
290 | if (! b.isAllocated()) | ||
291 | b.setPixel(BlackPixel(display(), screen)); | ||
292 | |||
293 | FbTk::GContext gc(root); | ||
294 | |||
295 | gc.setForeground(f); | ||
296 | gc.setBackground(b); | ||
297 | |||
298 | // copying bitmap to the one going to be used as tile | ||
299 | XCopyPlane(display(), bitmap, r_bitmap, gc.gc(), | ||
300 | 0, 0, 16, 16, 0, 0, 1l); | ||
301 | |||
302 | gc.setTile(r_bitmap); | ||
303 | gc.setFillStyle(FillTiled); | ||
304 | |||
305 | pixmaps[screen] = XCreatePixmap(display(), | ||
306 | root.window(), | ||
307 | root.width(), root.height(), | ||
308 | root.depth()); | ||
309 | |||
310 | XFillRectangle(display(), pixmaps[screen], gc.gc(), 0, 0, | ||
311 | root.width(), root.height()); | ||
312 | |||
313 | setRootAtoms(pixmaps[screen], screen); | ||
314 | root.setBackgroundPixmap(pixmaps[screen]); | ||
315 | root.clear(); | ||
316 | |||
317 | XFreePixmap(display(), bitmap); | ||
318 | XFreePixmap(display(), r_bitmap); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | draws pixmaps with a fluxbox texure | ||
324 | */ | ||
325 | void fbsetroot::gradient() { | ||
326 | // using temporaray pixmap and then copying it to background pixmap, as it'll | ||
327 | // get crashed somewhere on the way causing apps like XChat chrashing | ||
328 | // as the pixmap has been destroyed | ||
329 | Pixmap tmp; | ||
330 | pixmaps = new Pixmap[ScreenCount(display())]; | ||
331 | // we must insert gradient text | ||
332 | string texture_value = grad ? grad : "solid"; | ||
333 | texture_value.insert(0, "gradient "); | ||
334 | FbTk::Texture texture; | ||
335 | texture.setFromString(texture_value.c_str()); | ||
336 | |||
337 | for (int screen = 0; screen < ScreenCount(display()); screen++) { | ||
338 | FbRootWindow root(screen); | ||
339 | |||
340 | |||
341 | FbTk::GContext gc(root); | ||
342 | texture.color().setFromString(fore, screen); | ||
343 | texture.colorTo().setFromString(back, screen); | ||
344 | |||
345 | |||
346 | if (! texture.color().isAllocated()) | ||
347 | texture.color().setPixel(WhitePixel(display(), screen)); | ||
348 | |||
349 | if (! texture.colorTo().isAllocated()) | ||
350 | texture.colorTo().setPixel(BlackPixel(display(), screen)); | ||
351 | |||
352 | tmp = img_ctrl[screen]->renderImage(root.width(), root.height(), | ||
353 | texture); | ||
354 | |||
355 | pixmaps[screen] = XCreatePixmap(display(), | ||
356 | root.window(), | ||
357 | root.width(), root.height(), | ||
358 | root.depth()); | ||
359 | |||
360 | |||
361 | XCopyArea(display(), tmp, pixmaps[screen], gc.gc(), 0, 0, | ||
362 | root.width(), root.height(), | ||
363 | 0, 0); | ||
364 | |||
365 | setRootAtoms(pixmaps[screen], screen); | ||
366 | |||
367 | root.setBackgroundPixmap(pixmaps[screen]); | ||
368 | root.clear(); | ||
369 | |||
370 | if (! (root.visual()->c_class & 1)) { | ||
371 | img_ctrl[screen]->removeImage(tmp); | ||
372 | img_ctrl[screen]->cleanCache(); | ||
373 | } | ||
374 | |||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | Shows information about usage | ||
380 | */ | ||
381 | void fbsetroot::usage(int exit_code) { | ||
382 | _FB_USES_NLS; | ||
383 | cerr<<m_app_name<<" 2.3 : (c) 2003-2005 Fluxbox Development Team"<<endl; | ||
384 | cerr<<m_app_name<<" 2.1 : (c) 2002 Claes Nasten"<<endl; | ||
385 | cerr<<m_app_name<<" 2.0 : (c) 1997-2000 Brad Hughes\n"<<endl; | ||
386 | cerr<<_FBTEXT(fbsetroot, Usage, | ||
387 | " -display <string> display connection\n" | ||
388 | " -mod <x> <y> modula pattern\n" | ||
389 | " -foreground, -fg <color> modula foreground color\n" | ||
390 | " -background, -bg <color> modula background color\n\n" | ||
391 | " -gradient <texture> gradient texture\n" | ||
392 | " -from <color> gradient start color\n" | ||
393 | " -to <color> gradient end color\n\n" | ||
394 | " -solid <color> solid color\n\n" | ||
395 | " -help print this help text and exit\n", | ||
396 | "fbsetroot usage options")<<endl; | ||
397 | exit(exit_code); | ||
398 | } | ||
399 | |||
400 | |||
401 | int main(int argc, char **argv) { | ||
402 | char *display_name = (char *) 0; | ||
403 | int i = 1; | ||
404 | |||
405 | FbTk::NLSInit("fluxbox.cat"); | ||
406 | |||
407 | for (; i < argc; i++) { | ||
408 | if (! strcmp(argv[i], "-display")) { | ||
409 | // check for -display option | ||
410 | |||
411 | if ((++i) >= argc) { | ||
412 | _FB_USES_NLS; | ||
413 | cerr<<_FBTEXT(main, DISPLAYRequiresArg, | ||
414 | "error: '-display' requires an argument", | ||
415 | "option requires an argument")<<endl; | ||
416 | |||
417 | ::exit(1); | ||
418 | } | ||
419 | |||
420 | display_name = argv[i]; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | fbsetroot app(argc, argv, display_name); | ||
425 | |||
426 | return (0); | ||
427 | } | ||