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