aboutsummaryrefslogtreecommitdiff
path: root/util/fbsetroot.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/fbsetroot.cc')
-rw-r--r--util/fbsetroot.cc427
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
53using namespace std;
54
55fbsetroot::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
145fbsetroot::~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*/
167void 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*/
212void 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*/
247void 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*/
325void 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*/
381void 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
401int 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}