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-2003 Alfredo K. Kojima
7 * Copyright (c) 1998-2003 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
32 #include <X11/Xutil.h>
33 #include <X11/Xatom.h>
37 #include <sys/types.h>
40 #include "../src/config.h"
43 # ifdef SOLARIS_XINERAMA /* sucks */
44 # include <X11/extensions/xinerama.h>
46 # include <X11/extensions/Xinerama.h>
55 #include "../src/wconfig.h"
57 #include <WINGs/WINGs.h>
63 int count
; /* screen count, 0 = inactive */
67 #define PROG_VERSION "wmsetbg (Window Maker) 2.8"
70 #define WORKSPACE_COUNT (MAX_WORKSPACES+1)
82 WXineramaInfo xineInfo
;
87 Pixmap CurrentPixmap
= None
;
88 char *PixmapPath
= NULL
;
91 extern Pixmap
LoadJPEG(RContext
*rc
, char *file_name
, int *width
, int *height
);
94 typedef struct BackgroundTexture
{
102 Pixmap pixmap
; /* for all textures, including solid */
103 int width
; /* size of the pixmap */
112 xineInfo
.screens
= NULL
;
115 # ifdef SOLARIS_XINERAMA
116 if (XineramaGetState(dpy
, scr
)) {
117 XRectangle head
[MAXFRAMEBUFFERS
];
118 unsigned char hints
[MAXFRAMEBUFFERS
];
121 if (XineramaGetInfo(dpy
, scr
, head
, hints
,
124 xineInfo
.screens
= wmalloc(sizeof(WMRect
)*(xineInfo
.count
+1));
126 for (i
=0; i
<xineInfo
.count
; i
++) {
127 xineInfo
.screens
[i
].pos
.x
= head
[i
].x
;
128 xineInfo
.screens
[i
].pos
.y
= head
[i
].y
;
129 xineInfo
.screens
[i
].size
.width
= head
[i
].width
;
130 xineInfo
.screens
[i
].size
.height
= head
[i
].height
;
134 # else /* !SOLARIS_XINERAMA */
135 if (XineramaIsActive(dpy
)) {
136 XineramaInfo
*xine_screens
;
137 WXineramaInfo
*info
= &scr
->xine_info
;
140 xine_screens
= XineramaQueryScreens(dpy
, &xineInfo
.count
);
142 xineInfo
.screens
= wmalloc(sizeof(WMRect
)*(xineInfo
.count
+1));
144 for (i
=0; i
<xineInfo
.count
; i
++) {
145 xineInfo
.screens
[i
].pos
.x
= xineInfo
.screens
[i
].x_org
;
146 xineInfo
.screens
[i
].pos
.y
= xineInfo
.screens
[i
].y_org
;
147 xineInfo
.screens
[i
].size
.width
= xineInfo
.screens
[i
].width
;
148 xineInfo
.screens
[i
].size
.height
= xineInfo
.screens
[i
].height
;
152 # endif /* !SOLARIS_XINERAMA */
153 #endif /* XINERAMA */
158 loadImage(RContext
*rc
, char *file
)
163 if (access(file
, F_OK
)!=0) {
164 path
= wfindfile(PixmapPath
, file
);
166 wwarning("%s:could not find image file used in texture", file
);
170 path
= wstrdup(file
);
173 image
= RLoadImage(rc
, path
, 0);
175 wwarning("%s:could not load image file used in texture:%s", path
,
176 RMessageForError(RErrorCode
));
185 applyImage(RContext
*rc
, BackgroundTexture
*texture
, RImage
*image
, char type
,
186 int x
, int y
, int width
, int height
)
191 switch (toupper(type
)) {
194 if (toupper(type
) == 'S') {
198 if (image
->width
*height
> image
->height
*width
) {
200 h
= (width
*image
->height
) / image
->width
;
202 w
= (height
*image
->width
) / image
->height
;
207 if (w
!= image
->width
|| h
!= image
->height
) {
211 simage
= RSmoothScaleImage(image
, w
, h
);
213 simage
= RScaleImage(image
, w
, h
);
217 wwarning("could not scale image:%s", RMessageForError(RErrorCode
));
229 if (!RConvertImage(rc
, image
, &pixmap
)) {
230 wwarning("could not convert texture:%s", RMessageForError(RErrorCode
));
234 if (image
->width
!= width
|| image
->height
!= height
) {
237 if (image
->height
< height
) {
239 y
+= (height
- h
) / 2;
242 sy
= (image
->height
- height
) / 2;
245 if (image
->width
< width
) {
247 x
+= (width
- w
) / 2;
250 sx
= (image
->width
- width
) / 2;
254 XCopyArea(dpy
, pixmap
, texture
->pixmap
, DefaultGC(dpy
, scr
), sx
, sy
, w
, h
, x
, y
);
256 XCopyArea(dpy
, pixmap
, texture
->pixmap
, DefaultGC(dpy
, scr
), 0, 0, width
, height
, x
, y
);
258 XFreePixmap(dpy
, pixmap
);
260 RReleaseImage( image
);
269 parseTexture(RContext
*rc
, char *text
)
271 BackgroundTexture
*texture
= NULL
;
272 WMPropList
*texarray
;
278 #define GETSTRORGOTO(val, str, i, label) \
279 val = WMGetFromPLArray(texarray, i);\
280 if (!WMIsPLString(val)) {\
281 wwarning("could not parse texture %s", text);\
284 str = WMGetFromPLString(val)
286 texarray
= WMCreatePropListFromDescription(text
);
287 if (!texarray
|| !WMIsPLArray(texarray
)
288 || (count
= WMGetPropListItemCount(texarray
)) < 2) {
290 wwarning("could not parse texture %s", text
);
292 WMReleasePropList(texarray
);
296 texture
= wmalloc(sizeof(BackgroundTexture
));
297 memset(texture
, 0, sizeof(BackgroundTexture
));
299 GETSTRORGOTO(val
, type
, 0, error
);
301 if (strcasecmp(type
, "solid")==0) {
307 GETSTRORGOTO(val
, tmp
, 1, error
);
309 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
310 wwarning("could not parse color %s in texture %s", tmp
, text
);
313 XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
);
315 pixmap
= XCreatePixmap(dpy
, root
, 8, 8, DefaultDepth(dpy
, scr
));
316 XSetForeground(dpy
, DefaultGC(dpy
, scr
), color
.pixel
);
317 XFillRectangle(dpy
, pixmap
, DefaultGC(dpy
, scr
), 0, 0, 8, 8);
319 texture
->pixmap
= pixmap
;
320 texture
->color
= color
;
323 } else if (strcasecmp(type
, "vgradient")==0
324 || strcasecmp(type
, "dgradient")==0
325 || strcasecmp(type
, "hgradient")==0) {
327 RColor color1
, color2
;
333 GETSTRORGOTO(val
, tmp
, 1, error
);
335 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
336 wwarning("could not parse color %s in texture %s", tmp
, text
);
340 color1
.red
= color
.red
>> 8;
341 color1
.green
= color
.green
>> 8;
342 color1
.blue
= color
.blue
>> 8;
344 GETSTRORGOTO(val
, tmp
, 2, error
);
346 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
347 wwarning("could not parse color %s in texture %s", tmp
, text
);
351 color2
.red
= color
.red
>> 8;
352 color2
.green
= color
.green
>> 8;
353 color2
.blue
= color
.blue
>> 8;
358 gtype
= RHorizontalGradient
;
364 gtype
= RVerticalGradient
;
369 gtype
= RDiagonalGradient
;
375 image
= RRenderGradient(iwidth
, iheight
, &color1
, &color2
, gtype
);
378 wwarning("could not render gradient texture:%s",
379 RMessageForError(RErrorCode
));
383 if (!RConvertImage(rc
, image
, &pixmap
)) {
384 wwarning("could not convert texture:%s",
385 RMessageForError(RErrorCode
));
386 RReleaseImage(image
);
390 texture
->width
= image
->width
;
391 texture
->height
= image
->height
;
392 RReleaseImage(image
);
394 texture
->pixmap
= pixmap
;
395 } else if (strcasecmp(type
, "mvgradient")==0
396 || strcasecmp(type
, "mdgradient")==0
397 || strcasecmp(type
, "mhgradient")==0) {
406 colors
= malloc(sizeof(RColor
*)*(count
-1));
408 wwarning("out of memory while parsing texture");
411 memset(colors
, 0, sizeof(RColor
*)*(count
-1));
413 for (i
= 2; i
< count
; i
++) {
414 val
= WMGetFromPLArray(texarray
, i
);
415 if (!WMIsPLString(val
)) {
416 wwarning("could not parse texture %s", text
);
418 for (j
= 0; colors
[j
]!=NULL
; j
++)
423 tmp
= WMGetFromPLString(val
);
425 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
426 wwarning("could not parse color %s in texture %s",
429 for (j
= 0; colors
[j
]!=NULL
; j
++)
434 if (!(colors
[i
-2] = malloc(sizeof(RColor
)))) {
435 wwarning("out of memory while parsing texture");
437 for (j
= 0; colors
[j
]!=NULL
; j
++)
443 colors
[i
-2]->red
= color
.red
>> 8;
444 colors
[i
-2]->green
= color
.green
>> 8;
445 colors
[i
-2]->blue
= color
.blue
>> 8;
451 gtype
= RHorizontalGradient
;
457 gtype
= RVerticalGradient
;
462 gtype
= RDiagonalGradient
;
468 image
= RRenderMultiGradient(iwidth
, iheight
, colors
, gtype
);
470 for (j
= 0; colors
[j
]!=NULL
; j
++)
475 wwarning("could not render gradient texture:%s",
476 RMessageForError(RErrorCode
));
480 if (!RConvertImage(rc
, image
, &pixmap
)) {
481 wwarning("could not convert texture:%s",
482 RMessageForError(RErrorCode
));
483 RReleaseImage(image
);
487 texture
->width
= image
->width
;
488 texture
->height
= image
->height
;
489 RReleaseImage(image
);
491 texture
->pixmap
= pixmap
;
492 } else if (strcasecmp(type
, "cpixmap")==0
493 || strcasecmp(type
, "spixmap")==0
494 || strcasecmp(type
, "mpixmap")==0
495 || strcasecmp(type
, "tpixmap")==0) {
497 Pixmap pixmap
= None
;
498 RImage
*image
= NULL
;
504 GETSTRORGOTO(val
, tmp
, 1, error
);
506 if (toupper(type[0]) == 'T' || toupper(type[0]) == 'C')
507 pixmap = LoadJPEG(rc, tmp, &iwidth, &iheight);
511 image
= loadImage(rc
, tmp
);
515 iwidth
= image
->width
;
516 iheight
= image
->height
;
519 GETSTRORGOTO(val
, tmp
, 2, error
);
521 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
522 wwarning("could not parse color %s in texture %s\n", tmp
, text
);
523 RReleaseImage(image
);
526 if (!XAllocColor(dpy
, DefaultColormap(dpy
, scr
), &color
)) {
527 rcolor
.red
= color
.red
>> 8;
528 rcolor
.green
= color
.green
>> 8;
529 rcolor
.blue
= color
.blue
>> 8;
530 RGetClosestXColor(rc
, &rcolor
, &color
);
536 /* for images with a transparent color */
537 if (image
->data
[3]) {
538 RCombineImageWithColor(image
, &rcolor
);
541 switch (toupper(type
[0])) {
543 texture
->width
= iwidth
;
544 texture
->height
= iheight
;
545 if (!pixmap
&& !RConvertImage(rc
, image
, &pixmap
)) {
546 wwarning("could not convert texture:%s",
547 RMessageForError(RErrorCode
));
548 RReleaseImage(image
);
552 RReleaseImage(image
);
554 texture
->pixmap
= pixmap
;
555 texture
->color
= color
;
561 Pixmap tpixmap
= XCreatePixmap( dpy
, root
, scrWidth
, scrHeight
, DefaultDepth(dpy
, scr
));
562 XFillRectangle(dpy
, tpixmap
, DefaultGC(dpy
, scr
), 0, 0, scrWidth
, scrHeight
);
564 texture
->pixmap
= tpixmap
;
565 texture
->color
= color
;
566 texture
->width
= scrWidth
;
567 texture
->height
= scrHeight
;
570 if (xineInfo
.count
) {
572 for (i
=0; i
<xineInfo
.count
; ++i
) {
573 applyImage(rc
, texture
, image
, type
[0],
574 xineInfo
.screens
[i
].pos
.x
, xineInfo
.screens
[i
].pos
.y
,
575 xineInfo
.screens
[i
].size
.width
, xineInfo
.screens
[i
].size
.height
);
578 applyImage(rc
, texture
, image
, type
[0], 0, 0, scrWidth
, scrHeight
);
580 #else /* !XINERAMA */
581 applyImage(rc
, texture
, image
, type
[0], 0, 0, scrWidth
, scrHeight
);
582 #endif /* !XINERAMA */
583 RReleaseImage(image
);
587 } else if (strcasecmp(type
, "thgradient")==0
588 || strcasecmp(type
, "tvgradient")==0
589 || strcasecmp(type
, "tdgradient")==0) {
591 RColor color1
, color2
;
601 GETSTRORGOTO(val
, file
, 1, error
);
603 GETSTRORGOTO(val
, tmp
, 2, error
);
607 GETSTRORGOTO(val
, tmp
, 3, error
);
609 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
610 wwarning("could not parse color %s in texture %s", tmp
, text
);
614 color1
.red
= color
.red
>> 8;
615 color1
.green
= color
.green
>> 8;
616 color1
.blue
= color
.blue
>> 8;
618 GETSTRORGOTO(val
, tmp
, 4, error
);
620 if (!XParseColor(dpy
, DefaultColormap(dpy
, scr
), tmp
, &color
)) {
621 wwarning("could not parse color %s in texture %s", tmp
, text
);
625 color2
.red
= color
.red
>> 8;
626 color2
.green
= color
.green
>> 8;
627 color2
.blue
= color
.blue
>> 8;
629 image
= loadImage(rc
, file
);
637 gtype
= RHorizontalGradient
;
639 theight
= image
->height
> scrHeight
? scrHeight
: image
->height
;
643 gtype
= RVerticalGradient
;
644 twidth
= image
->width
> scrWidth
? scrWidth
: image
->width
;
648 gtype
= RDiagonalGradient
;
653 gradient
= RRenderGradient(twidth
, theight
, &color1
, &color2
, gtype
);
656 wwarning("could not render texture:%s",
657 RMessageForError(RErrorCode
));
658 RReleaseImage(gradient
);
659 RReleaseImage(image
);
663 tiled
= RMakeTiledImage(image
, twidth
, theight
);
665 wwarning("could not render texture:%s",
666 RMessageForError(RErrorCode
));
667 RReleaseImage(gradient
);
668 RReleaseImage(image
);
671 RReleaseImage(image
);
673 RCombineImagesWithOpaqueness(tiled
, gradient
, opaq
);
674 RReleaseImage(gradient
);
676 if (!RConvertImage(rc
, tiled
, &pixmap
)) {
677 wwarning("could not convert texture:%s",
678 RMessageForError(RErrorCode
));
679 RReleaseImage(tiled
);
682 texture
->width
= tiled
->width
;
683 texture
->height
= tiled
->height
;
685 RReleaseImage(tiled
);
687 texture
->pixmap
= pixmap
;
688 } else if (strcasecmp(type
, "function")==0) {
690 void (*initFunc
) (Display
*, Colormap
);
691 RImage
* (*mainFunc
) (int, char**, int, int, int);
695 char *lib
, *func
, **argv
= 0;
700 goto function_cleanup
;
702 /* get the library name */
703 GETSTRORGOTO(val
, lib
, 1, function_cleanup
);
705 /* get the function name */
706 GETSTRORGOTO(val
, func
, 2, function_cleanup
);
709 argv
= (char**)wmalloc(argc
* sizeof(char*));
711 /* get the parameters */
713 for (i
=0; i
<argc
-1; i
++) {
714 GETSTRORGOTO(val
, tmp
, 3+i
, function_cleanup
);
715 argv
[i
+1] = wstrdup(tmp
);
718 handle
= dlopen(lib
, RTLD_LAZY
);
720 wwarning("could not find library %s", lib
);
721 goto function_cleanup
;
724 initFunc
= dlsym(handle
, "initWindowMaker");
726 wwarning("could not initialize library %s", lib
);
727 goto function_cleanup
;
729 initFunc(dpy
, DefaultColormap(dpy
, scr
));
731 mainFunc
= dlsym(handle
, func
);
733 wwarning("could not find function %s::%s", lib
, func
);
734 goto function_cleanup
;
736 image
= mainFunc(argc
, argv
, scrWidth
, scrHeight
, 0);
738 if (!RConvertImage(rc
, image
, &pixmap
)) {
739 wwarning("could not convert texture:%s",
740 RMessageForError(RErrorCode
));
741 goto function_cleanup
;
743 texture
->width
= scrWidth
;
744 texture
->height
= scrHeight
;
745 texture
->pixmap
= pixmap
;
751 for (i
=0; i
<argc
; i
++) {
759 RReleaseImage(image
);
765 wwarning("function textures not supported");
769 wwarning("invalid texture type %s", text
);
773 texture
->spec
= wstrdup(text
);
781 WMReleasePropList(texarray
);
788 freeTexture(BackgroundTexture
*texture
)
790 if (texture
->solid
) {
793 pixel
[0] = texture
->color
.pixel
;
794 /* dont free black/white pixels */
795 if (pixel
[0]!=BlackPixelOfScreen(DefaultScreenOfDisplay(dpy
))
796 && pixel
[0]!=WhitePixelOfScreen(DefaultScreenOfDisplay(dpy
)))
797 XFreeColors(dpy
, DefaultColormap(dpy
, scr
), pixel
, 1, 0);
799 if (texture
->pixmap
) {
800 XFreePixmap(dpy
, texture
->pixmap
);
802 wfree(texture
->spec
);
808 setupTexture(RContext
*rc
, BackgroundTexture
**textures
, int *maxTextures
,
809 int workspace
, char *texture
)
811 BackgroundTexture
*newTexture
= NULL
;
814 /* unset the texture */
816 if (textures
[workspace
]!=NULL
) {
817 textures
[workspace
]->refcount
--;
819 if (textures
[workspace
]->refcount
== 0)
820 freeTexture(textures
[workspace
]);
822 textures
[workspace
] = NULL
;
826 if (textures
[workspace
]
827 && strcasecmp(textures
[workspace
]->spec
, texture
)==0) {
828 /* texture did not change */
832 /* check if the same texture is already created */
833 for (i
= 0; i
< *maxTextures
; i
++) {
834 if (textures
[i
] && strcasecmp(textures
[i
]->spec
, texture
)==0) {
835 newTexture
= textures
[i
];
841 /* create the texture */
842 newTexture
= parseTexture(rc
, texture
);
847 if (textures
[workspace
]!=NULL
) {
849 textures
[workspace
]->refcount
--;
851 if (textures
[workspace
]->refcount
== 0)
852 freeTexture(textures
[workspace
]);
855 newTexture
->refcount
++;
856 textures
[workspace
] = newTexture
;
858 if (*maxTextures
< workspace
)
859 *maxTextures
= workspace
;
865 duplicatePixmap(Pixmap pixmap
, int width
, int height
)
870 /* must open a new display or the RetainPermanent will
871 * leave stuff allocated in RContext unallocated after exit */
872 tmpDpy
= XOpenDisplay(display
);
874 wwarning("could not open display to update background image information");
880 copyP
= XCreatePixmap(tmpDpy
, root
, width
, height
,
881 DefaultDepth(tmpDpy
, scr
));
882 XCopyArea(tmpDpy
, pixmap
, copyP
, DefaultGC(tmpDpy
, scr
),
883 0, 0, width
, height
, 0, 0);
884 XSync(tmpDpy
, False
);
886 XSetCloseDownMode(tmpDpy
, RetainPermanent
);
887 XCloseDisplay(tmpDpy
);
895 dummyErrorHandler(Display
*dpy
, XErrorEvent
*err
)
901 setPixmapProperty(Pixmap pixmap
)
903 static Atom prop
= 0;
906 unsigned long length
, after
;
911 prop
= XInternAtom(dpy
, "_XROOTPMAP_ID", False
);
916 /* Clear out the old pixmap */
917 XGetWindowProperty(dpy
, root
, prop
, 0L, 1L, False
, AnyPropertyType
,
918 &type
, &format
, &length
, &after
, &data
);
920 if ((type
== XA_PIXMAP
) && (format
== 32) && (length
== 1)) {
921 XSetErrorHandler(dummyErrorHandler
);
922 XKillClient(dpy
, *((Pixmap
*)data
));
924 XSetErrorHandler(NULL
);
925 mode
= PropModeReplace
;
927 mode
= PropModeAppend
;
930 XChangeProperty(dpy
, root
, prop
, XA_PIXMAP
, 32, mode
,
931 (unsigned char *) &pixmap
, 1);
933 XDeleteProperty(dpy
, root
, prop
);
943 changeTexture(BackgroundTexture
*texture
)
949 if (texture
->solid
) {
950 XSetWindowBackground(dpy
, root
, texture
->color
.pixel
);
952 XSetWindowBackgroundPixmap(dpy
, root
, texture
->pixmap
);
954 XClearWindow(dpy
, root
);
961 pixmap
= duplicatePixmap(texture
->pixmap
, texture
->width
,
964 setPixmapProperty(pixmap
);
970 readmsg(int fd
, unsigned char *buffer
, int size
)
976 count
= read(fd
, buffer
, size
);
990 * sizeSntexture_spec - sets the texture for workspace n
991 * sizeCn - change background texture to the one for workspace n
992 * sizePpath - set the pixmap search path
995 * size = 4 bytes for length of the message data
998 helperLoop(RContext
*rc
)
1000 BackgroundTexture
*textures
[WORKSPACE_COUNT
];
1001 int maxTextures
= 0;
1002 unsigned char buffer
[2048], buf
[8];
1006 memset(textures
, 0, WORKSPACE_COUNT
*sizeof(BackgroundTexture
*));
1012 /* get length of message */
1013 if (readmsg(0, buffer
, 4) < 0) {
1014 wsyserror("error reading message from Window Maker");
1016 if (errcount
== 0) {
1022 memcpy(buf
, buffer
, 4);
1027 if (readmsg(0, buffer
, size
) < 0) {
1028 wsyserror("error reading message from Window Maker");
1030 if (errcount
== 0) {
1037 printf("RECEIVED %s\n",buffer
);
1039 if (buffer
[0]!='P' && buffer
[0]!='K') {
1040 memcpy(buf
, &buffer
[1], 4);
1042 workspace
= atoi(buf
);
1043 if (workspace
< 0 || workspace
>= WORKSPACE_COUNT
) {
1044 wwarning("received message with invalid workspace number %i\n",
1050 switch (buffer
[0]) {
1053 printf("set texture %s\n", &buffer
[5]);
1055 setupTexture(rc
, textures
, &maxTextures
, workspace
, &buffer
[5]);
1060 printf("change texture %i\n", workspace
);
1062 if (!textures
[workspace
]) {
1063 changeTexture(textures
[0]);
1065 changeTexture(textures
[workspace
]);
1071 printf("change pixmappath %s\n", &buffer
[1]);
1075 PixmapPath
= wstrdup(&buffer
[1]);
1080 printf("unset workspace %i\n", workspace
);
1082 setupTexture(rc
, textures
, &maxTextures
, workspace
, NULL
);
1087 printf("exit command\n");
1092 wwarning("unknown message received");
1100 updateDomain(char *domain
, char *key
, char *texture
)
1102 char *program
= "wdwrite";
1104 /* here is a mem leak */
1105 system(wstrconcat("wdwrite ",
1106 wstrconcat(domain
, smooth
? " SmoothWorkspaceBack YES"
1107 : " SmoothWorkspaceBack NO")));
1109 execlp(program
, program
, domain
, key
, texture
, NULL
);
1110 wwarning("warning could not run \"%s\"", program
);
1116 globalDefaultsPathForDomain(char *domain
)
1120 sprintf(path
, "%s/WindowMaker/%s", SYSCONFDIR
, domain
);
1122 return wstrdup(path
);
1127 getValueForKey(char *domain
, char *keyName
)
1130 WMPropList
*key
, *val
, *d
;
1132 key
= WMCreatePLString(keyName
);
1134 /* try to find PixmapPath in user defaults */
1135 path
= wdefaultspathfordomain(domain
);
1136 d
= WMReadPropListFromFile(path
);
1138 wwarning("could not open domain file %s", path
);
1142 if (d
&& !WMIsPLDictionary(d
)) {
1143 WMReleasePropList(d
);
1147 val
= WMGetFromPLDictionary(d
, key
);
1151 /* try to find PixmapPath in global defaults */
1153 path
= globalDefaultsPathForDomain(domain
);
1155 wwarning("could not locate file for domain %s", domain
);
1158 d
= WMReadPropListFromFile(path
);
1162 if (d
&& !WMIsPLDictionary(d
)) {
1163 WMReleasePropList(d
);
1167 val
= WMGetFromPLDictionary(d
, key
);
1175 WMRetainPropList(val
);
1177 WMReleasePropList(key
);
1179 WMReleasePropList(d
);
1187 getPixmapPath(char *domain
)
1193 val
= getValueForKey(domain
, "PixmapPath");
1195 if (!val
|| !WMIsPLArray(val
)) {
1197 WMReleasePropList(val
);
1201 count
= WMGetPropListItemCount(val
);
1203 for (i
=0; i
<count
; i
++) {
1206 v
= WMGetFromPLArray(val
, i
);
1207 if (!v
|| !WMIsPLString(v
)) {
1210 len
+= strlen(WMGetFromPLString(v
))+1;
1213 ptr
= data
= wmalloc(len
+1);
1216 for (i
=0; i
<count
; i
++) {
1219 v
= WMGetFromPLArray(val
, i
);
1220 if (!v
|| !WMIsPLString(v
)) {
1223 strcpy(ptr
, WMGetFromPLString(v
));
1225 ptr
+= strlen(WMGetFromPLString(v
));
1230 ptr
--; *(ptr
--) = 0;
1232 WMReleasePropList(val
);
1239 getFullPixmapPath(char *file
)
1243 if (!PixmapPath
|| !(tmp
= wfindfile(PixmapPath
, file
))) {
1245 char *path
= wmalloc(bsize
);
1247 while (!getcwd(path
, bsize
)) {
1249 path
= wrealloc(path
, bsize
);
1252 tmp
= wstrconcat(path
, "/");
1254 path
= wstrconcat(tmp
, file
);
1260 /* the file is in the PixmapPath */
1263 return wstrdup(file
);
1278 print_help(char *ProgName
)
1280 printf("Usage: %s [options] [image]\n", ProgName
);
1281 puts("Sets the workspace background to the specified image or a texture and optionally update Window Maker configuration");
1283 #define P(m) puts(m)
1284 P(" -display display to use");
1285 P(" -d, --dither dither image");
1286 P(" -m, --match match colors");
1287 P(" -S, --smooth smooth scaled image");
1288 P(" -b, --back-color <color> background color");
1289 P(" -t, --tile tile image");
1290 P(" -e, --center center image");
1291 P(" -s, --scale scale image (default)");
1292 P(" -a, --maxscale scale image and keep aspect ratio");
1293 P(" -u, --update-wmaker update WindowMaker domain database");
1294 P(" -D, --update-domain <domain> update <domain> database");
1295 P(" -c, --colors <cpc> colors per channel to use");
1296 P(" -p, --parse <texture> proplist style texture specification");
1297 P(" -w, --workspace <workspace> update background for the specified workspace");
1298 P(" --version show version of wmsetbg and exit");
1299 P(" --help show this help and exit");
1306 changeTextureForWorkspace(char *domain
, char *texture
, int workspace
)
1308 WMPropList
*array
, *val
;
1312 val
= WMCreatePropListFromDescription(texture
);
1314 wwarning("could not parse texture %s", texture
);
1318 array
= getValueForKey("WindowMaker", "WorkspaceSpecificBack");
1321 array
= WMCreatePLArray(NULL
, NULL
);
1324 j
= WMGetPropListItemCount(array
);
1325 if (workspace
>= j
) {
1328 empty
= WMCreatePLArray(NULL
, NULL
);
1330 while (j
++ < workspace
-1) {
1331 WMAddToPLArray(array
, empty
);
1333 WMAddToPLArray(array
, val
);
1335 WMDeleteFromPLArray(array
, workspace
);
1336 WMInsertInPLArray(array
, workspace
, val
);
1339 value
= WMGetPropListDescription(array
, False
);
1340 updateDomain(domain
, "WorkspaceSpecificBack", value
);
1345 main(int argc
, char **argv
)
1350 RContextAttributes rattr
;
1351 char *style
= "spixmap";
1352 char *back_color
= "gray20";
1353 char *image_name
= NULL
;
1354 char *domain
= "WindowMaker";
1355 int update
=0, cpc
=4, render_mode
=RDitheredRendering
, obey_user
=0;
1356 char *texture
= NULL
;
1359 signal(SIGINT
, SIG_DFL
);
1360 signal(SIGTERM
, SIG_DFL
);
1361 signal(SIGQUIT
, SIG_DFL
);
1362 signal(SIGSEGV
, SIG_DFL
);
1363 signal(SIGBUS
, SIG_DFL
);
1364 signal(SIGFPE
, SIG_DFL
);
1365 signal(SIGABRT
, SIG_DFL
);
1366 signal(SIGHUP
, SIG_DFL
);
1367 signal(SIGPIPE
, SIG_DFL
);
1368 signal(SIGCHLD
, SIG_DFL
);
1370 WMInitializeApplication("wmsetbg", &argc
, argv
);
1372 for (i
=1; i
<argc
; i
++) {
1373 if (strcmp(argv
[i
], "-helper")==0) {
1375 } else if (strcmp(argv
[i
], "-display")==0) {
1378 wfatal("too few arguments for %s\n", argv
[i
-1]);
1382 } else if (strcmp(argv
[i
], "-s")==0
1383 || strcmp(argv
[i
], "--scale")==0) {
1385 } else if (strcmp(argv
[i
], "-t")==0
1386 || strcmp(argv
[i
], "--tile")==0) {
1388 } else if (strcmp(argv
[i
], "-e")==0
1389 || strcmp(argv
[i
], "--center")==0) {
1391 } else if (strcmp(argv
[i
], "-a")==0
1392 || strcmp(argv
[i
], "--maxscale")==0) {
1394 } else if (strcmp(argv
[i
], "-d")==0
1395 || strcmp(argv
[i
], "--dither")==0) {
1396 render_mode
= RDitheredRendering
;
1398 } else if (strcmp(argv
[i
], "-m")==0
1399 || strcmp(argv
[i
], "--match")==0) {
1400 render_mode
= RBestMatchRendering
;
1402 } else if (strcmp(argv
[i
], "-S")==0
1403 || strcmp(argv
[i
], "--smooth")==0) {
1405 } else if (strcmp(argv
[i
], "-u")==0
1406 || strcmp(argv
[i
], "--update-wmaker")==0) {
1408 } else if (strcmp(argv
[i
], "-D")==0
1409 || strcmp(argv
[i
], "--update-domain")==0) {
1413 wfatal("too few arguments for %s\n", argv
[i
-1]);
1416 domain
= wstrdup(argv
[i
]);
1417 } else if (strcmp(argv
[i
], "-c")==0
1418 || strcmp(argv
[i
], "--colors")==0) {
1421 wfatal("too few arguments for %s\n", argv
[i
-1]);
1424 if (sscanf(argv
[i
], "%i", &cpc
)!=1) {
1425 wfatal("bad value for colors per channel: \"%s\"\n", argv
[i
]);
1428 } else if (strcmp(argv
[i
], "-b")==0
1429 || strcmp(argv
[i
], "--back-color")==0) {
1432 wfatal("too few arguments for %s\n", argv
[i
-1]);
1435 back_color
= argv
[i
];
1436 } else if (strcmp(argv
[i
], "-p")==0
1437 || strcmp(argv
[i
], "--parse")==0) {
1440 wfatal("too few arguments for %s\n", argv
[i
-1]);
1444 } else if (strcmp(argv
[i
], "-w")==0
1445 || strcmp(argv
[i
], "--workspace")==0) {
1448 wfatal("too few arguments for %s\n", argv
[i
-1]);
1451 if (sscanf(argv
[i
], "%i", &workspace
)!=1) {
1452 wfatal("bad value for workspace number: \"%s\"",
1456 } else if (strcmp(argv
[i
], "--version")==0) {
1458 printf(PROG_VERSION
);
1461 } else if (strcmp(argv
[i
], "--help")==0) {
1462 print_help(argv
[0]);
1464 } else if (argv
[i
][0] != '-') {
1465 image_name
= argv
[i
];
1467 printf("%s: invalid argument '%s'\n", argv
[0], argv
[i
]);
1468 printf("Try '%s --help' for more information\n", argv
[0]);
1472 if (!image_name
&& !texture
&& !helperMode
) {
1473 printf("%s: you must specify a image file name or a texture\n",
1475 printf("Try '%s --help' for more information\n", argv
[0]);
1480 PixmapPath
= getPixmapPath(domain
);
1483 #if 0 /* some problem with Alpha... TODO: check if its right */
1484 val
= WMGetFromPLDictionary(domain
,
1485 WMCreatePLString("SmoothWorkspaceBack"));
1487 val
= getValueForKey(domain
, "SmoothWorkspaceBack");
1490 if (val
&& WMIsPLString(val
) && strcasecmp(WMGetFromPLString(val
), "YES")==0)
1494 dpy
= XOpenDisplay(display
);
1496 wfatal("could not open display");
1500 XSynchronize(dpy
, 1);
1503 root
= DefaultRootWindow(dpy
);
1505 scr
= DefaultScreen(dpy
);
1507 scrWidth
= WidthOfScreen(DefaultScreenOfDisplay(dpy
));
1508 scrHeight
= HeightOfScreen(DefaultScreenOfDisplay(dpy
));
1514 if (!obey_user
&& DefaultDepth(dpy
, scr
) <= 8)
1515 render_mode
= RDitheredRendering
;
1517 rattr
.flags
= RC_RenderMode
| RC_ColorsPerChannel
1518 | RC_StandardColormap
| RC_DefaultVisual
;
1519 rattr
.render_mode
= render_mode
;
1520 rattr
.colors_per_channel
= cpc
;
1521 rattr
.standard_colormap_mode
= RCreateStdColormap
;
1523 rc
= RCreateContext(dpy
, scr
, &rattr
);
1526 rattr
.standard_colormap_mode
= RIgnoreStdColormap
;
1527 rc
= RCreateContext(dpy
, scr
, &rattr
);
1531 wfatal("could not initialize wrlib: %s",
1532 RMessageForError(RErrorCode
));
1537 /* lower priority, so that it wont use all the CPU */
1542 BackgroundTexture
*tex
;
1546 char *image_path
= getFullPixmapPath(image_name
);
1548 sprintf(buffer
, "(%s, \"%s\", %s)", style
, image_path
, back_color
);
1550 texture
= (char*)buffer
;
1553 if (update
&& workspace
< 0) {
1554 updateDomain(domain
, "WorkspaceBack", texture
);
1557 tex
= parseTexture(rc
, texture
);
1564 /* always update domain */
1565 changeTextureForWorkspace(domain
, texture
, workspace
);