mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 12:28:22 +01:00
---------------
- Added retain/release mechanism to RImage by adding RRetainImage() and
RReleaseImage(). RDestroyImage() is an alias to RReleaseImage() now, but
will be removed in a future release because it no longer fits with the
semantics. Will be kept for a while to allow a smoother transition.
More about in wrlib/NEWS
For WINGs:
----------
- Small API change:
1. Renamed WMSetApplicationIconImage(), WMGetApplicationIconImage() and
WMSetWindowMiniwindowImage() to respectively WMSetApplicationIconPixmap(),
WMGetApplicationIconPixmap() and WMSetWindowMiniwindowPixmap()
They operate on a WMPixmap which is practically an X Pixmap with no alpha
channel information and the new name is more suggestive and also leaves
room for the new functions added for operating on images with alpha info.
2. Added WMSetApplicationIconImage() and WMGetApplicationIconImage() which
operate on an RImage and store alpha information too.
3. Added WMGetApplicationIconBlendedPixmap() which will take the image with
alpha set by WMSetApplicationIconImage() and will blend it with a color.
If color is NULL it will blend using the default panel color (#aeaaae)
All these changes will allow WINGs to handle images with alpha blending
correctly in panels and wherever else needed. More about in WINGs/NEWS.
- updated panels to use the newly available RImages if present and fallback
to old WMPixmaps if not, to properly show alpha blended images.
- replaced some still left malloc's with wmalloc's.
For Window Maker:
-----------------
- Fixed wrong mapping position of the "Docked Applications Panel" for some
icons.
- Smoother animation for the smiley =)
- Made images with alpha blending be shown correctly in the panels and the
icon chooser.
- The icon image set to be shown in panels ("Logo.WMPanel") will be
automatically updated if its entry in WMWindowAttributes changes (without
a need to restart as until now).
*** Note!!! ***
If you are developing applications with one of libwraster or libWINGs
then you should look to wrlib/NEWS and WINGs/NEWS to see what changed
and how should you update your code.
1481 lines
32 KiB
C
1481 lines
32 KiB
C
/* wmsetbg.c- sets root window background image and also works as
|
|
* workspace background setting helper for wmaker
|
|
*
|
|
* WindowMaker window manager
|
|
*
|
|
* Copyright (c) 1998, 1999 Alfredo K. Kojima
|
|
* Copyright (c) 1998 Dan Pascu
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
* USA.
|
|
*/
|
|
|
|
/*
|
|
* TODO: rewrite, too dirty
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xatom.h>
|
|
#include <string.h>
|
|
#include <pwd.h>
|
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <ctype.h>
|
|
|
|
#include "../src/config.h"
|
|
|
|
#ifdef HAVE_DLFCN_H
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
#include "../src/wconfig.h"
|
|
|
|
#include <WINGs/WINGs.h>
|
|
#include <wraster.h>
|
|
|
|
#include <proplist.h>
|
|
|
|
#define PROG_VERSION "wmsetbg (Window Maker) 2.7"
|
|
|
|
|
|
#define WORKSPACE_COUNT (MAX_WORKSPACES+1)
|
|
|
|
|
|
Display *dpy;
|
|
char *display = "";
|
|
Window root;
|
|
int scr;
|
|
int scrWidth;
|
|
int scrHeight;
|
|
|
|
|
|
Bool smooth = False;
|
|
|
|
|
|
Pixmap CurrentPixmap = None;
|
|
char *PixmapPath = NULL;
|
|
|
|
|
|
extern Pixmap LoadJPEG(RContext *rc, char *file_name, int *width, int *height);
|
|
|
|
|
|
typedef struct BackgroundTexture {
|
|
int refcount;
|
|
|
|
int solid;
|
|
|
|
char *spec;
|
|
|
|
XColor color;
|
|
Pixmap pixmap; /* for all textures, including solid */
|
|
int width; /* size of the pixmap */
|
|
int height;
|
|
} BackgroundTexture;
|
|
|
|
|
|
|
|
RImage*
|
|
loadImage(RContext *rc, char *file)
|
|
{
|
|
char *path;
|
|
RImage *image;
|
|
|
|
if (access(file, F_OK)!=0) {
|
|
path = wfindfile(PixmapPath, file);
|
|
if (!path) {
|
|
wwarning("%s:could not find image file used in texture", file);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
path = wstrdup(file);
|
|
}
|
|
|
|
image = RLoadImage(rc, path, 0);
|
|
if (!image) {
|
|
wwarning("%s:could not load image file used in texture:%s", path,
|
|
RMessageForError(RErrorCode));
|
|
}
|
|
wfree(path);
|
|
|
|
return image;
|
|
}
|
|
|
|
|
|
BackgroundTexture*
|
|
parseTexture(RContext *rc, char *text)
|
|
{
|
|
BackgroundTexture *texture = NULL;
|
|
proplist_t texarray;
|
|
proplist_t val;
|
|
int count;
|
|
char *tmp;
|
|
char *type;
|
|
|
|
#define GETSTRORGOTO(val, str, i, label) \
|
|
val = PLGetArrayElement(texarray, i);\
|
|
if (!PLIsString(val)) {\
|
|
wwarning("could not parse texture %s", text);\
|
|
goto label;\
|
|
}\
|
|
str = PLGetString(val)
|
|
|
|
texarray = PLGetProplistWithDescription(text);
|
|
if (!texarray || !PLIsArray(texarray)
|
|
|| (count = PLGetNumberOfElements(texarray)) < 2) {
|
|
|
|
wwarning("could not parse texture %s", text);
|
|
if (texarray)
|
|
PLRelease(texarray);
|
|
return NULL;
|
|
}
|
|
|
|
texture = wmalloc(sizeof(BackgroundTexture));
|
|
memset(texture, 0, sizeof(BackgroundTexture));
|
|
|
|
GETSTRORGOTO(val, type, 0, error);
|
|
|
|
if (strcasecmp(type, "solid")==0) {
|
|
XColor color;
|
|
Pixmap pixmap;
|
|
|
|
texture->solid = 1;
|
|
|
|
GETSTRORGOTO(val, tmp, 1, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s", tmp, text);
|
|
goto error;
|
|
}
|
|
XAllocColor(dpy, DefaultColormap(dpy, scr), &color);
|
|
|
|
pixmap = XCreatePixmap(dpy, root, 8, 8, DefaultDepth(dpy, scr));
|
|
XSetForeground(dpy, DefaultGC(dpy, scr), color.pixel);
|
|
XFillRectangle(dpy, pixmap, DefaultGC(dpy, scr), 0, 0, 8, 8);
|
|
|
|
texture->pixmap = pixmap;
|
|
texture->color = color;
|
|
texture->width = 8;
|
|
texture->height = 8;
|
|
} else if (strcasecmp(type, "vgradient")==0
|
|
|| strcasecmp(type, "dgradient")==0
|
|
|| strcasecmp(type, "hgradient")==0) {
|
|
XColor color;
|
|
RColor color1, color2;
|
|
RImage *image;
|
|
Pixmap pixmap;
|
|
int gtype;
|
|
int iwidth, iheight;
|
|
|
|
GETSTRORGOTO(val, tmp, 1, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s", tmp, text);
|
|
goto error;
|
|
}
|
|
|
|
color1.red = color.red >> 8;
|
|
color1.green = color.green >> 8;
|
|
color1.blue = color.blue >> 8;
|
|
|
|
GETSTRORGOTO(val, tmp, 2, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s", tmp, text);
|
|
goto error;
|
|
}
|
|
|
|
color2.red = color.red >> 8;
|
|
color2.green = color.green >> 8;
|
|
color2.blue = color.blue >> 8;
|
|
|
|
switch (type[0]) {
|
|
case 'h':
|
|
case 'H':
|
|
gtype = RHorizontalGradient;
|
|
iwidth = scrWidth;
|
|
iheight = 32;
|
|
break;
|
|
case 'V':
|
|
case 'v':
|
|
gtype = RVerticalGradient;
|
|
iwidth = 32;
|
|
iheight = scrHeight;
|
|
break;
|
|
default:
|
|
gtype = RDiagonalGradient;
|
|
iwidth = scrWidth;
|
|
iheight = scrHeight;
|
|
break;
|
|
}
|
|
|
|
image = RRenderGradient(iwidth, iheight, &color1, &color2, gtype);
|
|
|
|
if (!image) {
|
|
wwarning("could not render gradient texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
goto error;
|
|
}
|
|
|
|
if (!RConvertImage(rc, image, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
|
|
texture->width = image->width;
|
|
texture->height = image->height;
|
|
RReleaseImage(image);
|
|
|
|
texture->pixmap = pixmap;
|
|
} else if (strcasecmp(type, "mvgradient")==0
|
|
|| strcasecmp(type, "mdgradient")==0
|
|
|| strcasecmp(type, "mhgradient")==0) {
|
|
XColor color;
|
|
RColor **colors;
|
|
RImage *image;
|
|
Pixmap pixmap;
|
|
int i, j;
|
|
int gtype;
|
|
int iwidth, iheight;
|
|
|
|
colors = malloc(sizeof(RColor*)*(count-1));
|
|
if (!colors) {
|
|
wwarning("out of memory while parsing texture");
|
|
goto error;
|
|
}
|
|
memset(colors, 0, sizeof(RColor*)*(count-1));
|
|
|
|
for (i = 2; i < count; i++) {
|
|
val = PLGetArrayElement(texarray, i);
|
|
if (!PLIsString(val)) {
|
|
wwarning("could not parse texture %s", text);
|
|
|
|
for (j = 0; colors[j]!=NULL; j++)
|
|
wfree(colors[j]);
|
|
wfree(colors);
|
|
goto error;
|
|
}
|
|
tmp = PLGetString(val);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s",
|
|
tmp, text);
|
|
|
|
for (j = 0; colors[j]!=NULL; j++)
|
|
wfree(colors[j]);
|
|
wfree(colors);
|
|
goto error;
|
|
}
|
|
if (!(colors[i-2] = malloc(sizeof(RColor)))) {
|
|
wwarning("out of memory while parsing texture");
|
|
|
|
for (j = 0; colors[j]!=NULL; j++)
|
|
wfree(colors[j]);
|
|
wfree(colors);
|
|
goto error;
|
|
}
|
|
|
|
colors[i-2]->red = color.red >> 8;
|
|
colors[i-2]->green = color.green >> 8;
|
|
colors[i-2]->blue = color.blue >> 8;
|
|
}
|
|
|
|
switch (type[1]) {
|
|
case 'h':
|
|
case 'H':
|
|
gtype = RHorizontalGradient;
|
|
iwidth = scrWidth;
|
|
iheight = 32;
|
|
break;
|
|
case 'V':
|
|
case 'v':
|
|
gtype = RVerticalGradient;
|
|
iwidth = 32;
|
|
iheight = scrHeight;
|
|
break;
|
|
default:
|
|
gtype = RDiagonalGradient;
|
|
iwidth = scrWidth;
|
|
iheight = scrHeight;
|
|
break;
|
|
}
|
|
|
|
image = RRenderMultiGradient(iwidth, iheight, colors, gtype);
|
|
|
|
for (j = 0; colors[j]!=NULL; j++)
|
|
wfree(colors[j]);
|
|
wfree(colors);
|
|
|
|
if (!image) {
|
|
wwarning("could not render gradient texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
goto error;
|
|
}
|
|
|
|
if (!RConvertImage(rc, image, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
|
|
texture->width = image->width;
|
|
texture->height = image->height;
|
|
RReleaseImage(image);
|
|
|
|
texture->pixmap = pixmap;
|
|
} else if (strcasecmp(type, "cpixmap")==0
|
|
|| strcasecmp(type, "spixmap")==0
|
|
|| strcasecmp(type, "mpixmap")==0
|
|
|| strcasecmp(type, "tpixmap")==0) {
|
|
XColor color;
|
|
Pixmap pixmap = None;
|
|
RImage *image = NULL;
|
|
int w, h;
|
|
int iwidth, iheight;
|
|
RColor rcolor;
|
|
|
|
|
|
GETSTRORGOTO(val, tmp, 1, error);
|
|
/*
|
|
if (toupper(type[0]) == 'T' || toupper(type[0]) == 'C')
|
|
pixmap = LoadJPEG(rc, tmp, &iwidth, &iheight);
|
|
*/
|
|
|
|
if (!pixmap) {
|
|
image = loadImage(rc, tmp);
|
|
if (!image) {
|
|
goto error;
|
|
}
|
|
iwidth = image->width;
|
|
iheight = image->height;
|
|
}
|
|
|
|
GETSTRORGOTO(val, tmp, 2, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s\n", tmp, text);
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
if (!XAllocColor(dpy, DefaultColormap(dpy, scr), &color)) {
|
|
rcolor.red = color.red >> 8;
|
|
rcolor.green = color.green >> 8;
|
|
rcolor.blue = color.blue >> 8;
|
|
RGetClosestXColor(rc, &rcolor, &color);
|
|
} else {
|
|
rcolor.red = 0;
|
|
rcolor.green = 0;
|
|
rcolor.blue = 0;
|
|
}
|
|
/* for images with a transparent color */
|
|
if (image->data[3]) {
|
|
RCombineImageWithColor(image, &rcolor);
|
|
}
|
|
|
|
switch (toupper(type[0])) {
|
|
case 'T':
|
|
texture->width = iwidth;
|
|
texture->height = iheight;
|
|
if (!pixmap && !RConvertImage(rc, image, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
if (image)
|
|
RReleaseImage(image);
|
|
break;
|
|
case 'S':
|
|
case 'M':
|
|
if (toupper(type[0])=='S') {
|
|
w = scrWidth;
|
|
h = scrHeight;
|
|
} else {
|
|
if (iwidth*scrHeight > iheight*scrWidth) {
|
|
w = scrWidth;
|
|
h = (scrWidth*iheight)/iwidth;
|
|
} else {
|
|
h = scrHeight;
|
|
w = (scrHeight*iwidth)/iheight;
|
|
}
|
|
}
|
|
if (w != image->width || h != image->height) {
|
|
RImage *simage;
|
|
|
|
if (smooth)
|
|
simage = RSmoothScaleImage(image, w, h);
|
|
else
|
|
simage = RScaleImage(image, w, h);
|
|
if (!simage) {
|
|
wwarning("could not scale image:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
RReleaseImage(image);
|
|
image = simage;
|
|
}
|
|
iwidth = image->width;
|
|
iheight = image->height;
|
|
|
|
/* fall through */
|
|
case 'C':
|
|
{
|
|
Pixmap cpixmap;
|
|
|
|
if (!pixmap && !RConvertImage(rc, image, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
|
|
if (iwidth != scrWidth || iheight != scrHeight) {
|
|
int x, y, sx, sy, w, h;
|
|
|
|
cpixmap = XCreatePixmap(dpy, root, scrWidth, scrHeight,
|
|
DefaultDepth(dpy, scr));
|
|
|
|
XSetForeground(dpy, DefaultGC(dpy, scr), color.pixel);
|
|
XFillRectangle(dpy, cpixmap, DefaultGC(dpy, scr),
|
|
0, 0, scrWidth, scrHeight);
|
|
|
|
if (iheight < scrHeight) {
|
|
h = iheight;
|
|
y = (scrHeight - h)/2;
|
|
sy = 0;
|
|
} else {
|
|
sy = (iheight - scrHeight)/2;
|
|
y = 0;
|
|
h = scrHeight;
|
|
}
|
|
if (iwidth < scrWidth) {
|
|
w = iwidth;
|
|
x = (scrWidth - w)/2;
|
|
sx = 0;
|
|
} else {
|
|
sx = (iwidth - scrWidth)/2;
|
|
x = 0;
|
|
w = scrWidth;
|
|
}
|
|
|
|
XCopyArea(dpy, pixmap, cpixmap, DefaultGC(dpy, scr),
|
|
sx, sy, w, h, x, y);
|
|
XFreePixmap(dpy, pixmap);
|
|
pixmap = cpixmap;
|
|
}
|
|
if (image)
|
|
RReleaseImage(image);
|
|
|
|
texture->width = scrWidth;
|
|
texture->height = scrHeight;
|
|
}
|
|
break;
|
|
}
|
|
|
|
texture->pixmap = pixmap;
|
|
texture->color = color;
|
|
} else if (strcasecmp(type, "thgradient")==0
|
|
|| strcasecmp(type, "tvgradient")==0
|
|
|| strcasecmp(type, "tdgradient")==0) {
|
|
XColor color;
|
|
RColor color1, color2;
|
|
RImage *image;
|
|
RImage *gradient;
|
|
RImage *tiled;
|
|
Pixmap pixmap;
|
|
int opaq;
|
|
char *file;
|
|
int gtype;
|
|
int twidth, theight;
|
|
|
|
GETSTRORGOTO(val, file, 1, error);
|
|
|
|
GETSTRORGOTO(val, tmp, 2, error);
|
|
|
|
opaq = atoi(tmp);
|
|
|
|
GETSTRORGOTO(val, tmp, 3, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s", tmp, text);
|
|
goto error;
|
|
}
|
|
|
|
color1.red = color.red >> 8;
|
|
color1.green = color.green >> 8;
|
|
color1.blue = color.blue >> 8;
|
|
|
|
GETSTRORGOTO(val, tmp, 4, error);
|
|
|
|
if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
|
|
wwarning("could not parse color %s in texture %s", tmp, text);
|
|
goto error;
|
|
}
|
|
|
|
color2.red = color.red >> 8;
|
|
color2.green = color.green >> 8;
|
|
color2.blue = color.blue >> 8;
|
|
|
|
image = loadImage(rc, file);
|
|
if (!image) {
|
|
goto error;
|
|
}
|
|
|
|
switch (type[1]) {
|
|
case 'h':
|
|
case 'H':
|
|
gtype = RHorizontalGradient;
|
|
twidth = scrWidth;
|
|
theight = image->height > scrHeight ? scrHeight : image->height;
|
|
break;
|
|
case 'V':
|
|
case 'v':
|
|
gtype = RVerticalGradient;
|
|
twidth = image->width > scrWidth ? scrWidth : image->width;
|
|
theight = scrHeight;
|
|
break;
|
|
default:
|
|
gtype = RDiagonalGradient;
|
|
twidth = scrWidth;
|
|
theight = scrHeight;
|
|
break;
|
|
}
|
|
gradient = RRenderGradient(twidth, theight, &color1, &color2, gtype);
|
|
|
|
if (!gradient) {
|
|
wwarning("could not render texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(gradient);
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
|
|
tiled = RMakeTiledImage(image, twidth, theight);
|
|
if (!tiled) {
|
|
wwarning("could not render texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(gradient);
|
|
RReleaseImage(image);
|
|
goto error;
|
|
}
|
|
RReleaseImage(image);
|
|
|
|
RCombineImagesWithOpaqueness(tiled, gradient, opaq);
|
|
RReleaseImage(gradient);
|
|
|
|
if (!RConvertImage(rc, tiled, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
RReleaseImage(tiled);
|
|
goto error;
|
|
}
|
|
texture->width = tiled->width;
|
|
texture->height = tiled->height;
|
|
|
|
RReleaseImage(tiled);
|
|
|
|
texture->pixmap = pixmap;
|
|
} else if (strcasecmp(type, "function")==0) {
|
|
#ifdef HAVE_DLFCN_H
|
|
void (*initFunc) (Display*, Colormap);
|
|
RImage* (*mainFunc) (int, char**, int, int, int);
|
|
Pixmap pixmap;
|
|
RImage *image = 0;
|
|
int success = 0;
|
|
char *lib, *func, **argv = 0;
|
|
void *handle = 0;
|
|
int i, argc;
|
|
|
|
if (count < 3)
|
|
goto function_cleanup;
|
|
|
|
/* get the library name */
|
|
GETSTRORGOTO(val, lib, 1, function_cleanup);
|
|
|
|
/* get the function name */
|
|
GETSTRORGOTO(val, func, 2, function_cleanup);
|
|
|
|
argc = count - 2;
|
|
argv = (char**)wmalloc(argc * sizeof(char*));
|
|
|
|
/* get the parameters */
|
|
argv[0] = func;
|
|
for (i=0; i<argc-1; i++) {
|
|
GETSTRORGOTO(val, tmp, 3+i, function_cleanup);
|
|
argv[i+1] = wstrdup(tmp);
|
|
}
|
|
|
|
handle = dlopen(lib, RTLD_LAZY);
|
|
if (!handle) {
|
|
wwarning("could not find library %s", lib);
|
|
goto function_cleanup;
|
|
}
|
|
|
|
initFunc = dlsym(handle, "initWindowMaker");
|
|
if (!initFunc) {
|
|
wwarning("could not initialize library %s", lib);
|
|
goto function_cleanup;
|
|
}
|
|
initFunc(dpy, DefaultColormap(dpy, scr));
|
|
|
|
mainFunc = dlsym(handle, func);
|
|
if (!mainFunc) {
|
|
wwarning("could not find function %s::%s", lib, func);
|
|
goto function_cleanup;
|
|
}
|
|
image = mainFunc(argc, argv, scrWidth, scrHeight, 0);
|
|
|
|
if (!RConvertImage(rc, image, &pixmap)) {
|
|
wwarning("could not convert texture:%s",
|
|
RMessageForError(RErrorCode));
|
|
goto function_cleanup;
|
|
}
|
|
texture->width = scrWidth;
|
|
texture->height = scrHeight;
|
|
texture->pixmap = pixmap;
|
|
success = 1;
|
|
|
|
function_cleanup:
|
|
if (argv) {
|
|
int i;
|
|
for (i=0; i<argc; i++) {
|
|
wfree(argv[i]);
|
|
}
|
|
}
|
|
if (handle) {
|
|
dlclose(handle);
|
|
}
|
|
if (image) {
|
|
RReleaseImage(image);
|
|
}
|
|
if (!success) {
|
|
goto error;
|
|
}
|
|
#else
|
|
wwarning("function textures not supported");
|
|
goto error;
|
|
#endif
|
|
} else {
|
|
wwarning("invalid texture type %s", text);
|
|
goto error;
|
|
}
|
|
|
|
texture->spec = wstrdup(text);
|
|
|
|
return texture;
|
|
|
|
error:
|
|
if (texture)
|
|
wfree(texture);
|
|
if (texarray)
|
|
PLRelease(texarray);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void
|
|
freeTexture(BackgroundTexture *texture)
|
|
{
|
|
if (texture->solid) {
|
|
long pixel[1];
|
|
|
|
pixel[0] = texture->color.pixel;
|
|
/* dont free black/white pixels */
|
|
if (pixel[0]!=BlackPixelOfScreen(DefaultScreenOfDisplay(dpy))
|
|
&& pixel[0]!=WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)))
|
|
XFreeColors(dpy, DefaultColormap(dpy, scr), pixel, 1, 0);
|
|
}
|
|
if (texture->pixmap) {
|
|
XFreePixmap(dpy, texture->pixmap);
|
|
}
|
|
wfree(texture->spec);
|
|
wfree(texture);
|
|
}
|
|
|
|
|
|
void
|
|
setupTexture(RContext *rc, BackgroundTexture **textures, int *maxTextures,
|
|
int workspace, char *texture)
|
|
{
|
|
BackgroundTexture *newTexture = NULL;
|
|
int i;
|
|
|
|
/* unset the texture */
|
|
if (!texture) {
|
|
if (textures[workspace]!=NULL) {
|
|
textures[workspace]->refcount--;
|
|
|
|
if (textures[workspace]->refcount == 0)
|
|
freeTexture(textures[workspace]);
|
|
}
|
|
textures[workspace] = NULL;
|
|
return;
|
|
}
|
|
|
|
if (textures[workspace]
|
|
&& strcasecmp(textures[workspace]->spec, texture)==0) {
|
|
/* texture did not change */
|
|
return;
|
|
}
|
|
|
|
/* check if the same texture is already created */
|
|
for (i = 0; i < *maxTextures; i++) {
|
|
if (textures[i] && strcasecmp(textures[i]->spec, texture)==0) {
|
|
newTexture = textures[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!newTexture) {
|
|
/* create the texture */
|
|
newTexture = parseTexture(rc, texture);
|
|
}
|
|
if (!newTexture)
|
|
return;
|
|
|
|
if (textures[workspace]!=NULL) {
|
|
|
|
textures[workspace]->refcount--;
|
|
|
|
if (textures[workspace]->refcount == 0)
|
|
freeTexture(textures[workspace]);
|
|
}
|
|
|
|
newTexture->refcount++;
|
|
textures[workspace] = newTexture;
|
|
|
|
if (*maxTextures < workspace)
|
|
*maxTextures = workspace;
|
|
}
|
|
|
|
|
|
|
|
Pixmap
|
|
duplicatePixmap(Pixmap pixmap, int width, int height)
|
|
{
|
|
Display *tmpDpy;
|
|
Pixmap copyP;
|
|
|
|
/* must open a new display or the RetainPermanent will
|
|
* leave stuff allocated in RContext unallocated after exit */
|
|
tmpDpy = XOpenDisplay(display);
|
|
if (!tmpDpy) {
|
|
wwarning("could not open display to update background image information");
|
|
|
|
return None;
|
|
} else {
|
|
XSync(dpy, False);
|
|
|
|
copyP = XCreatePixmap(tmpDpy, root, width, height,
|
|
DefaultDepth(tmpDpy, scr));
|
|
XCopyArea(tmpDpy, pixmap, copyP, DefaultGC(tmpDpy, scr),
|
|
0, 0, width, height, 0, 0);
|
|
XSync(tmpDpy, False);
|
|
|
|
XSetCloseDownMode(tmpDpy, RetainPermanent);
|
|
XCloseDisplay(tmpDpy);
|
|
}
|
|
|
|
return copyP;
|
|
}
|
|
|
|
|
|
static int
|
|
dummyErrorHandler(Display *dpy, XErrorEvent *err)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
setPixmapProperty(Pixmap pixmap)
|
|
{
|
|
static Atom prop = 0;
|
|
Atom type;
|
|
int format;
|
|
unsigned long length, after;
|
|
unsigned char *data;
|
|
int mode;
|
|
|
|
if (!prop) {
|
|
prop = XInternAtom(dpy, "_XROOTPMAP_ID", False);
|
|
}
|
|
|
|
XGrabServer(dpy);
|
|
|
|
/* Clear out the old pixmap */
|
|
XGetWindowProperty(dpy, root, prop, 0L, 1L, False, AnyPropertyType,
|
|
&type, &format, &length, &after, &data);
|
|
|
|
if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
|
|
XSetErrorHandler(dummyErrorHandler);
|
|
XKillClient(dpy, *((Pixmap *)data));
|
|
XSync(dpy, False);
|
|
XSetErrorHandler(NULL);
|
|
mode = PropModeReplace;
|
|
} else {
|
|
mode = PropModeAppend;
|
|
}
|
|
if (pixmap)
|
|
XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, mode,
|
|
(unsigned char *) &pixmap, 1);
|
|
else
|
|
XDeleteProperty(dpy, root, prop);
|
|
|
|
|
|
XUngrabServer(dpy);
|
|
XFlush(dpy);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
changeTexture(BackgroundTexture *texture)
|
|
{
|
|
if (!texture) {
|
|
return;
|
|
}
|
|
|
|
if (texture->solid) {
|
|
XSetWindowBackground(dpy, root, texture->color.pixel);
|
|
} else {
|
|
XSetWindowBackgroundPixmap(dpy, root, texture->pixmap);
|
|
}
|
|
XClearWindow(dpy, root);
|
|
|
|
XSync(dpy, False);
|
|
|
|
{
|
|
Pixmap pixmap;
|
|
|
|
pixmap = duplicatePixmap(texture->pixmap, texture->width,
|
|
texture->height);
|
|
|
|
setPixmapProperty(pixmap);
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
readmsg(int fd, unsigned char *buffer, int size)
|
|
{
|
|
int count;
|
|
|
|
count = 0;
|
|
while (size>0) {
|
|
count = read(fd, buffer, size);
|
|
if (count < 0)
|
|
return -1;
|
|
size -= count;
|
|
buffer += count;
|
|
*buffer = 0;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
/*
|
|
* Message Format:
|
|
* sizeSntexture_spec - sets the texture for workspace n
|
|
* sizeCn - change background texture to the one for workspace n
|
|
* sizePpath - set the pixmap search path
|
|
*
|
|
* n is 4 bytes
|
|
* size = 4 bytes for length of the message data
|
|
*/
|
|
void
|
|
helperLoop(RContext *rc)
|
|
{
|
|
BackgroundTexture *textures[WORKSPACE_COUNT];
|
|
int maxTextures = 0;
|
|
unsigned char buffer[2048], buf[8];
|
|
int size;
|
|
int errcount = 4;
|
|
|
|
memset(textures, 0, WORKSPACE_COUNT*sizeof(BackgroundTexture*));
|
|
|
|
|
|
while (1) {
|
|
int workspace;
|
|
|
|
/* get length of message */
|
|
if (readmsg(0, buffer, 4) < 0) {
|
|
wsyserror("error reading message from Window Maker");
|
|
errcount--;
|
|
if (errcount == 0) {
|
|
wfatal("quitting");
|
|
exit(1);
|
|
}
|
|
continue;
|
|
}
|
|
memcpy(buf, buffer, 4);
|
|
buf[4] = 0;
|
|
size = atoi(buf);
|
|
|
|
/* get message */
|
|
if (readmsg(0, buffer, size) < 0) {
|
|
wsyserror("error reading message from Window Maker");
|
|
errcount--;
|
|
if (errcount == 0) {
|
|
wfatal("quitting");
|
|
exit(1);
|
|
}
|
|
continue;
|
|
}
|
|
#ifdef DEBUG
|
|
printf("RECEIVED %s\n",buffer);
|
|
#endif
|
|
if (buffer[0]!='P' && buffer[0]!='K') {
|
|
memcpy(buf, &buffer[1], 4);
|
|
buf[4] = 0;
|
|
workspace = atoi(buf);
|
|
if (workspace < 0 || workspace >= WORKSPACE_COUNT) {
|
|
wwarning("received message with invalid workspace number %i\n",
|
|
workspace);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
switch (buffer[0]) {
|
|
case 'S':
|
|
#ifdef DEBUG
|
|
printf("set texture %s\n", &buffer[5]);
|
|
#endif
|
|
setupTexture(rc, textures, &maxTextures, workspace, &buffer[5]);
|
|
break;
|
|
|
|
case 'C':
|
|
#ifdef DEBUG
|
|
printf("change texture %i\n", workspace);
|
|
#endif
|
|
if (!textures[workspace]) {
|
|
changeTexture(textures[0]);
|
|
} else {
|
|
changeTexture(textures[workspace]);
|
|
}
|
|
break;
|
|
|
|
case 'P':
|
|
#ifdef DEBUG
|
|
printf("change pixmappath %s\n", &buffer[1]);
|
|
#endif
|
|
if (PixmapPath)
|
|
wfree(PixmapPath);
|
|
PixmapPath = wstrdup(&buffer[1]);
|
|
break;
|
|
|
|
case 'U':
|
|
#ifdef DEBUG
|
|
printf("unset workspace %i\n", workspace);
|
|
#endif
|
|
setupTexture(rc, textures, &maxTextures, workspace, NULL);
|
|
break;
|
|
|
|
case 'K':
|
|
#ifdef DEBUG
|
|
printf("exit command\n");
|
|
#endif
|
|
exit(0);
|
|
|
|
default:
|
|
wwarning("unknown message received");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
updateDomain(char *domain, char *key, char *texture)
|
|
{
|
|
char *program = "wdwrite";
|
|
|
|
/* here is a mem leak */
|
|
system(wstrconcat("wdwrite ",
|
|
wstrconcat(domain, smooth ? " SmoothWorkspaceBack YES"
|
|
: " SmoothWorkspaceBack NO")));
|
|
|
|
execlp(program, program, domain, key, texture, NULL);
|
|
wwarning("warning could not run \"%s\"", program);
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
globalDefaultsPathForDomain(char *domain)
|
|
{
|
|
char path[1024];
|
|
|
|
sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
|
|
|
|
return wstrdup(path);
|
|
}
|
|
|
|
|
|
proplist_t
|
|
getValueForKey(char *domain, char *keyName)
|
|
{
|
|
char *path;
|
|
proplist_t key;
|
|
proplist_t d;
|
|
proplist_t val;
|
|
|
|
key = PLMakeString(keyName);
|
|
|
|
/* try to find PixmapPath in user defaults */
|
|
path = wdefaultspathfordomain(domain);
|
|
d = PLGetProplistWithPath(path);
|
|
if (!d) {
|
|
wwarning("could not open domain file %s", path);
|
|
}
|
|
wfree(path);
|
|
|
|
if (d && !PLIsDictionary(d)) {
|
|
PLRelease(d);
|
|
d = NULL;
|
|
}
|
|
if (d) {
|
|
val = PLGetDictionaryEntry(d, key);
|
|
} else {
|
|
val = NULL;
|
|
}
|
|
/* try to find PixmapPath in global defaults */
|
|
if (!val) {
|
|
path = globalDefaultsPathForDomain(domain);
|
|
if (!path) {
|
|
wwarning("could not locate file for domain %s", domain);
|
|
d = NULL;
|
|
} else {
|
|
d = PLGetProplistWithPath(path);
|
|
wfree(path);
|
|
}
|
|
|
|
if (d && !PLIsDictionary(d)) {
|
|
PLRelease(d);
|
|
d = NULL;
|
|
}
|
|
if (d) {
|
|
val = PLGetDictionaryEntry(d, key);
|
|
|
|
} else {
|
|
val = NULL;
|
|
}
|
|
}
|
|
|
|
if (val)
|
|
PLRetain(val);
|
|
|
|
PLRelease(key);
|
|
if (d)
|
|
PLRelease(d);
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
getPixmapPath(char *domain)
|
|
{
|
|
proplist_t val;
|
|
char *ptr, *data;
|
|
int len, i, count;
|
|
|
|
val = getValueForKey(domain, "PixmapPath");
|
|
|
|
if (!val || !PLIsArray(val)) {
|
|
if (val)
|
|
PLRelease(val);
|
|
return wstrdup("");
|
|
}
|
|
|
|
count = PLGetNumberOfElements(val);
|
|
len = 0;
|
|
for (i=0; i<count; i++) {
|
|
proplist_t v;
|
|
|
|
v = PLGetArrayElement(val, i);
|
|
if (!v || !PLIsString(v)) {
|
|
continue;
|
|
}
|
|
len += strlen(PLGetString(v))+1;
|
|
}
|
|
|
|
ptr = data = wmalloc(len+1);
|
|
*ptr = 0;
|
|
|
|
for (i=0; i<count; i++) {
|
|
proplist_t v;
|
|
|
|
v = PLGetArrayElement(val, i);
|
|
if (!v || !PLIsString(v)) {
|
|
continue;
|
|
}
|
|
strcpy(ptr, PLGetString(v));
|
|
|
|
ptr += strlen(PLGetString(v));
|
|
*ptr = ':';
|
|
ptr++;
|
|
}
|
|
if (i>0)
|
|
ptr--; *(ptr--) = 0;
|
|
|
|
PLRelease(val);
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
char*
|
|
getFullPixmapPath(char *file)
|
|
{
|
|
char *tmp;
|
|
|
|
if (!PixmapPath || !(tmp = wfindfile(PixmapPath, file))) {
|
|
int bsize = 512;
|
|
char *path = wmalloc(bsize);
|
|
|
|
while (!getcwd(path, bsize)) {
|
|
wfree(path);
|
|
bsize += bsize/2;
|
|
path = malloc(bsize);
|
|
}
|
|
|
|
tmp = wstrconcat(path, "/");
|
|
wfree(path);
|
|
path = wstrconcat(tmp, file);
|
|
wfree(tmp);
|
|
|
|
return path;
|
|
}
|
|
|
|
/* the file is in the PixmapPath */
|
|
wfree(tmp);
|
|
|
|
return wstrdup(file);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
wAbort()
|
|
{
|
|
wfatal("aborting");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
print_help(char *ProgName)
|
|
{
|
|
printf("Usage: %s [options] [image]\n", ProgName);
|
|
puts("Sets the workspace background to the specified image or a texture and optionally update Window Maker configuration");
|
|
puts("");
|
|
#define P(m) puts(m)
|
|
P(" -display display to use");
|
|
P(" -d, --dither dither image");
|
|
P(" -m, --match match colors");
|
|
P(" -S, --smooth smooth scaled image");
|
|
P(" -b, --back-color <color> background color");
|
|
P(" -t, --tile tile image");
|
|
P(" -e, --center center image");
|
|
P(" -s, --scale scale image (default)");
|
|
P(" -a, --maxscale scale image and keep aspect ratio");
|
|
P(" -u, --update-wmaker update WindowMaker domain database");
|
|
P(" -D, --update-domain <domain> update <domain> database");
|
|
P(" -c, --colors <cpc> colors per channel to use");
|
|
P(" -p, --parse <texture> proplist style texture specification");
|
|
P(" -w, --workspace <workspace> update background for the specified workspace");
|
|
P(" --version show version of wmsetbg and exit");
|
|
P(" --help show this help and exit");
|
|
#undef P
|
|
}
|
|
|
|
|
|
|
|
void
|
|
changeTextureForWorkspace(char *domain, char *texture, int workspace)
|
|
{
|
|
proplist_t array;
|
|
proplist_t val;
|
|
char *value;
|
|
int j;
|
|
|
|
val = PLGetProplistWithDescription(texture);
|
|
if (!val) {
|
|
wwarning("could not parse texture %s", texture);
|
|
return;
|
|
}
|
|
|
|
array = getValueForKey("WindowMaker", "WorkspaceSpecificBack");
|
|
|
|
if (!array) {
|
|
array = PLMakeArrayFromElements(NULL, NULL);
|
|
}
|
|
|
|
j = PLGetNumberOfElements(array);
|
|
if (workspace >= j) {
|
|
proplist_t empty;
|
|
|
|
empty = PLMakeArrayFromElements(NULL, NULL);
|
|
|
|
while (j++ < workspace-1) {
|
|
PLAppendArrayElement(array, empty);
|
|
}
|
|
PLAppendArrayElement(array, val);
|
|
} else {
|
|
PLRemoveArrayElement(array, workspace);
|
|
PLInsertArrayElement(array, val, workspace);
|
|
}
|
|
|
|
value = PLGetDescription(array);
|
|
updateDomain(domain, "WorkspaceSpecificBack", value);
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
int helperMode = 0;
|
|
RContext *rc;
|
|
RContextAttributes rattr;
|
|
char *style = "spixmap";
|
|
char *back_color = "gray20";
|
|
char *image_name = NULL;
|
|
char *domain = "WindowMaker";
|
|
int update=0, cpc=4, render_mode=RDitheredRendering, obey_user=0;
|
|
char *texture = NULL;
|
|
int workspace = -1;
|
|
|
|
signal(SIGINT, SIG_DFL);
|
|
signal(SIGTERM, SIG_DFL);
|
|
signal(SIGQUIT, SIG_DFL);
|
|
signal(SIGSEGV, SIG_DFL);
|
|
signal(SIGBUS, SIG_DFL);
|
|
signal(SIGFPE, SIG_DFL);
|
|
signal(SIGABRT, SIG_DFL);
|
|
signal(SIGHUP, SIG_DFL);
|
|
signal(SIGPIPE, SIG_DFL);
|
|
signal(SIGCHLD, SIG_DFL);
|
|
|
|
WMInitializeApplication("wmsetbg", &argc, argv);
|
|
|
|
for (i=1; i<argc; i++) {
|
|
if (strcmp(argv[i], "-helper")==0) {
|
|
helperMode = 1;
|
|
} else if (strcmp(argv[i], "-display")==0) {
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
display = argv[i];
|
|
} else if (strcmp(argv[i], "-s")==0
|
|
|| strcmp(argv[i], "--scale")==0) {
|
|
style = "spixmap";
|
|
} else if (strcmp(argv[i], "-t")==0
|
|
|| strcmp(argv[i], "--tile")==0) {
|
|
style = "tpixmap";
|
|
} else if (strcmp(argv[i], "-e")==0
|
|
|| strcmp(argv[i], "--center")==0) {
|
|
style = "cpixmap";
|
|
} else if (strcmp(argv[i], "-a")==0
|
|
|| strcmp(argv[i], "--maxscale")==0) {
|
|
style = "mpixmap";
|
|
} else if (strcmp(argv[i], "-d")==0
|
|
|| strcmp(argv[i], "--dither")==0) {
|
|
render_mode = RDitheredRendering;
|
|
obey_user++;
|
|
} else if (strcmp(argv[i], "-m")==0
|
|
|| strcmp(argv[i], "--match")==0) {
|
|
render_mode = RBestMatchRendering;
|
|
obey_user++;
|
|
} else if (strcmp(argv[i], "-S")==0
|
|
|| strcmp(argv[i], "--smooth")==0) {
|
|
smooth = True;
|
|
} else if (strcmp(argv[i], "-u")==0
|
|
|| strcmp(argv[i], "--update-wmaker")==0) {
|
|
update++;
|
|
} else if (strcmp(argv[i], "-D")==0
|
|
|| strcmp(argv[i], "--update-domain")==0) {
|
|
update++;
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
domain = wstrdup(argv[i]);
|
|
} else if (strcmp(argv[i], "-c")==0
|
|
|| strcmp(argv[i], "--colors")==0) {
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
if (sscanf(argv[i], "%i", &cpc)!=1) {
|
|
wfatal("bad value for colors per channel: \"%s\"\n", argv[i]);
|
|
exit(1);
|
|
}
|
|
} else if (strcmp(argv[i], "-b")==0
|
|
|| strcmp(argv[i], "--back-color")==0) {
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
back_color = argv[i];
|
|
} else if (strcmp(argv[i], "-p")==0
|
|
|| strcmp(argv[i], "--parse")==0) {
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
texture = argv[i];
|
|
} else if (strcmp(argv[i], "-w")==0
|
|
|| strcmp(argv[i], "--workspace")==0) {
|
|
i++;
|
|
if (i>=argc) {
|
|
wfatal("too few arguments for %s\n", argv[i-1]);
|
|
exit(1);
|
|
}
|
|
if (sscanf(argv[i], "%i", &workspace)!=1) {
|
|
wfatal("bad value for workspace number: \"%s\"",
|
|
argv[i]);
|
|
exit(1);
|
|
}
|
|
} else if (strcmp(argv[i], "--version")==0) {
|
|
|
|
printf(PROG_VERSION);
|
|
exit(0);
|
|
|
|
} else if (strcmp(argv[i], "--help")==0) {
|
|
print_help(argv[0]);
|
|
exit(0);
|
|
} else if (argv[i][0] != '-') {
|
|
image_name = argv[i];
|
|
} else {
|
|
printf("%s: invalid argument '%s'\n", argv[0], argv[i]);
|
|
printf("Try '%s --help' for more information\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (!image_name && !texture && !helperMode) {
|
|
printf("%s: you must specify a image file name or a texture\n",
|
|
argv[0]);
|
|
printf("Try '%s --help' for more information\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
PixmapPath = getPixmapPath(domain);
|
|
if (!smooth) {
|
|
proplist_t val;
|
|
#if 0 /* some problem with Alpha... TODO: check if its right */
|
|
val = PLGetDictionaryEntry(domain,
|
|
PLMakeString("SmoothWorkspaceBack"));
|
|
#else
|
|
val = getValueForKey(domain, "SmoothWorkspaceBack");
|
|
#endif
|
|
|
|
if (val && PLIsString(val) && strcasecmp(PLGetString(val), "YES")==0)
|
|
smooth = True;
|
|
}
|
|
|
|
dpy = XOpenDisplay(display);
|
|
if (!dpy) {
|
|
wfatal("could not open display");
|
|
exit(1);
|
|
}
|
|
#if 0
|
|
XSynchronize(dpy, 1);
|
|
#endif
|
|
|
|
root = DefaultRootWindow(dpy);
|
|
|
|
scr = DefaultScreen(dpy);
|
|
|
|
scrWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
|
|
scrHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
|
|
|
|
if (!obey_user && DefaultDepth(dpy, scr) <= 8)
|
|
render_mode = RDitheredRendering;
|
|
|
|
rattr.flags = RC_RenderMode | RC_ColorsPerChannel
|
|
| RC_StandardColormap;
|
|
rattr.render_mode = render_mode;
|
|
rattr.colors_per_channel = cpc;
|
|
rattr.standard_colormap_mode = RCreateStdColormap;
|
|
|
|
rc = RCreateContext(dpy, scr, &rattr);
|
|
|
|
if (!rc) {
|
|
rattr.standard_colormap_mode = RIgnoreStdColormap;
|
|
rc = RCreateContext(dpy, scr, &rattr);
|
|
}
|
|
|
|
if (!rc) {
|
|
wfatal("could not initialize wrlib: %s",
|
|
RMessageForError(RErrorCode));
|
|
exit(1);
|
|
}
|
|
|
|
if (helperMode) {
|
|
/* lower priority, so that it wont use all the CPU */
|
|
nice(15);
|
|
|
|
helperLoop(rc);
|
|
} else {
|
|
BackgroundTexture *tex;
|
|
char buffer[4098];
|
|
|
|
if (!texture) {
|
|
char *image_path = getFullPixmapPath(image_name);
|
|
|
|
sprintf(buffer, "(%s, \"%s\", %s)", style, image_path, back_color);
|
|
wfree(image_path);
|
|
texture = (char*)buffer;
|
|
}
|
|
|
|
if (update && workspace < 0) {
|
|
updateDomain(domain, "WorkspaceBack", texture);
|
|
}
|
|
|
|
tex = parseTexture(rc, texture);
|
|
if (!tex)
|
|
exit(1);
|
|
|
|
if (workspace<0)
|
|
changeTexture(tex);
|
|
else {
|
|
/* always update domain */
|
|
changeTextureForWorkspace(domain, texture, workspace);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|