Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!uwm.edu!uakari.primate.wisc.edu!aplcen!haven!decuac!shlump.nac.dec.com!riscy.dec.com!dbb From: dbb@riscy.dec.com (David Barrett) Newsgroups: comp.windows.x Subject: Re: Window Managers, PseudoColor Displays, and "Technicolor" Message-ID: <1478@riscy.dec.com> Date: 12 Sep 89 17:05:28 GMT References: <1475@riscy.dec.com> <1469@riscy.dec.com> <6910010@hpfcdc.HP.COM> <1989Sep1.215106.11404@agate.uucp> Sender: news@riscy.dec.com Organization: Digital Equipment Corporation, NYC Lines: 299 > > > > > 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 #ifdef vms #include #include #include #include #else #include #include #include #include #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,¤t)) { 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, ¤t_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, ¤t)) { 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, ¤t_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