Path: utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ucbvax!bloom-beacon!godzilla.ele.toronto.EDU!moraes
From: moraes@godzilla.ele.toronto.EDU (Mark Moraes)
Newsgroups: comp.windows.x
Subject: Re: Bugs in twm, wm, xprop, and xplaces (or my ignorance)
Message-ID: <8806280637.AA08968@godzilla.ele.toronto.edu>
Date: 28 Jun 88 02:37:39 GMT
References: <6562@jhunix.HCF.JHU.EDU> <6910001@hpfcdc.HP.COM>
Sender: daemon@bloom-beacon.MIT.EDU
Reply-To: moraes%csri.toronto.edu@relay.cs.net
Organization: EECG, University of Toronto
Lines: 188

One way to fix the problem (twm reparenting the application top-level
window with a frame that has no properties) is to have twm copy all
the properties from the application top level to the frame. The code
to this is fairly straightforward. On PropertyNotify events, it would
have to change the changed property application in the frame.
I've implemented this for twm, and it seems to work. (diffs enclosed below). 

It seems inefficient to have to do this - particularly, as the
properties of the frame are inaccurate in size hints. One other way
that comes to mind is another property for window managers, something
like WM_CHILD which the frame would set to the window id of the
reparented window, so that applications like xprop would know which
window to query for application property information. A window having
a WM_CHILD property would also indicate that it is a frame created by
a window manager, and would avoid the need to keep copying properties
from the application top-level to the window manager frame.

Finally, session managers implemented separately from window managers
(if we ever see such beasts) would be able to tell which windows
placement information should be saved - not the frames, but rather the
application top-level windows.

Is this a better solution? If so, can someone please consider it for
the next ICCC draft? Window manager authors? 

Fixes to get twm to work with xprop:

*** /tmp/,RCSt1a25414	Fri Jun 24 03:26:21 1988
--- add_window.c	Fri Jun 24 03:22:20 1988
***************
*** 93,98
      XWindowChanges xwc;		/* change window structure */
      unsigned int xwcm;		/* change window mask */
      int dont_know;		/* don't know where to put the window */
      XColor blob, cret;
  
  #ifdef DEBUG

--- 93,99 -----
      XWindowChanges xwc;		/* change window structure */
      unsigned int xwcm;		/* change window mask */
      int dont_know;		/* don't know where to put the window */
+     void CopyWindowProperties();
      XColor blob, cret;
  
  #ifdef DEBUG
***************
*** 297,304
  
      /*
      XSetWindowBorderPixmap(dpy, tmp_win->frame, GrayTile);
      */
      
      tmp_win->title_w = XCreateSimpleWindow(dpy, tmp_win->frame,
  	-BorderWidth, -BorderWidth,

--- 302,309 -----
  
      /*
      XSetWindowBorderPixmap(dpy, tmp_win->frame, GrayTile);
      */
+     CopyWindowProperties(tmp_win->w, tmp_win->frame);
      
      tmp_win->title_w = XCreateSimpleWindow(dpy, tmp_win->frame,
  	-BorderWidth, -BorderWidth,
***************
*** 614,619
  
      XGetWindowAttributes(dpy, w, &wa);
      return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
  }
  
  /***********************************************************************

--- 616,687 -----
  
      XGetWindowAttributes(dpy, w, &wa);
      return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
+ }
+ 
+ /*
+  *  Copies the property 'prop' from Window 'wfrom' to 'wto'. Should work
+  *  correctly for an arbitrary lenth property.
+  */
+ void
+ CopyProperty(wfrom, wto, prop)
+ Window wfrom, wto;
+ Atom *prop;
+ {
+ 	Atom actual_type;
+ 	int actual_format;
+ 	long nitems;
+ 	long bytes_after;
+ 	int status;
+ 	long offset;
+ 	int mode;
+ 	char *propdata;
+ 
+ 	actual_type = AnyPropertyType;
+ 	offset = 0;
+ 	mode = PropModeReplace;
+ 	bytes_after = 1024;
+ 	do {
+ 		status = XGetWindowProperty(dpy, wfrom, 
+ 		 *prop, offset, (long) (bytes_after+3/4), 
+ 		 False, actual_type, &actual_type, &actual_format, 
+ 		 &nitems, &bytes_after, &propdata);
+ 		if (status==BadWindow) {
+ 			fprintf(stderr, "window id # 0x%lx does not exists!\n",
+ 			 wfrom);
+ 			return;
+ 		}
+ 		if (status!=Success) {
+ 			fprintf(stderr, "XGetWindowProperty failed!\n");
+ 			return;
+ 		}
+ 		if (bytes_after != 0) {
+ #ifdef DEBUG
+ 			fprintf(stderr, "Only got the first %d items. %d bytes remain\n", 
+ 			 nitems, bytes_after);
+ #endif
+ 			offset = (nitems * actual_format)/32;
+ 			mode = PropModeAppend;
+ 		}
+ 			
+ 		status = XChangeProperty(dpy, wto, *prop, actual_type, 
+ 		 actual_format, mode , propdata, nitems);
+ 		XFree(propdata);
+ 	} while (bytes_after != 0);
+ }
+ 
+ 
+ void
+ CopyWindowProperties(wfrom, wto)
+ Window wfrom, wto;
+ {
+ 	int num_prop, i;
+ 	Atom *properties, *prop;
+ 
+ 	properties = XListProperties(dpy, wfrom, &num_prop);
+ 	for (i = 0, prop = properties; i < num_prop; i++, prop++) {
+ 		CopyProperty(wfrom, wto, prop);
+ 	}
+ 	XFree(properties);
  }
  
  /***********************************************************************
*** /tmp/,RCSt1a25414	Fri Jun 24 03:26:23 1988
--- events.c	Fri Jun 24 03:22:20 1988
***************
*** 179,184
      unsigned long valuemask;		/* mask for create windows */
      XSetWindowAttributes attributes;	/* attributes for create windows */
      Pixmap pm;
  
  #ifdef DEBUG
      fprintf(stderr, "PropertyNotify\n");

--- 179,185 -----
      unsigned long valuemask;		/* mask for create windows */
      XSetWindowAttributes attributes;	/* attributes for create windows */
      Pixmap pm;
+     extern void CopyProperty();
  
  #ifdef DEBUG
      fprintf(stderr, "PropertyNotify\n");
***************
*** 187,192
      if (tmp_win == NULL)
  	return;
  
      XGetWindowProperty(dpy, w, event.xproperty.atom, 0, 200, False,
  	AnyPropertyType, &junk1, &junk2, &junk3, &len, &prop);
  

--- 188,200 -----
      if (tmp_win == NULL)
  	return;
  
+     /*
+      *  hmm - we could save a GetProperty if we used the info from
+      *  CopyProperty - unfortunately, CopyProperty loops around if the
+      *  bytes aren't returned in one go, which means that it doesn't get
+      *  the whole property. That should be changed. - moraes
+      */
+     CopyProperty(tmp_win->w, tmp_win->frame, &event.xproperty.atom);
      XGetWindowProperty(dpy, w, event.xproperty.atom, 0, 200, False,
  	AnyPropertyType, &junk1, &junk2, &junk3, &len, &prop);