/* This module, and the entire NoClutter program, and the concept for * interfacing this module to the Window Manager, are all original work * by Robert Nation * * Copyright 1994, Robert Nation. No guarantees or warantees or anything * are provided or implied in any way whatsoever. Use this program at your * own risk. Permission to use this program for any purpose is given, * as long as the copyright is kept intact. */ #define TRUE 1 #define FALSE #include "../../configure.h" #ifdef ISC #include /* Saul */ #endif #include #include #include #include #include #include #if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ #include #endif #include #include #include #include "../../fvwm/module.h" #include "FvwmClean.h" #include "../../version.h" char *MyName; int fd_width; int fd[2]; struct list *list_root = NULL; unsigned long current_focus = 0; long period[3] = {-1,-1,-1}; long maxperiod = -1; char command[3][256]; int num_commands = 0; unsigned long next_event_time = 0; unsigned long t0; /*********************************************************************** * * Procedure: * main - start of module * ***********************************************************************/ void main(int argc, char **argv) { char *temp, *s; FILE *file; /* Save the program name - its used for error messages and option parsing */ temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; MyName = safemalloc(strlen(temp)+2); strcpy(MyName,"*"); strcat(MyName, temp); if((argc != 6)&&(argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, VERSION); exit(1); } /* Save the program name - its used for error messages and option parsing */ temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; MyName = safemalloc(strlen(temp)+2); strcpy(MyName,"*"); strcat(MyName, temp); /* Dead pipes mean fvwm died */ signal (SIGPIPE, DeadPipe); fd[0] = atoi(argv[1]); fd[1] = atoi(argv[2]); /* scan config file for set-up parameters */ file = fopen(argv[3],"r"); if(file != (FILE *)NULL) { char line[256]; char *tline; tline = fgets(line,(sizeof line)-1,file); while((tline != (char *)0)&&(num_commands < 3)) { while(isspace(*tline))tline++; if((strlen(&tline[0])>1)&& (mystrncasecmp(tline, MyName,strlen(MyName))==0)) { sscanf(&tline[strlen(MyName)],"%ld",&period[num_commands]); if(period[num_commands]>maxperiod) maxperiod = period[num_commands]; while(!isspace(*tline))tline++; while(isspace(*tline))tline++; /* points to "time" field */ while(!isspace(*tline))tline++; while(isspace(*tline))tline++; /* points to "command" field */ strcpy(command[num_commands],tline); num_commands++; } tline = fgets(line,(sizeof line)-1,file); } } if(num_commands == 0) { fprintf(stderr,"%s: Nothing to do!\n",MyName); exit(0); } fd_width = GetFdWidth(); /* Create a list of all windows */ /* Request a list of all windows, * wait for ConfigureWindow packets */ SendInfo(fd,"Send_WindowList",0); Loop(fd); } /*********************************************************************** * * Procedure: * Loop - wait for data to process * ***********************************************************************/ void Loop(int *fd) { unsigned long header[3], *body; fd_set in_fdset; struct itimerval value; int retval, count; while(1) { FD_ZERO(&in_fdset); FD_SET(fd[1],&in_fdset); /* Find out when we have to iconify or whatever a window */ find_next_event_time(); /* set up a time-out, in case no packets arrive before we have to * iconify something */ value.it_value.tv_usec = 0; value.it_value.tv_sec = next_event_time - t0; #ifdef __hpux if(value.it_value.tv_sec > 0) retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value); else retval=select(fd_width,(int *)&in_fdset, 0, 0, NULL); #else if(value.it_value.tv_sec > 0) retval=select(fd_width,&in_fdset, 0, 0, &value.it_value); else retval=select(fd_width,&in_fdset, 0, 0, NULL); #endif if(FD_ISSET(fd[1], &in_fdset)) { /* read a packet */ if(ReadFvwmPacket(fd[1],header, &body) > 0) { /* dispense with the new packet */ process_message(header[1],body); free(body); } } } } /*********************************************************************** * * Procedure: * Process message - examines packet types, and takes appropriate action * ***********************************************************************/ void process_message(unsigned long type,unsigned long *body) { struct list *l; switch(type) { case M_ADD_WINDOW: if(!find_window(body[0])) add_window(body[0]); break; case M_CONFIGURE_WINDOW: if(!find_window(body[0])) add_window(body[0]); break; case M_DESTROY_WINDOW: remove_window(body[0]); break; case M_FOCUS_CHANGE: l = find_window(body[0]); if(l == 0) { add_window(body[0]); l = find_window(body[0]); update_focus(l,body[0]); } else update_focus(l,body[0]); break; default: break; } } /*********************************************************************** * * Procedure: * safemalloc - mallocs specified space or exits if there's a * problem * ***********************************************************************/ char *safemalloc(int length) { char *ptr; if(length <=0) length = 1; ptr = malloc(length); if(ptr == (char *)0) { fprintf(stderr,"%s:malloc failed",MyName); exit(1); } return ptr; } /*********************************************************************** * * Procedure: * find_window - find a window in the current window list * ***********************************************************************/ struct list *find_window(unsigned long id) { struct list *l; if(list_root == NULL) return NULL; for(l = list_root; l!= NULL; l= l->next) { if(l->id == id) return l; } return NULL; } /*********************************************************************** * * Procedure: * remove_window - remove a window in the current window list * ***********************************************************************/ void remove_window(unsigned long id) { struct list *l, *prev; if(list_root == NULL) return; prev = NULL; for(l = list_root; l!= NULL; l= l->next) { if(l->id == id) { if(prev != NULL) prev->next = l->next; else list_root = l->next; free(l); return; } prev = l; } } /*********************************************************************** * * Procedure: * add_window - add a new window in the current window list * ***********************************************************************/ void add_window(unsigned long new_win) { struct list *t; if(new_win == 0) return; t = (struct list *)safemalloc(sizeof(struct list)); t->id = new_win; t->last_focus_time = time(0); t->actions = 0; t->next = list_root; list_root = t; } /*********************************************************************** * * Procedure: * mark the window which currently has focus, so we don't iconify it * ***********************************************************************/ void update_focus(struct list *l, unsigned long win) { struct list *t; t=find_window(current_focus); if(t!= NULL) { t->last_focus_time = time(0); t->actions = 0; } if(l != NULL) { l->last_focus_time = time(0); l->actions = 0; } current_focus = win; } /*********************************************************************** * * Procedure: * SIGPIPE handler - SIGPIPE means fvwm is dying * ***********************************************************************/ void DeadPipe(int nonsense) { exit(0); } /*********************************************************************** * * Procedure: * checks to see if we are supposed to take some action now, * finds time for next action to be performed. * ***********************************************************************/ void find_next_event_time(void) { struct list *t; t0 = time(0); next_event_time = t0; if(list_root == NULL) return; next_event_time = t0 + maxperiod; for(t = list_root; t!= NULL; t= t->next) { if(t->id != current_focus) { if((period[2] >0)&&(t->last_focus_time + period[2] <= t0)) { if(!(t->actions & ACTION1)) { SendInfo(fd,command[2],t->id); t->actions |= ACTION1; } } else if((period[1]>0)&&(t->last_focus_time + period[1] <= t0)) { if(!(t->actions & ACTION2)) { SendInfo(fd,command[1],t->id); t->actions |= ACTION2; } } else if((period[0]>0)&&(t->last_focus_time + period[0] <= t0)) { if(!(t->actions & ACTION3)) { SendInfo(fd,command[0],t->id); t->actions |= ACTION3; } } } else t->last_focus_time = t0; if((period[0] > 0)&&(t->last_focus_time + period[0] > t0)&& (t->last_focus_time + period[0] last_focus_time + period[0]; else if((period[1]>0)&&(t->last_focus_time + period[1] > t0)& (t->last_focus_time + period[1] last_focus_time + period[1]; else if((period[2]>0)&&(t->last_focus_time + period[2] > t0)&& (t->last_focus_time + period[2] last_focus_time + period[2]; } }