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