This bug is submitted for your information only. I've also sent the bug report directly to xbugs and xfree86, so hopefully one of those groups will be fixing it. To: xbugs cc: XFree86 Newsgroups: Subject: Xaw: relayout of Form widget when a child resizes is broken ----- VERSION: R6.4, public-patch-3 XFree86 4.0.1 CLIENT MACHINE and OPERATING SYSTEM: Red Hat Linux 7.0, kernel 2.2.16 (but this doesn't matter to the bug) DISPLAY TYPE: XF86_Mach64 (but this doesn't matter to the bug; also seen on other displays) WINDOW MANAGER: GNOME with Sawfish window manager (but this doesn't matter to the bug) COMPILER: gcc version 2.96 20000731 (Red Hat Linux 7.0) AREA: Xaw SYNOPSIS: Relayout of Form widget when a child resizes is broken DESCRIPTION: When a child of a Form widget is resized by the user program after the Form widget has been realized, relayout of the form is not done properly. In the case I've seen, the children do not move. This bug was not present in earlier versions of Xaw; they repositioned the children correctly. Looking at the code and comparing it with an older version, the Form widget is going through the motions of trying to do the relayout, but an extra layer of code has been added that does not work properly and keeps the relayout from actually changing the layout as it should. It seems that layout now uses something called the "virtual" width and height of the child widgets to compute the layout instead of looking inside the child widgets for their actual width and height. I don't understand what is supposed to be accomplished by doing that -- it can't be an optimization to avoid communicating with the server, since the actual width and height are already in local fields. What it does do is break the relayout process, because the virtual width and height are not updated to match the real width and height. In particular, if a child resizes, the sequence of events is (1) the child resizes itself, (2) the Form's geometry manager is called, (3) the geometry manager redoes the form layout using the virtual sizes of the children, which DO NOT reflect the new size of the child that just changed, (4) the geometry manager MIGHT update the virtual size of the child. In step (3), obviously the layout will be wrong because the outdated size is used. In step (4) there is an additional bug, because the virtual size is updated only if XawFormDoLayout(w, False) had been called earlier to put the form into deferred layout mode. Perhaps the virtual stuff is some kind of optimization for the case where the form itself is resized and it must then resize its children. But it completely breaks the case where a child is resized by the user program and the form needs relayout. REPEAT BY: Below is a program that demonstrates the problem. If you run it with the argument "0", it draws a Form widget with three children and does not attempt to resize any of them. If you run it with the argument "1", it will widen the child marked "Label 1". Under older versions of Xaw, this causes Label 2 to move to the right to get out of the way. Under the current version, Label 2 does not move, because the Layout procedure uses the old size of Label 1 (the incorrect "virtual" size) to compute the new layout. Thus Label 1 ends up overlapping Label 2. You can also run the program with the argument "3", which calls XawFormDoLayout(w, FALSE) before the resize and XawFormDoLayout(2, TRUE) after. This does not change the result on the screen, but does cause the code to go down a somewhat different path. Another way to reproduce the problem is to run any version of xboard from 3.0.0 to 4.1.0. (See http://www.tim-mann.org for source code.) The button bar [<< < P > >>] ends up on top of the message widget instead of moving to the far right of the window as it should. xboard lays out its window by first making the message widget small, then realizing all the widgets, then looking to see how much extra space there is and enlarging the message widget to fill it. This has worked fine for years but is now broken with the current Xaw. =============cut here================= #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Shell.h> #include <X11/Xaw/Form.h> #include <X11/Xaw/Label.h> #include <stdio.h> XtAppContext appContext; Widget shellWidget, formWidget, labelWidget[3]; int main(int argc, char **argv) { int i; Arg args[16]; Dimension w, h, wr, hr; XtGeometryResult gres; int arg = 1; Position x, y; shellWidget = XtAppInitialize(&appContext, "XawBug", NULL, 0, &argc, argv, NULL, NULL, 0); if (argc > 1) arg = atoi(argv[1]); formWidget = XtCreateManagedWidget("form", formWidgetClass, shellWidget, NULL, 0); labelWidget[0] = XtCreateWidget("label0", labelWidgetClass, formWidget, NULL, 0); labelWidget[1] = XtCreateWidget("label1", labelWidgetClass, formWidget, NULL, 0); labelWidget[2] = XtCreateWidget("label2", labelWidgetClass, formWidget, NULL, 0); XtManageChildren(labelWidget, sizeof(labelWidget)/sizeof(Widget)); i = 0; XtSetArg(args[i], XtNlabel, "This is a long label to make the form wide"); i++; XtSetValues(labelWidget[0], args, i); i = 0; XtSetArg(args[i], XtNresizable, True); i++; XtSetArg(args[i], XtNlabel, "Label 1"); i++; XtSetArg(args[i], XtNfromVert, labelWidget[0]); i++; XtSetValues(labelWidget[1], args, i); i = 0; XtSetArg(args[i], XtNlabel, "Label 2"); i++; XtSetArg(args[i], XtNfromVert, labelWidget[0]); i++; XtSetArg(args[i], XtNfromHoriz, labelWidget[1]); i++; XtSetValues(labelWidget[2], args, i); XtRealizeWidget(shellWidget); if (arg & 2) { XawFormDoLayout(formWidget, False); } if (arg & 1) { i = 0; XtSetArg(args[i], XtNwidth, &w); i++; XtSetArg(args[i], XtNheight, &h); i++; XtGetValues(labelWidget[1], args, i); w += 40; gres = XtMakeResizeRequest(labelWidget[1], w, h, &wr, &hr); if (gres != XtGeometryYes) { fprintf(stderr, "resize geometry error %d %d %d %d %d\n", gres, w, h, wr, hr); } } if (arg & 2) { XawFormDoLayout(formWidget, True); } XtAppMainLoop(appContext); return 0; } =============cut here================= SAMPLE FIX: I'm sorry, but I don't understand what the virtual stuff is supposed to do, so I don't know the proper fix. You can definitely fix this bug by going back to the old version of Xaw that was used in XFree86 3.3.6. The identifying lines from the OLD, WORKING version are: /* $XConsortium: Form.c,v 1.52 94/04/17 20:12:06 kaleb Exp $ */ /* $XFree86: xc/lib/Xaw/Form.c,v 1.1.1.1.12.2 1998/05/16 09:05:19 dawes Exp $ */ The identifying lines from the NEW, BROKEN version are: /* $TOG: Form.c /main/54 1998/05/14 14:55:45 kaleb $ */ /* $XFree86: xc/lib/Xaw/Form.c,v 1.16 1999/11/19 13:53:26 hohndel Exp $ */ SERVER OUTPUT: This is totally irrelevant, but the XFree86 FAQ says to include it in but reports, so here it is. Apparently I have an XFree86 3.3.6 server, but nevertheless the bug I'm reporting is in the XFree86 4.0.1 libraries. It's independent of the server that's running. XFree86 Version 3.3.6 / X Window System (protocol Version 11, revision 0, vendor release 6300) Release Date: January 8 2000 If the server is older than 6-12 months, or if your card is newer than the above date, look for a newer version before reporting problems. (see http://www.XFree86.Org/FAQ) Operating System: Linux 2.2.5-22smp i686 [ELF] Configured drivers: Mach64: accelerated server for ATI Mach64 graphics adaptors (Patchlevel 1) (using VT number 8) XF86Config: /usr/X11R6/lib/X11/XF86Config (**) stands for supplied, (--) stands for probed/default values (**) XKB: rules: "xfree86" (**) XKB: model: "pc101" (**) XKB: layout: "us" (**) Mouse: type: PS/2, device: /dev/mouse, buttons: 3 (**) Mach64: Graphics device ID: "Primary Card" (**) Mach64: Monitor ID: "Primary Monitor" (**) FontPath set to "unix/:7100" (--) Mach64: PCI: Mach64 RagePro rev 92, Aperture @ 0x41000000, Registers @ 0x40000000, Block I/O @ 0x1000 (--) Mach64: PCI (92) and CONFIG_CHIP_ID (124) don't agree on ChipRev, using PCI value (--) Mach64: Card type: AGP (--) Mach64: Memory type: SGRAM (1:1) (5) (--) Mach64: Clock type: Internal (--) Mach64: Maximum allowed dot-clock: 230.000 MHz (**) Mach64: Mode "1600x1200": mode clock = 162.000 (--) Mach64: Too little memory for mode "1600x1200" (--) Mach64: Removing mode "1600x1200" from list of valid modes. (**) Mach64: Mode "1280x1024": mode clock = 135.000 (**) Mach64: Mode "1152x864": mode clock = 135.000 (**) Mach64: Mode "1024x768": mode clock = 115.500 (**) Mach64: Mode "800x600": mode clock = 69.650 (**) Mach64: Mode "640x480": mode clock = 45.800 (--) Mach64: Virtual resolution: 1280x1024 (--) Mach64: Video RAM: 6144k (--) Mach64: Using hardware cursor (--) Mach64: Using 16 MB aperture @ 0x41000000 (--) Mach64: Using 4 KB register aperture @ 0x40000000 (--) Mach64: Ramdac is Internal (--) Mach64: Ramdac speed: 230 MHz Warning: Ron = 43, Rloop = 10, Roff = 46 (--) Mach64: Pixmap cache: 0 256x256 slots, 0 128x128 slots, 0 64x64 slots (--) Mach64: Font cache: 0 fonts SESSION_MANAGER=local/milwaukee:/tmp/.ICE-unix/11319 Xlib: extension "XINERAMA" missing on display ":1.0". SetKbdSettings - type: 2 rate: 30 delay: 500 snumlk: 0 SetKbdSettings - Succeeded subshell.c: couldn't get terminal settings: Inappropriate ioctl for device Tim Mann tim.mann http://www.tim-mann.org Compaq Computer Corporation, Systems Research Center, Palo Alto, CA
If it hasn't been picked up already, we will pick up the upstream fix when available. Thanks for the report.
This should be fixed in XFree86 CVS which is going into rawhide soon, if not in an earlier release. Closing as RAWHIDE Thanks.