2 /* Copyright (C) 2001 Olivier Chapuis */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "libs/fvwmlib.h"
23 #include "libs/FShape.h"
24 #include "libs/PictureBase.h"
25 #include "libs/Picture.h"
26 #include "libs/PictureUtils.h"
27 #include "libs/PictureImageLoader.h"
28 #include "libs/FRenderInit.h"
29 #include "libs/Graphics.h"
30 #include "libs/Strings.h"
33 #include "window_flags.h"
35 #include "functions.h"
38 #include "module_interface.h"
42 #include "ewmh_intern.h"
47 int ewmh_WMIcon(EWMH_CMD_ARGS
)
50 CARD32
*new_list
= NULL
;
54 if (ev
!= NULL
&& HAS_EWMH_WM_ICON_HINT(fw
) == EWMH_FVWM_ICON
)
56 /* this event has been produced by fvwm itself */
60 list
= ewmh_AtomGetByName(FW_W(fw
),"_NET_WM_ICON",
61 EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &size
);
63 if (list
!= NULL
&& HAS_EWMH_WM_ICON_HINT(fw
) == EWMH_NO_ICON
)
65 /* the application have a true _NET_WM_ICON */
66 SET_HAS_EWMH_WM_ICON_HINT(fw
, EWMH_TRUE_ICON
);
69 if (list
== NULL
|| HAS_EWMH_WM_ICON_HINT(fw
) != EWMH_TRUE_ICON
)
71 /* No net icon or we have set the net icon */
72 if (DO_EWMH_DONATE_ICON(fw
) &&
74 ewmh_SetWmIconFromPixmap(
75 fw
, list
, &size
, False
)) != NULL
)
77 SET_HAS_EWMH_WM_ICON_HINT(fw
, EWMH_FVWM_ICON
);
80 else if (ev
!= NULL
&& USE_EWMH_ICON(fw
))
82 /* client message. the application change its net icon */
85 if (FMiniIconsSupported
)
88 HAS_EWMH_WM_ICON_HINT(fw
) != EWMH_TRUE_ICON
)
90 /* No net icon or we have set the net icon */
91 if (DO_EWMH_DONATE_MINI_ICON(fw
) &&
92 (dummy
= ewmh_SetWmIconFromPixmap(
93 fw
, (new_list
!= NULL
)? new_list
: list
,
94 &size
, True
)) != NULL
)
96 SET_HAS_EWMH_WM_ICON_HINT(
103 /* the application has a true ewmh icon */
104 if (EWMH_SetIconFromWMIcon(fw
, list
, size
, True
))
106 SET_HAS_EWMH_MINI_ICON(fw
, True
);
115 if (new_list
!= NULL
)
125 void EWMH_DoUpdateWmIcon(FvwmWindow
*fw
, Bool mini_icon
, Bool icon
)
128 CARD32
*new_list
= NULL
;
129 CARD32
*dummy
= NULL
;
131 Bool icon_too
= False
;
133 if (HAS_EWMH_WM_ICON_HINT(fw
) == EWMH_TRUE_ICON
)
138 /* first see if we have to delete */
139 if (FMiniIconsSupported
&& mini_icon
&&
140 !DO_EWMH_DONATE_MINI_ICON(fw
))
142 if (icon
&& !DO_EWMH_DONATE_ICON(fw
))
146 EWMH_DeleteWmIcon(fw
, True
, icon_too
);
148 if (!icon_too
&& icon
&& !DO_EWMH_DONATE_ICON(fw
))
150 EWMH_DeleteWmIcon(fw
, False
, True
);
153 /* now set if needed */
154 if ((mini_icon
&& DO_EWMH_DONATE_MINI_ICON(fw
)) ||
155 (icon
&& DO_EWMH_DONATE_ICON(fw
)))
157 list
= ewmh_AtomGetByName(
158 FW_W(fw
),"_NET_WM_ICON",
159 EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &size
);
166 /* we have to reset */
167 if (icon
&& DO_EWMH_DONATE_ICON(fw
))
169 if ((new_list
= ewmh_SetWmIconFromPixmap(
170 fw
, list
, &size
, False
)) != NULL
)
172 SET_HAS_EWMH_WM_ICON_HINT(fw
, EWMH_FVWM_ICON
);
175 if (FMiniIconsSupported
&& mini_icon
&& DO_EWMH_DONATE_MINI_ICON(fw
))
177 if ((dummy
= ewmh_SetWmIconFromPixmap(
178 fw
, (new_list
!= NULL
)? new_list
: list
, &size
,
181 SET_HAS_EWMH_WM_ICON_HINT(fw
, EWMH_FVWM_ICON
);
189 if (new_list
!= NULL
)
196 * build and set a net icon from a pixmap
198 CARD32
*ewmh_SetWmIconFromPixmap(
199 FvwmWindow
*fw
, CARD32
*orig_icon
, int *orig_size
, Bool is_mini_icon
)
201 CARD32
*new_icon
= NULL
;
202 int keep_start
= 0, keep_length
= 0;
203 int width
= 0, height
= 0;
206 Pixmap pixmap
= None
;
210 XImage
*m_image
= NULL
;
211 XImage
*a_image
= NULL
;
212 int save_picture_w_g_width
= 0;
213 int save_picture_w_g_height
= 0;
214 int save_icon_depth
= 0;
215 Pixmap save_icon_pixmap
= None
;
216 Pixmap save_icon_mask
= None
;
217 Pixmap save_icon_alpha
= None
;
218 int save_icon_nalloc_pixels
= 0;
219 Pixel
*save_icon_alloc_pixels
= NULL
;
220 int save_icon_no_limit
= 0;
221 Window save_icon_pixmap_w
= None
;
222 Bool is_pixmap_ours
= False
;
223 Bool is_icon_ours
= False
;
224 Bool is_icon_shaped
= False
;
225 Bool destroy_icon_pix
= False
;
227 s
= *orig_size
/ sizeof(CARD32
);
232 if (FMiniIconsSupported
&& fw
->mini_icon
!= NULL
)
234 pixmap
= fw
->mini_icon
->picture
;
235 mask
= fw
->mini_icon
->mask
;
236 alpha
= fw
->mini_icon
->alpha
;
237 width
= fw
->mini_icon
->width
;
238 height
= fw
->mini_icon
->height
;
243 /* should save and restore any iformation modified by
244 * a call to GetIconPicture */
245 save_picture_w_g_width
= fw
->icon_g
.picture_w_g
.width
;
246 save_picture_w_g_height
= fw
->icon_g
.picture_w_g
.height
;
247 save_icon_depth
= fw
->iconDepth
;
248 save_icon_pixmap
= fw
->iconPixmap
;
249 save_icon_mask
= fw
->icon_maskPixmap
;
250 save_icon_alpha
= fw
->icon_alphaPixmap
;
251 save_icon_nalloc_pixels
= fw
->icon_nalloc_pixels
;
252 save_icon_alloc_pixels
= fw
->icon_alloc_pixels
;
253 save_icon_no_limit
= fw
->icon_no_limit
;
254 save_icon_pixmap_w
= FW_W_ICON_PIXMAP(fw
);
255 is_pixmap_ours
= IS_PIXMAP_OURS(fw
);
256 is_icon_ours
= IS_ICON_OURS(fw
);
257 is_icon_shaped
= IS_ICON_SHAPED(fw
);
258 GetIconPicture(fw
, True
);
259 if (IS_PIXMAP_OURS(fw
))
261 destroy_icon_pix
= True
;
263 pixmap
= fw
->iconPixmap
;
264 mask
= fw
->icon_maskPixmap
;
265 alpha
= fw
->icon_alphaPixmap
;
266 width
= fw
->icon_g
.picture_w_g
.width
;
267 height
= fw
->icon_g
.picture_w_g
.height
;
268 if (fw
->icon_alloc_pixels
!= NULL
)
270 if (fw
->icon_nalloc_pixels
!= 0)
273 dpy
, Pcmap
, fw
->icon_alloc_pixels
,
274 fw
->icon_nalloc_pixels
, 0,
277 free(fw
->icon_alloc_pixels
);
280 fw
->icon_g
.picture_w_g
.width
= save_picture_w_g_width
;
281 fw
->icon_g
.picture_w_g
.height
= save_picture_w_g_height
;
282 fw
->iconDepth
= save_icon_depth
;
283 fw
->iconPixmap
= save_icon_pixmap
;
284 fw
->icon_maskPixmap
= save_icon_mask
;
285 fw
->icon_alphaPixmap
= save_icon_alpha
;
286 fw
->icon_nalloc_pixels
= save_icon_nalloc_pixels
;
287 fw
->icon_alloc_pixels
= save_icon_alloc_pixels
;
288 fw
->icon_no_limit
= save_icon_no_limit
;
289 FW_W_ICON_PIXMAP(fw
) = save_icon_pixmap_w
;
290 SET_ICON_OURS(fw
, is_icon_ours
);
291 SET_PIXMAP_OURS(fw
, is_pixmap_ours
);
292 SET_ICON_SHAPED(fw
, is_icon_shaped
);
300 if (FMiniIconsSupported
&& orig_icon
!= NULL
)
302 int k_width
= (is_mini_icon
)?
303 fw
->ewmh_icon_width
: fw
->ewmh_mini_icon_width
;
304 int k_height
= (is_mini_icon
)?
305 fw
->ewmh_icon_height
: fw
->ewmh_mini_icon_height
;
307 for (i
= 0; i
< s
- 1 && i
>= 0; )
309 if (i
+ 1 + orig_icon
[i
]*orig_icon
[i
+1] < s
)
311 if (orig_icon
[i
] == k_width
&&
312 orig_icon
[i
+1] == k_height
)
316 orig_icon
[i
] * orig_icon
[i
+1];
320 if (i
!= s
&& orig_icon
[i
]*orig_icon
[i
+1] > 0)
322 i
= i
+ 2 + orig_icon
[i
]*orig_icon
[i
+1];
332 dpy
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
336 ERR
, "EWMH_SetWmIconFromPixmap",
337 "cannot create XImage\n");
338 if (destroy_icon_pix
)
340 XFreePixmap(dpy
, pixmap
);
343 XFreePixmap(dpy
, mask
);
347 XFreePixmap(dpy
, alpha
);
355 m_image
= XGetImage(dpy
, mask
, 0, 0, width
, height
,
360 a_image
= XGetImage(dpy
, alpha
, 0, 0, width
, height
,
363 *orig_size
= (height
*width
+ 2 + keep_length
) * sizeof(CARD32
);
364 new_icon
= (CARD32
*)safemalloc(*orig_size
);
367 memcpy(new_icon
, &orig_icon
[keep_start
],
368 keep_length
* sizeof(CARD32
));
370 new_icon
[keep_length
] = width
;
371 new_icon
[1+keep_length
] = height
;
374 l
= (2 + keep_length
);
384 colors
[0].pixel
= fw
->colors
.fore
;
385 colors
[1].pixel
= fw
->colors
.back
;
386 XQueryColors(dpy
, Pcmap
, colors
, 2);
387 fg
= 0xff000000 + (((colors
[0].red
>> 8) & 0xff) << 16) +
388 (((colors
[0].green
>> 8) & 0xff) << 8) +
389 ((colors
[0].blue
>> 8) & 0xff);
390 bg
= 0xff000000 + (((colors
[1].red
>> 8) & 0xff) << 16) +
391 (((colors
[1].green
>> 8) & 0xff) << 8) +
392 ((colors
[1].blue
>> 8) & 0xff);
393 for (j
= 0; j
< height
; j
++)
395 for (i
= 0; i
< width
; i
++)
397 if (m_image
!= NULL
&&
398 (XGetPixel(m_image
, i
, j
) == 0))
402 else if (XGetPixel(image
, i
, j
) == 0)
415 default: /* depth = Pdepth */
420 colors
= (XColor
*)safemalloc(width
* height
* sizeof(XColor
));
421 cm
= (unsigned char *)safemalloc(
422 width
* height
* sizeof(char));
423 for (j
= 0; j
< height
; j
++)
425 for (i
= 0; i
< width
; i
++)
427 if (m_image
!= NULL
&&
428 (XGetPixel(m_image
, i
, j
) == 0))
432 else if (a_image
!= NULL
)
434 cm
[m
++] = (unsigned char)XGetPixel(
436 colors
[k
++].pixel
= XGetPixel(
442 colors
[k
++].pixel
= XGetPixel(
447 for (i
= 0; i
< k
; i
+= 256)
448 XQueryColors(dpy
, Pcmap
, &colors
[i
], min(k
- i
, 256));
451 for (j
= 0; j
< height
; j
++)
453 for (i
= 0; i
< width
; i
++)
458 ((cm
[m
] & 0xff) << 24) +
459 (((colors
[k
].red
>> 8) & 0xff)
461 (((colors
[k
].green
>> 8) &
463 ((colors
[k
].blue
>> 8) & 0xff);
482 fw
->ewmh_mini_icon_width
= width
;
483 fw
->ewmh_mini_icon_height
= height
;
487 fw
->ewmh_icon_width
= width
;
488 fw
->ewmh_icon_height
= height
;
492 FW_W(fw
), "_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY
,
493 (unsigned char *)new_icon
, height
*width
+ 2 + keep_length
);
495 if (destroy_icon_pix
)
497 XFreePixmap(dpy
, pixmap
);
500 XFreePixmap(dpy
, mask
);
504 XFreePixmap(dpy
, alpha
);
508 XDestroyImage(image
);
511 XDestroyImage(m_image
);
515 XDestroyImage(a_image
);
522 * delete the mini icon and/or the icon from a ewmh icon
524 void EWMH_DeleteWmIcon(FvwmWindow
*fw
, Bool mini_icon
, Bool icon
)
527 CARD32
*new_list
= NULL
;
528 int keep_start
= 0, keep_length
= 0;
532 if (mini_icon
&& icon
)
535 FW_W(fw
), "_NET_WM_ICON",
536 EWMH_ATOM_LIST_PROPERTY_NOTIFY
);
537 fw
->ewmh_mini_icon_width
= 0;
538 fw
->ewmh_mini_icon_height
= 0;
539 fw
->ewmh_icon_width
= 0;
540 fw
->ewmh_icon_height
= 0;
541 /*SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_NO_ICON);*/
545 list
= ewmh_AtomGetByName(
546 FW_W(fw
),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &s
);
551 s
= s
/ sizeof(CARD32
);
553 if (FMiniIconsSupported
&& list
!= NULL
)
555 int k_width
= (mini_icon
) ? fw
->ewmh_icon_width
:
556 fw
->ewmh_mini_icon_width
;
557 int k_height
= (mini_icon
) ? fw
->ewmh_icon_height
:
558 fw
->ewmh_mini_icon_height
;
560 for (i
= 0; i
< s
- 1; )
562 if (i
+ 1 + list
[i
]*list
[i
+1] < s
)
564 if (list
[i
] == k_width
&&
565 list
[i
+1] == k_height
)
568 keep_length
= 2 + list
[i
]*list
[i
+1];
572 if (i
!= s
&& list
[i
]*list
[i
+1] > 0)
574 i
= i
+ 2 + list
[i
]*list
[i
+1];
585 new_list
= (CARD32
*)safemalloc(keep_length
* sizeof(CARD32
));
587 new_list
, &list
[keep_start
],
588 keep_length
* sizeof(CARD32
));
591 if (new_list
!= NULL
)
594 FW_W(fw
),"_NET_WM_ICON",
595 EWMH_ATOM_LIST_PROPERTY_NOTIFY
,
596 (unsigned char *)new_list
, keep_length
);
600 /*SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_NO_ICON);*/
602 FW_W(fw
), "_NET_WM_ICON",
603 EWMH_ATOM_LIST_PROPERTY_NOTIFY
);
608 fw
->ewmh_mini_icon_width
= 0;
609 fw
->ewmh_mini_icon_height
= 0;
613 fw
->ewmh_icon_width
= 0;
614 fw
->ewmh_icon_height
= 0;
616 if (new_list
!= NULL
)
624 * Create an x image from a NET icon
627 #define SQUARE(X) ((X)*(X))
629 void extract_wm_icon(
630 CARD32
*list
, int size
, int wanted_w
, int wanted_h
,
631 int *start_best
, int *best_w
, int *best_h
)
639 size
= size
/ (sizeof(CARD32
));
641 for (i
= 0; i
< size
- 1; )
643 if (i
+ 1 + list
[i
]*list
[i
+1] < size
)
645 if (*best_w
== 0 && *best_h
== 0)
652 SQUARE(list
[i
+1]-wanted_h
);
654 else if (SQUARE(list
[i
]-wanted_w
) +
655 SQUARE(list
[i
+1]-wanted_h
) < dist
)
662 SQUARE(list
[i
+1]-wanted_h
);
665 if (list
[i
]*list
[i
+1] > 0)
667 i
= i
+ 2 + list
[i
]*list
[i
+1];
678 #define MINI_ICON_WANTED_WIDTH 16
679 #define MINI_ICON_WANTED_HEIGHT 16
680 #define MINI_ICON_MAX_WIDTH 22
681 #define MINI_ICON_MAX_HEIGHT 22
682 #define ICON_WANTED_WIDTH 56
683 #define ICON_WANTED_HEIGHT 56
684 #define ICON_MAX_WIDTH 100
685 #define ICON_MAX_HEIGHT 100
687 int EWMH_SetIconFromWMIcon(
688 FvwmWindow
*fw
, CARD32
*list
, int size
, Bool is_mini_icon
)
690 int start
, width
, height
;
691 int wanted_w
, wanted_h
;
693 Pixmap pixmap
= None
;
696 Bool free_list
= False
;
700 FvwmPictureAttributes fpa
;
704 /* we are called from icons.c or update.c */
705 list
= ewmh_AtomGetByName(
706 FW_W(fw
),"_NET_WM_ICON",
707 EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &size
);
717 wanted_w
= MINI_ICON_WANTED_WIDTH
;
718 wanted_h
= MINI_ICON_WANTED_HEIGHT
;
719 max_w
= MINI_ICON_MAX_WIDTH
;
720 max_h
= ICON_MAX_HEIGHT
;
725 wanted_w
= ICON_WANTED_WIDTH
;
726 wanted_h
= ICON_WANTED_HEIGHT
;
727 max_w
= ICON_MAX_WIDTH
;
728 max_h
= ICON_MAX_HEIGHT
;
729 if (fw
->cs
>= 0 && Colorset
[fw
->cs
].do_dither_icon
)
731 fpa
.mask
= FPAM_DITHER
;
740 list
, size
, wanted_w
, wanted_h
, &start
, &width
, &height
);
741 if (width
== 0 || height
== 0)
750 if (!PImageCreatePixmapFromArgbData(
751 dpy
, Scr
.NoFocusWin
, list
, start
, width
, height
,
752 &pixmap
, &mask
, &alpha
, &nalloc_pixels
,
753 &alloc_pixels
, &no_limit
, fpa
))
755 fvwm_msg(ERR
, "EWMH_SetIconFromWMIcon",
756 "fail to create a pixmap\n");
764 if (width
> max_w
|| height
> max_h
)
766 Pixmap np
= None
,nm
=None
, na
= None
;
770 np
= CreateStretchPixmap(
771 dpy
, pixmap
, width
, height
, Pdepth
, wanted_w
,
772 wanted_h
, Scr
.TitleGC
);
773 XFreePixmap(dpy
, pixmap
);
778 nm
= CreateStretchPixmap(
779 dpy
, mask
, width
, height
, 1, wanted_w
,
780 wanted_h
, Scr
.MonoGC
);
781 XFreePixmap(dpy
, mask
);
786 na
= CreateStretchPixmap(
787 dpy
, alpha
, width
, height
,
788 FRenderGetAlphaDepth(), wanted_w
, wanted_h
,
790 XFreePixmap(dpy
, alpha
);
796 if (FMiniIconsSupported
&& is_mini_icon
&&
797 !DO_EWMH_MINI_ICON_OVERRIDE(fw
))
801 CopyString(&name
,"ewmh_mini_icon");
804 PDestroyFvwmPicture(dpy
,fw
->mini_icon
);
807 fw
->mini_icon
= PCacheFvwmPictureFromPixmap(
808 dpy
, Scr
.NoFocusWin
, name
, pixmap
,mask
,alpha
, width
,
809 height
, nalloc_pixels
, alloc_pixels
, no_limit
);
810 if (fw
->mini_icon
!= NULL
)
812 fw
->mini_pixmap_file
= name
;
813 BroadcastFvwmPicture(
814 M_MINI_ICON
, FW_W(fw
), FW_W_FRAME(fw
),
815 (unsigned long)fw
, fw
->mini_icon
,
816 fw
->mini_pixmap_file
);
817 border_redraw_decorations(fw
);
822 fw
->iconPixmap
= pixmap
;
823 fw
->icon_maskPixmap
= mask
;
824 fw
->icon_alphaPixmap
= alpha
;
825 fw
->icon_nalloc_pixels
= nalloc_pixels
;
826 fw
->icon_alloc_pixels
= alloc_pixels
;
827 fw
->icon_no_limit
= no_limit
;
828 fw
->icon_g
.picture_w_g
.width
= width
;
829 fw
->icon_g
.picture_w_g
.height
= height
;
830 fw
->iconDepth
= Pdepth
;
831 SET_PIXMAP_OURS(fw
, 1);
832 if (FShapesSupported
&& mask
)
834 SET_ICON_SHAPED(fw
, 1);