/**************************************************************************** * This module is all new * by Rob Nation * Copyright 1993 Robert Nation. No restrictions are placed on this code, * as long as the copyright notice is preserved ****************************************************************************/ #include #include #include #include #include #include #include "fvwm.h" #include "menus.h" #include "misc.h" #include "parse.h" #include "screen.h" #include "module.h" /***************************************************************************** * * Waits Scr.ClickTime, or until it is evident that the user is not * clicking, but is moving the cursor * ****************************************************************************/ Bool IsClick(int x,int y,unsigned EndMask, XEvent *d) { int xcurrent,ycurrent,total = 0; Time t0; extern Time lastTimestamp; xcurrent = x; ycurrent = y; t0 = lastTimestamp; while((total < Scr.ClickTime)&& (x - xcurrent < 3)&&(x - xcurrent > -3)&& (y - ycurrent < 3)&&(y - ycurrent > -3)&& ((lastTimestamp - t0) < Scr.ClickTime)) { sleep_a_little(20000); total+=20; if(XCheckMaskEvent (dpy, EndMask, d)) { StashEventTime(d); return True; } if(XCheckMaskEvent (dpy, ButtonMotionMask|PointerMotionMask, d)) { xcurrent = d->xmotion.x_root; ycurrent = d->xmotion.y_root; StashEventTime(d); } } return False; } /***************************************************************************** * * Builtin which determines if the button press was a click or double click... * ****************************************************************************/ void ComplexFunction(XEvent *eventp,Window w,FvwmWindow *tmp_win, unsigned long context, char *action, int *Module) { char type = MOTION; char c; MenuItem *mi; Bool Persist = False; Bool HaveDoubleClick = False; Bool NeedsTarget = False; char *arguments[10], *junk, *taction; int x, y ,i; XEvent d, *ev; MenuRoot *mr; extern Bool desperate; mr = FindPopup(action); if(mr == NULL) { if(!desperate) fvwm_msg(ERR,"ComplexFunction","No such function %s",action); return; } desperate = 0; /* Get the argument list */ /* First entry in action is the function-name, ignore it */ action = GetNextToken(action,&junk); if(junk != NULL) free(junk); for(i=0;i<10;i++) action = GetNextToken(action,&arguments[i]); /* These built-ins require a selected window * The function code is >= 100 and < 1000 * F_RESIZE * F_MOVE * F_ICONIFY * F_RAISE * F_LOWER * F_DESTROY * F_DELETE * F_STICK * F_RAISELOWER * F_MAXIMIZE * F_FOCUS * * These do not: * The function code is < 100 * F_NOP * F_TITLE * F_BEEP * F_SCROLL * F_MOVECURSOR * F_RESTART * F_EXEC * F_REFRESH * F_GOTO_PAGE * F_TOGGLE_PAGE * F_CIRCULATE_UP * F_CIRCULATE_DOWN * F_WARP * F_DESK * F_MODULE * F_POPUP * F_QUIT * F_WINDOWLIST * F_FUNCTION * F_SEND_WINDOW_LIST */ ev = eventp; /* In case we want to perform an action on a button press, we * need to fool other routines */ if(eventp->type == ButtonPress) eventp->type = ButtonRelease; mi = mr->first; while(mi != NULL) { /* make lower case */ c = *(mi->item); if((mi->func_type >= 100)&&(mi->func_type < 1000)) NeedsTarget = True; if(isupper(c)) c=tolower(c); if(c==DOUBLE_CLICK) { HaveDoubleClick = True; Persist = True; } else if(c == IMMEDIATE) { if(tmp_win) w = tmp_win->frame; else w = None; taction = expand(mi->action,arguments,tmp_win); ExecuteFunction(taction,tmp_win,eventp,context,-2); free(taction); } else Persist = True; mi = mi->next; } if(!Persist) { for(i=0;i<10;i++) if(arguments[i] != NULL)free(arguments[i]); return; } /* Only defer execution if there is a possibility of needing * a window to operate on */ if(NeedsTarget) { if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonPress)) { WaitForButtonsUp(); for(i=0;i<10;i++) if(arguments[i] != NULL)free(arguments[i]); return; } } if(!GrabEm(SELECT)) { XBell(dpy,Scr.screen); for(i=0;i<10;i++) if(arguments[i] != NULL)free(arguments[i]); return; } XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x,&y,&JunkX, &JunkY, &JunkMask); /* Wait and see if we have a click, or a move */ /* wait 100 msec, see if the user releases the button */ if(IsClick(x,y,ButtonReleaseMask,&d)) { ev = &d; type = CLICK; } /* If it was a click, wait to see if its a double click */ if((HaveDoubleClick) && (type == CLICK) && (IsClick(x,y,ButtonPressMask, &d))) { type = ONE_AND_A_HALF_CLICKS; ev = &d; } if((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) && (IsClick(x,y,ButtonReleaseMask, &d))) { type = DOUBLE_CLICK; ev = &d; } /* some functions operate on button release instead of * presses. These gets really weird for complex functions ... */ if(ev->type == ButtonPress) ev->type = ButtonRelease; mi = mr->first; while(mi != NULL) { /* make lower case */ c = *(mi->item); if(isupper(c)) c=tolower(c); if(c == type) { if(tmp_win) w = tmp_win->frame; else w = None; taction = expand(mi->action,arguments,tmp_win); ExecuteFunction(taction,tmp_win,ev,context,-2); free(taction); } mi = mi->next; } WaitForButtonsUp(); UngrabEm(); for(i=0;i<10;i++) if(arguments[i] != NULL)free(arguments[i]); } char *expand(char *input, char *arguments[],FvwmWindow *tmp_win) { int l,i,l2,n,k,j; char *out; l = strlen(input); l2 = strlen(input); i=0; while(i= 0)&&(n <= 9)&&(arguments[n] != NULL)) { l2 += strlen(arguments[n])-2; i++; } else if(input[i+1]=='w') { l2 += 16; i++; } } i++; } out = safemalloc(l2+1); i=0; j=0; while(i= 0)&&(n <= 9)&&(arguments[n] != NULL)) { for(k=0;kw); else sprintf(&out[j],"$w"); j = strlen(out); i++; } else if(input[i+1] == '$') { out[j++] = '$'; i++; } else out[j++] = input[i]; } else out[j++] = input[i]; i++; } out[j] = 0; return out; }