1 /****************************************************************************
2 * Copyright (c) 2000,2001 Sasha Vasko <sasha at aftercode.net>
3 * Copyright (c) 1999 Ethan Fisher <allanon@crystaltokyo.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 ****************************************************************************/
20 /***********************************************************************
21 * desktop cover for houskeeping mode
22 ***********************************************************************/
23 #define LOCAL_DEBUG
24
25 #include "../../configure.h"
26
27 #include "asinternals.h"
28
29 #include <stdarg.h>
30
31 #if TIME_WITH_SYS_TIME
32 # include <sys/time.h>
33 # include <time.h>
34 #else
35 # if HAVE_SYS_TIME_H
36 # include <sys/time.h>
37 # else
38 # include <time.h>
39 # endif
40 #endif
41
42 #include "../../libAfterStep/colorscheme.h"
43
44 /**************************************************************************
45 * Different Desktop change Animation types
46 **************************************************************************/
47
48 static CARD32 rnd32_seed = 345824357;
49
50 #define MAX_MY_RND32 0x00ffffffff
51 #ifdef WORD64
52 #define MY_RND32() \
53 (rnd32_seed = ((1664525L*rnd32_seed)&MAX_MY_RND32)+1013904223L)
54 #else
55 #define MY_RND32() \
56 (rnd32_seed = (1664525L*rnd32_seed)+1013904223L)
57 #endif
58
59 #define BLOCKS_NUM 10
60 #define LEVELS_NUM 10
61
62 struct ASDeskAniBlocks {
63 Window cover;
64 int steps, steps_done;
65 unsigned int open_height;
66 unsigned char *stripes[LEVELS_NUM];
67 XRectangle blocks[BLOCKS_NUM];
68 int off_y[LEVELS_NUM];
69
70 };
71
72 void do_anim_shape_blocks (void *vdata);
73
74
75 void
desk_anim_shape_blocks(ScreenInfo * scr,Window cover,unsigned int steps)76 desk_anim_shape_blocks (ScreenInfo * scr, Window cover, unsigned int steps)
77 {
78 #ifdef SHAPE
79 XRectangle main_b = { 0, 0, scr->MyDisplayWidth, scr->MyDisplayHeight };
80 struct ASDeskAniBlocks *data =
81 safecalloc (1, sizeof (struct ASDeskAniBlocks));
82 int y_dim = scr->MyDisplayHeight / steps;
83 int i;
84
85 for (i = 0; i < LEVELS_NUM; i++) {
86 data->off_y[i] = (i - (LEVELS_NUM - 1)) * y_dim;
87 data->stripes[i] = safecalloc (BLOCKS_NUM, 1);
88 }
89
90 XShapeCombineRectangles (dpy, cover, ShapeBounding, 0, 0, &main_b, 1,
91 ShapeSet, Unsorted);
92 data->cover = cover;
93 data->steps = steps;
94
95 timer_new (20, do_anim_shape_blocks, data);
96 #endif
97 }
98
do_anim_shape_blocks(void * vdata)99 void do_anim_shape_blocks (void *vdata)
100 {
101 #ifdef SHAPE
102 struct ASDeskAniBlocks *data = (struct ASDeskAniBlocks *)vdata;
103 XRectangle main_b = { 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight };
104 int ratio = MAX_MY_RND32 / LEVELS_NUM;
105 int x_dim = Scr.MyDisplayWidth / BLOCKS_NUM;
106 int y_dim = Scr.MyDisplayHeight / data->steps;
107 int level, th;
108 unsigned char *tmp;
109
110 if (y_dim < 2)
111 y_dim = 2;
112
113
114 th = MAX_MY_RND32;
115
116 level = LEVELS_NUM;
117 while (--level >= 0) {
118 int blocks_used;
119 int i = 0;
120
121 th -= ratio;
122 if (data->off_y[level] < 0)
123 continue;
124 blocks_used = 0;
125
126 tmp = data->stripes[level];
127 for (i = 0; i < BLOCKS_NUM; i++) {
128 if (tmp[i] == 0 && MY_RND32 () > th) {
129 data->blocks[blocks_used].y = 0;
130 data->blocks[blocks_used].x = i * x_dim;
131 data->blocks[blocks_used].width = x_dim;
132 data->blocks[blocks_used].height = y_dim;
133 blocks_used++;
134 tmp[i] = 1;
135 }
136 }
137 XShapeCombineRectangles (dpy, data->cover, ShapeBounding, 0,
138 data->off_y[level], data->blocks, blocks_used,
139 ShapeSubtract, Unsorted);
140 XFlush (dpy);
141 }
142 if (data->off_y[0] >= 0)
143 data->open_height += y_dim;
144
145 tmp = data->stripes[0];
146 for (level = 0; level < LEVELS_NUM - 1; level++) {
147 data->off_y[level] += y_dim;
148 data->stripes[level] = data->stripes[level + 1];
149 }
150 data->off_y[LEVELS_NUM - 1] += y_dim;
151 data->stripes[LEVELS_NUM - 1] = tmp;
152 memset (tmp, 0x00, BLOCKS_NUM);
153
154 main_b.height = data->open_height;
155 if (main_b.height > 0)
156 XShapeCombineRectangles (dpy, data->cover, ShapeBounding, 0, 0,
157 &main_b, 1, ShapeSubtract, Unsorted);
158
159 ++data->steps_done;
160 if (data->steps_done >= data->steps) {
161 for (level = 0; level < LEVELS_NUM; level++)
162 free (data->stripes[level]);
163 XDestroyWindow (dpy, data->cover);
164 free (data);
165 } else
166 timer_new (20, do_anim_shape_blocks, vdata);
167 #endif
168 }
169
170 struct ASDeskAniMove {
171 Window cover;
172 int steps, steps_done;
173 int dirx, diry;
174 int px, py;
175 };
176
177 void do_anim_slide (void *vdata);
178 void do_anim_shrink (void *vdata);
179
180 void
desk_anim_slide(ScreenInfo * scr,Window cover,int dirx,int diry,unsigned int steps)181 desk_anim_slide (ScreenInfo * scr, Window cover, int dirx, int diry,
182 unsigned int steps)
183 {
184 struct ASDeskAniMove *data =
185 safecalloc (1, sizeof (struct ASDeskAniMove));
186
187 data->cover = cover;
188 data->dirx = dirx;
189 data->diry = diry;
190 data->steps = steps;
191
192 timer_new (20, do_anim_slide, data);
193 }
194
do_anim_slide(void * vdata)195 void do_anim_slide (void *vdata)
196 {
197 struct ASDeskAniMove *data = (struct ASDeskAniMove *)vdata;
198
199 int inc = Scr.MyDisplayWidth / data->steps;
200
201 if (inc == 0)
202 inc = 1;
203 data->px += data->dirx * inc;
204 data->py += data->diry * inc;
205 XMoveWindow (dpy, data->cover, data->px, data->py);
206 XFlush (dpy);
207 ++(data->steps_done);
208 if (data->steps_done >= data->steps) {
209 XDestroyWindow (dpy, data->cover);
210 free (data);
211 } else
212 timer_new (20, do_anim_slide, vdata);
213 }
214
215
216 void
desk_anim_shrink(ScreenInfo * scr,Window cover,int dirx,int diry,unsigned int steps)217 desk_anim_shrink (ScreenInfo * scr, Window cover, int dirx, int diry,
218 unsigned int steps)
219 {
220
221 struct ASDeskAniMove *data =
222 safecalloc (1, sizeof (struct ASDeskAniMove));
223
224 data->cover = cover;
225 data->dirx = dirx;
226 data->diry = diry;
227 data->steps = steps;
228 data->px = scr->MyDisplayWidth;
229 data->py = scr->MyDisplayHeight;
230
231 timer_new (20, do_anim_shrink, data);
232 }
233
do_anim_shrink(void * vdata)234 void do_anim_shrink (void *vdata)
235 {
236 struct ASDeskAniMove *data = (struct ASDeskAniMove *)vdata;
237 int inc = Scr.MyDisplayWidth / data->steps;
238
239 if (inc == 0)
240 inc = 1;
241
242 data->px += data->dirx * inc;
243 if (data->px < 1)
244 data->px = 1;
245 data->py += data->diry * inc;
246 if (data->py < 1)
247 data->py = 1;
248 XResizeWindow (dpy, data->cover, data->px, data->py);
249 XSync (dpy, False);
250
251 ++(data->steps_done);
252 if (data->steps_done >= data->steps) {
253 XDestroyWindow (dpy, data->cover);
254 free (data);
255 } else
256 timer_new (10, do_anim_shrink, data);
257 }
258
desk_anim_slideN(ScreenInfo * scr,Window cover,unsigned int steps)259 void desk_anim_slideN (ScreenInfo * scr, Window cover, unsigned int steps)
260 {
261 desk_anim_slide (scr, cover, 0, -1, steps);
262 }
263
desk_anim_slideW(ScreenInfo * scr,Window cover,unsigned int steps)264 void desk_anim_slideW (ScreenInfo * scr, Window cover, unsigned int steps)
265 {
266 desk_anim_slide (scr, cover, -1, 0, steps);
267 }
268
desk_anim_slideE(ScreenInfo * scr,Window cover,unsigned int steps)269 void desk_anim_slideE (ScreenInfo * scr, Window cover, unsigned int steps)
270 {
271 desk_anim_slide (scr, cover, 1, 0, steps);
272 }
273
desk_anim_slideS(ScreenInfo * scr,Window cover,unsigned int steps)274 void desk_anim_slideS (ScreenInfo * scr, Window cover, unsigned int steps)
275 {
276 desk_anim_slide (scr, cover, 0, 1, steps);
277 }
278
desk_anim_slideNW(ScreenInfo * scr,Window cover,unsigned int steps)279 void desk_anim_slideNW (ScreenInfo * scr, Window cover, unsigned int steps)
280 {
281 desk_anim_slide (scr, cover, -1, -1, steps);
282 }
283
desk_anim_slideNE(ScreenInfo * scr,Window cover,unsigned int steps)284 void desk_anim_slideNE (ScreenInfo * scr, Window cover, unsigned int steps)
285 {
286 desk_anim_slide (scr, cover, 1, -1, steps);
287 }
288
desk_anim_slideSE(ScreenInfo * scr,Window cover,unsigned int steps)289 void desk_anim_slideSE (ScreenInfo * scr, Window cover, unsigned int steps)
290 {
291 desk_anim_slide (scr, cover, 1, 1, steps);
292 }
293
desk_anim_slideSW(ScreenInfo * scr,Window cover,unsigned int steps)294 void desk_anim_slideSW (ScreenInfo * scr, Window cover, unsigned int steps)
295 {
296 desk_anim_slide (scr, cover, -1, 1, steps);
297 }
298
desk_anim_shrinkN(ScreenInfo * scr,Window cover,unsigned int steps)299 void desk_anim_shrinkN (ScreenInfo * scr, Window cover, unsigned int steps)
300 {
301 desk_anim_shrink (scr, cover, 0, -1, steps);
302 }
303
304 void
desk_anim_shrinkNW(ScreenInfo * scr,Window cover,unsigned int steps)305 desk_anim_shrinkNW (ScreenInfo * scr, Window cover, unsigned int steps)
306 {
307 desk_anim_shrink (scr, cover, -1, -1, steps);
308 }
309
desk_anim_shrinkW(ScreenInfo * scr,Window cover,unsigned int steps)310 void desk_anim_shrinkW (ScreenInfo * scr, Window cover, unsigned int steps)
311 {
312 desk_anim_shrink (scr, cover, -1, 0, steps);
313 }
314
315
316 /*************************************************************************/
317 /* main interface */
318 /*************************************************************************/
319
320 static int _as_desktop_cover_recursion = 0;
321 static Window _as_desktop_cover = None;
322 static GC _as_desktop_cover_gc = NULL;
323 static XFontStruct *_as_desktop_cover_xfs = NULL;
324 static int _as_progress_line = 0;
325 static int _as_progress_cursor = 0;
326
327 #define ANIMATIONS_NUM 13
328 static void (*DeskAnimations[ANIMATIONS_NUM]) (ScreenInfo *, Window,
329 unsigned int) = {
330 NULL, desk_anim_slideNW, desk_anim_slideN, desk_anim_slideNE,
331 desk_anim_slideE, desk_anim_slideSE, desk_anim_slideS,
332 desk_anim_slideSW, desk_anim_slideW, desk_anim_shrinkN,
333 desk_anim_shrinkNW, desk_anim_shrinkW, desk_anim_shape_blocks};
334
remove_desktop_cover()335 void remove_desktop_cover ()
336 {
337
338 if (_as_desktop_cover) {
339 --_as_desktop_cover_recursion;
340 if (_as_desktop_cover_recursion == 0) {
341 int steps = Scr.Feel.desk_cover_animation_steps;
342 int type = Scr.Feel.desk_cover_animation_type;
343
344 XSync (dpy, False);
345
346 if (steps > 0 && type >= 0 && DeskAnimations[type % ANIMATIONS_NUM])
347 DeskAnimations[type % ANIMATIONS_NUM] (ASDefaultScr,
348 _as_desktop_cover, steps);
349 else
350 XDestroyWindow (dpy, _as_desktop_cover);
351 _as_desktop_cover = None;
352
353 _as_progress_line = 0;
354 _as_progress_cursor = 0;
355
356 XSync (dpy, False);
357 }
358 }
359 }
360
get_desktop_cover_window()361 Window get_desktop_cover_window ()
362 {
363 return _as_desktop_cover;
364 }
365
restack_desktop_cover()366 void restack_desktop_cover ()
367 {
368 if (_as_desktop_cover)
369 XRaiseWindow (dpy, _as_desktop_cover);
370 }
371
cover_desktop()372 void cover_desktop ()
373 {
374 XSetWindowAttributes attributes;
375 unsigned long valuemask;
376 Window w;
377 XGCValues gcvalue;
378
379 if (get_flags (Scr.Feel.flags, DontCoverDesktop))
380 return;
381
382 ++_as_desktop_cover_recursion;
383
384 if (_as_desktop_cover != None)
385 return;
386
387 valuemask = (CWBackPixmap | CWBackingStore | CWOverrideRedirect);
388 attributes.background_pixmap = None;
389 attributes.backing_store = NotUseful;
390 attributes.override_redirect = True;
391
392 w = create_visual_window (Scr.asv, Scr.Root, 0, 0,
393 Scr.MyDisplayWidth, Scr.MyDisplayHeight,
394 0, InputOutput, valuemask, &attributes);
395
396 XMapRaised (dpy, w);
397 XSync (dpy, False);
398 if (_as_desktop_cover_gc == NULL) {
399 unsigned long mask =
400 GCFunction | GCForeground | GCBackground | GCGraphicsExposures;
401 CARD32 r16, g16, b16;
402
403 if (_as_desktop_cover_xfs == NULL)
404 _as_desktop_cover_xfs = XLoadQueryFont (dpy, "fixed");
405
406 if (_as_desktop_cover_xfs) {
407 gcvalue.font = _as_desktop_cover_xfs->fid;
408 mask |= GCFont;
409 }
410
411 LOCAL_DEBUG_OUT ("desk_anime_tint = %lX",
412 Scr.Look.desktop_animation_tint);
413 r16 = ARGB32_RED16 (Scr.Look.desktop_animation_tint);
414 g16 = ARGB32_GREEN16 (Scr.Look.desktop_animation_tint);
415 b16 = ARGB32_BLUE16 (Scr.Look.desktop_animation_tint);
416 if (ASCS_BLACK_O_WHITE_CRITERIA16 (r16, g16, b16)) {
417 gcvalue.foreground = Scr.asv->black_pixel;
418 gcvalue.background = Scr.asv->white_pixel;
419 } else {
420 gcvalue.foreground = Scr.asv->white_pixel;
421 gcvalue.background = Scr.asv->black_pixel;
422 }
423 gcvalue.function = GXcopy;
424 gcvalue.graphics_exposures = 0;
425
426 _as_desktop_cover_gc =
427 create_visual_gc (Scr.asv, Scr.Root, mask, &gcvalue);
428 }
429 if (_as_desktop_cover_gc) {
430 unsigned long pixel;
431 ARGB2PIXEL (Scr.asv, Scr.Look.desktop_animation_tint, &pixel);
432 gcvalue.foreground = pixel;
433 gcvalue.function = GXand;
434 XChangeGC (dpy, _as_desktop_cover_gc, GCFunction | GCForeground,
435 &gcvalue);
436 XFillRectangle (dpy, w, _as_desktop_cover_gc, 0, 0, Scr.MyDisplayWidth,
437 Scr.MyDisplayHeight);
438 gcvalue.foreground = Scr.asv->white_pixel;
439 gcvalue.function = GXcopy;
440 XChangeGC (dpy, _as_desktop_cover_gc, GCFunction | GCForeground,
441 &gcvalue);
442 }
443 _as_desktop_cover = w;
444 }
445
desktop_cover_cleanup()446 void desktop_cover_cleanup ()
447 {
448 if (_as_desktop_cover_gc) {
449 XFreeGC (dpy, _as_desktop_cover_gc);
450 _as_desktop_cover_gc = NULL;
451 }
452
453 if (_as_desktop_cover_xfs) {
454 XFreeFont (dpy, _as_desktop_cover_xfs);
455 _as_desktop_cover_xfs = NULL;
456 }
457
458 if (_as_desktop_cover) {
459 XDestroyWindow (dpy, _as_desktop_cover);
460 _as_desktop_cover = None;
461 }
462
463 _as_desktop_cover_recursion = 0;
464 }
465
466 static char buffer[8192];
467
display_progress(Bool new_line,const char * msg_format,...)468 void display_progress (Bool new_line, const char *msg_format, ...)
469 {
470 if (_as_desktop_cover && _as_desktop_cover_xfs && _as_desktop_cover_gc) {
471 int x, y;
472 int height;
473 int len;
474
475 va_list ap;
476 va_start (ap, msg_format);
477 vsnprintf (&buffer[0], 256, msg_format, ap);
478 va_end (ap);
479
480 len = strlen (&buffer[0]);
481 if (_as_progress_cursor > 0 && new_line) {
482 ++_as_progress_line;
483 _as_progress_cursor = 0;
484 }
485 /* and now we need to display the text on the screen */
486 x = Scr.MyDisplayWidth / 20 + _as_progress_cursor;
487 height =
488 _as_desktop_cover_xfs->ascent + _as_desktop_cover_xfs->descent + 5;
489 y = Scr.MyDisplayHeight / 5 + height * _as_progress_line;
490 _as_progress_cursor +=
491 XTextWidth (_as_desktop_cover_xfs, &buffer[0], len) + 10;
492 XDrawString (dpy, _as_desktop_cover, _as_desktop_cover_gc, x, y,
493 &buffer[0], len);
494 ASSync (False);
495 }
496 }
497