Package: xsnow Version: 1:1.42-8 Severity: minor Tags: patch
xnow does not react to screen resolution changes (resulting in a 'bottom' that does not coincide with the display bottom any more), and fails to detect when the entire root window is redrawn, e.g. after quitting a full-screen application and also when switching VT or waking from suspend (resulting in ugly snow-streaks). Please find below the proposed patch to correct these issues. More precisely, what follows is - the detailed list of changes to the source of xsnow 1.42 (in square brackets instructions on how to reproduce the bugs with the current version) - the diff-patch for xsnow.c - the diff-patch for xsnow.h regards, Adrian p.s. cc: to Rick Jansen because this issue has not been corrected upstream ------------ BEGIN: list of changes -------------- * to make xsnow aware of screen resolution changes: [to see this bug with the original version: xrandr to a lower resolution; launch xsnow; wait for some snow to accumulate at the bottom; switch back to higher resolution: the bottom snow now accumulates at the coordinate of the former display height, somewhere in mid-air] - moved some display-size-dependent initalisation code from main() to new function prepare(), which is then invoked at every display size change - make the main event loop listen to StructureNotify masked events, so that changes in root window size generate a ConfigureNotify event - call prepare() from within the main event loop on ConfigureNotify events where display size has changed * to erase bottom snow when full-screen app quits: [to see this bug with the original version: launch xsnow and wait for some snow to accumulate on bottom and/or windows (use -snowflakes 1000 to wait less long...); start full-screen app (e.g. "mplayer -fs somemovie.avi") and quit it: the snow has disappeared because of the resulting redraw, but xsnow still thinks there are thick layers of snow around. Flakes falling through these layers produce strange trails of free-standing snow...] - modified the tests that MWR() uses to skip over some child windows. These tests in particular would skip over any child window with the top at y=0, such as full-screen-windows. Now skip only completely invisible windows. * to make xsnow's memory of accumulated snow match full background window redraws in the absence of child window changes (such as occuring when switching VT or waking from suspend) [to see bug with the original version: same procedure as for full-screen-app bug, but switch to console and back to X11 instead of launching fs-app. Same observation.] - immediately subtract newly exposed areas from the accumulated snow region snscr (in the main event loop) - as this places some additional load on the machine when windows are moved around (was not able to measure the real impact reliably), added "#define CLEANONEXPOSE 1" to xsnow.h and added preprocessor instructions around the code in xsnow.c to conditionnally compile according to the value of CLEANONEXPOSE in xsnow.h * other minor changes - removed declaration unused variable current_snow_height - added a few comments here and there while figuring out xsnow's inner workings - corrected what seems like a typo: in MASR(), part of the code should clearly depend on NoKeepSBot, not on NoKeepSWin; has no effect in practice because snscr (initialised with the same code without typo) is merged into sar afterwards. ------------ END: list of changes -------------- ------------ BEGIN: diff-patch for xsnow.c -------------- --- xsnow-1.42/xsnow.c 2001-12-16 00:44:47.000000000 +0100 +++ xsnow-1.42resizeable/xsnow.c 2010-02-06 21:50:58.000000000 +0100 @@ -198,6 +198,10 @@ 14DEC2001 KDE and other root window obstructors: sub borrowed from xpenguins 2.2 to find the current "root" window for this system. Credit to Robin Hogan <r.j.ho...@reading.ac.uk> + + 05FEB2010 Now reacts to a change of its root window size (e.g. mode + changes through xrandr) and erases bottom snow when full-screen-app + quits. [Adrian Daerr, no rights claimed on contribution - public domain] */ #define debug 0 @@ -211,7 +215,7 @@ Xsnow dos mil etc. */ -#define VERSION "Xsnow-1.42, December 14th 2001 by Rick Jansen (r...@euronet.nl)\n\ +#define VERSION "Xsnow-1.42resizeable, December 14th 2001 by Rick Jansen (r...@euronet.nl)\n\ WWW: http://www.euronet.nl/~rja/Xsnow/\n" #ifdef VMS @@ -315,7 +319,6 @@ int wind = 0; int direction=0; int WindTimer=30; -int current_snow_height; int geta=0; XRectangle AddRect; unsigned int RunCounter = 0; @@ -324,6 +327,7 @@ void Usage(); void SigHandler(); void SigHupHandler(); +void prepare(int,int); void InitSnowflake(); void UpdateSnowflake(); void DrawSnowflake(); @@ -555,15 +559,6 @@ rootWin = ToonGetRootWindow(display, screen, &Parent); black = BlackPixel(display, screen); white = WhitePixel(display, screen); - display_width = DisplayWidth(display, screen); - display_height = DisplayHeight(display, screen); - center_x = display_width / 2; - center_y = display_height / 2; - current_snow_height = display_height; - if (MaxScrSnowDepth> (display_height-SNOWFREE)) { - printf("** Maximum snow depth set to %d\n", display_height-SNOWFREE); - MaxScrSnowDepth = display_height-SNOWFREE; - } for (flake=0; flake<=SNOWFLAKEMAXTYPE; flake++) { rp = &snowPix[flake]; rp->pixmap = XCreateBitmapFromData(display, rootWin, @@ -620,29 +615,9 @@ XSetForeground(display,TreesGC,trPix); XSetFillStyle(display, TreesGC, FillStippled); - - - - Wr = XCreateRegion(); - PrevWr = XCreateRegion(); - snscr = XCreateRegion(); - sar = XCreateRegion(); - WDR = XCreateRegion(); - CDR = XCreateRegion(); - rscrr = XCreateRegion(); - AddRect.x = 0; - AddRect.y = display_height; - AddRect.width = display_width - 1; - AddRect.height = MaxYStep+MaxSnowFlakeHeight; - if (!NoKeepSBot) - XUnionRectWithRegion(&AddRect, snscr, snscr); - for (i=0; i<maxSnowflakes; i++) InitSnowflake(i); -rc = MWR(1); - XUnionRegion(Wr,PrevWr, PrevWr); - RCSR(); - MASR(); - ResetSanta(); - XSelectInput(display, rootWin, ExposureMask | SubstructureNotifyMask); + + prepare(DisplayWidth(display, screen), DisplayHeight(display, screen)); + XSelectInput(display, rootWin, ExposureMask | SubstructureNotifyMask | StructureNotifyMask); while (!done) { @@ -657,16 +632,29 @@ switch (ev.type) { case Expose: #if debug - printf("EXPOSE\n"); + printf("EXPOSE in window %d: x=%d y=%d h=%d w=%d\n",ev.xexpose.window,ev.xexpose.x,ev.xexpose.y,ev.xexpose.height,ev.xexpose.width); #endif Exposed = 1; + #if CLEANONEXPOSE + // erase memory of accumulated snow here +// (xsnow usually tries to be smart and to look at child window +// positions in order to decide where to erase snow, but hence misses +// root window redraws due e.g. to VT switching or power suspend, +// resulting in internal snow memory not being up-to-date with visible +// snow, and ugly snow streaks on the display) + SubR = XCreateRegion(); + AddRect.x = ev.xexpose.x; + AddRect.y = ev.xexpose.y; + AddRect.width = ev.xexpose.width; + AddRect.height = ev.xexpose.height; + XUnionRectWithRegion(&AddRect, SubR,SubR); + XSubtractRegion(snscr,SubR, snscr); + XDestroyRegion(SubR); + #endif if (!DDLT()) { stilltddr = 1; continue; } - #if debug - printf("expose x:%d y:%d h:%d w:%d\n",ev.xexpose.x,ev.xexpose.y,ev.xexpose.height,ev.xexpose.width); - #endif break; case ConfigureNotify: #if debug @@ -680,12 +668,24 @@ ev.xconfigure.border_width, (rootWin == ev.xconfigure.event) ); + #endif + if (ev.xconfigure.window == rootWin) {// background window was modified + if (ev.xconfigure.width != display_width || + ev.xconfigure.height != display_height) { + #if debug + printf("Screen resolution changed. Reinitializing...\n"); + #endif + prepare(ev.xconfigure.width, ev.xconfigure.height); + } + } else { + #if debug printf("ConfigureNotify calling DDLT\n"); #endif if (!DDLT()) { stilltddr = 1; continue; } + } break; case ConfigureRequest: #if debug @@ -860,6 +860,52 @@ #endif } /* ------------------------------------------------------------------ */ + +/* called before setting up event loop and everytime screen resolution changes */ +void +prepare(width, height) +int width; +int height; +{ + int i; + // clean up + if (Wr != NULL) { XDestroyRegion(Wr); Wr = NULL; } + if (PrevWr != NULL) { XDestroyRegion(PrevWr); PrevWr = NULL; } + if (snscr != NULL) { XDestroyRegion(snscr); snscr = NULL; } + if (sar != NULL) { XDestroyRegion(sar); sar = NULL; } + if (WDR != NULL) { XDestroyRegion(WDR); WDR = NULL; } + if (CDR != NULL) { XDestroyRegion(CDR); CDR = NULL; } + if (rscrr != NULL) { XDestroyRegion(rscrr); rscrr = NULL; } + XClearWindow(display, rootWin); + // initialise + Wr = XCreateRegion(); + PrevWr = XCreateRegion(); + snscr = XCreateRegion(); + sar = XCreateRegion(); + WDR = XCreateRegion(); + CDR = XCreateRegion(); + rscrr = XCreateRegion(); + display_width = width; + display_height = height; + center_x = display_width / 2; + center_y = display_height / 2; + if (MaxScrSnowDepth> (display_height-SNOWFREE)) { + printf("** Maximum snow depth set to %d\n", display_height-SNOWFREE); + MaxScrSnowDepth = display_height-SNOWFREE; + } + AddRect.x = 0; + AddRect.y = display_height; + AddRect.width = display_width - 1; + AddRect.height = MaxYStep+MaxSnowFlakeHeight; + if (!NoKeepSBot) + XUnionRectWithRegion(&AddRect, snscr, snscr); + for (i=0; i<maxSnowflakes; i++) InitSnowflake(i); + rc = MWR(1); + XUnionRegion(Wr,PrevWr, PrevWr); + RCSR(); + MASR(); + ResetSanta(); +} int SnowPtInRect(snx, sny, recx, recy, width, height) @@ -1028,6 +1074,8 @@ False); } } + +/* unused (see changelog 20DEC93) */ void PaintSnowAtBottom(depth) int depth; @@ -1329,10 +1377,7 @@ &winWidth, &winHeight, &borderWidth, &depth); /*if (winWidth == 1280) continue; /* debug */ #if debug - printf("\nw x:%d y:%d w:%d h:%d - bw:%d d:%d \n", winX,winY,winWidth,winHeight,borderWidth,depth); - #endif - #if debug - printf("MakeWrx: (x;%d\ty:%d\tx+w%d\ty+h%d)\tbw:%d d:%d\n", + printf("MakeWr: x=%d\ty=%d\tx+w=%d\ty+h=%d,\tbw:%d depth:%d\n", winX,winY,winX+winWidth,winY+winHeight,borderWidth,depth); #endif if (errorVal) continue; @@ -1340,11 +1385,17 @@ WinRect.y = winY; WinRect.height = winHeight + 2*borderWidth; WinRect.width = winWidth + 2*borderWidth; + // zap invisible windows if (WinRect.x >= display_width) continue; if (WinRect.y >= display_height) continue; - if (WinRect.y <= 0) continue; - if ((WinRect.x + WinRect.width) < 0) continue; + if (WinRect.y < 0) continue; + if ((WinRect.x + WinRect.width) <= 0) continue; XUnionRectWithRegion(&WinRect,Wr, Wr); + #if debug + XClipBox( Wr, &WinRect ); + printf("Wr now: x=%d\ty=%d\tx+w=%d\ty+h=%d\n", + WinRect.x,WinRect.y,WinRect.x+WinRect.width,WinRect.y+WinRect.height); + #endif } } XFree((char *)children); @@ -1355,6 +1406,8 @@ #endif return 1; } +/** add to the region snscr strips of height + MaxYStep+MaxSnowFlakeHeight below every window-top */ void RCSR() { XDestroyRegion(rscrr); rscrr = XCreateRegion(); @@ -1369,6 +1422,7 @@ XUnionRegion(rscrr,snscr, snscr); if (SnowOffset != 0) XOffsetRegion(snscr,0,SnowOffset); } +/** create region 'sar' where snow may accumulate */ void MASR() { XRectangle AllowRect; XDestroyRegion(sar); @@ -1378,7 +1432,7 @@ XOffsetRegion(sar, 0,-MaxWinSnowDepth); XSubtractRegion(sar,Wr, sar); } - if (!NoKeepSWin) { + if (!NoKeepSBot) { AllowRect.x = 0; AllowRect.y = display_height - MaxScrSnowDepth; AllowRect.width = display_width - 1; @@ -1436,6 +1490,8 @@ #endif return 1; } +/** clear a given rectangle and remove it (plus margins related to + flake-size and snow-movement) from the snow-region snscr */ void HEAr(int X,int Y,int W, int H) { int AddX,AddY; int ClearX, ClearY; ------------ END: diff-patch for xsnow.c -------------- ------------ BEGIN: diff-patch for xsnow.h -------------- --- xsnow-1.42/xsnow.h 2000-12-19 21:24:58.000000000 +0100 +++ xsnow-1.42resizeable/xsnow.h 2010-02-06 20:58:21.000000000 +0100 @@ -9,6 +9,10 @@ #define INITIALSCRPAINTSNOWDEPTH 8 /* Painted in advance */ #define INITSCRSNOWDEPTH 50 /* Will build up to INITSCRSNOWDEPTH */ #define SNOWFREE 25 /* Must stay snowfree on display :) */ +#define CLEANONEXPOSE 1 /* clean memory of accumulated snow on expose + events without window change (e.g. VT + switching); increases server burden + during window movements */ /* ------------------------------------------------------------------ */ ------------ END: diff-patch for xsnow.h -------------- -- System Information: Debian Release: squeeze/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.32-trunk-686 (SMP w/1 CPU core) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages xsnow depends on: ii libc6 2.10.2-5 Embedded GNU C Library: Shared lib ii libx11-6 2:1.3.3-1 X11 client-side library ii libxext6 2:1.1.1-2 X11 miscellaneous extension librar ii libxpm4 1:3.5.8-1 X11 pixmap library ii procps 1:3.2.8-5 /proc file system utilities xsnow recommends no packages. xsnow suggests no packages. -- no debconf information -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org