aboutsummaryrefslogtreecommitdiff
path: root/util/fbsetroot.cc
diff options
context:
space:
mode:
authormathias <mathias>2005-07-12 04:56:05 (GMT)
committermathias <mathias>2005-07-12 04:56:05 (GMT)
commit1fe9ef3056e80dfed05bbb1b00443c11a64223c1 (patch)
tree3fbae0cada70fe79e939d6c32c7dcb2786b6a816 /util/fbsetroot.cc
parent9531144097b7fdae1051933fd2aa89c8928b72b2 (diff)
downloadfluxbox-1fe9ef3056e80dfed05bbb1b00443c11a64223c1.zip
fluxbox-1fe9ef3056e80dfed05bbb1b00443c11a64223c1.tar.bz2
Renaming of 'bsetroot' to 'fbsetroot' (Mathias)
blackbox's 'bsetroot' and fluxbox's 'bsetroot' have different syntax nowadays and collide when you install fluxbox and blackbox. hence the renaming.
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}