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