Subject: Menu problems with 2.1.7

From: Jay <[email-masked]>
Date: Sat, 2 Jan 1999 18:38:40 -0500 (EST)

Hi Everyone,

	I Just CVSup'ed 2.1.7 and have the following two problems to
report. I'm not sure if they are related to bugs already reported, so I
wanted to bring them up here before I sent in an official bug report.

>From CVS @ Jan  2 13:37

Problem 1:

	SetMenuStyle with a stylename other than "*" core dumps.
	e.g. SetMenuStyle bob mwm 

Problem 2: 

	Menus are not cleaning up after themselves.  I am using a
DGradient menuface.  Occasionally, After dragging down over my menu I wind
up with these 'default-grey' patches on my menu. IE: When I go to a
sub-menu or drag my mouse down along the right side of the menu (over the
triangles) causing the sub-menu's to pop-up and then disappear, sometimes
I wind up with my DGradient menu covered in plain-grey blocks where the
pop-ups overlapped the original menu.  I realize I haven't explained this
very well... so... look at the two jpegs @ http://oneway.com/jay/fvwm/

My SetMenuStyle line:
	SetMenuStyle * MenuFace DGradient 64 1 #455561 100 #102020

I can reproduce both of these at will... Should I put these into
jitterbug?  

Jay

PS - Excerpt from fvwm2 -debug -f system.fvwm2rc (on 'sample.fvwm2rc' with
setmenustyle line added)

----

[FVWM][ReadSubFunc]: <<DEBUG>> about to exec: 'HilightColor black
palevioletred
'
[FVWM][ReadSubFunc]: <<DEBUG>> about to exec: 'DeskTopSize 2x2
'
[FVWM][ReadSubFunc]: <<DEBUG>> about to exec: 'MenuStyle maroon grey60
grey40 -adobe-times-bold-r-*-*-14-*-*-*-*-*-*-* fvwm
'
[FVWM][ReadSubFunc]: <<DEBUG>> about to exec: 'SetMenuStyle bob mwm
'
Segmentation fault (core dumped)

-----

--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dominik Vogt <[email-masked]>
Date: Sun, 3 Jan 1999 09:34:26 +0100

> 	e.g. SetMenuStyle bob mwm 

fixed

> 	SetMenuStyle * MenuFace DGradient 64 1 #455561 100 #102020

fixed

Bye

Dominik

--
Dominik Vogt, [email-masked]
Reply-To: [email-masked]

---

From: Jay <[email-masked]>
Date: Sun, 3 Jan 1999 14:54:32 -0500 (EST)

> > 	SetMenuStyle * MenuFace DGradient 64 1 #455561 100 #102020

	This one is still broken.  CVSupped 14:13 EST, Jan 3.  Lots of
flicker as well when navigating the menus which you didn't see in 2.1.4.  
I've got them both running, just to verify it...  with 2.1.7 It's like the
menu is drawn in grey and then re-drawn using the gradient?  Is that
indeed what is happenning?  2.1.4 seems to draw initially with the
gradient...  I'm trying to figure out the menuing code, but I must
admit I'm a bit lost right now. 

Jay

---

From: Jay <[email-masked]>
Date: Sun, 3 Jan 1999 15:14:22 -0500 (EST)

Noticed one difference when using debug-mode on both version 2.1.4 and
2.1.7.  

It seems that when using a dgradient in 2.1.4 the box was initially filled
with the left-most color on the dgradient line, and then covered with the
gradient. (more accurately, the 'background' color specified in the old
setmenustyle command)  

In 2.1.7- the box for the menu is initally filled with the default grey.
If you specify a background color as well then the menus look much
better....

Which leads me to two questions:

	Is it possible to make the default background the first color of
the gradient, if no other is specified?

	Is there some way to 'clear' the default style so that it doesn't
take unspecified options from some previous definition?  (perhaps a 'reset
to default' type thing?)

Also, the flicker is because the DGradient is re-drawn over the initial
menu every time a sub-menu is popped up and then removed (re-exposing the
initial menu).  Forgive me if I am being daft, please, but couldn't we
save the contents of the screen for the menu beneath the popup and restore
it rather than re-drawing the entire gradient(and hence the entire menu) ?

As I mentioned before, I'm still trying to get my fingers around the menu
code... so forgive me if I'm missing something.

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 4 Jan 1999 05:14:12 +0100

On Sun, Jan 03, 1999 at 02:54:32PM -0500, [email-masked] wrote:
> This one is still broken.

What do you think is still broken? I don't think you still get
your 'grey blocks'.

Bye

Dominik

-- 
Dominik Vogt, Hewlett-Packard GmbH, Dept. BVS
Herrenberger Str.130, 71034 Boeblingen, Germany
phone: 07031/14-4596, fax: 07031/14-3883, [email-masked]
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 4 Jan 1999 05:27:45 +0100

> the gradient, if no other is specified?

I don't think so.

> take unspecified options from some previous definition?  (perhaps a 'reset

Yes: 'MenuStyle * fvwm' resets everything to default.
 
> initial menu).

Yes. This is because when a submenu is unmapped the parent menu gets
an expose event to redraw itself. But before it arrives another menu
item is selected. If you have 3d hilighting or background hilighting
on the menu, I'll have to save the new item before hilighting it. But
at this time it contains only the grey blocks you saw. The only way
to get that right is by redrawing the menu right now.

> Forgive me if I am being daft, please, but couldn't we

That is a task of the X server (backing storage). Please have a look
at the last wuestion in the FAQ. I added that recently. Apart from
that, how would you know which menus are overlapped? It's easy with
the parent menu, but after that it gets complicated. If you don't
want the flicker the best solution is to make sure the menus don't
overlap. And be sure you have backing store enabled.

> code... so forgive me if I'm missing something.

Don't try it, it's not worth the effort ;-) I understand quite well
what is happening (I wrote it). If I'd seen a better solution I'd
have done it. German had an idea about converting the gradient
into a pixmap and use it as background. This solution is fast
and without flicker, but I assume it consumes much more memory.

Perhaps we'll do it this way after 2.2.

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Sun, 3 Jan 1999 23:42:26 -0500 (EST)

> > the gradient, if no other is specified?

	No Problem.  Adding the 'background #c01010' thing works well
enough.

> Yes: 'MenuStyle * fvwm' resets everything to default.

	Thank you.

> Yes. This is because when a submenu is unmapped the parent menu gets
[ . . . ]
> to get that right is by redrawing the menu right now.

	Gotcha.

> what is happening (I wrote it).

	Too Late.... I've been playing with Xnest and debugging all day...
I think I almost understand how it works... at least on the visual-side.

> If I'd seen a better solution I'd

	I've been experimenting with exactly that for a few hours now..
and have managed to make it work.  The way I'm doing it is to create a
pixmap, draw the gradient to it and set the background of the menu window
to the pixmap.  Then free the pixmap.  Therefore it doesn't take much
extra memory as we are only allocating it as long as it is needed...  I
imagine that it is a hair slower than the way we are doing it now... but
actually using it I can't tell the difference.  It does reduce the
overhead of redrawing the gradient everytime a submenu is exposed.

Would you like a patch... just to look at perhaps?  It's a change only to
PaintMenu() in menus.c.. (it probably should be more... but for
demonstration purposes...)

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 4 Jan 1999 05:54:13 +0100

> I think I almost understand how it works... at least on the visual-side.

Next time you can as well start with asking me. Rewriting the
menu code was one of the first things I did for fvwm and I do
understand some things quite well.
 
> demonstration purposes...)

Go ahead. I don't like the current implementation and if the patch
is simple enough I'll replace it before 2.2.

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Mon, 4 Jan 1999 01:37:45 -0500 (EST)

> is simple enough I'll replace it before 2.2.

Well, here it is... I did not do anything except change it so that the
gradients are done into a pixmap rather than the window itself.  
Obviously, if we were to incorporate this approach, we'd want to do less
during expose events, (ie we could avoid re-building the gradient each
time) etc.  

Jay

---  context-style diff follows:
*** menus.c	Sun Jan  3 17:41:37 1999
--- menus.c.new	Mon Jan  4 01:06:17 1999
***************
*** 1915,1920 ****
--- 1915,1924 ----
    MenuStyle *ms = mr->ms;
    register int type;
    XRectangle bounds;
+   Pixmap pmap;			
+   GC	pmapgc;
+   XGCValues gcv;
+   unsigned long gcm = 0;
  
  #ifdef PIXMAP_BUTTONS
    Picture *p;
***************
*** 1923,1929 ****
--- 1927,1938 ----
  #endif
  #ifdef GRADIENT_BUTTONS
    mr->flags.f.painted = 1;
+   gcm = GCLineWidth;
+   gcv.line_width = 3;
+   pmap = XCreatePixmap(dpy, Scr.Root, mr->width, mr->height, Scr.d_depth);
+   pmapgc = XCreateGC(dpy, pmap, gcm, &gcv);
  #endif
+ 
    if( ms )
      {
        type = ms->look.face.type;
***************
*** 1950,1958 ****
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short x = i * bounds.width / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, Scr.TransMaskGC,
  			   ms->look.face.u.grad.pixels[i++ ]);
! 	    XFillRectangle(dpy, mr->w, Scr.TransMaskGC,
  			   bounds.x + x, bounds.y,
  			   dw, bounds.height);
  	  }
--- 1962,1970 ----
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short x = i * bounds.width / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, pmapgc,
  			   ms->look.face.u.grad.pixels[i++ ]); 
! 	    XFillRectangle(dpy, pmap, pmapgc,
  			   bounds.x + x, bounds.y,
  			   dw, bounds.height); 
  	  }
***************
*** 1964,1972 ****
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short y = i*bounds.height / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, Scr.TransMaskGC,
  			   ms->look.face.u.grad.pixels[i++]);
! 	    XFillRectangle(dpy, mr->w, Scr.TransMaskGC,
  			   bounds.x, bounds.y + y,
  			   bounds.width, dh);
  	  }
--- 1978,1986 ----
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short y = i*bounds.height / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, pmapgc,
  			   ms->look.face.u.grad.pixels[i++]);
! 	    XFillRectangle(dpy, pmap, pmapgc,
  			   bounds.x, bounds.y + y,
  			   bounds.width, dh);
  	  }
***************
*** 1984,1999 ****
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, 0, i*ds, i, 0);
  	    }
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, i, mr->height, mr->width,
  			i*ds);
  	    }
  	  }
--- 1998,2013 ----
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, 0, i*ds, i, 0);
  	    }
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, i, mr->height, mr->width,
  			i*ds);
  	    }
  	  }
***************
*** 2004,2019 ****
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, 0, i, i*ds, 0);
  	    }
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, i*ds, mr->height,
  			mr->width, i);
  	    }
  	  }
--- 2018,2033 ----
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, 0, i, i*ds, 0);
  	    }
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, i*ds, mr->height,
  			mr->width, i);
  	    }
  	  }
***************
*** 2031,2047 ****
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, 0, mr->height - i*ds, i,
  			mr->height);
  	    }
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, i, 0, mr->width,
  			mr->height - i*ds);
  	    }
  	  }
--- 2046,2062 ----
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, 0, mr->height - i*ds, i,
  			mr->height);
  	    }
  	    for(i = 0; i < mr->width; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, i, 0, mr->width,
  			mr->height - i*ds);
  	    }
  	  }
***************
*** 2052,2072 ****
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, 0, mr->height - i, i*ds,
  			mr->height);
  	    }
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, Scr.TransMaskGC,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, mr->w, Scr.TransMaskGC, i*ds, 0, mr->width,
  			mr->height - i);
  	    }
  	  }
          }
          break;
  #endif  /* GRADIENT_BUTTONS */
  #ifdef PIXMAP_BUTTONS
--- 2067,2092 ----
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, 0, mr->height - i, i*ds,
  			mr->height);
  	    }
  	    for(i = 0; i < mr->height; i++)
  	    {
  	      if( i % dc == 0 )
! 		XSetForeground(dpy, pmapgc,
  			       ms->look.face.u.grad.pixels[cindex++]);
! 	      XDrawLine(dpy, pmap, pmapgc, i*ds, 0, mr->width,
  			mr->height - i);
  	    }
  	  }
          }
+ 	XSetWindowBackgroundPixmap(dpy, mr->w, pmap);
+	flush_expose(mr->w);
+       XClearWindow(dpy,mr->w);
+ 	XFreeGC(dpy, pmapgc);
+ 	XFreePixmap(dpy, pmap);
          break;
  #endif  /* GRADIENT_BUTTONS */
  #ifdef PIXMAP_BUTTONS

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 4 Jan 1999 08:10:28 +0100

> during expose events, (ie we could avoid re-building the gradient each

If the patch is complete otherwise I will take care of reworking the
current logic. No problem.

Bye

Dominik

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 4 Jan 1999 18:34:12 +0100

> during expose events, (ie we could avoid re-building the gradient each

That doesn't work very well:

1) The menus are still painted in grey the first time they are mapped.
   This probably is because the background is set after the window
   has been mapped. Is it possible to change that?

2) It still flickers although not as bad as before.

3) If you have large menus it is **slow**. On my machine mapping a
   menu filling 75% of the screen takes several seconds. Using a
   simple but long menu that covers about 5% of the screen is
   still unbearably slow. Perhaps this would be acceptable if this
   delay occured only once per menu. Do we have to redraw the pixmap
   every time the menu is painted? It should be only necessary if the
   gradient or the size of the menu has changed.

I don't understand why these pixmap operations are so slow. I had
the same problem with XGetImage when I used XYPixmap. After changing
to ZPixmap it runs smoothly now. This is probably the same problem.
Redrawing the whole menu is much faster than this. There must be
a way to prevent the delay.

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Mon, 4 Jan 1999 15:30:44 -0500 (EST)

>    has been mapped. Is it possible to change that?

	You can set the background before you map the window, but I'm not
sure where the mapping is done or how / where / if we could move it.

>    gradient or the size of the menu has changed.

	No we don't... If we cache the pixmaps.  But this brings the bloat
factor into it.  Of course... if we were to start caching the pixmaps...
then _technically_ we could draw the menus onto the pixmaps and never have
to redraw anything unless the menu changed... which could be nice... 
Another option would be to create a temporary window.  Draw into that and
XCopyArea to the pixmap.  If the drawing into a pixmap is
significantly slower than drawing into a window, that could solve the
problem.  

sigh.. What I would give for a nice fast pixmap-scaling routine. Then we
could cache one pixmap and scale it appropriately when necessary.  

I'll think on this... 

> a way to prevent the delay.

Looking in on this too.

Jay

---

From: Jay <[email-masked]>
Date: Mon, 4 Jan 1999 23:23:09 -0500 (EST)

> sure where the mapping is done or how / where / if we could move it.

	I tried it... I created a function called 'DoMenuBackground' which
basically generates the gradient (or pixmap) and then assigns the window
background to the pixmap.  (or solid color, as neccesary).  I then dropped
this into FPopupMenu Between the XMoveWindow and XMapRaised window.  Thus
setting the background before it maps it.  It works... and avoids the
painted-in-grey first business.  

> > 2) It still flickers although not as bad as before.
	I also removed the background-building in PaintMenu (as it is all
done in DoMenuBackground in my version)  The flicker is pretty much gone
now.

> >    gradient or the size of the menu has changed.

	Still have this problem.  It is unbearably slow the first time.  
I just realized that if we set the background of a window to a pixmap, the
server caches it anyway, until that window is destroyed (or the background
is changed)  This means that on large menus we will eat up alot of space
on the server as long as we use the background pixmap method.  And it will
stay that way until the menu-window is destroyed or the background is
changed.  I've just tested it and verified.  (2 meg on a full-
screen-height menu.  uggh)

So looks like we are back to painting it each time by hand.  

But Wait!!!

We can take advantage of the fact that the BackgroundPixmap tiles... at
least on horizontal and vertical gradients.  In those cases we can
create a small pixmap (say, 20 pixels high for a Horizontal) and set the
background pixmap to that.  The server will tile it (nice and fast) for us
without holding on to a huge chunk of memory... even on large windows. (an
1152 x 20 pixmap would only use ~90k max (on a 32bpp display))

What do you think of this:

	On HGradients and VGradients we create a small pixmap of
appropriate size and set it to the background.  Once the window has been
created and the background has been set, we don't have to worry about the
background anymore (unless the menu changes).  All it would take to
'redraw' our gradient is 'XClearWindow'  (heck, we could do the
gradient-building / background setting at MakeMenu time if we got really
excited =P )
  	This would speed up the menu drawing significantly (at least for
everything but the diagonal gradients)  In addition, the initial drawing
of the gradient would be faster because of the small size of the pixmap.

I think that the DGradients and BGradients are gonna give us a hard time
no matter what we do.  But we can clean house on the H and VGradients...

Thoughts?

Jay

PS- Please pardon my ranting... It all came together as I wrote.

PPS- it's too bad about the Dgradients though.... I liked those best. =(

---

From: Tim Phipps <[email-masked]>
Date: Tue, 05 Jan 1999 09:46:17 +0000

> could cache one pixmap and scale it appropriately when necessary.

ISTR that one of the first features of Enlightenment was a library to do
pixmap scaling, it might be worth trawling through the sources.

Cheers,
Tim.

---

From: Michael M Han <[email-masked]>
Date: Tue, 05 Jan 1999 10:15:58 -0800

Previously...
>pixmap scaling, it might be worth trawling through the sources.

Enlightenment, I think, put all of its graphics routines into imlib. I
don't know what imlib's dependencies are (maybe gtk+ & glib) but I'm
pretty sure it'd be GPL'd. Just thought I'd mention it in case
anyone's really interested in linking a library for more graphics
capabilities. Personally, I think additional library dependencies
could get kinda irksome. I suppose ImageMagick's also got some
potential there.

Overall though, I'd find it really annoying if one needed, in order to
build fvwm, some graphics lib like imlib or libMagick, which
consequently further require libpng, libgif, libjpeg, etc... Just an
observation.
_________
mike ([email-masked])
I will not dissect things unless instructed
 - The collected wisdom of Bart Simpson
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Jason L Tibbitts III <[email-masked]>
Date: 05 Jan 1999 12:47:35 -0600

>>>>> "MMH" == Michael M Han <[email-masked]> writes:

MMH> Enlightenment, I think, put all of its graphics routines into imlib. I
MMH> don't know what imlib's dependencies are (maybe gtk+ & glib) but I'm
MMH> pretty sure it'd be GPL'd.

Imlib is GPL'd and has dependencies neither on gtk+ nor on glib as far as I
can tell.  The gtk-imlib stuff of course has the obvious dependencies, but
that's only useful if you want to use imlib within gtk widgets.

Imlib will use Imagemagik if you have it.  It does also require a ton of
format libraries, like libpng and libjpeg, some of which aren't the
simplest things to build.

It might be nice to use it if it's there, but this is really in the range
of serious bloat.

 - J<

---

From: Tim Phipps <[email-masked]>
Date: Wed, 06 Jan 1999 08:58:23 +0000

> consequently further require libpng, libgif, libjpeg, etc... Just an

I wasn't suggesting linking in libraries to get the code, just cut and
paste into fvwm's lib.

Cheers,
Tim.

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 6 Jan 1999 13:57:15 +0100

On Mon, Jan 04, 1999 at 11:23:09PM -0500, Jay wrote:
> 'redraw' our gradient is 'XClearWindow'

> (heck, we could do the

That would slow down startup a lot

> no matter what we do.  But we can clean house on the H and VGradients...

This doesn't satisfy me a bit. It sounds so complicated for so little
gain. German suggested something about creating and xpm file for the
gradient. But then this would only work if xpm support was compiled
in :( I think we'll leave it as it is for 2.2 and try to find a clean
solution then.

Bye

Dominik

---

From: Tim Phipps <[email-masked]>
Date: Wed, 06 Jan 1999 14:28:23 +0000

Jay wrote:
> appropriate size and set it to the background.

For H/V gradients you could use a one pixel tall/wide pixmap which
should make them tiny (better chance of the server being able to cache
them). For D gradients you can set the menu background pixmap to None to
remove the flicker before painting.

Cheers,
Tim.

---

From: Jay <[email-masked]>
Date: Wed, 6 Jan 1999 11:39:12 -0500 (EST)

> remove the flicker before painting.

	Wouldn't making the H/V gradients one pixel wide increase what the
server has to do to tile it?  I wonder where the break-even point is.

I don't understand what you mean about setting the background pixmap to
None... would that, in effect, make a transparent window until we drew on
it?  

Jay

---

From: Jay <[email-masked]>
Date: Wed, 6 Jan 1999 11:47:00 -0500 (EST)

> I wasn't suggesting linking in libraries to get the code, just cut and

	my thought for this is to take a libxpm-ish approach... IE: Build
an XImage of the gradient locally, and then XPutImage it to the window.
This would be much faster than drawing the gradient using X-drawing
routines...  and we wouldn't then be dependant on any external libraries.

Jay

---

From: Tim Phipps <[email-masked]>
Date: Wed, 06 Jan 1999 17:21:36 +0000

> server has to do to tile it?  I wonder where the break-even point is.

Very difficult to work out a break even point as each server may be
different with each graphics card.  Hopefully the graphics card will
have functions to tile and so the XServer won't have more work to do
with one pixel tiles and the hardware will be just as fast since the
total number of bits to set will be the same. (I'm just guessing)

> None... would that, in effect, make a transparent window until we drew on

Yes, so you don't get flicker because you can't see the window before it
is drawn.  Well, it's not really transparent, that would imply that a
window underneath it would be visible and any changes in that window
would show. What really happens when a window with background "none" is
mapped is that that area on screen that it takes up is frozen.  What was
underneath is still visible but any changes don't show.  Have a look at
the source to xrefresh, I'm not sure how fvwm does refreshing.

Cheers,
Tim.

---

From: Jay <[email-masked]>
Date: Wed, 6 Jan 1999 12:24:07 -0500 (EST)

> That would slow down startup a lot

	Yeah... Sorry... got a bit too excited =P

> in :( I think we'll leave it as it is for 2.2 and try to find a clean

	Gotcha... I have a good idea about this... drawing the gradient
locally and then sending the info to the Xserver vi XPutImage.  Doing it
locally would make it much faster than drawing via Xcalls... Then we could
do whatever was deemed appropriate (making them background pixmaps or
simply drawing them, I mean) also we wouldn't then be dependant on any
external libraries.  I still think that the D/B Gradients are going to
give us trouble regardless though..  This is assuming that XPutImage will
outpace the line-drawing method. (which it should)

On an semi-related note, I notice we use XGetImage and XPutImage...
since we are just holding and restoring an image, it would probably be a
good idea to use a Pixmap and XCopyArea instead...  XGetImage and
XPutimage transfer the image from the server to the client and vice-versa
respectively.  We aren't doing anything to them locally, so it would be
more efficient to create a Pixmap and XCopyArea into the pixmap and then
back to the window as all the data transfer stays within the server.  It
should be much faster for that reason alone.

(XGetImage and XPutImage also have the overhead of converting byte and bit
order from client to server during each call)

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 6 Jan 1999 23:33:34 +0100

> should be much faster for that reason alone.

We won't get around XCopyArea anyway in the long run. The menu
might be partially off screen and XGetImage fails miserably
then (I've already seen if).

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Wed, 6 Jan 1999 21:20:22 -0500 (EST)

> then (I've already seen if).

	Ok... So I've put together a new patch.  This is off of the
original 2.1.7...   This patch does two things:

	Switches to XCopyArea from the XGetImage and XPutImage method of
saving the backdrop.  

	Uses a small Pixmap background for HGradient and VGradient menus.
It also does not need to redraw the gradient (on H/V gradients) unless the
menu has changed.

	I ran across the XGetImage problem you mentioned.  I've checked
and XCopyArea is not susceptable to the same problem.  This patch speeds
up the menu-redraws alot when using HGradients and VGradients with a
minimum of overhead.  (Especially on large menus.  wow.)

	Please check it out and let me know what you think.

Jay	

---snip---

*** menus.c	Wed Jan  6 17:21:25 1999
--- menus.c.new	Wed Jan  6 20:19:04 1999
***************
*** 1387,1414 ****
        if (iy + ih > mh)
  	ih = mh - iy;
        /* grab image */
!       mi->mr->stored_item.image = XGetImage(dpy, mi->mr->w, 0, iy, mw, ih,
! 					    AllPlanes, ZPixmap);
        mi->mr->stored_item.y = iy;
      }
!     else if (f == False && mi->mr->stored_item.image != None)
      {
        /* ungrab image */
!       XPutImage(dpy, mi->mr->w, mi->mr->ms->look.MenuGC,
! 		mi->mr->stored_item.image,
! 		0, 0,
! 		0, mi->mr->stored_item.y,
! 		mi->mr->stored_item.image->width,
! 		mi->mr->stored_item.image->height);
!       XDestroyImage(mi->mr->stored_item.image);
!       mi->mr->stored_item.image = None;
      }
      break;
    default:
!     if (mi->mr->stored_item.image != None)
      {
!       XDestroyImage(mi->mr->stored_item.image);
!       mi->mr->stored_item.image = None;
      }
      break;
    }
--- 1387,1423 ----
        if (iy + ih > mh)
  	ih = mh - iy;
        /* grab image */
!       mi->mr->stored_item.stored = XCreatePixmap(dpy, Scr.Root, mw,ih, Scr.d_depth);
!       XCopyArea(dpy, mi->mr->w, mi->mr->stored_item.stored, 
! 		mi->mr->ms->look.MenuGC, 0, iy, mw, ih, 0, 0);
!       DBUG("SetMenuItemSelected", itoa(mw));
!       DBUG("SetMenuItemSelected", itoa(ih));
        mi->mr->stored_item.y = iy;
+       mi->mr->stored_item.width = mw;
+       mi->mr->stored_item.height = ih;
      }
!     else if (f == False && mi->mr->stored_item.width != 0)
      {
        /* ungrab image */
! 
! 	XCopyArea(dpy, mi->mr->stored_item.stored, mi->mr->w, 
! 		  mi->mr->ms->look.MenuGC, 0,0, mi->mr->stored_item.width, 
! 		  mi->mr->stored_item.height, 0, mi->mr->stored_item.y);
! 
!         XFreePixmap(dpy, mi->mr->stored_item.stored);
!         mi->mr->stored_item.width = 0;
!         mi->mr->stored_item.height = 0;
!         mi->mr->stored_item.y = 0;
! 
      }
      break;
    default:
!     if (mi->mr->stored_item.width != 0)
      {
!       XFreePixmap(dpy, mi->mr->stored_item.stored);
!       mi->mr->stored_item.width = 0;
!       mi->mr->stored_item.height = 0;
!       mi->mr->stored_item.y = 0;
      }
      break;
    }
***************
*** 1921,1927 ****
--- 1930,1944 ----
    int border = 0;
    int width, height, x, y;
  #endif
+ 
  #ifdef GRADIENT_BUTTONS
+   Pixmap pmap;
+   GC	 pmapgc;
+   XGCValues gcv;
+   unsigned long gcm = 0;
+   gcv.line_width=3;
+   gcm = GCLineWidth;
+ 
    mr->flags.f.painted = 1;
  #endif
    if( ms )
***************
*** 1944,1975 ****
          bounds.height = mr->height;
  
          if ( type == HGradMenu ) {
  	  register int i = 0;
  	  register int dw;
  	  dw= (float) bounds.width / ms->look.face.u.grad.npixels + 1;
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short x = i * bounds.width / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, Scr.TransMaskGC,
  			   ms->look.face.u.grad.pixels[i++ ]);
! 	    XFillRectangle(dpy, mr->w, Scr.TransMaskGC,
! 			   bounds.x + x, bounds.y,
! 			   dw, bounds.height);
  	  }
          }
          else if ( type == VGradMenu )
          {
  	  register int i = 0;
  	  register int dh = bounds.height / ms->look.face.u.grad.npixels + 1;
  	  while (i < ms->look.face.u.grad.npixels)
            {
  	    unsigned short y = i*bounds.height / ms->look.face.u.grad.npixels;
! 	    XSetForeground(dpy, Scr.TransMaskGC,
  			   ms->look.face.u.grad.pixels[i++]);
! 	    XFillRectangle(dpy, mr->w, Scr.TransMaskGC,
! 			   bounds.x, bounds.y + y,
! 			   bounds.width, dh);
  	  }
          }
          else if ( type == DGradMenu )
          {
--- 1961,2017 ----
          bounds.height = mr->height;
  
          if ( type == HGradMenu ) {
+ 	  if (mr->backgroundset == 0)
+ 	  {
  	     register int i = 0;
  	     register int dw;
+ 
+              pmap = XCreatePixmap(dpy, Scr.Root, mr->width, 5, Scr.d_depth);
+ 	     pmapgc = XCreateGC(dpy, pmap, gcm, &gcv);
+    
+ 	     bounds.width = mr->width;
  	     dw= (float) bounds.width / ms->look.face.u.grad.npixels + 1;
  	     while (i < ms->look.face.u.grad.npixels)
               {
  	       unsigned short x = i * bounds.width / ms->look.face.u.grad.npixels;
! 	       XSetForeground(dpy, pmapgc,
  			      ms->look.face.u.grad.pixels[i++ ]);
! 	       XFillRectangle(dpy, pmap, pmapgc,
! 			      x, 0,
! 			      dw, 5);
! 	     }
! 	     XSetWindowBackgroundPixmap(dpy, mr->w, pmap);
! 	     XFreeGC(dpy,pmapgc);
! 	     XFreePixmap(dpy,pmap);
! 	     mr->backgroundset = 1;
  	  }
+ 	  XClearWindow(dpy, mr->w);
          }
          else if ( type == VGradMenu )
          {
+ 	  if (mr->backgroundset == 0)
+ 	  {
  	     register int i = 0;
  	     register int dh = bounds.height / ms->look.face.u.grad.npixels + 1;
+ 
+              pmap = XCreatePixmap(dpy, Scr.Root, 5, mr->height, Scr.d_depth);
+ 	     pmapgc = XCreateGC(dpy, pmap, gcm, &gcv);
+ 
  	     while (i < ms->look.face.u.grad.npixels)
               {
  	       unsigned short y = i*bounds.height / ms->look.face.u.grad.npixels;
! 	       XSetForeground(dpy, pmapgc,
  			      ms->look.face.u.grad.pixels[i++]);
! 	       XFillRectangle(dpy, pmap, pmapgc,
! 			      0, y,
! 			      5, dh);
! 	     }
! 	     XSetWindowBackgroundPixmap(dpy, mr->w, pmap);
! 	     XFreeGC(dpy,pmapgc);
! 	     XFreePixmap(dpy,pmap);
! 	     mr->backgroundset = 1;
  	  }
+ 	  XClearWindow(dpy, mr->w);
          }
          else if ( type == DGradMenu )
          {
***************
*** 2444,2449 ****
--- 2486,2492 ----
    }
  
    mr->width = mr->width0 + mr->width + mr->width2 + mr->xoffset;
+   mr->backgroundset = 0;
  
    mr->w = XCreateWindow (dpy, Scr.Root, 0, 0, (unsigned int) (mr->width),
  			 (unsigned int) mr->height, (unsigned int) 0,
***************
*** 2883,2889 ****
    tmp->last = NULL;
    tmp->selected = NULL;
  #ifdef GRADIENT_BUTTONS
!   tmp->stored_item.image = None;
  #endif
    tmp->next  = Scr.menus.all;
    tmp->continuation = NULL;
--- 2926,2932 ----
    tmp->last = NULL;
    tmp->selected = NULL;
  #ifdef GRADIENT_BUTTONS
!   tmp->stored_item.width = 0;
  #endif
    tmp->next  = Scr.menus.all;
    tmp->continuation = NULL;

*** menus.h	Wed Jan  6 20:26:19 1999
--- menus.h.new	Wed Jan  6 20:03:30 1999
***************
*** 178,184 ****
  #ifdef GRADIENT_BUTTONS
      struct
      {
!       XImage *image; /* storage pointer for selected item */
        int y;
      } stored_item;
  #endif
--- 178,186 ----
  #ifdef GRADIENT_BUTTONS
      struct
      {
!       Pixmap stored;
!       int width;
!       int height;
        int y;
      } stored_item;
  #endif
***************
*** 197,202 ****
--- 199,205 ----
      short width2;		/* width of the menu for 2nd col */
      short width0;               /* width of the menu-left-picture col */
      short items;		/* number of items in the menu */
+     short backgroundset;	/* is win background set for this menu ?? */
      Bool in_use;
      int func;
      Picture *sidePic;

---

From: Jay <[email-masked]>
Date: Thu, 7 Jan 1999 11:00:41 -0500 (EST)

> total number of bits to set will be the same. (I'm just guessing)
	I tried a 5-pixel-size window in the patch I submitted yesterday.
It was blazing-fast.  I'm satisfied with that (unless someone tells me
it's different on their machine)

> the source to xrefresh, I'm not sure how fvwm does refreshing.

	It seems to be a little different on my machine.  If you set the
background of the window to 'None' it does not redraw in solid color...
but it does not leave the window below it (in my case, the root window)
showing... instead it keeps whatever contents were on the screen (above or
below) until the window is redrawn... A bit faster, but very disturbing to
look at.  (Especially if animation is on) I'd rather see the flicker...
It's too bad, that would have been useful.

Jay

---

From: Tim Phipps <[email-masked]>
Date: Thu, 07 Jan 1999 17:20:55 +0000

> It's too bad, that would have been useful.

This sounds weird. Are you saying that if you map a window with a "None"
background the server draws stuff on the screen before giving the expose
event?  If so it sounds like a bug in your server.

Cheers,
Tim.

---

From: Jay <[email-masked]>
Date: Thu, 7 Jan 1999 13:00:57 -0500 (EST)

> event?  If so it sounds like a bug in your server.

	No... Here is an example.  Assuming the backgroundpixmap of all
menus is set to None and Animation is on.  You open your root-menu near
the edge of the screen, go to a menu selection that has a popup menu...
then you select another popup off of that... The menu happily moves over
obscuring your root menu.  Then you decide to go back to your original
menu... the last popup goes away, and the windows where the root and
submenu were are now filled with the contents of the popup that just
closed... (as if that particular portion of the screen was not redrawn,
which is indeed what is happening) then it is refilled with the proper
information. It is even more disturbing if a menu slides completely on and
then off of a menu... you have little chunks-o-menu all over the original
menu.  It is u-u-ugly.

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 7 Jan 1999 23:45:15 +0100

> 	Please check it out and let me know what you think.

Neat. It works quite well. And it fixed the bug with hilighting
in menus that are not fully on the screen (or obscured otherwise).
I'll commit that one. There's only a bit flickering left. If we
can avoid that it's perfect. And of course the problem with
B and D gradients :(

Did you clean up my attempts of getting this straight?

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Fri, 8 Jan 1999 17:13:38 -0500 (EST)

> can avoid that it's perfect. And of course the problem with

Great!! glad to hear it's going in! woo-woo!

 As far as the remaining flicker goes: I don't know what to do to get the
remaining flicker out of there. I don't know if it is just my Xserver, but
I don't seem to get any saveunders at all.  I am not sure if all the menus
have to be set so that backingstore is defined as 'whenmapped' for it to
work... or if my Xservers are just broke.

> Did you clean up my attempts of getting this straight?

	I don't understand what you mean... so I guess no. =)

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Sat, 9 Jan 1999 08:18:16 +0100

> work... or if my Xservers are just broke.

I thought from the start that your X server does something wrong.
Have you tried to start the Xserver with '-wm' to force backing
storage on?
 
> 	I don't understand what you mean... so I guess no. =)

Ah, I think I'll look myself. Don't know how to describe what I did
without looking through the code. In particular I coded a lot of
unnecessary PaintMenu calls.

Bye

Dominik

---

From: Jay <[email-masked]>
Date: Wed, 13 Jan 1999 08:53:15 -0500 (EST)

> Have you tried to start the Xserver with '-wm' to force backing

	Yeah... but I'm not convinced it is doing it.  I use both
AcceleratedX and XFree... and neither of them do it...  I haven't tried
really hard to test it, though.

> unnecessary PaintMenu calls.

	I did notice alot of paintmenu calls, but I didn't want to mess
with them as I am not so familiar with the menu system.  

Jay

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 13 Jan 1999 15:31:35 +0100

> really hard to test it, though.

It should use backing storage unless you tell it otherwise (perhaps
you see a difference when you explicitly turn it off wit '-bs'?) or
if it runs out of resources. Since I could reproduce the bugs you
reported only when I switched backing storage off I'm convinced your
X server isn't using it. Do you have a lot of big overlapping
windows perhaps?

> with them as I am not so familiar with the menu system.  

Don't worry about that, I've cleaned that up in the meantime.

Bye

Dominik