add tests for menu and menustyle commands.
[fvwm.git] / fvwm / icons.c
bloba9827efe66823f28cda0f377967168124bf8371a
1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; either version 2 of the License, or
4 * (at your option) any later version.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 /****************************************************************************
17 * This module is mostly all new
18 * by Rob Nation
19 * A little of it is borrowed from ctwm.
20 * Copyright 1993 Robert Nation. No restrictions are placed on this code,
21 * as long as the copyright notice is preserved
22 ****************************************************************************/
23 /***********************************************************************
25 * fvwm icon code
27 ***********************************************************************/
29 #include "config.h"
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
35 #include <X11/Intrinsic.h>
36 #ifdef XPM
37 #include <X11/xpm.h>
38 #endif /* XPM */
40 #include "libs/fvwmlib.h"
41 #include <stdio.h>
42 #include "fvwm.h"
43 #include "externs.h"
44 #include "cursor.h"
45 #include "functions.h"
46 #include "bindings.h"
47 #include "events.h"
48 #include "misc.h"
49 #include "screen.h"
50 #include "defaults.h"
51 #include "icons.h"
52 #include "borders.h"
53 #include "focus.h"
54 #include "colormaps.h"
55 #include "stack.h"
56 #include "virtual.h"
57 #include "decorations.h"
58 #include "module_interface.h"
59 #include "libs/Colorset.h"
60 #include "gnome.h"
61 #include "geometry.h"
63 #ifdef SHAPE
64 #include <X11/extensions/shape.h>
65 #endif /* SHAPE */
67 static int do_all_iconboxes(FvwmWindow *t, icon_boxes **icon_boxes_ptr);
68 static void GetBitmapFile(FvwmWindow *tmp_win);
69 static void GetXPMFile(FvwmWindow *tmp_win);
73 /****************************************************************************
75 * Creates an icon window as needed
77 ****************************************************************************/
78 void CreateIconWindow(FvwmWindow *tmp_win, int def_x, int def_y)
80 /* mask for create windows */
81 unsigned long valuemask;
82 /* attributes for create windows */
83 XSetWindowAttributes attributes;
84 XWindowChanges xwc;
86 SET_ICON_OURS(tmp_win, 1);
87 SET_PIXMAP_OURS(tmp_win, 0);
88 SET_ICON_SHAPED(tmp_win, 0);
89 tmp_win->icon_pixmap_w = None;
90 tmp_win->iconPixmap = None;
91 tmp_win->iconDepth = 0;
93 if (IS_ICON_SUPPRESSED(tmp_win))
94 return;
96 /* First, see if it was specified in the .fvwmrc */
97 tmp_win->icon_p_height = 0;
98 tmp_win->icon_p_width = 0;
100 /* First, check for a monochrome bitmap */
101 if (tmp_win->icon_bitmap_file != NULL)
102 GetBitmapFile(tmp_win);
104 #ifdef XPM
105 /* Next, check for a color pixmap */
106 if ((tmp_win->icon_bitmap_file != NULL) && (tmp_win->icon_p_height == 0)
107 && (tmp_win->icon_p_width == 0))
108 GetXPMFile(tmp_win);
109 #endif /* XPM */
111 /* Next, See if the app supplies its own icon window */
112 if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0)
113 && (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconWindowHint))
114 GetIconWindow(tmp_win);
116 /* Finally, try to get icon bitmap from the application */
117 if ((tmp_win->icon_p_height == 0) && (tmp_win->icon_p_width == 0)
118 && (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconPixmapHint))
119 GetIconBitmap(tmp_win);
121 /* figure out the icon window size */
122 if (!HAS_NO_ICON_TITLE(tmp_win))
124 tmp_win->icon_t_width =
125 XTextWidth(tmp_win->icon_font.font, tmp_win->icon_name,
126 strlen(tmp_win->icon_name));
127 tmp_win->icon_g.height = ICON_HEIGHT(tmp_win);
129 else
131 tmp_win->icon_t_width = 0;
132 tmp_win->icon_g.height = 0;
135 /* make space for relief to be drawn outside the icon */
136 /* this does not happen if fvwm is using a non-default visual (with
137 private colormap) and the client has supplied a pixmap (not a bitmap) */
138 if ((IS_ICON_OURS(tmp_win)) && (tmp_win->icon_p_height > 0)
139 && (Pdefault || (tmp_win->iconDepth == 1) || IS_PIXMAP_OURS(tmp_win)))
141 tmp_win->icon_p_width += 4;
142 tmp_win->icon_p_height += 4;
145 if (tmp_win->icon_p_width == 0)
146 tmp_win->icon_p_width = tmp_win->icon_t_width + 6;
147 tmp_win->icon_g.width = tmp_win->icon_p_width;
149 tmp_win->icon_g.x = tmp_win->icon_xl_loc = def_x;
150 tmp_win->icon_g.y = def_y;
152 /* create the icon title window */
153 valuemask = CWColormap | CWBorderPixel
154 | CWBackPixel | CWCursor | CWEventMask;
155 attributes.colormap = Pcmap;
156 attributes.background_pixel = Scr.StdBack;
157 attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT];
158 attributes.border_pixel = 0;
159 attributes.event_mask = (ButtonPressMask | ButtonReleaseMask
160 | VisibilityChangeMask | ExposureMask | KeyPressMask
161 | EnterWindowMask | LeaveWindowMask
162 | FocusChangeMask );
163 if (!HAS_NO_ICON_TITLE(tmp_win))
165 tmp_win->icon_w =
166 XCreateWindow(
167 dpy, Scr.Root, def_x, def_y + tmp_win->icon_p_height,
168 tmp_win->icon_g.width, tmp_win->icon_g.height, 0, Pdepth,
169 InputOutput, Pvisual, valuemask, &attributes);
171 if (Scr.DefaultColorset >= 0)
172 SetWindowBackground(dpy, tmp_win->icon_w, tmp_win->icon_g.width,
173 tmp_win->icon_g.height, &Colorset[Scr.DefaultColorset],
174 Pdepth, Scr.StdGC, False);
176 /* create a window to hold the picture */
177 if((IS_ICON_OURS(tmp_win)) && (tmp_win->icon_p_width > 0)
178 && (tmp_win->icon_p_height > 0))
180 /* use fvwm's visuals in these cases */
181 if (Pdefault || (tmp_win->iconDepth == 1) || IS_PIXMAP_OURS(tmp_win))
183 tmp_win->icon_pixmap_w =
184 XCreateWindow(
185 dpy, Scr.Root, def_x, def_y, tmp_win->icon_p_width,
186 tmp_win->icon_p_height, 0, Pdepth, InputOutput, Pvisual, valuemask,
187 &attributes);
188 if (Scr.DefaultColorset >= 0)
189 SetWindowBackground(dpy, tmp_win->icon_w, tmp_win->icon_p_width,
190 tmp_win->icon_p_height,
191 &Colorset[Scr.DefaultColorset], Pdepth, Scr.StdGC,
192 False);
194 else
196 /* client supplied icon pixmap and fvwm is using another visual */
197 /* use it as the background pixmap, don't try to put relief on it
198 * because fvwm will not have the correct colors
199 * the Exceed server has problems maintaining the icon window, it usually
200 * fails to refresh the icon leaving it black so ask for expose events */
201 attributes.background_pixmap = tmp_win->iconPixmap;
202 attributes.colormap = DefaultColormap(dpy, Scr.screen);
203 valuemask &= ~CWBackPixel;
204 valuemask |= CWBackPixmap;
205 tmp_win->icon_pixmap_w =
206 XCreateWindow(
207 dpy, Scr.Root, def_x, def_y, tmp_win->icon_p_width,
208 tmp_win->icon_p_height, 0, DefaultDepth(dpy, Scr.screen), InputOutput,
209 DefaultVisual(dpy, Scr.screen), valuemask, &attributes);
212 else
214 /* client supplied icon window: select events on it */
215 attributes.event_mask = ButtonPressMask | ButtonReleaseMask | KeyPressMask
216 | VisibilityChangeMask | FocusChangeMask
217 | EnterWindowMask | LeaveWindowMask;
218 valuemask = CWEventMask;
219 XChangeWindowAttributes(dpy, tmp_win->icon_pixmap_w, valuemask,&attributes);
223 #ifdef SHAPE
224 if (ShapesSupported && IS_ICON_SHAPED(tmp_win))
226 /* when fvwm is using the non-default visual client supplied icon pixmaps
227 * are drawn in a window with no relief */
228 int off = (Pdefault || (tmp_win->iconDepth == 1) || IS_PIXMAP_OURS(tmp_win))
229 ? 2 : 0;
230 XShapeCombineMask(dpy, tmp_win->icon_pixmap_w, ShapeBounding, off, off,
231 tmp_win->icon_maskPixmap, ShapeSet);
233 #endif
235 if(tmp_win->icon_w != None)
237 XSaveContext(dpy, tmp_win->icon_w, FvwmContext, (caddr_t)tmp_win);
238 XDefineCursor(dpy, tmp_win->icon_w, Scr.FvwmCursors[CRS_DEFAULT]);
239 GrabAllWindowKeysAndButtons(dpy, tmp_win->icon_w, Scr.AllBindings,
240 C_ICON, GetUnusedModifiers(),
241 Scr.FvwmCursors[CRS_DEFAULT], True);
243 xwc.sibling = tmp_win->frame;
244 xwc.stack_mode = Below;
245 XConfigureWindow(dpy, tmp_win->icon_w, CWSibling|CWStackMode, &xwc);
247 if(tmp_win->icon_pixmap_w != None)
249 XSaveContext(dpy, tmp_win->icon_pixmap_w, FvwmContext, (caddr_t)tmp_win);
250 XDefineCursor(dpy, tmp_win->icon_pixmap_w, Scr.FvwmCursors[CRS_DEFAULT]);
251 GrabAllWindowKeysAndButtons(dpy, tmp_win->icon_pixmap_w, Scr.AllBindings,
252 C_ICON, GetUnusedModifiers(),
253 Scr.FvwmCursors[CRS_DEFAULT], True);
255 xwc.sibling = tmp_win->frame;
256 xwc.stack_mode = Below;
257 XConfigureWindow(dpy,tmp_win->icon_pixmap_w,CWSibling|CWStackMode,&xwc);
259 return;
262 /****************************************************************************
264 * Draws the icon window
266 ****************************************************************************/
267 void DrawIconWindow(FvwmWindow *tmp_win)
269 GC Shadow;
270 GC Relief;
271 Pixel TextColor;
272 Pixel BackColor;
273 int x;
274 color_quad *draw_colors;
276 if(IS_ICON_SUPPRESSED(tmp_win))
277 return;
279 if(tmp_win->icon_w != None)
280 flush_expose (tmp_win->icon_w);
281 if(tmp_win->icon_pixmap_w != None)
282 flush_expose (tmp_win->icon_pixmap_w);
284 if(Scr.Hilite == tmp_win)
285 draw_colors = &(tmp_win->hicolors);
286 else
287 draw_colors = &(tmp_win->colors);
288 if (Pdepth < 2 && Scr.Hilite != tmp_win)
290 Relief = Scr.StdReliefGC;
291 Shadow = Scr.StdShadowGC;
293 else
295 if (Pdepth < 2 && Scr.Hilite == tmp_win)
296 Relief = Scr.ScratchGC2;
297 else
299 Globalgcv.foreground = draw_colors->hilight;
300 Globalgcm = GCForeground;
301 XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv);
302 Relief = Scr.ScratchGC1;
304 Globalgcv.foreground = draw_colors->shadow;
305 XChangeGC(dpy,Scr.ScratchGC2, Globalgcm, &Globalgcv);
306 Shadow = Scr.ScratchGC2;
308 TextColor = draw_colors->fore;
309 BackColor = draw_colors->back;
311 if(tmp_win->icon_w != None)
313 if (IS_ICON_ENTERED(tmp_win))
315 /* resize the icon name window */
316 tmp_win->icon_g.width = tmp_win->icon_t_width + 8;
317 if (IS_STICKY(tmp_win) || IS_ICON_STICKY(tmp_win))
318 tmp_win->icon_g.width += 10;
319 if(tmp_win->icon_g.width < tmp_win->icon_p_width)
320 tmp_win->icon_g.width = tmp_win->icon_p_width;
321 tmp_win->icon_xl_loc = tmp_win->icon_g.x -
322 (tmp_win->icon_g.width - tmp_win->icon_p_width)/2;
323 /* start keep label on screen. dje 8/7/97 */
324 if (tmp_win->icon_xl_loc < 0) { /* if new loc neg (off left edge) */
325 tmp_win->icon_xl_loc = 0; /* move to edge */
326 } else { /* if not on left edge */
327 /* if (new loc + width) > screen width (off edge on right) */
328 if ((tmp_win->icon_xl_loc + tmp_win->icon_g.width) >
329 Scr.MyDisplayWidth) { /* off right */
330 /* position up against right edge */
331 tmp_win->icon_xl_loc = Scr.MyDisplayWidth-tmp_win->icon_g.width;
333 /* end keep label on screen. dje 8/7/97 */
336 else
338 /* resize the icon name window */
339 tmp_win->icon_g.width = tmp_win->icon_p_width;
340 tmp_win->icon_xl_loc = tmp_win->icon_g.x;
344 /* set up TitleGC for drawing the icon label */
345 if (tmp_win->icon_font.font != None)
346 NewFontAndColor(tmp_win->icon_font.font->fid, TextColor, BackColor);
347 if(tmp_win->icon_w != None)
349 tmp_win->icon_g.height = ICON_HEIGHT(tmp_win);
350 XMoveResizeWindow(dpy, tmp_win->icon_w, tmp_win->icon_xl_loc,
351 tmp_win->icon_g.y + tmp_win->icon_p_height,
352 tmp_win->icon_g.width,ICON_HEIGHT(tmp_win));
353 XSetWindowBackground(dpy, tmp_win->icon_w, BackColor);
354 XClearWindow(dpy,tmp_win->icon_w);
356 /* text position */
357 x = (tmp_win->icon_g.width - tmp_win->icon_t_width) / 2;
358 if (x < 3)
359 x = 3;
360 if ((IS_STICKY(tmp_win) || IS_ICON_STICKY(tmp_win)))
362 XRectangle r;
364 if (x < 7)
365 x = 7;
366 r.x = 0;
367 r.y = 0;
368 r.width = tmp_win->icon_g.width - 7;
369 r.height = ICON_HEIGHT(tmp_win);
370 XSetClipRectangles(dpy, Scr.TitleGC, 0, 0, &r, 1, Unsorted);
372 #ifdef I18N_MB
373 XmbDrawString (dpy, tmp_win->icon_w, tmp_win->icon_font.fontset,
374 #else
375 XDrawString (dpy, tmp_win->icon_w,
376 #endif
377 Scr.TitleGC, x,
378 tmp_win->icon_g.height - tmp_win->icon_font.height +
379 tmp_win->icon_font.y - 3, tmp_win->icon_name,
380 strlen(tmp_win->icon_name));
381 RelieveRectangle(dpy, tmp_win->icon_w, 0, 0, tmp_win->icon_g.width - 1,
382 ICON_HEIGHT(tmp_win) - 1, Relief, Shadow, 2);
383 if (IS_STICKY(tmp_win) || IS_ICON_STICKY(tmp_win))
385 /* an odd number of lines every 4 pixels */
386 int num = (ICON_HEIGHT(tmp_win) / 8) * 2 - 1;
387 int min = ICON_HEIGHT(tmp_win) / 2 - num * 2 + 1;
388 int max = ICON_HEIGHT(tmp_win) / 2 + num * 2 - 3;
389 int i;
390 int stipple_w = x - 6;
392 if (stipple_w < 3)
393 stipple_w = 3;
394 for(i = min; i <= max; i += 4)
396 RelieveRectangle(
397 dpy, tmp_win->icon_w, 2, i, stipple_w, 1, Shadow, Relief, 1);
398 RelieveRectangle(
399 dpy, tmp_win->icon_w, tmp_win->icon_g.width - 3 - stipple_w, i,
400 stipple_w, 1, Shadow, Relief, 1);
402 XSetClipMask(dpy, Scr.TitleGC, None);
406 if(tmp_win->icon_pixmap_w != None)
408 XMoveWindow(dpy, tmp_win->icon_pixmap_w, tmp_win->icon_g.x,
409 tmp_win->icon_g.y);
412 /* only relieve unshaped icons that share fvwm's visual */
413 if ((tmp_win->iconPixmap != None) && !IS_ICON_SHAPED(tmp_win)
414 && (Pdefault || (tmp_win->iconDepth == 1) || IS_PIXMAP_OURS(tmp_win)))
415 RelieveRectangle(dpy, tmp_win->icon_pixmap_w, 0, 0,
416 tmp_win->icon_p_width - 1, tmp_win->icon_p_height - 1,
417 Relief, Shadow, 2);
419 /* need to locate the icon pixmap */
420 if (tmp_win->iconPixmap != None)
422 if (tmp_win->iconDepth == 1)
424 /* it's a bitmap */
425 XCopyPlane(dpy, tmp_win->iconPixmap, tmp_win->icon_pixmap_w,
426 Scr.TitleGC, 0, 0, tmp_win->icon_p_width - 4,
427 tmp_win->icon_p_height - 4, 2, 2, 1);
429 else
431 if (Pdefault || IS_PIXMAP_OURS(tmp_win))
433 /* it's a pixmap that need copying */
434 XCopyArea(dpy, tmp_win->iconPixmap, tmp_win->icon_pixmap_w,
435 Scr.TitleGC, 0, 0, tmp_win->icon_p_width - 4,
436 tmp_win->icon_p_height - 4, 2, 2);
438 else
440 /* it's a client pixmap and fvwm is not using the root visual
441 * The icon window has no 3d border so copy to (0,0)
442 * install the root colormap temporarily to help the Exceed server */
443 if (Scr.bo.InstallRootCmap)
444 InstallRootColormap();
445 XCopyArea(dpy, tmp_win->iconPixmap, tmp_win->icon_pixmap_w,
446 DefaultGC(dpy, Scr.screen), 0, 0, tmp_win->icon_p_width,
447 tmp_win->icon_p_height, 0, 0);
448 if (Scr.bo.InstallRootCmap)
449 UninstallRootColormap();
454 if (IS_ICON_ENTERED(tmp_win))
456 if (tmp_win->icon_w != None)
458 XRaiseWindow (dpy, tmp_win->icon_w);
459 raisePanFrames ();
462 else
464 XWindowChanges xwc;
465 int mask;
466 xwc.sibling = tmp_win->frame;
467 xwc.stack_mode = Below;
468 mask = CWSibling|CWStackMode;
469 if (tmp_win->icon_w != None)
471 XConfigureWindow(dpy, tmp_win->icon_w, mask, &xwc);
473 if (tmp_win->icon_pixmap_w != None)
475 XConfigureWindow(dpy, tmp_win->icon_pixmap_w, mask, &xwc);
481 /***********************************************************************
483 * Procedure:
484 * RedoIconName - procedure to re-position the icon window and name
486 ************************************************************************/
487 void RedoIconName(FvwmWindow *tmp_win)
489 if(IS_ICON_SUPPRESSED(tmp_win))
490 return;
492 if (tmp_win->icon_w == (int)NULL)
493 return;
495 if (HAS_NO_ICON_TITLE(tmp_win))
496 tmp_win->icon_t_width = 0;
497 else
498 tmp_win->icon_t_width =
499 XTextWidth(tmp_win->icon_font.font,tmp_win->icon_name,
500 strlen(tmp_win->icon_name));
501 /* clear the icon window, and trigger a re-draw via an expose event */
502 if (IS_ICONIFIED(tmp_win))
503 DrawIconWindow(tmp_win);
504 if (IS_ICONIFIED(tmp_win))
505 XClearArea(dpy, tmp_win->icon_w, 0, 0, 0, 0, True);
506 return;
512 /************************************************************************
514 * Procedure:
515 * AutoPlace - Find a home for an icon
517 ************************************************************************/
518 void AutoPlaceIcon(FvwmWindow *t)
520 int tw,th,tx,ty;
521 int base_x, base_y;
522 int width,height;
523 FvwmWindow *test_window;
524 Bool loc_ok;
525 int real_x=10, real_y=10;
526 int new_x, new_y;
527 Bool do_move_pixmap = False;
528 Bool do_move_title = False;
530 /* New! Put icon in same page as the center of the window */
531 /* Not a good idea for StickyIcons. Neither for icons of windows that are
532 * visible on the current page. */
533 if(IS_ICON_STICKY(t)||IS_STICKY(t))
535 base_x = 0;
536 base_y = 0;
537 /*Also, if its a stickyWindow, put it on the current page! */
538 new_x = t->frame_g.x % Scr.MyDisplayWidth;
539 new_y = t->frame_g.y % Scr.MyDisplayHeight;
540 if(new_x + t->frame_g.width <= 0)
541 new_x += Scr.MyDisplayWidth;
542 if(new_y + t->frame_g.height <= 0)
543 new_y += Scr.MyDisplayHeight;
544 SetupFrame(t, new_x, new_y, t->frame_g.width, t->frame_g.height, False);
545 t->Desk = Scr.CurrentDesk;
547 else if (IsRectangleOnThisPage(&(t->frame_g), t->Desk))
549 base_x = 0;
550 base_y = 0;
552 else
554 base_x=((t->frame_g.x+Scr.Vx+(t->frame_g.width>>1))/Scr.MyDisplayWidth)*
555 Scr.MyDisplayWidth;
556 base_y=((t->frame_g.y+Scr.Vy+(t->frame_g.height>>1))/
557 Scr.MyDisplayHeight)*Scr.MyDisplayHeight;
558 /* limit icon position to desktop */
559 if (base_x > Scr.VxMax)
560 base_x = Scr.VxMax;
561 if (base_x < 0)
562 base_x = 0;
563 if (base_y > Scr.VyMax)
564 base_y = Scr.VyMax;
565 if (base_y < 0)
566 base_y = 0;
567 base_x -= Scr.Vx;
568 base_y -= Scr.Vy;
570 if(IS_ICON_MOVED(t))
572 /* just make sure the icon is on this screen */
573 t->icon_g.x = t->icon_g.x % Scr.MyDisplayWidth + base_x;
574 t->icon_g.y = t->icon_g.y % Scr.MyDisplayHeight + base_y;
575 if(t->icon_g.x < 0)
576 t->icon_g.x += Scr.MyDisplayWidth;
577 if(t->icon_g.y < 0)
578 t->icon_g.y += Scr.MyDisplayHeight;
579 t->icon_xl_loc = t->icon_g.x;
580 do_move_pixmap = True;
581 do_move_title = True;
583 else if (USE_ICON_POSITION_HINT(t) && t->wmhints &&
584 t->wmhints->flags & IconPositionHint)
586 t->icon_g.x = t->wmhints->icon_x;
587 t->icon_g.y = t->wmhints->icon_y;
588 t->icon_xl_loc = t->icon_g.x;
590 /* dje 10/12/97:
591 Look thru chain of icon boxes assigned to window.
592 Add logic for grids and fill direction.
594 else
596 /* A place to hold inner and outer loop variables. */
597 typedef struct dimension_struct
599 int step; /* grid size (may be negative) */
600 int start_at; /* starting edge */
601 int real_start; /* on screen starting edge */
602 int end_at; /* ending edge */
603 int base; /* base for screen */
604 int icon_dimension; /* height or width */
605 int nom_dimension; /* nonminal height or width */
606 int screen_dimension; /* screen height or width */
607 } dimension;
608 dimension dim[3]; /* space for work, 1st, 2nd dimen */
609 icon_boxes *icon_boxes_ptr; /* current icon box */
610 int i; /* index for inner/outer loop data */
612 /* Hopefully this makes the following more readable. */
613 #define ICONBOX_LFT icon_boxes_ptr->IconBox[0]
614 #define ICONBOX_TOP icon_boxes_ptr->IconBox[1]
615 #define ICONBOX_RGT icon_boxes_ptr->IconBox[2]
616 #define ICONBOX_BOT icon_boxes_ptr->IconBox[3]
617 #define BOT_FILL icon_boxes_ptr->IconFlags & ICONFILLBOT
618 #define RGT_FILL icon_boxes_ptr->IconFlags & ICONFILLRGT
619 #define HRZ_FILL icon_boxes_ptr->IconFlags & ICONFILLHRZ
621 /* unnecessary copy of width */
622 width = t->icon_p_width;
623 /* total height */
624 height = t->icon_g.height + t->icon_p_height;
625 /* no slot found yet */
626 loc_ok = False;
628 /* check all boxes in order */
629 icon_boxes_ptr = NULL; /* init */
630 while(do_all_iconboxes(t, &icon_boxes_ptr))
632 if (loc_ok == True)
634 /* leave for loop */
635 break;
637 /* y amount */
638 dim[1].step = icon_boxes_ptr->IconGrid[1];
639 /* init start from */
640 dim[1].start_at = ICONBOX_TOP;
641 /* init end at */
642 dim[1].end_at = ICONBOX_BOT;
643 /* save base */
644 dim[1].base = base_y;
645 /* save dimension */
646 dim[1].icon_dimension = height;
647 dim[1].screen_dimension = Scr.MyDisplayHeight;
648 if (BOT_FILL)
650 /* fill from bottom */
651 /* reverse step */
652 dim[1].step = 0 - dim[1].step;
653 } /* end fill from bottom */
655 /* x amount */
656 dim[2].step = icon_boxes_ptr->IconGrid[0];
657 /* init start from */
658 dim[2].start_at = ICONBOX_LFT;
659 /* init end at */
660 dim[2].end_at = ICONBOX_RGT;
661 /* save base */
662 dim[2].base = base_x;
663 /* save dimension */
664 dim[2].icon_dimension = width;
665 dim[2].screen_dimension = Scr.MyDisplayWidth;
666 if (RGT_FILL)
668 /* fill from right */
669 /* reverse step */
670 dim[2].step = 0 - dim[2].step;
671 } /* end fill from right */
672 for (i=1;i<=2;i++)
674 /* for dimensions 1 and 2 */
675 /* If the window is taller than the icon box, ignore the icon height
676 * when figuring where to put it. Same goes for the width
677 * This should permit reasonably graceful handling of big icons. */
678 dim[i].nom_dimension = dim[i].icon_dimension;
679 if (dim[i].icon_dimension >= dim[i].end_at - dim[i].start_at)
681 dim[i].nom_dimension = dim[i].end_at - dim[i].start_at - 1;
683 if (dim[i].step < 0)
685 /* if moving backwards */
686 /* save */
687 dim[0].start_at = dim[i].start_at;
688 /* swap one */
689 dim[i].start_at = dim[i].end_at;
690 /* swap the other */
691 dim[i].end_at = dim[0].start_at;
692 dim[i].start_at -= dim[i].icon_dimension;
693 } /* end moving backwards */
694 /* adjust both to base */
695 dim[i].start_at += dim[i].base;
696 dim[i].end_at += dim[i].base;
697 } /* end 2 dimensions */
698 if (HRZ_FILL)
700 /* if hrz first */
701 /* save */
702 memcpy(&dim[0],&dim[1],sizeof(dimension));
703 /* switch one */
704 memcpy(&dim[1],&dim[2],sizeof(dimension));
705 /* switch the other */
706 memcpy(&dim[2],&dim[0],sizeof(dimension));
707 } /* end horizontal dimension first */
708 /* save for reseting inner loop */
709 dim[0].start_at = dim[2].start_at;
710 while((dim[1].step < 0 /* filling reversed */
711 ? (dim[1].start_at + dim[1].icon_dimension - dim[1].nom_dimension
712 > dim[1].end_at) /* check back edge */
713 : (dim[1].start_at + dim[1].nom_dimension
714 < dim[1].end_at)) /* check front edge */
715 && (!loc_ok)) { /* nothing found yet */
716 dim[1].real_start = dim[1].start_at; /* init */
717 if (dim[1].start_at + dim[1].icon_dimension >
718 dim[1].screen_dimension - 2 + dim[1].base)
720 /* off screen, move on screen */
721 dim[1].real_start = dim[1].screen_dimension
722 - dim[1].icon_dimension + dim[1].base;
723 } /* end off screen */
724 if (dim[1].start_at < dim[1].base)
726 /* if off other edge, move on screen */
727 dim[1].real_start = dim[1].base;
728 } /* end off other edge */
729 /* reset inner loop */
730 dim[2].start_at = dim[0].start_at;
731 while((dim[2].step < 0 /* filling reversed */
732 ? (dim[2].start_at + dim[2].icon_dimension-dim[2].nom_dimension
733 > dim[2].end_at) /* check back edge */
734 : (dim[2].start_at + dim[2].nom_dimension
735 < dim[2].end_at)) /* check front edge */
736 && (!loc_ok)) { /* nothing found yet */
737 dim[2].real_start = dim[2].start_at; /* init */
738 if (dim[2].start_at + dim[2].icon_dimension >
739 dim[2].screen_dimension - 2 + dim[2].base)
741 /* if off screen, move on screen */
742 dim[2].real_start = dim[2].screen_dimension
743 - dim[2].icon_dimension + dim[2].base;
744 } /* end off screen */
745 if (dim[2].start_at < dim[2].base)
747 /* if off other edge, move on screen */
748 dim[2].real_start = dim[2].base;
749 } /* end off other edge */
751 if (HRZ_FILL)
753 /* hrz first */
754 /* unreverse them */
755 real_x = dim[1].real_start;
756 real_y = dim[2].real_start;
758 else
760 /* reverse them */
761 real_x = dim[2].real_start;
762 real_y = dim[1].real_start;
765 /* this may be a good location */
766 loc_ok = True;
767 test_window = Scr.FvwmRoot.next;
768 while((test_window != (FvwmWindow *)0)
769 &&(loc_ok == True))
771 /* test overlap */
772 if(test_window->Desk == t->Desk)
774 if((IS_ICONIFIED(test_window)) &&
775 (!IS_TRANSIENT(test_window) ||
776 !IS_ICONIFIED_BY_PARENT(test_window)) &&
777 (test_window->icon_w||test_window->icon_pixmap_w) &&
778 (test_window != t)) {
779 tw=test_window->icon_p_width;
780 th=test_window->icon_p_height+
781 test_window->icon_g.height;
782 tx = test_window->icon_g.x;
783 ty = test_window->icon_g.y;
785 if((tx<(real_x+width+3))&&((tx+tw+3) > real_x)&&
786 (ty<(real_y+height+3))&&((ty+th + 3)>real_y))
788 /* don't accept this location */
789 loc_ok = False;
790 } /* end if icons overlap */
791 } /* end if its an icon */
792 } /* end if same desk */
793 test_window = test_window->next;
794 } /* end while icons that may overlap */
795 /* Grid inner value & direction */
796 dim[2].start_at += dim[2].step;
797 } /* end while room inner dimension */
798 /* Grid outer value & direction */
799 dim[1].start_at += dim[1].step;
800 } /* end while room outer dimension */
801 } /* end for all icon boxes, or found space */
802 if(loc_ok == False)
803 /* If icon never found a home just leave it */
804 return;
805 t->icon_g.x = real_x;
806 t->icon_g.y = real_y;
808 if(t->icon_pixmap_w)
809 XMoveWindow(dpy,t->icon_pixmap_w,t->icon_g.x, t->icon_g.y);
811 t->icon_g.width = t->icon_p_width;
812 t->icon_xl_loc = t->icon_g.x;
814 do_move_title = True;
815 BroadcastPacket(M_ICON_LOCATION, 7,
816 t->w, t->frame,
817 (unsigned long)t,
818 t->icon_g.x, t->icon_g.y,
819 t->icon_p_width, t->icon_g.height+t->icon_p_height);
821 if (do_move_pixmap && t->icon_pixmap_w != None)
823 XMoveWindow(dpy, t->icon_pixmap_w, t->icon_g.x, t->icon_g.y);
825 if (do_move_title && t->icon_w != None)
827 XMoveResizeWindow(
828 dpy, t->icon_w, t->icon_xl_loc, t->icon_g.y+t->icon_p_height,
829 t->icon_g.width, ICON_HEIGHT(t));
833 static icon_boxes *global_icon_box_ptr;
834 /* Find next icon box to try to place icon in.
835 Goes thru chain that the window got thru style matching,
836 then the global icon box.
837 Create the global icon box on first call.
838 Return code indicates when the boxes are used up.
839 The boxes could only get completely used up when you fill the screen
840 with them.
842 static int
843 do_all_iconboxes(FvwmWindow *t, icon_boxes **icon_boxes_ptr)
845 if (global_icon_box_ptr == 0) { /* if first time */
846 /* Right now, the global box is hard-coded, fills the screen,
847 uses an 80x80 grid, and fills top-bottom, left-right */
848 global_icon_box_ptr = calloc(1, sizeof(icon_boxes));
849 global_icon_box_ptr->IconBox[2] = Scr.MyDisplayHeight;
850 global_icon_box_ptr->IconBox[3] = Scr.MyDisplayWidth;
851 global_icon_box_ptr->IconGrid[0] = 80;
852 global_icon_box_ptr->IconGrid[1] = 80;
853 global_icon_box_ptr->IconFlags = ICONFILLHRZ;
855 if (*icon_boxes_ptr == NULL) { /* first time? */
856 *icon_boxes_ptr = t->IconBoxes; /* start at windows box */
857 if (!*icon_boxes_ptr) { /* if window has no box */
858 *icon_boxes_ptr = global_icon_box_ptr; /* use global box */
860 return (1); /* use box */
863 /* Here its not the first call, we are either on the chain or at
864 the global box */
865 if (*icon_boxes_ptr == global_icon_box_ptr) { /* if the global box */
866 return (0); /* completely out of boxes (unlikely) */
868 *icon_boxes_ptr = (*icon_boxes_ptr)->next; /* move to next one on chain */
869 if (*icon_boxes_ptr) { /* if there is a next one */
870 return (1); /* return it */
872 *icon_boxes_ptr = global_icon_box_ptr; /* global box */
873 return (1); /* use it */
876 /****************************************************************************
878 * Looks for a monochrome icon bitmap file
880 ****************************************************************************/
881 static void GetBitmapFile(FvwmWindow *tmp_win)
883 char *path = NULL;
884 int HotX,HotY;
886 path = findImageFile(tmp_win->icon_bitmap_file, NULL, R_OK);
888 if (path == NULL)
889 return;
890 if (XReadBitmapFile(dpy, Scr.Root, path,
891 (unsigned int *)&tmp_win->icon_p_width,
892 (unsigned int *)&tmp_win->icon_p_height,
893 &tmp_win->iconPixmap, &HotX, &HotY) == BitmapSuccess)
895 tmp_win->iconDepth = 1;
896 SET_PIXMAP_OURS(tmp_win, 1);
898 else
900 tmp_win->icon_p_width = 0;
901 tmp_win->icon_p_height = 0;
904 free(path);
907 /****************************************************************************
909 * Looks for a color XPM icon file
911 ****************************************************************************/
912 static void GetXPMFile(FvwmWindow *tmp_win)
914 #ifdef XPM
915 XpmAttributes xpm_attributes;
916 char *path = NULL;
917 XpmImage my_image;
918 int rc;
920 path = findImageFile(tmp_win->icon_bitmap_file, NULL, R_OK);
921 if(path == NULL)return;
923 xpm_attributes.visual = Pvisual;
924 xpm_attributes.colormap = Pcmap;
925 xpm_attributes.depth = Pdepth;
926 xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
927 xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmCloseness
928 | XpmVisual | XpmColormap | XpmDepth;
930 rc = XpmReadFileToXpmImage(path, &my_image, NULL);
931 if (rc != XpmSuccess)
933 fvwm_msg(ERR,"GetXPMFile","XpmReadFileToXpmImage failed, pixmap %s, rc %d",
934 path, rc);
935 free(path);
936 return;
938 free(path);
939 color_reduce_pixmap(&my_image,Scr.ColorLimit);
940 rc = XpmCreatePixmapFromXpmImage(dpy,Scr.NoFocusWin, &my_image,
941 &tmp_win->iconPixmap,
942 &tmp_win->icon_maskPixmap,
943 &xpm_attributes);
944 if (rc != XpmSuccess)
946 fvwm_msg(ERR,"GetXPMFile",
947 "XpmCreatePixmapFromXpmImage failed, rc %d\n", rc);
948 XpmFreeXpmImage(&my_image);
949 return;
951 tmp_win->icon_p_width = my_image.width;
952 tmp_win->icon_p_height = my_image.height;
953 SET_PIXMAP_OURS(tmp_win, 1);
954 tmp_win->iconDepth = Pdepth;
956 #ifdef SHAPE
957 if (ShapesSupported && tmp_win->icon_maskPixmap)
958 SET_ICON_SHAPED(tmp_win, 1);
959 #endif
961 XpmFreeXpmImage(&my_image);
963 #endif /* XPM */
966 /****************************************************************************
968 * Looks for an application supplied icon window
970 ****************************************************************************/
971 void GetIconWindow(FvwmWindow *tmp_win)
973 /* We are guaranteed that wmhints is non-null when calling this
974 * routine */
975 if(XGetGeometry(dpy, tmp_win->wmhints->icon_window, &JunkRoot,
976 &JunkX, &JunkY,(unsigned int *)&tmp_win->icon_p_width,
977 (unsigned int *)&tmp_win->icon_p_height,
978 &JunkBW, &JunkDepth)==0)
980 fvwm_msg(ERR,"GetIconWindow","Help! Bad Icon Window!");
982 tmp_win->icon_p_width += JunkBW<<1;
983 tmp_win->icon_p_height += JunkBW<<1;
985 * Now make the new window the icon window for this window,
986 * and set it up to work as such (select for key presses
987 * and button presses/releases, set up the contexts for it,
988 * and define the cursor for it).
990 tmp_win->icon_pixmap_w = tmp_win->wmhints->icon_window;
991 #ifdef SHAPE
992 if (ShapesSupported)
994 if (tmp_win->wmhints->flags & IconMaskHint)
996 SET_ICON_SHAPED(tmp_win, 1);
997 tmp_win->icon_maskPixmap = tmp_win->wmhints->icon_mask;
1000 #endif
1001 /* Make sure that the window is a child of the root window ! */
1002 /* Olwais screws this up, maybe others do too! */
1003 XReparentWindow(dpy, tmp_win->icon_pixmap_w, Scr.Root, 0,0);
1004 SET_ICON_OURS(tmp_win, 0);
1008 /****************************************************************************
1010 * Looks for an application supplied bitmap or pixmap
1012 ****************************************************************************/
1013 void GetIconBitmap(FvwmWindow *tmp_win)
1015 unsigned int width, height, depth;
1017 /* We are guaranteed that wmhints is non-null when calling this routine */
1018 if (!XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap, &JunkRoot,
1019 &JunkX, &JunkY, &width, &height, &JunkBW, &depth))
1021 return;
1024 /* sanity check the pixmap depth, it must be the same as the root or 1 */
1025 if ((depth != 1) && (depth != DefaultDepth(dpy,Scr.screen)))
1027 fvwm_msg(ERR, "GetIconBitmap", "Bad client icon pixmap depth %d", depth);
1028 return;
1031 tmp_win->iconPixmap = tmp_win->wmhints->icon_pixmap;
1032 tmp_win->icon_p_width = width;
1033 tmp_win->icon_p_height = height;
1034 tmp_win->iconDepth = depth;
1036 #ifdef SHAPE
1037 if (ShapesSupported)
1039 if (tmp_win->wmhints->flags & IconMaskHint)
1041 SET_ICON_SHAPED(tmp_win, 1);
1042 tmp_win->icon_maskPixmap = tmp_win->wmhints->icon_mask;
1045 #endif
1047 SET_PIXMAP_OURS(tmp_win, 0);
1052 /***********************************************************************
1054 * Procedure:
1055 * DeIconify a window
1057 ***********************************************************************/
1058 void DeIconify(FvwmWindow *tmp_win)
1060 FvwmWindow *t,*tmp;
1062 if(!tmp_win)
1063 return;
1065 if (IS_MAP_PENDING(tmp_win))
1067 /* final state: de-iconified */
1068 SET_ICONIFY_AFTER_MAP(tmp_win, 0);
1069 return;
1072 while (IS_ICONIFIED_BY_PARENT(tmp_win))
1074 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
1076 if (t != tmp_win && tmp_win->transientfor == t->w)
1077 tmp_win = t;
1081 /* AS dje RaiseWindow(tmp_win); */
1082 /* now de-iconify transients */
1083 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
1085 if ((t == tmp_win)||
1086 ((IS_TRANSIENT(t)) && (t->transientfor == tmp_win->w)))
1088 SET_MAPPED(t, 1);
1089 SET_ICONIFIED_BY_PARENT(t, 0);
1090 if(Scr.Hilite == t)
1091 DrawDecorations(t, DRAW_ALL, False, True, None);
1093 /* AS stuff starts here dje */
1094 if (t->icon_pixmap_w)
1095 XUnmapWindow(dpy, t->icon_pixmap_w);
1096 if (t->icon_w)
1097 XUnmapWindow(dpy, t->icon_w);
1098 XFlush(dpy);
1099 /* End AS */
1100 XMapWindow(dpy, t->w);
1101 if(t->Desk == Scr.CurrentDesk)
1103 rectangle r;
1105 r.x = t->icon_g.x;
1106 r.y = t->icon_g.y;
1107 r.width = t->icon_g.width;
1108 r.height = t->icon_p_height+t->icon_g.height;
1109 /* update frame geometry in case the icon was moved over a page
1110 * boundary*/
1111 update_relative_geometry(t);
1112 if (IsRectangleOnThisPage(&r, t->Desk) &&
1113 !IsRectangleOnThisPage(&(t->frame_g), t->Desk))
1115 /* Make sure we keep it on screen when de-iconifying. */
1116 t->frame_g.x -=
1117 truncate_to_multiple(t->frame_g.x,Scr.MyDisplayWidth);
1118 t->frame_g.y -=
1119 truncate_to_multiple(t->frame_g.y,Scr.MyDisplayHeight);
1120 XMoveWindow(dpy, t->frame, t->frame_g.x, t->frame_g.y);
1121 update_absolute_geometry(t);
1122 maximize_adjust_offset(t);
1125 /* domivogt (1-Mar-2000): The next block is a hack to prevent animation
1126 * if the window has an icon, but neither a pixmap nor a title. */
1127 if (HAS_NO_ICON_TITLE(t) && t->icon_pixmap_w == None)
1129 t->icon_g.width = 0;
1130 t->icon_g.height = 0;
1131 t->icon_p_width = 0;
1132 t->icon_p_height = 0;
1134 if (t == tmp_win)
1136 BroadcastPacket(M_DEICONIFY, 11,
1137 t->w, t->frame,
1138 (unsigned long)t,
1139 t->icon_g.x, t->icon_g.y,
1140 t->icon_p_width, t->icon_p_height+t->icon_g.height,
1141 t->frame_g.x, t->frame_g.y,
1142 t->frame_g.width, t->frame_g.height);
1144 else
1146 BroadcastPacket(M_DEICONIFY, 7,
1147 t->w, t->frame,
1148 (unsigned long)t,
1149 t->icon_g.x, t->icon_g.y,
1150 t->icon_p_width,
1151 t->icon_p_height+t->icon_g.height);
1153 if(t->Desk == Scr.CurrentDesk)
1155 XMapWindow(dpy, t->frame);
1156 SET_MAP_PENDING(t, 1);
1158 XMapWindow(dpy, t->Parent);
1159 SetMapStateProp(t, NormalState);
1160 SET_ICONIFIED(t, 0);
1161 SET_ICON_UNMAPPED(t, 0);
1162 SET_ICON_ENTERED(t, 0);
1163 /* Need to make sure the border is colored correctly,
1164 * in case it was stuck or unstuck while iconified. */
1165 tmp = Scr.Hilite;
1166 Scr.Hilite = t;
1167 DrawDecorations(t, DRAW_ALL, False, True, None);
1168 Scr.Hilite = tmp;
1172 #if 1
1173 RaiseWindow(tmp_win); /* moved dje */
1174 #endif
1176 if(HAS_CLICK_FOCUS(tmp_win))
1177 FocusOn(tmp_win, TRUE, "");
1178 GNOME_SetWinArea(tmp_win);
1180 return;
1184 /****************************************************************************
1186 * Iconifies the selected window
1188 ****************************************************************************/
1189 void Iconify(FvwmWindow *tmp_win, int def_x, int def_y)
1191 FvwmWindow *t;
1192 XWindowAttributes winattrs = {0};
1193 unsigned long eventMask;
1195 if(!tmp_win)
1196 return;
1198 if (IS_MAP_PENDING(tmp_win))
1200 /* final state: iconified */
1201 SET_ICONIFY_AFTER_MAP(tmp_win, 1);
1202 return;
1205 if (!XGetWindowAttributes(dpy, tmp_win->w, &winattrs))
1207 return;
1209 eventMask = winattrs.your_event_mask;
1211 if((tmp_win == Scr.Hilite)&&(HAS_CLICK_FOCUS(tmp_win))&&(tmp_win->next))
1213 SetFocus(tmp_win->next->w,tmp_win->next,1);
1216 /* iconify transients first */
1217 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
1219 if ((t==tmp_win)||((IS_TRANSIENT(t)) && (t->transientfor == tmp_win->w)))
1221 SET_ICON_ENTERED(t, 0);
1223 * Prevent the receipt of an UnmapNotify, since that would
1224 * cause a transition to the Withdrawn state.
1226 SET_MAPPED(t, 0);
1227 XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
1228 XUnmapWindow(dpy, t->w);
1229 XSelectInput(dpy, t->w, eventMask);
1230 XUnmapWindow(dpy, t->frame);
1231 t->DeIconifyDesk = t->Desk;
1232 if (t->icon_w)
1233 XUnmapWindow(dpy, t->icon_w);
1234 if (t->icon_pixmap_w)
1235 XUnmapWindow(dpy, t->icon_pixmap_w);
1237 SetMapStateProp(t, IconicState);
1238 DrawDecorations(t, DRAW_ALL, False, False, None);
1239 if (t == tmp_win)
1241 SET_DEICONIFY_PENDING(t, 1);
1243 else
1245 SET_ICONIFIED(t, 1);
1246 SET_ICON_UNMAPPED(t, 1);
1247 SET_ICONIFIED_BY_PARENT(t, 1);
1249 BroadcastPacket(M_ICONIFY, 7,
1250 t->w, t->frame,
1251 (unsigned long)t,
1252 -10000, -10000,
1253 t->icon_g.width,
1254 t->icon_g.height+t->icon_p_height);
1255 BroadcastConfig(M_CONFIGURE_WINDOW,t);
1257 } /* if */
1258 } /* for */
1260 /* necessary during a recapture */
1261 if (IS_ICONIFIED_BY_PARENT(tmp_win))
1262 return;
1264 if (tmp_win->icon_w == None)
1266 if(IS_ICON_MOVED(tmp_win))
1267 CreateIconWindow(tmp_win,tmp_win->icon_g.x,tmp_win->icon_g.y);
1268 else
1269 CreateIconWindow(tmp_win, def_x, def_y);
1272 /* if no pixmap we want icon width to change to text width every iconify */
1273 if( (tmp_win->icon_w != None) && (tmp_win->icon_pixmap_w == None) )
1275 if (HAS_NO_ICON_TITLE(tmp_win))
1277 tmp_win->icon_t_width = 0;
1278 tmp_win->icon_p_width = 0;
1279 tmp_win->icon_g.width = 0;
1281 else
1283 tmp_win->icon_t_width =
1284 XTextWidth(tmp_win->icon_font.font,tmp_win->icon_name,
1285 strlen(tmp_win->icon_name));
1286 tmp_win->icon_p_width = tmp_win->icon_t_width + 6 + 4;
1287 tmp_win->icon_g.width = tmp_win->icon_p_width;
1291 /* this condition will be true unless we restore a window to
1292 iconified state from a saved session. */
1293 if (!(DO_START_ICONIC(tmp_win) && IS_ICON_MOVED(tmp_win)))
1295 AutoPlaceIcon(tmp_win);
1297 /* domivogt (1-Mar-2000): The next block is a hack to prevent animation if the
1298 * window has an icon, but neither a pixmap nor a title. */
1299 if (HAS_NO_ICON_TITLE(tmp_win) && tmp_win->icon_pixmap_w == None)
1301 tmp_win->icon_g.width = 0;
1302 tmp_win->icon_g.height = 0;
1303 tmp_win->icon_p_width = 0;
1304 tmp_win->icon_p_height = 0;
1306 SET_ICONIFIED(tmp_win, 1);
1307 SET_ICON_UNMAPPED(tmp_win, 0);
1308 BroadcastPacket(M_ICONIFY, 11,
1309 tmp_win->w, tmp_win->frame,
1310 (unsigned long)tmp_win,
1311 tmp_win->icon_g.x,
1312 tmp_win->icon_g.y,
1313 tmp_win->icon_g.width,
1314 tmp_win->icon_g.height+tmp_win->icon_p_height,
1315 tmp_win->frame_g.x, /* next 4 added for Animate module */
1316 tmp_win->frame_g.y,
1317 tmp_win->frame_g.width,
1318 tmp_win->frame_g.height);
1319 BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win);
1321 if (!(DO_START_ICONIC(tmp_win) && IS_ICON_MOVED(tmp_win)))
1323 LowerWindow(tmp_win);
1326 if(tmp_win->Desk == Scr.CurrentDesk)
1328 if (tmp_win->icon_w != None)
1329 XMapWindow(dpy, tmp_win->icon_w);
1331 if(tmp_win->icon_pixmap_w != None)
1332 XMapWindow(dpy, tmp_win->icon_pixmap_w);
1334 if(HAS_CLICK_FOCUS(tmp_win) || HAS_SLOPPY_FOCUS(tmp_win))
1336 if (tmp_win == Scr.Focus)
1338 if(Scr.PreviousFocus == Scr.Focus)
1339 Scr.PreviousFocus = NULL;
1340 if(HAS_CLICK_FOCUS(tmp_win) && tmp_win->next)
1341 SetFocus(tmp_win->next->w, tmp_win->next,1);
1342 else
1343 SetFocus(Scr.NoFocusWin, NULL,1);
1350 /****************************************************************************
1352 * This is used to tell applications which windows on the screen are
1353 * top level appication windows, and which windows are the icon windows
1354 * that go with them.
1356 ****************************************************************************/
1357 void SetMapStateProp(FvwmWindow *tmp_win, int state)
1359 unsigned long data[2]; /* "suggested" by ICCCM version 1 */
1361 data[0] = (unsigned long) state;
1362 data[1] = (unsigned long) tmp_win->icon_w;
1363 /* data[2] = (unsigned long) tmp_win->icon_pixmap_w;*/
1365 XChangeProperty(dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32,
1366 PropModeReplace, (unsigned char *) data, 2);
1367 return;
1371 void iconify_function(F_CMD_ARGS)
1373 int toggle;
1375 if (DeferExecution(eventp,&w,&tmp_win,&context, CRS_SELECT, ButtonRelease))
1376 return;
1378 toggle = ParseToggleArgument(action, NULL, -1, 0);
1379 if (toggle == -1)
1381 if (GetIntegerArguments(action, NULL, &toggle, 1) > 0)
1383 if (toggle > 0)
1384 toggle = 1;
1385 else if (toggle < 0)
1386 toggle = 0;
1387 else
1388 toggle = -1;
1391 if (toggle == -1)
1392 toggle = (IS_ICONIFIED(tmp_win)) ? 0 : 1;
1394 if (IS_ICONIFIED(tmp_win))
1396 if (toggle == 0)
1397 DeIconify(tmp_win);
1399 else
1401 if (toggle == 1)
1403 if(check_if_function_allowed(F_ICONIFY,tmp_win,True,0) == 0)
1405 XBell(dpy, 0);
1406 return;
1408 Iconify(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5);