[comp.windows.x] Window Managers, PseudoColor Displays, and "Technicolor"

csvsj@garnet.berkeley.edu (Steve Jacobson) (09/02/89)

There are a number of strategies for minimizing "technicolor" color map
switching when running concurrent applications that require individual
color maps. There are many situations, however, where you must accept
that only one application will "look right" at a time.

At that point, the window manager becomes very important, since it will
allow the user to change color map focus.

The twm window manager changes colormap focus by tracking the mouse - wherever
the mouse is, that window's colormap is used. This behavior can often be
undesirable. For example, one window might have its own unique colormap, and
all the other windows use the root window colormap, and only use two entries
for foreground and background. If the window with the unique colormap is
careful about setting up its colormap, it can match those two entries so
the other windows "look right" when the unqie colormap window has the colormap
focus. But when another window has the focus, the unique colormap window
will go "technicolor", even though the non-unique colormap windows would look
ok if the unique colormap were still in place. Even when the user doesn't
want to shift keyboard and colormap focus to another window, mouse movements
that accidently move the mouse across the window border cause technicolor
flickering.

Worse things happen when an application with a unique color map uses multiple
windows. If the two windows are next to each other or overlap, and they both
use the same colormap, it seems reasonable to expect that the colormap focus
would not change as the pointer moves across the border from one window to
the other. But it looks like the twm created border uses the root window
colormap, so as the mouse crosses the border, there's a brief but very
disconcerting technicolor flash as the colormap shifts from the unique
colormap to the root colormap and back to the unique colormap.

Note that these comments about twm apply to the "unfocused" mode. When
"click to type" is used, it's hard to use applications with unique colormaps.
You have to iconify and deiconify windows to bypass the focus mechanism
to get colormaps to switch. However, when you can't change the colormap,
you don't have a flicker problem :-).

The DEC dxwm window manager handles this a little better. Colormap and
keyboard focus are linked together, and focus follows mouse clicks rather
than window exits and enters. This reduces technicolor flickering and the
user doesn't have to be so careful when moving the mouse. There are still
those situations where you might be happier with the colormap from one
window being in focus while you type in another.

It might be helpful to separate keyboard and colormap focus. For example, twm
might have another titlebar doodad to click on for "click to change colormap
focus." That way a user could optionally separate the focuses to minimize
flickering, minimize "wrong" colormaps, and provide flexibility. Color
flickering is disconcerting, but many users who don't like "click to type"
might not be happy about having to accept "click to type" to eliminate
flickering.

stroyan@hpfcdc.HP.COM (Mike Stroyan) (09/06/89)

> csvsj@garnet.berkeley.edu (Steve Jacobson) /  3:51 pm  Sep  1, 1989 /

> The twm window manager changes colormap focus by tracking the mouse - wherever
> the mouse is, that window's colormap is used

> The DEC dxwm window manager handles this a little better. Colormap and
> keyboard focus are linked together, and focus follows mouse clicks rather
> than window exits and enters.

Continuing your survey of window managers, the hpwm and mwm (OSF Motif)
window managers have .Xdefaults controlled selection of colormap focus
policy.  They can be configured to "pointer", "explicit", or "keyboard"
colormap focus.  The f.focus_color operation can be configured in the
.mwmrc file to a button, key or menu.  Their is also a "f.next_cmap"
operation that cycles through the windows listed in a top level window's
WM_COLORMAP_WINDOWS property.

Mike Stroyan, stroyan@hpfcla.hp.com

dbb@riscy.dec.com (David Barrett) (09/08/89)

> > The DEC dxwm window manager handles this a little better. Colormap and
> > keyboard focus are linked together, and focus follows mouse clicks rather
> > than window exits and enters.


FYI, the DECwindows window manager, dxwm, can be made to follow the pointer
as opposed to it's normal behavior of "click to focus".

If anyone is interested in this, send me some mail.


	David Barrett

	dbb@riscy.dec.com
	..!decwrl!riscy.dec!dbb

bmc@MYCROFT.MAYO.EDU (09/11/89)

I would be very interested in getting dxwm to follow the pointer.
thanks for the info.


--Bruce
----------------------------------------------------
Bruce M. Cameron                    bmc@bru.mayo.edu
Medical Sciences 1-14               (507) 284-3288
Mayo Foundation                     WD9CKW
Rochester, MN 55905
----------------------------------------------------

dbb@riscy.dec.com (David Barrett) (09/12/89)

In article <1469@riscy.dec.com>, dbb@riscy.dec.com (David Barrett) writes:

> > > The DEC dxwm window manager handles this a little better. Colormap and
> > > keyboard focus are linked together, and focus follows mouse clicks rather
> > > than window exits and enters.
> 
> 
> FYI, the DECwindows window manager, dxwm, can be made to follow the pointer
> as opposed to it's normal behavior of "click to focus".
> 
> If anyone is interested in this, send me some mail.
> 
> 
> 	David Barrett
> 

Well, due to popular demand (25-30 requests in the last few days) here
is the compressed and uuencoded version of "cycle.c", which accomplishes
the above.  The sources are for ULTRIX and VMS.

==========================CUT HERE=================================

begin 644 cycle.c.Z
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
M3:+2C P%9&(*SS"!?VGP^"0FX# 06$-EQ)\*MN9+Z>DQ#1F&06!,G&$1NR&
M<.9!&KL,E@"N8 5I6,J?U>A'[IHDN2@@8Q@SK#\P^D_& :VBB4'<6NT:>IA8
M6'%';OEBC$&:,*UE01&>(P<^2GD-*<:T$493AD2W(<W]\F)^9\W951<'!7:F
M,D4&"$$)8H:\M,'>>@FJ%SE$92^<,=_.-D:C^<0,@Q+#7H4 -,/\( 8ZFWV2
MA8@]FO6D@4F/H=>H+U/J,8.@#$QBX9KU.[\5TZ$(430+$DK3$3F@H-=F*0,%
M+3AF7>]7J&<R@RW)-+K\'.DQ;L;-'  $X;+ H<(4&2LTRXJ9YR*3G6V@PAN0
M"<I/+P4+2_B"$6)P@U0/5@ZFK?C\+EXZC7.<E1Y?N<AC@(-4FW*EI:5XAD&N
MRY9OO+#:B3G(9YX#?Q/3?)VVC!%X%O,0-U:BKP6!"0HI!SKNQ>9FPO737<LS
M/\)3JK?$R\4UV.9\4V^[F\5"$=)=%'2C2-:<!3(<UHZBAW#PX7E$ 1;D3G=U
MI\ $;@\+W.<W;KGPL>]%40&*Y))AO1>^W-!&_$/^'G@Z#!X+JS+R&_)P>+8_
M1#N:=ZX>,8^?R6R^\W57 >79?GED2EX%HVL\S_/P>C\"GO7LYJL36O9NMGO\
M]BA*-47FT*8MHZ#R+AB7>PJ]V1C*"C-R5S(J=9 P/2K:?XS>,/_"Z/'F#_/[
MX \_^._> A\X6#KB3[_ZU>_TMH;%TMY?_T@UW>*DT\'CH7Z\J5$F?/F#'PNV
MUFK75S']YW\AH50&^'WL\AYK\#[Q-P;/EQ6D)GV*07V(UEHYU2\GX5FT-'!B
M5U7RE0 4P4TQM'49F&&+)P?EYV#O(X(308(3\74>N!9C%X(CZ(+MAG0P1@=+
MMS$QAX&O%7\)*'\%1#UTH'%0\ ;W(Q<=IC1#L'54D 9?48!#.!$+:#,."'X0
MR!N99WIY0(%Y8(%9!WI>N(+FU@-Y1&/IP7Q5F'[>U2YT$%[C%44L( )\! )
M-F",1U^7008N\%[Q-7AM:!)\:%]4.(A*)8);B!E.-AIV07T/=8,7:()OU3W<
MY((Z=(DA@6BC4WXZAX8@('$I9XDPJ$]2\$AEP$<_2(E=UX*E>&ZI8QQ9UXD^
M\(EY='*C^%"O.!&9>(GT,V9!D">481GX(2 FB!9A,B;XX8K<E&D;!HS"*";$
MF!\L<P=?@(S#>!ESX("7F #[](S0%HS).(VKZ'Y<1U%2AX'8*(W:&(*76(W7
M&(W*V#/A$479 4VC@1C=5A1Y%%FMU(U8, 0S-"*I"(WCJ(WEB%-!V(V7. 17
M\ 34$Q3:44#ZV&)+06)E8(WK.(_NV(Q,P$F0%S$)Z5@;TY$) (\;.8TN4(\2
MB8_0D0;[6&?'*(\JR9+W^ 7Y"),MQHS>*)"-06!\)([9B!\C"77AI(L,Z9 0
M25[W2)$Z>4L7B9(TV8[,:#V)^(JHPQN<6#R>"'05ET<WQU(41XHX^$M(Z8V.
MAC^PQHV7Z%?&!'94Q2\:U(VPY@)F\$/)DF$WAA9ET#^6=Y9UN25I<15?$#\J
MEP0J52%[>1D\Z8S[XY?_\V'&:(X9>)&PUI%6B903@8"XY4M*E5L,!!+TLWW8
MIP*-1IH5XW'G%P;M\04.YD<#5$!0A$"8L6X4,5U%]'GM942^=(?G5T.MR8(*
M<&FC"9D/,8#;R&Z(AIP[=YJ0J9K]QH8F 9QPX)IG^&P1,WBC00>YD1?(Z46<
M"8N\<6D4<8<,Q@)PL"93)&E7E$7LR45/M'49)IS6@T:!5F+MV6>YQUE14$[&
M-DZW]F&A-G4U!F+I.4>4QF=L06*Y-GANA@)PED=RQF575&<*BF=CLV?Y>6<@
M\&>!UJ$K0&AH!W[+^6J+ED?.R7T?]I[1P9K5^9K2&7X R&JXIJ"'!+;V9VB
M8J)F%'_A26N;F'7XR452Y$<S>FL-NEDY*@=Y85V"Y)D* )HITD!W>)I-B'\*
MR@)#>F(EQ$.[J9MAQ9OE:6X"86>#E'A;*D4YU)OF=G[G>: HHD4FYD7%N6AC
MQ*,5<Z8@@ <L0!B_00;_P0+(42!*(P9WP +: 0>!.ALGU$6^-!IG ":,9Y]9
M^&_]M2 +)0>2(1O"Q08M, =CP&IYH49E$HHU!G$3X6 9UH2J^&&K8@;!-5Q3
M$*K%X0:?EEU>Q*@+DD=&<!5_4:D[0W4CJD_]*1=Y *"M]F'G1Z!.9 )P.D5V
MIJ5):A(/&J$@,*&DFD<LJJ;QD:$JD*9]!J(?.F@F%J,F\8UT4#YO\!63D4PK
MJD8@=IXFP*<F0!@F\*>!:@*#:AX@9J@@EJC_<8BZ^AAIF!W_@4=YA)M )#Z
MB@8>]ZJQ2@>S*JJWW:GLF((36LZ\& HH*FP=(4 :$^K!,%;$36ZL5*XC5AP(#
MZT=7V(![]:,IN[)/,1I8N%>(]JVY-C\!B +;"A;]-P<=409P@ (UD&JYM6M6
MAJDPN:D"9S*?2JOK1:HUDJE,VZE/*ZH4RD6EBF'K9F'7R:)TNK,]BV*Y*AR[
M"@*]&HO *CUNIR'D.3_%^I\TJJQC%J\%ZJSJJ331"JYDNU?5&F=S5J'::J;=
MJF<X>Z'B*F@A6J[#.E+ZHZ[L:FP>QZ)VVZST:J_XB@8@IK%*8P+^:@( BP8"
M:[8$&S,-B[ V$J8,^Q\B"ZO");%0:ZN!I5TF<+'^Q[FHV[$?&[*N.K*O6[)@
M<;+>AV@RV[)P![/$2[HL2[,N>VA9=[@;:J1B.ZTA ;3%,;1%"Y[L-D!+UZC8
M&6"-868%=F!ED& +5F,!M*1Y$300=AI9>V*H^KT2,[ASZDM'VFICFVI8$+?'
M.K>[R0++*J_/JK=9RK>IIK[R^SY2"CZ9A&\3]![\!FT>!VQRT*6IVUQ@VEQT
M"F_6(0>O1\%KBEQ91\'E-QI;47I? $JH2P,RX$<@,$!,D!CF1"]/]6UR\1<7
?F174DP?_P27&93WJZT59B1F.R<'R1F]R45V!)%^Y!4!,

end

==================CUT HERE===============================


	David Barrett

	dbb@riscy.dec.com
	..!decwrl!riscy.dec!dbb

	These opinions are mine.

dbb@riscy.dec.com (David Barrett) (09/13/89)

> 
> > > > The DEC dxwm window manager handles this a little better. Colormap and
> > > > keyboard focus are linked together, and focus follows mouse
clicks rather
> > > > than window exits and enters.
> > 
> > 
> > FYI, the DECwindows window manager, dxwm, can be made to follow the pointer
> > as opposed to it's normal behavior of "click to focus".
> > 
> > If anyone is interested in this, send me some mail.
> > 
> > 
> > 	David Barrett
> > 
> 
> Well, due to popular demand (25-30 requests in the last few days) here
> is the compressed and uuencoded version of "cycle.c", which accomplishes
> the above.  The sources are for ULTRIX and VMS.


/********************************************************************
 *
 *      @(#)cycle.c     1.0     ULTRIX/SWS     9/11/89
 *
 * Copyright 1988, 1989 by Digital Equipment Corporation,
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.
 *
 * AUTHOR'S DISCLAIMER:
 *
 * This program written by Jatin Desai.
 * Please use at your own risk.
 *
 * Known Bugs/Problems:
 * 1. Doesn't know sticky property of winodws (brings them to the top
 *    anyways).
 * 2. Doesn't know if a toplevel window wants input focus or not.  It
 *    will ask the 'next' window to take input focus.  If it doesn't
 *    take it, hit F5 again.
 *
 ********************************************************************/

#include <stdio.h>
#ifdef vms
#include <decw$include/X.h>
#include <decw$include/Xlib.h>
#include <decw$include/Xutil.h>
#include <decw$include/keysym.h>
#else
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#endif

#define forever           while(1)

static Window GetWMRoot();
static XWMHints *GetWMHints();  /* Recursive */
static int IgnoreDeadWindow();

main(argc,argv)
   unsigned int argc;
   char *argv[];
{
   Display *display;
   Window wmroot,current,*children,*child;
   XWMHints *wmhints;
   int nchildren,i;
   Window current_focus = (Window) NULL;
   int revert_to;
   unsigned int raise_keycode;
   unsigned int lower_keycode;
   unsigned int iconify_keycode;
#define GrabFunctionKeys() \
     { \
       XGrabKey(display, raise_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
       XGrabKey(display, lower_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
       XGrabKey(display, iconify_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
     }
#define UngrabFunctionKeys() \
     { \
       XUngrabKey(display, raise_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
       XUngrabKey(display, lower_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
       XUngrabKey(display, iconify_keycode, AnyModifier, \
                current_focus, True, GrabModeAsync, GrabModeAsync); \
     }

   /* Open the default display */

   if (!(display = XOpenDisplay(NULL))) {
      fprintf(stderr,"Can't open display\n");
      exit(0);
   }

   /* Find the window manager's pseudo-root window & its children */

   wmroot = GetWMRoot(display,&children,&nchildren);
  
XSelectInput(display,wmroot,StructureNotifyMask|SubstructureNotifyMask|K
eyPressMask);

   /* Find out which children have set window manager hints */

   for (i = 0, child = children; i < nchildren; ++i, ++child) {
      if (wmhints = GetWMHints(display,*child,&current)) {
         XSelectInput(display,current,EnterWindowMask);
         XFree(wmhints);
      }
   }
   XFree(children);

   /* Ignore error when we try to set focus on a window which has died
      since we received the EnterWindow event */

   XSetErrorHandler(IgnoreDeadWindow);

   /* Grab the function keys used for push & pop */

   raise_keycode = XKeysymToKeycode(display, XK_F17);
   lower_keycode = XKeysymToKeycode(display, XK_F18);
   iconify_keycode = XKeysymToKeycode(display, XK_F19);

   XGetInputFocus(display, &current_focus, &revert_to);
   if (current_focus) GrabFunctionKeys();

   forever {
      XEvent event;
      XMapEvent *map = (XMapEvent *)&event;
      XEnterWindowEvent *enter = (XEnterWindowEvent *)&event;
      XDestroyWindowEvent *destroy = (XDestroyWindowEvent *)&event;
      XKeyEvent *key = (XKeyEvent *) &event;

      XNextEvent(display,&event);
      switch (event.type) {
         case MapNotify: if (wmhints = GetWMHints(display,
                                                  map->window,
                                                  &current)) {
                            XSelectInput(display,current,EnterWindowMask);
                            XFree(wmhints);
                         }
                         break;

         case EnterNotify: if (current_focus) UngrabFunctionKeys();
                           current_focus = enter->window;
                           GrabFunctionKeys();
                           XSetInputFocus(display, current_focus,
                                          RevertToPointerRoot,CurrentTime);
                           break;

         case DestroyNotify: if (destroy->window == wmroot) {
                                fprintf(stderr,"Window Manager exited.\n");
                                exit(0);
                             }
         case KeyPress:
                        if (current_focus)
                          {
                            if (key->keycode == raise_keycode)
                              XRaiseWindow(display, current_focus);
                            else if (key->keycode == lower_keycode)
                              {
                                XWindowAttributes current_attributes;
                                XSetWindowAttributes new_attributes;

                                XGetWindowAttributes(display,
current_focus, &current_attributes);
                                new_attributes.override_redirect = True;
                                XChangeWindowAttributes(display, current_focus,
                                                       
CWOverrideRedirect, &new_attributes);
                                XLowerWindow(display, current_focus);
                                new_attributes.override_redirect =
current_attributes.override_redirect;
                                XChangeWindowAttributes(display, current_focus,
                                                       
CWOverrideRedirect, &new_attributes);
                              }
                            else if (key->keycode == iconify_keycode)
                              {
                                XWMHints hints;

                                UngrabFunctionKeys();
                                hints.flags = StateHint;
                                hints.initial_state = IconicState;
                                XSetWMHints(display, current_focus, &hints);
                              }
                          }
      }
   }
}

static XWMHints *GetWMHints(display,window,app_window) /* Recursive */
   Display *display;
   Window window,*app_window;
{
   XWMHints *wmhints;

   if (wmhints = XGetWMHints(display,window)) {
      *app_window = window;
      return wmhints;
   }
   else {
      Window root,parent,*children,*child,current = window;
      int i,nchildren;

      XQueryTree(display,current,&root,&parent,&children,&nchildren);
      for (i = 0, child = children; i < nchildren; ++i, ++child) {
         if (wmhints = GetWMHints(display,*child,app_window)) {
            XFree(children);
            return wmhints;
         }
      }
      if (nchildren) XFree(children);
      return NULL;
   }
}

static Window GetWMRoot(display,children,nchildren)
   Display *display;
   Window **children;
   int *nchildren;
{
   Window window,root,parent,*child;
   XWMHints *wmhints;
   int x,y,width,height,bw,depth,found;
   register int i;

   /* Find first full-screen child of root */

   window = RootWindow(display,DefaultScreen(display));
   found = False;

   forever {
     XQueryTree(display,window,&root,&parent,children,nchildren);
     for (i = 0, child = *children; i < *nchildren; ++i, ++child) {
        XGetGeometry(display,*child,&root,&x,&y,&width,&height,&bw,&depth);
        found = width == DisplayWidth(display,DefaultScreen(display)) &&
                height == DisplayHeight(display,DefaultScreen(display));
        if (found) break;
     }
     if (found) break;
     if (*nchildren) XFree(*children);
     sleep(5);
   }

   /* Find first full-screen child of first full-screen child of root */

   window = *child;
   XFree(*children);
   found = False;

   forever {
     XQueryTree(display,window,&root,&parent,children,nchildren);
     for (i = 0, child = *children; i < *nchildren; ++i, ++child) {
        XGetGeometry(display,*child,&root,&x,&y,&width,&height,&bw,&depth);
        found = width == DisplayWidth(display,DefaultScreen(display)) &&
                height == DisplayHeight(display,DefaultScreen(display));
        if (found) break;
     }
     if (found) break;
     if (*nchildren) XFree(*children);
     sleep(5);
   }

   /* Found window manager's pseudo-root; return it & its children */

   window = *child;
   XFree(*children);
   XQueryTree(display,window,&root,&parent,children,nchildren);
   return window;
}

static int IgnoreDeadWindow(display,error)
   Display *display;
   XErrorEvent *error;
{
   if (error->request_code == 42)  /* Life, the Universe, & Everything */
      return;
   else XSetErrorHandler(NULL);
}

 

	David Barrett

	dbb@riscy.dec.com
	..!decwrl!riscy.dec!dbb