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-2002 Alfredo K. Kojima
7 * Copyright (c) 1998-2002 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"
44 #include <X11/extensions/Xinerama.h>
51 #include "../src/wconfig.h"
53 #include <WINGs/WINGs.h>
57 #define PROG_VERSION "wmsetbg (Window Maker) 2.7"
60 #define WORKSPACE_COUNT (MAX_WORKSPACES+1)
72 XineramaScreenInfo
*xine_screens
;
79 Pixmap CurrentPixmap
= None
;
80 char *PixmapPath
= NULL
;
83 extern Pixmap
LoadJPEG(RContext
*rc
, char *file_name
, int *width
, int *height
);
86 typedef struct BackgroundTexture
{
94 Pixmap pixmap
; /* for all textures, including solid */
95 int width
; /* size of the pixmap */
102 loadImage(RContext
*rc
, char *file
)
107 if (access(file
, F_OK
)!=0) {
108 path
= wfindfile(PixmapPath
, file
);
110 wwarning("%s:could not find image file used in texture", file
);
114 path
= wstrdup(file
);
117 image
= RLoadImage(rc
, path
, 0);
119 wwarning("%s:could not load image file used in texture:%s", path
,
120 RMessageForError(RErrorCode
));
128 void applyImage( RContext
* rc
, BackgroundTexture
*texture
, RImage
*image
, char type
, int x
, int y
, int width
, int height
) {
133 switch( toupper(type
)) {
140 if ( image
->width
*height
> image
->height
*width
) {
142 h
= (width
*image
->height
) / image
->width
;
144 w
= (height
*image
->width
) / image
->height
;
149 if ( w
!= image
->width
|| h
!= image
->height
) {
153 simage
= RSmoothScaleImage( image
, w
, h
);
155 simage
= RScaleImage( image
, w
, h
);
159 wwarning( "could not scale image:%s", RMessageForError(RErrorCode
));
171 if ( !RConvertImage(rc
, image
, &pixmap
)) {
172 wwarning( "could not convert texture:%s", RMessageForError(RErrorCode
));
176 if ( image
->width
!= width
|| image
->height
!= height
) {
179 if ( image
->height
< height
) {
181 y
+= (height
- h
) / 2;
184 sy
= (image
->height
- height
) / 2;
187 if ( image
->width
< width
) {
189 x
+= (width
- w
) / 2;
192 sx
= (image
->width
- width
) / 2;
196 XCopyArea(dpy
, pixmap
, texture
->pixmap
, DefaultGC(dpy
, scr
), sx
, sy
, w
, h
, x
, y
);
198 XCopyArea(dpy
, pixmap
, texture
->pixmap
, DefaultGC(dpy
, scr
), 0, 0, width
, height
, x
, y
);
200 XFreePixmap(dpy
, pixmap
);
201 if ( fimage
) RReleaseImage( image
);
209 parseTexture(RContext
*rc
, char *text
)
211 BackgroundTexture
*texture
= NULL
;
212 WMPropList
*texarray
;
218 #define GETSTRORGOTO(val, str, i, label) \
219 val = WMGetFromPLArray(texarray, i);\
220 if (!WMIsPLString(val)) {\
221 wwarning("could not parse texture %s", text);\
224 str = WMGetFromPLString(val)
226 texarray
= WMCreatePropListFromDescription(text
);
227 if (!texarray
|| !WMIsPLArray(texarray
)
228 || (count
= WMGetPropListItemCount(texarray
)) < 2) {
230 wwarning("could not parse texture %s", text
);
232 WMReleasePropList(texarray
);
236 texture
= wmalloc(sizeof(BackgroundTexture
));
237 memset(texture
, 0, sizeof(BackgroundTexture
));
239 GETSTRORGOTO(val
, type
, 0, error
);
241 if (strcasecmp(type
, "solid")==0) {
247 GETSTRORGOTO(val
, tmp
, 1, error
);
249 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
250 wwarning("could not parse color %s in texture %s", tmp
, text
);
253 XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
);
255 pixmap
= XCreatePixmap(dpy
, root
, 8, 8, DefaultDepth(dpy
, scr
));
256 XSetForeground(dpy
, DefaultGC(dpy
, scr
), color
.pixel
);
257 XFillRectangle(dpy
, pixmap
, DefaultGC(dpy
, scr
), 0, 0, 8, 8);
259 texture
->pixmap
= pixmap
;
260 texture
->color
= color
;
263 } else if (strcasecmp(type
, "vgradient")==0
264 || strcasecmp(type
, "dgradient")==0
265 || strcasecmp(type
, "hgradient")==0) {
267 RColor color1
, color2
;
273 GETSTRORGOTO(val
, tmp
, 1, error
);
275 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
276 wwarning("could not parse color %s in texture %s", tmp
, text
);
280 color1
.red
= color
.red
>> 8;
281 color1
.green
= color
.green
>> 8;
282 color1
.blue
= color
.blue
>> 8;
284 GETSTRORGOTO(val
, tmp
, 2, error
);
286 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
287 wwarning("could not parse color %s in texture %s", tmp
, text
);
291 color2
.red
= color
.red
>> 8;
292 color2
.green
= color
.green
>> 8;
293 color2
.blue
= color
.blue
>> 8;
298 gtype
= RHorizontalGradient
;
304 gtype
= RVerticalGradient
;
309 gtype
= RDiagonalGradient
;
315 image
= RRenderGradient(iwidth
, iheight
, &color1
, &color2
, gtype
);
318 wwarning("could not render gradient texture:%s",
319 RMessageForError(RErrorCode
));
323 if (!RConvertImage(rc
, image
, &pixmap
)) {
324 wwarning("could not convert texture:%s",
325 RMessageForError(RErrorCode
));
326 RReleaseImage(image
);
330 texture
->width
= image
->width
;
331 texture
->height
= image
->height
;
332 RReleaseImage(image
);
334 texture
->pixmap
= pixmap
;
335 } else if (strcasecmp(type
, "mvgradient")==0
336 || strcasecmp(type
, "mdgradient")==0
337 || strcasecmp(type
, "mhgradient")==0) {
346 colors
= malloc(sizeof(RColor
*)*(count
-1));
348 wwarning("out of memory while parsing texture");
351 memset(colors
, 0, sizeof(RColor
*)*(count
-1));
353 for (i
= 2; i
< count
; i
++) {
354 val
= WMGetFromPLArray(texarray
, i
);
355 if (!WMIsPLString(val
)) {
356 wwarning("could not parse texture %s", text
);
358 for (j
= 0; colors
[j
]!=NULL
; j
++)
363 tmp
= WMGetFromPLString(val
);
365 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
366 wwarning("could not parse color %s in texture %s",
369 for (j
= 0; colors
[j
]!=NULL
; j
++)
374 if (!(colors
[i
-2] = malloc(sizeof(RColor
)))) {
375 wwarning("out of memory while parsing texture");
377 for (j
= 0; colors
[j
]!=NULL
; j
++)
383 colors
[i
-2]->red
= color
.red
>> 8;
384 colors
[i
-2]->green
= color
.green
>> 8;
385 colors
[i
-2]->blue
= color
.blue
>> 8;
391 gtype
= RHorizontalGradient
;
397 gtype
= RVerticalGradient
;
402 gtype
= RDiagonalGradient
;
408 image
= RRenderMultiGradient(iwidth
, iheight
, colors
, gtype
);
410 for (j
= 0; colors
[j
]!=NULL
; j
++)
415 wwarning("could not render gradient texture:%s",
416 RMessageForError(RErrorCode
));
420 if (!RConvertImage(rc
, image
, &pixmap
)) {
421 wwarning("could not convert texture:%s",
422 RMessageForError(RErrorCode
));
423 RReleaseImage(image
);
427 texture
->width
= image
->width
;
428 texture
->height
= image
->height
;
429 RReleaseImage(image
);
431 texture
->pixmap
= pixmap
;
432 } else if (strcasecmp(type
, "cpixmap")==0
433 || strcasecmp(type
, "spixmap")==0
434 || strcasecmp(type
, "mpixmap")==0
435 || strcasecmp(type
, "tpixmap")==0) {
437 Pixmap pixmap
= None
;
438 RImage
*image
= NULL
;
444 GETSTRORGOTO(val
, tmp
, 1, error
);
446 if (toupper(type[0]) == 'T' || toupper(type[0]) == 'C')
447 pixmap = LoadJPEG(rc, tmp, &iwidth, &iheight);
451 image
= loadImage(rc
, tmp
);
455 iwidth
= image
->width
;
456 iheight
= image
->height
;
459 GETSTRORGOTO(val
, tmp
, 2, error
);
461 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
462 wwarning("could not parse color %s in texture %s\n", tmp
, text
);
463 RReleaseImage(image
);
466 if (!XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
)) {
467 rcolor
.red
= color
.red
>> 8;
468 rcolor
.green
= color
.green
>> 8;
469 rcolor
.blue
= color
.blue
>> 8;
470 RGetClosestXColor(rc
, &rcolor
, &color
);
476 /* for images with a transparent color */
477 if (image
->data
[3]) {
478 RCombineImageWithColor(image
, &rcolor
);
481 switch (toupper(type
[0])) {
483 texture
->width
= iwidth
;
484 texture
->height
= iheight
;
485 if (!pixmap
&& !RConvertImage(rc
, image
, &pixmap
)) {
486 wwarning("could not convert texture:%s",
487 RMessageForError(RErrorCode
));
488 RReleaseImage(image
);
492 RReleaseImage(image
);
497 if (toupper(type
[0])=='S') {
501 if (iwidth
*scrHeight
> iheight
*scrWidth
) {
503 h
= (scrWidth
*iheight
)/iwidth
;
506 w
= (scrHeight
*iwidth
)/iheight
;
509 if (w
!= image
->width
|| h
!= image
->height
) {
513 simage
= RSmoothScaleImage(image
, w
, h
);
515 simage
= RScaleImage(image
, w
, h
);
517 wwarning("could not scale image:%s",
518 RMessageForError(RErrorCode
));
519 RReleaseImage(image
);
522 RReleaseImage(image
);
525 iwidth
= image
->width
;
526 iheight
= image
->height
;
533 if (!pixmap
&& !RConvertImage(rc
, image
, &pixmap
)) {
534 wwarning("could not convert texture:%s",
535 RMessageForError(RErrorCode
));
536 RReleaseImage(image
);
540 if (iwidth
!= scrWidth
|| iheight
!= scrHeight
) {
541 int x
, y
, sx
, sy
, w
, h
;
543 cpixmap
= XCreatePixmap(dpy
, root
, scrWidth
, scrHeight
,
544 DefaultDepth(dpy
, scr
));
546 XSetForeground(dpy
, DefaultGC(dpy
, scr
), color
.pixel
);
547 XFillRectangle(dpy
, cpixmap
, DefaultGC(dpy
, scr
),
548 0, 0, scrWidth
, scrHeight
);
550 if (iheight
< scrHeight
) {
552 y
= (scrHeight
- h
)/2;
555 sy
= (iheight
- scrHeight
)/2;
559 if (iwidth
< scrWidth
) {
561 x
= (scrWidth
- w
)/2;
564 sx
= (iwidth
- scrWidth
)/2;
569 XCopyArea(dpy
, pixmap
, cpixmap
, DefaultGC(dpy
, scr
),
571 XFreePixmap(dpy
, pixmap
);
575 RReleaseImage(image
);
577 texture
->width
= scrWidth
;
578 texture
->height
= scrHeight
;
584 Pixmap tpixmap
= XCreatePixmap( dpy
, root
, scrWidth
, scrHeight
, DefaultDepth(dpy
, scr
));
585 XFillRectangle(dpy
, tpixmap
, DefaultGC(dpy
, scr
), 0, 0, scrWidth
, scrHeight
);
587 texture
->pixmap
= tpixmap
;
588 texture
->color
= color
;
589 texture
->width
= scrWidth
;
590 texture
->height
= scrHeight
;
594 for ( i
=0; i
<xine_count
; ++i
) {
595 applyImage( rc
, texture
, image
, type
[0],
596 xine_screens
[i
].x_org
, xine_screens
[i
].y_org
,
597 xine_screens
[i
].width
, xine_screens
[i
].height
);
600 applyImage( rc
, texture
, image
, type
[0], 0, 0, scrWidth
, scrHeight
);
602 RReleaseImage( image
);
609 texture
->pixmap
= pixmap
;
610 texture
->color
= color
;
612 } else if (strcasecmp(type
, "thgradient")==0
613 || strcasecmp(type
, "tvgradient")==0
614 || strcasecmp(type
, "tdgradient")==0) {
616 RColor color1
, color2
;
626 GETSTRORGOTO(val
, file
, 1, error
);
628 GETSTRORGOTO(val
, tmp
, 2, error
);
632 GETSTRORGOTO(val
, tmp
, 3, error
);
634 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
635 wwarning("could not parse color %s in texture %s", tmp
, text
);
639 color1
.red
= color
.red
>> 8;
640 color1
.green
= color
.green
>> 8;
641 color1
.blue
= color
.blue
>> 8;
643 GETSTRORGOTO(val
, tmp
, 4, error
);
645 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
646 wwarning("could not parse color %s in texture %s", tmp
, text
);
650 color2
.red
= color
.red
>> 8;
651 color2
.green
= color
.green
>> 8;
652 color2
.blue
= color
.blue
>> 8;
654 image
= loadImage(rc
, file
);
662 gtype
= RHorizontalGradient
;
664 theight
= image
->height
> scrHeight
? scrHeight
: image
->height
;
668 gtype
= RVerticalGradient
;
669 twidth
= image
->width
> scrWidth
? scrWidth
: image
->width
;
673 gtype
= RDiagonalGradient
;
678 gradient
= RRenderGradient(twidth
, theight
, &color1
, &color2
, gtype
);
681 wwarning("could not render texture:%s",
682 RMessageForError(RErrorCode
));
683 RReleaseImage(gradient
);
684 RReleaseImage(image
);
688 tiled
= RMakeTiledImage(image
, twidth
, theight
);
690 wwarning("could not render texture:%s",
691 RMessageForError(RErrorCode
));
692 RReleaseImage(gradient
);
693 RReleaseImage(image
);
696 RReleaseImage(image
);
698 RCombineImagesWithOpaqueness(tiled
, gradient
, opaq
);
699 RReleaseImage(gradient
);
701 if (!RConvertImage(rc
, tiled
, &pixmap
)) {
702 wwarning("could not convert texture:%s",
703 RMessageForError(RErrorCode
));
704 RReleaseImage(tiled
);
707 texture
->width
= tiled
->width
;
708 texture
->height
= tiled
->height
;
710 RReleaseImage(tiled
);
712 texture
->pixmap
= pixmap
;
713 } else if (strcasecmp(type
, "function")==0) {
715 void (*initFunc
) (Display
*, Colormap
);
716 RImage
* (*mainFunc
) (int, char**, int, int, int);
720 char *lib
, *func
, **argv
= 0;
725 goto function_cleanup
;
727 /* get the library name */
728 GETSTRORGOTO(val
, lib
, 1, function_cleanup
);
730 /* get the function name */
731 GETSTRORGOTO(val
, func
, 2, function_cleanup
);
734 argv
= (char**)wmalloc(argc
* sizeof(char*));
736 /* get the parameters */
738 for (i
=0; i
<argc
-1; i
++) {
739 GETSTRORGOTO(val
, tmp
, 3+i
, function_cleanup
);
740 argv
[i
+1] = wstrdup(tmp
);
743 handle
= dlopen(lib
, RTLD_LAZY
);
745 wwarning("could not find library %s", lib
);
746 goto function_cleanup
;
749 initFunc
= dlsym(handle
, "initWindowMaker");
751 wwarning("could not initialize library %s", lib
);
752 goto function_cleanup
;
754 initFunc(dpy
, DefaultColormap(dpy
, scr
));
756 mainFunc
= dlsym(handle
, func
);
758 wwarning("could not find function %s::%s", lib
, func
);
759 goto function_cleanup
;
761 image
= mainFunc(argc
, argv
, scrWidth
, scrHeight
, 0);
763 if (!RConvertImage(rc
, image
, &pixmap
)) {
764 wwarning("could not convert texture:%s",
765 RMessageForError(RErrorCode
));
766 goto function_cleanup
;
768 texture
->width
= scrWidth
;
769 texture
->height
= scrHeight
;
770 texture
->pixmap
= pixmap
;
776 for (i
=0; i
<argc
; i
++) {
784 RReleaseImage(image
);
790 wwarning("function textures not supported");
794 wwarning("invalid texture type %s", text
);
798 texture
->spec
= wstrdup(text
);
806 WMReleasePropList(texarray
);
813 freeTexture(BackgroundTexture
*texture
)
815 if (texture
->solid
) {
818 pixel
[0] = texture
->color
.pixel
;
819 /* dont free black/white pixels */
820 if (pixel
[0]!=BlackPixelOfScreen(DefaultScreenOfDisplay(dpy
))
821 && pixel
[0]!=WhitePixelOfScreen(DefaultScreenOfDisplay(dpy
)))
822 XFreeColors(dpy
, DefaultColormap(dpy
, scr
), pixel
, 1, 0);
824 if (texture
->pixmap
) {
825 XFreePixmap(dpy
, texture
->pixmap
);
827 wfree(texture
->spec
);
833 setupTexture(RContext
*rc
, BackgroundTexture
**textures
, int *maxTextures
,
834 int workspace
, char *texture
)
836 BackgroundTexture
*newTexture
= NULL
;
839 /* unset the texture */
841 if (textures
[workspace
]!=NULL
) {
842 textures
[workspace
]->refcount
--;
844 if (textures
[workspace
]->refcount
== 0)
845 freeTexture(textures
[workspace
]);
847 textures
[workspace
] = NULL
;
851 if (textures
[workspace
]
852 && strcasecmp(textures
[workspace
]->spec
, texture
)==0) {
853 /* texture did not change */
857 /* check if the same texture is already created */
858 for (i
= 0; i
< *maxTextures
; i
++) {
859 if (textures
[i
] && strcasecmp(textures
[i
]->spec
, texture
)==0) {
860 newTexture
= textures
[i
];
866 /* create the texture */
867 newTexture
= parseTexture(rc
, texture
);
872 if (textures
[workspace
]!=NULL
) {
874 textures
[workspace
]->refcount
--;
876 if (textures
[workspace
]->refcount
== 0)
877 freeTexture(textures
[workspace
]);
880 newTexture
->refcount
++;
881 textures
[workspace
] = newTexture
;
883 if (*maxTextures
< workspace
)
884 *maxTextures
= workspace
;
890 duplicatePixmap(Pixmap pixmap
, int width
, int height
)
895 /* must open a new display or the RetainPermanent will
896 * leave stuff allocated in RContext unallocated after exit */
897 tmpDpy
= XOpenDisplay(display
);
899 wwarning("could not open display to update background image information");
905 copyP
= XCreatePixmap(tmpDpy
, root
, width
, height
,
906 DefaultDepth(tmpDpy
, scr
));
907 XCopyArea(tmpDpy
, pixmap
, copyP
, DefaultGC(tmpDpy
, scr
),
908 0, 0, width
, height
, 0, 0);
909 XSync(tmpDpy
, False
);
911 XSetCloseDownMode(tmpDpy
, RetainPermanent
);
912 XCloseDisplay(tmpDpy
);
920 dummyErrorHandler(Display
*dpy
, XErrorEvent
*err
)
926 setPixmapProperty(Pixmap pixmap
)
928 static Atom prop
= 0;
931 unsigned long length
, after
;
936 prop
= XInternAtom(dpy
, "_XROOTPMAP_ID", False
);
941 /* Clear out the old pixmap */
942 XGetWindowProperty(dpy
, root
, prop
, 0L, 1L, False
, AnyPropertyType
,
943 &type
, &format
, &length
, &after
, &data
);
945 if ((type
== XA_PIXMAP
) && (format
== 32) && (length
== 1)) {
946 XSetErrorHandler(dummyErrorHandler
);
947 XKillClient(dpy
, *((Pixmap
*)data
));
949 XSetErrorHandler(NULL
);
950 mode
= PropModeReplace
;
952 mode
= PropModeAppend
;
955 XChangeProperty(dpy
, root
, prop
, XA_PIXMAP
, 32, mode
,
956 (unsigned char *) &pixmap
, 1);
958 XDeleteProperty(dpy
, root
, prop
);
968 changeTexture(BackgroundTexture
*texture
)
974 if (texture
->solid
) {
975 XSetWindowBackground(dpy
, root
, texture
->color
.pixel
);
977 XSetWindowBackgroundPixmap(dpy
, root
, texture
->pixmap
);
979 XClearWindow(dpy
, root
);
986 pixmap
= duplicatePixmap(texture
->pixmap
, texture
->width
,
989 setPixmapProperty(pixmap
);
995 readmsg(int fd
, unsigned char *buffer
, int size
)
1001 count
= read(fd
, buffer
, size
);
1015 * sizeSntexture_spec - sets the texture for workspace n
1016 * sizeCn - change background texture to the one for workspace n
1017 * sizePpath - set the pixmap search path
1020 * size = 4 bytes for length of the message data
1023 helperLoop(RContext
*rc
)
1025 BackgroundTexture
*textures
[WORKSPACE_COUNT
];
1026 int maxTextures
= 0;
1027 unsigned char buffer
[2048], buf
[8];
1031 memset(textures
, 0, WORKSPACE_COUNT
*sizeof(BackgroundTexture
*));
1037 /* get length of message */
1038 if (readmsg(0, buffer
, 4) < 0) {
1039 wsyserror("error reading message from Window Maker");
1041 if (errcount
== 0) {
1047 memcpy(buf
, buffer
, 4);
1052 if (readmsg(0, buffer
, size
) < 0) {
1053 wsyserror("error reading message from Window Maker");
1055 if (errcount
== 0) {
1062 printf("RECEIVED %s\n",buffer
);
1064 if (buffer
[0]!='P' && buffer
[0]!='K') {
1065 memcpy(buf
, &buffer
[1], 4);
1067 workspace
= atoi(buf
);
1068 if (workspace
< 0 || workspace
>= WORKSPACE_COUNT
) {
1069 wwarning("received message with invalid workspace number %i\n",
1075 switch (buffer
[0]) {
1078 printf("set texture %s\n", &buffer
[5]);
1080 setupTexture(rc
, textures
, &maxTextures
, workspace
, &buffer
[5]);
1085 printf("change texture %i\n", workspace
);
1087 if (!textures
[workspace
]) {
1088 changeTexture(textures
[0]);
1090 changeTexture(textures
[workspace
]);
1096 printf("change pixmappath %s\n", &buffer
[1]);
1100 PixmapPath
= wstrdup(&buffer
[1]);
1105 printf("unset workspace %i\n", workspace
);
1107 setupTexture(rc
, textures
, &maxTextures
, workspace
, NULL
);
1112 printf("exit command\n");
1117 wwarning("unknown message received");
1125 updateDomain(char *domain
, char *key
, char *texture
)
1127 char *program
= "wdwrite";
1129 /* here is a mem leak */
1130 system(wstrconcat("wdwrite ",
1131 wstrconcat(domain
, smooth
? " SmoothWorkspaceBack YES"
1132 : " SmoothWorkspaceBack NO")));
1134 execlp(program
, program
, domain
, key
, texture
, NULL
);
1135 wwarning("warning could not run \"%s\"", program
);
1141 globalDefaultsPathForDomain(char *domain
)
1145 sprintf(path
, "%s/WindowMaker/%s", SYSCONFDIR
, domain
);
1147 return wstrdup(path
);
1152 getValueForKey(char *domain
, char *keyName
)
1155 WMPropList
*key
, *val
, *d
;
1157 key
= WMCreatePLString(keyName
);
1159 /* try to find PixmapPath in user defaults */
1160 path
= wdefaultspathfordomain(domain
);
1161 d
= WMReadPropListFromFile(path
);
1163 wwarning("could not open domain file %s", path
);
1167 if (d
&& !WMIsPLDictionary(d
)) {
1168 WMReleasePropList(d
);
1172 val
= WMGetFromPLDictionary(d
, key
);
1176 /* try to find PixmapPath in global defaults */
1178 path
= globalDefaultsPathForDomain(domain
);
1180 wwarning("could not locate file for domain %s", domain
);
1183 d
= WMReadPropListFromFile(path
);
1187 if (d
&& !WMIsPLDictionary(d
)) {
1188 WMReleasePropList(d
);
1192 val
= WMGetFromPLDictionary(d
, key
);
1200 WMRetainPropList(val
);
1202 WMReleasePropList(key
);
1204 WMReleasePropList(d
);
1212 getPixmapPath(char *domain
)
1218 val
= getValueForKey(domain
, "PixmapPath");
1220 if (!val
|| !WMIsPLArray(val
)) {
1222 WMReleasePropList(val
);
1226 count
= WMGetPropListItemCount(val
);
1228 for (i
=0; i
<count
; i
++) {
1231 v
= WMGetFromPLArray(val
, i
);
1232 if (!v
|| !WMIsPLString(v
)) {
1235 len
+= strlen(WMGetFromPLString(v
))+1;
1238 ptr
= data
= wmalloc(len
+1);
1241 for (i
=0; i
<count
; i
++) {
1244 v
= WMGetFromPLArray(val
, i
);
1245 if (!v
|| !WMIsPLString(v
)) {
1248 strcpy(ptr
, WMGetFromPLString(v
));
1250 ptr
+= strlen(WMGetFromPLString(v
));
1255 ptr
--; *(ptr
--) = 0;
1257 WMReleasePropList(val
);
1264 getFullPixmapPath(char *file
)
1268 if (!PixmapPath
|| !(tmp
= wfindfile(PixmapPath
, file
))) {
1270 char *path
= wmalloc(bsize
);
1272 while (!getcwd(path
, bsize
)) {
1274 path
= wrealloc(path
, bsize
);
1277 tmp
= wstrconcat(path
, "/");
1279 path
= wstrconcat(tmp
, file
);
1285 /* the file is in the PixmapPath */
1288 return wstrdup(file
);
1303 print_help(char *ProgName
)
1305 printf("Usage: %s [options] [image]\n", ProgName
);
1306 puts("Sets the workspace background to the specified image or a texture and optionally update Window Maker configuration");
1308 #define P(m) puts(m)
1309 P(" -display display to use");
1310 P(" -d, --dither dither image");
1311 P(" -m, --match match colors");
1312 P(" -S, --smooth smooth scaled image");
1313 P(" -b, --back-color <color> background color");
1314 P(" -t, --tile tile image");
1315 P(" -e, --center center image");
1316 P(" -s, --scale scale image (default)");
1317 P(" -a, --maxscale scale image and keep aspect ratio");
1318 P(" -u, --update-wmaker update WindowMaker domain database");
1319 P(" -D, --update-domain <domain> update <domain> database");
1320 P(" -c, --colors <cpc> colors per channel to use");
1321 P(" -p, --parse <texture> proplist style texture specification");
1322 P(" -w, --workspace <workspace> update background for the specified workspace");
1323 P(" --version show version of wmsetbg and exit");
1324 P(" --help show this help and exit");
1331 changeTextureForWorkspace(char *domain
, char *texture
, int workspace
)
1333 WMPropList
*array
, *val
;
1337 val
= WMCreatePropListFromDescription(texture
);
1339 wwarning("could not parse texture %s", texture
);
1343 array
= getValueForKey("WindowMaker", "WorkspaceSpecificBack");
1346 array
= WMCreatePLArray(NULL
, NULL
);
1349 j
= WMGetPropListItemCount(array
);
1350 if (workspace
>= j
) {
1353 empty
= WMCreatePLArray(NULL
, NULL
);
1355 while (j
++ < workspace
-1) {
1356 WMAddToPLArray(array
, empty
);
1358 WMAddToPLArray(array
, val
);
1360 WMDeleteFromPLArray(array
, workspace
);
1361 WMInsertInPLArray(array
, workspace
, val
);
1364 value
= WMGetPropListDescription(array
, False
);
1365 updateDomain(domain
, "WorkspaceSpecificBack", value
);
1370 main(int argc
, char **argv
)
1375 RContextAttributes rattr
;
1376 char *style
= "spixmap";
1377 char *back_color
= "gray20";
1378 char *image_name
= NULL
;
1379 char *domain
= "WindowMaker";
1380 int update
=0, cpc
=4, render_mode
=RDitheredRendering
, obey_user
=0;
1381 char *texture
= NULL
;
1384 signal(SIGINT
, SIG_DFL
);
1385 signal(SIGTERM
, SIG_DFL
);
1386 signal(SIGQUIT
, SIG_DFL
);
1387 signal(SIGSEGV
, SIG_DFL
);
1388 signal(SIGBUS
, SIG_DFL
);
1389 signal(SIGFPE
, SIG_DFL
);
1390 signal(SIGABRT
, SIG_DFL
);
1391 signal(SIGHUP
, SIG_DFL
);
1392 signal(SIGPIPE
, SIG_DFL
);
1393 signal(SIGCHLD
, SIG_DFL
);
1395 WMInitializeApplication("wmsetbg", &argc
, argv
);
1397 for (i
=1; i
<argc
; i
++) {
1398 if (strcmp(argv
[i
], "-helper")==0) {
1400 } else if (strcmp(argv
[i
], "-display")==0) {
1403 wfatal("too few arguments for %s\n", argv
[i
-1]);
1407 } else if (strcmp(argv
[i
], "-s")==0
1408 || strcmp(argv
[i
], "--scale")==0) {
1410 } else if (strcmp(argv
[i
], "-t")==0
1411 || strcmp(argv
[i
], "--tile")==0) {
1413 } else if (strcmp(argv
[i
], "-e")==0
1414 || strcmp(argv
[i
], "--center")==0) {
1416 } else if (strcmp(argv
[i
], "-a")==0
1417 || strcmp(argv
[i
], "--maxscale")==0) {
1419 } else if (strcmp(argv
[i
], "-d")==0
1420 || strcmp(argv
[i
], "--dither")==0) {
1421 render_mode
= RDitheredRendering
;
1423 } else if (strcmp(argv
[i
], "-m")==0
1424 || strcmp(argv
[i
], "--match")==0) {
1425 render_mode
= RBestMatchRendering
;
1427 } else if (strcmp(argv
[i
], "-S")==0
1428 || strcmp(argv
[i
], "--smooth")==0) {
1430 } else if (strcmp(argv
[i
], "-u")==0
1431 || strcmp(argv
[i
], "--update-wmaker")==0) {
1433 } else if (strcmp(argv
[i
], "-D")==0
1434 || strcmp(argv
[i
], "--update-domain")==0) {
1438 wfatal("too few arguments for %s\n", argv
[i
-1]);
1441 domain
= wstrdup(argv
[i
]);
1442 } else if (strcmp(argv
[i
], "-c")==0
1443 || strcmp(argv
[i
], "--colors")==0) {
1446 wfatal("too few arguments for %s\n", argv
[i
-1]);
1449 if (sscanf(argv
[i
], "%i", &cpc
)!=1) {
1450 wfatal("bad value for colors per channel: \"%s\"\n", argv
[i
]);
1453 } else if (strcmp(argv
[i
], "-b")==0
1454 || strcmp(argv
[i
], "--back-color")==0) {
1457 wfatal("too few arguments for %s\n", argv
[i
-1]);
1460 back_color
= argv
[i
];
1461 } else if (strcmp(argv
[i
], "-p")==0
1462 || strcmp(argv
[i
], "--parse")==0) {
1465 wfatal("too few arguments for %s\n", argv
[i
-1]);
1469 } else if (strcmp(argv
[i
], "-w")==0
1470 || strcmp(argv
[i
], "--workspace")==0) {
1473 wfatal("too few arguments for %s\n", argv
[i
-1]);
1476 if (sscanf(argv
[i
], "%i", &workspace
)!=1) {
1477 wfatal("bad value for workspace number: \"%s\"",
1481 } else if (strcmp(argv
[i
], "--version")==0) {
1483 printf(PROG_VERSION
);
1486 } else if (strcmp(argv
[i
], "--help")==0) {
1487 print_help(argv
[0]);
1489 } else if (argv
[i
][0] != '-') {
1490 image_name
= argv
[i
];
1492 printf("%s: invalid argument '%s'\n", argv
[0], argv
[i
]);
1493 printf("Try '%s --help' for more information\n", argv
[0]);
1497 if (!image_name
&& !texture
&& !helperMode
) {
1498 printf("%s: you must specify a image file name or a texture\n",
1500 printf("Try '%s --help' for more information\n", argv
[0]);
1505 PixmapPath
= getPixmapPath(domain
);
1508 #if 0 /* some problem with Alpha... TODO: check if its right */
1509 val
= WMGetFromPLDictionary(domain
,
1510 WMCreatePLString("SmoothWorkspaceBack"));
1512 val
= getValueForKey(domain
, "SmoothWorkspaceBack");
1515 if (val
&& WMIsPLString(val
) && strcasecmp(WMGetFromPLString(val
), "YES")==0)
1519 dpy
= XOpenDisplay(display
);
1521 wfatal("could not open display");
1525 XSynchronize(dpy
, 1);
1528 root
= DefaultRootWindow(dpy
);
1530 scr
= DefaultScreen(dpy
);
1532 scrWidth
= WidthOfScreen(DefaultScreenOfDisplay(dpy
));
1533 scrHeight
= HeightOfScreen(DefaultScreenOfDisplay(dpy
));
1537 xine_screens
= XineramaQueryScreens(dpy
, &xine_count
);
1541 if (!obey_user
&& DefaultDepth(dpy
, scr
) <= 8)
1542 render_mode
= RDitheredRendering
;
1544 rattr
.flags
= RC_RenderMode
| RC_ColorsPerChannel
1545 | RC_StandardColormap
| RC_DefaultVisual
;
1546 rattr
.render_mode
= render_mode
;
1547 rattr
.colors_per_channel
= cpc
;
1548 rattr
.standard_colormap_mode
= RCreateStdColormap
;
1550 rc
= RCreateContext(dpy
, scr
, &rattr
);
1553 rattr
.standard_colormap_mode
= RIgnoreStdColormap
;
1554 rc
= RCreateContext(dpy
, scr
, &rattr
);
1558 wfatal("could not initialize wrlib: %s",
1559 RMessageForError(RErrorCode
));
1564 /* lower priority, so that it wont use all the CPU */
1569 BackgroundTexture
*tex
;
1573 char *image_path
= getFullPixmapPath(image_name
);
1575 sprintf(buffer
, "(%s, \"%s\", %s)", style
, image_path
, back_color
);
1577 texture
= (char*)buffer
;
1580 if (update
&& workspace
< 0) {
1581 updateDomain(domain
, "WorkspaceBack", texture
);
1584 tex
= parseTexture(rc
, texture
);
1591 /* always update domain */
1592 changeTextureForWorkspace(domain
, texture
, workspace
);