2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <X11/Xutil.h>
32 #include "WindowMaker.h"
36 extern WPreferences wPreferences
;
38 static void bevelImage(RImage
* image
, int relief
);
40 WTexSolid
*wTextureMakeSolid(WScreen
* scr
, XColor
* color
)
46 texture
= wmalloc(sizeof(WTexture
));
48 texture
->type
= WTEX_SOLID
;
51 XAllocColor(dpy
, scr
->w_colormap
, color
);
52 texture
->normal
= *color
;
53 if (color
->red
== 0 && color
->blue
== 0 && color
->green
== 0) {
54 texture
->light
.red
= 0xb6da;
55 texture
->light
.green
= 0xb6da;
56 texture
->light
.blue
= 0xb6da;
57 texture
->dim
.red
= 0x6185;
58 texture
->dim
.green
= 0x6185;
59 texture
->dim
.blue
= 0x6185;
65 rgb
.red
= color
->red
>> 8;
66 rgb
.green
= color
->green
>> 8;
67 rgb
.blue
= color
->blue
>> 8;
68 RRGBtoHSV(&rgb
, &hsv
);
69 RHSVtoRGB(&hsv
, &rgb
);
72 v
= hsv
.value
* 16 / 10;
73 hsv
.value
= (v
> 255 ? 255 : v
);
74 RHSVtoRGB(&hsv
, &rgb
);
75 texture
->light
.red
= rgb
.red
<< 8;
76 texture
->light
.green
= rgb
.green
<< 8;
77 texture
->light
.blue
= rgb
.blue
<< 8;
79 hsv2
.value
= hsv2
.value
/ 2;
80 RHSVtoRGB(&hsv2
, &rgb
);
81 texture
->dim
.red
= rgb
.red
<< 8;
82 texture
->dim
.green
= rgb
.green
<< 8;
83 texture
->dim
.blue
= rgb
.blue
<< 8;
85 texture
->dark
.red
= 0;
86 texture
->dark
.green
= 0;
87 texture
->dark
.blue
= 0;
88 XAllocColor(dpy
, scr
->w_colormap
, &texture
->light
);
89 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dim
);
90 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dark
);
92 gcm
= GCForeground
| GCBackground
| GCGraphicsExposures
;
93 gcv
.graphics_exposures
= False
;
95 gcv
.background
= gcv
.foreground
= texture
->light
.pixel
;
96 texture
->light_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
98 gcv
.background
= gcv
.foreground
= texture
->dim
.pixel
;
99 texture
->dim_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
101 gcv
.background
= gcv
.foreground
= texture
->dark
.pixel
;
102 texture
->dark_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
104 gcv
.background
= gcv
.foreground
= color
->pixel
;
105 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
110 static int dummyErrorHandler(Display
* foo
, XErrorEvent
* bar
)
115 void wTextureDestroy(WScreen
* scr
, WTexture
* texture
)
119 unsigned long colors
[8];
122 * some stupid servers don't like white or black being freed...
124 #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
125 switch (texture
->any
.type
) {
127 XFreeGC(dpy
, texture
->solid
.light_gc
);
128 XFreeGC(dpy
, texture
->solid
.dark_gc
);
129 XFreeGC(dpy
, texture
->solid
.dim_gc
);
130 if (CANFREE(texture
->solid
.light
.pixel
))
131 colors
[count
++] = texture
->solid
.light
.pixel
;
132 if (CANFREE(texture
->solid
.dim
.pixel
))
133 colors
[count
++] = texture
->solid
.dim
.pixel
;
134 if (CANFREE(texture
->solid
.dark
.pixel
))
135 colors
[count
++] = texture
->solid
.dark
.pixel
;
139 RReleaseImage(texture
->pixmap
.pixmap
);
142 case WTEX_MHGRADIENT
:
143 case WTEX_MVGRADIENT
:
144 case WTEX_MDGRADIENT
:
145 for (i
= 0; texture
->mgradient
.colors
[i
] != NULL
; i
++) {
146 wfree(texture
->mgradient
.colors
[i
]);
148 wfree(texture
->mgradient
.colors
);
151 case WTEX_THGRADIENT
:
152 case WTEX_TVGRADIENT
:
153 case WTEX_TDGRADIENT
:
154 RReleaseImage(texture
->tgradient
.pixmap
);
158 if (CANFREE(texture
->any
.color
.pixel
))
159 colors
[count
++] = texture
->any
.color
.pixel
;
161 XErrorHandler oldhandler
;
163 /* ignore error from buggy servers that don't know how
164 * to do reference counting for colors. */
166 oldhandler
= XSetErrorHandler(dummyErrorHandler
);
167 XFreeColors(dpy
, scr
->w_colormap
, colors
, count
, 0);
169 XSetErrorHandler(oldhandler
);
171 XFreeGC(dpy
, texture
->any
.gc
);
176 WTexGradient
*wTextureMakeGradient(WScreen
* scr
, int style
, RColor
* from
, RColor
* to
)
178 WTexGradient
*texture
;
181 texture
= wmalloc(sizeof(WTexture
));
182 memset(texture
, 0, sizeof(WTexture
));
183 texture
->type
= style
;
184 texture
->subtype
= 0;
186 texture
->color1
= *from
;
187 texture
->color2
= *to
;
189 texture
->normal
.red
= (from
->red
+ to
->red
) << 7;
190 texture
->normal
.green
= (from
->green
+ to
->green
) << 7;
191 texture
->normal
.blue
= (from
->blue
+ to
->blue
) << 7;
193 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
194 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
195 gcv
.graphics_exposures
= False
;
196 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
201 WTexIGradient
*wTextureMakeIGradient(WScreen
* scr
, int thickness1
, RColor colors1
[2],
202 int thickness2
, RColor colors2
[2])
204 WTexIGradient
*texture
;
208 texture
= wmalloc(sizeof(WTexture
));
209 memset(texture
, 0, sizeof(WTexture
));
210 texture
->type
= WTEX_IGRADIENT
;
211 for (i
= 0; i
< 2; i
++) {
212 texture
->colors1
[i
] = colors1
[i
];
213 texture
->colors2
[i
] = colors2
[i
];
215 texture
->thickness1
= thickness1
;
216 texture
->thickness2
= thickness2
;
217 if (thickness1
>= thickness2
) {
218 texture
->normal
.red
= (colors1
[0].red
+ colors1
[1].red
) << 7;
219 texture
->normal
.green
= (colors1
[0].green
+ colors1
[1].green
) << 7;
220 texture
->normal
.blue
= (colors1
[0].blue
+ colors1
[1].blue
) << 7;
222 texture
->normal
.red
= (colors2
[0].red
+ colors2
[1].red
) << 7;
223 texture
->normal
.green
= (colors2
[0].green
+ colors2
[1].green
) << 7;
224 texture
->normal
.blue
= (colors2
[0].blue
+ colors2
[1].blue
) << 7;
226 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
227 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
228 gcv
.graphics_exposures
= False
;
229 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
234 WTexMGradient
*wTextureMakeMGradient(WScreen
* scr
, int style
, RColor
** colors
)
236 WTexMGradient
*texture
;
240 texture
= wmalloc(sizeof(WTexture
));
241 memset(texture
, 0, sizeof(WTexture
));
242 texture
->type
= style
;
243 texture
->subtype
= 0;
246 while (colors
[i
] != NULL
)
249 texture
->normal
.red
= (colors
[0]->red
<< 8);
250 texture
->normal
.green
= (colors
[0]->green
<< 8);
251 texture
->normal
.blue
= (colors
[0]->blue
<< 8);
253 texture
->colors
= colors
;
255 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
256 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
257 gcv
.graphics_exposures
= False
;
258 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
263 WTexPixmap
*wTextureMakePixmap(WScreen
* scr
, int style
, char *pixmap_file
, XColor
* color
)
270 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
272 wwarning(_("image file \"%s\" used as texture could not be found."), pixmap_file
);
275 image
= RLoadImage(scr
->rcontext
, file
, 0);
277 wwarning(_("could not load texture pixmap \"%s\":%s"), file
, RMessageForError(RErrorCode
));
283 texture
= wmalloc(sizeof(WTexture
));
284 memset(texture
, 0, sizeof(WTexture
));
285 texture
->type
= WTEX_PIXMAP
;
286 texture
->subtype
= style
;
288 texture
->normal
= *color
;
290 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
291 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
292 gcv
.graphics_exposures
= False
;
293 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
295 texture
->pixmap
= image
;
300 WTexTGradient
*wTextureMakeTGradient(WScreen
* scr
, int style
, RColor
* from
, RColor
* to
,
301 char *pixmap_file
, int opacity
)
303 WTexTGradient
*texture
;
308 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
310 wwarning(_("image file \"%s\" used as texture could not be found."), pixmap_file
);
313 image
= RLoadImage(scr
->rcontext
, file
, 0);
315 wwarning(_("could not load texture pixmap \"%s\":%s"), file
, RMessageForError(RErrorCode
));
321 texture
= wmalloc(sizeof(WTexture
));
322 memset(texture
, 0, sizeof(WTexture
));
323 texture
->type
= style
;
325 texture
->opacity
= opacity
;
327 texture
->color1
= *from
;
328 texture
->color2
= *to
;
330 texture
->normal
.red
= (from
->red
+ to
->red
) << 7;
331 texture
->normal
.green
= (from
->green
+ to
->green
) << 7;
332 texture
->normal
.blue
= (from
->blue
+ to
->blue
) << 7;
334 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
335 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
336 gcv
.graphics_exposures
= False
;
337 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
339 texture
->pixmap
= image
;
344 RImage
*wTextureRenderImage(WTexture
* texture
, int width
, int height
, int relief
)
346 RImage
*image
= NULL
;
351 switch (texture
->any
.type
) {
353 image
= RCreateImage(width
, height
, False
);
355 color1
.red
= texture
->solid
.normal
.red
>> 8;
356 color1
.green
= texture
->solid
.normal
.green
>> 8;
357 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
360 RClearImage(image
, &color1
);
364 if (texture
->pixmap
.subtype
== WTP_TILE
) {
365 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
366 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
367 color1
.red
= texture
->pixmap
.normal
.red
>> 8;
368 color1
.green
= texture
->pixmap
.normal
.green
>> 8;
369 color1
.blue
= texture
->pixmap
.normal
.blue
>> 8;
371 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
, &color1
);
373 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
378 image
= RRenderInterwovenGradient(width
, height
,
379 texture
->igradient
.colors1
,
380 texture
->igradient
.thickness1
,
381 texture
->igradient
.colors2
, texture
->igradient
.thickness2
);
385 subtype
= RGRD_HORIZONTAL
;
386 goto render_gradient
;
389 subtype
= RGRD_VERTICAL
;
390 goto render_gradient
;
393 subtype
= RGRD_DIAGONAL
;
396 image
= RRenderGradient(width
, height
, &texture
->gradient
.color1
,
397 &texture
->gradient
.color2
, subtype
);
400 case WTEX_MHGRADIENT
:
401 subtype
= RGRD_HORIZONTAL
;
402 goto render_mgradient
;
404 case WTEX_MVGRADIENT
:
405 subtype
= RGRD_VERTICAL
;
406 goto render_mgradient
;
408 case WTEX_MDGRADIENT
:
409 subtype
= RGRD_DIAGONAL
;
411 image
= RRenderMultiGradient(width
, height
, &(texture
->mgradient
.colors
[1]), subtype
);
414 case WTEX_THGRADIENT
:
415 subtype
= RGRD_HORIZONTAL
;
416 goto render_tgradient
;
418 case WTEX_TVGRADIENT
:
419 subtype
= RGRD_VERTICAL
;
420 goto render_tgradient
;
422 case WTEX_TDGRADIENT
:
423 subtype
= RGRD_DIAGONAL
;
428 image
= RMakeTiledImage(texture
->tgradient
.pixmap
, width
, height
);
432 grad
= RRenderGradient(width
, height
, &texture
->tgradient
.color1
,
433 &texture
->tgradient
.color2
, subtype
);
435 RReleaseImage(image
);
440 RCombineImagesWithOpaqueness(image
, grad
, texture
->tgradient
.opacity
);
445 puts("ERROR in wTextureRenderImage()");
453 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
455 image
= RCreateImage(width
, height
, False
);
457 wwarning(_("could not allocate image buffer"));
465 RClearImage(image
, &gray
);
496 RBevelImage(image
, d
);
498 bevelImage(image
, -d
);
504 static void bevelImage(RImage
* image
, int relief
)
506 int width
= image
->width
;
507 int height
= image
->height
;
512 color
.red
= color
.green
= color
.blue
= 80;
514 /**/ ROperateLine(image
, RAddOperation
, 1, 0, width
- 2, 0, &color
);
515 /**/ ROperateLine(image
, RAddOperation
, 0, 0, 0, height
- 1, &color
);
517 color
.red
= color
.green
= color
.blue
= 40;
519 ROperateLine(image
, RSubtractOperation
, width
- 1, 0, width
- 1, height
- 1, &color
);
521 /**/ ROperateLine(image
, RSubtractOperation
, 1, height
- 2, width
- 2, height
- 2, &color
);
523 color
.red
= color
.green
= color
.blue
= 0;
525 RDrawLine(image
, 0, height
- 1, width
- 1, height
- 1, &color
);
531 void wDrawBevel(Drawable d
, unsigned width
, unsigned height
, WTexSolid
* texture
, int relief
)
536 if (relief
== WREL_FLAT
)
539 light
= texture
->light_gc
;
540 dim
= texture
->dim_gc
;
541 dark
= texture
->dark_gc
;
549 segs
[0].x2
= width
- 2;
550 segs
[0].y2
= segs
[0].y1
= height
- 2;
551 segs
[1].x1
= width
- 2;
553 segs
[1].x2
= width
- 2;
554 segs
[1].y2
= height
- 2;
555 if (wPreferences
.new_style
== TS_NEXT
) {
556 XDrawSegments(dpy
, d
, dark
, segs
, 2);
558 XDrawSegments(dpy
, d
, dim
, segs
, 2);
561 segs
[0].x2
= width
- 1;
562 segs
[0].y2
= segs
[0].y1
= height
- 1;
563 segs
[1].x1
= segs
[1].x2
= width
- 1;
565 segs
[1].y2
= height
- 1;
566 if (wPreferences
.new_style
== TS_NEXT
) {
567 XDrawSegments(dpy
, d
, light
, segs
, 2);
569 XDrawSegments(dpy
, d
, dark
, segs
, 2);
571 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
572 segs
[0].x2
= width
- 2;
573 segs
[1].x1
= segs
[1].y1
= 0;
575 segs
[1].y2
= height
- 2;
576 if (wPreferences
.new_style
== TS_NEXT
) {
577 XDrawSegments(dpy
, d
, dark
, segs
, 2);
579 XDrawSegments(dpy
, d
, light
, segs
, 2);
581 if (relief
== WREL_ICON
) {
582 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
583 segs
[0].x2
= width
- 2;
584 segs
[1].x1
= segs
[1].y1
= 1;
586 segs
[1].y2
= height
- 2;
587 XDrawSegments(dpy
, d
, light
, segs
, 2);