xsetroot.c revision f40e0d56
1/* 2 * $Xorg: xsetroot.c,v 1.4 2001/02/09 02:05:59 xorgcvs Exp $ 3 * 4Copyright 1987, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 */ 26 27/* 28 * xsetroot.c MIT Project Athena, X Window System root window 29 * parameter setting utility. This program will set 30 * various parameters of the X root window. 31 * 32 * Author: Mark Lillibridge, MIT Project Athena 33 * 11-Jun-87 34 */ 35/* $XFree86: xc/programs/xsetroot/xsetroot.c,v 1.7 2001/04/01 14:00:24 tsi Exp $ */ 36 37#include <X11/Xlib.h> 38#include <X11/Xutil.h> 39#include <X11/Xatom.h> 40#include <X11/Xmu/CurUtil.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include "X11/bitmaps/gray" 45 46#define Dynamic 1 47 48static char *program_name; 49static Display *dpy; 50static int screen; 51static Window root; 52static char *fore_color = NULL; 53static char *back_color = NULL; 54static int reverse = 0; 55static int save_colors = 0; 56static int unsave_past = 0; 57static Pixmap save_pixmap = (Pixmap)None; 58 59static void usage(void); 60static void FixupState(void); 61static void SetBackgroundToBitmap(Pixmap bitmap, 62 unsigned int width, unsigned int height); 63static Cursor CreateCursorFromFiles(char *cursor_file, char *mask_file); 64static Cursor CreateCursorFromName(char *name); 65static Pixmap MakeModulaBitmap(int mod_x, int mod_y); 66static XColor NameToXColor(char *name, unsigned long pixel); 67static unsigned long NameToPixel(char *name, unsigned long pixel); 68static Pixmap ReadBitmapFile(char *filename, unsigned int *width, unsigned int *height, int *x_hot, int *y_hot); 69 70static void 71usage(void) 72{ 73 fprintf(stderr, "usage: %s [options]\n", program_name); 74 fprintf(stderr, " where options are:\n"); 75 fprintf(stderr, " -display <display> or -d <display>\n"); 76 fprintf(stderr, " -fg <color> or -foreground <color>\n"); 77 fprintf(stderr, " -bg <color> or -background <color>\n"); 78 fprintf(stderr, " -rv or -reverse\n"); 79 fprintf(stderr, " -help\n"); 80 fprintf(stderr, " -def or -default\n"); 81 fprintf(stderr, " -name <string>\n"); 82 fprintf(stderr, " -cursor <cursor file> <mask file>\n"); 83 fprintf(stderr, " -cursor_name <cursor-font name>\n"); 84 fprintf(stderr, " -solid <color>\n"); 85 fprintf(stderr, " -gray or -grey\n"); 86 fprintf(stderr, " -bitmap <filename>\n"); 87 fprintf(stderr, " -mod <x> <y>\n"); 88 exit(1); 89 /*NOTREACHED*/ 90} 91 92 93int 94main(int argc, char *argv[]) 95{ 96 int excl = 0; 97 int nonexcl = 0; 98 int restore_defaults = 0; 99 char *display_name = NULL; 100 char *name = NULL; 101 char *cursor_file = NULL; 102 char *cursor_mask = NULL; 103 char *cursor_name = NULL; 104 char *solid_color = NULL; 105 Cursor cursor; 106 int gray = 0; 107 char *bitmap_file = NULL; 108 int mod_x = 0; 109 int mod_y = 0; 110 register int i; 111 unsigned int ww, hh; 112 Pixmap bitmap; 113 114 program_name=argv[0]; 115 116 for (i = 1; i < argc; i++) { 117 if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) { 118 if (++i>=argc) usage (); 119 display_name = argv[i]; 120 continue; 121 } 122 if (!strcmp("-help", argv[i])) { 123 usage(); 124 } 125 if (!strcmp("-def", argv[i]) || !strcmp("-default", argv[i])) { 126 restore_defaults = 1; 127 continue; 128 } 129 if (!strcmp("-name", argv[i])) { 130 if (++i>=argc) usage(); 131 name = argv[i]; 132 nonexcl++; 133 continue; 134 } 135 if (!strcmp("-cursor", argv[i])) { 136 if (++i>=argc) usage(); 137 cursor_file = argv[i]; 138 if (++i>=argc) usage(); 139 cursor_mask = argv[i]; 140 nonexcl++; 141 continue; 142 } 143 if (!strcmp("-cursor_name", argv[i])) { 144 if (++i>=argc) usage(); 145 cursor_name = argv[i]; 146 nonexcl++; 147 continue; 148 } 149 if (!strcmp("-fg",argv[i]) || !strcmp("-foreground",argv[i])) { 150 if (++i>=argc) usage(); 151 fore_color = argv[i]; 152 continue; 153 } 154 if (!strcmp("-bg",argv[i]) || !strcmp("-background",argv[i])) { 155 if (++i>=argc) usage(); 156 back_color = argv[i]; 157 continue; 158 } 159 if (!strcmp("-solid", argv[i])) { 160 if (++i>=argc) usage(); 161 solid_color = argv[i]; 162 excl++; 163 continue; 164 } 165 if (!strcmp("-gray", argv[i]) || !strcmp("-grey", argv[i])) { 166 gray = 1; 167 excl++; 168 continue; 169 } 170 if (!strcmp("-bitmap", argv[i])) { 171 if (++i>=argc) usage(); 172 bitmap_file = argv[i]; 173 excl++; 174 continue; 175 } 176 if (!strcmp("-mod", argv[i])) { 177 if (++i>=argc) usage(); 178 mod_x = atoi(argv[i]); 179 if (mod_x <= 0) mod_x = 1; 180 if (++i>=argc) usage(); 181 mod_y = atoi(argv[i]); 182 if (mod_y <= 0) mod_y = 1; 183 excl++; 184 continue; 185 } 186 if (!strcmp("-rv",argv[i]) || !strcmp("-reverse",argv[i])) { 187 reverse = 1; 188 continue; 189 } 190 usage(); 191 } 192 193 /* Check for multiple use of exclusive options */ 194 if (excl > 1) { 195 fprintf(stderr, "%s: choose only one of {solid, gray, bitmap, mod}\n", 196 program_name); 197 usage(); 198 } 199 200 dpy = XOpenDisplay(display_name); 201 if (!dpy) { 202 fprintf(stderr, "%s: unable to open display '%s'\n", 203 program_name, XDisplayName (display_name)); 204 exit (2); 205 } 206 screen = DefaultScreen(dpy); 207 root = RootWindow(dpy, screen); 208 209 /* If there are no arguments then restore defaults. */ 210 if (!excl && !nonexcl) 211 restore_defaults = 1; 212 213 /* Handle a cursor file */ 214 if (cursor_file) { 215 cursor = CreateCursorFromFiles(cursor_file, cursor_mask); 216 XDefineCursor(dpy, root, cursor); 217 XFreeCursor(dpy, cursor); 218 } 219 220 if (cursor_name) { 221 cursor = CreateCursorFromName (cursor_name); 222 if (cursor) 223 { 224 XDefineCursor (dpy, root, cursor); 225 XFreeCursor (dpy, cursor); 226 } 227 } 228 /* Handle -gray and -grey options */ 229 if (gray) { 230 bitmap = XCreateBitmapFromData(dpy, root, gray_bits, 231 gray_width, gray_height); 232 SetBackgroundToBitmap(bitmap, gray_width, gray_height); 233 } 234 235 /* Handle -solid option */ 236 if (solid_color) { 237 XSetWindowBackground(dpy, root, NameToPixel(solid_color, 238 BlackPixel(dpy, screen))); 239 XClearWindow(dpy, root); 240 unsave_past = 1; 241 } 242 243 /* Handle -bitmap option */ 244 if (bitmap_file) { 245 bitmap = ReadBitmapFile(bitmap_file, &ww, &hh, (int *)NULL, (int *)NULL); 246 SetBackgroundToBitmap(bitmap, ww, hh); 247 } 248 249 /* Handle set background to a modula pattern */ 250 if (mod_x) { 251 bitmap = MakeModulaBitmap(mod_x, mod_y); 252 SetBackgroundToBitmap(bitmap, 16, 16); 253 } 254 255 /* Handle set name */ 256 if (name) 257 XStoreName(dpy, root, name); 258 259 /* Handle restore defaults */ 260 if (restore_defaults) { 261 if (!cursor_file) 262 XUndefineCursor(dpy, root); 263 if (!excl) { 264 XSetWindowBackgroundPixmap(dpy, root, (Pixmap) None); 265 XClearWindow(dpy, root); 266 unsave_past = 1; 267 } 268 } 269 270 FixupState(); 271 XCloseDisplay(dpy); 272 exit (0); 273} 274 275 276/* Free past incarnation if needed, and retain state if needed. */ 277static void 278FixupState(void) 279{ 280 Atom prop, type; 281 int format; 282 unsigned long length, after; 283 unsigned char *data; 284 285 if (!(DefaultVisual(dpy, screen)->class & Dynamic)) 286 unsave_past = 0; 287 if (!unsave_past && !save_colors) 288 return; 289 prop = XInternAtom(dpy, "_XSETROOT_ID", False); 290 if (unsave_past) { 291 (void)XGetWindowProperty(dpy, root, prop, 0L, 1L, True, AnyPropertyType, 292 &type, &format, &length, &after, &data); 293 if ((type == XA_PIXMAP) && (format == 32) && 294 (length == 1) && (after == 0)) 295 XKillClient(dpy, *((Pixmap *)data)); 296 else if (type != None) 297 fprintf(stderr, "%s: warning: _XSETROOT_ID property is garbage\n", 298 program_name); 299 } 300 if (save_colors) { 301 if (!save_pixmap) 302 save_pixmap = XCreatePixmap(dpy, root, 1, 1, 1); 303 XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace, 304 (unsigned char *) &save_pixmap, 1); 305 XSetCloseDownMode(dpy, RetainPermanent); 306 } 307} 308 309/* 310 * SetBackgroundToBitmap: Set the root window background to a caller supplied 311 * bitmap. 312 */ 313static void 314SetBackgroundToBitmap(Pixmap bitmap, unsigned int width, unsigned int height) 315{ 316 Pixmap pix; 317 GC gc; 318 XGCValues gc_init; 319 320 gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen)); 321 gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen)); 322 if (reverse) { 323 unsigned long temp=gc_init.foreground; 324 gc_init.foreground=gc_init.background; 325 gc_init.background=temp; 326 } 327 gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init); 328 pix = XCreatePixmap(dpy, root, width, height, 329 (unsigned int)DefaultDepth(dpy, screen)); 330 XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1); 331 XSetWindowBackgroundPixmap(dpy, root, pix); 332 XFreeGC(dpy, gc); 333 XFreePixmap(dpy, bitmap); 334 if (save_colors) 335 save_pixmap = pix; 336 else 337 XFreePixmap(dpy, pix); 338 XClearWindow(dpy, root); 339 unsave_past = 1; 340} 341 342 343/* 344 * CreateCursorFromFiles: make a cursor of the right colors from two bitmap 345 * files. 346 */ 347#define BITMAP_HOT_DEFAULT 8 348 349static Cursor 350CreateCursorFromFiles(char *cursor_file, char *mask_file) 351{ 352 Pixmap cursor_bitmap, mask_bitmap; 353 unsigned int width, height, ww, hh; 354 int x_hot, y_hot; 355 Cursor cursor; 356 XColor fg, bg, temp; 357 358 fg = NameToXColor(fore_color, BlackPixel(dpy, screen)); 359 bg = NameToXColor(back_color, WhitePixel(dpy, screen)); 360 if (reverse) { 361 temp = fg; fg = bg; bg = temp; 362 } 363 364 cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot); 365 mask_bitmap = ReadBitmapFile(mask_file, &ww, &hh, (int *)NULL, (int *)NULL); 366 367 if (width != ww || height != hh) { 368 fprintf(stderr, 369"%s: dimensions of cursor bitmap and cursor mask bitmap are different\n", 370 program_name); 371 exit(1); 372 /*NOTREACHED*/ 373 } 374 375 if ((x_hot == -1) && (y_hot == -1)) { 376 x_hot = BITMAP_HOT_DEFAULT; 377 y_hot = BITMAP_HOT_DEFAULT; 378 } 379 if ((x_hot < 0) || (x_hot >= width) || 380 (y_hot < 0) || (y_hot >= height)) { 381 fprintf(stderr, "%s: hotspot is outside cursor bounds\n", program_name); 382 exit(1); 383 /*NOTREACHED*/ 384 } 385 386 cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg, 387 (unsigned int)x_hot, (unsigned int)y_hot); 388 XFreePixmap(dpy, cursor_bitmap); 389 XFreePixmap(dpy, mask_bitmap); 390 391 return(cursor); 392} 393 394static Cursor 395CreateCursorFromName(char *name) 396{ 397 XColor fg, bg, temp; 398 int i; 399 Font fid; 400 401 fg = NameToXColor(fore_color, BlackPixel(dpy, screen)); 402 bg = NameToXColor(back_color, WhitePixel(dpy, screen)); 403 if (reverse) { 404 temp = fg; fg = bg; bg = temp; 405 } 406 i = XmuCursorNameToIndex (name); 407 if (i == -1) 408 return (Cursor) 0; 409 fid = XLoadFont (dpy, "cursor"); 410 if (!fid) 411 return (Cursor) 0; 412 return XCreateGlyphCursor (dpy, fid, fid, 413 i, i+1, &fg, &bg); 414} 415 416/* 417 * MakeModulaBitmap: Returns a modula bitmap based on an x & y mod. 418 */ 419static Pixmap 420MakeModulaBitmap(int mod_x, int mod_y) 421{ 422 int i; 423 long pattern_line = 0; 424 char modula_data[16*16/8]; 425 426 for (i=16; i--; ) { 427 pattern_line <<=1; 428 if ((i % mod_x) == 0) pattern_line |= 0x0001; 429 } 430 for (i=0; i<16; i++) { 431 if ((i % mod_y) == 0) { 432 modula_data[i*2] = (char)0xff; 433 modula_data[i*2+1] = (char)0xff; 434 } else { 435 modula_data[i*2] = pattern_line & 0xff; 436 modula_data[i*2+1] = (pattern_line>>8) & 0xff; 437 } 438 } 439 440 return(XCreateBitmapFromData(dpy, root, modula_data, 16, 16)); 441} 442 443 444/* 445 * NameToXColor: Convert the name of a color to its Xcolor value. 446 */ 447static XColor 448NameToXColor(char *name, unsigned long pixel) 449{ 450 XColor c; 451 452 if (!name || !*name) { 453 c.pixel = pixel; 454 XQueryColor(dpy, DefaultColormap(dpy, screen), &c); 455 } else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c)) { 456 fprintf(stderr, "%s: unknown color or bad color format: %s\n", 457 program_name, name); 458 exit(1); 459 /*NOTREACHED*/ 460 } 461 return(c); 462} 463 464static unsigned long 465NameToPixel(char *name, unsigned long pixel) 466{ 467 XColor ecolor; 468 469 if (!name || !*name) 470 return pixel; 471 if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) { 472 fprintf(stderr,"%s: unknown color \"%s\"\n",program_name,name); 473 exit(1); 474 /*NOTREACHED*/ 475 } 476 if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) { 477 fprintf(stderr, "%s: unable to allocate color for \"%s\"\n", 478 program_name, name); 479 exit(1); 480 /*NOTREACHED*/ 481 } 482 if ((ecolor.pixel != BlackPixel(dpy, screen)) && 483 (ecolor.pixel != WhitePixel(dpy, screen)) && 484 (DefaultVisual(dpy, screen)->class & Dynamic)) 485 save_colors = 1; 486 return(ecolor.pixel); 487} 488 489static Pixmap 490ReadBitmapFile(char *filename, unsigned int *width, unsigned int *height, 491 int *x_hot, int *y_hot) 492{ 493 Pixmap bitmap; 494 int status; 495 496 status = XReadBitmapFile(dpy, root, filename, width, 497 height, &bitmap, x_hot, y_hot); 498 if (status == BitmapSuccess) 499 return(bitmap); 500 else if (status == BitmapOpenFailed) 501 fprintf(stderr, "%s: can't open file: %s\n", program_name, filename); 502 else if (status == BitmapFileInvalid) 503 fprintf(stderr, "%s: bad bitmap format file: %s\n", 504 program_name, filename); 505 else 506 fprintf(stderr, "%s: insufficient memory for bitmap: %s", 507 program_name, filename); 508 exit(1); 509 /*NOTREACHED*/ 510} 511