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

Reply via email to