1 /* $Id: icons.c,v 1.1 2004/08/28 19:25:46 dannybackx Exp $ */
2 /****************************************************************************
3  * This module is mostly all new
4  * by Rob Nation
5  * A little of it is borrowed from ctwm.
6  * Copyright 1993 Robert Nation. No restrictions are placed on this code,
7  * as long as the copyright notice is preserved
8  ****************************************************************************/
9 /***********************************************************************
10  *
11  * mwm icon code
12  *
13  ***********************************************************************/
14 
15 #include <LTconfig.h>
16 
17 #include <stdio.h>
18 #include <string.h>
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #ifdef HAVE_FCNTL_H
23 #include <fcntl.h>
24 #endif
25 
26 #include <X11/Intrinsic.h>
27 #include <X11/extensions/shape.h>
28 
29 #include <Xm/Xm.h>
30 #include <Xm/MwmUtil.h>
31 #if XmVERSION >= 2
32 #include <Xm/XpmP.h>
33 #else
34 #include <XmI/XmXpm.h>
35 #endif
36 
37 #include "mwm.h"
38 
39 
40 #define def_bitmap_width 50
41 #define def_bitmap_height 50
42 static unsigned char def_bitmap_bits[] =
43 {
44     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
45     0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x80,
46     0x00, 0x00, 0x20, 0x02, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x30, 0x02, 0xe1,
47     0xff, 0xdf, 0xf0, 0xff, 0x37, 0x02, 0xe1, 0xff, 0xdf, 0xb0, 0xaa, 0x36,
48     0x02, 0xe1, 0xff, 0xdf, 0x50, 0x55, 0x35, 0x02, 0xe1, 0xff, 0xdf, 0xb0,
49     0xaa, 0x36, 0x02, 0xe1, 0xff, 0xdf, 0x50, 0x55, 0x35, 0x02, 0xe1, 0xff,
50     0xdf, 0xb0, 0xaa, 0x36, 0x02, 0xe1, 0xff, 0xdf, 0x50, 0x55, 0x35, 0x02,
51     0xe1, 0xff, 0xdf, 0xb0, 0xaa, 0x36, 0x02, 0xe1, 0xff, 0xdf, 0x50, 0x55,
52     0x35, 0x02, 0xe1, 0xff, 0xdf, 0xb0, 0xaa, 0x36, 0x02, 0xe1, 0xff, 0xdf,
53     0x50, 0x55, 0x35, 0x02, 0xe1, 0xff, 0xdf, 0xb0, 0xaa, 0x36, 0x02, 0xe1,
54     0xff, 0xdf, 0x50, 0x55, 0x35, 0x02, 0xe1, 0xff, 0xdf, 0xf0, 0xff, 0x37,
55     0x02, 0x01, 0x00, 0x80, 0x00, 0x00, 0x20, 0x02, 0xf1, 0xff, 0x3f, 0xf8,
56     0xff, 0x0f, 0x02, 0xf9, 0xff, 0x7f, 0xfc, 0xff, 0x1f, 0x02, 0x01, 0x00,
57     0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
58     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x02, 0x01, 0x00, 0x80, 0x00, 0x00, 0x20, 0x02, 0x01, 0x00, 0xc0,
60     0x00, 0x00, 0x30, 0x02, 0xe1, 0xff, 0xdf, 0xf0, 0xff, 0x37, 0x02, 0x61,
61     0x55, 0xd5, 0xf0, 0xff, 0x37, 0x02, 0xa1, 0xaa, 0xda, 0xf0, 0xff, 0x37,
62     0x02, 0x61, 0x55, 0xd5, 0xf0, 0xff, 0x37, 0x02, 0xa1, 0xaa, 0xda, 0xf0,
63     0xff, 0x37, 0x02, 0x61, 0x55, 0xd5, 0xf0, 0xff, 0x37, 0x02, 0xa1, 0xaa,
64     0xda, 0xf0, 0xff, 0x37, 0x02, 0x61, 0x55, 0xd5, 0xf0, 0xff, 0x37, 0x02,
65     0xa1, 0xaa, 0xda, 0xf0, 0xff, 0x37, 0x02, 0x61, 0x55, 0xd5, 0xf0, 0xff,
66     0x37, 0x02, 0xa1, 0xaa, 0xda, 0xf0, 0xff, 0x37, 0x02, 0x61, 0x55, 0xd5,
67     0xf0, 0xff, 0x37, 0x02, 0xa1, 0xaa, 0xda, 0xf0, 0xff, 0x37, 0x02, 0x61,
68     0x55, 0xd5, 0xf0, 0xff, 0x37, 0x02, 0xe1, 0xff, 0xdf, 0xf0, 0xff, 0x37,
69     0x02, 0x01, 0x00, 0x80, 0x00, 0x00, 0x20, 0x02, 0xf1, 0xff, 0x3f, 0xf8,
70     0xff, 0x0f, 0x02, 0xf9, 0xff, 0x7f, 0xfc, 0xff, 0x1f, 0x02, 0x01, 0x00,
71     0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
72     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
73     0xff, 0x03};
74 
75 
76 #ifdef __EMX__
77  /* dos-like */
78 #define cPATHELEMENTSEP ';'
79 #else
80   /* un*x-like */
81 #define cPATHELEMENTSEP ':'
82 #endif
83 
84 /*
85  * Find the specified icon file somewhere along the given path.
86  *
87  * There is a possible race condition here:  We check the file and later
88  * do something with it.  By then, the file might not be accessible.
89  * Oh well.
90  */
91 static char *
find_icon_file(const char * icon,const char * pathlist,int type)92 find_icon_file(const char *icon, const char *pathlist, int type)
93 {
94     char *path;
95     char *dir_end;
96     int l1, l2;
97 
98     if (icon != NULL)
99 	l1 = strlen(icon);
100     else
101 	l1 = 0;
102 
103     if (pathlist != NULL)
104 	l2 = strlen(pathlist);
105     else
106 	l2 = 0;
107 
108     path = XtMalloc(l1 + l2 + 10);
109     *path = '\0';
110     if (*icon == '/')
111     {
112 	/* No search if icon begins with a slash */
113 	strcpy(path, icon);
114 	return path;
115     }
116 
117     if ((pathlist == NULL) || (*pathlist == '\0'))
118     {
119 	/* No search if pathlist is empty */
120 	strcpy(path, icon);
121 	return path;
122     }
123 
124     /* Search each element of the pathlist for the icon file */
125     while ((pathlist) && (*pathlist))
126     {
127 	dir_end = strchr(pathlist, cPATHELEMENTSEP);
128 	if (dir_end != NULL)
129 	{
130 	    strncpy(path, pathlist, dir_end - pathlist);
131 	    path[dir_end - pathlist] = 0;
132 	}
133 	else
134 	    strcpy(path, pathlist);
135 
136 	strcat(path, "/");
137 	strcat(path, icon);
138 	if (access(path, type) == 0)
139 	    return path;
140 	strcat(path, ".gz");
141 	if (access(path, type) == 0)
142 	    return path;
143 
144 	/* Point to next element of the path */
145 	if (dir_end == NULL)
146 	    pathlist = NULL;
147 	else
148 	    pathlist = dir_end + 1;
149     }
150     /* Hmm, couldn't find the file.  Return NULL */
151     XtFree(path);
152     return NULL;
153 }
154 
155 /*
156  * grab needed buttons for the icon window
157  */
158 static void
grab_icon_buttons(ScreenInfo * scr,MwmWindow * tmp_win,Window w)159 grab_icon_buttons(ScreenInfo *scr, MwmWindow *tmp_win, Window w)
160 {
161     MouseButton *MouseEntry;
162 
163     MouseEntry = scr->buttons;
164     while (MouseEntry != (MouseButton *)0)
165     {
166 	if ((MouseEntry->func != (int)0) && (MouseEntry->context & C_ICON))
167 	{
168 	    if (MouseEntry->button > 0)
169 		XGrabButton(dpy, MouseEntry->button, MouseEntry->modifier, w,
170 			    True, ButtonPressMask | ButtonReleaseMask,
171 			    GrabModeAsync, GrabModeAsync, None,
172 			    scr->cursors[DEFAULT_CURS]);
173 	    else
174 	    {
175 		XGrabButton(dpy, 1, MouseEntry->modifier, w,
176 			    True, ButtonPressMask | ButtonReleaseMask,
177 			    GrabModeAsync, GrabModeAsync, None,
178 			    scr->cursors[DEFAULT_CURS]);
179 		XGrabButton(dpy, 2, MouseEntry->modifier, w,
180 			    True, ButtonPressMask | ButtonReleaseMask,
181 			    GrabModeAsync, GrabModeAsync, None,
182 			    scr->cursors[DEFAULT_CURS]);
183 		XGrabButton(dpy, 3, MouseEntry->modifier, w,
184 			    True, ButtonPressMask | ButtonReleaseMask,
185 			    GrabModeAsync, GrabModeAsync, None,
186 			    scr->cursors[DEFAULT_CURS]);
187 	    }
188 	}
189 
190 	MouseEntry = MouseEntry->next;
191     }
192 }
193 
194 /*
195  * grab needed keys for the icon window
196  */
197 static void
grab_icon_keys(ScreenInfo * scr,MwmWindow * tmp_win,Window w)198 grab_icon_keys(ScreenInfo *scr, MwmWindow *tmp_win, Window w)
199 {
200     FuncKey *tmp;
201 
202     for (tmp = scr->keys; tmp != NULL; tmp = tmp->next)
203     {
204 	if (tmp->cont & C_ICON)
205 	    XGrabKey(dpy, tmp->keycode, tmp->mods, w, True,
206 		     GrabModeAsync, GrabModeAsync);
207     }
208 }
209 
210 /*
211  * Looks for a monochrome icon bitmap file
212  */
213 static void
get_bitmap_file(ScreenInfo * scr,MwmWindow * tmp_win)214 get_bitmap_file(ScreenInfo *scr, MwmWindow *tmp_win)
215 {
216     char *path = NULL;
217     int HotX, HotY;
218 
219     path = find_icon_file(tmp_win->icon_image, scr->IconPath, R_OK);
220 
221     if (path == NULL)
222 	return;
223     if (XReadBitmapFile(dpy, scr->root_win, path,
224 			(unsigned int *)&tmp_win->icon_p_width,
225 			(unsigned int *)&tmp_win->icon_p_height,
226 			&tmp_win->icon_pixmap,
227 			&HotX, &HotY) != BitmapSuccess)
228     {
229 	tmp_win->icon_p_width = 0;
230 	tmp_win->icon_p_height = 0;
231     }
232 
233     XtFree(path);
234 }
235 
236 /*
237  * Looks for a color XPM icon file
238  */
239 static void
get_xpm_file(ScreenInfo * scr,MwmWindow * tmp_win)240 get_xpm_file(ScreenInfo *scr, MwmWindow *tmp_win)
241 {
242     XWindowAttributes root_attr;
243 #if XmVERSION >= 2
244     XpmAttributes xpm_attributes;
245 #else
246     _LtXpmAttributes xpm_attributes;
247 #endif
248     XImage *im, *imshape;
249     GC gc;
250     char *path = NULL;
251 
252     path = find_icon_file(tmp_win->icon_image, scr->PixmapPath, R_OK);
253     if (path == NULL)
254 	return;
255 
256     XGetWindowAttributes(dpy, scr->root_win, &root_attr);
257     xpm_attributes.colormap = root_attr.colormap;
258     xpm_attributes.closeness = 40000;	/* Allow for "similar" colors */
259 #if XmVERSION >= 2
260     xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap |
261 	XpmCloseness;
262 #else
263     xpm_attributes.valuemask = _LtXpmSize | _LtXpmReturnPixels | _LtXpmColormap |
264 	_LtXpmCloseness;
265 #endif
266 
267 #ifdef NONSTANDARD_CONVERTERS
268 #if XmVERSION >= 2
269     if (XpmReadFileToImage(dpy, path, &im, &imshape, &xpm_attributes) == XpmSuccess)
270 #else
271     if (_LtXpmReadFileToImage(dpy, path, &im, &imshape, &xpm_attributes) == _LtXpmSuccess)
272 #endif
273     {
274 
275 	tmp_win->icon_pixmap = XCreatePixmap(dpy, scr->root_win,
276 					     im->width, im->height,
277 					     scr->d_depth);
278 
279 	if (imshape)
280 	    tmp_win->icon_mask_pixmap = XCreatePixmap(dpy, scr->root_win,
281 						  imshape->width,
282 						  imshape->height,
283 						  1);
284 
285 	gc = XCreateGC(dpy, tmp_win->icon_pixmap, 0, NULL);
286 
287 	XPutImage(dpy, tmp_win->icon_pixmap, gc, im, 0, 0, 0, 0,
288 		  im->width, im->height);
289 
290 	XFreeGC(dpy, gc);
291 
292 	gc = XCreateGC(dpy, tmp_win->icon_mask_pixmap, 0, NULL);
293 
294 	if (imshape)
295 	    XPutImage(dpy, tmp_win->icon_mask_pixmap, gc, imshape, 0, 0, 0, 0,
296 		  imshape->width, imshape->height);
297 
298 	XFreeGC(dpy, gc);
299 
300 	if (tmp_win->icon_mask_pixmap)
301 	    tmp_win->flags |= SHAPED_ICON;
302 	tmp_win->icon_p_width = xpm_attributes.width;
303 	tmp_win->icon_p_height = xpm_attributes.height;
304 	tmp_win->flags |= XPM_FLAG;
305 	tmp_win->flags |= PIXMAP_OURS;
306 	tmp_win->icon_depth = scr->d_depth;
307     }
308 #endif
309 
310     XtFree(path);
311 }
312 
313 /*
314  * Looks for an application supplied icon window
315  */
316 static void
get_icon_window(ScreenInfo * scr,MwmWindow * tmp_win)317 get_icon_window(ScreenInfo *scr, MwmWindow *tmp_win)
318 {
319     /* We are guaranteed that wmhints is non-null when calling this
320      * routine */
321     if (XGetGeometry(dpy, tmp_win->wmhints->icon_window, &JunkRoot,
322 		     &JunkX, &JunkY, (unsigned int *)&tmp_win->icon_p_width,
323 		     (unsigned int *)&tmp_win->icon_p_height,
324 		     &JunkBW, &JunkDepth) == 0)
325     {
326 	fprintf(stderr, "Help! Bad Icon Window!\n");
327     }
328     tmp_win->icon_p_width += JunkBW << 1;
329     tmp_win->icon_p_height += JunkBW << 1;
330     /*
331      * Now make the new window the icon window for this window,
332      * and set it up to work as such (select for key presses
333      * and button presses/releases, set up the contexts for it,
334      * and define the cursor for it).
335      */
336     tmp_win->icon_pixmap_w = tmp_win->wmhints->icon_window;
337     if (tmp_win->wmhints->flags & IconMaskHint)
338     {
339 	tmp_win->flags |= SHAPED_ICON;
340 	tmp_win->icon_mask_pixmap = tmp_win->wmhints->icon_mask;
341     }
342     tmp_win->flags &= ~ICON_OURS;
343 }
344 
345 /*
346  * Looks for an application supplied bitmap or pixmap
347  */
348 static void
get_icon_bitmap(MwmWindow * tmp_win)349 get_icon_bitmap(MwmWindow *tmp_win)
350 {
351     /* We are guaranteed that wmhints is non-null when calling this
352      * routine */
353     XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap, &JunkRoot, &JunkX, &JunkY,
354 		 (unsigned int *)&tmp_win->icon_p_width,
355 		 (unsigned int *)&tmp_win->icon_p_height, &JunkBW, &JunkDepth);
356     tmp_win->icon_pixmap = tmp_win->wmhints->icon_pixmap;
357     tmp_win->icon_depth = JunkDepth;
358     if (tmp_win->wmhints->flags & IconMaskHint)
359     {
360 	tmp_win->flags |= SHAPED_ICON;
361 	tmp_win->icon_mask_pixmap = tmp_win->wmhints->icon_mask;
362     }
363 }
364 
365 #if 0
366 /*
367  * draw icon border windows
368  */
369 static void
370 draw_icon_border(MwmWindow *t, Window win, int x, int y, int w, int h,
371 		 GC ReliefGC, GC ShadowGC)
372 {
373     XSegment seg[4];
374     int i;
375 
376     /* top */
377     if (win == t->icon_borders[0])
378     {
379 	i = 0;
380 	seg[i].x1 = x;
381 	seg[i].y1 = y;
382 	seg[i].x2 = w + x - 1;
383 	seg[i++].y2 = y;
384 
385 	seg[i].x1 = x;
386 	seg[i].y1 = y;
387 	seg[i].x2 = x;
388 	seg[i++].y2 = h + y - 1;
389 
390 	XDrawSegments(dpy, win, ReliefGC, seg, i);
391 
392 	i = 0;
393 	seg[i].x1 = x + t->icon_border_width;
394 	seg[i].y1 = y + h - 1;
395 	seg[i].x2 = w + x - 1 - t->icon_border_width;
396 	seg[i++].y2 = y + h - 1;
397 
398 	seg[i].x1 = x + w - 1;
399 	seg[i].y1 = y;
400 	seg[i].x2 = x + w - 1;
401 	seg[i++].y2 = y + h - 1;
402 
403 	XDrawSegments(dpy, win, ShadowGC, seg, i);
404     }
405     /* right */
406     else if (win == t->icon_borders[1])
407     {
408 	i = 0;
409 	seg[i].x1 = x;
410 	seg[i].y1 = y;
411 	seg[i].x2 = w + x - 1;
412 	seg[i++].y2 = y;
413 
414 	seg[i].x1 = x;
415 	seg[i].y1 = y + t->icon_border_width - 1;
416 	seg[i].x2 = x;
417 	seg[i++].y2 = h + y - 1 - t->icon_border_width;
418 
419 	XDrawSegments(dpy, win, ReliefGC, seg, i);
420 
421 	i = 0;
422 	seg[i].x1 = x;
423 	seg[i].y1 = y + h - 1;
424 	seg[i].x2 = w + x - 1;
425 	seg[i++].y2 = y + h - 1;
426 
427 	seg[i].x1 = x + w - 1;
428 	seg[i].y1 = y;
429 	seg[i].x2 = x + w - 1;
430 	seg[i++].y2 = y + h - 1;
431 
432 	XDrawSegments(dpy, win, ShadowGC, seg, i);
433     }
434     /* bottom */
435     else if (win == t->icon_borders[2])
436     {
437 	i = 0;
438 	seg[i].x1 = x + t->icon_border_width;
439 	seg[i].y1 = y;
440 	seg[i].x2 = w + x - t->icon_border_width;
441 	seg[i++].y2 = y;
442 
443 	seg[i].x1 = x;
444 	seg[i].y1 = y;
445 	seg[i].x2 = x;
446 	seg[i++].y2 = h + y - 1;
447 
448 	XDrawSegments(dpy, win, ReliefGC, seg, i);
449 
450 	i = 0;
451 	seg[i].x1 = x;
452 	seg[i].y1 = y + h - 1;
453 	seg[i].x2 = w + x - 1;
454 	seg[i++].y2 = y + h - 1;
455 
456 	seg[i].x1 = x + w - 1;
457 	seg[i].y1 = y;
458 	seg[i].x2 = x + w - 1;
459 	seg[i++].y2 = y + h - 1;
460 
461 	XDrawSegments(dpy, win, ShadowGC, seg, i);
462     }
463     /* left */
464     else
465     {
466 	i = 0;
467 	seg[i].x1 = x;
468 	seg[i].y1 = y;
469 	seg[i].x2 = w + x - 1;
470 	seg[i++].y2 = y;
471 
472 	seg[i].x1 = x;
473 	seg[i].y1 = y;
474 	seg[i].x2 = x;
475 	seg[i++].y2 = h + y - 1;
476 
477 	XDrawSegments(dpy, win, ReliefGC, seg, i);
478 
479 	i = 0;
480 	seg[i].x1 = x;
481 	seg[i].y1 = y + h - 1;
482 	seg[i].x2 = w + x - 1;
483 	seg[i++].y2 = y + h - 1;
484 
485 	seg[i].x1 = x + w - 1;
486 	seg[i].y1 = y + t->icon_border_width - 1;
487 	seg[i].x2 = x + w - 1;
488 	seg[i++].y2 = y + h - t->icon_border_width;
489 
490 	XDrawSegments(dpy, win, ShadowGC, seg, i);
491     }
492 }
493 
494 #endif
495 
496 /*
497  * Creates an icon window as needed
498  */
499 void
ICON_CreateWindow(ScreenInfo * scr,MwmWindow * tmp_win,int def_x,int def_y)500 ICON_CreateWindow(ScreenInfo *scr, MwmWindow *tmp_win, int def_x, int def_y)
501 {
502     int final_x, final_y;
503     unsigned long valuemask;	/* mask for create windows */
504     XSetWindowAttributes attributes;	/* attributes for create windows */
505 
506     tmp_win->flags |= ICON_OURS;
507     tmp_win->flags &= ~XPM_FLAG;
508     tmp_win->flags &= ~PIXMAP_OURS;
509     tmp_win->flags &= ~SHAPED_ICON;
510     tmp_win->icon_pixmap_w = None;
511     tmp_win->icon_pixmap = None;
512     tmp_win->icon_depth = 0;
513 
514     /* First, see if it was specified in the .mwmrc */
515     tmp_win->icon_p_height = 0;
516     tmp_win->icon_p_width = 0;
517 
518     if ((scr->icon_decoration & XmICON_IMAGE) && tmp_win->use_client_icon)
519     {
520 	/* First, See if the app supplies its own icon window */
521 	if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0) &&
522 	    (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconWindowHint))
523 	    get_icon_window(scr, tmp_win);
524 
525 	/* Next, try to get icon bitmap from the application */
526 	if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0) &&
527 	    (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconPixmapHint))
528 	    get_icon_bitmap(tmp_win);
529 
530 	/* Next, check for a color pixmap */
531 	if (tmp_win->icon_image != NULL &&
532 	    (tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0))
533 	    get_xpm_file(scr, tmp_win);
534 
535 	/* Finally, check for a monochrome bitmap */
536 	if (tmp_win->icon_image != NULL &&
537 	    (tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0))
538 	    get_bitmap_file(scr, tmp_win);
539     }
540     else if (scr->icon_decoration & XmICON_IMAGE)
541     {
542 	/* First, check for a color pixmap */
543 	if (tmp_win->icon_image != NULL &&
544 	    (tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0))
545 	    get_xpm_file(scr, tmp_win);
546 
547 	/* Next, check for a monochrome bitmap */
548 	if (tmp_win->icon_image != NULL &&
549 	    (tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0))
550 	    get_bitmap_file(scr, tmp_win);
551 
552 	/* Next, See if the app supplies its own icon window */
553 	if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0) &&
554 	    (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconWindowHint))
555 	    get_icon_window(scr, tmp_win);
556 
557 	/* Finally, try to get icon bitmap from the application */
558 	if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0) &&
559 	    (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconPixmapHint))
560 	    get_icon_bitmap(tmp_win);
561     }
562 
563     /* If all that failed, use the default */
564     if ((scr->icon_decoration & XmICON_IMAGE) &&
565 	(tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0))
566     {
567 	tmp_win->icon_pixmap = XCreateBitmapFromData(dpy,
568 					scr->root_win, (char *)def_bitmap_bits,
569 					  def_bitmap_width, def_bitmap_height);
570 	tmp_win->icon_p_width = def_bitmap_width;
571 	tmp_win->icon_p_height = def_bitmap_height;
572 	tmp_win->flags |= PIXMAP_OURS;
573     }
574 
575     /* compute the icon border width, if applicable */
576     if (tmp_win->flags & SHAPED_ICON)
577 	tmp_win->icon_border_width = 0;
578     else
579 	tmp_win->icon_border_width = scr->frame_border_width;
580 
581     /* figure out the icon label size */
582     tmp_win->icon_t_width =
583 	XTextWidth(scr->components[MWM_ICON].font,
584 		   tmp_win->icon_label, strlen(tmp_win->icon_label));
585     tmp_win->icon_w_height = scr->components[MWM_ICON].f_height + 6;
586 
587     if ((tmp_win->flags & ICON_OURS) && (tmp_win->icon_p_height > 0))
588     {
589 	tmp_win->icon_p_width += 4;
590 	tmp_win->icon_p_height += 4;
591     }
592 
593     if (tmp_win->icon_p_width == 0)
594 	tmp_win->icon_p_width = tmp_win->icon_t_width + 6;
595 
596     tmp_win->icon_w_width = tmp_win->icon_p_width;
597 
598     /* clip to fit on screen */
599     final_x = def_x;
600     final_y = def_y;
601 
602     if (final_x < 0)
603 	final_x = 0;
604     if (final_y < 0)
605 	final_y = 0;
606 
607     if (final_x + tmp_win->icon_w_width >= scr->d_width)
608 	final_x = scr->d_width - tmp_win->icon_w_width - 1;
609     if (final_y + tmp_win->icon_w_height >= scr->d_height)
610 	final_y = scr->d_height - tmp_win->icon_w_height - 1;
611 
612     tmp_win->icon_x_loc = final_x;
613     tmp_win->icon_xl_loc = final_x;
614     tmp_win->icon_y_loc = final_y;
615 
616     attributes.background_pixel = tmp_win->icon_image_background;
617     valuemask = CWBorderPixel | CWCursor | CWEventMask | CWBackPixel;
618     attributes.border_pixel = tmp_win->icon_image_foreground;
619     attributes.cursor = scr->cursors[DEFAULT_CURS];
620     attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
621 			     VisibilityChangeMask |
622 			     ExposureMask | KeyPressMask | EnterWindowMask |
623 			     FocusChangeMask);
624 
625     if (scr->icon_decoration & (XmICON_LABEL | XmICON_ACTIVELABEL))
626     {
627 	tmp_win->icon_w =
628 	    XCreateWindow(dpy, scr->root_win,
629 			  final_x, final_y + tmp_win->icon_p_height,
630 			  tmp_win->icon_w_width, tmp_win->icon_w_height, 0,
631 			  CopyFromParent, CopyFromParent, CopyFromParent,
632 			  valuemask, &attributes);
633     }
634     else
635 	tmp_win->icon_w = None;
636 
637     if (scr->icon_decoration & XmICON_IMAGE)
638     {
639         /* int i; */
640 
641 #if 0
642 	attributes.event_mask = KeyPressMask | ButtonPressMask;
643 	attributes.override_redirect = True;
644 	tmp_win->icon_frame = XCreateWindow(dpy, scr->root_win,
645 					    final_x, final_y,
646 					    tmp_win->icon_p_width +
647 					    2 * tmp_win->icon_border_width,
648 					    tmp_win->icon_p_height +
649 					    2 * tmp_win->icon_border_width,
650 					    0, CopyFromParent,
651 					    CopyFromParent, CopyFromParent,
652 #if 0
653 					    CWEventMask | CWOverrideRedirect,
654 #else
655 					    valuemask,
656 #endif
657 					    &attributes);
658 #endif
659 
660 #if 0
661 	valuemask = CWBorderPixel | CWCursor | CWEventMask | CWBackPixel;
662 	attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
663 				 VisibilityChangeMask |
664 				 ExposureMask | KeyPressMask | EnterWindowMask |
665 				 FocusChangeMask);
666 #endif
667 
668 	if ((tmp_win->flags & ICON_OURS) && (tmp_win->icon_p_width > 0) &&
669 	    (tmp_win->icon_p_height > 0))
670 	{
671 	    tmp_win->icon_pixmap_w =
672 		XCreateWindow(dpy,
673 #if 0
674 			      tmp_win->icon_frame,
675 #else
676 			      scr->root_win,
677 #endif
678 			      final_x + tmp_win->icon_border_width,
679 			      final_y + tmp_win->icon_border_width,
680 			      tmp_win->icon_p_width,
681 			      tmp_win->icon_p_height,
682 			      0, CopyFromParent,
683 			      CopyFromParent, CopyFromParent,
684 			      valuemask, &attributes);
685 	}
686 	else
687 	{
688 	    attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
689 				     VisibilityChangeMask |
690 				     KeyPressMask | EnterWindowMask |
691 				     FocusChangeMask | LeaveWindowMask);
692 
693 	    valuemask = CWEventMask;
694 	    XChangeWindowAttributes(dpy, tmp_win->icon_pixmap_w,
695 				    valuemask, &attributes);
696 
697 #if 0
698 	    /* This used to say:
699 	     *   Make sure that the window is a child of the root window!
700 	     *   Olwais screws this up, maybe others do too!
701 	     * Now, make sure that *we're* the parent of the pixmap window
702 	     */
703 	    XReparentWindow(dpy, tmp_win->icon_pixmap_w, tmp_win->icon_frame,
704 			    tmp_win->icon_border_width,
705 			    tmp_win->icon_border_width);
706 #else
707 	    XReparentWindow(dpy, tmp_win->icon_pixmap_w, scr->root_win,
708 			    0, 0);
709 #endif
710 	}
711 
712 #if 0
713 	if (!(tmp_win->flags & SHAPED_ICON))
714 	{
715 	    for (i = 0; i < 4; i++)
716 	    {
717 		tmp_win->icon_borders[i] =
718 		    XCreateWindow(dpy, tmp_win->icon_frame, 0, 0,
719 				  tmp_win->icon_border_width,
720 				  tmp_win->icon_border_width,
721 				  0, CopyFromParent,
722 				  CopyFromParent, CopyFromParent,
723 				  valuemask, &attributes);
724 
725 		XSaveContext(dpy, tmp_win->icon_borders[i],
726 			     MwmContext, (XPointer)tmp_win);
727 	    }
728 	}
729 	else
730 	{
731 	    for (i = 0; i < 4; i++)
732 		tmp_win->icon_borders[i] = None;
733 	}
734 	XMapWindow(dpy, tmp_win->icon_frame);
735 	XMapSubwindows(dpy, tmp_win->icon_frame);
736 	XRaiseWindow(dpy, tmp_win->icon_pixmap_w);
737 #endif
738     }
739     else
740 	tmp_win->icon_pixmap_w = None;
741 
742 
743     if (tmp_win->flags & SHAPED_ICON)
744     {
745 	XShapeCombineMask(dpy, tmp_win->icon_pixmap_w, ShapeBounding, 2, 2,
746 			  tmp_win->icon_mask_pixmap, ShapeSet);
747     }
748 
749     if (tmp_win->icon_w != None)
750     {
751 	XSaveContext(dpy, tmp_win->icon_w, MwmContext, (XPointer)tmp_win);
752 	XDefineCursor(dpy, tmp_win->icon_w, scr->cursors[DEFAULT_CURS]);
753 	grab_icon_buttons(scr, tmp_win, tmp_win->icon_w);
754 	grab_icon_keys(scr, tmp_win, tmp_win->icon_w);
755     }
756     if (tmp_win->icon_pixmap_w != None)
757     {
758 	XSaveContext(dpy, tmp_win->icon_pixmap_w, MwmContext, (XPointer)tmp_win);
759 	XDefineCursor(dpy, tmp_win->icon_pixmap_w, scr->cursors[DEFAULT_CURS]);
760 	grab_icon_buttons(scr, tmp_win, tmp_win->icon_pixmap_w);
761 	grab_icon_keys(scr, tmp_win, tmp_win->icon_pixmap_w);
762     }
763 }
764 
765 /*
766  * Draws the icon window
767  */
768 void
ICON_DrawWindow(ScreenInfo * scr,MwmWindow * tmp)769 ICON_DrawWindow(ScreenInfo *scr, MwmWindow *tmp)
770 {
771     GC Shadow, Relief;
772     Pixel TextColor, BackColor;
773     int x;
774     char *label;
775 
776     if (tmp->icon_w != None)
777 	MISC_FlushExpose(tmp->icon_w);
778     if (tmp->icon_pixmap_w != None)
779 	MISC_FlushExpose(tmp->icon_pixmap_w);
780 
781     if (tmp == scr->mwm_highlight && (scr->icon_decoration & XmICON_ACTIVELABEL)
782  && tmp->icon_active_label != NoName && tmp->icon_active_label != NULL
783       && tmp->icon_active_label[0] != '\0')
784 	label = tmp->icon_active_label;
785     else
786 	label = tmp->icon_label;
787 
788     if (label == NULL)
789 	label = "";
790 
791     tmp->icon_t_width = XTextWidth(scr->components[MWM_ICON].font,
792 				   label, strlen(label));
793 
794     if (scr->mwm_highlight == tmp)
795     {
796 	Relief = scr->components[MWM_ICON].active_top_GC;
797 	Shadow = scr->components[MWM_ICON].active_bot_GC;
798 	/* resize the icon name window */
799 	if (tmp->icon_w != None)
800 	{
801 	    tmp->icon_w_width = tmp->icon_t_width + 6;
802 	    if (tmp->icon_w_width < tmp->icon_p_width)
803 		tmp->icon_w_width = tmp->icon_p_width;
804 	    tmp->icon_xl_loc = tmp->icon_x_loc -
805 		(tmp->icon_w_width - tmp->icon_p_width) / 2;
806 	}
807 	TextColor = scr->components[MWM_ICON].active_foreground;
808 	BackColor = scr->components[MWM_ICON].active_background;
809     }
810     else
811     {
812 	Relief = scr->components[MWM_ICON].top_GC;
813 	Shadow = scr->components[MWM_ICON].bot_GC;
814 
815 	/* resize the icon name window */
816 	if (tmp->icon_w != None)
817 	{
818 	    tmp->icon_w_width = tmp->icon_p_width;
819 	    tmp->icon_xl_loc = tmp->icon_x_loc;
820 	}
821 	TextColor = scr->components[MWM_ICON].foreground;
822 	BackColor = scr->components[MWM_ICON].background;
823 
824     }
825 
826 #if 1
827     if ((tmp->flags & ICON_OURS) && (tmp->icon_pixmap_w != None))
828 	XSetWindowBackground(dpy, tmp->icon_pixmap_w,
829 			     BackColor);
830 #else
831     if (!(tmp->flags & SHAPED_ICON))
832     {
833 	int i;
834 	XSetWindowAttributes attributes;
835 	unsigned long valuemask;
836 
837 	for (i = 0; i < 4; i++)
838 	{
839 	    XWindowChanges xwc;
840 	    unsigned int xwcm = CWWidth | CWHeight | CWX | CWY;
841 
842 	    if (i == 0)
843 	    {
844 		xwc.x = 0;
845 		xwc.y = 0;
846 		xwc.height = tmp->icon_border_width;
847 		xwc.width = tmp->icon_p_width + 2 * tmp->icon_border_width;
848 	    }
849 	    else if (i == 1)
850 	    {
851 		xwc.x = tmp->icon_border_width + tmp->icon_p_width;
852 		xwc.y = 0;
853 		xwc.width = tmp->icon_border_width;
854 		xwc.height = tmp->icon_p_height + 2 * tmp->icon_border_width;
855 	    }
856 	    else if (i == 2)
857 	    {
858 		xwc.x = 0;
859 		xwc.y = tmp->icon_border_width + tmp->icon_p_height;
860 		xwc.height = tmp->icon_border_width;
861 		xwc.width = tmp->icon_p_width + 2 * tmp->icon_border_width;
862 	    }
863 	    else
864 	    {
865 		xwc.x = 0;
866 		xwc.y = 0;
867 		xwc.width = tmp->icon_border_width;
868 		xwc.height = tmp->icon_p_height + 2 * tmp->icon_border_width;
869 	    }
870 	    XConfigureWindow(dpy, tmp->icon_borders[i], xwcm, &xwc);
871 	}
872 
873 	valuemask = CWBackPixel;
874 	if (scr->mwm_highlight == tmp)
875 	    attributes.background_pixel = scr->components[MWM_ICON].active_background;
876 	else
877 	    attributes.background_pixel = scr->components[MWM_ICON].background;
878 
879 	for (i = 0; i < 4; i++)
880 	{
881 	    XChangeWindowAttributes(dpy, tmp->icon_borders[i],
882 				    valuemask, &attributes);
883 	    XClearWindow(dpy, tmp->icon_borders[i]);
884 	    draw_icon_border(tmp, tmp->icon_borders[i], 0, 0,
885 			     ((i % 2)
886 			      ? tmp->icon_border_width
887 			      : tmp->icon_p_width + 2 * tmp->icon_border_width),
888 			     ((i % 2)
889 			      ? tmp->icon_p_height + 2 * tmp->icon_border_width
890 			      : tmp->icon_border_width),
891 			     Relief, Shadow);
892 	}
893 
894 	for (i = 0; i < 4; i++)
895 	    if (tmp->icon_borders[i] != None)
896 		MISC_FlushExpose(tmp->icon_borders[i]);
897     }
898 
899 #endif
900 
901     if (tmp->icon_w != None)
902 	XSetWindowBackground(dpy, tmp->icon_w, BackColor);
903 
904     if (tmp->icon_pixmap_w != None)
905     {
906 #if 0
907 	XMoveWindow(dpy, tmp->icon_frame, tmp->icon_x_loc, tmp->icon_y_loc);
908 #else
909 	XMoveWindow(dpy, tmp->icon_pixmap_w, tmp->icon_x_loc,
910 		    tmp->icon_y_loc);
911 #endif
912     }
913 
914     if (tmp->icon_w != None)
915     {
916 	XMoveResizeWindow(dpy, tmp->icon_w, tmp->icon_xl_loc,
917 			  tmp->icon_y_loc + tmp->icon_p_height,
918 			  tmp->icon_w_width,
919 			  scr->components[MWM_ICON].f_height + 6);
920 
921 	XClearWindow(dpy, tmp->icon_w);
922     }
923 
924     if ((tmp->icon_pixmap != None) && (!(tmp->flags & SHAPED_ICON)))
925 	DEC_DrawShadows(tmp, tmp->icon_pixmap_w, 0, 0,
926 			tmp->icon_p_width, tmp->icon_p_height,
927 			Relief, Shadow);
928 
929     /* need to locate the icon pixmap */
930     if (tmp->icon_pixmap != None)
931     {
932 	if (tmp->icon_depth == scr->d_depth)
933 	{
934 	    XCopyArea(dpy, tmp->icon_pixmap, tmp->icon_pixmap_w,
935 		      (scr->mwm_highlight == tmp)
936 		      ? scr->components[MWM_ICON].active_GC
937 		      : scr->components[MWM_ICON].normal_GC,
938 		      0, 0,
939 		      tmp->icon_p_width - 4, tmp->icon_p_height - 4, 2, 2);
940 	}
941 	else
942 	    XCopyPlane(dpy, tmp->icon_pixmap, tmp->icon_pixmap_w,
943 		       (scr->mwm_highlight == tmp)
944 		       ? scr->components[MWM_ICON].active_GC
945 		       : scr->components[MWM_ICON].normal_GC,
946 		       0, 0,
947 		       tmp->icon_p_width - 4, tmp->icon_p_height - 4, 2, 2, 1);
948     }
949 
950     if (tmp->icon_w != None)
951     {
952 	char *label;
953 
954 	if (tmp == scr->mwm_highlight &&
955 	    (scr->icon_decoration & XmICON_ACTIVELABEL) &&
956 	    tmp->icon_active_label != NoName &&
957 	    tmp->icon_active_label != NULL &&
958 	    tmp->icon_active_label[0] != '\0')
959 	{
960 	    label = tmp->icon_active_label;
961 	}
962 	else
963 	{
964 	    label = tmp->icon_label;
965 	}
966 
967 	if (label == NULL)
968 	    label = "";
969 
970 	/* text position */
971 	x = (tmp->icon_w_width - tmp->icon_t_width) / 2;
972 	if (x < 3)
973 	    x = 3;
974 
975 	XDrawString(dpy, tmp->icon_w,
976 		    (scr->mwm_highlight == tmp)
977 		    ? scr->components[MWM_ICON].active_GC
978 		    : scr->components[MWM_ICON].normal_GC,
979 		    x, tmp->icon_w_height -
980 		    scr->components[MWM_ICON].f_height +
981 		    scr->components[MWM_ICON].f_y - 3,
982 		    label, strlen(label));
983 	DEC_DrawShadows(tmp, tmp->icon_w,
984 			0, 0,
985 			tmp->icon_w_width,
986 			scr->components[MWM_ICON].f_height + 6,
987 			Relief, Shadow);
988     }
989 }
990 
991 /*
992  * procedure to re-position the icon window and name
993  */
994 void
ICON_UpdateWindow(ScreenInfo * scr,MwmWindow * tmp,Boolean force)995 ICON_UpdateWindow(ScreenInfo *scr, MwmWindow *tmp, Boolean force)
996 {
997     char *label;
998 
999     if (scr->components[MWM_PAGER].f_height > 0)
1000     {
1001 	XClearWindow(dpy, tmp->pager_view);
1002 	PAGER_Clear(scr);
1003     }
1004 
1005     if (tmp->icon_w == None && tmp->icon_pixmap_w == None)
1006 	return;
1007 
1008     if ((force || (tmp == scr->mwm_highlight &&
1009 	 (scr->icon_decoration & XmICON_ACTIVELABEL))) &&
1010 	tmp->icon_active_label != NoName &&
1011 	tmp->icon_active_label != NULL &&
1012 	tmp->icon_active_label[0] != '\0')
1013     {
1014 	label = tmp->icon_active_label;
1015     }
1016     else
1017     {
1018 	label = tmp->icon_label;
1019     }
1020 
1021     if (label == NULL)
1022 	label = "";
1023 
1024     tmp->icon_t_width = XTextWidth(scr->components[MWM_ICON].font,
1025 				   label, strlen(label));
1026 
1027     /* clear the icon window, and trigger a re-draw via an expose event */
1028     if (tmp->flags & ICONIFIED)
1029 	XClearArea(dpy, tmp->icon_w, 0, 0, 0, 0, True);
1030 }
1031 
1032 /*
1033  * Find a home for an icon
1034  */
1035 void
ICON_AutoPlace(ScreenInfo * scr,MwmWindow * t)1036 ICON_AutoPlace(ScreenInfo *scr, MwmWindow *t)
1037 {
1038     int test_x = 0, test_y = 0, tw, th, tx, ty, i, temp_h, temp_w;
1039     int base_x, base_y;
1040     int width, height;
1041     MwmWindow *test_window;
1042     Bool loc_ok;
1043     int real_x = 10, real_y = 10;
1044 
1045     /* New! Put icon in same page as the center of the window */
1046     if ((t->flags & STICKY))
1047     {
1048 	base_x = 0;
1049 	base_y = 0;
1050     }
1051     else
1052     {
1053 	base_x = ((t->frame_x + scr->virt_x + (t->frame_width >> 1)) /
1054 		  scr->d_width) * scr->d_width - scr->virt_x;
1055 	base_y = ((t->frame_y + scr->virt_y + (t->frame_height >> 1)) /
1056 		  scr->d_height) * scr->d_height - scr->virt_y;
1057     }
1058     if (t->flags & ICON_MOVED)
1059     {
1060 	/* just make sure the icon is on this screen */
1061 	t->icon_x_loc = t->icon_x_loc % scr->d_width + base_x;
1062 	t->icon_y_loc = t->icon_y_loc % scr->d_height + base_y;
1063 	if (t->icon_x_loc < 0)
1064 	    t->icon_x_loc += scr->d_width;
1065 	if (t->icon_y_loc < 0)
1066 	    t->icon_y_loc += scr->d_height;
1067     }
1068     else if (t->wmhints && t->wmhints->flags & IconPositionHint)
1069     {
1070 	t->icon_x_loc = t->wmhints->icon_x;
1071 	t->icon_y_loc = t->wmhints->icon_y;
1072     }
1073     else
1074     {
1075 	width = t->icon_p_width;
1076 	height = t->icon_w_height + t->icon_p_height;
1077 	loc_ok = False;
1078 
1079 	/* check all boxes in order */
1080 	i = 0;
1081 	while ((i < scr->num_icon_boxes) && (!loc_ok))
1082 	{
1083 	    /* In each IconBox, start at the upper left, travel right, then
1084 	     * down */
1085 	    test_y = scr->icon_boxes[i][1] + base_y;
1086 
1087 	    temp_h = height;
1088 	    temp_w = width;
1089 
1090 	    /* OK second try at this.
1091 	     * If the window is taller than the icon box, ignore the icon height
1092 	     * when figuring where to put it. Same goes for the width */
1093 	    /* This should permit reasonably graceful handling of big icons. */
1094 	    if (width >= (scr->icon_boxes[i][2] - scr->icon_boxes[i][0]))
1095 		temp_w = 0;
1096 	    if (height >= (scr->icon_boxes[i][3] - scr->icon_boxes[i][1]))
1097 		temp_h = 0;
1098 
1099 	    while (((test_y + temp_h) < (scr->icon_boxes[i][3] + base_y)) &&
1100 		   (!loc_ok))
1101 	    {
1102 
1103 		test_x = scr->icon_boxes[i][0] + base_x;
1104 		while (((test_x + temp_w) < (scr->icon_boxes[i][2] + base_x)) &&
1105 		       (!loc_ok))
1106 		{
1107 		    real_x = test_x;
1108 		    real_y = test_y;
1109 
1110 		    if (test_x + width > (scr->d_width - 2 + base_x))
1111 			real_x = scr->d_width - width - 2 + base_x;
1112 		    if (test_y + height > (scr->d_height - 2 + base_y))
1113 			real_y = scr->d_height - height - 2 + base_y;
1114 		    if (test_x < base_x)
1115 			real_x = base_x;
1116 		    if (test_y < base_y)
1117 			real_y = base_y;
1118 		    loc_ok = True;
1119 		    test_window = scr->mwm_root.next;
1120 		    while ((test_window != (MwmWindow *)0) && (loc_ok == True))
1121 		    {
1122 			if (test_window->Desk == t->Desk)
1123 			{
1124 			    if ((test_window->flags & ICONIFIED) &&
1125 				(test_window->icon_w ||
1126 				 test_window->icon_pixmap_w) &&
1127 				(test_window != t))
1128 			    {
1129 				tw = test_window->icon_p_width;
1130 				th = test_window->icon_p_height +
1131 				    test_window->icon_w_height;
1132 				tx = test_window->icon_x_loc;
1133 				ty = test_window->icon_y_loc;
1134 
1135 				if ((tx < (real_x + width + 3)) &&
1136 				    ((tx + tw + 3) > real_x) &&
1137 				    (ty < (real_y + height + 3)) &&
1138 				    ((ty + th + 3) > real_y))
1139 				{
1140 				    loc_ok = False;
1141 				}
1142 			    }
1143 			    if (scr->flags & StubbornIconPlacement)
1144 			    {
1145 				if (!(test_window->flags & ICONIFIED) &&
1146 				    (test_window != t))
1147 				{
1148 				    tw = test_window->frame_width;
1149 				    th = test_window->frame_height;
1150 				    tx = test_window->frame_x;
1151 				    ty = test_window->frame_y;
1152 
1153 				    if ((tx < (real_x + width + 3)) &&
1154 					((tx + tw + 3) > real_x) &&
1155 					(ty < (real_y + height + 3)) &&
1156 					((ty + th + 3) > real_y))
1157 				    {
1158 					loc_ok = False;
1159 				    }
1160 				}
1161 			    }
1162 			}
1163 			test_window = test_window->next;
1164 		    }
1165 		    test_x += 3;
1166 		}
1167 		test_y += 3;
1168 	    }
1169 	    i++;
1170 	}
1171 	if (loc_ok == False)
1172 	    return;
1173 	t->icon_x_loc = real_x;
1174 	t->icon_y_loc = real_y;
1175     }
1176 
1177     if (t->icon_pixmap_w)
1178 	XMoveWindow(dpy, t->icon_pixmap_w, t->icon_x_loc, t->icon_y_loc);
1179 
1180     t->icon_w_width = t->icon_p_width;
1181     t->icon_xl_loc = t->icon_x_loc;
1182 
1183     if (t->icon_w != None)
1184 	XMoveResizeWindow(dpy, t->icon_w, t->icon_xl_loc,
1185 			  t->icon_y_loc + t->icon_p_height,
1186 			  t->icon_w_width,
1187 			  scr->components[MWM_ICON].f_height + 6);
1188 }
1189 
1190 /*
1191  * Iconifies the selected window
1192  */
1193 void
ICON_Iconify(ScreenInfo * scr,MwmWindow * tmp_win,int def_x,int def_y)1194 ICON_Iconify(ScreenInfo *scr, MwmWindow *tmp_win, int def_x, int def_y)
1195 {
1196     MwmWindow *t;
1197     XWindowAttributes winattrs;
1198     unsigned long eventMask;
1199 
1200     XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
1201     eventMask = winattrs.your_event_mask;
1202 
1203     if ((tmp_win) && (tmp_win == scr->mwm_highlight) &&
1204 	(Mwm.keyboard_focus_policy == XmEXPLICIT) && (tmp_win->next))
1205     {
1206 	WIN_SetFocusInTree(tmp_win->next);
1207 	WIN_SetFocus(scr, tmp_win->next->w, tmp_win->next);
1208 	MISC_SetFocusSequence(scr);
1209     }
1210 
1211     /* iconify transients first */
1212     for (t = scr->mwm_root.next; t != NULL; t = t->next)
1213     {
1214 	if ((t == tmp_win) ||
1215 	    ((t->flags & TRANSIENT) && (t->transientfor == tmp_win->w)))
1216 	{
1217 	    /*
1218 	     * Prevent the receipt of an UnmapNotify, since that would
1219 	     * cause a transition to the Withdrawn state.
1220 	     */
1221 	    t->flags &= ~MAPPED;
1222 	    XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
1223 	    XUnmapWindow(dpy, t->w);
1224 	    XSelectInput(dpy, t->w, eventMask);
1225 	    XUnmapWindow(dpy, t->frame);
1226 	    t->DeIconifyDesk = t->Desk;
1227 	    if (t->icon_w)
1228 		XUnmapWindow(dpy, t->icon_w);
1229 	    if (t->icon_pixmap_w)
1230 		XUnmapWindow(dpy, t->icon_pixmap_w);
1231 
1232 	    PROP_SetState(t, IconicState);
1233 	    DEC_DrawDecorations(scr, t, False, False, False, None);
1234 	    if (t != tmp_win)
1235 		t->flags |= ICONIFIED | ICON_UNMAPPED;
1236 	    if (t != tmp_win)
1237 		PAGER_UpdateView(scr, t);
1238 	}
1239     }
1240     if (tmp_win->icon_w == None)
1241     {
1242 	if (tmp_win->flags & ICON_MOVED)
1243 	    ICON_CreateWindow(scr, tmp_win,
1244 			      tmp_win->icon_x_loc, tmp_win->icon_y_loc);
1245 	else
1246 	    ICON_CreateWindow(scr, tmp_win, def_x, def_y);
1247     }
1248     if (Mwm.icon_auto_place)
1249 	ICON_AutoPlace(scr, tmp_win);
1250     tmp_win->flags |= ICONIFIED;
1251     tmp_win->flags &= ~ICON_UNMAPPED;
1252     WIN_Lower(scr, tmp_win);
1253     if (tmp_win->Desk == scr->current_desk)
1254     {
1255 	if (tmp_win->icon_w != None)
1256 	    XMapWindow(dpy, tmp_win->icon_w);
1257 
1258 	if (tmp_win->icon_pixmap_w != None)
1259 	    XMapWindow(dpy, tmp_win->icon_pixmap_w);
1260 	PAGER_UpdateView(scr, tmp_win);
1261     }
1262     if ((Mwm.keyboard_focus_policy == XmEXPLICIT) ||
1263 	(Mwm.keyboard_focus_policy == XmPOINTER))
1264     {
1265 	if ((tmp_win) && (tmp_win == scr->mwm_focus))
1266 	{
1267 	    if (scr->mwm_last_focus == scr->mwm_focus)
1268 		scr->mwm_last_focus = NULL;
1269 	    if ((Mwm.keyboard_focus_policy == XmEXPLICIT) && (tmp_win->next))
1270 	    {
1271 		WIN_SetFocusInTree(tmp_win->next);
1272 		WIN_SetFocus(scr, tmp_win->next->w, tmp_win->next);
1273 	    }
1274 	    else
1275 		WIN_SetFocus(scr, scr->no_focus_win, NULL);
1276 
1277 	    MISC_SetFocusSequence(scr);
1278 	}
1279     }
1280     if (Mwm.lower_on_iconify)
1281 	WIN_Lower(scr, tmp_win);
1282 }
1283 
1284 /*
1285  * DeIconify a window
1286  */
1287 void
ICON_DeIconify(ScreenInfo * scr,MwmWindow * tmp_win)1288 ICON_DeIconify(ScreenInfo *scr, MwmWindow *tmp_win)
1289 {
1290     MwmWindow *t, *tmp;
1291     int new_x, new_y, w2, h2;
1292 
1293     /* now de-iconify transients */
1294     for (t = scr->mwm_root.next; t != NULL; t = t->next)
1295     {
1296 	if ((t == tmp_win) ||
1297 	    ((t->flags & TRANSIENT) && (t->transientfor == tmp_win->w)))
1298 	{
1299 	    t->flags |= MAPPED;
1300 	    if (scr->mwm_highlight == t)
1301 		DEC_DrawDecorations(scr, t, False, True, True, None);
1302 	    /* make sure that the window is on this screen */
1303 	    if ((t->frame_x < 0) || (t->frame_y < 0) ||
1304 		(t->frame_x >= scr->d_width) ||
1305 		(t->frame_y >= scr->d_height))
1306 	    {
1307 		/* try to put at least half the window
1308 		 * in the current screen, if the current desktop
1309 		 * is the windows desktop */
1310 		if (scr->flags & StubbornIcons)
1311 		    t->Desk = t->DeIconifyDesk;
1312 		else
1313 		    t->Desk = scr->current_desk;
1314 
1315 		if (t->Desk == scr->current_desk)
1316 		{
1317 		    new_x = t->frame_x;
1318 		    new_y = t->frame_y;
1319 		    w2 = (t->frame_width >> 1);
1320 		    h2 = (t->frame_height >> 1);
1321 		    if (!(scr->flags & StubbornIcons))
1322 		    {
1323 			if ((new_x < -w2) || (new_x > (scr->d_width - w2)))
1324 			{
1325 			    new_x = new_x % scr->d_width;
1326 			    if (new_x < -w2)
1327 				new_x += scr->d_width;
1328 			}
1329 			if ((new_y < -h2) || (new_y > (scr->d_height - h2)))
1330 			{
1331 			    new_y = new_y % scr->d_height;
1332 			    if (new_y < -h2)
1333 				new_y += scr->d_height;
1334 			}
1335 		    }
1336 		    DEC_ConfigureDecorations(scr, t, new_x, new_y,
1337 				       t->frame_width, t->frame_height, False);
1338 		}
1339 	    }
1340 	    XMapWindow(dpy, t->w);
1341 	    if (t->Desk == scr->current_desk)
1342 	    {
1343 		XMapWindow(dpy, t->frame);
1344 		t->flags |= MAP_PENDING;
1345 	    }
1346 	    XMapWindow(dpy, t->parent);
1347 	    PROP_SetState(t, NormalState);
1348 	    t->flags &= ~ICONIFIED;
1349 	    t->flags &= ~ICON_UNMAPPED;
1350 	    /* Need to make sure the border is colored correctly,
1351 	     * in case it was stuck or unstuck while iconified. */
1352 	    tmp = scr->mwm_highlight;
1353 	    scr->mwm_highlight = t;
1354 	    DEC_DrawDecorations(scr, t, False, True, True, None);
1355 	    scr->mwm_highlight = tmp;
1356 	    XRaiseWindow(dpy, t->w);
1357 	    if (t->icon_w)
1358 		XUnmapWindow(dpy, t->icon_w);
1359 	    if (t->icon_pixmap_w)
1360 		XUnmapWindow(dpy, t->icon_pixmap_w);
1361 	}
1362     }
1363     WIN_Raise(scr, tmp_win);
1364 
1365     if ((scr->flags & StubbornIcons) ||
1366 	(Mwm.keyboard_focus_policy == XmEXPLICIT && Mwm.deiconify_key_focus))
1367 	WIN_ChangeFocus(scr, tmp_win, 1);
1368 
1369     PAGER_UpdateView(scr, tmp_win);
1370 }
1371