home *** CD-ROM | disk | FTP | other *** search
- /*Copyright (c) 1991 Xerox Corporation. All Rights Reserved.
-
- Permission to use, copy, modify and distribute without
- charge this software, documentation, images, etc. is grant-
- ed, provided that this copyright and the author's name is
- retained.
-
- A fee may be charged for this program ONLY to recover costs
- for distribution (i.e. media costs). No profit can be made
- on this program.
-
- The author assumes no responsibility for disasters (natural
- or otherwise) as a consequence of use of this software.
-
- Adam Stein (stein.wbst129@xerox.com)
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/cursorfont.h>
- #include <X11/Xatom.h>
-
- int mult_screens,screen_number,display_number;
- char hostname[50];
- Atom wm_save_yourself,wm_protocols,wm_client_machine;
- Display *display;
- Window root_window;
- extern int console_checking;
- extern char *program,*addon,*use_display;
- extern FILE *fp;
-
- /*This function will initialize the interface to X, lock the pointer and
- change it to a watch, start the recursive procedure of going through
- the window tree list, and then release the pointer and change the cursor
- back to normal when done.
-
- Inputs: none
- Outputs: none
- Locals: child - list of child window IDs
- cursor - X cursor bitmap
- hostname - name of host
- loop - loop through screen number array
- num_child - number of children under a parent
- parent - parent window ID of child in the window tree
- root - top window ID to start in window tree from
- screens - array of screens to save from
- Globals: display - interface info to X display
- display_number - number of the display this will be working under
- mult_screens - flag indicating if saving more than 1 screen
- program - name of currently executing program
- root_window - root window ID
- screen_number - number of the screen this will be working under
- stderr - standard error
- use_display - display to use
- wm_client_machine - WM_CLIENT_MACHINE atom
- wm_protocols - WM_PROTOCOLS atom
- wm_save_yourself - WM_SAVE_YOURSELF atom
- CurrentTime - indicates to execute action immediately
- False - indicates not to do something
- GrabModeAsync - indicates to grab device asynchronously
- GrabModeSync - indicates to grab device synchronously
- None - indicates no choice for an item
- NULL - 0
- XC_watch - indicates the watch bitmap
- */
- getinfo()
- {
- register int *screens,loop;
- int num_child;
- register Cursor cursor;
- Window root,parent,*child;
- int *make_list();
-
- /*Get hostname*/
- if(gethostname(hostname,50)) {
- perror(program);
- exit(1);
- }
-
- /*Open a connection to the X server*/
- if((display = XOpenDisplay(use_display)) == NULL) {
- fprintf(stderr,"%s: can't open display (%s)\n",program,
- XDisplayName(use_display));
- exit(1);
- }
-
- /*Find out what screens to save application states from*/
- display_number = display->ext_number;
- screens = make_list(DefaultScreen(display),ScreenCount(display));
- if(screens[1] != -1) mult_screens = 1;
- else mult_screens = 0;
-
- /*Set up ATOMS to use*/
- wm_save_yourself = XInternAtom(display,"WM_SAVE_YOURSELF",False);
- wm_protocols = XInternAtom(display,"WM_PROTOCOLS",False);
- wm_client_machine = XInternAtom(display,"WM_CLIENT_MACHINE",False);
-
- /*Change cursor to a watch and ring bell once to let user know
- that the server is tied up and the process has begun*/
- root_window = RootWindow(display,DefaultScreen(display));
- cursor = XCreateFontCursor(display,XC_watch);
- XGrabPointer(display,root_window,False,0,GrabModeSync,GrabModeAsync,
- None,cursor,CurrentTime);
- XBell(display,50);
-
- /*Loop through the screens to save from*/
- for(loop = 0;screens[loop] != -1;++loop) {
- /*Get information about root window*/
- screen_number = screens[loop];
- root_window = RootWindow(display,screen_number);
-
- /*Get list of root window's child*/
- if(!XQueryTree(display,root_window,&root,&parent,&child,&num_child)) {
- fprintf(stderr,"%s: couldn't get root window's child (window 0x%lx)\n",program,root_window);
- exit(1);
- }
-
- /*Loop through children windows*/
- for(;num_child;--num_child)
- search(display,child[num_child-1],root_window);
-
- /*Free resources*/
- XFree(child);
- }
-
- /*Change cursor back to normal and ring bell twice to signal that
- the process of saving the desktop is over*/
- XUngrabPointer(display,CurrentTime);
- XBell(display,50);
- XBell(display,50);
- XFlush(display);
-
- /*Close the connection to the X server*/
- XCloseDisplay(display);
- }
-
- /*This function will recursively search through the window tree. It will check
- each window to see if it's state should be saved with a WM_SAVE_YOURSELF
- message and if it has a WM_COMMAND property to save. A window is saved
- if:
- 1. it has WM_NAME set (so we know it's not a pop-up, etc)
- 2. it's a group leader or assume it's ok if group leader isn't set
- 3. it's parent is the root window
- 4. it has a WM_COMMAND property to save or is on a list specified
- with the '-m' option
-
- Inputs: display - interface info to X display
- parent_window - parent window ID of window we are examining
- window - window we are examining
- Outputs: none
- Locals: argc - number of WM_COMMAND arguments
- argv - WM_COMMAND arguments
- child - list of child window IDs
- command_line - command line arguments in a single string
- console - indicates if a window is a console
- count - number of protocols that a window can receive
- event - event information
- group_leader - window ID of group leader
- hints - window hints
- name - X window name
- num_child - number of children under a parent
- parent - parent window ID of child in the window tree
- protocols - list of protocols that a window can receive
- root - top window ID to start in window tree from
- save_yourself - flag indicating if window saved itself or not
- status - status of get calls
- Globals: addon - name of file containing commands to add on
- console_checking - indicates if the check console flag was given
- fp - file pointer to write window information to
- mult_screens - flag indicating if saving more than 1 screen
- on_missing_list - flag indicating if window is a missing app
- program - name of currently executing program
- screen_number - number of the screen this will be working under
- stderr - standard error
- wm_protocols - WM_PROTOCOLS atom
- wm_save_yourself - WM_SAVE_YOURSELF atom
- ClientMessage - event that indicates a message from 1 client
- to another
- False - indicates not to do something
- PropertyChangeMask - indicates a window property has changed
- PropertyNotify - event that indicates a property has changed
- WindowGroupHint - mask for group hint bit in hint flags
- */
- search(display,window,parent_window)
- register Display *display;
- register Window window,parent_window;
- {
- register int save_yourself,on_missing_list,console = 0;
- int num_child,count,argc,group_leader = 0;
- register char *command_line,*name;
- char **argv;
- Atom *protocols;
- register Status status;
- Window root,parent,*child;
- XEvent event;
- register XWMHints *hints;
- char *combine(),*get_geometry(),*getname(),*lower();
-
-
- /*If a child had children of it's own, loop thru it's children
- recursively*/
- if(XQueryTree(display,window,&root,&parent,&child,&num_child)) {
- for(;num_child;--num_child)
- search(display,child[num_child-1],parent);
-
- /*Free resources*/
- XFree(child);
- }
-
- /*Don't report window if it doesn't have a name (in which case it's
- probably a pop-up or unmapped child*/
- if(name = getname(window)) XFree(name);
- else return;
-
- /*Don't report window if it's not a group leader or isn't a top
- window*/
- hints = XGetWMHints(display,window);
-
- /*Also check if program didn't set #!$% group leader, in this case
- assume it's ok (I'm sure that's asking for trouble!)*/
- if(hints) {
- if((hints->window_group == window) ||
- !(hints->flags & WindowGroupHint))
- group_leader = 1;
- XFree(hints);
- }
- if(!group_leader || (parent_window != root_window)) return;
-
- /*Determine if window has WM_SAVE_YOURSELF ATOM and send it if
- it does to save it's state*/
- status = XGetWMProtocols(display,window,&protocols,&count);
- if(status && is_save_yourself(protocols,count)) {
- save_yourself = 1;
-
- /*If window does have WM_SAVE_YOURSELF, send it a message to
- save it's state and wait for the PropertyNotify response*/
- event.type = ClientMessage;
- event.xclient.window = window;
- event.xclient.message_type = wm_protocols;
- event.xclient.format = 32;
- event.xclient.data.l[0] = (long) wm_save_yourself;
- XSelectInput(display,window,PropertyChangeMask);
- XSendEvent(display,window,False,0L,&event);
- XNextEvent(display,&event);
- if(event.type == PropertyNotify) {
- if(event.xproperty.window != window) {
- fprintf(stderr,"%s: unexpected PropertyNotify event\n",program);
- exit(1);
- }
- } else {
- fprintf(stderr,"%s: unexpected event\n",program);
- exit(1);
- }
- } else save_yourself = 0;
-
- /*Free resources*/
- XFree(protocols);
-
- /*Determine if window is on missing apps list*/
- on_missing_list = on_list(window);
-
- /*Get WM_COMMAND. If window doesn't have it set, skip it, otherwise
- write it out*/
- status = XGetCommand(display,window,&argv,&argc);
- if((status && argc && isprint(argv[0][0])) || on_missing_list) {
- /*Put arguments into a single string and free up argv. Makes it
- easier to check for things*/
- if(status) {
- command_line = combine(argc,argv);
- XFreeStringList(argv);
- } else {
- /*It is ASSUMED that if we have to save a window that
- doesn't have WM_COMMAND set, it's name is WM_NAME in all
- lower case (i.e. xman sets WM_NAME to Xman)*/
- command_line = lower(getname(window));
- save_yourself = 0;
- }
-
- if(!save_yourself) command_line = get_geometry(window,command_line);
-
- /*If console checking flag was given, check each window to see
- if it's a console window*/
- if(console_checking)
- console = is_console(window,command_line);
-
- /*If this window is a console window, write out the special
- 'if ... fi' clause*/
- if(console)
- fputs("if [ \"`tty`\" = \"/dev/console\" ]\nthen\n ",fp);
-
- /*Check to see if window is a remote application*/
- is_remote(window);
-
- /*Fix Xview's long label problem*/
- fix_command(command_line);
-
- /*If saving from more than 1 screen, make sure each application
- has the correct -display option to put it back onto the correct
- screen*/
-
- /*Write out all the arguments in WM_COMMAND*/
- fprintf(fp,"%s ",command_line);
-
- if(mult_screens) adddisplay(command_line,screen_number);
-
- /*If -a option given, search for any addon commands for this window*/
- if(addon) addto(command_line);
-
- /*Write out ampersand to put command into the background*/
- fputs("&\n",fp);
-
- if(console)
- fputs("fi\n",fp);
-
- /*Free resources*/
- free(command_line);
- }
- }
-
- /*This function will convert all letters in a string to lower case (if not
- already lower case).
-
- Inputs: string - string to turn all characters to lower case
- Outputs: string - string of all lower case characters
- Locals: loop - loop through string
- Globals: none
- */
- char *lower(string)
- register char *string;
- {
- register int loop;
-
- for(loop = 0;loop < strlen(string);++loop)
- if(isupper(string[loop])) string[loop] = tolower(string[loop]);
-
- return(string);
- }
-
-