]> Dogcows Code - chaz/openbox/blob - util/bsetroot.cc
sync with blackbox-cvs
[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
42 #include <cctype>
43
44 #include "../src/i18n.hh"
45 #include "../src/GCCache.hh"
46 #include "../src/Texture.hh"
47 #include "../src/Util.hh"
48 #include "bsetroot.hh"
49
50
51 I18n i18n;
52
53 bsetroot::bsetroot(int argc, char **argv, char *dpy_name)
54 : BaseDisplay(argv[0], dpy_name) {
55
56 bool mod = False, sol = False, grd = False;
57 int mod_x = 0, mod_y = 0;
58
59 for (int i = 1; i < argc; i++) {
60 if (! strcmp("-help", argv[i])) {
61 usage();
62 } else if ((! strcmp("-fg", argv[i])) ||
63 (! strcmp("-foreground", argv[i])) ||
64 (! strcmp("-from", argv[i]))) {
65 if ((++i) >= argc) usage(1);
66
67 fore = argv[i];
68 } else if ((! strcmp("-bg", argv[i])) ||
69 (! strcmp("-background", argv[i])) ||
70 (! strcmp("-to", argv[i]))) {
71 if ((++i) >= argc) usage(1);
72
73 back = argv[i];
74 } else if (! strcmp("-solid", argv[i])) {
75 if ((++i) >= argc) usage(1);
76
77 fore = argv[i];
78 sol = True;
79 } else if (! strcmp("-mod", argv[i])) {
80 if ((++i) >= argc) usage();
81
82 mod_x = atoi(argv[i]);
83
84 if ((++i) >= argc) usage();
85
86 mod_y = atoi(argv[i]);
87
88 if (mod_x < 1) mod_x = 1;
89 if (mod_y < 1) mod_y = 1;
90
91 mod = True;
92 } else if (! strcmp("-gradient", argv[i])) {
93 if ((++i) >= argc) usage();
94
95 grad = argv[i];
96 grd = True;
97 } else if (! strcmp("-display", argv[i])) {
98 // -display passed through tests ealier... we just skip it now
99 i++;
100 } else {
101 usage();
102 }
103 }
104
105 if ((mod + sol + grd) != True) {
106 fprintf(stderr,
107 i18n(bsetrootSet, bsetrootMustSpecify,
108 "%s: error: must specify one of: -solid, -mod, -gradient\n"),
109 getApplicationName());
110
111 usage(2);
112 }
113
114 img_ctrl = new BImageControl*[getNumberOfScreens()];
115 for (unsigned int s = 0; s < getNumberOfScreens(); ++s)
116 img_ctrl[s] = new BImageControl(this, getScreenInfo(s), True);
117
118 if (sol && ! fore.empty())
119 solid();
120 else if (mod && mod_x && mod_y && ! (fore.empty() || back.empty()))
121 modula(mod_x, mod_y);
122 else if (grd && ! (grad.empty() || fore.empty() || back.empty()))
123 gradient();
124 else usage();
125 }
126
127
128 bsetroot::~bsetroot(void) {
129 XSetCloseDownMode(getXDisplay(), RetainPermanent);
130
131 XKillClient(getXDisplay(), AllTemporary);
132
133 std::for_each(img_ctrl, img_ctrl + getNumberOfScreens(), PointerAssassin());
134
135 delete [] img_ctrl;
136 }
137
138
139 // adapted from wmsetbg
140 void bsetroot::setPixmapProperty(int screen, Pixmap pixmap) {
141 static Atom rootpmap_id = None, esetroot_id = None;
142 Atom type;
143 int format;
144 unsigned long length, after;
145 unsigned char *data;
146 const ScreenInfo *screen_info = getScreenInfo(screen);
147
148 if (rootpmap_id == None) {
149 rootpmap_id = XInternAtom(getXDisplay(), "_XROOTPMAP_ID", False);
150 esetroot_id = XInternAtom(getXDisplay(), "ESETROOT_PMAP_ID", False);
151 }
152
153 XGrabServer(getXDisplay());
154
155 /* Clear out the old pixmap */
156 XGetWindowProperty(getXDisplay(), screen_info->getRootWindow(),
157 rootpmap_id, 0L, 1L, False, AnyPropertyType,
158 &type, &format, &length, &after, &data);
159
160 if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
161 unsigned char* data_esetroot = 0;
162 XGetWindowProperty(getXDisplay(), screen_info->getRootWindow(),
163 esetroot_id, 0L, 1L, False, AnyPropertyType,
164 &type, &format, &length, &after, &data_esetroot);
165 if (data && data_esetroot && *((Pixmap *) data)) {
166 XKillClient(getXDisplay(), *((Pixmap *) data));
167 XSync(getXDisplay(), False);
168 XFree(data_esetroot);
169 }
170 XFree(data);
171 }
172
173 if (pixmap) {
174 XChangeProperty(getXDisplay(), screen_info->getRootWindow(),
175 rootpmap_id, XA_PIXMAP, 32, PropModeReplace,
176 (unsigned char *) &pixmap, 1);
177 XChangeProperty(getXDisplay(), screen_info->getRootWindow(),
178 esetroot_id, XA_PIXMAP, 32, PropModeReplace,
179 (unsigned char *) &pixmap, 1);
180 } else {
181 XDeleteProperty(getXDisplay(), screen_info->getRootWindow(),
182 rootpmap_id);
183 XDeleteProperty(getXDisplay(), screen_info->getRootWindow(),
184 esetroot_id);
185 }
186
187 XUngrabServer(getXDisplay());
188 XFlush(getXDisplay());
189 }
190
191
192 // adapted from wmsetbg
193 Pixmap bsetroot::duplicatePixmap(int screen, Pixmap pixmap,
194 int width, int height) {
195 XSync(getXDisplay(), False);
196
197 Pixmap copyP = XCreatePixmap(getXDisplay(),
198 getScreenInfo(screen)->getRootWindow(),
199 width, height,
200 DefaultDepth(getXDisplay(), screen));
201 XCopyArea(getXDisplay(), pixmap, copyP, DefaultGC(getXDisplay(), screen),
202 0, 0, width, height, 0, 0);
203 XSync(getXDisplay(), False);
204
205 return copyP;
206 }
207
208
209 void bsetroot::solid(void) {
210 for (unsigned int screen = 0; screen < getNumberOfScreens(); screen++) {
211 BColor c(fore, this, screen);
212 const ScreenInfo *screen_info = getScreenInfo(screen);
213
214 XSetWindowBackground(getXDisplay(), screen_info->getRootWindow(),
215 c.pixel());
216 XClearWindow(getXDisplay(), screen_info->getRootWindow());
217
218 Pixmap pixmap = XCreatePixmap(getXDisplay(),
219 screen_info->getRootWindow(),
220 8, 8, DefaultDepth(getXDisplay(), screen));
221 BPen pen(c);
222 XFillRectangle(getXDisplay(), pixmap, pen.gc(), 0, 0, 8, 8);
223
224 setPixmapProperty(screen, duplicatePixmap(screen, pixmap, 8, 8));
225
226 XFreePixmap(getXDisplay(), pixmap);
227 }
228 }
229
230
231 void bsetroot::modula(int x, int y) {
232 char data[32];
233 long pattern;
234
235 unsigned int screen, i;
236
237 for (pattern = 0, screen = 0; screen < getNumberOfScreens(); screen++) {
238 for (i = 0; i < 16; i++) {
239 pattern <<= 1;
240 if ((i % x) == 0)
241 pattern |= 0x0001;
242 }
243
244 for (i = 0; i < 16; i++) {
245 if ((i % y) == 0) {
246 data[(i * 2)] = static_cast<char>(0xff);
247 data[(i * 2) + 1] = static_cast<char>(0xff);
248 } else {
249 data[(i * 2)] = pattern & 0xff;
250 data[(i * 2) + 1] = (pattern >> 8) & 0xff;
251 }
252 }
253
254 BColor f(fore, this, screen), b(back, this, screen);
255 GC gc;
256 Pixmap bitmap;
257 const ScreenInfo *screen_info = getScreenInfo(screen);
258
259 bitmap =
260 XCreateBitmapFromData(getXDisplay(),
261 screen_info->getRootWindow(), data,
262 16, 16);
263
264 XGCValues gcv;
265 gcv.foreground = f.pixel();
266 gcv.background = b.pixel();
267
268 gc = XCreateGC(getXDisplay(), screen_info->getRootWindow(),
269 GCForeground | GCBackground, &gcv);
270
271 Pixmap pixmap = XCreatePixmap(getXDisplay(),
272 screen_info->getRootWindow(),
273 16, 16, screen_info->getDepth());
274
275 XCopyPlane(getXDisplay(), bitmap, pixmap, gc,
276 0, 0, 16, 16, 0, 0, 1l);
277 XSetWindowBackgroundPixmap(getXDisplay(),
278 screen_info->getRootWindow(),
279 pixmap);
280 XClearWindow(getXDisplay(), screen_info->getRootWindow());
281
282 setPixmapProperty(screen,
283 duplicatePixmap(screen, pixmap, 16, 16));
284
285 XFreeGC(getXDisplay(), gc);
286 XFreePixmap(getXDisplay(), bitmap);
287
288 if (! (screen_info->getVisual()->c_class & 1))
289 XFreePixmap(getXDisplay(), pixmap);
290 }
291 }
292
293
294 void bsetroot::gradient(void) {
295 /*
296 we have to be sure that neither raised nor sunken is specified otherwise
297 odd looking borders appear. So we convert to lowercase then look for
298 'raised' or 'sunken' in the description and erase them. To be paranoid
299 the search is done in a loop.
300 */
301 std::string descr;
302 descr.reserve(grad.size());
303
304 std::string::const_iterator it = grad.begin(), end = grad.end();
305 for (; it != end; ++it)
306 descr += std::tolower(*it);
307
308 std::string::size_type pos;
309 while ((pos = descr.find("raised")) != std::string::npos)
310 descr.erase(pos, 6); // 6 is strlen raised
311
312 while ((pos = descr.find("sunken")) != std::string::npos)
313 descr.erase(pos, 6);
314
315 // now add on 'flat' to prevent the bevels from being added
316 descr += "flat";
317
318 for (unsigned int screen = 0; screen < getNumberOfScreens(); screen++) {
319 BTexture texture(descr, this, screen, img_ctrl[screen]);
320 const ScreenInfo *screen_info = getScreenInfo(screen);
321
322 texture.setColor(BColor(fore, this, screen));
323 texture.setColorTo(BColor(back, this, screen));
324
325 Pixmap pixmap =
326 img_ctrl[screen]->renderImage(screen_info->getWidth(),
327 screen_info->getHeight(),
328 texture);
329
330 XSetWindowBackgroundPixmap(getXDisplay(),
331 screen_info->getRootWindow(),
332 pixmap);
333 XClearWindow(getXDisplay(), screen_info->getRootWindow());
334
335 setPixmapProperty(screen,
336 duplicatePixmap(screen, pixmap,
337 screen_info->getWidth(),
338 screen_info->getHeight()));
339
340 if (! (screen_info->getVisual()->c_class & 1)) {
341 img_ctrl[screen]->removeImage(pixmap);
342 }
343 }
344 }
345
346
347 void bsetroot::usage(int exit_code) {
348 fprintf(stderr,
349 i18n(bsetrootSet, bsetrootUsage,
350 "%s 2.0\n\n"
351 "Copyright (c) 1997-2000, 2002 Bradley T Hughes\n"
352 "Copyright (c) 2001-2002 Sean 'Shaleh' Perry\n\n"
353 " -display <string> display connection\n"
354 " -mod <x> <y> modula pattern\n"
355 " -foreground, -fg <color> modula foreground color\n"
356 " -background, -bg <color> modula background color\n\n"
357 " -gradient <texture> gradient texture\n"
358 " -from <color> gradient start color\n"
359 " -to <color> gradient end color\n\n"
360 " -solid <color> solid color\n\n"
361 " -help print this help text and exit\n"),
362 getApplicationName());
363
364 exit(exit_code);
365 }
366
367 int main(int argc, char **argv) {
368 char *display_name = (char *) 0;
369
370 i18n.openCatalog("openbox.cat");
371
372 for (int i = 1; i < argc; i++) {
373 if (! strcmp(argv[i], "-display")) {
374 // check for -display option
375
376 if ((++i) >= argc) {
377 fprintf(stderr, i18n(mainSet, mainDISPLAYRequiresArg,
378 "error: '-display' requires an argument\n"));
379
380 ::exit(1);
381 }
382
383 display_name = argv[i];
384 }
385 }
386
387 bsetroot app(argc, argv, display_name);
388
389 return 0;
390 }
This page took 0.057729 seconds and 5 git commands to generate.