2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2008 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "container.h"
27 #include "e16-ecore_hints.h"
38 static Container *SelectIconboxForEwin(EWin * ewin);
40 /* Silly hack to avoid name clash warning when using -Wshadow */
43 #define IB_ANIM_TIME Conf_containers.anim_time
44 #define IB_ANIM_STEP Conf.animation.step
47 IB_Animate_Sleep(double t0, double a)
52 dt = t - t0 - a * 1e-3 * IB_ANIM_TIME;
53 dt = 1e-3 * IB_ANIM_STEP - dt;
55 usleep((unsigned long)(1e6 * dt));
59 IB_Animate_A(char iconify, EWin * ewin, EWin * ibox)
62 double a, aa, spd, t0;
63 int x, y, x1, y1, x2, y2, x3, y3, x4, y4, w, h;
64 int fx, fy, fw, fh, tx, ty, tw, th;
65 Window root = WinGetXwin(VROOT);
69 /* Window: Extents, Iconbox: Center */
80 tx = EoGetX(to) + EoGetW(to) / 2 - 2;
81 ty = EoGetY(to) + EoGetH(to) / 2 - 2;
89 fx = EoGetX(fr) + EoGetW(fr) / 2 - 2;
90 fy = EoGetY(fr) + EoGetH(fr) / 2 - 2;
96 fx += EoGetX(EoGetDesk(fr));
97 fy += EoGetY(EoGetDesk(fr));
98 tx += EoGetX(EoGetDesk(to));
99 ty += EoGetY(EoGetDesk(to));
101 gcv.subwindow_mode = IncludeInferiors;
102 gcv.function = GXxor;
104 gcv.foreground = Dpy.pixel_white;
105 if (gcv.foreground == 0)
106 gcv.foreground = Dpy.pixel_black;
107 gc = EXCreateGC(root,
108 GCFunction | GCForeground | GCSubwindowMode | GCLineWidth,
111 spd = (1. * IB_ANIM_STEP) / IB_ANIM_TIME;
114 for (a = 0.0; a < 1.0; a += spd)
118 x = (int)((fx * aa) + (tx * a));
119 y = (int)((fy * aa) + (ty * a));
120 w = (int)((fw * aa) + (tw * a));
121 h = (int)((fh * aa) + (th * a));
123 x = (2 * x + w) / 2; /* x middle */
124 y = (2 * y + h) / 2; /* y middle */
125 w /= 2; /* width/2 */
126 h /= 2; /* height/2 */
128 x1 = (int)(x + w * (1 - .5 * sin(3.14159 + a * 6.2831853072)));
129 y1 = (int)(y + h * cos(a * 6.2831853072));
130 x2 = (int)(x + w * (1 - .5 * sin(a * 6.2831853072)));
131 y2 = (int)(y - h * cos(a * 6.2831853072));
132 x3 = (int)(x - w * (1 - .5 * sin(3.14159 + a * 6.2831853072)));
133 y3 = (int)(y - h * cos(a * 6.2831853072));
134 x4 = (int)(x - w * (1 - .5 * sin(a * 6.2831853072)));
135 y4 = (int)(y + h * cos(a * 6.2831853072));
137 XDrawLine(disp, root, gc, x1, y1, x2, y2);
138 XDrawLine(disp, root, gc, x2, y2, x3, y3);
139 XDrawLine(disp, root, gc, x3, y3, x4, y4);
140 XDrawLine(disp, root, gc, x4, y4, x1, y1);
143 IB_Animate_Sleep(t0, a);
145 XDrawLine(disp, root, gc, x1, y1, x2, y2);
146 XDrawLine(disp, root, gc, x2, y2, x3, y3);
147 XDrawLine(disp, root, gc, x3, y3, x4, y4);
148 XDrawLine(disp, root, gc, x4, y4, x1, y1);
155 IB_Animate_B(char iconify, EWin * ewin, EWin * ibox)
160 int fx, fy, fw, fh, tx, ty, tw, th;
161 Window root = WinGetXwin(VROOT);
186 fx += EoGetX(EoGetDesk(fr));
187 fy += EoGetY(EoGetDesk(fr));
188 tx += EoGetX(EoGetDesk(to));
189 ty += EoGetY(EoGetDesk(to));
191 gcv.subwindow_mode = IncludeInferiors;
192 gcv.function = GXxor;
193 gcv.fill_style = FillOpaqueStippled;
194 gcv.foreground = Dpy.pixel_white;
195 if (gcv.foreground == 0)
196 gcv.foreground = Dpy.pixel_black;
197 gc = EXCreateGC(root,
198 GCFunction | GCForeground | GCSubwindowMode | GCFillStyle,
201 XDrawLine(disp, root, gc, fx, fy, tx, ty);
202 XDrawLine(disp, root, gc, fx + fw, fy, tx + tw, ty);
203 XDrawLine(disp, root, gc, fx, fy + fh, tx, ty + th);
204 XDrawLine(disp, root, gc, fx + fw, fy + fh, tx + tw, ty + th);
205 XDrawRectangle(disp, root, gc, tx, ty, tw, th);
206 XDrawRectangle(disp, root, gc, fx, fy, fw, fh);
208 spd = (1. * IB_ANIM_STEP) / IB_ANIM_TIME;
211 for (a = 0.0; a < 1.0; a += spd)
213 x = (int)(fx + a * (tx - fx));
214 w = (int)(fw + a * (tw - fw));
215 y = (int)(fy + a * (ty - fy));
216 h = (int)(fh + a * (th - fh));
217 XDrawRectangle(disp, root, gc, x, y, w, h);
220 IB_Animate_Sleep(t0, a);
222 XDrawRectangle(disp, root, gc, x, y, w, h);
225 XDrawLine(disp, root, gc, fx, fy, tx, ty);
226 XDrawLine(disp, root, gc, fx + fw, fy, tx + tw, ty);
227 XDrawLine(disp, root, gc, fx, fy + fh, tx, ty + th);
228 XDrawLine(disp, root, gc, fx + fw, fy + fh, tx + tw, ty + th);
229 XDrawRectangle(disp, root, gc, tx, ty, tw, th);
230 XDrawRectangle(disp, root, gc, fx, fy, fw, fh);
236 IB_Animate(Container * ct, int iconify, EWin * ewin)
238 if (Mode.wm.startup || ct->anim_mode <= 0)
241 if (Conf_containers.anim_time < 10 || Conf_containers.anim_time > 10000)
242 Conf_containers.anim_time = 250;
247 switch (ct->anim_mode)
252 IB_Animate_A(iconify, ewin, ct->ewin);
255 IB_Animate_B(iconify, ewin, ct->ewin);
263 IconboxObjEwinFind(Container * ct, EWin * ewin)
265 return ContainerObjectFind(ct, ewin);
269 IconboxObjEwinAdd(Container * ct, EWin * ewin)
273 i = ContainerObjectAdd(ct, ewin);
277 ct->objs[i].im = EwinIconImageGet(ewin, ct->iconsize, ct->icon_mode);
282 IconboxObjEwinDel(Container * ct, EWin * ewin)
286 i = IconboxObjEwinFind(ct, ewin);
291 EImageFree(ct->objs[i].im);
293 ContainerObjectDel(ct, ewin);
297 IconboxesEwinIconify(EWin * ewin)
301 ct = SelectIconboxForEwin(ewin);
305 SoundPlay(SOUND_ICONIFY);
307 if (EoIsShown(ewin) && ct->anim_mode && !ewin->state.showingdesk)
308 IB_Animate(ct, 1, ewin);
310 IconboxObjEwinAdd(ct, ewin);
314 IconboxesEwinDeIconify(EWin * ewin)
318 ct = SelectIconboxForEwin(ewin);
322 SoundPlay(SOUND_DEICONIFY);
324 if (ct->anim_mode && !ewin->state.showingdesk)
325 IB_Animate(ct, 0, ewin);
327 IconboxObjEwinDel(ct, ewin);
333 RemoveMiniIcon(EWin * ewin)
337 ct = SelectIconboxForEwin(ewin);
341 IconboxObjEwinDel(ct, ewin);
346 IconboxFindEwin(Container * ct, void *data)
348 EWin *ewin = (EWin *) data;
350 return IconboxObjEwinFind(ct, ewin) >= 0;
355 SelectIconboxForEwin(EWin * ewin)
357 /* find the appropriate iconbox from all available ones for this app */
358 /* if it is to be iconified, or if it is alreayd return which iconbox */
360 Container *ct, *ib_sel = NULL;
365 if (ewin->state.iconified)
367 /* find the iconbox this window got iconifed into */
368 ib_sel = ContainersIterate(IconboxFindEwin, IB_TYPE_ICONBOX, ewin);
372 /* pick the closest iconbox physically on screen to put it in */
378 lst = ContainersGetList(&num);
379 min_dist = 0x7fffffff;
380 for (i = 0; i < num; i++)
383 if (ct->ewin == NULL || ct->type != IB_TYPE_ICONBOX)
386 dx = (EoGetX(ct->ewin) + (EoGetW(ct->ewin) / 2)) -
387 (EoGetX(ewin) + (EoGetW(ewin) / 2));
388 dy = (EoGetY(ct->ewin) + (EoGetH(ct->ewin) / 2)) -
389 (EoGetY(ewin) + (EoGetH(ewin) / 2));
390 dist = (dx * dx) + (dy * dy);
391 if ((!EoIsSticky(ct->ewin)) &&
392 (EoGetDesk(ct->ewin) != EoGetDesk(ewin)))
393 dist += (WinGetW(VROOT) * WinGetW(VROOT)) +
394 (WinGetH(VROOT) * WinGetH(VROOT));
408 IconboxUpdateEwinIcon(Container * ct, EWin * ewin, int icon_mode)
412 if (ct->icon_mode != icon_mode)
415 i = IconboxObjEwinFind(ct, ewin);
420 EImageFree(ct->objs[i].im);
421 ct->objs[i].im = EwinIconImageGet(ewin, ct->iconsize, icon_mode);
427 IconboxesUpdateEwinIcon(EWin * ewin, int icon_mode)
430 Container **lst, *ct;
432 lst = ContainersGetList(&num);
433 for (i = 0; i < num; i++)
436 IconboxUpdateEwinIcon(ct, ewin, icon_mode);
442 IconboxFindIconSize(EImage * im, int *pw, int *ph, int size)
444 int w, h, minsz, maxwh;
446 EImageGetSize(im, &w, &h);
448 maxwh = (w > h) ? w : h;
452 minsz = (size * 3) / 4;
454 if (maxwh < minsz || maxwh > size)
456 w = (w * size) / maxwh;
457 h = (h * size) / maxwh;
466 IconboxInit(Container * ct)
468 ct->wm_name = "Iconbox";
469 ct->menu_title = _("Iconbox Options");
470 ct->dlg_title = _("Iconbox Settings");
476 IconboxExit(Container * ct, int wm_exit)
481 EwinDeIconify((EWin *) ct->objs[0].obj);
482 IconboxObjEwinDel(ct, (EWin *) ct->objs[0].obj);
487 IconboxSighan(Container * ct __UNUSED__, int sig, void *prm)
493 case ESIGNAL_EWIN_ICONIFY:
495 IconboxesEwinIconify(ewin);
497 case ESIGNAL_EWIN_DEICONIFY:
499 IconboxesEwinDeIconify(ewin);
501 case ESIGNAL_EWIN_DESTROY:
503 if (ewin->state.iconified)
504 RemoveMiniIcon(ewin);
506 case ESIGNAL_EWIN_CHANGE_ICON:
508 if (ewin->state.iconified)
509 IconboxesUpdateEwinIcon(ewin, 1);
515 IconboxEvent(Container * ct, XEvent * ev)
517 static EWin *name_ewin = NULL;
526 if (ev->xbutton.button == 1)
527 ct->icon_clicked = 1;
531 if (!ct->icon_clicked)
533 ct->icon_clicked = 0;
536 (EWin *) ContainerObjectFindByXY(ct, ev->xbutton.x, ev->xbutton.y);
540 tt = TooltipFind("ICONBOX");
544 EwinOpIconify(ewin, OPSRC_USER, 0);
561 ewin = (EWin *) ContainerObjectFindByXY(ct, x, y);
562 if (ewin == name_ewin)
566 tt = TooltipFind("ICONBOX");
574 name = EwinGetIconName(ewin);
576 TooltipShow(tt, name, NULL, Mode.events.cx, Mode.events.cy);
580 tt = TooltipFind("ICONBOX");
591 IconboxObjSizeCalc(Container * ct, ContainerObject * cto)
594 cto->wi = cto->hi = 8;
596 IconboxFindIconSize(cto->im, &cto->wi, &cto->hi, ct->iconsize);
600 IconboxObjPlace(Container * ct __UNUSED__, ContainerObject * cto, EImage * im)
607 EImageGetSize(cto->im, &w, &h);
608 EImageBlend(im, cto->im, EIMAGE_BLEND | EIMAGE_ANTI_ALIAS, 0, 0, w, h,
609 cto->xi, cto->yi, cto->wi, cto->hi, 1);
612 extern const ContainerOps IconboxOps;
613 const ContainerOps IconboxOps = {