[comp.windows.x] BUG: XtSetValues assumes all non-widgets are RectObjs

gnb@bby.oz.au (Gregory N. Bond) (04/17/91)

[This has been sent to xbugs]

			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu


VERSION:
    R4, MIT tape patched to fix-18

CLIENT MACHINE and OPERATING SYSTEM:
	Any

DISPLAY TYPE:
	Any

WINDOW MANAGER:
	Any

AREA:
	Xt

SYNOPSIS:
	XtSetValues assumes all non-widget objects are RectObjs

DESCRIPTION: 
	The XtSetValues handling of redraws is flawed for Objects that
	are not widgets and not subclasses of RectObj.  When a widget
	set_values routine returns True, XtSetValues forces a redraw
	by doing an XClearArea on the widget window.  If the object is
	not a widget, XtSetValues finds the nearest widget ancestor
	and, treating the object as a RectObj, clears the portion of
	the ancestor window that is "covered" by the RectObj.  If the
	object is not a RectObj, this will be wrong and a random part
	of the window will be cleared.  If the data wrongly read as
	the rectangle coords is sufficiently perverse, a BadValue
	error may be generated (I think, I've not actually seen one).

	It doesn't seem to be actually causing any problems for me,
	but perhaps I am just lucky with the data I have in the
	"rectangle" fields (they overlap 2 Pixel values and an integer
	in the subclass I am using, which means XtSetValues was seing
	x=<small number>, y=0, 	width=<small number>, height=0,
	borderwidth=0).  

	It is not clear what the correct action is in this case.  One
	approach is to generate a synthetic expose event on the window
	with an empty region.  The fix below handles it by just not
	doing any redraws for changes on non-RectObj objects.
	Whatever is chosen will need to be documented!

REPEAT BY:
	Examine the source code!

SAMPLE FIX:
   *** SetValues.c.DIST    Wed Apr 17 17:16:24 1991
   --- SetValues.c Wed Apr 17 17:17:35 1991
   ***************
   *** 262,268 ****
		 if (redisplay && XtIsRealized(w) && !w->core.being_destroyed)
		     XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, TRUE);
	     } else { /*non-window object */
   !         if (redisplay && ! cleared_rect_obj ) {
		 Widget pw = _XtWindowedAncestor(w);
		 if (XtIsRealized(pw) && !pw->core.being_destroyed) {
		     RectObj r = (RectObj)w;
   --- 262,268 ----
		 if (redisplay && XtIsRealized(w) && !w->core.being_destroyed)
		     XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, TRUE);
	     } else { /*non-window object */
   !         if (XtIsRectObj(w) && redisplay && ! cleared_rect_obj ) {
		 Widget pw = _XtWindowedAncestor(w);
		 if (XtIsRealized(pw) && !pw->core.being_destroyed) {
		     RectObj r = (RectObj)w;
--
Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia
Internet: gnb@melba.bby.oz.au    non-MX: gnb%melba.bby.oz@uunet.uu.net
Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb

gnb@bby.oz.au (Gregory N. Bond) (04/18/91)

Red faces time, folks.

The bug report I posted was wrong.  It turns out the check for RectObj
was made a page or so higher in the code.  I missed it for some reason
(perhaps I deleted a curly and the editor mismatched them...)

I thought it explained a few problems I was having, but it didn't.
Sincerest apologies to all concerned.

You can stop mailing me now.

Greg, Penitent.
--
Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia
Internet: gnb@melba.bby.oz.au    non-MX: gnb%melba.bby.oz@uunet.uu.net
Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb

marbru@auto-trol.com (Martin Brunecky) (04/19/91)

In article <1991Apr17.073327.12784@melba.bby.oz.au> gnb@bby.oz.au (Gregory N. Bond) writes:
>[This has been sent to xbugs]
>
>	The XtSetValues handling of redraws is flawed for Objects that
>	are not widgets and not subclasses of RectObj.  When a widget
>	set_values routine returns True, XtSetValues forces a redraw
>	by doing an XClearArea on the widget window.  If the object is
>	not a widget, XtSetValues finds the nearest widget ancestor
>	and, treating the object as a RectObj, clears the portion of
>	the ancestor window that is "covered" by the RectObj.  If the
>	object is not a RectObj, this will be wrong and a random part
>	of the window will be cleared.  If the data wrongly read as
>	the rectangle coords is sufficiently perverse, a BadValue
>	error may be generated (I think, I've not actually seen one).
>
>	It doesn't seem to be actually causing any problems for me,
        ....

     I had more than my share of troubles with SIMILAR bug in Motif 1.0
     "flavor" of XtIntrinsics. We ended-up padding all our "objects"
     with "RectObj" fields, initialized appropriately. ick, ick, ick.

     However, this WAS Motif R3++ code, and it WAS really bad. I looked
     at the R4 code several times, and it does NOT seem to have this
     problem (at least not THAT bad).
     UNLESS there is a "buggy" widget. The MIT code assumes that "Objects"
     will be "reasonable" and set_values will return redisplay = FALSE.
     It also assumes that constraint widgets will be "reasonable", and
     for "Object" children their constraint_set_values will return FALSE.
     So, if the objects in question are not buggy - no problem, as far
     as I can tell.

     However, the world is not a perfect place. Though I would like all
     the widgets to be perfect, I doubt it will ever happen. AS in this
     case XtIntrinsics can compensate for "buggy" widgets, I'd recomend
     to change the code as suggested.

>	It is not clear what the correct action is in this case.  One
>	approach is to generate a synthetic expose event on the window
>	with an empty region.  
     
     Why ? If there is a window/rectangle, XClearArea will do the job.
     
     There, however, is another, related problem. SetValues descends the
     class hierarchy top-down. If my widget's superclass said "yes, I
     need to redisplay", my widget has no way to change that - even though
     because of changed semantics my class in fact may not need to redisplay
     at all.
     So what I need is a tri-state return from SetValues:
        TRUE  = this class does require redisplay
        FALSE = this class does not require redisplay
        UNDO  = even if superclass required redisplay, it is not needed



-- 
=*= Opinions presented here are solely of my own and not those of Auto-trol =*=
Martin Brunecky                           {...}sunpeaks!auto-trol!marbru
(303) 252-2499                        (sometimes also:  marbru@auto-trol.COM )
Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404