10bbfda8aSnia/* 20bbfda8aSnia * Animation routines 30bbfda8aSnia */ 40bbfda8aSnia 50bbfda8aSnia 60bbfda8aSnia#include "ctwm.h" 70bbfda8aSnia 80bbfda8aSnia#include <sys/time.h> 9b18c2d1eSnia#include <assert.h> 100bbfda8aSnia#include <stdio.h> 110bbfda8aSnia#include <string.h> 120bbfda8aSnia 130bbfda8aSnia#include <X11/extensions/shape.h> 140bbfda8aSnia 150bbfda8aSnia#include "ctwm_atoms.h" 160bbfda8aSnia#include "events.h" 170bbfda8aSnia#include "icons.h" 180bbfda8aSnia#include "image.h" 190bbfda8aSnia#include "screen.h" 200bbfda8aSnia#include "util.h" 210bbfda8aSnia#include "vscreen.h" 220bbfda8aSnia#include "win_utils.h" 230bbfda8aSnia 240bbfda8aSnia#include "animate.h" 250bbfda8aSnia 260bbfda8aSnia 270bbfda8aSnia#define MAXANIMATIONSPEED 20 280bbfda8aSnia 290bbfda8aSnia 300bbfda8aSniaint Animating = 0; 310bbfda8aSniaint AnimationSpeed = 0; 320bbfda8aSniabool AnimationActive = false; 330bbfda8aSniabool MaybeAnimate = true; 340bbfda8aSniastruct timeval AnimateTimeout; 350bbfda8aSnia 360bbfda8aSnia 370bbfda8aSniastatic void Animate(void); 380bbfda8aSniastatic void AnimateButton(TBWindow *tbw); 390bbfda8aSniastatic void AnimateHighlight(TwmWindow *t); 400bbfda8aSniastatic void AnimateIcons(ScreenInfo *scr, Icon *icon); 410bbfda8aSniastatic bool AnimateRoot(void); 420bbfda8aSnia 430bbfda8aSnia 440bbfda8aSnia/* 450bbfda8aSnia * XXX We're directly looking at this for hopefully hysterical raisins. 460bbfda8aSnia * Rexamine the whole tracefile subsystem at some point when we look at 470bbfda8aSnia * debugging. 480bbfda8aSnia * 490bbfda8aSnia * Currently get it via pollution from events.h anyway. 500bbfda8aSnia * 510bbfda8aSnia * extern FILE *tracefile; 520bbfda8aSnia */ 530bbfda8aSnia 540bbfda8aSniavoid 550bbfda8aSniaTryToAnimate(void) 560bbfda8aSnia{ 570bbfda8aSnia struct timeval tp; 580bbfda8aSnia static unsigned long lastsec; 590bbfda8aSnia static long lastusec; 600bbfda8aSnia unsigned long gap; 610bbfda8aSnia 620bbfda8aSnia if(Animating > 1) { 630bbfda8aSnia return; /* rate limiting */ 640bbfda8aSnia } 650bbfda8aSnia 660bbfda8aSnia gettimeofday(&tp, NULL); 670bbfda8aSnia gap = ((tp.tv_sec - lastsec) * 1000000) + (tp.tv_usec - lastusec); 680bbfda8aSnia if(tracefile) { 690bbfda8aSnia fprintf(tracefile, "Time = %lu, %ld, %ld, %ld, %lu\n", lastsec, 700bbfda8aSnia lastusec, (long)tp.tv_sec, (long)tp.tv_usec, gap); 710bbfda8aSnia fflush(tracefile); 720bbfda8aSnia } 730bbfda8aSnia gap *= AnimationSpeed; 740bbfda8aSnia if(gap < 1000000) { 750bbfda8aSnia return; 760bbfda8aSnia } 770bbfda8aSnia if(tracefile) { 780bbfda8aSnia fprintf(tracefile, "Animate\n"); 790bbfda8aSnia fflush(tracefile); 800bbfda8aSnia } 810bbfda8aSnia Animate(); 820bbfda8aSnia lastsec = tp.tv_sec; 830bbfda8aSnia lastusec = tp.tv_usec; 840bbfda8aSnia} 850bbfda8aSnia 860bbfda8aSnia 870bbfda8aSnia 880bbfda8aSniavoid 890bbfda8aSniaStartAnimation(void) 900bbfda8aSnia{ 910bbfda8aSnia 920bbfda8aSnia if(AnimationSpeed > MAXANIMATIONSPEED) { 930bbfda8aSnia AnimationSpeed = MAXANIMATIONSPEED; 940bbfda8aSnia } 950bbfda8aSnia if(AnimationSpeed <= 0) { 960bbfda8aSnia AnimationSpeed = 0; 970bbfda8aSnia } 980bbfda8aSnia if(AnimationActive) { 990bbfda8aSnia return; 1000bbfda8aSnia } 1010bbfda8aSnia switch(AnimationSpeed) { 1020bbfda8aSnia case 0 : 1030bbfda8aSnia return; 1040bbfda8aSnia case 1 : 1050bbfda8aSnia AnimateTimeout.tv_sec = 1; 1060bbfda8aSnia AnimateTimeout.tv_usec = 0; 1070bbfda8aSnia break; 1080bbfda8aSnia default : 1090bbfda8aSnia AnimateTimeout.tv_sec = 0; 1100bbfda8aSnia AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1110bbfda8aSnia } 1120bbfda8aSnia AnimationActive = true; 1130bbfda8aSnia} 1140bbfda8aSnia 1150bbfda8aSnia 1160bbfda8aSniavoid 1170bbfda8aSniaStopAnimation(void) 1180bbfda8aSnia{ 1190bbfda8aSnia AnimationActive = false; 1200bbfda8aSnia} 1210bbfda8aSnia 1220bbfda8aSnia 1230bbfda8aSniavoid 1240bbfda8aSniaSetAnimationSpeed(int speed) 1250bbfda8aSnia{ 1260bbfda8aSnia AnimationSpeed = speed; 1270bbfda8aSnia if(AnimationSpeed > MAXANIMATIONSPEED) { 1280bbfda8aSnia AnimationSpeed = MAXANIMATIONSPEED; 1290bbfda8aSnia } 1300bbfda8aSnia} 1310bbfda8aSnia 1320bbfda8aSnia 1330bbfda8aSniavoid 1340bbfda8aSniaModifyAnimationSpeed(int incr) 1350bbfda8aSnia{ 1360bbfda8aSnia if((AnimationSpeed + incr) < 0) { 1370bbfda8aSnia return; 1380bbfda8aSnia } 1390bbfda8aSnia if((AnimationSpeed + incr) == 0) { 1400bbfda8aSnia if(AnimationActive) { 1410bbfda8aSnia StopAnimation(); 1420bbfda8aSnia } 1430bbfda8aSnia AnimationSpeed = 0; 1440bbfda8aSnia return; 1450bbfda8aSnia } 1460bbfda8aSnia AnimationSpeed += incr; 1470bbfda8aSnia if(AnimationSpeed > MAXANIMATIONSPEED) { 1480bbfda8aSnia AnimationSpeed = MAXANIMATIONSPEED; 1490bbfda8aSnia } 1500bbfda8aSnia 1510bbfda8aSnia if(AnimationSpeed == 1) { 1520bbfda8aSnia AnimateTimeout.tv_sec = 1; 1530bbfda8aSnia AnimateTimeout.tv_usec = 0; 1540bbfda8aSnia } 1550bbfda8aSnia else { 1560bbfda8aSnia AnimateTimeout.tv_sec = 0; 1570bbfda8aSnia AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1580bbfda8aSnia } 1590bbfda8aSnia AnimationActive = true; 1600bbfda8aSnia} 1610bbfda8aSnia 1620bbfda8aSnia 1630bbfda8aSnia 1640bbfda8aSnia/* 1650bbfda8aSnia * Only called from TryToAnimate 1660bbfda8aSnia */ 1670bbfda8aSniastatic void 1680bbfda8aSniaAnimate(void) 1690bbfda8aSnia{ 1700bbfda8aSnia TwmWindow *t; 1710bbfda8aSnia int scrnum; 1720bbfda8aSnia ScreenInfo *scr; 1730bbfda8aSnia int i; 1740bbfda8aSnia TBWindow *tbw; 1750bbfda8aSnia int nb; 1760bbfda8aSnia 1770bbfda8aSnia if(AnimationSpeed == 0) { 1780bbfda8aSnia return; 1790bbfda8aSnia } 1800bbfda8aSnia if(Animating > 1) { 1810bbfda8aSnia return; /* rate limiting */ 1820bbfda8aSnia } 1830bbfda8aSnia 1840bbfda8aSnia /* Impossible? */ 1850bbfda8aSnia if(NumScreens < 1) { 1860bbfda8aSnia return; 1870bbfda8aSnia } 1880bbfda8aSnia 1890bbfda8aSnia MaybeAnimate = false; 1900bbfda8aSnia scr = NULL; 1910bbfda8aSnia for(scrnum = 0; scrnum < NumScreens; scrnum++) { 1920bbfda8aSnia if((scr = ScreenList [scrnum]) == NULL) { 1930bbfda8aSnia continue; 1940bbfda8aSnia } 1950bbfda8aSnia 1960bbfda8aSnia for(t = scr->FirstWindow; t != NULL; t = t->next) { 1970bbfda8aSnia if(! visible(t)) { 1980bbfda8aSnia continue; 1990bbfda8aSnia } 2000bbfda8aSnia if(t->icon_on && t->icon && t->icon->bm_w && t->icon->image && 2010bbfda8aSnia t->icon->image->next) { 2020bbfda8aSnia AnimateIcons(scr, t->icon); 2030bbfda8aSnia MaybeAnimate = true; 2040bbfda8aSnia } 2050bbfda8aSnia else if(t->mapped && t->titlebuttons) { 2060bbfda8aSnia nb = scr->TBInfo.nleft + scr->TBInfo.nright; 2070bbfda8aSnia for(i = 0, tbw = t->titlebuttons; i < nb; i++, tbw++) { 2080bbfda8aSnia if(tbw->image && tbw->image->next) { 2090bbfda8aSnia AnimateButton(tbw); 2100bbfda8aSnia MaybeAnimate = true; 2110bbfda8aSnia } 2120bbfda8aSnia } 2130bbfda8aSnia } 2140bbfda8aSnia } 2150bbfda8aSnia if(scr->Focus) { 2160bbfda8aSnia t = scr->Focus; 2170bbfda8aSnia if(t->mapped && t->titlehighlight && t->title_height && 2180bbfda8aSnia t->HiliteImage && t->HiliteImage->next) { 2190bbfda8aSnia AnimateHighlight(t); 2200bbfda8aSnia MaybeAnimate = true; 2210bbfda8aSnia } 2220bbfda8aSnia } 2230bbfda8aSnia } 2240bbfda8aSnia MaybeAnimate |= AnimateRoot(); 2250bbfda8aSnia if(MaybeAnimate) { 226b18c2d1eSnia // Impossible: scr==NULL means we had no valid screens, which 227b18c2d1eSnia // means we'd'a bomed out WAY earlier than trying to animate 228b18c2d1eSnia // something... 229b18c2d1eSnia assert(scr != NULL); 2300bbfda8aSnia Animating++; 2310bbfda8aSnia send_clientmessage(scr->currentvs->wsw->w, XA_WM_END_OF_ANIMATION, 2320bbfda8aSnia EventTime); 2330bbfda8aSnia } 2340bbfda8aSnia XFlush(dpy); 2350bbfda8aSnia return; 2360bbfda8aSnia} 2370bbfda8aSnia 2380bbfda8aSnia 2390bbfda8aSnia/* Originally in add_window.c */ 2400bbfda8aSniastatic void 2410bbfda8aSniaAnimateButton(TBWindow *tbw) 2420bbfda8aSnia{ 2430bbfda8aSnia Image *image; 2440bbfda8aSnia XSetWindowAttributes attr; 2450bbfda8aSnia 2460bbfda8aSnia image = tbw->image; 2470bbfda8aSnia attr.background_pixmap = image->pixmap; 2480bbfda8aSnia XChangeWindowAttributes(dpy, tbw->window, CWBackPixmap, &attr); 2490bbfda8aSnia XClearWindow(dpy, tbw->window); 2500bbfda8aSnia tbw->image = image->next; 2510bbfda8aSnia} 2520bbfda8aSnia 2530bbfda8aSnia/* Originally in add_window.c */ 2540bbfda8aSniastatic void 2550bbfda8aSniaAnimateHighlight(TwmWindow *t) 2560bbfda8aSnia{ 2570bbfda8aSnia Image *image; 2580bbfda8aSnia XSetWindowAttributes attr; 2590bbfda8aSnia 2600bbfda8aSnia image = t->HiliteImage; 2610bbfda8aSnia attr.background_pixmap = image->pixmap; 2620bbfda8aSnia if(t->hilite_wl) { 2630bbfda8aSnia XChangeWindowAttributes(dpy, t->hilite_wl, CWBackPixmap, &attr); 2640bbfda8aSnia XClearWindow(dpy, t->hilite_wl); 2650bbfda8aSnia } 2660bbfda8aSnia if(t->hilite_wr) { 2670bbfda8aSnia XChangeWindowAttributes(dpy, t->hilite_wr, CWBackPixmap, &attr); 2680bbfda8aSnia XClearWindow(dpy, t->hilite_wr); 2690bbfda8aSnia } 2700bbfda8aSnia t->HiliteImage = image->next; 2710bbfda8aSnia} 2720bbfda8aSnia 2730bbfda8aSnia 2740bbfda8aSnia/* Originally in icons.c */ 2750bbfda8aSniastatic void 2760bbfda8aSniaAnimateIcons(ScreenInfo *scr, Icon *icon) 2770bbfda8aSnia{ 2780bbfda8aSnia Image *image; 2790bbfda8aSnia XRectangle rect; 2800bbfda8aSnia XSetWindowAttributes attr; 2810bbfda8aSnia int x; 2820bbfda8aSnia 2830bbfda8aSnia image = icon->image; 2840bbfda8aSnia attr.background_pixmap = image->pixmap; 2850bbfda8aSnia XChangeWindowAttributes(dpy, icon->bm_w, CWBackPixmap, &attr); 2860bbfda8aSnia 2870bbfda8aSnia if(image->mask != None) { 2880bbfda8aSnia x = GetIconOffset(icon); 2890bbfda8aSnia XShapeCombineMask(dpy, icon->bm_w, ShapeBounding, 0, 0, image->mask, ShapeSet); 2900bbfda8aSnia if(icon->has_title) { 2910bbfda8aSnia rect.x = 0; 2920bbfda8aSnia rect.y = icon->height; 2930bbfda8aSnia rect.width = icon->w_width; 2940bbfda8aSnia rect.height = scr->IconFont.height + 6; 2950bbfda8aSnia 2960bbfda8aSnia XShapeCombineShape(dpy, scr->ShapeWindow, ShapeBounding, x, 0, icon->bm_w, 2970bbfda8aSnia ShapeBounding, ShapeSet); 2980bbfda8aSnia XShapeCombineRectangles(dpy, scr->ShapeWindow, ShapeBounding, 0, 0, &rect, 1, 2990bbfda8aSnia ShapeUnion, 0); 3000bbfda8aSnia XShapeCombineShape(dpy, icon->w, ShapeBounding, 0, 0, scr->ShapeWindow, 3010bbfda8aSnia ShapeBounding, ShapeSet); 3020bbfda8aSnia } 3030bbfda8aSnia else 3040bbfda8aSnia XShapeCombineShape(dpy, icon->w, ShapeBounding, x, 0, icon->bm_w, 3050bbfda8aSnia ShapeBounding, ShapeSet); 3060bbfda8aSnia } 3070bbfda8aSnia XClearWindow(dpy, icon->bm_w); 3080bbfda8aSnia icon->image = image->next; 3090bbfda8aSnia return; 3100bbfda8aSnia} 3110bbfda8aSnia 3120bbfda8aSnia 3130bbfda8aSnia/* Original in workmgr.c */ 3140bbfda8aSniastatic bool 3150bbfda8aSniaAnimateRoot(void) 3160bbfda8aSnia{ 3170bbfda8aSnia VirtualScreen *vs; 3180bbfda8aSnia ScreenInfo *scr; 3190bbfda8aSnia int scrnum; 3200bbfda8aSnia Image *image; 3210bbfda8aSnia WorkSpace *ws; 3220bbfda8aSnia bool maybeanimate; 3230bbfda8aSnia 3240bbfda8aSnia maybeanimate = false; 3250bbfda8aSnia for(scrnum = 0; scrnum < NumScreens; scrnum++) { 3260bbfda8aSnia if((scr = ScreenList [scrnum]) == NULL) { 3270bbfda8aSnia continue; 3280bbfda8aSnia } 3290bbfda8aSnia if(! scr->workSpaceManagerActive) { 3300bbfda8aSnia continue; 3310bbfda8aSnia } 3320bbfda8aSnia 3330bbfda8aSnia for(vs = scr->vScreenList; vs != NULL; vs = vs->next) { 3340bbfda8aSnia if(! vs->wsw->currentwspc) { 3350bbfda8aSnia continue; 3360bbfda8aSnia } 3370bbfda8aSnia image = vs->wsw->currentwspc->image; 3380bbfda8aSnia if((image == NULL) || (image->next == NULL)) { 3390bbfda8aSnia continue; 3400bbfda8aSnia } 3410bbfda8aSnia if(scr->DontPaintRootWindow) { 3420bbfda8aSnia continue; 3430bbfda8aSnia } 3440bbfda8aSnia 3450bbfda8aSnia XSetWindowBackgroundPixmap(dpy, vs->window, image->pixmap); 3460bbfda8aSnia XClearWindow(dpy, scr->Root); 3470bbfda8aSnia vs->wsw->currentwspc->image = image->next; 3480bbfda8aSnia maybeanimate = true; 3490bbfda8aSnia } 3500bbfda8aSnia } 3510bbfda8aSnia for(scrnum = 0; scrnum < NumScreens; scrnum++) { 3520bbfda8aSnia if((scr = ScreenList [scrnum]) == NULL) { 3530bbfda8aSnia continue; 3540bbfda8aSnia } 3550bbfda8aSnia 3560bbfda8aSnia for(vs = scr->vScreenList; vs != NULL; vs = vs->next) { 3570bbfda8aSnia if(vs->wsw->state == WMS_buttons) { 3580bbfda8aSnia continue; 3590bbfda8aSnia } 3600bbfda8aSnia for(ws = scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { 3610bbfda8aSnia image = ws->image; 3620bbfda8aSnia 3630bbfda8aSnia if((image == NULL) || (image->next == NULL)) { 3640bbfda8aSnia continue; 3650bbfda8aSnia } 3660bbfda8aSnia if(ws == vs->wsw->currentwspc) { 3670bbfda8aSnia continue; 3680bbfda8aSnia } 3690bbfda8aSnia XSetWindowBackgroundPixmap(dpy, vs->wsw->mswl [ws->number]->w, image->pixmap); 3700bbfda8aSnia XClearWindow(dpy, vs->wsw->mswl [ws->number]->w); 3710bbfda8aSnia ws->image = image->next; 3720bbfda8aSnia maybeanimate = true; 3730bbfda8aSnia } 3740bbfda8aSnia } 3750bbfda8aSnia } 3760bbfda8aSnia return maybeanimate; 3770bbfda8aSnia} 378