1 /* wmsetbg.c- sets root window background image and also works as
2 * workspace background setting helper for wmaker
4 * WindowMaker window manager
6 * Copyright (c) 1998, 1999 Alfredo K. Kojima
7 * Copyright (c) 1998 Dan Pascu
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 * TODO: rewrite, too dirty
33 #include <X11/Xutil.h>
34 #include <X11/Xatom.h>
38 #include <sys/types.h>
41 #include "../src/config.h"
47 #include "../src/wconfig.h"
49 #include <WINGs/WINGs.h>
53 #define PROG_VERSION "wmsetbg (Window Maker) 2.7"
56 #define WORKSPACE_COUNT (MAX_WORKSPACES+1)
70 Pixmap CurrentPixmap
= None
;
71 char *PixmapPath
= NULL
;
74 extern Pixmap
LoadJPEG(RContext
*rc
, char *file_name
, int *width
, int *height
);
77 typedef struct BackgroundTexture
{
85 Pixmap pixmap
; /* for all textures, including solid */
86 int width
; /* size of the pixmap */
93 loadImage(RContext
*rc
, char *file
)
98 if (access(file
, F_OK
)!=0) {
99 path
= wfindfile(PixmapPath
, file
);
101 wwarning("%s:could not find image file used in texture", file
);
105 path
= wstrdup(file
);
108 image
= RLoadImage(rc
, path
, 0);
110 wwarning("%s:could not load image file used in texture:%s", path
,
111 RMessageForError(RErrorCode
));
120 parseTexture(RContext
*rc
, char *text
)
122 BackgroundTexture
*texture
= NULL
;
123 WMPropList
*texarray
;
129 #define GETSTRORGOTO(val, str, i, label) \
130 val = WMGetFromPLArray(texarray, i);\
131 if (!WMIsPLString(val)) {\
132 wwarning("could not parse texture %s", text);\
135 str = WMGetFromPLString(val)
137 texarray
= WMCreatePropListFromDescription(text
);
138 if (!texarray
|| !WMIsPLArray(texarray
)
139 || (count
= WMGetPropListItemCount(texarray
)) < 2) {
141 wwarning("could not parse texture %s", text
);
143 WMReleasePropList(texarray
);
147 texture
= wmalloc(sizeof(BackgroundTexture
));
148 memset(texture
, 0, sizeof(BackgroundTexture
));
150 GETSTRORGOTO(val
, type
, 0, error
);
152 if (strcasecmp(type
, "solid")==0) {
158 GETSTRORGOTO(val
, tmp
, 1, error
);
160 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
161 wwarning("could not parse color %s in texture %s", tmp
, text
);
164 XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
);
166 pixmap
= XCreatePixmap(dpy
, root
, 8, 8, DefaultDepth(dpy
, scr
));
167 XSetForeground(dpy
, DefaultGC(dpy
, scr
), color
.pixel
);
168 XFillRectangle(dpy
, pixmap
, DefaultGC(dpy
, scr
), 0, 0, 8, 8);
170 texture
->pixmap
= pixmap
;
171 texture
->color
= color
;
174 } else if (strcasecmp(type
, "vgradient")==0
175 || strcasecmp(type
, "dgradient")==0
176 || strcasecmp(type
, "hgradient")==0) {
178 RColor color1
, color2
;
184 GETSTRORGOTO(val
, tmp
, 1, error
);
186 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
187 wwarning("could not parse color %s in texture %s", tmp
, text
);
191 color1
.red
= color
.red
>> 8;
192 color1
.green
= color
.green
>> 8;
193 color1
.blue
= color
.blue
>> 8;
195 GETSTRORGOTO(val
, tmp
, 2, error
);
197 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
198 wwarning("could not parse color %s in texture %s", tmp
, text
);
202 color2
.red
= color
.red
>> 8;
203 color2
.green
= color
.green
>> 8;
204 color2
.blue
= color
.blue
>> 8;
209 gtype
= RHorizontalGradient
;
215 gtype
= RVerticalGradient
;
220 gtype
= RDiagonalGradient
;
226 image
= RRenderGradient(iwidth
, iheight
, &color1
, &color2
, gtype
);
229 wwarning("could not render gradient texture:%s",
230 RMessageForError(RErrorCode
));
234 if (!RConvertImage(rc
, image
, &pixmap
)) {
235 wwarning("could not convert texture:%s",
236 RMessageForError(RErrorCode
));
237 RReleaseImage(image
);
241 texture
->width
= image
->width
;
242 texture
->height
= image
->height
;
243 RReleaseImage(image
);
245 texture
->pixmap
= pixmap
;
246 } else if (strcasecmp(type
, "mvgradient")==0
247 || strcasecmp(type
, "mdgradient")==0
248 || strcasecmp(type
, "mhgradient")==0) {
257 colors
= malloc(sizeof(RColor
*)*(count
-1));
259 wwarning("out of memory while parsing texture");
262 memset(colors
, 0, sizeof(RColor
*)*(count
-1));
264 for (i
= 2; i
< count
; i
++) {
265 val
= WMGetFromPLArray(texarray
, i
);
266 if (!WMIsPLString(val
)) {
267 wwarning("could not parse texture %s", text
);
269 for (j
= 0; colors
[j
]!=NULL
; j
++)
274 tmp
= WMGetFromPLString(val
);
276 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
277 wwarning("could not parse color %s in texture %s",
280 for (j
= 0; colors
[j
]!=NULL
; j
++)
285 if (!(colors
[i
-2] = malloc(sizeof(RColor
)))) {
286 wwarning("out of memory while parsing texture");
288 for (j
= 0; colors
[j
]!=NULL
; j
++)
294 colors
[i
-2]->red
= color
.red
>> 8;
295 colors
[i
-2]->green
= color
.green
>> 8;
296 colors
[i
-2]->blue
= color
.blue
>> 8;
302 gtype
= RHorizontalGradient
;
308 gtype
= RVerticalGradient
;
313 gtype
= RDiagonalGradient
;
319 image
= RRenderMultiGradient(iwidth
, iheight
, colors
, gtype
);
321 for (j
= 0; colors
[j
]!=NULL
; j
++)
326 wwarning("could not render gradient texture:%s",
327 RMessageForError(RErrorCode
));
331 if (!RConvertImage(rc
, image
, &pixmap
)) {
332 wwarning("could not convert texture:%s",
333 RMessageForError(RErrorCode
));
334 RReleaseImage(image
);
338 texture
->width
= image
->width
;
339 texture
->height
= image
->height
;
340 RReleaseImage(image
);
342 texture
->pixmap
= pixmap
;
343 } else if (strcasecmp(type
, "cpixmap")==0
344 || strcasecmp(type
, "spixmap")==0
345 || strcasecmp(type
, "mpixmap")==0
346 || strcasecmp(type
, "tpixmap")==0) {
348 Pixmap pixmap
= None
;
349 RImage
*image
= NULL
;
355 GETSTRORGOTO(val
, tmp
, 1, error
);
357 if (toupper(type[0]) == 'T' || toupper(type[0]) == 'C')
358 pixmap = LoadJPEG(rc, tmp, &iwidth, &iheight);
362 image
= loadImage(rc
, tmp
);
366 iwidth
= image
->width
;
367 iheight
= image
->height
;
370 GETSTRORGOTO(val
, tmp
, 2, error
);
372 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
373 wwarning("could not parse color %s in texture %s\n", tmp
, text
);
374 RReleaseImage(image
);
377 if (!XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
)) {
378 rcolor
.red
= color
.red
>> 8;
379 rcolor
.green
= color
.green
>> 8;
380 rcolor
.blue
= color
.blue
>> 8;
381 RGetClosestXColor(rc
, &rcolor
, &color
);
387 /* for images with a transparent color */
388 if (image
->data
[3]) {
389 RCombineImageWithColor(image
, &rcolor
);
392 switch (toupper(type
[0])) {
394 texture
->width
= iwidth
;
395 texture
->height
= iheight
;
396 if (!pixmap
&& !RConvertImage(rc
, image
, &pixmap
)) {
397 wwarning("could not convert texture:%s",
398 RMessageForError(RErrorCode
));
399 RReleaseImage(image
);
403 RReleaseImage(image
);
407 if (toupper(type
[0])=='S') {
411 if (iwidth
*scrHeight
> iheight
*scrWidth
) {
413 h
= (scrWidth
*iheight
)/iwidth
;
416 w
= (scrHeight
*iwidth
)/iheight
;
419 if (w
!= image
->width
|| h
!= image
->height
) {
423 simage
= RSmoothScaleImage(image
, w
, h
);
425 simage
= RScaleImage(image
, w
, h
);
427 wwarning("could not scale image:%s",
428 RMessageForError(RErrorCode
));
429 RReleaseImage(image
);
432 RReleaseImage(image
);
435 iwidth
= image
->width
;
436 iheight
= image
->height
;
443 if (!pixmap
&& !RConvertImage(rc
, image
, &pixmap
)) {
444 wwarning("could not convert texture:%s",
445 RMessageForError(RErrorCode
));
446 RReleaseImage(image
);
450 if (iwidth
!= scrWidth
|| iheight
!= scrHeight
) {
451 int x
, y
, sx
, sy
, w
, h
;
453 cpixmap
= XCreatePixmap(dpy
, root
, scrWidth
, scrHeight
,
454 DefaultDepth(dpy
, scr
));
456 XSetForeground(dpy
, DefaultGC(dpy
, scr
), color
.pixel
);
457 XFillRectangle(dpy
, cpixmap
, DefaultGC(dpy
, scr
),
458 0, 0, scrWidth
, scrHeight
);
460 if (iheight
< scrHeight
) {
462 y
= (scrHeight
- h
)/2;
465 sy
= (iheight
- scrHeight
)/2;
469 if (iwidth
< scrWidth
) {
471 x
= (scrWidth
- w
)/2;
474 sx
= (iwidth
- scrWidth
)/2;
479 XCopyArea(dpy
, pixmap
, cpixmap
, DefaultGC(dpy
, scr
),
481 XFreePixmap(dpy
, pixmap
);
485 RReleaseImage(image
);
487 texture
->width
= scrWidth
;
488 texture
->height
= scrHeight
;
493 texture
->pixmap
= pixmap
;
494 texture
->color
= color
;
495 } else if (strcasecmp(type
, "thgradient")==0
496 || strcasecmp(type
, "tvgradient")==0
497 || strcasecmp(type
, "tdgradient")==0) {
499 RColor color1
, color2
;
509 GETSTRORGOTO(val
, file
, 1, error
);
511 GETSTRORGOTO(val
, tmp
, 2, error
);
515 GETSTRORGOTO(val
, tmp
, 3, error
);
517 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
518 wwarning("could not parse color %s in texture %s", tmp
, text
);
522 color1
.red
= color
.red
>> 8;
523 color1
.green
= color
.green
>> 8;
524 color1
.blue
= color
.blue
>> 8;
526 GETSTRORGOTO(val
, tmp
, 4, error
);
528 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
529 wwarning("could not parse color %s in texture %s", tmp
, text
);
533 color2
.red
= color
.red
>> 8;
534 color2
.green
= color
.green
>> 8;
535 color2
.blue
= color
.blue
>> 8;
537 image
= loadImage(rc
, file
);
545 gtype
= RHorizontalGradient
;
547 theight
= image
->height
> scrHeight
? scrHeight
: image
->height
;
551 gtype
= RVerticalGradient
;
552 twidth
= image
->width
> scrWidth
? scrWidth
: image
->width
;
556 gtype
= RDiagonalGradient
;
561 gradient
= RRenderGradient(twidth
, theight
, &color1
, &color2
, gtype
);
564 wwarning("could not render texture:%s",
565 RMessageForError(RErrorCode
));
566 RReleaseImage(gradient
);
567 RReleaseImage(image
);
571 tiled
= RMakeTiledImage(image
, twidth
, theight
);
573 wwarning("could not render texture:%s",
574 RMessageForError(RErrorCode
));
575 RReleaseImage(gradient
);
576 RReleaseImage(image
);
579 RReleaseImage(image
);
581 RCombineImagesWithOpaqueness(tiled
, gradient
, opaq
);
582 RReleaseImage(gradient
);
584 if (!RConvertImage(rc
, tiled
, &pixmap
)) {
585 wwarning("could not convert texture:%s",
586 RMessageForError(RErrorCode
));
587 RReleaseImage(tiled
);
590 texture
->width
= tiled
->width
;
591 texture
->height
= tiled
->height
;
593 RReleaseImage(tiled
);
595 texture
->pixmap
= pixmap
;
596 } else if (strcasecmp(type
, "function")==0) {
598 void (*initFunc
) (Display
*, Colormap
);
599 RImage
* (*mainFunc
) (int, char**, int, int, int);
603 char *lib
, *func
, **argv
= 0;
608 goto function_cleanup
;
610 /* get the library name */
611 GETSTRORGOTO(val
, lib
, 1, function_cleanup
);
613 /* get the function name */
614 GETSTRORGOTO(val
, func
, 2, function_cleanup
);
617 argv
= (char**)wmalloc(argc
* sizeof(char*));
619 /* get the parameters */
621 for (i
=0; i
<argc
-1; i
++) {
622 GETSTRORGOTO(val
, tmp
, 3+i
, function_cleanup
);
623 argv
[i
+1] = wstrdup(tmp
);
626 handle
= dlopen(lib
, RTLD_LAZY
);
628 wwarning("could not find library %s", lib
);
629 goto function_cleanup
;
632 initFunc
= dlsym(handle
, "initWindowMaker");
634 wwarning("could not initialize library %s", lib
);
635 goto function_cleanup
;
637 initFunc(dpy
, DefaultColormap(dpy
, scr
));
639 mainFunc
= dlsym(handle
, func
);
641 wwarning("could not find function %s::%s", lib
, func
);
642 goto function_cleanup
;
644 image
= mainFunc(argc
, argv
, scrWidth
, scrHeight
, 0);
646 if (!RConvertImage(rc
, image
, &pixmap
)) {
647 wwarning("could not convert texture:%s",
648 RMessageForError(RErrorCode
));
649 goto function_cleanup
;
651 texture
->width
= scrWidth
;
652 texture
->height
= scrHeight
;
653 texture
->pixmap
= pixmap
;
659 for (i
=0; i
<argc
; i
++) {
667 RReleaseImage(image
);
673 wwarning("function textures not supported");
677 wwarning("invalid texture type %s", text
);
681 texture
->spec
= wstrdup(text
);
689 WMReleasePropList(texarray
);
696 freeTexture(BackgroundTexture
*texture
)
698 if (texture
->solid
) {
701 pixel
[0] = texture
->color
.pixel
;
702 /* dont free black/white pixels */
703 if (pixel
[0]!=BlackPixelOfScreen(DefaultScreenOfDisplay(dpy
))
704 && pixel
[0]!=WhitePixelOfScreen(DefaultScreenOfDisplay(dpy
)))
705 XFreeColors(dpy
, DefaultColormap(dpy
, scr
), pixel
, 1, 0);
707 if (texture
->pixmap
) {
708 XFreePixmap(dpy
, texture
->pixmap
);
710 wfree(texture
->spec
);
716 setupTexture(RContext
*rc
, BackgroundTexture
**textures
, int *maxTextures
,
717 int workspace
, char *texture
)
719 BackgroundTexture
*newTexture
= NULL
;
722 /* unset the texture */
724 if (textures
[workspace
]!=NULL
) {
725 textures
[workspace
]->refcount
--;
727 if (textures
[workspace
]->refcount
== 0)
728 freeTexture(textures
[workspace
]);
730 textures
[workspace
] = NULL
;
734 if (textures
[workspace
]
735 && strcasecmp(textures
[workspace
]->spec
, texture
)==0) {
736 /* texture did not change */
740 /* check if the same texture is already created */
741 for (i
= 0; i
< *maxTextures
; i
++) {
742 if (textures
[i
] && strcasecmp(textures
[i
]->spec
, texture
)==0) {
743 newTexture
= textures
[i
];
749 /* create the texture */
750 newTexture
= parseTexture(rc
, texture
);
755 if (textures
[workspace
]!=NULL
) {
757 textures
[workspace
]->refcount
--;
759 if (textures
[workspace
]->refcount
== 0)
760 freeTexture(textures
[workspace
]);
763 newTexture
->refcount
++;
764 textures
[workspace
] = newTexture
;
766 if (*maxTextures
< workspace
)
767 *maxTextures
= workspace
;
773 duplicatePixmap(Pixmap pixmap
, int width
, int height
)
778 /* must open a new display or the RetainPermanent will
779 * leave stuff allocated in RContext unallocated after exit */
780 tmpDpy
= XOpenDisplay(display
);
782 wwarning("could not open display to update background image information");
788 copyP
= XCreatePixmap(tmpDpy
, root
, width
, height
,
789 DefaultDepth(tmpDpy
, scr
));
790 XCopyArea(tmpDpy
, pixmap
, copyP
, DefaultGC(tmpDpy
, scr
),
791 0, 0, width
, height
, 0, 0);
792 XSync(tmpDpy
, False
);
794 XSetCloseDownMode(tmpDpy
, RetainPermanent
);
795 XCloseDisplay(tmpDpy
);
803 dummyErrorHandler(Display
*dpy
, XErrorEvent
*err
)
809 setPixmapProperty(Pixmap pixmap
)
811 static Atom prop
= 0;
814 unsigned long length
, after
;
819 prop
= XInternAtom(dpy
, "_XROOTPMAP_ID", False
);
824 /* Clear out the old pixmap */
825 XGetWindowProperty(dpy
, root
, prop
, 0L, 1L, False
, AnyPropertyType
,
826 &type
, &format
, &length
, &after
, &data
);
828 if ((type
== XA_PIXMAP
) && (format
== 32) && (length
== 1)) {
829 XSetErrorHandler(dummyErrorHandler
);
830 XKillClient(dpy
, *((Pixmap
*)data
));
832 XSetErrorHandler(NULL
);
833 mode
= PropModeReplace
;
835 mode
= PropModeAppend
;
838 XChangeProperty(dpy
, root
, prop
, XA_PIXMAP
, 32, mode
,
839 (unsigned char *) &pixmap
, 1);
841 XDeleteProperty(dpy
, root
, prop
);
851 changeTexture(BackgroundTexture
*texture
)
857 if (texture
->solid
) {
858 XSetWindowBackground(dpy
, root
, texture
->color
.pixel
);
860 XSetWindowBackgroundPixmap(dpy
, root
, texture
->pixmap
);
862 XClearWindow(dpy
, root
);
869 pixmap
= duplicatePixmap(texture
->pixmap
, texture
->width
,
872 setPixmapProperty(pixmap
);
878 readmsg(int fd
, unsigned char *buffer
, int size
)
884 count
= read(fd
, buffer
, size
);
898 * sizeSntexture_spec - sets the texture for workspace n
899 * sizeCn - change background texture to the one for workspace n
900 * sizePpath - set the pixmap search path
903 * size = 4 bytes for length of the message data
906 helperLoop(RContext
*rc
)
908 BackgroundTexture
*textures
[WORKSPACE_COUNT
];
910 unsigned char buffer
[2048], buf
[8];
914 memset(textures
, 0, WORKSPACE_COUNT
*sizeof(BackgroundTexture
*));
920 /* get length of message */
921 if (readmsg(0, buffer
, 4) < 0) {
922 wsyserror("error reading message from Window Maker");
930 memcpy(buf
, buffer
, 4);
935 if (readmsg(0, buffer
, size
) < 0) {
936 wsyserror("error reading message from Window Maker");
945 printf("RECEIVED %s\n",buffer
);
947 if (buffer
[0]!='P' && buffer
[0]!='K') {
948 memcpy(buf
, &buffer
[1], 4);
950 workspace
= atoi(buf
);
951 if (workspace
< 0 || workspace
>= WORKSPACE_COUNT
) {
952 wwarning("received message with invalid workspace number %i\n",
961 printf("set texture %s\n", &buffer
[5]);
963 setupTexture(rc
, textures
, &maxTextures
, workspace
, &buffer
[5]);
968 printf("change texture %i\n", workspace
);
970 if (!textures
[workspace
]) {
971 changeTexture(textures
[0]);
973 changeTexture(textures
[workspace
]);
979 printf("change pixmappath %s\n", &buffer
[1]);
983 PixmapPath
= wstrdup(&buffer
[1]);
988 printf("unset workspace %i\n", workspace
);
990 setupTexture(rc
, textures
, &maxTextures
, workspace
, NULL
);
995 printf("exit command\n");
1000 wwarning("unknown message received");
1008 updateDomain(char *domain
, char *key
, char *texture
)
1010 char *program
= "wdwrite";
1012 /* here is a mem leak */
1013 system(wstrconcat("wdwrite ",
1014 wstrconcat(domain
, smooth
? " SmoothWorkspaceBack YES"
1015 : " SmoothWorkspaceBack NO")));
1017 execlp(program
, program
, domain
, key
, texture
, NULL
);
1018 wwarning("warning could not run \"%s\"", program
);
1024 globalDefaultsPathForDomain(char *domain
)
1028 sprintf(path
, "%s/WindowMaker/%s", SYSCONFDIR
, domain
);
1030 return wstrdup(path
);
1035 getValueForKey(char *domain
, char *keyName
)
1038 WMPropList
*key
, *val
, *d
;
1040 key
= WMCreatePLString(keyName
);
1042 /* try to find PixmapPath in user defaults */
1043 path
= wdefaultspathfordomain(domain
);
1044 d
= WMReadPropListFromFile(path
);
1046 wwarning("could not open domain file %s", path
);
1050 if (d
&& !WMIsPLDictionary(d
)) {
1051 WMReleasePropList(d
);
1055 val
= WMGetFromPLDictionary(d
, key
);
1059 /* try to find PixmapPath in global defaults */
1061 path
= globalDefaultsPathForDomain(domain
);
1063 wwarning("could not locate file for domain %s", domain
);
1066 d
= WMReadPropListFromFile(path
);
1070 if (d
&& !WMIsPLDictionary(d
)) {
1071 WMReleasePropList(d
);
1075 val
= WMGetFromPLDictionary(d
, key
);
1083 WMRetainPropList(val
);
1085 WMReleasePropList(key
);
1087 WMReleasePropList(d
);
1095 getPixmapPath(char *domain
)
1101 val
= getValueForKey(domain
, "PixmapPath");
1103 if (!val
|| !WMIsPLArray(val
)) {
1105 WMReleasePropList(val
);
1109 count
= WMGetPropListItemCount(val
);
1111 for (i
=0; i
<count
; i
++) {
1114 v
= WMGetFromPLArray(val
, i
);
1115 if (!v
|| !WMIsPLString(v
)) {
1118 len
+= strlen(WMGetFromPLString(v
))+1;
1121 ptr
= data
= wmalloc(len
+1);
1124 for (i
=0; i
<count
; i
++) {
1127 v
= WMGetFromPLArray(val
, i
);
1128 if (!v
|| !WMIsPLString(v
)) {
1131 strcpy(ptr
, WMGetFromPLString(v
));
1133 ptr
+= strlen(WMGetFromPLString(v
));
1138 ptr
--; *(ptr
--) = 0;
1140 WMReleasePropList(val
);
1147 getFullPixmapPath(char *file
)
1151 if (!PixmapPath
|| !(tmp
= wfindfile(PixmapPath
, file
))) {
1153 char *path
= wmalloc(bsize
);
1155 while (!getcwd(path
, bsize
)) {
1157 path
= wrealloc(path
, bsize
);
1160 tmp
= wstrconcat(path
, "/");
1162 path
= wstrconcat(tmp
, file
);
1168 /* the file is in the PixmapPath */
1171 return wstrdup(file
);
1186 print_help(char *ProgName
)
1188 printf("Usage: %s [options] [image]\n", ProgName
);
1189 puts("Sets the workspace background to the specified image or a texture and optionally update Window Maker configuration");
1191 #define P(m) puts(m)
1192 P(" -display display to use");
1193 P(" -d, --dither dither image");
1194 P(" -m, --match match colors");
1195 P(" -S, --smooth smooth scaled image");
1196 P(" -b, --back-color <color> background color");
1197 P(" -t, --tile tile image");
1198 P(" -e, --center center image");
1199 P(" -s, --scale scale image (default)");
1200 P(" -a, --maxscale scale image and keep aspect ratio");
1201 P(" -u, --update-wmaker update WindowMaker domain database");
1202 P(" -D, --update-domain <domain> update <domain> database");
1203 P(" -c, --colors <cpc> colors per channel to use");
1204 P(" -p, --parse <texture> proplist style texture specification");
1205 P(" -w, --workspace <workspace> update background for the specified workspace");
1206 P(" --version show version of wmsetbg and exit");
1207 P(" --help show this help and exit");
1214 changeTextureForWorkspace(char *domain
, char *texture
, int workspace
)
1216 WMPropList
*array
, *val
;
1220 val
= WMCreatePropListFromDescription(texture
);
1222 wwarning("could not parse texture %s", texture
);
1226 array
= getValueForKey("WindowMaker", "WorkspaceSpecificBack");
1229 array
= WMCreatePLArray(NULL
, NULL
);
1232 j
= WMGetPropListItemCount(array
);
1233 if (workspace
>= j
) {
1236 empty
= WMCreatePLArray(NULL
, NULL
);
1238 while (j
++ < workspace
-1) {
1239 WMAddToPLArray(array
, empty
);
1241 WMAddToPLArray(array
, val
);
1243 WMDeleteFromPLArray(array
, workspace
);
1244 WMInsertInPLArray(array
, workspace
, val
);
1247 value
= WMGetPropListDescription(array
, False
);
1248 updateDomain(domain
, "WorkspaceSpecificBack", value
);
1253 main(int argc
, char **argv
)
1258 RContextAttributes rattr
;
1259 char *style
= "spixmap";
1260 char *back_color
= "gray20";
1261 char *image_name
= NULL
;
1262 char *domain
= "WindowMaker";
1263 int update
=0, cpc
=4, render_mode
=RDitheredRendering
, obey_user
=0;
1264 char *texture
= NULL
;
1267 signal(SIGINT
, SIG_DFL
);
1268 signal(SIGTERM
, SIG_DFL
);
1269 signal(SIGQUIT
, SIG_DFL
);
1270 signal(SIGSEGV
, SIG_DFL
);
1271 signal(SIGBUS
, SIG_DFL
);
1272 signal(SIGFPE
, SIG_DFL
);
1273 signal(SIGABRT
, SIG_DFL
);
1274 signal(SIGHUP
, SIG_DFL
);
1275 signal(SIGPIPE
, SIG_DFL
);
1276 signal(SIGCHLD
, SIG_DFL
);
1278 WMInitializeApplication("wmsetbg", &argc
, argv
);
1280 for (i
=1; i
<argc
; i
++) {
1281 if (strcmp(argv
[i
], "-helper")==0) {
1283 } else if (strcmp(argv
[i
], "-display")==0) {
1286 wfatal("too few arguments for %s\n", argv
[i
-1]);
1290 } else if (strcmp(argv
[i
], "-s")==0
1291 || strcmp(argv
[i
], "--scale")==0) {
1293 } else if (strcmp(argv
[i
], "-t")==0
1294 || strcmp(argv
[i
], "--tile")==0) {
1296 } else if (strcmp(argv
[i
], "-e")==0
1297 || strcmp(argv
[i
], "--center")==0) {
1299 } else if (strcmp(argv
[i
], "-a")==0
1300 || strcmp(argv
[i
], "--maxscale")==0) {
1302 } else if (strcmp(argv
[i
], "-d")==0
1303 || strcmp(argv
[i
], "--dither")==0) {
1304 render_mode
= RDitheredRendering
;
1306 } else if (strcmp(argv
[i
], "-m")==0
1307 || strcmp(argv
[i
], "--match")==0) {
1308 render_mode
= RBestMatchRendering
;
1310 } else if (strcmp(argv
[i
], "-S")==0
1311 || strcmp(argv
[i
], "--smooth")==0) {
1313 } else if (strcmp(argv
[i
], "-u")==0
1314 || strcmp(argv
[i
], "--update-wmaker")==0) {
1316 } else if (strcmp(argv
[i
], "-D")==0
1317 || strcmp(argv
[i
], "--update-domain")==0) {
1321 wfatal("too few arguments for %s\n", argv
[i
-1]);
1324 domain
= wstrdup(argv
[i
]);
1325 } else if (strcmp(argv
[i
], "-c")==0
1326 || strcmp(argv
[i
], "--colors")==0) {
1329 wfatal("too few arguments for %s\n", argv
[i
-1]);
1332 if (sscanf(argv
[i
], "%i", &cpc
)!=1) {
1333 wfatal("bad value for colors per channel: \"%s\"\n", argv
[i
]);
1336 } else if (strcmp(argv
[i
], "-b")==0
1337 || strcmp(argv
[i
], "--back-color")==0) {
1340 wfatal("too few arguments for %s\n", argv
[i
-1]);
1343 back_color
= argv
[i
];
1344 } else if (strcmp(argv
[i
], "-p")==0
1345 || strcmp(argv
[i
], "--parse")==0) {
1348 wfatal("too few arguments for %s\n", argv
[i
-1]);
1352 } else if (strcmp(argv
[i
], "-w")==0
1353 || strcmp(argv
[i
], "--workspace")==0) {
1356 wfatal("too few arguments for %s\n", argv
[i
-1]);
1359 if (sscanf(argv
[i
], "%i", &workspace
)!=1) {
1360 wfatal("bad value for workspace number: \"%s\"",
1364 } else if (strcmp(argv
[i
], "--version")==0) {
1366 printf(PROG_VERSION
);
1369 } else if (strcmp(argv
[i
], "--help")==0) {
1370 print_help(argv
[0]);
1372 } else if (argv
[i
][0] != '-') {
1373 image_name
= argv
[i
];
1375 printf("%s: invalid argument '%s'\n", argv
[0], argv
[i
]);
1376 printf("Try '%s --help' for more information\n", argv
[0]);
1380 if (!image_name
&& !texture
&& !helperMode
) {
1381 printf("%s: you must specify a image file name or a texture\n",
1383 printf("Try '%s --help' for more information\n", argv
[0]);
1388 PixmapPath
= getPixmapPath(domain
);
1391 #if 0 /* some problem with Alpha... TODO: check if its right */
1392 val
= WMGetFromPLDictionary(domain
,
1393 WMCreatePLString("SmoothWorkspaceBack"));
1395 val
= getValueForKey(domain
, "SmoothWorkspaceBack");
1398 if (val
&& WMIsPLString(val
) && strcasecmp(WMGetFromPLString(val
), "YES")==0)
1402 dpy
= XOpenDisplay(display
);
1404 wfatal("could not open display");
1408 XSynchronize(dpy
, 1);
1411 root
= DefaultRootWindow(dpy
);
1413 scr
= DefaultScreen(dpy
);
1415 scrWidth
= WidthOfScreen(DefaultScreenOfDisplay(dpy
));
1416 scrHeight
= HeightOfScreen(DefaultScreenOfDisplay(dpy
));
1418 if (!obey_user
&& DefaultDepth(dpy
, scr
) <= 8)
1419 render_mode
= RDitheredRendering
;
1421 rattr
.flags
= RC_RenderMode
| RC_ColorsPerChannel
1422 | RC_StandardColormap
| RC_DefaultVisual
;
1423 rattr
.render_mode
= render_mode
;
1424 rattr
.colors_per_channel
= cpc
;
1425 rattr
.standard_colormap_mode
= RCreateStdColormap
;
1427 rc
= RCreateContext(dpy
, scr
, &rattr
);
1430 rattr
.standard_colormap_mode
= RIgnoreStdColormap
;
1431 rc
= RCreateContext(dpy
, scr
, &rattr
);
1435 wfatal("could not initialize wrlib: %s",
1436 RMessageForError(RErrorCode
));
1441 /* lower priority, so that it wont use all the CPU */
1446 BackgroundTexture
*tex
;
1450 char *image_path
= getFullPixmapPath(image_name
);
1452 sprintf(buffer
, "(%s, \"%s\", %s)", style
, image_path
, back_color
);
1454 texture
= (char*)buffer
;
1457 if (update
&& workspace
< 0) {
1458 updateDomain(domain
, "WorkspaceBack", texture
);
1461 tex
= parseTexture(rc
, texture
);
1468 /* always update domain */
1469 changeTextureForWorkspace(domain
, texture
, workspace
);