4 * Based on icons.c of GoodStuff:
5 * Copyright 1993, Robert Nation.
8 /* Copyright 1993, Robert Nation. No guarantees or warantees or anything
9 * are provided or implied in any way whatsoever. Use this program at your
10 * own risk. Permission to use this program for any purpose is given,
11 * as long as the copyright is kept intact. */
13 /* This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * Derived from fvwm icon code
41 #include <X11/Xutil.h>
42 #include <X11/Xproto.h>
43 #include <X11/Xatom.h>
44 #include <X11/Intrinsic.h>
46 #include "libs/Module.h"
47 #include "libs/Grab.h"
48 #include "libs/Graphics.h"
54 #include "libs/fvwmlib.h"
55 #include "libs/FShape.h"
56 #include "libs/Picture.h"
57 #include "fvwm/fvwm.h"
58 #include "FvwmIconBox.h"
60 extern Bool do_allow_bad_access
;
61 extern Bool was_bad_access
;
63 extern int Iconcolorset
;
65 extern int normal_title_relief
;
66 extern int iconified_title_relief
;
68 #define ICON_EVENTS (ExposureMask |\
69 ButtonReleaseMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask)
73 * Creates an Icon Window
74 * Loads an icon file and combines icon shape masks after a resize
75 * special thanks to Rich Neitzel <thor@thor.atd.ucar.edu>
76 * for his patch to handle icon windows
79 void CreateIconWindow(struct icon_info
*item
)
81 unsigned long valuemask
; /* mask for create windows */
82 XSetWindowAttributes attributes
; /* attributes for create windows */
84 attributes
.background_pixel
= icon_back_pix
;
85 attributes
.border_pixel
= 0;
86 attributes
.colormap
= Pcmap
;
87 attributes
.event_mask
= ExposureMask
;
88 valuemask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
90 /* ccreate the icon label */
91 item
->IconWin
= XCreateWindow(dpy
, icon_win
, 0, 0, max_icon_width
,
92 max_icon_height
+ 10, 0, CopyFromParent
,
93 CopyFromParent
, CopyFromParent
, valuemask
,
95 XSelectInput(dpy
, item
->IconWin
, ICON_EVENTS
);
97 XSelectInput(dpy
, item
->id
, PropertyChangeMask
);
98 item
->wmhints
= XGetWMHints(dpy
, item
->id
);
100 if (max_icon_height
== 0)
103 /* config specified icons have priority */
104 if ((item
->icon_file
!= NULL
) && !(item
->extra_flags
& DEFAULTICON
))
106 GetIconFromFile(item
);
108 /* next come program specified icon windows and pixmaps*/
109 if((item
->icon_h
== 0) && (item
->icon_w
== 0) && item
->wmhints
)
111 if (item
->wmhints
->flags
& IconWindowHint
)
113 else if (item
->wmhints
->flags
& IconPixmapHint
)
117 /* if that all fails get the default */
118 if ((item
->icon_file
!= NULL
) && (item
->icon_h
== 0) &&
121 GetIconFromFile(item
);
124 if ((item
->icon_h
== 0) && (item
->icon_w
== 0))
129 /* create the window to hold the pixmap */
130 /* if using a non default visual client pixmaps must have a default
131 * visual window to be drawn into */
132 if (IS_ICON_OURS(item
))
134 if (Pdefault
|| (item
->icon_depth
== 1) || IS_PIXMAP_OURS(item
))
136 item
->icon_pixmap_w
= XCreateWindow(dpy
, icon_win
, 0, 0,
137 max(max_icon_width
, item
->icon_w
),
138 max(max_icon_height
, item
->icon_h
), 0,
139 CopyFromParent
, CopyFromParent
,
140 CopyFromParent
, valuemask
,
145 attributes
.background_pixel
= 0;
146 attributes
.colormap
= DefaultColormap(dpy
, screen
);
147 item
->icon_pixmap_w
= XCreateWindow(dpy
, icon_win
, 0, 0,
148 max(max_icon_width
,item
->icon_w
),
149 max(max_icon_height
,item
->icon_h
), 0,
155 XSelectInput(dpy
, item
->icon_pixmap_w
, ICON_EVENTS
);
158 if (FShapesSupported
&& item
->icon_maskPixmap
!= None
)
161 hr
= (Pdefault
| (item
->icon_depth
== 1) |
162 IS_PIXMAP_OURS(item
)) ? icon_relief
/2 : 0;
163 FShapeCombineMask(dpy
, item
->icon_pixmap_w
, FShapeBounding
,
164 hr
, hr
, item
->icon_maskPixmap
, FShapeSet
);
167 if (FShapesSupported
)
169 XSetWindowBackgroundPixmap(
170 dpy
, item
->icon_pixmap_w
, ParentRelative
);
176 * Bodge the icon title and picture windows for the 3D shadows
177 * Puts them in the correct location
178 * This could do with some serious variable renaming
181 void AdjustIconWindow(struct icon_info
*item
, int n
)
183 int x
=0, y
=0, w
, h
, h2
, h3
, w3
;
185 w3
= w
= max_icon_width
+ icon_relief
;
186 /* the height of the picture window */
187 h3
= h2
= max_icon_height
+ icon_relief
;
188 h
= h2
+ 2 + 2 * max(normal_title_relief
, iconified_title_relief
) +
194 if (secondary
== BOTTOM
)
196 y
= icon_win_height
- (n
/ Lines
+ 1)*(h
+ interval
);
198 else if (secondary
== TOP
)
200 y
= (n
/ Lines
)*(h
+ interval
) + interval
;
205 x
= (n
% Lines
)*(w
+ interval
) + interval
;
209 x
= icon_win_width
- (n
% Lines
+ 1)*(w
+ interval
);
214 if (secondary
== RIGHT
)
216 x
= icon_win_width
- (n
/ Lines
+ 1)*(w
+ interval
);
218 else if (secondary
== LEFT
)
220 x
= (n
/ Lines
)*(w
+ interval
) + interval
;
225 y
= (n
% Lines
)*(h
+ interval
) + interval
;
229 y
= icon_win_height
- (n
% Lines
+ 1)*(h
+ interval
);
239 if (item
->icon_w
> 0 && item
->icon_h
> 0) {
240 w3
= min(max_icon_width
, item
->icon_w
) + icon_relief
;
241 h3
= min(max_icon_height
, item
->icon_h
) + icon_relief
;
243 if (max_icon_height
!= 0) {
244 /* fudge factor for foreign visual icon pixmaps */
245 int r
= (Pdefault
| (item
->icon_depth
== 1) |
246 IS_PIXMAP_OURS(item
)) ? 0 : icon_relief
;
247 XMoveResizeWindow(dpy
, item
->icon_pixmap_w
,
248 x
+ (w
- w3
) / 2 + r
/ 2, y
+ (h2
- h3
) / 2 + r
/ 2,
251 XMoveResizeWindow(dpy
, item
->IconWin
, x
,y
+ h2
,w
,h
- h2
);
256 * Looks for icon from a file
259 void GetIconFromFile(struct icon_info
*item
)
261 char *path
= PictureFindImageFile(item
->icon_file
, imagePath
, R_OK
);
262 FvwmPictureAttributes fpa
;
266 fprintf(stderr
, "[FvwmIconBox] cannot find %s on ImagePath %s\n",
267 item
->icon_file
, imagePath
);
271 if (Iconcolorset
>= 0 && Colorset
[Iconcolorset
].do_dither_icon
)
273 fpa
.mask
|= FPAM_DITHER
;
277 if (!PImageLoadPixmapFromFile(
278 dpy
, main_win
, path
, &item
->iconPixmap
,
279 &item
->icon_maskPixmap
,
280 &item
->icon_alphaPixmap
, &item
->icon_w
, &item
->icon_h
,
281 &item
->icon_depth
, &item
->icon_nalloc_pixels
,
282 &item
->icon_alloc_pixels
, &item
->icon_no_limit
, fpa
))
284 fprintf(stderr
, "[FvwmIconBox] cannot load pixmap from "
290 item
->icon_w
= min(max_icon_width
, item
->icon_w
);
291 item
->icon_h
= min(max_icon_height
, item
->icon_h
);
292 SET_ICON_OURS(item
, True
);
293 SET_PIXMAP_OURS(item
, True
);
300 * Looks for an application supplied icon window
303 void GetIconWindow(struct icon_info
*item
)
310 dpy
, item
->wmhints
->icon_window
, &Junkroot
, &x
, &y
,
311 (unsigned int *)&item
->icon_w
, (unsigned int *)&item
->icon_h
,
312 &bw
, (unsigned int *)&item
->icon_depth
))
315 fprintf(stderr
, "[%s][GetIconWindow] WARN -- '%s' has an "
316 "invalid icon window hint\n", MyName
, item
->name
);
318 /* disable the icon window hint */
321 item
->wmhints
->icon_window
= None
;
322 item
->wmhints
->flags
&= ~IconWindowHint
;
326 item
->icon_pixmap_w
= item
->wmhints
->icon_window
;
328 if (FShapesSupported
&& (item
->wmhints
->flags
& IconMaskHint
))
330 SET_ICON_SHAPED(item
, True
);
331 item
->icon_maskPixmap
= item
->wmhints
->icon_mask
;
334 item
->icon_w
= min(max_icon_width
+ icon_relief
, item
->icon_w
);
335 item
->icon_h
= min(max_icon_height
+ icon_relief
, item
->icon_h
);
338 do_allow_bad_access
= True
;
339 XReparentWindow(dpy
, item
->icon_pixmap_w
, icon_win
, 0, 0);
340 XSetWindowBorderWidth(dpy
, item
->icon_pixmap_w
, 0);
341 XSelectInput(dpy
, item
->icon_pixmap_w
, ICON_EVENTS
);
343 do_allow_bad_access
= False
;
348 fprintf(stderr
, "[%s][GetIconWindow] WARN -- BadAcces when "
349 "reparenting %s icon window\n", MyName
, item
->name
);
351 XSelectInput(dpy
, item
->icon_pixmap_w
, NoEventMask
);
352 XUnmapWindow(dpy
, item
->icon_pixmap_w
);
353 XReparentWindow(dpy
, item
->icon_pixmap_w
, Root
, 0, 0);
354 XUnmapWindow(dpy
, item
->icon_pixmap_w
);
355 MyXUngrabServer(dpy
);
356 item
->icon_pixmap_w
= item
->wmhints
->icon_window
= None
;
357 item
->wmhints
->flags
&= ~IconWindowHint
;
358 item
->icon_maskPixmap
= None
;
361 was_bad_access
= False
;
364 MyXUngrabServer(dpy
);
365 SET_ICON_OURS(item
, False
);
366 SET_PIXMAP_OURS(item
, False
);
371 * Looks for an application supplied bitmap or pixmap
374 void GetIconBitmap(struct icon_info
*item
)
377 unsigned int bw
, depth
;
381 item
->icon_file
= NULL
;
382 item
->icon_maskPixmap
= None
;
383 item
->icon_alphaPixmap
= None
;
384 item
->iconPixmap
= None
;
388 dpy
, item
->wmhints
->icon_pixmap
, &Junkroot
, &x
, &y
,
389 (unsigned int *)&item
->icon_w
, (unsigned int *)&item
->icon_h
,
392 /* disable icon pixmap hint */
395 item
->wmhints
->icon_pixmap
= None
;
396 item
->wmhints
->flags
&= ~IconPixmapHint
;
399 /* sanity check the pixmap depth, it must be the same as the root or 1 */
400 if (depth
!= 1 && depth
!= Pdepth
)
402 /* disable icon pixmap hint */
405 item
->wmhints
->icon_pixmap
= None
;
406 item
->wmhints
->flags
&= ~IconPixmapHint
;
409 item
->icon_depth
= depth
;
411 if (FShapesSupported
&& (item
->wmhints
->flags
& IconMaskHint
))
413 SET_ICON_SHAPED(item
, True
);
414 item
->icon_maskPixmap
= item
->wmhints
->icon_mask
;
417 item
->icon_w
= min(max_icon_width
, item
->icon_w
);
418 item
->icon_h
= min(max_icon_height
, item
->icon_h
);
419 if (item
->icon_w
<= 0 || item
->icon_h
<= 0)
426 item
->iconPixmap
= XCreatePixmap(dpy
, Root
,
427 item
->icon_w
, item
->icon_h
, depth
);
428 gc
= fvwmlib_XCreateGC(dpy
, item
->iconPixmap
, 0, NULL
);
429 XCopyArea(dpy
, item
->wmhints
->icon_pixmap
, item
->iconPixmap
,
430 gc
, 0, 0, item
->icon_w
, item
->icon_h
, 0, 0);
432 SET_PIXMAP_OURS(item
, False
);
433 SET_ICON_OURS(item
, True
);
436 Bool
GetBackPixmap(void)
443 FvwmPictureAttributes fpa
;
445 fpa
.mask
= FPAM_NO_ALLOC_PIXELS
| FPAM_NO_ALPHA
;
448 fpa
.mask
|= FPAM_DITHER
;
450 if (IconwinPixmapFile
== NULL
)
453 path
= PictureFindImageFile(IconwinPixmapFile
, imagePath
, R_OK
);
458 if (!PImageLoadPixmapFromFile(
459 dpy
, main_win
, path
, &tmp_pixmap
, &maskPixmap
, NULL
, &w
, &h
,
460 &icon_depth
, 0, NULL
, 0, fpa
))
464 fprintf(stderr
, "[FvwmIconBox] Problem creating pixmap from "
471 IconwinPixmap
= XCreatePixmap(dpy
, main_win
, w
, h
, Pdepth
);
472 XCopyPlane(dpy
, tmp_pixmap
, IconwinPixmap
, NormalGC
,
473 0, 0, w
, h
, 0, 0, 1);
474 XFreePixmap(dpy
, tmp_pixmap
);
478 IconwinPixmap
= tmp_pixmap
;
481 if (w
!= 0 && h
!= 0)