NEWS/Changelog for previous commit.
[fvwm.git] / modules / FvwmIconBox / icons.c
blob9797215319ade11921e21103d157fcae4dc9f53c
1 /* -*-c-*- */
2 /*
3 * icons.c
4 * Based on icons.c of GoodStuff:
5 * Copyright 1993, Robert Nation.
6 */
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
34 #include "config.h"
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <signal.h>
40 #include <X11/Xlib.h>
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"
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
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;
62 extern char *MyName;
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,
94 &attributes);
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)
101 return;
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)
112 GetIconWindow(item);
113 else if (item->wmhints->flags & IconPixmapHint)
114 GetIconBitmap(item);
117 /* if that all fails get the default */
118 if ((item->icon_file != NULL) && (item->icon_h == 0) &&
119 (item->icon_w == 0))
121 GetIconFromFile(item);
124 if ((item->icon_h == 0) && (item->icon_w == 0))
126 return;
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,
141 &attributes);
143 else
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,
150 Pdepth,
151 InputOutput,
152 Pvisual, valuemask,
153 &attributes);
155 XSelectInput(dpy, item->icon_pixmap_w, ICON_EVENTS);
158 if (FShapesSupported && item->icon_maskPixmap != None)
160 int hr;
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) +
189 Ffont->height;
191 switch (primary) {
192 case LEFT:
193 case RIGHT:
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;
203 if (primary == LEFT)
205 x = (n % Lines)*(w + interval) + interval;
207 else
209 x = icon_win_width - (n % Lines + 1)*(w + interval);
211 break;
212 case TOP:
213 case BOTTOM:
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;
223 if (primary == TOP)
225 y = (n % Lines)*(h + interval) + interval;
227 else
229 y = icon_win_height - (n % Lines + 1)*(h + interval);
231 break;
232 default:
233 break;
236 item->x = x;
237 item->y = y;
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,
249 w3 - r, h3 - r);
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;
264 if (NULL == path)
266 fprintf(stderr, "[FvwmIconBox] cannot find %s on ImagePath %s\n",
267 item->icon_file, imagePath);
268 return;
270 fpa.mask = 0;
271 if (Iconcolorset >= 0 && Colorset[Iconcolorset].do_dither_icon)
273 fpa.mask |= FPAM_DITHER;
275 item->icon_w = 0;
276 item->icon_h = 0;
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 "
285 "file '%s'\n",path);
286 item->icon_w = 0;
287 item->icon_h = 0;
288 return;
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);
294 free(path);
295 return;
300 * Looks for an application supplied icon window
303 void GetIconWindow(struct icon_info *item)
305 int x, y;
306 unsigned int bw;
307 Window Junkroot;
309 if (!XGetGeometry(
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))
314 #if 0
315 fprintf(stderr, "[%s][GetIconWindow] WARN -- '%s' has an "
316 "invalid icon window hint\n", MyName, item->name);
317 #endif
318 /* disable the icon window hint */
319 item->icon_w = 0;
320 item->icon_h = 0;
321 item->wmhints->icon_window = None;
322 item->wmhints->flags &= ~IconWindowHint;
323 return;
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);
337 MyXGrabServer(dpy);
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);
342 XSync(dpy, 0);
343 do_allow_bad_access = False;
344 if (was_bad_access)
346 /* give up */
347 #if 0
348 fprintf(stderr, "[%s][GetIconWindow] WARN -- BadAcces when "
349 "reparenting %s icon window\n", MyName, item->name);
350 #endif
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;
359 item->icon_w = 0;
360 item->icon_h = 0;
361 was_bad_access = False;
362 return;
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)
376 int x, y;
377 unsigned int bw, depth;
378 Window Junkroot;
379 GC gc;
381 item->icon_file = NULL;
382 item->icon_maskPixmap = None;
383 item->icon_alphaPixmap = None;
384 item->iconPixmap = None;
385 item->icon_w = 0;
386 item->icon_h = 0;
387 if (!XGetGeometry(
388 dpy, item->wmhints->icon_pixmap, &Junkroot, &x, &y,
389 (unsigned int *)&item->icon_w, (unsigned int *)&item->icon_h,
390 &bw, &depth))
392 /* disable icon pixmap hint */
393 item->icon_w = 0;
394 item->icon_h = 0;
395 item->wmhints->icon_pixmap = None;
396 item->wmhints->flags &= ~IconPixmapHint;
397 return;
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 */
403 item->icon_w = 0;
404 item->icon_h = 0;
405 item->wmhints->icon_pixmap = None;
406 item->wmhints->flags &= ~IconPixmapHint;
407 return;
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)
421 item->icon_w = 0;
422 item->icon_h = 0;
423 return;
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);
431 XFreeGC(dpy, gc);
432 SET_PIXMAP_OURS(item, False);
433 SET_ICON_OURS(item, True);
436 Bool GetBackPixmap(void)
438 Pixmap maskPixmap;
439 char *path = NULL;
440 Pixmap tmp_pixmap;
441 int w=0, h=0;
442 int icon_depth = 0;
443 FvwmPictureAttributes fpa;
445 fpa.mask = FPAM_NO_ALLOC_PIXELS | FPAM_NO_ALPHA;
446 if (Pdepth <= 8)
448 fpa.mask |= FPAM_DITHER;
450 if (IconwinPixmapFile == NULL)
451 return False;
453 path = PictureFindImageFile(IconwinPixmapFile, imagePath, R_OK);
454 if (path == NULL)
456 return False;
458 if (!PImageLoadPixmapFromFile(
459 dpy, main_win, path, &tmp_pixmap, &maskPixmap, NULL, &w, &h,
460 &icon_depth, 0, NULL, 0, fpa))
462 w = 0;
463 h = 0;
464 fprintf(stderr, "[FvwmIconBox] Problem creating pixmap from "
465 "file: %s\n", path);
466 free(path);
467 return False;
469 if (icon_depth == 1)
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);
476 else
478 IconwinPixmap = tmp_pixmap;
480 free(path);
481 if (w != 0 && h != 0)
482 return True;
483 return False;