/* * Filename: xstroke.c * Author: David Ljung Madison * See License: http://MarginalHacks.com/License * Version: 1.5 beta * Description: Xstroke is a utilty that will grab mouse button events and * run commands in their place. */ #include "xstroke.h" /* selects input from a tree of windows */ void SelectTree(w,level) Window w; int level; { Window rootw; Window par; Window *childrn; int cnt; unsigned int nchild; /* for (cnt=0;cnt 100000) { */ XSelectInput(dpy, w,KeyPressMask|StructureNotifyMask); XQueryTree(dpy, w, &rootw, &par, &childrn, &nchild); /* } */ for(cnt=0;cnt - button 2 down at start point */ /* * Create a format list from a button string. * The .x field is the next character, if it is zero, then * we look at the .y field for the 'action' (see defs above) * - Remember, add_to_list pushes things backwards :( */ list_t *create_format(str) char *str; { list_t *format=NULL; char buf[3]; char ch; int action,button,direction; while(*str) { switch (*str) { case '\\': /* escaped characters */ str++; switch (*str) { /* these are the only ones I could think of :) */ case 'n': ch='\n'; break; case 'r': ch='\r'; break; case 't': ch='\t'; break; case 'b': ch='\b'; break; default: ch=*str; break; } add_to_list_end((int) ch,0,&format); str++; break; case '<': /* actions ( format ) */ action=0; if(!strncmp("",str,6)) { action=BUTTON_STRING; str+=6; } else { button=1; direction=BDOWN; switch (*(str+1)) { case '1': button=1; break; case '2': button=2; break; case '3': button=3; break; case '4': button=4; break; case '5': button=5; break; default: fprintf(stderr,"ERROR: Don't know that button, using 1!\n"); break; } switch (*(str+2)) { case 'U': case 'u': direction=BUP; break; case 'C': case 'c': direction=BCLICK; break; case 'D': case 'd': break; default: fprintf(stderr,"ERROR: " "Don't know that direction, using down!\n"); break; } if ((*(str+3))!=':') fprintf(stderr,"ERROR: malformed string.\n"); if(!strncmp("BL>",str+4,3)) action=BUTTON_BOTTOM_LEFT; else if(!strncmp("TR>",str+4,3)) action=BUTTON_TOP_RIGHT; else if(!strncmp("ST>",str+4,3)) action=BUTTON_START; else if(!strncmp("EN>",str+4,3)) action=BUTTON_END; if (action) { /* Put in the direction (shift 3 first) */ action|=(direction<<4); /* Add in the button number */ action|=button; /* Move to the end of the action */ str+=7; } } /* end parse button actions */ if(action) { add_to_list_end(0,action,&format); } else { add_to_list_end((int) *str,0,&format); str++; } break; default: /* just a regular character */ add_to_list_end((int) *str,0,&format); str++; break; } /* end character switch */ } /* end while loop */ return format; } void free_Win_l_t(ptr) Win_l_t *ptr; { fprintf(stderr,"\nWindow has been destroyed - removing from watch\n"); free(ptr->name); free_list(&(ptr->points)); /* ZZZZZ ACK! What if someone else is using this? */ /* free_list(&(ptr->format)); */ free(ptr); } /* take this out of our watch list. * ZZZZZZZ Maybe unselect the input and ungrab the button first??? */ void remove_from_watch(win) Window win; { Win_l_t *ptr,*ptr2; /* remove all the instances of this window in our watch list */ ptr2=which_watch(win,TRUE); if(!ptr2) return; /* remove this window */ fprintf(stderr,"Removing window: 0x%x (%s)\n",win,watch->name); if (ptr2==watch) { watch=watch->next; free_Win_l_t(ptr2); } else { ptr=watch; while(ptr->next != ptr2) ptr=ptr->next; ptr->next=ptr->next->next; free_Win_l_t(ptr2); } if(watch==NULL) { fprintf(stderr,"No more windows to watch - exiting\n"); exit(0); } } /* Add this window to our watch list */ void add_to_watch(win,name,format,btn) Window win; char *name; list_t *format; int btn; { Win_l_t *watch_this; if(watch_this=which_watch(win,FALSE)) { /* Make sure we aren't already watching this button */ if(watch_this->formats[btn]) { fprintf(stderr,"ERROR: I'm already watching button %d of window %s\n",btn,name); return; } } else { /* Make a new watch element */ MK_WIN_L(watch_this); watch_this->formats[1]=NULL; watch_this->formats[2]=NULL; watch_this->formats[3]=NULL; watch_this->formats[4]=NULL; watch_this->formats[5]=NULL; watch_this->next=watch; watch_this->win=win; watch_this->name=strdup(name); watch_this->textwin=(int) NULL; watch_this->points=NULL; watch=watch_this; } watch_this->formats[btn]=format; } /* * Recursively search through the window hierarchy to find all * window with a specific name * format is a pointer to a button-string-output-format list (see create_format) */ void Select_Windows_by_name(top,name,format,btn) Window top; char *name; list_t *format; int btn; { Window *children, dummy,w=0; unsigned int nchildren; int i; char *window_name; if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name)) add_to_watch(top,window_name,format,btn); XFree((char *)window_name); if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren)) return; for (i=0; i 0) /* there may have been some down before we started */ buttons--; break; } } XUngrabPointer(dpy, CurrentTime); /* Done with pointer */ if (!XFetchName(dpy, target_win, &name)) name="no name"; add_to_watch(target_win,name,format,btn); } /* Find out if win is in the hierarchy of windows under top */ int find_child(win,top) Window win,top; { Window rootw,parent,*children; unsigned int nchildren; int cnt,found=0; if (win==top) return 1; XQueryTree(dpy, top, &rootw, &parent, &children, &nchildren); for(cnt=0;cntwin) return ptr; if(win==ptr->textwin) return ptr; if(check_children && find_child(win,ptr->win)) return ptr; ptr=ptr->next; } return NULL; } /* Print out a usage message */ #define USAGE usage(argv[0]) void usage(name) char *name; { fprintf(stderr,"\n\n"); fprintf(stderr,"Usage: %s [ -btn