2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 * Copyright (c) 1998-2003 Dan Pascu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 #include <X11/Xutil.h>
35 #include "WindowMaker.h"
38 #include "superfluous.h"
44 extern WPreferences wPreferences;
46 #ifdef NORMAL_ICON_KABOOM
47 void DoKaboom(WScreen * scr, Window win, int x, int y)
50 int sw = scr->scr_width, sh = scr->scr_height;
51 #define KAB_PRECISION 4
54 char pvx[PIECES], pvy[PIECES];
55 /* in MkLinux/PPC gcc seems to think that char is unsigned? */
56 signed char ax[PIECES], ay[PIECES];
59 XSetClipMask(dpy, scr->copy_gc, None);
60 tmp = XCreatePixmap(dpy, scr->root_win, wPreferences.icon_size, wPreferences.icon_size, scr->depth);
61 if (scr->w_visual == DefaultVisual(dpy, scr->screen))
62 XCopyArea(dpy, win, tmp, scr->copy_gc, 0, 0, wPreferences.icon_size, wPreferences.icon_size, 0, 0);
66 image = XGetImage(dpy, win, 0, 0, wPreferences.icon_size,
67 wPreferences.icon_size, AllPlanes, ZPixmap);
69 XUnmapWindow(dpy, win);
72 XPutImage(dpy, tmp, scr->copy_gc, image, 0, 0, 0, 0,
73 wPreferences.icon_size, wPreferences.icon_size);
77 for (i = 0, k = 0; i < wPreferences.icon_size / ICON_KABOOM_PIECE_SIZE && k < PIECES; i++) {
78 for (j = 0; j < wPreferences.icon_size / ICON_KABOOM_PIECE_SIZE && k < PIECES; j++) {
82 px[k] = (x + i * ICON_KABOOM_PIECE_SIZE) << KAB_PRECISION;
83 py[k] = y + j * ICON_KABOOM_PIECE_SIZE;
84 pvx[k] = rand() % (1 << (KAB_PRECISION + 3)) - (1 << (KAB_PRECISION + 3)) / 2;
85 pvy[k] = -15 - rand() % 7;
93 XUnmapWindow(dpy, win);
99 if (XCheckTypedEvent(dpy, ButtonPress, &foo)) {
100 XPutBackEvent(dpy, &foo);
101 XClearWindow(dpy, scr->root_win);
105 for (i = 0; i < j; i++) {
107 int _px = px[i] >> KAB_PRECISION;
108 XClearArea(dpy, scr->root_win, _px, py[i],
109 ICON_KABOOM_PIECE_SIZE, ICON_KABOOM_PIECE_SIZE, False);
112 _px = px[i] >> KAB_PRECISION;
114 if (_px < -wPreferences.icon_size || _px > sw || py[i] >= sh) {
118 XCopyArea(dpy, tmp, scr->root_win, scr->copy_gc,
119 ax[i] * ICON_KABOOM_PIECE_SIZE, ay[i] * ICON_KABOOM_PIECE_SIZE,
120 ICON_KABOOM_PIECE_SIZE, ICON_KABOOM_PIECE_SIZE, _px, py[i]);
126 wusleep(MINIATURIZE_ANIMATION_DELAY_Z * 2);
129 XFreePixmap(dpy, tmp);
131 #endif /* NORMAL_ICON_KABOOM */
133 Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y)
135 WScreen *scr = dock->screen_ptr;
137 RImage *back, *dock_image;
139 int i, virtual_tiles, h, j, n;
140 unsigned long red_mask, green_mask, blue_mask;
143 for (i = 0; i < dock->max_icons; i++) {
144 if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > virtual_tiles)
145 virtual_tiles = dock->icon_array[i]->yindex;
148 h = virtual_tiles * wPreferences.icon_size;
149 h = (y + h > scr->scr_height) ? scr->scr_height - y : h;
150 virtual_tiles = h / wPreferences.icon_size; /* The visible ones */
151 if (h % wPreferences.icon_size)
152 virtual_tiles++; /* There is one partially visible tile at end */
154 img = XGetImage(dpy, scr->root_win, dx, y, wPreferences.icon_size, h, AllPlanes, ZPixmap);
158 red_mask = img->red_mask;
159 green_mask = img->green_mask;
160 blue_mask = img->blue_mask;
162 back = RCreateImageFromXImage(scr->rcontext, img, NULL);
168 for (i = 0; i < dock->max_icons; i++) {
169 if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex < virtual_tiles) {
171 j = dock->icon_array[i]->yindex * wPreferences.icon_size;
172 n = (h - j < wPreferences.icon_size) ? h - j : wPreferences.icon_size;
173 if (dock->icon_array[i]->icon->pixmap)
174 which = dock->icon_array[i]->icon->pixmap;
176 which = dock->icon_array[i]->icon->core->window;
178 img = XGetImage(dpy, which, 0, 0, wPreferences.icon_size, n, AllPlanes, ZPixmap);
184 img->red_mask = red_mask;
185 img->green_mask = green_mask;
186 img->blue_mask = blue_mask;
188 dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL);
194 RCombineAreaWithOpaqueness(back, dock_image, 0, 0,
195 wPreferences.icon_size, n, 0, j, 30 * 256 / 100);
196 RReleaseImage(dock_image);
200 RConvertImage(scr->rcontext, back, &pixmap);
207 Pixmap MakeGhostIcon(WScreen * scr, Drawable drawable)
216 back = RCreateImageFromDrawable(scr->rcontext, drawable, None);
225 RClearImage(back, &color);
226 RConvertImage(scr->rcontext, back, &pixmap);
233 #ifdef WINDOW_BIRTH_ZOOM
235 void DoWindowBirth(WWindow *wwin)
237 int center_x, center_y;
238 int width = wwin->frame->core->width;
239 int height = wwin->frame->core->height;
240 int w = WMIN(width, 20);
241 int h = WMIN(height, 20);
242 WScreen *scr = wwin->screen_ptr;
244 center_x = wwin->frame_x + (width - w) / 2;
245 center_y = wwin->frame_y + (height - h) / 2;
247 animateResize(scr, center_x, center_y, 1, 1, wwin->frame_x, wwin->frame_y, width, height);
250 void DoWindowBirth(WWindow *wwin)
259 #define BOUNCE_DELAY (1000/BOUNCE_HZ)
260 #define BOUNCE_HEIGHT 24
261 #define BOUNCE_LENGTH 0.3
262 #define BOUNCE_DAMP 0.6
264 typedef struct AppBouncerData {
272 static void doAppBounce(void *arg)
274 AppBouncerData *data = (AppBouncerData*)arg;
275 WAppIcon *aicon = data->wapp->app_icon;
278 if (aicon && data->wapp->refcount > 1) {
279 const double ticks = BOUNCE_HZ * BOUNCE_LENGTH;
280 const double s = sqrt(BOUNCE_HEIGHT)/(ticks/2);
281 double h = BOUNCE_HEIGHT*pow(BOUNCE_DAMP, data->pow);
282 double sqrt_h = sqrt(h);
284 double offset, x = s * data->count - sqrt_h;
289 } else ++data->count;
293 case 0: /* left, bounce to right */
294 XMoveWindow(dpy, aicon->icon->core->window,
295 aicon->x_pos + (int)offset, aicon->y_pos);
297 case 1: /* right, bounce to left */
298 XMoveWindow(dpy, aicon->icon->core->window,
299 aicon->x_pos - (int)offset, aicon->y_pos);
301 case 2: /* top, bounce down */
302 XMoveWindow(dpy, aicon->icon->core->window,
303 aicon->x_pos, aicon->y_pos + (int)offset);
305 case 3: /* bottom, bounce up */
306 XMoveWindow(dpy, aicon->icon->core->window,
307 aicon->x_pos, aicon->y_pos - (int)offset);
312 XMoveWindow(dpy, aicon->icon->core->window,
313 aicon->x_pos, aicon->y_pos);
316 data->wapp->flags.bouncing = 0;
317 WMDeleteTimerHandler(data->timer);
318 wApplicationDestroy(data->wapp);
322 static int bounceDirection(WAppIcon *aicon)
324 enum { left_e = 1, right_e = 2, top_e = 4, bottom_e = 8 };
326 WScreen *scr = aicon->icon->core->screen_ptr;
328 int l, r, t, b, h, v;
331 rr.pos.x = aicon->x_pos;
332 rr.pos.y = aicon->y_pos;
333 rr.size.width = rr.size.height = 64;
335 sr = wGetRectForHead(scr, wGetHeadForRect(scr, rr));
337 l = rr.pos.x - sr.pos.x;
338 r = sr.pos.x + sr.size.width - rr.pos.x - rr.size.width;
339 t = rr.pos.y - sr.pos.y;
340 b = sr.pos.y + sr.size.height - rr.pos.y - rr.size.height;
358 if (h < v) dir &= ~(top_e | bottom_e);
359 else dir &= ~(left_e | right_e);
379 wwarning(_("Impossible direction: %d\n"), dir);
387 void wAppBounce(WApplication *wapp)
389 if (wapp->app_icon && !wapp->flags.bouncing) {
391 wapp->flags.bouncing = 1;
393 AppBouncerData *data = (AppBouncerData *)malloc(sizeof(AppBouncerData));
395 data->count = data->pow = 0;
396 data->dir = bounceDirection(wapp->app_icon);
397 data->timer = WMAddPersistentTimerHandler(BOUNCE_DELAY, doAppBounce, data);
402 void wAppBounce(WApplication *wapp)