[comp.windows.x] Bugs in twm, wm, xprop, and xplaces

bph_cwjb@jhunix.HCF.JHU.EDU (William J. Bogstad) (06/18/88)

	When using the "twm" or "wm" window manager the commands xprop
and xplaces seem to be unable to obtain useful information about my
windows.  Is this a problem with the programs/managers in question or
a consequence of the way that X works?  Please note my ignorance of
X is high at this point.  I'm just trying to figure out how things
work or don't work.

					Thanks,
					Bill

-- 
Bill Bogstad				bogstad@cs.jhu.edu
Work: (301)338-8019			bill@green.bph.jhu.edu

jkh@ardent.UUCP (06/18/88)

That's because twm and wm don't set the class hints on the outer "frame"
window they reparent your windows to. xprop/xplaces look at this frame window
and see, of course, nothing.

					Jordan

stroyan@hpfcdc.HP.COM (Mike Stroyan) (06/19/88)

> That's because twm and wm don't set the class hints on the outer "frame"
> window they reparent your windows to. xprop/xplaces look at this frame window
> and see, of course, nothing.
> 
> 					Jordan

That's one way to look at it.  It seems to me that the problem is that
xprop/xplaces are just using the window id of the first child window
under root, as returned with the button event.  The programs could take
the screen coordinates of the button event and find the smallest window
by examining the window tree.  Xprop could report data on the smallest
subwindow or on that window and its ancestors.  That gives an xprop
user the power to indicate and get data about a window manager's border
area, or an application's window, or some subwindow.

Mike Stroyan

moraes@godzilla.ele.toronto.EDU (Mark Moraes) (06/28/88)

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);
  

msm@jumbo.dec.com (Mark S. Manasse) (06/29/88)

The current draft ICCCM includes a property WM_STATE which is supposed
to be present on all top-level windows, at least whenever there's
a window manager running.  This property should appear only on the
top-level client windows.  Thus, a client window is one which either
has the WM_STATE property on it, or a mapped child of the root which
doesn't contain any window with WM_STATE on its property list.  The
only way this goes wrong is in the case of a window manager which
isn't managing any clients, but which maps a subwindow as a sort-of
pseudoroot, which hardly seems like an important enough case to get
all that worried about.

Some window managers don't put the frame windows on the root, but
instead add an extra window or two between the root and the frames.
This lets you select for SubstructureNotify on the root without hearing
about all the things that happen because the window manager asked
for them to happen.  Thus, some windows other than the root may contain
multiple application windows.  Don't be fooled, use recursion.

Mark