]> Dogcows Code - chaz/openbox/blob - util/bsetroot.cc
caps
[chaz/openbox] / util / bsetroot.cc
1 // -*- mode++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // bsetroot.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
4 // Copyright (c) 1997 - 2000, 2002 Brad Hughes <bhughes at trolltech.com>
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #ifdef HAVE_STDLIB_H
30 # include <stdlib.h>
31 #endif // HAVE_STDLIB_H
32
33 #ifdef HAVE_STRING_H
34 # include <string.h>
35 #endif // HAVE_STRING_H
36
37 #ifdef HAVE_STDIO_H
38 # include <stdio.h>
39 #endif // HAVE_STDIO_H
40
41 #ifdef HAVE_CTYPE_H
42 # include <ctype.h>
43 #endif // HAVE_CTYPE_H
44 }
45
46 #include "../src/i18n.hh"
47 #include "../src/GCCache.hh"
48 #include "../src/Texture.hh"
49 #include "../src/Util.hh"
50 #include "bsetroot.hh"
51
52
53 I18n i18n;
54
55 bsetroot::bsetroot(int argc, char **argv, char *dpy_name)
56 : BaseDisplay(argv[0], dpy_name) {
57
58 bool mod = False, sol = False, grd = False;
59 int mod_x = 0, mod_y = 0;
60
61 for (int i = 1; i < argc; i++) {
62 if (! strcmp("-help", argv[i])) {
63 usage();
64 } else if ((! strcmp("-fg", argv[i])) ||
65 (! strcmp("-foreground", argv[i])) ||
66 (! strcmp("-from", argv[i]))) {
67 if ((++i) >= argc) usage(1);
68
69 fore = argv[i];
70 } else if ((! strcmp("-bg", argv[i])) ||
71 (! strcmp("-background", argv[i])) ||
72 (! strcmp("-to", argv[i]))) {
73 if ((++i) >= argc) usage(1);
74
75 back = argv[i];
76 } else if (! strcmp("-solid", argv[i])) {
77 if ((++i) >= argc) usage(1);
78
79 fore = argv[i];
80 sol = True;
81 } else if (! strcmp("-mod", argv[i])) {
82 if ((++i) >= argc) usage();
83
84 mod_x = atoi(argv[i]);
85
86 if ((++i) >= argc) usage();
87
88 mod_y = atoi(argv[i]);
89
90 if (mod_x < 1) mod_x = 1;
91 if (mod_y < 1) mod_y = 1;
92
93 mod = True;
94 } else if (! strcmp("-gradient", argv[i])) {
95 if ((++i) >= argc) usage();
96
97 grad = argv[i];
98 grd = True;
99 } else if (! strcmp("-display", argv[i])) {
100 // -display passed through tests ealier... we just skip it now
101 i++;
102 } else {
103 usage();
104 }
105 }
106
107 if ((mod + sol + grd) != True) {
108 fprintf(stderr,
109 i18n(bsetrootSet, bsetrootMustSpecify,
110 "%s: error: must specify one of: -solid, -mod, -gradient\n"),
111 getApplicationName());
112
113 usage(2);
114 }
115
116 img_ctrl = new BImageControl*[getNumberOfScreens()];
117 for (unsigned int s = 0; s < getNumberOfScreens(); ++s)
118 img_ctrl[s] = new BImageControl(this, getScreenInfo(s), True);
119
120 if (sol && ! fore.empty())
121 solid();
122 else if (mod && mod_x && mod_y && ! (fore.empty() || back.empty()))
123 modula(mod_x, mod_y);
124 else if (grd && ! (grad.empty() || fore.empty() || back.empty()))
125 gradient();
126 else usage();
127 }
128
129
130 bsetroot::~bsetroot(void) {
131 XSetCloseDownMode(getXDisplay(), RetainPermanent);
132
133 XKillClient(getXDisplay(), AllTemporary);
134
135 std::for_each(img_ctrl, img_ctrl + getNumberOfScreens(), PointerAssassin());
136
137 delete [] img_ctrl;
138 }
139
140
141 // adapted from wmsetbg
142 void bsetroot::setPixmapProperty(int screen, Pixmap pixmap) {
143 static Atom rootpmap_id = None, esetroot_id = None;
144 Atom type;
145 int format;
146 unsigned long length, after;
147 unsigned char *data;
148 const ScreenInfo *screen_info = getScreenInfo(screen);
149
150 if (rootpmap_id == None) {
151 rootpmap_id = XInternAtom(getXDisplay(), "_XROOTPMAP_ID", False);
152 esetroot_id = XInternAtom(getXDisplay(), "ESETROOT_PMAP_ID", False);
153 }
154
155 XGrabServer(getXDisplay());
156
157 /* Clear out the old pixmap */
158 XGetWindowProperty(getXDisplay(), screen_info->getRootWindow(),
159 rootpmap_id, 0L, 1L, False, AnyPropertyType,
160 &type, &format, &length, &after, &data);
161
162 if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
163 unsigned char* data_esetroot = 0;
164 XGetWindowProperty(getXDisplay(), screen_info->getRootWindow(),
165 esetroot_id, 0L, 1L, False, AnyPropertyType,
166 &type, &format, &length, &after, &data_esetroot);
167 if (data && data_esetroot && *((Pixmap *) data)) {
168 XKillClient(getXDisplay(), *((Pixmap *) data));
169 XSync(getXDisplay(), False);
170 XFree(data_esetroot);
171 }
172 XFree(data);
173 }
174
175 if (pixmap) {
176 XChangeProperty(getXDisplay(), screen_info->getRootWindow(),
177 rootpmap_id, XA_PIXMAP, 32, PropModeReplace,
178 (unsigned char *) &pixmap, 1);
179 XChangeProperty(getXDisplay(), screen_info->getRootWindow(),
180 esetroot_id, XA_PIXMAP, 32, PropModeReplace,
181 (unsigned char *) &pixmap, 1);
182 } else {
183 XDeleteProperty(getXDisplay(), screen_info->getRootWindow(),
184 rootpmap_id);
185 XDeleteProperty(getXDisplay(), screen_info->getRootWindow(),
186 esetroot_id);
187 }
188
189 XUngrabServer(getXDisplay());
190 XFlush(getXDisplay());
191 }
192
193
194 // adapted from wmsetbg
195 Pixmap bsetroot::duplicatePixmap(int screen, Pixmap pixmap,
196 int width, int height) {
197 XSync(getXDisplay(), False);
198
199 Pixmap copyP = XCreatePixmap(getXDisplay(),
200 getScreenInfo(screen)->getRootWindow(),
201 width, height,
202 DefaultDepth(getXDisplay(), screen));
203 XCopyArea(getXDisplay(), pixmap, copyP, DefaultGC(getXDisplay(), screen),
204 0, 0, width, height, 0, 0);
205 XSync(getXDisplay(), False);
206
207 return copyP;
208 }
209
210
211 void bsetroot::solid(void) {
212 for (unsigned int screen = 0; screen < getNumberOfScreens(); screen++) {
213 BColor c(fore, this, screen);
214 const ScreenInfo *screen_info = getScreenInfo(screen);
215
216 XSetWindowBackground(getXDisplay(), screen_info->getRootWindow(),
217 c.pixel());
218 XClearWindow(getXDisplay(), screen_info->getRootWindow());
219
220 Pixmap pixmap = XCreatePixmap(getXDisplay(),
221 screen_info->getRootWindow(),
222 8, 8, DefaultDepth(getXDisplay(), screen));
223 BPen pen(c);
224 XFillRectangle(getXDisplay(), pixmap, pen.gc(), 0, 0, 8, 8);
225
226 setPixmapProperty(screen, duplicatePixmap(screen, pixmap, 8, 8));
227
228 XFreePixmap(getXDisplay(), pixmap);
229 }
230 }
231
232
233 void bsetroot::modula(int x, int y) {
234 char data[32];
235 long pattern;
236
237 unsigned int screen, i;
238
239 for (pattern = 0, screen = 0; screen < getNumberOfScreens(); screen++) {
240 for (i = 0; i < 16; i++) {
241 pattern <<= 1;
242 if ((i % x) == 0)
243 pattern |= 0x0001;
244 }
245
246 for (i = 0; i < 16; i++) {
247 if ((i % y) == 0) {
248 data[(i * 2)] = static_cast<char>(0xff);
249 data[(i * 2) + 1] = static_cast<char>(0xff);
250 } else {
251 data[(i * 2)] = pattern & 0xff;
252 data[(i * 2) + 1] = (pattern >> 8) & 0xff;
253 }
254 }
255
256 BColor f(fore, this, screen), b(back, this, screen);
257 GC gc;
258 Pixmap bitmap;
259 const ScreenInfo *screen_info = getScreenInfo(screen);
260
261 bitmap =
262 XCreateBitmapFromData(getXDisplay(),
263 screen_info->getRootWindow(), data,
264 16, 16);
265
266 XGCValues gcv;
267 gcv.foreground = f.pixel();
268 gcv.background = b.pixel();
269
270 gc = XCreateGC(getXDisplay(), screen_info->getRootWindow(),
271 GCForeground | GCBackground, &gcv);
272
273 Pixmap pixmap = XCreatePixmap(getXDisplay(),
274 screen_info->getRootWindow(),
275 16, 16, screen_info->getDepth());
276
277 XCopyPlane(getXDisplay(), bitmap, pixmap, gc,
278 0, 0, 16, 16, 0, 0, 1l);
279 XSetWindowBackgroundPixmap(getXDisplay(),
280 screen_info->getRootWindow(),
281 pixmap);
282 XClearWindow(getXDisplay(), screen_info->getRootWindow());
283
284 setPixmapProperty(screen,
285 duplicatePixmap(screen, pixmap, 16, 16));
286
287 XFreeGC(getXDisplay(), gc);
288 XFreePixmap(getXDisplay(), bitmap);
289
290 if (! (screen_info->getVisual()->c_class & 1))
291 XFreePixmap(getXDisplay(), pixmap);
292 }
293 }
294
295
296 void bsetroot::gradient(void) {
297 /*
298 we have to be sure that neither raised nor sunken is specified otherwise
299 odd looking borders appear. So we convert to lowercase then look for
300 'raised' or 'sunken' in the description and erase them. To be paranoid
301 the search is done in a loop.
302 */
303 std::string descr;
304 descr.reserve(grad.size());
305
306 std::string::const_iterator it = grad.begin(), end = grad.end();
307 for (; it != end; ++it)
308 descr += tolower(*it);
309
310 std::string::size_type pos;
311 while ((pos = descr.find("raised")) != std::string::npos)
312 descr.erase(pos, 6); // 6 is strlen raised
313
314 while ((pos = descr.find("sunken")) != std::string::npos)
315 descr.erase(pos, 6);
316
317 // now add on 'flat' to prevent the bevels from being added
318 descr += "flat";
319
320 for (unsigned int screen = 0; screen < getNumberOfScreens(); screen++) {
321 BTexture texture(descr, this, screen, img_ctrl[screen]);
322 const ScreenInfo *screen_info = getScreenInfo(screen);
323
324 texture.setColor(BColor(fore, this, screen));
325 texture.setColorTo(BColor(back, this, screen));
326
327 Pixmap pixmap =
328 img_ctrl[screen]->renderImage(screen_info->getWidth(),
329 screen_info->getHeight(),
330 texture);
331
332 XSetWindowBackgroundPixmap(getXDisplay(),
333 screen_info->getRootWindow(),
334 pixmap);
335 XClearWindow(getXDisplay(), screen_info->getRootWindow());
336
337 setPixmapProperty(screen,
338 duplicatePixmap(screen, pixmap,
339 screen_info->getWidth(),
340 screen_info->getHeight()));
341
342 if (! (screen_info->getVisual()->c_class & 1)) {
343 img_ctrl[screen]->removeImage(pixmap);
344 }
345 }
346 }
347
348
349 void bsetroot::usage(int exit_code) {
350 fprintf(stderr,
351 i18n(bsetrootSet, bsetrootUsage,
352 "%s 2.0\n\n"
353 "Copyright (c) 1997-2000, 2002 Bradley T Hughes\n"
354 "Copyright (c) 2001-2002 Sean 'Shaleh' Perry\n\n"
355 " -display <string> display connection\n"
356 " -mod <x> <y> modula pattern\n"
357 " -foreground, -fg <color> modula foreground color\n"
358 " -background, -bg <color> modula background color\n\n"
359 " -gradient <texture> gradient texture\n"
360 " -from <color> gradient start color\n"
361 " -to <color> gradient end color\n\n"
362 " -solid <color> solid color\n\n"
363 " -help print this help text and exit\n"),
364 getApplicationName());
365
366 exit(exit_code);
367 }
368
369 int main(int argc, char **argv) {
370 char *display_name = (char *) 0;
371
372 i18n.openCatalog("openbox.cat");
373
374 for (int i = 1; i < argc; i++) {
375 if (! strcmp(argv[i], "-display")) {
376 // check for -display option
377
378 if ((++i) >= argc) {
379 fprintf(stderr, i18n(mainSet, mainDISPLAYRequiresArg,
380 "error: '-display' requires an argument\n"));
381
382 ::exit(1);
383 }
384
385 display_name = argv[i];
386 }
387 }
388
389 bsetroot app(argc, argv, display_name);
390
391 return 0;
392 }
This page took 0.049746 seconds and 4 git commands to generate.