icons.c revision 645f5050
1645f5050Syouri/*
2645f5050Syouri * Copyright 1989 Massachusetts Institute of Technology
3645f5050Syouri *
4645f5050Syouri * Permission to use, copy, modify, and distribute this software and its
5645f5050Syouri * documentation for any purpose and without fee is hereby granted, provided
6645f5050Syouri * that the above copyright notice appear in all copies and that both that
7645f5050Syouri * copyright notice and this permission notice appear in supporting
8645f5050Syouri * documentation, and that the name of M.I.T. not be used in advertising
9645f5050Syouri * or publicity pertaining to distribution of the software without specific,
10645f5050Syouri * written prior permission.  M.I.T. makes no representations about the
11645f5050Syouri * suitability of this software for any purpose.  It is provided "as is"
12645f5050Syouri * without express or implied warranty.
13645f5050Syouri *
14645f5050Syouri * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15645f5050Syouri * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
16645f5050Syouri * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17645f5050Syouri * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18645f5050Syouri * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19645f5050Syouri * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20645f5050Syouri */
21645f5050Syouri/*
22645f5050Syouri *  [ ctwm ]
23645f5050Syouri *
24645f5050Syouri *  Copyright 1992 Claude Lecommandeur.
25645f5050Syouri *
26645f5050Syouri * Permission to use, copy, modify  and distribute this software  [ctwm] and
27645f5050Syouri * its documentation for any purpose is hereby granted without fee, provided
28645f5050Syouri * that the above  copyright notice appear  in all copies and that both that
29645f5050Syouri * copyright notice and this permission notice appear in supporting documen-
30645f5050Syouri * tation, and that the name of  Claude Lecommandeur not be used in adverti-
31645f5050Syouri * sing or  publicity  pertaining to  distribution of  the software  without
32645f5050Syouri * specific, written prior permission. Claude Lecommandeur make no represen-
33645f5050Syouri * tations  about the suitability  of this software  for any purpose.  It is
34645f5050Syouri * provided "as is" without express or implied warranty.
35645f5050Syouri *
36645f5050Syouri * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
37645f5050Syouri * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
38645f5050Syouri * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
39645f5050Syouri * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
40645f5050Syouri * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
41645f5050Syouri * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
42645f5050Syouri * PERFORMANCE OF THIS SOFTWARE.
43645f5050Syouri *
44645f5050Syouri * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
45645f5050Syouri */
46645f5050Syouri
47645f5050Syouri/**********************************************************************
48645f5050Syouri *
49645f5050Syouri * $XConsortium: icons.c,v 1.22 91/07/12 09:58:38 dave Exp $
50645f5050Syouri *
51645f5050Syouri * Icon releated routines
52645f5050Syouri *
53645f5050Syouri * 10-Apr-89 Tom LaStrange        Initial Version.
54645f5050Syouri *
55645f5050Syouri * Do the necessary modification to be integrated in ctwm.
56645f5050Syouri * Can no longer be used for the standard twm.
57645f5050Syouri *
58645f5050Syouri * 22-April-92 Claude Lecommandeur.
59645f5050Syouri *
60645f5050Syouri *
61645f5050Syouri **********************************************************************/
62645f5050Syouri
63645f5050Syouri#include <stdio.h>
64645f5050Syouri#include "twm.h"
65645f5050Syouri#include "screen.h"
66645f5050Syouri#include "icons.h"
67645f5050Syouri#include "list.h"
68645f5050Syouri#include "parse.h"
69645f5050Syouri#include "util.h"
70645f5050Syouri
71645f5050Syouriextern void twmrc_error_prefix(void);
72645f5050Syouriextern Bool AnimationPending;
73645f5050Syouriextern Bool AnimationActive;
74645f5050Syouriextern Bool MaybeAnimate;
75645f5050Syouri
76645f5050Syouri#define iconWidth(w)	(w->icon->border_width * 2 + \
77645f5050Syouri			Scr->ShrinkIconTitles ? w->icon->width : w->icon->w_width)
78645f5050Syouri#define iconHeight(w)	(w->icon->border_width * 2 + w->icon->w_height)
79645f5050Syouri
80645f5050Syouristatic void splitEntry (IconEntry *ie, int grav1, int grav2, int w, int h)
81645f5050Syouri{
82645f5050Syouri    IconEntry	*new;
83645f5050Syouri
84645f5050Syouri    switch (grav1) {
85645f5050Syouri    case D_NORTH:
86645f5050Syouri    case D_SOUTH:
87645f5050Syouri	if (w != ie->w)
88645f5050Syouri	    splitEntry (ie, grav2, grav1, w, ie->h);
89645f5050Syouri	if (h != ie->h) {
90645f5050Syouri	    new = (IconEntry *)malloc (sizeof (IconEntry));
91645f5050Syouri	    new->twm_win = 0;
92645f5050Syouri	    new->used = 0;
93645f5050Syouri	    new->next = ie->next;
94645f5050Syouri	    ie->next = new;
95645f5050Syouri	    new->x = ie->x;
96645f5050Syouri	    new->h = (ie->h - h);
97645f5050Syouri	    new->w = ie->w;
98645f5050Syouri	    ie->h = h;
99645f5050Syouri	    if (grav1 == D_SOUTH) {
100645f5050Syouri		new->y = ie->y;
101645f5050Syouri		ie->y = new->y + new->h;
102645f5050Syouri	    } else
103645f5050Syouri		new->y = ie->y + ie->h;
104645f5050Syouri	}
105645f5050Syouri	break;
106645f5050Syouri    case D_EAST:
107645f5050Syouri    case D_WEST:
108645f5050Syouri	if (h != ie->h)
109645f5050Syouri	    splitEntry (ie, grav2, grav1, ie->w, h);
110645f5050Syouri	if (w != ie->w) {
111645f5050Syouri	    new = (IconEntry *)malloc (sizeof (IconEntry));
112645f5050Syouri	    new->twm_win = 0;
113645f5050Syouri	    new->used = 0;
114645f5050Syouri	    new->next = ie->next;
115645f5050Syouri	    ie->next = new;
116645f5050Syouri	    new->y = ie->y;
117645f5050Syouri	    new->w = (ie->w - w);
118645f5050Syouri	    new->h = ie->h;
119645f5050Syouri	    ie->w = w;
120645f5050Syouri	    if (grav1 == D_EAST) {
121645f5050Syouri		new->x = ie->x;
122645f5050Syouri		ie->x = new->x + new->w;
123645f5050Syouri	    } else
124645f5050Syouri		new->x = ie->x + ie->w;
125645f5050Syouri	}
126645f5050Syouri	break;
127645f5050Syouri    }
128645f5050Syouri}
129645f5050Syouri
130645f5050Syouristatic int roundUp (int v, int multiple)
131645f5050Syouri{
132645f5050Syouri    return ((v + multiple - 1) / multiple) * multiple;
133645f5050Syouri}
134645f5050Syouri
135645f5050Syouristatic void PlaceIcon(TwmWindow *tmp_win, int def_x, int def_y,
136645f5050Syouri		      int *final_x, int *final_y)
137645f5050Syouri{
138645f5050Syouri    IconRegion	*ir, *oldir;
139645f5050Syouri    IconEntry	*ie;
140645f5050Syouri    int		w = 0, h = 0;
141645f5050Syouri
142645f5050Syouri    /*
143645f5050Syouri     * First, check to see if the window is in a region's client list
144645f5050Syouri     */
145645f5050Syouri    ie = 0;
146645f5050Syouri    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
147645f5050Syouri	if (LookInList(ir->clientlist, tmp_win->full_name, &tmp_win->class))
148645f5050Syouri	{
149645f5050Syouri	    w = roundUp (iconWidth (tmp_win), ir->stepx);
150645f5050Syouri	    h = roundUp (iconHeight (tmp_win), ir->stepy);
151645f5050Syouri	    for (ie = ir->entries; ie; ie=ie->next) {
152645f5050Syouri	        if (ie->used)
153645f5050Syouri		    continue;
154645f5050Syouri	        if (ie->w >= w && ie->h >= h)
155645f5050Syouri		    break;
156645f5050Syouri	    }
157645f5050Syouri	    if (ie)
158645f5050Syouri	        break;
159645f5050Syouri	}
160645f5050Syouri    }
161645f5050Syouri
162645f5050Syouri    /*
163645f5050Syouri     * If not found in any region's client list, place anywhere
164645f5050Syouri     */
165645f5050Syouri    if (!ie)
166645f5050Syouri    {
167645f5050Syouri        for (ir = Scr->FirstRegion; ir; ir = ir->next) {
168645f5050Syouri	    w = roundUp (iconWidth (tmp_win), ir->stepx);
169645f5050Syouri	    h = roundUp (iconHeight (tmp_win), ir->stepy);
170645f5050Syouri	    for (ie = ir->entries; ie; ie=ie->next) {
171645f5050Syouri	        if (ie->used)
172645f5050Syouri		    continue;
173645f5050Syouri	        if (ie->w >= w && ie->h >= h)
174645f5050Syouri		    break;
175645f5050Syouri	    }
176645f5050Syouri	    if (ie)
177645f5050Syouri	        break;
178645f5050Syouri        }
179645f5050Syouri    }
180645f5050Syouri    oldir = tmp_win->icon->ir;
181645f5050Syouri    if (ie) {
182645f5050Syouri	splitEntry (ie, ir->grav1, ir->grav2, w, h);
183645f5050Syouri	ie->used = 1;
184645f5050Syouri	ie->twm_win = tmp_win;
185645f5050Syouri	switch (ir->Justification) {
186645f5050Syouri	    case J_LEFT :
187645f5050Syouri		*final_x = ie->x;
188645f5050Syouri		break;
189645f5050Syouri	    case J_UNDEF :
190645f5050Syouri	    case J_CENTER :
191645f5050Syouri		*final_x = ie->x + (ie->w - iconWidth (tmp_win)) / 2;
192645f5050Syouri		break;
193645f5050Syouri	    case J_RIGHT :
194645f5050Syouri		*final_x = ie->x + ie->w - iconWidth (tmp_win);
195645f5050Syouri		break;
196645f5050Syouri	    case J_BORDER :
197645f5050Syouri		if (ir->grav2 == D_EAST)
198645f5050Syouri		    *final_x = ie->x + ie->w - iconWidth (tmp_win);
199645f5050Syouri		else
200645f5050Syouri		    *final_x = ie->x;
201645f5050Syouri		break;
202645f5050Syouri	}
203645f5050Syouri	switch (ir->Alignement) {
204645f5050Syouri	    case J_TOP :
205645f5050Syouri		*final_y = ie->y;
206645f5050Syouri		break;
207645f5050Syouri	    case J_UNDEF :
208645f5050Syouri	    case J_CENTER :
209645f5050Syouri		*final_y = ie->y + (ie->h - iconHeight (tmp_win)) / 2;
210645f5050Syouri		break;
211645f5050Syouri	    case J_BOTTOM :
212645f5050Syouri		*final_y = ie->y + ie->h - iconHeight (tmp_win);
213645f5050Syouri		break;
214645f5050Syouri	    case J_BORDER :
215645f5050Syouri		if (ir->grav1 == D_SOUTH)
216645f5050Syouri		    *final_y = ie->y + ie->h - iconHeight (tmp_win);
217645f5050Syouri		else
218645f5050Syouri		    *final_y = ie->y;
219645f5050Syouri		break;
220645f5050Syouri	}
221645f5050Syouri	tmp_win->icon->ir = ir;
222645f5050Syouri    } else {
223645f5050Syouri	*final_x = def_x;
224645f5050Syouri	*final_y = def_y;
225645f5050Syouri	tmp_win->icon->ir = (IconRegion*)0;
226645f5050Syouri	return;
227645f5050Syouri    }
228645f5050Syouri    if (Scr->ShrinkIconTitles && tmp_win->icon->has_title) {
229645f5050Syouri	*final_x -= GetIconOffset (tmp_win->icon);
230645f5050Syouri	if (tmp_win->icon->ir != oldir) ReshapeIcon (tmp_win->icon);
231645f5050Syouri    }
232645f5050Syouri    return;
233645f5050Syouri}
234645f5050Syouri
235645f5050Syouristatic IconEntry *FindIconEntry (TwmWindow *tmp_win, IconRegion **irp)
236645f5050Syouri{
237645f5050Syouri    IconRegion	*ir;
238645f5050Syouri    IconEntry	*ie;
239645f5050Syouri
240645f5050Syouri    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
241645f5050Syouri	for (ie = ir->entries; ie; ie=ie->next)
242645f5050Syouri	    if (ie->twm_win == tmp_win) {
243645f5050Syouri		if (irp)
244645f5050Syouri		    *irp = ir;
245645f5050Syouri		return ie;
246645f5050Syouri	    }
247645f5050Syouri    }
248645f5050Syouri    return 0;
249645f5050Syouri}
250645f5050Syouri
251645f5050Syouriint IconUp (TwmWindow *tmp_win)
252645f5050Syouri{
253645f5050Syouri    int		x, y;
254645f5050Syouri    int		defx, defy;
255645f5050Syouri    struct IconRegion *ir;
256645f5050Syouri
257645f5050Syouri    /*
258645f5050Syouri     * If the client specified a particular location, let's use it (this might
259645f5050Syouri     * want to be an option at some point).  Otherwise, try to fit within the
260645f5050Syouri     * icon region.
261645f5050Syouri     */
262645f5050Syouri    if (tmp_win->wmhints && (tmp_win->wmhints->flags & IconPositionHint))
263645f5050Syouri      return (0);
264645f5050Syouri
265645f5050Syouri    if (tmp_win->icon_moved) {
266645f5050Syouri	if (!XGetGeometry (dpy, tmp_win->icon->w, &JunkRoot, &defx, &defy,
267645f5050Syouri			   &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth))
268645f5050Syouri	  return (1);
269645f5050Syouri
270645f5050Syouri	x = defx + ((int) JunkWidth) / 2;
271645f5050Syouri	y = defy + ((int) JunkHeight) / 2;
272645f5050Syouri
273645f5050Syouri	for (ir = Scr->FirstRegion; ir; ir = ir->next) {
274645f5050Syouri	    if (x >= ir->x && x < (ir->x + ir->w) &&
275645f5050Syouri		y >= ir->y && y < (ir->y + ir->h))
276645f5050Syouri	      break;
277645f5050Syouri	}
278645f5050Syouri	if (!ir) return (0);		/* outside icon regions, leave alone */
279645f5050Syouri    }
280645f5050Syouri
281645f5050Syouri    defx = -100;
282645f5050Syouri    defy = -100;
283645f5050Syouri    PlaceIcon(tmp_win, defx, defy, &x, &y);
284645f5050Syouri    if (x != defx || y != defy) {
285645f5050Syouri	XMoveWindow (dpy, tmp_win->icon->w, x, y);
286645f5050Syouri	tmp_win->icon_moved = FALSE;	/* since we've restored it */
287645f5050Syouri    }
288645f5050Syouri    MaybeAnimate = True;
289645f5050Syouri    return (0);
290645f5050Syouri}
291645f5050Syouri
292645f5050Syouristatic IconEntry *prevIconEntry (IconEntry *ie, IconRegion *ir)
293645f5050Syouri{
294645f5050Syouri    IconEntry	*ip;
295645f5050Syouri
296645f5050Syouri    if (ie == ir->entries)
297645f5050Syouri	return 0;
298645f5050Syouri    for (ip = ir->entries; ip->next != ie; ip=ip->next)
299645f5050Syouri	;
300645f5050Syouri    return ip;
301645f5050Syouri}
302645f5050Syouri
303645f5050Syouri/* old is being freed; and is adjacent to ie.  Merge
304645f5050Syouri * regions together
305645f5050Syouri */
306645f5050Syouri
307645f5050Syouristatic void mergeEntries (IconEntry *old, IconEntry *ie)
308645f5050Syouri{
309645f5050Syouri    if (old->y == ie->y) {
310645f5050Syouri	ie->w = old->w + ie->w;
311645f5050Syouri	if (old->x < ie->x)
312645f5050Syouri	    ie->x = old->x;
313645f5050Syouri    } else {
314645f5050Syouri	ie->h = old->h + ie->h;
315645f5050Syouri	if (old->y < ie->y)
316645f5050Syouri	    ie->y = old->y;
317645f5050Syouri    }
318645f5050Syouri}
319645f5050Syouri
320645f5050Syourivoid IconDown (TwmWindow *tmp_win)
321645f5050Syouri{
322645f5050Syouri    IconEntry	*ie, *ip, *in;
323645f5050Syouri    IconRegion	*ir;
324645f5050Syouri
325645f5050Syouri    ie = FindIconEntry (tmp_win, &ir);
326645f5050Syouri    if (ie) {
327645f5050Syouri	ie->twm_win = 0;
328645f5050Syouri	ie->used = 0;
329645f5050Syouri	ip = prevIconEntry (ie, ir);
330645f5050Syouri	in = ie->next;
331645f5050Syouri	for (;;) {
332645f5050Syouri	    if (ip && ip->used == 0 &&
333645f5050Syouri	       ((ip->x == ie->x && ip->w == ie->w) ||
334645f5050Syouri	        (ip->y == ie->y && ip->h == ie->h)))
335645f5050Syouri	    {
336645f5050Syouri	    	ip->next = ie->next;
337645f5050Syouri	    	mergeEntries (ie, ip);
338645f5050Syouri	    	free ((char *) ie);
339645f5050Syouri		ie = ip;
340645f5050Syouri	    	ip = prevIconEntry (ip, ir);
341645f5050Syouri	    } else if (in && in->used == 0 &&
342645f5050Syouri	       ((in->x == ie->x && in->w == ie->w) ||
343645f5050Syouri	        (in->y == ie->y && in->h == ie->h)))
344645f5050Syouri	    {
345645f5050Syouri	    	ie->next = in->next;
346645f5050Syouri	    	mergeEntries (in, ie);
347645f5050Syouri	    	free ((char *) in);
348645f5050Syouri	    	in = ie->next;
349645f5050Syouri	    } else
350645f5050Syouri		break;
351645f5050Syouri	}
352645f5050Syouri    }
353645f5050Syouri}
354645f5050Syouri
355645f5050Syouriname_list **AddIconRegion(char *geom,
356645f5050Syouri			  int grav1, int grav2,
357645f5050Syouri			  int stepx, int stepy,
358645f5050Syouri			  char *ijust, char *just, char *align)
359645f5050Syouri{
360645f5050Syouri    IconRegion *ir;
361645f5050Syouri    int mask, tmp;
362645f5050Syouri
363645f5050Syouri    ir = (IconRegion *)malloc(sizeof(IconRegion));
364645f5050Syouri    ir->next = NULL;
365645f5050Syouri
366645f5050Syouri    if (Scr->LastRegion) Scr->LastRegion->next = ir;
367645f5050Syouri    Scr->LastRegion = ir;
368645f5050Syouri    if (!Scr->FirstRegion) Scr->FirstRegion = ir;
369645f5050Syouri
370645f5050Syouri    ir->entries = NULL;
371645f5050Syouri    ir->clientlist = NULL;
372645f5050Syouri    ir->grav1 = grav1;
373645f5050Syouri    ir->grav2 = grav2;
374645f5050Syouri    if (stepx <= 0)
375645f5050Syouri	stepx = 1;
376645f5050Syouri    if (stepy <= 0)
377645f5050Syouri	stepy = 1;
378645f5050Syouri    ir->stepx = stepx;
379645f5050Syouri    ir->stepy = stepy;
380645f5050Syouri    ir->x = ir->y = ir->w = ir->h = 0;
381645f5050Syouri
382645f5050Syouri    mask = XParseGeometry(geom, &ir->x, &ir->y, (unsigned int *)&ir->w, (unsigned int *)&ir->h);
383645f5050Syouri
384645f5050Syouri    if (mask & XNegative) ir->x += Scr->rootw - ir->w;
385645f5050Syouri    if (mask & YNegative) ir->y += Scr->rooth - ir->h;
386645f5050Syouri
387645f5050Syouri    ir->entries = (IconEntry *)malloc(sizeof(IconEntry));
388645f5050Syouri    ir->entries->next = 0;
389645f5050Syouri    ir->entries->x = ir->x;
390645f5050Syouri    ir->entries->y = ir->y;
391645f5050Syouri    ir->entries->w = ir->w;
392645f5050Syouri    ir->entries->h = ir->h;
393645f5050Syouri    ir->entries->twm_win = 0;
394645f5050Syouri    ir->entries->used = 0;
395645f5050Syouri
396645f5050Syouri    tmp = ParseJustification (ijust);
397645f5050Syouri    if ((tmp < 0) || (tmp == J_BORDER)) {
398645f5050Syouri	twmrc_error_prefix();
399645f5050Syouri	fprintf (stderr, "ignoring invalid IconRegion argument \"%s\"\n", ijust);
400645f5050Syouri	tmp = J_UNDEF;
401645f5050Syouri    }
402645f5050Syouri    ir->TitleJustification = tmp;
403645f5050Syouri
404645f5050Syouri    tmp = ParseJustification (just);
405645f5050Syouri    if ((tmp = ParseJustification (just)) < 0) {
406645f5050Syouri	twmrc_error_prefix();
407645f5050Syouri	fprintf (stderr, "ignoring invalid IconRegion argument \"%s\"\n", just);
408645f5050Syouri	tmp = J_UNDEF;
409645f5050Syouri    }
410645f5050Syouri    ir->Justification = tmp;
411645f5050Syouri
412645f5050Syouri    if ((tmp = ParseAlignement (align)) < 0) {
413645f5050Syouri	twmrc_error_prefix();
414645f5050Syouri	fprintf (stderr, "ignoring invalid IconRegion argument \"%s\"\n", align);
415645f5050Syouri	tmp = J_UNDEF;
416645f5050Syouri    }
417645f5050Syouri    ir->Alignement = tmp;
418645f5050Syouri
419645f5050Syouri    return(&(ir->clientlist));
420645f5050Syouri}
421645f5050Syouri
422645f5050Syouri#ifdef comment
423645f5050SyouriFreeIconEntries (ir)
424645f5050Syouri    IconRegion	*ir;
425645f5050Syouri{
426645f5050Syouri    IconEntry	*ie, *tmp;
427645f5050Syouri
428645f5050Syouri    for (ie = ir->entries; ie; ie=tmp)
429645f5050Syouri    {
430645f5050Syouri	tmp = ie->next;
431645f5050Syouri	free ((char *) ie);
432645f5050Syouri    }
433645f5050Syouri}
434645f5050SyouriFreeIconRegions()
435645f5050Syouri{
436645f5050Syouri    IconRegion *ir, *tmp;
437645f5050Syouri
438645f5050Syouri    for (ir = Scr->FirstRegion; ir != NULL;)
439645f5050Syouri    {
440645f5050Syouri	tmp = ir;
441645f5050Syouri	FreeIconEntries (ir);
442645f5050Syouri	ir = ir->next;
443645f5050Syouri	free((char *) tmp);
444645f5050Syouri    }
445645f5050Syouri    Scr->FirstRegion = NULL;
446645f5050Syouri    Scr->LastRegion = NULL;
447645f5050Syouri}
448645f5050Syouri#endif
449645f5050Syouri
450645f5050Syouriint CreateIconWindow(TwmWindow *tmp_win, int def_x, int def_y)
451645f5050Syouri{
452645f5050Syouri    unsigned long event_mask;
453645f5050Syouri    unsigned long valuemask;		/* mask for create windows */
454645f5050Syouri    XSetWindowAttributes attributes;	/* attributes for create windows */
455645f5050Syouri    int final_x, final_y;
456645f5050Syouri    int x;
457645f5050Syouri    Icon	*icon;
458645f5050Syouri    Image	*image = None;
459645f5050Syouri
460645f5050Syouri    icon = (Icon*) malloc (sizeof (struct Icon));
461645f5050Syouri
462645f5050Syouri    icon->border	= Scr->IconBorderColor;
463645f5050Syouri    icon->iconc.fore	= Scr->IconC.fore;
464645f5050Syouri    icon->iconc.back	= Scr->IconC.back;
465645f5050Syouri
466645f5050Syouri    GetColorFromList(Scr->IconBorderColorL, tmp_win->full_name, &tmp_win->class,
467645f5050Syouri	&icon->border);
468645f5050Syouri    GetColorFromList(Scr->IconForegroundL, tmp_win->full_name, &tmp_win->class,
469645f5050Syouri	&icon->iconc.fore);
470645f5050Syouri    GetColorFromList(Scr->IconBackgroundL, tmp_win->full_name, &tmp_win->class,
471645f5050Syouri	&icon->iconc.back);
472645f5050Syouri    if (Scr->use3Diconmanagers && !Scr->BeNiceToColormap) GetShadeColors (&icon->iconc);
473645f5050Syouri
474645f5050Syouri    FB(icon->iconc.fore, icon->iconc.back);
475645f5050Syouri
476645f5050Syouri    icon->match   = match_none;
477645f5050Syouri    icon->pattern = NULL;
478645f5050Syouri    icon->image   = None;
479645f5050Syouri    icon->ir      = (IconRegion*) 0;
480645f5050Syouri
481645f5050Syouri    tmp_win->forced = FALSE;
482645f5050Syouri    tmp_win->icon_not_ours = FALSE;
483645f5050Syouri
484645f5050Syouri    /* now go through the steps to get an icon window,  if ForceIcon is
485645f5050Syouri     * set, then no matter what else is defined, the bitmap from the
486645f5050Syouri     * .twmrc file is used
487645f5050Syouri     */
488645f5050Syouri    if (Scr->ForceIcon) {
489645f5050Syouri	char *icon_name;
490645f5050Syouri
491645f5050Syouri	icon_name = LookInNameList (Scr->IconNames, tmp_win->icon_name);
492645f5050Syouri        if (icon_name != NULL) {
493645f5050Syouri	    icon->pattern = LookPatternInNameList (Scr->IconNames, tmp_win->icon_name);
494645f5050Syouri	    icon->match = match_icon;
495645f5050Syouri	}
496645f5050Syouri        if (icon->match == match_none)
497645f5050Syouri	    icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
498645f5050Syouri        if ((icon->match == match_none) && (icon_name != NULL)) {
499645f5050Syouri	    icon->pattern = LookPatternInNameList (Scr->IconNames, tmp_win->full_name);
500645f5050Syouri	    icon->match = match_name;
501645f5050Syouri	}
502645f5050Syouri        if (icon->match == match_none)
503645f5050Syouri	    icon_name = LookInList(Scr->IconNames, tmp_win->full_name, &tmp_win->class);
504645f5050Syouri        if ((icon->match == match_none) && (icon_name != NULL)) {
505645f5050Syouri	    icon->pattern = LookPatternInList (Scr->IconNames, tmp_win->full_name, &tmp_win->class);
506645f5050Syouri	    icon->match = match_class;
507645f5050Syouri	}
508645f5050Syouri	if ((image  = GetImage (icon_name, icon->iconc)) != None) {
509645f5050Syouri	    icon->image  = image;
510645f5050Syouri	    icon->width  = image->width;
511645f5050Syouri	    icon->height = image->height;
512645f5050Syouri	    tmp_win->forced = TRUE;
513645f5050Syouri	}
514645f5050Syouri    }
515645f5050Syouri
516645f5050Syouri    /* if the pixmap is still NULL, we didn't get one from the above code,
517645f5050Syouri     * that could mean that ForceIcon was not set, or that the window
518645f5050Syouri     * was not in the Icons list, now check the WM hints for an icon
519645f5050Syouri     */
520645f5050Syouri    if (image == None && tmp_win->wmhints &&
521645f5050Syouri	tmp_win->wmhints->flags & IconPixmapHint) {
522645f5050Syouri	if (XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap,
523645f5050Syouri		&JunkRoot, &JunkX, &JunkY, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) {
524645f5050Syouri	    image = (Image*) malloc (sizeof (struct _Image));
525645f5050Syouri	    image->width  = JunkWidth;
526645f5050Syouri	    image->height = JunkHeight;
527645f5050Syouri	    image->pixmap = XCreatePixmap (dpy, Scr->Root, image->width,
528645f5050Syouri					image->height, Scr->d_depth);
529645f5050Syouri	    image->mask   = None;
530645f5050Syouri	    image->next   = None;
531645f5050Syouri	    if (JunkDepth == Scr->d_depth)
532645f5050Syouri		XCopyArea  (dpy, tmp_win->wmhints->icon_pixmap, image->pixmap, Scr->NormalGC,
533645f5050Syouri			0, 0, image->width, image->height, 0, 0);
534645f5050Syouri	    else
535645f5050Syouri		XCopyPlane (dpy, tmp_win->wmhints->icon_pixmap, image->pixmap, Scr->NormalGC,
536645f5050Syouri			0, 0, image->width, image->height, 0, 0, 1 );
537645f5050Syouri
538645f5050Syouri	    icon->width   = image->width;
539645f5050Syouri	    icon->height  = image->height;
540645f5050Syouri
541645f5050Syouri	    if ((tmp_win->wmhints->flags & IconMaskHint) &&
542645f5050Syouri		XGetGeometry(dpy, tmp_win->wmhints->icon_mask,
543645f5050Syouri		    &JunkRoot, &JunkX, &JunkY, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) &&
544645f5050Syouri		(JunkDepth == 1)) {
545645f5050Syouri		GC gc;
546645f5050Syouri
547645f5050Syouri		image->mask = XCreatePixmap (dpy, Scr->Root, JunkWidth, JunkHeight, 1);
548645f5050Syouri		if (image->mask) {
549645f5050Syouri		    gc = XCreateGC (dpy, image->mask, 0, NULL);
550645f5050Syouri		    if (gc) {
551645f5050Syouri			XCopyArea (dpy, tmp_win->wmhints->icon_mask, image->mask, gc,
552645f5050Syouri				0, 0, JunkWidth, JunkHeight, 0, 0);
553645f5050Syouri			XFreeGC (dpy, gc);
554645f5050Syouri		    }
555645f5050Syouri		}
556645f5050Syouri	    }
557645f5050Syouri	    icon->image = image;
558645f5050Syouri	}
559645f5050Syouri    }
560645f5050Syouri
561645f5050Syouri    /* if we still haven't got an icon, let's look in the Icon list
562645f5050Syouri     * if ForceIcon is not set
563645f5050Syouri     */
564645f5050Syouri    if (image == None && !Scr->ForceIcon) {
565645f5050Syouri	char *icon_name;
566645f5050Syouri
567645f5050Syouri	icon->match   = match_none;
568645f5050Syouri	icon->pattern = NULL;
569645f5050Syouri	icon_name = LookInNameList(Scr->IconNames, tmp_win->icon_name);
570645f5050Syouri        if (icon_name != NULL) {
571645f5050Syouri	    icon->pattern = LookPatternInNameList (Scr->IconNames, tmp_win->icon_name);
572645f5050Syouri	    icon->match = match_icon;
573645f5050Syouri	}
574645f5050Syouri        if (icon->match == match_none)
575645f5050Syouri	    icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
576645f5050Syouri        if ((icon->match == match_none) && (icon_name != NULL)) {
577645f5050Syouri	    icon->pattern = LookPatternInNameList (Scr->IconNames, tmp_win->full_name);
578645f5050Syouri	    icon->match = match_name;
579645f5050Syouri	}
580645f5050Syouri        if (icon->match == match_none)
581645f5050Syouri	    icon_name = LookInList(Scr->IconNames, tmp_win->full_name, &tmp_win->class);
582645f5050Syouri        if ((icon->match == match_none) && (icon_name != NULL)) {
583645f5050Syouri	    icon->pattern = LookPatternInList (Scr->IconNames,
584645f5050Syouri				tmp_win->full_name, &tmp_win->class);
585645f5050Syouri	    icon->match = match_class;
586645f5050Syouri	}
587645f5050Syouri	if ((image = GetImage (icon_name, icon->iconc)) != None) {
588645f5050Syouri	    icon->image  = image;
589645f5050Syouri	    icon->width  = image->width;
590645f5050Syouri	    icon->height = image->height;
591645f5050Syouri	    tmp_win->forced = TRUE;
592645f5050Syouri	}
593645f5050Syouri    }
594645f5050Syouri
595645f5050Syouri    /* if we still don't have an icon, assign the UnknownIcon */
596645f5050Syouri    if (image == None && Scr->UnknownImage != None)
597645f5050Syouri    {
598645f5050Syouri	image = Scr->UnknownImage;
599645f5050Syouri	icon->width   = image->width;
600645f5050Syouri	icon->height  = image->height;
601645f5050Syouri	icon->image   = image;
602645f5050Syouri    }
603645f5050Syouri
604645f5050Syouri    if (image == None)
605645f5050Syouri    {
606645f5050Syouri	icon->height = 0;
607645f5050Syouri	icon->width  = 0;
608645f5050Syouri	valuemask    = 0;
609645f5050Syouri    }
610645f5050Syouri    else
611645f5050Syouri    {
612645f5050Syouri	valuemask = CWBackPixmap;
613645f5050Syouri	attributes.background_pixmap = image->pixmap;
614645f5050Syouri    }
615645f5050Syouri
616645f5050Syouri    icon->border_width = Scr->IconBorderWidth;
617645f5050Syouri    if (Scr->NoIconTitlebar ||
618645f5050Syouri	LookInNameList (Scr->NoIconTitle, tmp_win->icon_name) ||
619645f5050Syouri	LookInList (Scr->NoIconTitle, tmp_win->full_name, &tmp_win->class))
620645f5050Syouri    {
621645f5050Syouri	icon->w_width  = icon->width;
622645f5050Syouri	icon->w_height = icon->height;
623645f5050Syouri	icon->x = 0;
624645f5050Syouri	icon->y = 0;
625645f5050Syouri	icon->has_title = False;
626645f5050Syouri    }
627645f5050Syouri    else {
628645f5050Syouri	XRectangle inc_rect;
629645f5050Syouri	XRectangle logical_rect;
630645f5050Syouri
631645f5050Syouri	XmbTextExtents(Scr->IconFont.font_set,
632645f5050Syouri		       tmp_win->icon_name, strlen (tmp_win->icon_name),
633645f5050Syouri		       &inc_rect, &logical_rect);
634645f5050Syouri	icon->w_width = logical_rect.width;
635645f5050Syouri
636645f5050Syouri	icon->w_width += 2 * Scr->IconManagerShadowDepth + 6;
637645f5050Syouri	if (icon->w_width > Scr->MaxIconTitleWidth) icon->w_width = Scr->MaxIconTitleWidth;
638645f5050Syouri	if (icon->w_width < icon->width)
639645f5050Syouri	{
640645f5050Syouri	    icon->x  = (icon->width - icon->w_width) / 2;
641645f5050Syouri	    icon->x += Scr->IconManagerShadowDepth + 3;
642645f5050Syouri	    icon->w_width = icon->width;
643645f5050Syouri	}
644645f5050Syouri	else
645645f5050Syouri	{
646645f5050Syouri	    icon->x = Scr->IconManagerShadowDepth + 3;
647645f5050Syouri	}
648645f5050Syouri	icon->y = icon->height + Scr->IconFont.height + Scr->IconManagerShadowDepth;
649645f5050Syouri	icon->w_height = icon->height + Scr->IconFont.height +
650645f5050Syouri			 2 * Scr->IconManagerShadowDepth + 6;
651645f5050Syouri	icon->has_title = True;
652645f5050Syouri	if (icon->height) icon->border_width = 0;
653645f5050Syouri    }
654645f5050Syouri
655645f5050Syouri    event_mask = 0;
656645f5050Syouri    if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)
657645f5050Syouri    {
658645f5050Syouri	icon->w = tmp_win->wmhints->icon_window;
659645f5050Syouri	if (tmp_win->forced ||
660645f5050Syouri	    XGetGeometry(dpy, icon->w, &JunkRoot, &JunkX, &JunkY,
661645f5050Syouri		     (unsigned int *)&icon->w_width, (unsigned int *)&icon->w_height,
662645f5050Syouri		     &JunkBW, &JunkDepth) == 0)
663645f5050Syouri	{
664645f5050Syouri	    icon->w = None;
665645f5050Syouri	    tmp_win->wmhints->flags &= ~IconWindowHint;
666645f5050Syouri	}
667645f5050Syouri	else
668645f5050Syouri	{
669645f5050Syouri	    tmp_win->icon_not_ours = TRUE;
670645f5050Syouri	    image = None;
671645f5050Syouri	    icon->width  = icon->w_width;
672645f5050Syouri	    icon->height = icon->w_height;
673645f5050Syouri	    icon->image  = image;
674645f5050Syouri	    icon->has_title = False;
675645f5050Syouri	    event_mask = 0;
676645f5050Syouri	}
677645f5050Syouri    }
678645f5050Syouri    else
679645f5050Syouri    {
680645f5050Syouri	icon->w = None;
681645f5050Syouri    }
682645f5050Syouri
683645f5050Syouri    if ((image != None) &&
684645f5050Syouri	 image->mask != None &&
685645f5050Syouri	 (! (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint))) {
686645f5050Syouri	    icon->border_width = 0;
687645f5050Syouri    }
688645f5050Syouri    if (icon->w == None)
689645f5050Syouri    {
690645f5050Syouri	icon->w = XCreateSimpleWindow(dpy, Scr->Root,
691645f5050Syouri	    0,0,
692645f5050Syouri	    icon->w_width, icon->w_height,
693645f5050Syouri	    icon->border_width, icon->border, icon->iconc.back);
694645f5050Syouri	event_mask = ExposureMask;
695645f5050Syouri    }
696645f5050Syouri
697645f5050Syouri    if (Scr->AutoRaiseIcons || Scr->ShrinkIconTitles)
698645f5050Syouri	event_mask |= EnterWindowMask | LeaveWindowMask;
699645f5050Syouri    event_mask |= KeyPressMask | ButtonPressMask | ButtonReleaseMask;
700645f5050Syouri
701645f5050Syouri    if (tmp_win->icon_not_ours) {
702645f5050Syouri	XWindowAttributes wattr;
703645f5050Syouri
704645f5050Syouri        XGetWindowAttributes(dpy, icon->w, &wattr);
705645f5050Syouri        if (wattr.all_event_masks & ButtonPressMask) {
706645f5050Syouri            event_mask &= ~ButtonPressMask;
707645f5050Syouri	}
708645f5050Syouri    }
709645f5050Syouri    XSelectInput (dpy, icon->w, event_mask);
710645f5050Syouri
711645f5050Syouri    if (icon->width == 0) icon->width = icon->w_width;
712645f5050Syouri    icon->bm_w = None;
713645f5050Syouri    if (image && (! (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint))) {
714645f5050Syouri	XRectangle rect;
715645f5050Syouri
716645f5050Syouri	x = GetIconOffset (icon);
717645f5050Syouri	icon->bm_w = XCreateWindow (dpy, icon->w, x, 0,
718645f5050Syouri					    (unsigned int)icon->width,
719645f5050Syouri					    (unsigned int)icon->height,
720645f5050Syouri					    (unsigned int) 0, Scr->d_depth,
721645f5050Syouri					    (unsigned int) CopyFromParent,
722645f5050Syouri					    Scr->d_visual, valuemask,
723645f5050Syouri					    &attributes);
724645f5050Syouri	if (image->mask) {
725645f5050Syouri	    XShapeCombineMask (dpy, icon->bm_w, ShapeBounding, 0, 0, image->mask, ShapeSet);
726645f5050Syouri	    XShapeCombineMask (dpy, icon->w,    ShapeBounding, x, 0, image->mask, ShapeSet);
727645f5050Syouri	} else if (icon->has_title) {
728645f5050Syouri	    rect.x      = x;
729645f5050Syouri	    rect.y      = 0;
730645f5050Syouri	    rect.width  = icon->width;
731645f5050Syouri	    rect.height = icon->height;
732645f5050Syouri	    XShapeCombineRectangles (dpy, icon->w, ShapeBounding,
733645f5050Syouri			0, 0, &rect, 1, ShapeSet, 0);
734645f5050Syouri	}
735645f5050Syouri	if (icon->has_title) {
736645f5050Syouri	    if (Scr->ShrinkIconTitles) {
737645f5050Syouri		rect.x      = x;
738645f5050Syouri		rect.y      = icon->height;
739645f5050Syouri		rect.width  = icon->width;
740645f5050Syouri		rect.height = icon->w_height - icon->height;
741645f5050Syouri		icon->title_shrunk = True;
742645f5050Syouri	    } else {
743645f5050Syouri		rect.x      = 0;
744645f5050Syouri		rect.y      = icon->height;
745645f5050Syouri		rect.width  = icon->w_width;
746645f5050Syouri		rect.height = icon->w_height - icon->height;
747645f5050Syouri		icon->title_shrunk = False;
748645f5050Syouri	    }
749645f5050Syouri	    XShapeCombineRectangles (dpy, icon->w, ShapeBounding,
750645f5050Syouri			0, 0, &rect, 1, ShapeUnion, 0);
751645f5050Syouri	}
752645f5050Syouri    }
753645f5050Syouri
754645f5050Syouri    if (icon->match != match_none)
755645f5050Syouri	AddToList (&tmp_win->iconslist, icon->pattern, (char*) icon);
756645f5050Syouri
757645f5050Syouri    tmp_win->icon = icon;
758645f5050Syouri    /* I need to figure out where to put the icon window now, because
759645f5050Syouri     * getting here means that I am going to make the icon visible
760645f5050Syouri     */
761645f5050Syouri    if (tmp_win->wmhints &&
762645f5050Syouri	tmp_win->wmhints->flags & IconPositionHint)
763645f5050Syouri    {
764645f5050Syouri	final_x = tmp_win->wmhints->icon_x;
765645f5050Syouri	final_y = tmp_win->wmhints->icon_y;
766645f5050Syouri    }
767645f5050Syouri    else
768645f5050Syouri    {
769645f5050Syouri      if (visible (tmp_win))
770645f5050Syouri	PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y);
771645f5050Syouri    }
772645f5050Syouri
773645f5050Syouri  if (visible (tmp_win) ||
774645f5050Syouri      (tmp_win->wmhints && tmp_win->wmhints->flags & IconPositionHint)) {
775645f5050Syouri    if (final_x > Scr->rootw)
776645f5050Syouri	final_x = Scr->rootw - icon->w_width - (2 * Scr->IconBorderWidth);
777645f5050Syouri    if (Scr->ShrinkIconTitles && icon->bm_w) {
778645f5050Syouri	if (final_x + (icon->w_width - icon->width) < 0) final_x = 0;
779645f5050Syouri    } else {
780645f5050Syouri	if (final_x < 0) final_x = 0;
781645f5050Syouri    }
782645f5050Syouri    if (final_y > Scr->rooth)
783645f5050Syouri	final_y = Scr->rooth - icon->height -
784645f5050Syouri	    Scr->IconFont.height - 6 - (2 * Scr->IconBorderWidth);
785645f5050Syouri    if (final_y < 0) final_y = 0;
786645f5050Syouri
787645f5050Syouri    XMoveWindow(dpy, icon->w, final_x, final_y);
788645f5050Syouri  }
789645f5050Syouri    tmp_win->iconified = TRUE;
790645f5050Syouri
791645f5050Syouri    XMapSubwindows(dpy, icon->w);
792645f5050Syouri    XSaveContext(dpy, icon->w, TwmContext, (XPointer)tmp_win);
793645f5050Syouri    XSaveContext(dpy, icon->w, ScreenContext, (XPointer)Scr);
794645f5050Syouri    XDefineCursor(dpy, icon->w, Scr->IconCursor);
795645f5050Syouri    MaybeAnimate = True;
796645f5050Syouri    return (0);
797645f5050Syouri}
798645f5050Syouri
799645f5050Syourivoid DeleteIconsList(TwmWindow *tmp_win)
800645f5050Syouri{
801645f5050Syouri    /*
802645f5050Syouri     * Only the list itself needs to be freed, since the pointers it
803645f5050Syouri     * contains point into various lists that belong to Scr.
804645f5050Syouri     */
805645f5050Syouri    FreeList(&tmp_win->iconslist);
806645f5050Syouri}
807645f5050Syouri
808645f5050Syourivoid ShrinkIconTitle (TwmWindow *tmp_win)
809645f5050Syouri{
810645f5050Syouri    Icon	*icon;
811645f5050Syouri    XRectangle	rect;
812645f5050Syouri
813645f5050Syouri    if (!tmp_win || !tmp_win->icon) return;
814645f5050Syouri    icon = tmp_win->icon;
815645f5050Syouri    if (!icon->has_title) return;
816645f5050Syouri    if (icon->w_width == icon->width) return;
817645f5050Syouri    if (icon->height  == 0) return;
818645f5050Syouri
819645f5050Syouri    rect.x      = GetIconOffset (icon);
820645f5050Syouri    rect.y      = 0;
821645f5050Syouri    rect.width  = icon->width;
822645f5050Syouri    rect.height = icon->w_height;
823645f5050Syouri    XShapeCombineRectangles (dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeIntersect, 0);
824645f5050Syouri    icon->title_shrunk = True;
825645f5050Syouri    XClearArea (dpy, icon->w, 0, icon->height, icon->w_width,
826645f5050Syouri		icon->w_height - icon->height, True);
827645f5050Syouri}
828645f5050Syouri
829645f5050Syourivoid ExpandIconTitle (TwmWindow *tmp_win)
830645f5050Syouri{
831645f5050Syouri    Icon	*icon;
832645f5050Syouri    XRectangle	rect;
833645f5050Syouri
834645f5050Syouri    if (!tmp_win || !tmp_win->icon) return;
835645f5050Syouri    icon = tmp_win->icon;
836645f5050Syouri    if (!icon->has_title) return;
837645f5050Syouri    if (icon->w_width == icon->width) return;
838645f5050Syouri    if (icon->height  == 0) return;
839645f5050Syouri
840645f5050Syouri    rect.x      = 0;
841645f5050Syouri    rect.y      = icon->height;
842645f5050Syouri    rect.width  = icon->w_width;
843645f5050Syouri    rect.height = icon->w_height - icon->height;
844645f5050Syouri    XShapeCombineRectangles (dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, 0);
845645f5050Syouri    icon->title_shrunk = False;
846645f5050Syouri    XClearArea (dpy, icon->w, 0, icon->height, icon->w_width,
847645f5050Syouri		icon->w_height - icon->height, True);
848645f5050Syouri}
849645f5050Syouri
850645f5050Syourivoid ReshapeIcon (Icon *icon)
851645f5050Syouri{
852645f5050Syouri    int x;
853645f5050Syouri    XRectangle	rect;
854645f5050Syouri
855645f5050Syouri    if (!icon) return;
856645f5050Syouri    x = GetIconOffset (icon);
857645f5050Syouri    XMoveWindow (dpy, icon->bm_w, x, 0);
858645f5050Syouri
859645f5050Syouri    if (icon->image && icon->image->mask) {
860645f5050Syouri	XShapeCombineMask (dpy, icon->w, ShapeBounding, x, 0, icon->image->mask, ShapeSet);
861645f5050Syouri    } else {
862645f5050Syouri	rect.x      = x;
863645f5050Syouri	rect.y      = 0;
864645f5050Syouri	rect.width  = icon->width;
865645f5050Syouri	rect.height = icon->height;
866645f5050Syouri	XShapeCombineRectangles (dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
867645f5050Syouri    }
868645f5050Syouri    rect.x      = x;
869645f5050Syouri    rect.y      = icon->height;
870645f5050Syouri    rect.width  = icon->width;
871645f5050Syouri    rect.height = icon->w_height - icon->height;
872645f5050Syouri    XShapeCombineRectangles (dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, 0);
873645f5050Syouri}
874645f5050Syouri
875645f5050Syouriint GetIconOffset (Icon *icon)
876645f5050Syouri{
877645f5050Syouri    short justif;
878645f5050Syouri
879645f5050Syouri    if (!icon) return (0);
880645f5050Syouri
881645f5050Syouri    justif = icon->ir ? icon->ir->TitleJustification : Scr->IconJustification;
882645f5050Syouri    switch (justif) {
883645f5050Syouri	case J_LEFT :
884645f5050Syouri	    return (0);
885645f5050Syouri
886645f5050Syouri	case J_CENTER :
887645f5050Syouri	    return ((icon->w_width - icon->width) / 2);
888645f5050Syouri
889645f5050Syouri	case J_RIGHT :
890645f5050Syouri	    return (icon->w_width - icon->width);
891645f5050Syouri
892645f5050Syouri	default :
893645f5050Syouri	    return (0);
894645f5050Syouri    }
895645f5050Syouri}
896645f5050Syouri
897645f5050SyouriBool AnimateIcons (ScreenInfo *scr, Icon *icon)
898645f5050Syouri{
899645f5050Syouri    Image	*image;
900645f5050Syouri    XRectangle	rect;
901645f5050Syouri    XSetWindowAttributes attr;
902645f5050Syouri    int		x;
903645f5050Syouri
904645f5050Syouri    image = icon->image;
905645f5050Syouri    attr.background_pixmap = image->pixmap;
906645f5050Syouri    XChangeWindowAttributes (dpy, icon->bm_w, CWBackPixmap, &attr);
907645f5050Syouri
908645f5050Syouri    if (image->mask != None) {
909645f5050Syouri	x = GetIconOffset (icon);
910645f5050Syouri	XShapeCombineMask (dpy, icon->bm_w, ShapeBounding, 0, 0, image->mask, ShapeSet);
911645f5050Syouri	if (icon->has_title) {
912645f5050Syouri	    rect.x      = 0;
913645f5050Syouri	    rect.y      = icon->height;
914645f5050Syouri	    rect.width  = icon->w_width;
915645f5050Syouri	    rect.height = scr->IconFont.height + 6;
916645f5050Syouri
917645f5050Syouri	    XShapeCombineShape (dpy, scr->ShapeWindow, ShapeBounding, x, 0, icon->bm_w,
918645f5050Syouri				ShapeBounding, ShapeSet);
919645f5050Syouri	    XShapeCombineRectangles (dpy, scr->ShapeWindow, ShapeBounding, 0, 0, &rect, 1,
920645f5050Syouri				ShapeUnion, 0);
921645f5050Syouri	    XShapeCombineShape (dpy, icon->w, ShapeBounding, 0, 0, scr->ShapeWindow,
922645f5050Syouri				ShapeBounding, ShapeSet);
923645f5050Syouri	}
924645f5050Syouri	else
925645f5050Syouri	    XShapeCombineShape (dpy, icon->w, ShapeBounding, x, 0, icon->bm_w,
926645f5050Syouri				ShapeBounding, ShapeSet);
927645f5050Syouri    }
928645f5050Syouri    XClearWindow (dpy, icon->bm_w);
929645f5050Syouri    icon->image  = image->next;
930645f5050Syouri    return (True);
931645f5050Syouri}
932645f5050Syouri
933