2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This module is mostly all new
20 * A little of it is borrowed from ctwm.
21 * Copyright 1993 Robert Nation. No restrictions are placed on this code,
22 * as long as the copyright notice is preserved
37 #include "libs/fvwmlib.h"
38 #include "libs/FScreen.h"
39 #include "libs/FShape.h"
40 #include "libs/Parse.h"
41 #include "libs/Picture.h"
42 #include "libs/Graphics.h"
43 #include "libs/PictureGraphics.h"
44 #include "libs/FRenderInit.h"
45 #include "libs/Rectangles.c"
46 #include "libs/charmap.h"
47 #include "libs/wcontext.h"
51 #include "execcontext.h"
55 #include "eventmask.h"
56 #include "eventhandler.h"
63 #include "colormaps.h"
66 #include "decorations.h"
67 #include "module_interface.h"
72 static int do_all_iconboxes(FvwmWindow
*t
, icon_boxes
**icon_boxes_ptr
);
73 static void GetIconFromFile(FvwmWindow
*fw
);
74 static void GetIconWindow(FvwmWindow
*fw
);
75 static void GetIconBitmap(FvwmWindow
*fw
);
77 static void clear_icon_dimensions(FvwmWindow
*fw
)
84 px
= fw
->icon_g
.picture_w_g
.x
;
85 py
= fw
->icon_g
.picture_w_g
.y
;
86 tx
= fw
->icon_g
.title_w_g
.x
;
87 ty
= fw
->icon_g
.title_w_g
.y
;
88 memset(&fw
->icon_g
, 0, sizeof(fw
->icon_g
));
89 fw
->icon_g
.picture_w_g
.x
= px
;
90 fw
->icon_g
.picture_w_g
.y
= py
;
91 fw
->icon_g
.title_w_g
.x
= tx
;
92 fw
->icon_g
.title_w_g
.y
= ty
;
96 /* erase all traces of the last used icon in the window structure */
97 void clear_icon(FvwmWindow
*fw
)
99 FW_W_ICON_PIXMAP(fw
) = None
;
100 fw
->iconPixmap
= None
;
101 fw
->icon_maskPixmap
= None
;
102 fw
->icon_alphaPixmap
= None
;
103 fw
->icon_nalloc_pixels
= 0;
104 fw
->icon_alloc_pixels
= NULL
;
105 fw
->icon_no_limit
= 0;
106 if (IS_ICON_MOVED(fw
))
108 clear_icon_dimensions(fw
);
112 memset(&fw
->icon_g
, 0, sizeof(fw
->icon_g
));
118 int get_visible_icon_window_count(FvwmWindow
*fw
)
122 if (fw
== NULL
|| !IS_ICONIFIED(fw
) ||
123 IS_ICON_SUPPRESSED(fw
))
127 if (FW_W_ICON_PIXMAP(fw
) != None
)
131 if (FW_W_ICON_TITLE(fw
) != None
)
139 void setup_icon_title_size(FvwmWindow
*fw
)
141 if (HAS_NO_ICON_TITLE(fw
))
143 fw
->icon_g
.title_text_width
= 0;
144 fw
->icon_g
.title_w_g
.width
= 0;
145 fw
->icon_g
.title_w_g
.height
= 0;
149 fw
->icon_g
.title_text_width
=
151 fw
->icon_font
, fw
->visible_icon_name
,
152 strlen(fw
->visible_icon_name
));
153 fw
->icon_g
.title_w_g
.height
= ICON_HEIGHT(fw
);
154 if (fw
->icon_g
.picture_w_g
.width
== 0)
156 fw
->icon_g
.title_w_g
.width
=
157 fw
->icon_g
.title_text_width
+
158 2 * (ICON_TITLE_TEXT_GAP_COLLAPSED
+
159 abs(fw
->icon_title_relief
));
160 if (IS_STICKY_ACROSS_PAGES(fw
) ||
161 IS_ICON_STICKY_ACROSS_PAGES(fw
) ||
162 IS_STICKY_ACROSS_DESKS(fw
) ||
163 IS_ICON_STICKY_ACROSS_DESKS(fw
))
165 fw
->icon_g
.title_w_g
.width
+=
166 2 * (ICON_TITLE_TO_STICK_EXTRA_GAP
+
167 ICON_TITLE_STICK_MIN_WIDTH
);
172 fw
->icon_g
.title_w_g
.width
=
173 fw
->icon_g
.picture_w_g
.width
;
182 * Resizes the given icon Pixmap.
185 static void SetIconPixmapSize(
186 Pixmap
*icon
, int width
, int height
, int depth
, int newWidth
,
187 int newHeight
, Bool force_centering
, int resize_type
, int *nrx
,
188 int *nry
, int freeOldPixmap
)
191 Pixmap resizedPixmap
= None
;
199 /* Check for invalid dimensions */
200 if (newWidth
== 0 || newHeight
== 0)
205 /* Save the existing Pixmap */
208 gc
= XCreateGC(dpy
, oldPixmap
, 0, &gc_init
);
212 case ICON_RESIZE_TYPE_ADJUSTED
:
213 if (newWidth
!= width
|| newHeight
!= height
)
215 *icon
= CreateStretchPixmap(
216 dpy
, oldPixmap
, width
, height
, depth
, newWidth
,
220 case ICON_RESIZE_TYPE_STRETCHED
:
221 if (width
< newWidth
|| height
< newHeight
)
223 r_w
= max(newWidth
, width
);
224 r_h
= max(newHeight
, height
);
225 resizedPixmap
= CreateStretchPixmap(
226 dpy
, oldPixmap
, width
, height
, depth
, r_w
, r_h
,
232 case ICON_RESIZE_TYPE_SHRUNK
:
233 if (width
> newWidth
|| height
> newHeight
)
235 r_w
= min(newWidth
, width
);
236 r_h
= min(newHeight
, height
);
237 resizedPixmap
= CreateStretchPixmap(
238 dpy
, oldPixmap
, width
, height
, depth
, r_w
, r_h
,
248 if (resize_type
!= ICON_RESIZE_TYPE_ADJUSTED
)
250 *icon
= XCreatePixmap(
251 dpy
, oldPixmap
, newWidth
, newHeight
, depth
);
252 XSetForeground(dpy
, gc
, 0);
253 XFillRectangle(dpy
, *icon
, gc
, 0, 0, newWidth
, newHeight
);
256 * Copy old Pixmap onto new. Center horizontally. Center
257 * vertically if the new height is smaller than the old.
258 * Otherwise, place the icon on the bottom, along the title bar.
260 *nrx
= (newWidth
- width
) / 2;
261 *nry
= (newHeight
> height
&& !force_centering
) ?
262 newHeight
- height
: (newHeight
- height
) / 2;
264 dpy
, (resizedPixmap
)? resizedPixmap
:oldPixmap
, *icon
,
265 gc
, 0, 0, width
, height
, *nrx
, *nry
);
272 XFreePixmap(dpy
, oldPixmap
);
276 /* Move the icon of a window by dx/dy pixels */
279 * Get the Icon for the icon window (also used by ewmh_icon)
282 void GetIconPicture(FvwmWindow
*fw
, Bool no_icon_window
)
287 /* First, see if it was specified in the .fvwmrc */
288 if (ICON_OVERRIDE_MODE(fw
) == ICON_OVERRIDE
)
290 /* try fvwm provided icons before application provided icons */
295 ICON_DBG((stderr
,"ciw: hint order: file iwh iph '%s'\n", fw
->name
));
297 else if (ICON_OVERRIDE_MODE(fw
) == NO_ACTIVE_ICON_OVERRIDE
)
299 if (fw
->wmhints
&& (fw
->wmhints
->flags
& IconPixmapHint
) &&
300 WAS_ICON_HINT_PROVIDED(fw
) == ICON_HINT_MULTIPLE
)
302 /* use application provided icon window or pixmap
303 * first, then fvwm provided icons. */
308 ICON_DBG((stderr
,"ciw: hint order: iwh iph file '%s'\n", fw
->name
));
310 else if (Scr
.DefaultIcon
&&
311 fw
->icon_bitmap_file
== Scr
.DefaultIcon
)
313 /* use application provided icon window/pixmap first,
314 * then fvwm provided default icon */
319 ICON_DBG((stderr
,"ciw: hint order: iwh iph file '%s'\n", fw
->name
));
323 /* use application provided icon window or ewmh icon
324 * first, then fvwm provided icons and then application
325 * provided icon pixmap */
330 ICON_DBG((stderr
,"ciw: hint order: iwh file iph '%s'\n", fw
->name
));
335 /* use application provided icon rather than fvwm provided
341 ICON_DBG((stderr
,"ciw: hint order: iwh iph file '%s'\n", fw
->name
));
344 fw
->icon_g
.picture_w_g
.width
= 0;
345 fw
->icon_g
.picture_w_g
.height
= 0;
346 fw
->iconPixmap
= None
;
347 fw
->icon_maskPixmap
= None
;
348 fw
->icon_alphaPixmap
= None
;
349 FW_W_ICON_PIXMAP(fw
) = None
;
350 for (i
= 0; i
< 4 && fw
->icon_g
.picture_w_g
.width
== 0 &&
351 fw
->icon_g
.picture_w_g
.height
== 0; i
++)
353 switch (icon_order
[i
])
356 /* Next, check for a color pixmap */
357 if (fw
->icon_bitmap_file
)
361 ICON_DBG((stderr
,"ciw: file%s used '%s'\n", (fw
->icon_g
.picture_w_g
.height
)?"":" not", fw
->name
));
364 /* Next, See if the app supplies its own icon window */
370 (fw
->wmhints
->flags
& IconWindowHint
))
374 ICON_DBG((stderr
,"ciw: iwh%s used '%s'\n", (fw
->icon_g
.picture_w_g
.height
)?"":" not",fw
->name
));
377 /* try an ewmh icon */
378 if (HAS_EWMH_WM_ICON_HINT(fw
) == EWMH_TRUE_ICON
)
380 if (EWMH_SetIconFromWMIcon(fw
, NULL
, 0, False
))
382 SET_USE_EWMH_ICON(fw
, True
);
385 ICON_DBG((stderr
,"ciw: inh%s used '%s'\n", (fw
->icon_g
.picture_w_g
.height
)?"":" not",fw
->name
));
388 /* Finally, try to get icon bitmap from the
391 (fw
->wmhints
->flags
& IconPixmapHint
))
395 ICON_DBG((stderr
,"ciw: iph%s used '%s'\n", (fw
->icon_g
.picture_w_g
.height
)?"":" not",fw
->name
));
403 /* Resize icon if necessary */
404 if ((IS_ICON_OURS(fw
)) && fw
->icon_g
.picture_w_g
.height
> 0 &&
405 fw
->icon_g
.picture_w_g
.height
> 0)
407 int newWidth
= fw
->icon_g
.picture_w_g
.width
;
408 int newHeight
= fw
->icon_g
.picture_w_g
.height
;
409 Boolean resize
= False
;
411 if (newWidth
< fw
->min_icon_width
)
413 newWidth
= fw
->min_icon_width
;
418 if (newWidth
> fw
->max_icon_width
)
420 newWidth
= fw
->max_icon_width
;
424 if (newHeight
< fw
->min_icon_height
)
426 newHeight
= fw
->min_icon_height
;
431 if (newHeight
> fw
->max_icon_height
)
433 newHeight
= fw
->max_icon_height
;
439 /* Resize the icon Pixmap */
440 int force_centering
= False
;
443 ICON_DBG((stderr
,"ciw: Changing icon (%s) from %dx%d to"
444 " %dx%d\n", fw
->name
,
445 fw
->icon_g
.picture_w_g
.width
,
446 fw
->icon_g
.picture_w_g
.height
,
447 newWidth
, newHeight
));
448 /* Resize the icon Pixmap */
449 /* force to center if the icon has a bg */
450 if (fw
->icon_background_cs
>= 0 ||
451 fw
->icon_maskPixmap
== None
)
453 force_centering
= True
;
457 fw
->icon_g
.picture_w_g
.width
,
458 fw
->icon_g
.picture_w_g
.height
, fw
->iconDepth
,
459 newWidth
, newHeight
, force_centering
,
460 fw
->icon_resize_type
, &nrx
, &nry
,
463 /* Resize the icon mask Pixmap if one was defined */
464 if (fw
->icon_maskPixmap
)
467 &(fw
->icon_maskPixmap
),
468 fw
->icon_g
.picture_w_g
.width
,
469 fw
->icon_g
.picture_w_g
.height
, 1,
470 newWidth
, newHeight
, force_centering
,
471 fw
->icon_resize_type
, &nrx
, &nry
,
474 else if ((nrx
> 0 || nry
> 0) && fw
->iconDepth
> 1)
476 fw
->icon_maskPixmap
= XCreatePixmap(
478 newWidth
, newHeight
, 1);
479 XSetForeground(dpy
, Scr
.MonoGC
, 0);
481 dpy
, fw
->icon_maskPixmap
, Scr
.MonoGC
,
482 0, 0, newWidth
, newHeight
);
483 XSetForeground(dpy
, Scr
.MonoGC
, 1);
485 dpy
, fw
->icon_maskPixmap
, Scr
.MonoGC
,
486 nrx
, nry
, fw
->icon_g
.picture_w_g
.width
,
487 fw
->icon_g
.picture_w_g
.height
);
488 XSetForeground(dpy
, Scr
.MonoGC
, 0);
489 /* set it shaped ? YES */
490 SET_ICON_SHAPED(fw
, 1);
493 /* Resize the icon alpha Pixmap if one was defined */
494 if (fw
->icon_alphaPixmap
)
497 &(fw
->icon_alphaPixmap
),
498 fw
->icon_g
.picture_w_g
.width
,
499 fw
->icon_g
.picture_w_g
.height
,
500 FRenderGetAlphaDepth(), newWidth
,
501 newHeight
, force_centering
,
502 fw
->icon_resize_type
, &nrx
, &nry
,
506 /* Set the new dimensions of the icon window */
507 fw
->icon_g
.picture_w_g
.width
= newWidth
;
508 fw
->icon_g
.picture_w_g
.height
= newHeight
;
517 * set the icon pixmap window background
520 static void set_icon_pixmap_background(FvwmWindow
*fw
)
522 if (fw
->iconPixmap
!= None
&&
523 (Pdefault
|| fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
||
526 if (fw
->icon_background_cs
>= 0)
529 dpy
, FW_W_ICON_PIXMAP(fw
),
530 fw
->icon_g
.picture_w_g
.width
,
531 fw
->icon_g
.picture_w_g
.height
,
532 &Colorset
[fw
->icon_background_cs
],
533 Pdepth
, Scr
.StdGC
, False
);
535 else if (FShapesSupported
&&
536 Pdepth
== DefaultDepth(dpy
, (DefaultScreen(dpy
))))
538 XSetWindowBackgroundPixmap(
539 dpy
, FW_W_ICON_PIXMAP(fw
), ParentRelative
);
541 else if (Scr
.DefaultColorset
>= 0)
544 dpy
, FW_W_ICON_PIXMAP(fw
),
545 fw
->icon_g
.picture_w_g
.width
,
546 fw
->icon_g
.picture_w_g
.height
,
547 &Colorset
[Scr
.DefaultColorset
], Pdepth
,
555 * Creates an icon window as needed
558 void CreateIconWindow(FvwmWindow
*fw
, int def_x
, int def_y
)
560 /* mask for create windows */
561 unsigned long valuemask
;
562 /* attributes for create windows */
563 XSetWindowAttributes attributes
;
565 Window old_icon_pixmap_w
;
567 Bool is_old_icon_shaped
= IS_ICON_SHAPED(fw
);
569 old_icon_w
= FW_W_ICON_TITLE(fw
);
570 old_icon_pixmap_w
= (IS_ICON_OURS(fw
)) ? FW_W_ICON_PIXMAP(fw
) : None
;
571 if (!IS_ICON_OURS(fw
) && FW_W_ICON_PIXMAP(fw
))
573 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
575 SET_ICON_OURS(fw
, 1);
576 SET_PIXMAP_OURS(fw
, 0);
577 SET_ICON_SHAPED(fw
, 0);
578 FW_W_ICON_PIXMAP(fw
) = None
;
579 fw
->iconPixmap
= None
;
582 if (IS_ICON_SUPPRESSED(fw
))
588 * set up the icon picture
590 GetIconPicture(fw
, False
);
591 /* make space for relief to be drawn outside the icon */
592 /* this does not happen if fvwm is using a non-default visual (with
593 * private colormap) and the client has supplied a pixmap (not a
595 if ((IS_ICON_OURS(fw
)) && (fw
->icon_g
.picture_w_g
.height
> 0)
596 && (Pdefault
|| fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
||
599 fw
->icon_g
.picture_w_g
.width
+=
600 2 * abs(fw
->icon_background_relief
)
601 + 2 * fw
->icon_background_padding
;
602 fw
->icon_g
.picture_w_g
.height
+=
603 2 * abs(fw
->icon_background_relief
)
604 + 2 * fw
->icon_background_padding
;
608 * set up the icon title geometry
610 setup_icon_title_size(fw
);
613 * set up icon position
615 set_icon_position(fw
, def_x
, def_y
);
618 * create the icon title window
620 valuemask
= CWColormap
| CWBorderPixel
| CWBackPixel
| CWCursor
|
622 attributes
.colormap
= Pcmap
;
623 attributes
.background_pixel
= Scr
.StdBack
;
624 attributes
.cursor
= Scr
.FvwmCursors
[CRS_DEFAULT
];
625 attributes
.border_pixel
= 0;
626 attributes
.event_mask
= XEVMASK_ICONW
;
627 if (HAS_NO_ICON_TITLE(fw
))
629 if (FW_W_ICON_TITLE(fw
))
631 XDeleteContext(dpy
, FW_W_ICON_TITLE(fw
), FvwmContext
);
632 XDestroyWindow(dpy
, FW_W_ICON_TITLE(fw
));
634 FW_W_ICON_TITLE(fw
) = None
;
639 if (FW_W_ICON_TITLE(fw
) == None
)
641 FW_W_ICON_TITLE(fw
) = XCreateWindow(
642 dpy
, Scr
.Root
, fw
->icon_g
.title_w_g
.x
,
643 fw
->icon_g
.title_w_g
.y
,
644 fw
->icon_g
.title_w_g
.width
,
645 fw
->icon_g
.title_w_g
.height
, 0, Pdepth
,
646 InputOutput
, Pvisual
, valuemask
, &attributes
);
651 dpy
, FW_W_ICON_TITLE(fw
),
652 fw
->icon_g
.title_w_g
.x
, fw
->icon_g
.title_w_g
.y
,
653 fw
->icon_g
.title_w_g
.width
,
654 fw
->icon_g
.title_w_g
.height
);
657 if (Scr
.DefaultColorset
>= 0)
660 dpy
, FW_W_ICON_TITLE(fw
), fw
->icon_g
.title_w_g
.width
,
661 fw
->icon_g
.title_w_g
.height
,
662 &Colorset
[Scr
.DefaultColorset
], Pdepth
, Scr
.StdGC
,
667 * create the icon picture window
669 if (IS_ICON_OURS(fw
) && fw
->icon_g
.picture_w_g
.width
> 0 &&
670 fw
->icon_g
.picture_w_g
.height
> 0)
672 /* use fvwm's visuals in these cases */
673 if (Pdefault
|| fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
||
676 if (!old_icon_pixmap_w
)
678 FW_W_ICON_PIXMAP(fw
) = XCreateWindow(
679 dpy
, Scr
.Root
, fw
->icon_g
.picture_w_g
.x
,
680 fw
->icon_g
.picture_w_g
.y
,
681 fw
->icon_g
.picture_w_g
.width
,
682 fw
->icon_g
.picture_w_g
.height
, 0,
683 Pdepth
, InputOutput
, Pvisual
,
684 valuemask
, &attributes
);
688 FW_W_ICON_PIXMAP(fw
) = old_icon_pixmap_w
;
690 dpy
, FW_W_ICON_PIXMAP(fw
),
691 fw
->icon_g
.picture_w_g
.x
,
692 fw
->icon_g
.picture_w_g
.y
,
693 fw
->icon_g
.picture_w_g
.width
,
694 fw
->icon_g
.picture_w_g
.height
);
696 set_icon_pixmap_background(fw
);
700 /* client supplied icon pixmap and fvwm is using
702 * use it as the background pixmap, don't try to put
703 * relief on it because fvwm will not have the correct
704 * colors the Exceed server has problems maintaining
705 * the icon window, it usually fails to refresh the
706 * icon leaving it black so ask for expose events */
707 attributes
.background_pixmap
= fw
->iconPixmap
;
708 attributes
.colormap
= DefaultColormap(dpy
, Scr
.screen
);
709 valuemask
&= ~CWBackPixel
;
710 valuemask
|= CWBackPixmap
;
711 FW_W_ICON_PIXMAP(fw
) = XCreateWindow(
712 dpy
, Scr
.Root
, fw
->icon_g
.picture_w_g
.x
,
713 fw
->icon_g
.picture_w_g
.y
,
714 fw
->icon_g
.picture_w_g
.width
,
715 fw
->icon_g
.picture_w_g
.height
, 0,
716 DefaultDepth(dpy
, Scr
.screen
), InputOutput
,
717 DefaultVisual(dpy
, Scr
.screen
), valuemask
,
721 else if (FW_W_ICON_PIXMAP(fw
) != None
)
723 /* client supplied icon window: select events on it */
724 attributes
.event_mask
= XEVMASK_ICONPW
;
725 valuemask
= CWEventMask
;
726 XChangeWindowAttributes(
727 dpy
, FW_W_ICON_PIXMAP(fw
), valuemask
,&attributes
);
728 if (!IS_ICON_OURS(fw
))
731 dpy
, FW_W_ICON_PIXMAP(fw
),
732 fw
->icon_g
.picture_w_g
.x
,
733 fw
->icon_g
.picture_w_g
.y
);
736 if (old_icon_pixmap_w
!= None
&&
737 old_icon_pixmap_w
!= FW_W_ICON_PIXMAP(fw
))
739 /* destroy the old window */
740 XDestroyWindow(dpy
, old_icon_pixmap_w
);
741 XDeleteContext(dpy
, old_icon_pixmap_w
, FvwmContext
);
743 is_old_icon_shaped
= False
;
746 if (FShapesSupported
)
748 if (IS_ICON_SHAPED(fw
) && fw
->icon_background_cs
< 0)
750 /* when fvwm is using the non-default visual client
751 * supplied icon pixmaps are drawn in a window with no
755 if (Pdefault
|| fw
->iconDepth
== 1 ||
756 fw
->iconDepth
== Pdepth
|| IS_PIXMAP_OURS(fw
))
758 off
= abs(fw
->icon_background_relief
) +
759 fw
->icon_background_padding
;
762 dpy
, FW_W_ICON_PIXMAP(fw
), FShapeBounding
, off
,
763 off
, fw
->icon_maskPixmap
, FShapeSet
);
765 else if (is_old_icon_shaped
&&
766 FW_W_ICON_PIXMAP(fw
) == old_icon_pixmap_w
)
768 /* remove the shape */
773 r
.width
= fw
->icon_g
.picture_w_g
.width
;
774 r
.height
= fw
->icon_g
.picture_w_g
.height
;
775 FShapeCombineRectangles(
776 dpy
, FW_W_ICON_PIXMAP(fw
), FShapeBounding
, 0,
777 0, &r
, 1, FShapeSet
, 0);
781 if (FW_W_ICON_TITLE(fw
) != None
&& FW_W_ICON_TITLE(fw
) != old_icon_w
)
784 dpy
, FW_W_ICON_TITLE(fw
), FvwmContext
, (caddr_t
)fw
);
786 dpy
, FW_W_ICON_TITLE(fw
), Scr
.FvwmCursors
[CRS_DEFAULT
]);
787 GrabAllWindowKeysAndButtons(
788 dpy
, FW_W_ICON_TITLE(fw
), Scr
.AllBindings
, C_ICON
,
789 GetUnusedModifiers(), Scr
.FvwmCursors
[CRS_DEFAULT
],
791 xwc
.sibling
= FW_W_FRAME(fw
);
792 xwc
.stack_mode
= Below
;
794 dpy
, FW_W_ICON_TITLE(fw
), CWSibling
|CWStackMode
, &xwc
);
796 if (FW_W_ICON_PIXMAP(fw
) != None
&&
797 FW_W_ICON_PIXMAP(fw
) != old_icon_pixmap_w
)
800 dpy
, FW_W_ICON_PIXMAP(fw
), FvwmContext
, (caddr_t
)fw
);
802 dpy
, FW_W_ICON_PIXMAP(fw
),
803 Scr
.FvwmCursors
[CRS_DEFAULT
]);
804 GrabAllWindowKeysAndButtons(
805 dpy
, FW_W_ICON_PIXMAP(fw
), Scr
.AllBindings
, C_ICON
,
806 GetUnusedModifiers(), Scr
.FvwmCursors
[CRS_DEFAULT
],
808 xwc
.sibling
= FW_W_FRAME(fw
);
809 xwc
.stack_mode
= Below
;
811 dpy
,FW_W_ICON_PIXMAP(fw
),CWSibling
|CWStackMode
,&xwc
);
819 * Draws the icon window
823 void DrawIconTitleWindow(
824 FvwmWindow
*fw
, XEvent
*pev
, Pixel BackColor
, GC Shadow
, GC Relief
,
825 int cs
, int title_cs
)
827 int is_expanded
= IS_ICON_ENTERED(fw
);
828 FlocaleWinString fstr
;
829 Region region
= None
;
831 int relief
= abs(fw
->icon_title_relief
);
834 int w_title
= fw
->icon_g
.title_text_width
;
835 int x_title_w
= fw
->icon_g
.picture_w_g
.x
;
836 int w_title_w
= fw
->icon_g
.picture_w_g
.width
;
837 int x_stipple
= relief
;
838 int w_title_text_gap
= 0;
842 int use_unexpanded_size
= 1;
843 Bool draw_string
= True
;
846 (IS_STICKY_ACROSS_PAGES(fw
) || IS_ICON_STICKY_ACROSS_PAGES(fw
));
848 (IS_STICKY_ACROSS_DESKS(fw
) || IS_ICON_STICKY_ACROSS_DESKS(fw
));
849 is_stippled
= ((is_sticky
&& HAS_STICKY_STIPPLED_ICON_TITLE(fw
)) ||
850 HAS_STIPPLED_ICON_TITLE(fw
));
851 if (is_expanded
&& FW_W_ICON_PIXMAP(fw
) != None
)
858 use_unexpanded_size
= 0;
859 w_title_text_gap
= ICON_TITLE_TEXT_GAP_EXPANDED
;
860 x_title_min
= w_title_text_gap
+ relief
;
863 w_stipple
= ICON_TITLE_STICK_MIN_WIDTH
;
865 w_stipple
+ ICON_TITLE_TO_STICK_EXTRA_GAP
;
867 /* resize the icon name window */
868 w_title_w
= w_title
+ 2 * x_title_min
;
869 if (w_title_w
<= fw
->icon_g
.picture_w_g
.width
)
871 /* the expanded title is smaller, so do not
875 use_unexpanded_size
= 1;
879 x_title_w
= fw
->icon_g
.picture_w_g
.x
-
880 (w_title_w
- fw
->icon_g
.picture_w_g
.width
) / 2;
882 NULL
, FSCREEN_CURRENT
,
884 /* start keep label on screen. dje 8/7/97 */
885 if (x_title_w
< sx
) {
886 /* if new loc neg (off left edge) */
887 x_title_w
= sx
; /* move to edge */
891 /* if not on left edge */
892 /* if (new loc + width) > screen width
893 * (off edge on right) */
894 if ((x_title_w
+ w_title_w
) >sx
+ sw
) {
896 /* position up against right
898 x_title_w
= sx
+ sw
- w_title_w
;
900 /* end keep label on screen. dje
905 if (use_unexpanded_size
)
907 w_title_text_gap
= ICON_TITLE_TEXT_GAP_COLLAPSED
;
908 x_title_min
= w_title_text_gap
+ relief
;
909 /* resize the icon name window */
910 if (FW_W_ICON_PIXMAP(fw
) != None
)
912 w_title_w
= fw
->icon_g
.picture_w_g
.width
;
913 x_title_w
= fw
->icon_g
.picture_w_g
.x
;
917 w_title_w
= fw
->icon_g
.title_w_g
.width
;
918 x_title_w
= fw
->icon_g
.title_w_g
.x
;
922 if (fw
->icon_g
.title_w_g
.width
!= w_title_w
||
923 fw
->icon_g
.title_w_g
.x
!= x_title_w
||
924 fw
->icon_g
.title_w_g
.height
!= ICON_HEIGHT(fw
))
926 fw
->icon_g
.title_w_g
.width
= w_title_w
;
927 fw
->icon_g
.title_w_g
.x
= x_title_w
;
928 fw
->icon_g
.title_w_g
.height
= ICON_HEIGHT(fw
);
929 pev
= NULL
; /* resize && redraw all */
935 dpy
, FW_W_ICON_TITLE(fw
), fw
->icon_g
.title_w_g
.x
,
936 fw
->icon_g
.title_w_g
.y
, w_title_w
,
943 dpy
, FW_W_ICON_TITLE(fw
), w_title_w
,
944 ICON_HEIGHT(fw
), &Colorset
[title_cs
], Pdepth
,
949 XSetWindowBackground(
950 dpy
, FW_W_ICON_TITLE(fw
), BackColor
);
954 x_title
= (w_title_w
- w_title
) / 2;
955 if (x_title
< x_title_min
)
956 x_title
= x_title_min
;
960 r
.width
= w_title_w
- x_title
- relief
;
961 r
.height
= ICON_HEIGHT(fw
) - 2*relief
;
967 w_stipple
= ((w_title_w
- 2 *
968 (x_stipple
+ w_title_text_gap
) -
971 if (w_stipple
< ICON_TITLE_STICK_MIN_WIDTH
)
973 w_stipple
= ICON_TITLE_STICK_MIN_WIDTH
;
975 if (x_title
< x_stipple
+ w_stipple
+ w_title_text_gap
)
977 x_title
= x_stipple
+ w_stipple
+
981 r
.width
= w_title_w
- 2 * x_title
;
986 memset(&fstr
, 0, sizeof(fstr
));
988 if (pev
|| is_stippled
)
992 if (!frect_get_intersection(
993 pev
->xexpose
.x
, pev
->xexpose
.y
,
996 r
.x
, r
.y
, r
.width
, r
.height
, &clip
))
1005 clip
.width
= r
.width
;
1006 clip
.height
= r
.height
;
1011 dpy
, Scr
.TitleGC
, 0, 0, &clip
, 1, Unsorted
);
1012 region
= XCreateRegion();
1013 XUnionRectWithRegion (&clip
, region
, region
);
1014 fstr
.flags
.has_clip_region
= True
;
1015 fstr
.clip_region
= region
;
1022 clip
.width
= w_title_w
- 2*relief
;
1023 clip
.height
= ICON_HEIGHT(fw
) - 2*relief
;
1024 XClearWindow(dpy
, FW_W_ICON_TITLE(fw
));
1028 /* needed for first drawing */
1029 if (x_title
- relief
>= 1)
1031 /* clear before the text */
1033 dpy
, FW_W_ICON_TITLE(fw
),
1034 relief
, relief
, x_title
- relief
,
1035 ICON_HEIGHT(fw
) - 2*relief
, False
);
1039 /* clear the stippled area after the text */
1041 dpy
, FW_W_ICON_TITLE(fw
),
1042 w_title_w
- x_stipple
- w_stipple
-1, relief
,
1043 w_stipple
+ 2, ICON_HEIGHT(fw
) - 2*relief
,
1052 /* needed by xft font and at first drawing */
1054 dpy
, FW_W_ICON_TITLE(fw
),
1055 clip
.x
, clip
.y
, clip
.width
, clip
.height
,
1058 fstr
.str
= fw
->visible_icon_name
;
1059 fstr
.win
= FW_W_ICON_TITLE(fw
);
1060 fstr
.gc
= Scr
.TitleGC
;
1063 fstr
.colorset
= &Colorset
[title_cs
];
1064 fstr
.flags
.has_colorset
= 1;
1068 fstr
.colorset
= &Colorset
[cs
];
1069 fstr
.flags
.has_colorset
= 1;
1072 fstr
.y
= fw
->icon_g
.title_w_g
.height
- relief
1073 - fw
->icon_font
->height
+ fw
->icon_font
->ascent
;
1074 FlocaleDrawString(dpy
, fw
->icon_font
, &fstr
, 0);
1075 if (pev
|| is_stippled
)
1077 XSetClipMask(dpy
, Scr
.TitleGC
, None
);
1080 XDestroyRegion(region
);
1085 dpy
, FW_W_ICON_TITLE(fw
), 0, 0, w_title_w
- 1,
1086 ICON_HEIGHT(fw
) - 1,
1087 (fw
->icon_title_relief
> 0)? Relief
:Shadow
,
1088 (fw
->icon_title_relief
> 0)? Shadow
:Relief
, relief
);
1091 /* an odd number of lines every 4 pixels */
1092 int pseudo_height
= ICON_HEIGHT(fw
)- 2*relief
+ 2;
1093 int num
= (pseudo_height
/
1094 ICON_TITLE_STICK_VERT_DIST
/ 2) * 2 - 1;
1095 int min
= ICON_HEIGHT(fw
) / 2 -
1097 int max
= ICON_HEIGHT(fw
) / 2 +
1098 num
* 2 - ICON_TITLE_STICK_VERT_DIST
+ 1;
1101 for(i
= min
; w_stipple
> 0 && i
<= max
;
1102 i
+= ICON_TITLE_STICK_VERT_DIST
)
1105 dpy
, FW_W_ICON_TITLE(fw
), x_stipple
,
1106 i
, w_stipple
- 1, 1, Shadow
,
1107 Relief
, ICON_TITLE_STICK_HEIGHT
);
1109 dpy
, FW_W_ICON_TITLE(fw
),
1110 w_title_w
- x_stipple
- w_stipple
, i
,
1111 w_stipple
- 1, 1, Shadow
, Relief
,
1112 ICON_TITLE_STICK_HEIGHT
);
1120 void DrawIconPixmapWindow(
1121 FvwmWindow
*fw
, Bool reset_bg
, XEvent
*pev
, GC Shadow
, GC Relief
, int cs
)
1124 Bool cleared
= False
;
1129 dpy
, FW_W_ICON_PIXMAP(fw
), fw
->icon_g
.picture_w_g
.x
,
1130 fw
->icon_g
.picture_w_g
.y
);
1132 (fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
|| Pdefault
||
1133 IS_PIXMAP_OURS(fw
)))
1135 set_icon_pixmap_background(fw
);
1136 XClearArea(dpy
, FW_W_ICON_PIXMAP(fw
), 0, 0, 0, 0, False
);
1141 /* need to locate the icon pixmap */
1142 if (fw
->iconPixmap
!= None
)
1144 if (fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
|| Pdefault
||
1147 FvwmRenderAttributes fra
;
1148 Bool draw_icon
= True
;
1150 memset(&fra
, 0, sizeof(fra
));
1151 fra
.mask
= FRAM_DEST_IS_A_WINDOW
;
1154 fra
.mask
|= FRAM_HAVE_ICON_CSET
;
1155 fra
.colorset
= &Colorset
[cs
];
1157 r
.x
= r
.y
= abs(fw
->icon_background_relief
) +
1158 fw
->icon_background_padding
;
1159 r
.width
= fw
->icon_g
.picture_w_g
.width
-
1160 2 * (abs(fw
->icon_background_relief
) +
1161 fw
->icon_background_padding
);
1162 r
.height
= fw
->icon_g
.picture_w_g
.height
-
1163 2 * (abs(fw
->icon_background_relief
) +
1164 fw
->icon_background_padding
);
1167 if (!frect_get_intersection(
1168 pev
->xexpose
.x
, pev
->xexpose
.y
,
1169 pev
->xexpose
.width
, pev
->xexpose
.height
,
1170 r
.x
, r
.y
, r
.width
, r
.height
, &clip
))
1179 clip
.width
= r
.width
;
1180 clip
.height
= r
.height
;
1185 (fw
->icon_alphaPixmap
||
1187 Colorset
[cs
].icon_alpha_percent
< 100)))
1190 dpy
, FW_W_ICON_PIXMAP(fw
),
1191 clip
.x
, clip
.y
, clip
.width
,
1192 clip
.height
, False
);
1194 PGraphicsRenderPixmaps(
1195 dpy
, FW_W_ICON_PIXMAP(fw
),
1196 fw
->iconPixmap
, fw
->icon_maskPixmap
,
1197 fw
->icon_alphaPixmap
, fw
->iconDepth
,
1198 &fra
, FW_W_ICON_PIXMAP(fw
),
1199 Scr
.TitleGC
, Scr
.MonoGC
, Scr
.AlphaGC
,
1200 clip
.x
- r
.x
, clip
.y
- r
.y
,
1201 clip
.width
, clip
.height
,
1202 clip
.x
, clip
.y
, clip
.width
, clip
.height
,
1208 /* it's a client pixmap and fvwm is not using
1209 * the root visual The icon window has no 3d
1210 * border so copy to (0,0) install the root
1211 * colormap temporarily to help the Exceed
1213 if (Scr
.bo
.do_install_root_cmap
)
1214 InstallRootColormap();
1216 dpy
, fw
->iconPixmap
, FW_W_ICON_PIXMAP(fw
),
1217 DefaultGC(dpy
, Scr
.screen
), 0, 0,
1218 fw
->icon_g
.picture_w_g
.width
,
1219 fw
->icon_g
.picture_w_g
.height
, 0, 0);
1220 if (Scr
.bo
.do_install_root_cmap
)
1221 UninstallRootColormap();
1224 /* only relieve unshaped icons or icons with a bg that share fvwm's
1226 if ((fw
->iconPixmap
!= None
) &&
1227 (!IS_ICON_SHAPED(fw
) || fw
->icon_background_cs
>= 0) &&
1228 (Pdefault
|| fw
->iconDepth
== 1 || fw
->iconDepth
== Pdepth
||
1229 IS_PIXMAP_OURS(fw
)))
1232 dpy
, FW_W_ICON_PIXMAP(fw
), 0, 0,
1233 fw
->icon_g
.picture_w_g
.width
- 1,
1234 fw
->icon_g
.picture_w_g
.height
- 1,
1235 (fw
->icon_background_relief
> 0)? Relief
:Shadow
,
1236 (fw
->icon_background_relief
> 0)? Shadow
:Relief
,
1237 abs(fw
->icon_background_relief
));
1242 void DrawIconWindow(
1243 FvwmWindow
*fw
, Bool draw_title
, Bool draw_pixmap
, Bool focus_change
,
1244 Bool reset_bg
, XEvent
*pev
)
1250 color_quad draw_colors
;
1251 color_quad co_draw_colors
;
1254 int co_title_cs
= -1;
1255 int is_expanded
= IS_ICON_ENTERED(fw
);
1257 if (IS_ICON_SUPPRESSED(fw
) || (pev
&& fw
->Desk
!= Scr
.CurrentDesk
))
1262 if (Scr
.Hilite
== fw
)
1264 if (fw
->icon_title_cs_hi
>= 0)
1266 title_cs
= fw
->icon_title_cs_hi
;
1267 draw_colors
.hilight
= Colorset
[title_cs
].hilite
;
1268 draw_colors
.shadow
= Colorset
[title_cs
].shadow
;
1269 draw_colors
.back
= Colorset
[title_cs
].bg
;
1270 draw_colors
.fore
= Colorset
[title_cs
].fg
;
1274 draw_colors
.hilight
= fw
->hicolors
.hilight
;
1275 draw_colors
.shadow
= fw
->hicolors
.shadow
;
1276 draw_colors
.back
= fw
->hicolors
.back
;
1277 draw_colors
.fore
= fw
->hicolors
.fore
;
1279 if (fw
->icon_title_cs
>= 0)
1281 co_title_cs
= fw
->icon_title_cs
;
1282 co_draw_colors
.hilight
= Colorset
[co_title_cs
].hilite
;
1283 co_draw_colors
.shadow
= Colorset
[co_title_cs
].shadow
;
1284 co_draw_colors
.back
= Colorset
[co_title_cs
].bg
;
1285 co_draw_colors
.fore
= Colorset
[co_title_cs
].fg
;
1289 co_draw_colors
.hilight
= fw
->colors
.hilight
;
1290 co_draw_colors
.shadow
= fw
->colors
.shadow
;
1291 co_draw_colors
.back
= fw
->colors
.back
;
1292 co_draw_colors
.fore
= fw
->colors
.fore
;
1299 if (fw
->icon_title_cs
>= 0)
1301 title_cs
= fw
->icon_title_cs
;
1302 draw_colors
.hilight
= Colorset
[title_cs
].hilite
;
1303 draw_colors
.shadow
= Colorset
[title_cs
].shadow
;
1304 draw_colors
.back
= Colorset
[title_cs
].bg
;
1305 draw_colors
.fore
= Colorset
[title_cs
].fg
;
1309 draw_colors
.hilight
= fw
->colors
.hilight
;
1310 draw_colors
.shadow
= fw
->colors
.shadow
;
1311 draw_colors
.back
= fw
->colors
.back
;
1312 draw_colors
.fore
= fw
->colors
.fore
;
1314 if (fw
->icon_title_cs_hi
>= 0)
1316 co_title_cs
= fw
->icon_title_cs_hi
;
1317 co_draw_colors
.hilight
= Colorset
[co_title_cs
].hilite
;
1318 co_draw_colors
.shadow
= Colorset
[co_title_cs
].shadow
;
1319 co_draw_colors
.back
= Colorset
[co_title_cs
].bg
;
1320 co_draw_colors
.fore
= Colorset
[co_title_cs
].fg
;
1324 co_draw_colors
.hilight
= fw
->hicolors
.hilight
;
1325 co_draw_colors
.shadow
= fw
->hicolors
.shadow
;
1326 co_draw_colors
.back
= fw
->hicolors
.back
;
1327 co_draw_colors
.fore
= fw
->hicolors
.fore
;
1332 if (Pdepth
< 2 && Scr
.Hilite
!= fw
)
1334 Relief
= Scr
.StdReliefGC
;
1335 Shadow
= Scr
.StdShadowGC
;
1339 if (Pdepth
< 2 && Scr
.Hilite
== fw
)
1341 Relief
= Scr
.ScratchGC2
;
1345 Globalgcv
.foreground
= draw_colors
.hilight
;
1346 Globalgcm
= GCForeground
;
1347 XChangeGC(dpy
,Scr
.ScratchGC1
,Globalgcm
,&Globalgcv
);
1348 Relief
= Scr
.ScratchGC1
;
1350 Globalgcv
.foreground
= draw_colors
.shadow
;
1351 XChangeGC(dpy
,Scr
.ScratchGC2
, Globalgcm
, &Globalgcv
);
1352 Shadow
= Scr
.ScratchGC2
;
1354 TextColor
= draw_colors
.fore
;
1355 BackColor
= draw_colors
.back
;
1356 /* set up TitleGC for drawing the icon label */
1357 if (fw
->icon_font
!= NULL
)
1359 NewFontAndColor(fw
->icon_font
, TextColor
, BackColor
);
1362 if (draw_title
&& FW_W_ICON_TITLE(fw
) != None
)
1364 if (pev
&& pev
->xexpose
.window
!= FW_W_ICON_TITLE(fw
))
1367 if (FCheckTypedWindowEvent(
1368 dpy
, FW_W_ICON_TITLE(fw
), Expose
, &e
))
1370 flush_accumulate_expose(
1371 FW_W_ICON_TITLE(fw
), &e
);
1372 DrawIconTitleWindow(
1373 fw
, &e
, BackColor
, Shadow
, Relief
, cs
,
1381 flush_expose(FW_W_ICON_TITLE(fw
));
1383 DrawIconTitleWindow(
1384 fw
, pev
, BackColor
, Shadow
, Relief
, cs
,
1391 int bg_cs
= fw
->icon_background_cs
;
1394 (fw
->iconDepth
!= 1 ||
1395 fw
->icon_background_padding
> 0 ||
1396 fw
->icon_maskPixmap
!= None
||
1397 fw
->icon_alphaPixmap
!= None
))
1399 if (Pdepth
< 2 && Scr
.Hilite
== fw
)
1401 Relief
= Scr
.ScratchGC2
;
1405 Globalgcv
.foreground
= Colorset
[bg_cs
].hilite
;
1406 Globalgcm
= GCForeground
;
1408 dpy
,Scr
.ScratchGC1
,Globalgcm
,&Globalgcv
);
1409 Relief
= Scr
.ScratchGC1
;
1411 Globalgcv
.foreground
= Colorset
[bg_cs
].shadow
;
1412 XChangeGC(dpy
,Scr
.ScratchGC2
, Globalgcm
, &Globalgcv
);
1413 Shadow
= Scr
.ScratchGC2
;
1417 if (focus_change
&& draw_pixmap
)
1419 Bool alpha_change
= False
;
1420 Bool tint_change
= False
;
1421 Bool relief_change
= False
;
1422 Bool color_change
= False
;
1424 draw_pixmap
= False
;
1425 /* check if we have to draw the icons */
1429 relief_change
= True
;
1431 else if (fw
->iconDepth
== 1)
1434 (draw_colors
.fore
!=
1435 co_draw_colors
.back
) ||
1436 (draw_colors
.fore
!=
1437 co_draw_colors
.back
);
1439 if (!relief_change
&&
1440 (fw
->iconPixmap
!= None
) && !IS_ICON_SHAPED(fw
)
1441 && (Pdefault
|| fw
->iconDepth
== Pdepth
|| fw
->iconDepth
== 1
1442 || IS_PIXMAP_OURS(fw
)))
1445 (draw_colors
.hilight
!=
1446 co_draw_colors
.hilight
) ||
1447 (draw_colors
.shadow
!=
1448 co_draw_colors
.shadow
);
1450 if (cs
>= 0 && co_cs
>= 0)
1453 (Colorset
[cs
].icon_alpha_percent
!=
1454 Colorset
[co_cs
].icon_alpha_percent
);
1456 (Colorset
[cs
].icon_tint_percent
!=
1457 Colorset
[co_cs
].icon_tint_percent
) ||
1458 (Colorset
[cs
].icon_tint_percent
> 0 &&
1459 Colorset
[cs
].icon_tint
!=
1460 Colorset
[co_cs
].icon_tint
);
1462 else if (cs
>= 0 && co_cs
< 0)
1464 alpha_change
= (Colorset
[cs
].icon_alpha_percent
< 100);
1465 tint_change
= (Colorset
[cs
].icon_tint_percent
> 0);
1467 else if (cs
< 0 && co_cs
>= 0)
1470 (Colorset
[co_cs
].icon_alpha_percent
< 100);
1471 tint_change
= (Colorset
[co_cs
].icon_tint_percent
> 0);
1473 if (alpha_change
|| tint_change
|| relief_change
||
1480 if (draw_pixmap
&& FW_W_ICON_PIXMAP(fw
) != None
)
1482 if (pev
&& pev
->xexpose
.window
!= FW_W_ICON_PIXMAP(fw
))
1485 if (FCheckTypedWindowEvent(
1486 dpy
, FW_W_ICON_PIXMAP(fw
), Expose
, &e
))
1488 flush_accumulate_expose(
1489 FW_W_ICON_PIXMAP(fw
), &e
);
1490 DrawIconPixmapWindow(
1491 fw
, reset_bg
, &e
, Shadow
, Relief
, cs
);
1498 flush_expose(FW_W_ICON_PIXMAP(fw
));
1500 DrawIconPixmapWindow(
1501 fw
, reset_bg
, pev
, Shadow
, Relief
, cs
);
1507 if (FW_W_ICON_TITLE(fw
) != None
)
1509 XRaiseWindow(dpy
, FW_W_ICON_TITLE(fw
));
1517 xwc
.sibling
= FW_W_FRAME(fw
);
1518 xwc
.stack_mode
= Below
;
1519 mask
= CWSibling
|CWStackMode
;
1520 if (FW_W_ICON_TITLE(fw
) != None
)
1522 XConfigureWindow(dpy
, FW_W_ICON_TITLE(fw
), mask
, &xwc
);
1524 if (FW_W_ICON_PIXMAP(fw
) != None
)
1526 XConfigureWindow(dpy
, FW_W_ICON_PIXMAP(fw
), mask
, &xwc
);
1529 /* wait for pending EnterNotify/LeaveNotify events to suppress race
1530 * condition w/ expanding/collapsing icon titles */
1537 * ChangeIconPixmap - procedure change the icon pixmap or "pixmap"
1538 * window. Called in events.c and ewmh_events.c
1541 void ChangeIconPixmap(FvwmWindow
*fw
)
1545 if (!IS_ICONIFIED(fw
))
1547 ICON_DBG((stderr
,"hpn: postpone icon change '%s'\n", fw
->name
));
1548 /* update the icon later when application is iconified */
1549 SET_HAS_ICON_CHANGED(fw
, 1);
1551 else if (IS_ICONIFIED(fw
))
1553 ICON_DBG((stderr
,"hpn: applying new icon '%s'\n", fw
->name
));
1554 SET_ICONIFIED(fw
, 0);
1555 SET_ICON_UNMAPPED(fw
, 0);
1556 get_icon_geometry(fw
, &g
);
1557 CreateIconWindow(fw
, g
.x
, g
.y
);
1558 broadcast_icon_geometry(fw
, False
);
1559 /* domivogt (15-Sep-1999): BroadcastConfig informs modules of
1560 * the configuration change including the iconified flag. So
1561 * this flag must be set here. I'm not sure if the two calls of
1562 * the SET_ICONIFIED macro after BroadcastConfig are necessary,
1563 * but since it's only minimal overhead I prefer to be on the
1565 SET_ICONIFIED(fw
, 1);
1566 BroadcastConfig(M_CONFIGURE_WINDOW
, fw
);
1567 SET_ICONIFIED(fw
, 0);
1569 if (!IS_ICON_SUPPRESSED(fw
))
1571 LowerWindow(fw
, False
);
1572 AutoPlaceIcon(fw
, NULL
, True
);
1573 if (fw
->Desk
== Scr
.CurrentDesk
)
1575 if (FW_W_ICON_TITLE(fw
))
1577 XMapWindow(dpy
, FW_W_ICON_TITLE(fw
));
1579 if (FW_W_ICON_PIXMAP(fw
) != None
)
1581 XMapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
1585 SET_ICONIFIED(fw
, 1);
1586 DrawIconWindow(fw
, False
, True
, False
, False
, NULL
);
1595 * RedoIconName - procedure to re-position the icon window and name
1598 void RedoIconName(FvwmWindow
*fw
)
1600 if (IS_ICON_SUPPRESSED(fw
))
1604 if (FW_W_ICON_TITLE(fw
) == None
)
1608 setup_icon_title_size(fw
);
1609 /* clear the icon window, and trigger a re-draw via an expose event */
1610 if (IS_ICONIFIED(fw
))
1612 DrawIconWindow(fw
, True
, False
, False
, False
, NULL
);
1613 XClearArea(dpy
, FW_W_ICON_TITLE(fw
), 0, 0, 0, 0, True
);
1622 * AutoPlace - Find a home for an icon
1626 FvwmWindow
*t
, initial_window_options_t
*win_opts
,
1627 Bool do_move_immediately
)
1631 FvwmWindow
*test_fw
;
1633 Bool loc_ok_wrong_screen
;
1634 Bool loc_ok_wrong_screen2
;
1635 int real_x
=10, real_y
=10;
1637 Bool do_move_icon
= False
;
1640 /* dv (16-Mar-2003): We need to place the icon even if there is no icon so
1641 * the 'position' can be communicated to the modules to decide whether to show
1642 * the icon or not. */
1643 if (FW_W_ICON_PIXMAP(t
) == None
&& FW_W_ICON_TITLE(t
) == None
)
1648 /* New! Put icon in same page as the center of the window */
1649 /* Not a good idea for StickyIcons. Neither for icons of windows that are
1650 * visible on the current page. */
1651 if (IS_ICON_STICKY_ACROSS_DESKS(t
) || IS_STICKY_ACROSS_DESKS(t
))
1653 t
->Desk
= Scr
.CurrentDesk
;
1655 if (IS_ICON_STICKY_ACROSS_PAGES(t
) || IS_STICKY_ACROSS_PAGES(t
))
1659 /*Also, if its a stickyWindow, put it on the current page! */
1660 new_x
= t
->g
.frame
.x
% Scr
.MyDisplayWidth
;
1661 new_y
= t
->g
.frame
.y
% Scr
.MyDisplayHeight
;
1662 if (new_x
+ t
->g
.frame
.width
<= 0)
1663 new_x
+= Scr
.MyDisplayWidth
;
1664 if (new_y
+ t
->g
.frame
.height
<= 0)
1665 new_y
+= Scr
.MyDisplayHeight
;
1667 t
, new_x
, new_y
, t
->g
.frame
.width
, t
->g
.frame
.height
, False
);
1669 else if (IsRectangleOnThisPage(&(t
->g
.frame
), t
->Desk
))
1676 base_x
= ((t
->g
.frame
.x
+ Scr
.Vx
+ (t
->g
.frame
.width
>> 1)) /
1677 Scr
.MyDisplayWidth
) * Scr
.MyDisplayWidth
;
1678 base_y
= ((t
->g
.frame
.y
+ Scr
.Vy
+ (t
->g
.frame
.height
>> 1)) /
1679 Scr
.MyDisplayHeight
) * Scr
.MyDisplayHeight
;
1680 /* limit icon position to desktop */
1681 if (base_x
> Scr
.VxMax
)
1685 if (base_y
> Scr
.VyMax
)
1692 if (IS_ICON_MOVED(t
) ||
1693 (win_opts
!= NULL
&& win_opts
->flags
.use_initial_icon_xy
))
1699 get_icon_geometry(t
, &g
);
1700 if (win_opts
!= NULL
&& win_opts
->flags
.use_initial_icon_xy
)
1702 g
.x
= win_opts
->initial_icon_x
;
1703 g
.y
= win_opts
->initial_icon_y
;
1708 /* just make sure the icon is on this page */
1709 g
.x
= g
.x
% Scr
.MyDisplayWidth
+ base_x
;
1710 g
.y
= g
.y
% Scr
.MyDisplayHeight
+ base_y
;
1713 g
.x
+= Scr
.MyDisplayWidth
;
1717 g
.y
+= Scr
.MyDisplayHeight
;
1721 modify_icon_position(t
, dx
, dy
);
1722 do_move_icon
= True
;
1724 else if (USE_ICON_POSITION_HINT(t
) && t
->wmhints
&&
1725 t
->wmhints
->flags
& IconPositionHint
)
1727 set_icon_position(t
, t
->wmhints
->icon_x
, t
->wmhints
->icon_y
);
1728 do_move_icon
= True
;
1731 Look thru chain of icon boxes assigned to window.
1732 Add logic for grids and fill direction.
1734 else if (DO_IGNORE_ICON_BOXES(t
))
1740 fscreen_scr_arg fscr
;
1743 get_icon_geometry(t
, &g
);
1744 get_icon_corner(t
, &g
);
1745 fscr
.xypos
.x
= g
.x
+ g
.width
/ 2;
1746 fscr
.xypos
.y
= g
.y
+ g
.height
/ 2;
1747 FScreenGetScrRect(&fscr
, FSCREEN_XYPOS
, &sx
, &sy
, &sw
, &sh
);
1750 else if (g
.x
+ g
.width
> sx
+ sw
)
1751 g
.x
= sx
+ sw
- g
.width
;
1754 else if (g
.y
+ g
.height
> sy
+ sh
)
1755 g
.y
= sy
+ sh
- g
.height
;
1756 set_icon_position(t
, g
.x
, g
.y
);
1757 do_move_icon
= True
;
1761 /* A place to hold inner and outer loop variables. */
1762 typedef struct dimension_struct
1764 int step
; /* grid size (may be negative) */
1765 int start_at
; /* starting edge */
1766 int real_start
; /* on screen starting edge */
1767 int end_at
; /* ending edge */
1768 int base
; /* base for screen */
1769 int icon_dimension
; /* height or width */
1770 int nom_dimension
; /* nonminal height or width */
1771 int screen_dimension
; /* screen height or width */
1772 int screen_offset
; /* screen offset */
1774 dimension dim
[3]; /* space for work, 1st, 2nd dimen */
1775 icon_boxes
*icon_boxes_ptr
; /* current icon box */
1776 int i
; /* index for inner/outer loop data */
1777 fscreen_scr_arg fscr
;
1781 /* Hopefully this makes the following more readable. */
1782 #define ICONBOX_LFT icon_boxes_ptr->IconBox[0]
1783 #define ICONBOX_TOP icon_boxes_ptr->IconBox[1]
1784 #define ICONBOX_RGT icon_boxes_ptr->IconBox[2]
1785 #define ICONBOX_BOT icon_boxes_ptr->IconBox[3]
1786 #define BOT_FILL icon_boxes_ptr->IconFlags & ICONFILLBOT
1787 #define RGT_FILL icon_boxes_ptr->IconFlags & ICONFILLRGT
1788 #define HRZ_FILL icon_boxes_ptr->IconFlags & ICONFILLHRZ
1791 fscr
.xypos
.x
= t
->g
.frame
.x
+ (t
->g
.frame
.width
/ 2) - base_x
;
1792 fscr
.xypos
.y
= t
->g
.frame
.y
+ (t
->g
.frame
.height
/ 2) - base_y
;
1793 get_icon_geometry(t
, &g
);
1794 /* unnecessary copy of width */
1798 /* no slot found yet */
1800 loc_ok_wrong_screen
= False
;
1802 /* check all boxes in order */
1803 icon_boxes_ptr
= NULL
; /* init */
1804 while(do_all_iconboxes(t
, &icon_boxes_ptr
))
1808 /* leave for loop */
1811 /* get the screen dimensions for the icon box */
1812 if (icon_boxes_ptr
->IconScreen
== FSCREEN_CURRENT
)
1813 fscr
.mouse_ev
= NULL
;
1816 icon_boxes_ptr
->IconScreen
,
1817 &ref
.x
, &ref
.y
, &ref
.width
, &ref
.height
);
1818 dim
[1].screen_offset
= ref
.y
;
1819 dim
[1].screen_dimension
= ref
.height
;
1820 dim
[2].screen_offset
= ref
.x
;
1821 dim
[2].screen_dimension
= ref
.width
;
1823 dim
[1].step
= icon_boxes_ptr
->IconGrid
[1];
1824 /* init start from */
1825 dim
[1].start_at
= ICONBOX_TOP
+ dim
[1].screen_offset
;
1826 if (icon_boxes_ptr
->IconSign
[1] == '-') {
1827 dim
[1].start_at
+= dim
[1].screen_dimension
;
1830 dim
[1].end_at
= ICONBOX_BOT
+ dim
[1].screen_offset
;
1831 if (icon_boxes_ptr
->IconSign
[3] == '-') {
1832 dim
[1].end_at
+= dim
[1].screen_dimension
;
1835 dim
[1].base
= base_y
;
1836 /* save dimension */
1837 dim
[1].icon_dimension
= height
;
1840 /* fill from bottom */
1842 dim
[1].step
= 0 - dim
[1].step
;
1843 } /* end fill from bottom */
1846 dim
[2].step
= icon_boxes_ptr
->IconGrid
[0];
1847 /* init start from */
1848 dim
[2].start_at
= ICONBOX_LFT
+ dim
[2].screen_offset
;
1849 if (icon_boxes_ptr
->IconSign
[0] == '-') {
1850 dim
[2].start_at
+= dim
[2].screen_dimension
;
1853 dim
[2].end_at
= ICONBOX_RGT
+ dim
[2].screen_offset
;
1854 if (icon_boxes_ptr
->IconSign
[2] == '-') {
1855 dim
[2].end_at
+= dim
[2].screen_dimension
;
1858 dim
[2].base
= base_x
;
1859 /* save dimension */
1860 dim
[2].icon_dimension
= width
;
1863 /* fill from right */
1865 dim
[2].step
= 0 - dim
[2].step
;
1866 } /* end fill from right */
1869 /* for dimensions 1 and 2 */
1870 /* If the window is taller than the icon box, ignore the icon height
1871 * when figuring where to put it. Same goes for the width
1872 * This should permit reasonably graceful handling of big icons. */
1873 dim
[i
].nom_dimension
= dim
[i
].icon_dimension
;
1874 if (dim
[i
].icon_dimension
>= dim
[i
].end_at
- dim
[i
].start_at
)
1876 dim
[i
].nom_dimension
= dim
[i
].end_at
- dim
[i
].start_at
- 1;
1878 if (dim
[i
].step
< 0)
1880 /* if moving backwards */
1882 dim
[0].start_at
= dim
[i
].start_at
;
1884 dim
[i
].start_at
= dim
[i
].end_at
;
1885 /* swap the other */
1886 dim
[i
].end_at
= dim
[0].start_at
;
1887 dim
[i
].start_at
-= dim
[i
].icon_dimension
;
1888 } /* end moving backwards */
1889 /* adjust both to base */
1890 dim
[i
].start_at
+= dim
[i
].base
;
1891 dim
[i
].end_at
+= dim
[i
].base
;
1892 } /* end 2 dimensions */
1897 memcpy(&dim
[0],&dim
[1],sizeof(dimension
));
1899 memcpy(&dim
[1],&dim
[2],sizeof(dimension
));
1900 /* switch the other */
1901 memcpy(&dim
[2],&dim
[0],sizeof(dimension
));
1902 } /* end horizontal dimension first */
1903 /* save for reseting inner loop */
1904 dim
[0].start_at
= dim
[2].start_at
;
1905 loc_ok_wrong_screen2
= False
;
1906 while((dim
[1].step
< 0 /* filling reversed */
1907 ? (dim
[1].start_at
+ dim
[1].icon_dimension
- dim
[1].nom_dimension
1908 > dim
[1].end_at
) /* check back edge */
1909 : (dim
[1].start_at
+ dim
[1].nom_dimension
1910 < dim
[1].end_at
)) /* check front edge */
1912 && (!loc_ok_wrong_screen2
)) { /* nothing found yet */
1913 dim
[1].real_start
= dim
[1].start_at
; /* init */
1914 if (dim
[1].start_at
+ dim
[1].icon_dimension
>
1915 dim
[1].screen_offset
+ dim
[1].screen_dimension
- 2 + dim
[1].base
)
1917 /* off screen, move on screen */
1918 dim
[1].real_start
= dim
[1].screen_offset
+ dim
[1].screen_dimension
1919 - dim
[1].icon_dimension
+ dim
[1].base
;
1920 } /* end off screen */
1921 if (dim
[1].start_at
< dim
[1].screen_offset
+ dim
[1].base
)
1923 /* if off other edge, move on screen */
1924 dim
[1].real_start
= dim
[1].screen_offset
+ dim
[1].base
;
1925 } /* end off other edge */
1926 /* reset inner loop */
1927 dim
[2].start_at
= dim
[0].start_at
;
1928 while((dim
[2].step
< 0 /* filling reversed */
1929 ? (dim
[2].start_at
+ dim
[2].icon_dimension
-dim
[2].nom_dimension
1930 > dim
[2].end_at
) /* check back edge */
1931 : (dim
[2].start_at
+ dim
[2].nom_dimension
1932 < dim
[2].end_at
)) /* check front edge */
1934 && (!loc_ok_wrong_screen2
)) { /* nothing found yet */
1935 dim
[2].real_start
= dim
[2].start_at
; /* init */
1936 if (dim
[2].start_at
+ dim
[2].icon_dimension
>
1937 dim
[2].screen_offset
+ dim
[2].screen_dimension
- 2 + dim
[2].base
)
1939 /* if off screen, move on screen */
1940 dim
[2].real_start
= dim
[2].screen_offset
+ dim
[2].screen_dimension
1941 - dim
[2].icon_dimension
+ dim
[2].base
;
1942 } /* end off screen */
1943 if (dim
[2].start_at
< dim
[2].screen_offset
+ dim
[2].base
)
1945 /* if off other edge, move on screen */
1946 dim
[2].real_start
= dim
[2].screen_offset
+ dim
[2].base
;
1947 } /* end off other edge */
1952 /* unreverse them */
1953 real_x
= dim
[1].real_start
;
1954 real_y
= dim
[2].real_start
;
1959 real_x
= dim
[2].real_start
;
1960 real_y
= dim
[1].real_start
;
1963 /* this may be a good location */
1964 if (FScreenIsRectangleOnScreen(&fscr
, FSCREEN_XYPOS
, &ref
))
1970 loc_ok_wrong_screen2
= True
;
1972 test_fw
= Scr
.FvwmRoot
.next
;
1973 while((test_fw
!= (FvwmWindow
*)0)
1974 &&(loc_ok
== True
|| loc_ok_wrong_screen2
))
1977 if (test_fw
->Desk
== t
->Desk
)
1981 if ((IS_ICONIFIED(test_fw
)) &&
1982 (!IS_TRANSIENT(test_fw
) ||
1983 !IS_ICONIFIED_BY_PARENT(test_fw
)) &&
1984 (FW_W_ICON_TITLE(test_fw
)||FW_W_ICON_PIXMAP(test_fw
)) &&
1986 get_icon_geometry(test_fw
, &g
);
1987 if ((g
.x
<(real_x
+width
+MIN_ICON_BOX_DIST
))&&
1988 ((g
.x
+g
.width
+MIN_ICON_BOX_DIST
) > real_x
)&&
1989 (g
.y
<(real_y
+height
+MIN_ICON_BOX_DIST
))&&
1990 ((g
.y
+g
.height
+ MIN_ICON_BOX_DIST
)>real_y
))
1992 /* don't accept this location */
1994 loc_ok_wrong_screen2
= False
;
1995 } /* end if icons overlap */
1996 } /* end if its an icon */
1997 } /* end if same desk */
1998 test_fw
= test_fw
->next
;
1999 } /* end while icons that may overlap */
2000 if (loc_ok_wrong_screen2
)
2002 loc_ok_wrong_screen
= True
;
2004 /* Grid inner value & direction */
2005 dim
[2].start_at
+= dim
[2].step
;
2006 } /* end while room inner dimension */
2007 /* Grid outer value & direction */
2008 dim
[1].start_at
+= dim
[1].step
;
2009 } /* end while room outer dimension */
2010 } /* end for all icon boxes, or found space */
2011 if (!loc_ok
&& !loc_ok_wrong_screen
)
2012 /* If icon never found a home just leave it */
2014 set_icon_position(t
, real_x
, real_y
);
2015 broadcast_icon_geometry(t
, True
);
2016 do_move_icon
= True
;
2018 if (do_move_icon
&& do_move_immediately
)
2020 move_icon_to_position(t
);
2026 static icon_boxes
*global_icon_box_ptr
;
2027 /* Find next icon box to try to place icon in.
2028 Goes thru chain that the window got thru style matching,
2029 then the global icon box.
2030 Create the global icon box on first call.
2031 Return code indicates when the boxes are used up.
2032 The boxes could only get completely used up when you fill the screen
2036 do_all_iconboxes(FvwmWindow
*t
, icon_boxes
**icon_boxes_ptr
)
2038 if (global_icon_box_ptr
== 0)
2045 /* Right now, the global box is hard-coded, fills the primary
2046 * screen, uses an 80x80 grid, and fills top-bottom,
2048 FScreenGetScrRect(NULL
, FSCREEN_PRIMARY
, &sx
, &sy
, &sw
, &sh
);
2049 global_icon_box_ptr
= calloc(1, sizeof(icon_boxes
));
2050 global_icon_box_ptr
->IconBox
[0] = sx
;
2051 global_icon_box_ptr
->IconBox
[1] = sy
;
2052 global_icon_box_ptr
->IconBox
[2] = sx
+ sw
;
2053 global_icon_box_ptr
->IconBox
[3] = sy
+ sh
;
2054 global_icon_box_ptr
->IconGrid
[0] = 80;
2055 global_icon_box_ptr
->IconGrid
[1] = 80;
2056 global_icon_box_ptr
->IconFlags
= ICONFILLHRZ
;
2058 if (*icon_boxes_ptr
== NULL
)
2061 /* start at windows box */
2062 *icon_boxes_ptr
= t
->IconBoxes
;
2063 if (!*icon_boxes_ptr
)
2065 /* if window has no box */
2066 /* use global box */
2067 *icon_boxes_ptr
= global_icon_box_ptr
;
2073 /* Here its not the first call, we are either on the chain or at
2075 if (*icon_boxes_ptr
== global_icon_box_ptr
)
2077 /* if the global box */
2078 /* completely out of boxes (unlikely) */
2081 /* move to next one on chain */
2082 *icon_boxes_ptr
= (*icon_boxes_ptr
)->next
;
2083 if (*icon_boxes_ptr
)
2085 /* if there is a next one */
2090 *icon_boxes_ptr
= global_icon_box_ptr
;
2098 * Looks for icon from a file
2101 static void GetIconFromFile(FvwmWindow
*fw
)
2104 FvwmPictureAttributes fpa
;
2107 if (fw
->cs
>= 0 && Colorset
[fw
->cs
].do_dither_icon
)
2109 fpa
.mask
|= FPAM_DITHER
;
2111 fw
->icon_g
.picture_w_g
.width
= 0;
2112 fw
->icon_g
.picture_w_g
.height
= 0;
2113 path
= PictureFindImageFile(fw
->icon_bitmap_file
, NULL
, R_OK
);
2118 if (!PImageLoadPixmapFromFile(
2119 dpy
, Scr
.NoFocusWin
, path
, &fw
->iconPixmap
,
2120 &fw
->icon_maskPixmap
, &fw
->icon_alphaPixmap
,
2121 &fw
->icon_g
.picture_w_g
.width
, &fw
->icon_g
.picture_w_g
.height
,
2122 &fw
->iconDepth
, &fw
->icon_nalloc_pixels
, &fw
->icon_alloc_pixels
,
2123 &fw
->icon_no_limit
, fpa
))
2125 fvwm_msg(ERR
, "GetIconFromFile", "Failed to load %s", path
);
2129 SET_PIXMAP_OURS(fw
, 1);
2131 if (FShapesSupported
&& fw
->icon_maskPixmap
)
2133 SET_ICON_SHAPED(fw
, 1);
2141 * Looks for an application supplied icon window
2144 static void GetIconWindow(FvwmWindow
*fw
)
2150 fw
->icon_g
.picture_w_g
.width
= 0;
2151 fw
->icon_g
.picture_w_g
.height
= 0;
2153 /* We are guaranteed that wmhints is non-null when calling this
2156 dpy
, fw
->wmhints
->icon_window
, &JunkRoot
, &JunkX
, &JunkY
,
2157 (unsigned int*)&w
, (unsigned int*)&h
,(unsigned int*)&bw
,
2158 (unsigned int*)&JunkDepth
) == 0)
2161 ERR
,"GetIconWindow",
2162 "Window '%s' has a bad icon window! Ignoring icon"
2163 " window.", fw
->name
.name
);
2164 /* disable the icon window hint */
2165 fw
->wmhints
->icon_window
= None
;
2166 fw
->wmhints
->flags
&= ~IconWindowHint
;
2169 fw
->icon_border_width
= bw
;
2170 fw
->icon_g
.picture_w_g
.width
= w
+ 2 * bw
;
2171 fw
->icon_g
.picture_w_g
.height
= h
+ 2 * bw
;
2173 * Now make the new window the icon window for this window,
2174 * and set it up to work as such (select for key presses
2175 * and button presses/releases, set up the contexts for it,
2176 * and define the cursor for it).
2178 FW_W_ICON_PIXMAP(fw
) = fw
->wmhints
->icon_window
;
2179 if (FShapesSupported
)
2181 if (fw
->wmhints
->flags
& IconMaskHint
)
2183 SET_ICON_SHAPED(fw
, 1);
2184 fw
->icon_maskPixmap
= fw
->wmhints
->icon_mask
;
2187 /* Make sure that the window is a child of the root window ! */
2188 /* Olwais screws this up, maybe others do too! */
2189 XReparentWindow(dpy
, FW_W_ICON_PIXMAP(fw
), Scr
.Root
, 0,0);
2190 SET_ICON_OURS(fw
, 0);
2198 * Looks for an application supplied bitmap or pixmap
2201 static void GetIconBitmap(FvwmWindow
*fw
)
2203 int width
, height
, depth
;
2205 fw
->icon_g
.picture_w_g
.width
= 0;
2206 fw
->icon_g
.picture_w_g
.height
= 0;
2208 /* We are guaranteed that wmhints is non-null when calling this routine
2211 dpy
, fw
->wmhints
->icon_pixmap
, &JunkRoot
, &JunkX
, &JunkY
,
2212 (unsigned int*)&width
, (unsigned int*)&height
,
2213 (unsigned int*)&JunkBW
, (unsigned int*)&depth
))
2216 ERR
,"GetIconBitmap",
2217 "Window '%s' has a bad icon pixmap! Ignoring icon.",
2219 /* disable icon pixmap hint */
2220 fw
->wmhints
->icon_pixmap
= None
;
2221 fw
->wmhints
->flags
&= ~IconPixmapHint
;
2224 /* sanity check the pixmap depth, it must be the same as the root or 1
2226 if (depth
!= 1 && depth
!= Pdepth
&&
2227 depth
!= DefaultDepth(dpy
,Scr
.screen
))
2230 ERR
, "GetIconBitmap",
2231 "Window '%s' has a bad icon bitmap depth %d (should"
2232 " be 1, %d or %d)! Ignoring icon bitmap.",
2233 fw
->name
.name
, depth
, Pdepth
,
2234 DefaultDepth(dpy
,Scr
.screen
));
2235 /* disable icon pixmap hint */
2236 fw
->wmhints
->icon_pixmap
= None
;
2237 fw
->wmhints
->flags
&= ~IconPixmapHint
;
2240 fw
->iconPixmap
= fw
->wmhints
->icon_pixmap
;
2241 fw
->icon_g
.picture_w_g
.width
= width
;
2242 fw
->icon_g
.picture_w_g
.height
= height
;
2243 fw
->iconDepth
= depth
;
2244 if (FShapesSupported
)
2246 if (fw
->wmhints
->flags
& IconMaskHint
)
2248 SET_ICON_SHAPED(fw
, 1);
2249 fw
->icon_maskPixmap
= fw
->wmhints
->icon_mask
;
2252 SET_PIXMAP_OURS(fw
, 0);
2260 * DeIconify a window
2263 void DeIconify(FvwmWindow
*fw
)
2265 FvwmWindow
*t
, *tmp
, *ofw
;
2266 FvwmWindow
*sf
= get_focus_window();
2267 rectangle icon_rect
;
2268 XWindowAttributes winattrs
= {0};
2274 if (!XGetWindowAttributes(dpy
, FW_W(fw
), &winattrs
))
2279 /* make sure fw->flags.is_map_pending is OK */
2280 if (winattrs
.map_state
== IsViewable
&& IS_MAP_PENDING(fw
))
2282 SET_MAP_PENDING(fw
, 0);
2284 else if (IS_MAP_PENDING(fw
))
2286 /* final state: de-iconified */
2287 SET_ICONIFY_AFTER_MAP(fw
, 0);
2290 for (ofw
= NULL
; fw
!= ofw
&& IS_ICONIFIED_BY_PARENT(fw
); )
2292 t
= get_transientfor_fvwmwindow(fw
);
2300 if (IS_ICONIFIED_BY_PARENT(fw
))
2302 SET_ICONIFIED_BY_PARENT(fw
, 0);
2305 /* AS dje RaiseWindow(fw); */
2309 /* take away the focus before mapping */
2312 /* Note: DeleteFocus may delete the flags set by
2313 * mark_transient_subtree(), so do it later. */
2314 mark_transient_subtree(fw
, MARK_ALL_LAYERS
, MARK_ALL
, False
, True
);
2315 /* now de-iconify transients */
2316 for (t
= Scr
.FvwmRoot
.next
; t
!= NULL
; t
= t
->next
)
2318 if (t
== fw
|| IS_IN_TRANSIENT_SUBTREE(t
))
2320 SET_IN_TRANSIENT_SUBTREE(t
, 0);
2322 SET_ICONIFIED_BY_PARENT(t
, 0);
2323 if (Scr
.Hilite
== t
)
2325 border_draw_decorations(
2326 t
, PART_ALL
, False
, True
, CLEAR_ALL
,
2330 /* AS stuff starts here dje */
2331 if (FW_W_ICON_PIXMAP(t
))
2333 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(t
));
2335 if (FW_W_ICON_TITLE(t
))
2337 XUnmapWindow(dpy
, FW_W_ICON_TITLE(t
));
2341 XMapWindow(dpy
, FW_W(t
));
2342 if (t
->Desk
== Scr
.CurrentDesk
)
2346 get_icon_geometry(t
, &r
);
2347 /* update absoluthe geometry in case the icon
2348 * was moved over a page boundary; the move
2349 * code already takes care of keeping the frame
2350 * geometry up to date */
2351 update_absolute_geometry(t
);
2352 if (IsRectangleOnThisPage(&r
, t
->Desk
) &&
2353 !IsRectangleOnThisPage(
2354 &(t
->g
.frame
), t
->Desk
))
2356 /* Make sure we keep it on screen when
2359 truncate_to_multiple(
2361 Scr
.MyDisplayWidth
);
2363 truncate_to_multiple(
2365 Scr
.MyDisplayHeight
);
2368 t
->g
.frame
.x
, t
->g
.frame
.y
);
2369 update_absolute_geometry(t
);
2370 maximize_adjust_offset(t
);
2373 /* domivogt (1-Mar-2000): The next block is a hack to
2374 * prevent animation if the window has an icon, but
2375 * neither a pixmap nor a title. */
2376 if (HAS_NO_ICON_TITLE(t
) && FW_W_ICON_PIXMAP(t
) == None
)
2378 memset(&fw
->icon_g
, 0, sizeof(fw
->icon_g
));
2380 get_icon_geometry(t
, &icon_rect
);
2381 /* if this fails it does not overwrite icon_rect */
2382 EWMH_GetIconGeometry(t
, &icon_rect
);
2386 M_DEICONIFY
, 11, (long)FW_W(t
),
2387 (long)FW_W_FRAME(t
), (unsigned long)t
,
2388 (long)icon_rect
.x
, (long)icon_rect
.y
,
2389 (long)icon_rect
.width
,
2390 (long)icon_rect
.height
,
2393 (long)t
->g
.frame
.width
,
2394 (long)t
->g
.frame
.height
);
2399 M_DEICONIFY
, 7, (long)FW_W(t
),
2400 (long)FW_W_FRAME(t
),
2401 (unsigned long)t
, (long)icon_rect
.x
,
2403 (long)icon_rect
.width
,
2404 (long)icon_rect
.height
);
2406 XMapWindow(dpy
, FW_W_PARENT(t
));
2407 if (t
->Desk
== Scr
.CurrentDesk
)
2409 XMapWindow(dpy
, FW_W_FRAME(t
));
2410 SET_MAP_PENDING(t
, 1);
2412 SetMapStateProp(t
, NormalState
);
2413 SET_ICONIFIED(t
, 0);
2414 SET_ICON_UNMAPPED(t
, 0);
2415 SET_ICON_ENTERED(t
, 0);
2416 /* Need to make sure the border is colored correctly,
2417 * in case it was stuck or unstuck while iconified. */
2420 border_draw_decorations(
2421 t
, PART_ALL
, (sf
== t
) ? True
: False
, True
,
2422 CLEAR_ALL
, NULL
, NULL
);
2428 RaiseWindow(fw
, False
); /* moved dje */
2432 /* update the focus to make sure the application knows its
2434 if (!FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(fw
)))
2436 SetFocusWindow(fw
, True
, FOCUS_SET_FORCE
);
2439 else if (FP_DO_SORT_WINDOWLIST_BY(FW_FOCUS_POLICY(fw
)) ==
2440 FPOL_SORT_WL_BY_OPEN
)
2442 SetFocusWindow(fw
, True
, FOCUS_SET_FORCE
);
2444 focus_grab_buttons_on_layer(fw
->layer
);
2445 GNOME_SetWinArea(fw
);
2453 * Iconifies the selected window
2456 void Iconify(FvwmWindow
*fw
, initial_window_options_t
*win_opts
)
2460 XWindowAttributes winattrs
= {0};
2461 unsigned long eventMask
;
2462 rectangle icon_rect
;
2468 if (!XGetWindowAttributes(dpy
, FW_W(fw
), &winattrs
))
2473 /* make sure fw->flags.is_map_pending is OK */
2474 if ((winattrs
.map_state
== IsViewable
) && IS_MAP_PENDING(fw
))
2476 SET_MAP_PENDING(fw
, 0);
2479 if (IS_MAP_PENDING(fw
))
2481 /* final state: iconified */
2482 SET_ICONIFY_AFTER_MAP(fw
, 1);
2485 eventMask
= winattrs
.your_event_mask
;
2487 mark_transient_subtree(fw
, MARK_ALL_LAYERS
, MARK_ALL
, False
, True
);
2488 sf
= get_focus_window();
2489 if (sf
&& IS_IN_TRANSIENT_SUBTREE(sf
))
2491 restore_focus_after_unmap(sf
, True
);
2492 /* restore_focus_after_unmap() destorys the flags set by
2493 * mark_transient_subtree(), so we have to unfortunately call
2495 mark_transient_subtree(
2496 fw
, MARK_ALL_LAYERS
, MARK_ALL
, False
, True
);
2498 /* iconify transients first */
2499 for (t
= Scr
.FvwmRoot
.next
; t
!= NULL
; t
= t
->next
)
2501 if (t
== fw
|| IS_IN_TRANSIENT_SUBTREE(t
))
2503 SET_IN_TRANSIENT_SUBTREE(t
, 0);
2504 SET_ICON_ENTERED(t
, 0);
2505 /* Prevent the receipt of an UnmapNotify, since that
2506 * would cause a transition to the Withdrawn state. */
2509 dpy
, FW_W(t
), eventMask
& ~StructureNotifyMask
);
2510 XUnmapWindow(dpy
, FW_W(t
));
2511 XSelectInput(dpy
, FW_W(t
), eventMask
);
2512 XUnmapWindow(dpy
, FW_W_FRAME(t
));
2513 border_undraw_decorations(t
);
2514 t
->DeIconifyDesk
= t
->Desk
;
2515 if (FW_W_ICON_TITLE(t
))
2517 XUnmapWindow(dpy
, FW_W_ICON_TITLE(t
));
2519 if (FW_W_ICON_PIXMAP(t
))
2521 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(t
));
2524 SetMapStateProp(t
, IconicState
);
2525 border_draw_decorations(
2526 t
, PART_ALL
, False
, False
, CLEAR_ALL
, NULL
,
2528 if (t
== fw
&& !IS_ICONIFIED_BY_PARENT(fw
))
2530 SET_ICONIFY_PENDING(t
, 1);
2536 SET_ICONIFIED(t
, 1);
2537 SET_ICON_UNMAPPED(t
, 1);
2538 SET_ICONIFIED_BY_PARENT(t
, 1);
2539 get_icon_geometry(t
, &g
);
2541 M_ICONIFY
, 7, (long)FW_W(t
),
2542 (long)FW_W_FRAME(t
),
2543 (unsigned long)t
, (long)-32768,
2544 (long)-32768, (long)g
.width
,
2546 BroadcastConfig(M_CONFIGURE_WINDOW
,t
);
2551 /* necessary during a recapture */
2552 if (IS_ICONIFIED_BY_PARENT(fw
))
2557 if (FW_W_ICON_TITLE(fw
) == None
|| HAS_ICON_CHANGED(fw
))
2559 if (IS_ICON_MOVED(fw
) || win_opts
->flags
.use_initial_icon_xy
)
2563 get_icon_geometry(fw
, &g
);
2564 if (win_opts
->flags
.use_initial_icon_xy
)
2566 g
.x
= win_opts
->initial_icon_x
;
2567 g
.y
= win_opts
->initial_icon_y
;
2569 CreateIconWindow(fw
, g
.x
, g
.y
);
2574 fw
, win_opts
->default_icon_x
,
2575 win_opts
->default_icon_y
);
2577 SET_HAS_ICON_CHANGED(fw
, 0);
2579 else if (FW_W_ICON_TITLE(fw
) && !FW_W_ICON_PIXMAP(fw
))
2581 /* if no pixmap we want icon width to change to text width
2582 * every iconify; not necessary if the icon was created above */
2583 setup_icon_title_size(fw
);
2586 /* this condition will be true unless we restore a window to
2587 * iconified state from a saved session. */
2588 if (win_opts
->initial_state
!= IconicState
||
2589 (!IS_ICON_MOVED(fw
) && !win_opts
->flags
.use_initial_icon_xy
))
2591 AutoPlaceIcon(fw
, win_opts
, True
);
2593 /* domivogt (12-Mar-2003): Clean out the icon geometry if there is no
2594 * icon. Necessary to initialise the values and to suppress animation
2595 * if there is no icon. */
2596 if (HAS_NO_ICON_TITLE(fw
) && FW_W_ICON_PIXMAP(fw
) == None
)
2598 clear_icon_dimensions(fw
);
2600 SET_ICONIFIED(fw
, 1);
2601 SET_ICON_UNMAPPED(fw
, 0);
2602 get_icon_geometry(fw
, &icon_rect
);
2603 /* if this fails it does not overwrite icon_rect */
2604 EWMH_GetIconGeometry(fw
, &icon_rect
);
2606 M_ICONIFY
, 11, (long)FW_W(fw
), (long)FW_W_FRAME(fw
),
2607 (unsigned long)fw
, (long)icon_rect
.x
, (long)icon_rect
.y
,
2608 (long)icon_rect
.width
, (long)icon_rect
.height
,
2609 /* next 4 added for Animate module */
2610 (long)fw
->g
.frame
.x
, (long)fw
->g
.frame
.y
,
2611 (long)fw
->g
.frame
.width
, (long)fw
->g
.frame
.height
);
2612 BroadcastConfig(M_CONFIGURE_WINDOW
,fw
);
2614 if (win_opts
->initial_state
!= IconicState
||
2615 (!IS_ICON_MOVED(fw
) && !win_opts
->flags
.use_initial_icon_xy
))
2617 LowerWindow(fw
, False
);
2619 if (IS_ICON_STICKY_ACROSS_DESKS(fw
) || IS_STICKY_ACROSS_DESKS(fw
))
2621 fw
->Desk
= Scr
.CurrentDesk
;
2623 if (fw
->Desk
== Scr
.CurrentDesk
)
2625 if (FW_W_ICON_TITLE(fw
) != None
)
2627 XMapWindow(dpy
, FW_W_ICON_TITLE(fw
));
2629 if (FW_W_ICON_PIXMAP(fw
) != None
)
2631 XMapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
2634 focus_grab_buttons_on_layer(fw
->layer
);
2641 * This is used to tell applications which windows on the screen are
2642 * top level appication windows, and which windows are the icon windows
2643 * that go with them.
2646 void SetMapStateProp(const FvwmWindow
*fw
, int state
)
2648 /* "suggested" by ICCCM version 1 */
2649 unsigned long data
[2];
2651 data
[0] = (unsigned long) state
;
2652 data
[1] = (unsigned long) FW_W_ICON_TITLE(fw
);
2653 /* data[2] = (unsigned long) FW_W_ICON_PIXMAP(fw);*/
2656 dpy
, FW_W(fw
), _XA_WM_STATE
, _XA_WM_STATE
, 32, PropModeReplace
,
2657 (unsigned char *) data
, 2);
2662 void CMD_Iconify(F_CMD_ARGS
)
2665 FvwmWindow
* const fw
= exc
->w
.fw
;
2667 toggle
= ParseToggleArgument(action
, NULL
, -1, 0);
2670 if (GetIntegerArguments(action
, NULL
, &toggle
, 1) > 0)
2676 else if (toggle
< 0)
2688 toggle
= (IS_ICONIFIED(fw
)) ? 0 : 1;
2691 if (IS_ICONIFIED(fw
))
2696 EWMH_SetWMState(fw
, False
);
2703 initial_window_options_t win_opts
;
2706 !is_function_allowed(
2707 F_ICONIFY
, NULL
, fw
, RQORIG_PROGRAM
,
2714 memset(&win_opts
, 0, sizeof(win_opts
));
2715 fev_get_evpos_or_query(
2716 dpy
, Scr
.Root
, NULL
, &win_opts
.default_icon_x
,
2717 &win_opts
.default_icon_y
);
2718 Iconify(fw
, &win_opts
);
2719 EWMH_SetWMState(fw
, False
);