/* acf4:comp.os.vms / mcmahon@tgv.com (John McMahon) / 8:05 am Sep 11, 1990 */ /*:In article <1554@front.se>, thomas@front.se (Thomas Thyberg) writes: */ /* Question: Is there a way to get the keyboard focus to follow the mouse pointer? The following program was posted to comp.os.vms a while ago, unfortunately I have lost the name of the person who provided it. It provides the "mouse following focus" that you desire under the DECwindows window manager. */ /* autofocus.c: Crude hack to do uwm-style focus management. Author: (chooses to remain anonymous) */ #include #ifdef vms #include #include #include #else #include #include #include #endif #define forever while(1) static Window GetWMRoot(); static void LowerWindow(); static Window FrameOf(); /* Recursive */ static XWMHints *GetWMHints(); /* Recursive */ static int IgnoreDeadWindow(); main(argc,argv) unsigned int argc; char *argv[]; { Display *display; Window wmroot,current,*children,*child, focus = 0; XWMHints *wmhints; int nchildren,i,revert_to; /* 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| KeyPressMask); /* 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 */ XGetInputFocus(display,&focus,&revert_to); forever { XEvent event; XMapEvent *map = (XMapEvent *)&event; XEnterWindowEvent *enter = (XEnterWindowEvent *)&event; XDestroyWindowEvent *destroy = (XDestroyWindowEvent *)&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: focus = enter->window; XSetInputFocus(display,focus, RevertToPointerRoot,CurrentTime); break; case DestroyNotify: if (destroy->window == wmroot) { fprintf(stderr,"Window Manager exited.\n"); exit(0); } } } } 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) /* Bad Window Id */ return; else XSetErrorHandler(NULL); } static Window FrameOf(display,window,wmroot) /* recursive */ Display *display; Window window,wmroot; { Window root,parent,*children; int nchildren; XQueryTree(display,window,&root,&parent,&children,&nchildren); return parent == wmroot ? window : FrameOf(display,parent,wmroot); } static void LowerWindow(display,window) Display *display; Window window; { XWindowAttributes old; XSetWindowAttributes new; XGetWindowAttributes(display,window,&old); if (!old.override_redirect) { new.override_redirect = True; XChangeWindowAttributes(display,window,CWOverrideRedirect,&new); } XLowerWindow(display,window); if (!old.override_redirect) { new.override_redirect = False; XChangeWindowAttributes(display,window,CWOverrideRedirect,&new); } } /* John 'Fast-Eddie' McMahon : MCMAHON@TGV.COM : TTTTTTTTTTTTTTTTTTTTTTTT TGV, Incorporated : : T GGGGGGG V V 603 Mission Street : HAVK (abha) Gur bayl : T G V V Santa Cruz, California 95060 : bcrengvat flfgrz gb : T G GGGG V V 408-427-4366 or 800-TGV-3440 : or qrfgeblrq ol znvy : T GGGGGGG V */